Created
March 6, 2019 13:48
-
-
Save russell-brady/368ce2509a557d9701b040987096c39c to your computer and use it in GitHub Desktop.
Ar Cloud Anchor Activity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.arproject.russell.ar_t.ar; | |
import android.app.Activity; | |
import android.app.ActivityManager; | |
import android.content.Context; | |
import android.net.Uri; | |
import android.os.Bundle; | |
import android.support.v7.app.AppCompatActivity; | |
import android.util.Log; | |
import android.view.Gravity; | |
import android.view.MotionEvent; | |
import android.widget.Button; | |
import android.widget.Toast; | |
import com.arproject.russell.ar_t.R; | |
import com.arproject.russell.ar_t.augmentedimages.helpers.SnackbarHelper; | |
import com.google.ar.core.Anchor; | |
import com.google.ar.core.HitResult; | |
import com.google.ar.core.Plane; | |
import com.google.ar.sceneform.AnchorNode; | |
import com.google.ar.sceneform.FrameTime; | |
import com.google.ar.sceneform.assets.RenderableSource; | |
import com.google.ar.sceneform.rendering.ModelRenderable; | |
import com.google.ar.sceneform.ux.ArFragment; | |
import com.google.ar.sceneform.ux.TransformableNode; | |
public class ArActivity extends AppCompatActivity { | |
private enum AppAnchorState { | |
NONE, | |
HOSTING, | |
HOSTED, | |
RESOLVING, | |
RESOLVED | |
} | |
private AppAnchorState appAnchorState = AppAnchorState.NONE; | |
private static final String TAG = ArActivity.class.getSimpleName(); | |
private static final double MIN_OPENGL_VERSION = 3.0; | |
private static final String GLTF_ASSET = "https://raw.githubusercontent.com/yudiz-solutions/runtime_ar_android/master/model/model.gltf"; | |
private ArFragment arFragment; | |
private ModelRenderable renderable; | |
private SnackbarHelper snackbarHelper; | |
private Anchor cloudAnchor; | |
@Override | |
@SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"}) | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
if (!checkIsSupportedDeviceOrFinish(this)) { | |
return; | |
} | |
snackbarHelper = new SnackbarHelper(); | |
setContentView(R.layout.activity_ux); | |
arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.sceneform_fragment); | |
arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame); | |
ModelRenderable.builder() | |
.setSource(this, RenderableSource.builder().setSource( | |
this, | |
Uri.parse(GLTF_ASSET), | |
RenderableSource.SourceType.GLTF2) | |
.build()) | |
.setRegistryId(GLTF_ASSET) | |
.build() | |
.thenAccept(renderable -> this.renderable = renderable) | |
.exceptionally( | |
throwable -> { | |
Toast toast = | |
Toast.makeText(this, "Unable to load renderable " + | |
GLTF_ASSET, Toast.LENGTH_LONG); | |
toast.setGravity(Gravity.CENTER, 0, 0); | |
toast.show(); | |
return null; | |
}); | |
Button clearButton = findViewById(R.id.clear_button); | |
clearButton.setOnClickListener(view -> setCloudAnchor(null)); | |
Button hostButton = findViewById(R.id.host_button); | |
hostButton.setOnClickListener(view -> hostModel()); | |
arFragment.setOnTapArPlaneListener( | |
(HitResult hitResult, Plane plane, MotionEvent motionEvent) -> { | |
if (renderable == null) { | |
return; | |
} | |
// Create the Anchor. | |
Anchor anchor = hitResult.createAnchor(); | |
setCloudAnchor(anchor); | |
AnchorNode anchorNode = new AnchorNode(cloudAnchor); | |
TransformableNode node = new TransformableNode(arFragment.getTransformationSystem()); | |
node.setRenderable(renderable); | |
node.setParent(anchorNode); | |
arFragment.getArSceneView().getScene().addChild(anchorNode); | |
node.select(); | |
}); | |
} | |
private void hostModel() { | |
if (cloudAnchor != null) { | |
arFragment.getArSceneView().getSession().hostCloudAnchor(cloudAnchor); | |
appAnchorState = AppAnchorState.HOSTING; | |
snackbarHelper.showMessage(this, "Now hosting anchor..."); | |
} else { | |
snackbarHelper.showMessage(this, "No anchor to host, Please create an anchor..."); | |
} | |
} | |
private void setCloudAnchor (Anchor newAnchor){ | |
if (cloudAnchor != null){ | |
cloudAnchor.detach(); | |
} | |
cloudAnchor = newAnchor; | |
appAnchorState = AppAnchorState.NONE; | |
snackbarHelper.hide(this); | |
} | |
private void onUpdateFrame(FrameTime frameTime){ | |
if (cloudAnchor != null) { | |
checkUpdatedAnchor(); | |
} | |
} | |
private synchronized void checkUpdatedAnchor(){ | |
if (appAnchorState != AppAnchorState.HOSTING){ | |
return; | |
} | |
Anchor.CloudAnchorState cloudState = cloudAnchor.getCloudAnchorState(); | |
if (appAnchorState == AppAnchorState.HOSTING) { | |
if (cloudState.isError()) { | |
snackbarHelper.showMessageWithDismiss(this, "Error hosting anchor.. " | |
+ cloudState); | |
appAnchorState = AppAnchorState.NONE; | |
} else if (cloudState == Anchor.CloudAnchorState.SUCCESS) { | |
snackbarHelper.showMessageWithDismiss(this, "Anchor hosted with id " | |
+ cloudAnchor.getCloudAnchorId()); | |
appAnchorState = AppAnchorState.HOSTED; | |
} | |
} | |
} | |
public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) { | |
String openGlVersionString = | |
((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE)) | |
.getDeviceConfigurationInfo() | |
.getGlEsVersion(); | |
if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) { | |
Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later"); | |
Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG) | |
.show(); | |
activity.finish(); | |
return false; | |
} | |
return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply plugin: 'com.android.application' | |
apply plugin: 'jacoco' | |
android { | |
compileSdkVersion 27 | |
defaultConfig { | |
applicationId "com.arproject.russell.ar_t" | |
minSdkVersion 24 | |
targetSdkVersion 27 | |
versionCode 1 | |
versionName "1.0" | |
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | |
multiDexEnabled true | |
} | |
compileOptions { | |
sourceCompatibility 1.8 | |
targetCompatibility 1.8 | |
} | |
buildTypes { | |
release { | |
minifyEnabled false | |
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | |
} | |
debug { | |
testCoverageEnabled true | |
} | |
} | |
} | |
dependencies { | |
implementation fileTree(dir: 'libs', include: ['*.jar']) | |
implementation 'com.android.support:appcompat-v7:27.1.1' | |
implementation 'com.android.support.constraint:constraint-layout:1.1.3' | |
implementation 'android.arch.lifecycle:extensions:1.1.1' | |
implementation 'com.android.support:support-v4:27.1.1' | |
testImplementation 'junit:junit:4.12' | |
androidTestImplementation 'com.android.support.test:runner:1.0.2' | |
androidTestImplementation 'com.android.support.test:rules:1.0.2' | |
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' | |
androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.0.2' | |
testImplementation 'org.mockito:mockito-core:2.8.9' | |
implementation 'com.android.support:multidex:1.0.3' | |
/* dagger dependency for DI*/ | |
implementation "com.google.dagger:dagger:2.13" | |
annotationProcessor "com.google.dagger:dagger-compiler:2.13" | |
compileOnly 'javax.annotation:jsr250-api:1.0' | |
implementation 'javax.inject:javax.inject:1' | |
/*Retrofit lib*/ | |
implementation 'com.squareup.retrofit2:retrofit:2.3.0' | |
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' | |
/*RxJava lib*/ | |
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' | |
implementation "io.reactivex.rxjava2:rxjava:2.1.8" | |
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' | |
/* LiveData lib*/ | |
implementation "android.arch.lifecycle:extensions:1.1.1" | |
implementation "android.arch.lifecycle:runtime:1.1.1" | |
annotationProcessor "android.arch.lifecycle:compiler:1.1.1" | |
// Room DB | |
implementation "android.arch.persistence.room:runtime:1.1.1" | |
annotationProcessor "android.arch.persistence.room:compiler:1.1.1" | |
//Design | |
implementation 'com.android.support:design:27.1.1' | |
implementation 'com.android.support:appcompat-v7:27.1.1' | |
//Circle Image View | |
implementation 'de.hdodenhof:circleimageview:2.2.0' | |
// ARCore | |
implementation 'com.google.ar:core:1.5.0' | |
// SceneForm | |
// Provides ArFragment, and other UX resources. | |
implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.5.1' | |
implementation 'com.google.ar.sceneform:assets:1.5.1' | |
//Preferences Screen | |
implementation 'com.android.support:preference-v7:27.1.1' | |
implementation 'com.android.support:preference-v14:27.1.1' | |
// Glide - An image loading and caching library for Android | |
// https://github.com/bumptech/glide | |
implementation 'com.github.bumptech.glide:glide:4.6.1' | |
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1' | |
// CardView | |
implementation "com.android.support:cardview-v7:27.1.1" | |
//RecyclerView | |
implementation 'com.android.support:recyclerview-v7:27.1.1' | |
// ViewPager Arrow Indicator | |
implementation 'com.github.sembozdemir:ViewPagerArrowIndicator:1.0.0' | |
implementation 'com.mikhaellopez:circularimageview:3.0.2' | |
} | |
apply plugin: 'com.google.ar.sceneform.plugin' | |
sceneform.asset('sampledata/models/andy.obj', | |
'default', | |
'sampledata/models/andy.sfa', | |
'src/main/res/raw/andy') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.arproject.russell.ar_t.ar; | |
import com.google.ar.core.Config; | |
import com.google.ar.core.Session; | |
import com.google.ar.sceneform.ux.ArFragment; | |
public class CustomArFragment extends ArFragment { | |
@Override | |
protected Config getSessionConfiguration(Session session) { | |
Config config = super.getSessionConfiguration(session); | |
config.setCloudAnchorMode(Config.CloudAnchorMode.ENABLED); | |
return config; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment