diff --git a/cloud-anchors/.idea/vcs.xml b/cloud-anchors/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/cloud-anchors/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/cloud-anchors/app/build.gradle b/cloud-anchors/app/build.gradle index 1ca60f7..894e2e0 100644 --- a/cloud-anchors/app/build.gradle +++ b/cloud-anchors/app/build.gradle @@ -37,7 +37,7 @@ dependencies { androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation "com.google.ar.sceneform.ux:sceneform-ux:1.6.0" implementation 'com.google.firebase:firebase-core:16.0.6' - implementation 'com.google.firebase:firebase-database:16.0.5' + implementation 'com.google.firebase:firebase-firestore:17.1.5' } diff --git a/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/CloudAnchorsHelper.kt b/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/CloudAnchorsHelper.kt new file mode 100644 index 0000000..a23a63e --- /dev/null +++ b/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/CloudAnchorsHelper.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, norangebit + * + * This file is part of cloud-anchors. + * + * cloud-anchors is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * cloud-anchors is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with cloud-anchors. If not, see + * + */ + +package it.norangeb.cloudanchors + +import com.google.firebase.firestore.FirebaseFirestore +import com.google.firebase.firestore.SetOptions + +class CloudAnchorsHelper { + private val fireStoreDb = FirebaseFirestore.getInstance() + private var nextCode = 0 + + init { + fireStoreDb.collection(COLLECTION) + .document(DOCUMENT) + .get() + .addOnSuccessListener { + val nCode = it.data?.get(NEXT_CODE) ?: return@addOnSuccessListener + nextCode = nCode.toString().toInt() + } + } + + fun getShortCode(cloudAnchorId: String): Int { + fireStoreDb.collection(COLLECTION) + .document(DOCUMENT) + .set( + mapOf(Pair(nextCode.toString(), cloudAnchorId)), + SetOptions.merge()) + uploadNextCode(nextCode+1) + return nextCode++ + } + + private fun uploadNextCode(nextCode: Int) { + fireStoreDb.collection(COLLECTION) + .document(DOCUMENT) + .set( + mapOf(Pair(NEXT_CODE, nextCode)), + SetOptions.merge() + ) + } + + fun getCloudAnchorId( + shortCode: Int, + onSuccess: (String) -> Unit + ) { + fireStoreDb.collection(COLLECTION) + .document(DOCUMENT) + .get() + .addOnSuccessListener { + val x = it.data?.get(shortCode.toString()) as String + onSuccess(x) + } + } + + companion object { + private const val COLLECTION = "short_codes" + private const val DOCUMENT = "short_codes_doc" + private const val NEXT_CODE = "next_short_code" + } +} \ No newline at end of file diff --git a/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/MainActivity.kt b/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/MainActivity.kt index cab914e..9d70c3c 100644 --- a/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/MainActivity.kt +++ b/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/MainActivity.kt @@ -36,8 +36,8 @@ class MainActivity : AppCompatActivity() { private val TAG = MainActivity::class.java.canonicalName private lateinit var arFragment: CloudArFragment - private lateinit var storageManager: StorageManager - private var cloudAnchorState = CloudAnchorState.LOCAL + private val cloudAnchorsHelper = CloudAnchorsHelper() + private var cloudAnchorState = CloudAnchorState.NONE private var cloudAnchor: Anchor? = null set(value) { field?.detach() @@ -50,8 +50,6 @@ class MainActivity : AppCompatActivity() { if (!checkIsSupportedDeviceOrFinish(this, TAG)) return - storageManager = StorageManager(this) - setContentView(R.layout.activity_main) arFragment = supportFragmentManager.findFragmentById(R.id.ar_fragment) as CloudArFragment @@ -63,7 +61,7 @@ class MainActivity : AppCompatActivity() { } private fun addModel(hitResult: HitResult, plane: Plane, motionEvent: MotionEvent) { - if (cloudAnchorState != CloudAnchorState.LOCAL) + if (cloudAnchorState != CloudAnchorState.NONE) return cloudAnchor = arFragment.arSceneView.session @@ -90,7 +88,7 @@ class MainActivity : AppCompatActivity() { if (cloudState.isError) { toastError() - cloudAnchorState = CloudAnchorState.LOCAL + cloudAnchorState = CloudAnchorState.NONE return } @@ -98,29 +96,25 @@ class MainActivity : AppCompatActivity() { return if (cloudAnchorState == CloudAnchorState.HOSTING) - checkHosting(cloudState) + checkHosting() else - checkResolving(cloudState) + checkResolving() } - private fun checkResolving(state: Anchor.CloudAnchorState) { + private fun checkResolving() { Toast.makeText(this, "Anchor resolved!", Toast.LENGTH_LONG) .show() cloudAnchorState = CloudAnchorState.RESOLVED } - private fun checkHosting(state: Anchor.CloudAnchorState) { - storageManager.nextShortCode { shortCode -> - if (shortCode == null) { - toastError() - return@nextShortCode - } - storageManager.storeUsingShortCode(shortCode, cloudAnchor?.cloudAnchorId) + private fun checkHosting() { + val cAnchor = cloudAnchor ?: return - Toast.makeText(this, "Anchor hosted with code $shortCode", Toast.LENGTH_LONG) - .show() - Log.d("NORANGEBIT", "$shortCode") - } + val shortCode = cloudAnchorsHelper.getShortCode(cAnchor.cloudAnchorId) + + Toast.makeText(this, "Anchor hosted with code $shortCode", Toast.LENGTH_LONG) + .show() + Log.d("NORANGEBIT", "$shortCode") cloudAnchorState = CloudAnchorState.HOSTED } @@ -130,8 +124,8 @@ class MainActivity : AppCompatActivity() { .show() private fun onResolveOkPressed(dialogValue: String) { - val shortCode = Integer.parseInt(dialogValue) - storageManager.getCloudAnchorID(shortCode) { + val shortCode = dialogValue.toInt() + cloudAnchorsHelper.getCloudAnchorId(shortCode) { cloudAnchor = arFragment.arSceneView.session .resolveCloudAnchor(it) @@ -146,7 +140,7 @@ class MainActivity : AppCompatActivity() { fun onClearClick(view: View) { cloudAnchor?.detach() cloudAnchor = null - cloudAnchorState = CloudAnchorState.LOCAL + cloudAnchorState = CloudAnchorState.NONE } fun onResolveClick(view: View) { diff --git a/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/StorageManager.java b/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/StorageManager.java deleted file mode 100644 index 63d41b1..0000000 --- a/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/StorageManager.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * This class is made by Google - * - * visit https://codelabs.developers.google.com/codelabs/arcore-cloud-anchors/#4 - */ - -package it.norangeb.cloudanchors; - -import android.content.Context; -import android.util.Log; -import com.google.firebase.FirebaseApp; -import com.google.firebase.database.*; - -/** Helper class for Firebase storage of cloud anchor IDs. */ -class StorageManager { - - /** Listener for a new Cloud Anchor ID from the Firebase Database. */ - interface CloudAnchorIdListener { - void onCloudAnchorIdAvailable(String cloudAnchorId); - } - - /** Listener for a new short code from the Firebase Database. */ - interface ShortCodeListener { - void onShortCodeAvailable(Integer shortCode); - } - - private static final String TAG = StorageManager.class.getName(); - private static final String KEY_ROOT_DIR = "shared_anchor_codelab_root"; - private static final String KEY_NEXT_SHORT_CODE = "next_short_code"; - private static final String KEY_PREFIX = "anchor;"; - private static final int INITIAL_SHORT_CODE = 142; - private final DatabaseReference rootRef; - - StorageManager(Context context) { - FirebaseApp firebaseApp = FirebaseApp.initializeApp(context); - rootRef = FirebaseDatabase.getInstance(firebaseApp).getReference().child(KEY_ROOT_DIR); - DatabaseReference.goOnline(); - } - - /** Gets a new short code that can be used to store the anchor ID. */ - void nextShortCode(ShortCodeListener listener) { - // Run a transaction on the node containing the next short code available. This increments the - // value in the database and retrieves it in one atomic all-or-nothing operation. - rootRef - .child(KEY_NEXT_SHORT_CODE) - .runTransaction( - new Transaction.Handler() { - @Override - public Transaction.Result doTransaction(MutableData currentData) { - Integer shortCode = currentData.getValue(Integer.class); - if (shortCode == null) { - shortCode = INITIAL_SHORT_CODE - 1; - } - currentData.setValue(shortCode + 1); - return Transaction.success(currentData); - } - - @Override - public void onComplete( - DatabaseError error, boolean committed, DataSnapshot currentData) { - if (!committed) { - Log.e(TAG, "Firebase Error", error.toException()); - listener.onShortCodeAvailable(null); - } else { - listener.onShortCodeAvailable(currentData.getValue(Integer.class)); - } - } - }); - } - - /** Stores the cloud anchor ID in the configured Firebase Database. */ - void storeUsingShortCode(int shortCode, String cloudAnchorId) { - rootRef.child(KEY_PREFIX + shortCode).setValue(cloudAnchorId); - } - - /** - * Retrieves the cloud anchor ID using a short code. Returns an empty string if a cloud anchor ID - * was not stored for this short code. - */ - void getCloudAnchorID(int shortCode, CloudAnchorIdListener listener) { - rootRef - .child(KEY_PREFIX + shortCode) - .addListenerForSingleValueEvent( - new ValueEventListener() { - @Override - public void onDataChange(DataSnapshot dataSnapshot) { - listener.onCloudAnchorIdAvailable(String.valueOf(dataSnapshot.getValue())); - } - - @Override - public void onCancelled(DatabaseError error) { - Log.e(TAG, "The database operation for getCloudAnchorID was cancelled.", - error.toException()); - listener.onCloudAnchorIdAvailable(null); - } - }); - } -} diff --git a/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/Util.kt b/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/Util.kt index 56d702b..bd126ed 100644 --- a/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/Util.kt +++ b/cloud-anchors/app/src/main/java/it/norangeb/cloudanchors/Util.kt @@ -29,12 +29,8 @@ import android.os.Build import android.util.Log import android.widget.Toast import com.google.ar.core.Anchor -import com.google.ar.core.Session -import com.google.ar.core.Trackable -import com.google.ar.core.TrackingState import com.google.ar.sceneform.AnchorNode import com.google.ar.sceneform.Node -import com.google.ar.sceneform.math.Vector3 import com.google.ar.sceneform.rendering.* import com.google.ar.sceneform.ux.ArFragment import com.google.ar.sceneform.ux.TransformableNode @@ -62,10 +58,6 @@ fun checkIsSupportedDeviceOrFinish(activity: Activity, tag: String): Boolean { return true } -operator fun ArFragment.invoke(λ: ArFragment.() -> Unit) = λ() - -fun isTrackig(trackable: Trackable) = trackable.trackingState == TrackingState.TRACKING - fun buildRenderable( context: Context, model: Uri, @@ -81,55 +73,6 @@ fun buildRenderable( } } -fun buildMaterial( - context: Context, - color: Color, - onSuccess: (material: Material) -> Unit -) { - MaterialFactory - .makeOpaqueWithColor(context, color) - .thenAccept(onSuccess) -} - -fun changeColorOfMaterial( - context: Context, - color: Color, - renderable: Renderable -) { - val newColor = buildMaterial(context, color) { - renderable.material = it - } -} - - -/** -fun buildRenderable( - context: Context, - model: RenderableSource, - modelUri: Uri, - onSuccess: (renderable: Renderable) -> Unit -) { - ModelRenderable.builder() - .setRegistryId(modelUri) - .setSource(context, model) - .build() - .thenAccept(onSuccess) - .exceptionally { - Log.e("SCENEFORM", "unable to load model", it) - return@exceptionally null - } -} - -fun fetchModel( - context: Context, - source: Uri -) : RenderableSource { - return RenderableSource.builder() - .setSource(context, source, RenderableSource.SourceType.GLTF2) - .setRecenterMode(RenderableSource.RecenterMode.ROOT) - .build() -} -*/ fun addTransformableNodeToScene(arFragment: ArFragment, anchor: Anchor, renderable: Renderable): Node { val anchorNode = AnchorNode(anchor) @@ -142,7 +85,7 @@ fun addTransformableNodeToScene(arFragment: ArFragment, anchor: Anchor, renderab } enum class CloudAnchorState { - LOCAL, + NONE, HOSTING, HOSTED, RESOLVING,