move to firestore

This commit is contained in:
Raffaele Mignone 2019-01-21 18:23:12 +01:00
parent 1433334f15
commit 9a0a49fd38
Signed by: norangebit
GPG Key ID: 4B9DF72AB9508845
6 changed files with 102 additions and 180 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@ -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'
}

View File

@ -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 <http://www.gnu.org/licenses/>
*
*/
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"
}
}

View File

@ -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) {

View File

@ -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);
}
});
}
}

View File

@ -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,