And there’s this test code
`package com.m.co/;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import com.firebase.client.AuthData;
import com.firebase.client.ChildEventListener;
import com.firebase.client.Config;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.MutableData;
import com.firebase.client.Transaction;
import com.firebase.client.ValueEventListener;
import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleEvent;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.annotations.UsesLibraries;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import com.google.appinventor.components.runtime.util.JsonUtil;
import com.google.appinventor.components.runtime.util.SdkLevel;
import com.google.appinventor.components.runtime.util.YailList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.json.JSONException;
@DesignerComponent(androidMinSdk = 10, category = ComponentCategory.EXTENSION, description = “Non-visible component that communicates with Firebase to store and retrieve information.”, designerHelpDescription = “Non-visible component that communicates with a Firebase to store and retrieve information.”, iconName = “images/firebaseDB.png”, nonVisible = true, version = 3)
@SimpleObject
@UsesLibraries(libraries = “firebase.jar”)
@UsesPermissions(permissionNames = “android.permission.INTERNET”)
public class FirebaseDB extends AndroidNonvisibleComponent implements Component {
private static final String a = “Firebase”;
private static boolean h = false;
private static boolean i = false;
private String b = null;
private String c = null;
private boolean d = true;
private String e;
private String f;
private String g;
private Handler j = new Handler();
private final Activity k;
private Firebase l;
private ChildEventListener m;
private Firebase.AuthStateListener n;
public FirebaseDB(ComponentContainer paramComponentContainer) {
super(paramComponentContainer.$form());
this.k = paramComponentContainer.$context();
Firebase.setAndroidContext((Context)this.k);
this.e = “”;
this.f = “”;
this.g = “”;
this.m = new ChildEventListener(this) {
public void onCancelled(FirebaseError param1FirebaseError) {
FirebaseDB.a(this.a).post(new Runnable(this, param1FirebaseError) {
public void run() {
this.b.a.FirebaseError(this.a.getMessage());
}
});
}
public void onChildAdded(DataSnapshot param1DataSnapshot, String param1String) {
FirebaseDB.a(this.a).post(new Runnable(this, param1DataSnapshot) {
public void run() {
this.b.a.DataChanged(this.a.getKey(), this.a.getValue());
}
});
}
public void onChildChanged(DataSnapshot param1DataSnapshot, String param1String) {
FirebaseDB.a(this.a).post(new Runnable(this, param1DataSnapshot) {
public void run() {
this.b.a.DataChanged(this.a.getKey(), this.a.getValue());
}
});
}
public void onChildMoved(DataSnapshot param1DataSnapshot, String param1String) {}
public void onChildRemoved(DataSnapshot param1DataSnapshot) {
Log.i("Firebase", "onChildRemoved: " + param1DataSnapshot.getKey() + " removed.");
}
};
this.n = new Firebase.AuthStateListener(this) {
public void onAuthStateChanged(AuthData param1AuthData) {
Log.i("Firebase", "onAuthStateChanged: data = " + param1AuthData);
if (param1AuthData == null)
FirebaseDB.c(this.a).authWithCustomToken(FirebaseDB.b(this.a), new Firebase.AuthResultHandler(this) {
public void onAuthenticated(AuthData param2AuthData) {
Log.i("Firebase", "Auth Successful.");
}
public void onAuthenticationError(FirebaseError param2FirebaseError) {
Log.e("Firebase", "Auth Failed: " + param2FirebaseError.getMessage());
}
});
}
};
}
private void a() {
if (!h)
return;
if (this.l != null) {
this.l.removeEventListener(this.m);
this.l.removeAuthStateListener(this.n);
}
this.l = null;
b();
}
private void a(Transactional paramTransactional, Firebase paramFirebase, Runnable paramRunnable) {
paramFirebase.runTransaction(new Transaction.Handler(this, paramTransactional, paramTransactional.a(), paramRunnable) {
public Transaction.Result doTransaction(MutableData param1MutableData) {
return this.a.a(param1MutableData);
}
public void onComplete(FirebaseError param1FirebaseError, boolean param1Boolean, DataSnapshot param1DataSnapshot) {
if (param1FirebaseError != null) {
FirebaseDB.a(this.d).post(new Runnable(this, param1FirebaseError) {
public void run() {
Log.i("Firebase", "AppendValue(onComplete): firebase: " + this.a.getMessage());
Log.i("Firebase", "AppendValue(onComplete): result.err: " + this.b.b.a);
this.b.d.FirebaseError(this.a.getMessage());
}
});
return;
}
if (!param1Boolean) {
FirebaseDB.a(this.d).post(new Runnable(this) {
public void run() {
Log.i("Firebase", "AppendValue(!committed): result.err: " + this.a.b.a);
this.a.d.FirebaseError(this.a.b.a);
}
});
return;
}
if (this.c != null) {
FirebaseDB.a(this.d).post(this.c);
return;
}
}
});
}
private void b() {
if (SdkLevel.getLevel() < 10) {
Notifier.oneButtonAlert(this.k, “The version of Android on this device is too old to use Firebase.”, “Android Too Old”, “OK”);
return;
}
if (this.d) {
this.l = new Firebase(this.b + “developers/” + this.e + this.f);
} else {
this.l = new Firebase(this.b + this.f);
}
this.l.addChildEventListener(this.m);
this.l.addAuthStateListener(this.n);
}
@SimpleFunction(description = “Append a value to the end of a list atomically. If two devices use this function simultaneously, both will be appended and no data lost.”)
public void AppendValue(String paramString, Object paramObject) {
ReturnVal returnVal = new ReturnVal();
Firebase firebase = this.l.child(paramString);
a(new Transactional(this, null, null, returnVal, returnVal, paramObject) {
Transaction.Result a(MutableData param1MutableData) {
Object object = param1MutableData.getValue();
if (object == null) {
this.a.a = “Previous value was empty.”;
return Transaction.abort();
}
try {
if (object instanceof String) {
object = JsonUtil.getObjectFromJson((String)object);
if (object instanceof List) {
((List)object).add(this.b);
try {
object = JsonUtil.getJsonRepresentation(object);
param1MutableData.setValue(object);
return Transaction.success(param1MutableData);
} catch (JSONException jSONException) {
this.a.a = “Could not convert value to JSON.”;
return Transaction.abort();
}
}
} else {
this.a.a = “Invalid JSON object in database (shouldn’t happen!)”;
return Transaction.abort();
}
} catch (JSONException jSONException) {
this.a.a = “Invalid JSON object in database (shouldn’t happen!)”;
return Transaction.abort();
}
this.a.a = “You can only append to a list.”;
return Transaction.abort();
}
}firebase, null);
}
@SimpleFunction(description = “Remove the tag from Firebase”)
public void ClearTag(String paramString) {
this.l.child(paramString).removeValue();
}
@SimpleEvent
public void DataChanged(String paramString, Object paramObject) {
Object object = paramObject;
if (paramObject != null) {
object = paramObject;
try {
if (paramObject instanceof String)
object = JsonUtil.getObjectFromJson((String)paramObject);
EventDispatcher.dispatchEvent(this, “DataChanged”, new Object[] { paramString, object });
return;
} catch (JSONException jSONException) {
throw new YailRuntimeError(“Value failed to convert from JSON.”, “JSON Retrieval Error.”);
}
}
EventDispatcher.dispatchEvent(this, “DataChanged”, new Object[] { jSONException, object });
}
@DesignerProperty(editorType = “string”)
@SimpleProperty(category = PropertyCategory.BEHAVIOR, userVisible = false)
public void DefaultURL(String paramString) {
this.c = paramString;
if (this.d) {
this.b = this.c;
a();
}
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR, userVisible = false)
public String DeveloperBucket() {
return this.e;
}
@DesignerProperty(editorType = “string”)
@SimpleProperty
public void DeveloperBucket(String paramString) {
this.e = paramString;
a();
}
@SimpleEvent
public void FirebaseError(String paramString) {
Log.e(“Firebase”, paramString);
if (!EventDispatcher.dispatchEvent(this, “FirebaseError”, new Object[] { paramString }))
Notifier.oneButtonAlert(this.form, paramString, “FirebaseError”, “Continue”);
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR, userVisible = false)
public String FirebaseToken() {
return this.g;
}
@DesignerProperty(editorType = “string”)
@SimpleProperty
public void FirebaseToken(String paramString) {
this.g = paramString;
a();
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = “Gets the URL for this FirebaseDB.”, userVisible = false)
public String FirebaseURL() {
return this.d ? “DEFAULT” : this.b;
}
@DesignerProperty(defaultValue = “DEFAULT”, editorType = “FirbaseURL”)
@SimpleProperty(description = “Sets the URL for this FirebaseDB.”)
public void FirebaseURL(String paramString) {
if (paramString.equals(“DEFAULT”) || paramString.isEmpty()) {
if (!this.d) {
this.d = true;
if (this.c == null) {
Log.d(“Firebase”, “FirebaseURL called before DefaultURL (should not happen!)”);
return;
}
this.b = this.c;
a();
return;
}
this.b = this.c;
return;
}
this.d = false;
StringBuilder stringBuilder = (new StringBuilder()).append(paramString);
if (paramString.endsWith("/")) {
paramString = “”;
} else {
paramString = “/”;
}
paramString = stringBuilder.append(paramString).toString();
if (!this.b.equals(paramString)) {
this.b = paramString;
this.d = false;
a();
return;
}
}
@SimpleEvent(description = “Event triggered by the “RemoveFirst” function. The argument “value” is the object that was the first in the list, and which is now removed.”)
public void FirstRemoved(Object paramObject) {
EventDispatcher.dispatchEvent(this, “FirstRemoved”, new Object[] { paramObject });
}
@SimpleFunction(description = “Get the list of tags for this application. When complete a “TagList” event will be triggered with the list of known tags.”)
public void GetTagList() {
this.l.child("").addListenerForSingleValueEvent(new ValueEventListener(this) {
public void onCancelled(FirebaseError param1FirebaseError) {}
public void onDataChange(DataSnapshot param1DataSnapshot) {
Object object = param1DataSnapshot.getValue();
if (object instanceof HashMap) {
object = new ArrayList(((HashMap)object).keySet());
FirebaseDB.a(this.a).post(new Runnable(this, (List)object) {
public void run() {
this.b.a.TagList(this.a);
}
});
}
}
});
}
@SimpleFunction
public void GetValue(String paramString, Object paramObject) {
this.l.child(paramString).addListenerForSingleValueEvent(new ValueEventListener(this, paramObject, paramString) {
public void onCancelled(FirebaseError param1FirebaseError) {
FirebaseDB.a(this.c).post(new Runnable(this, param1FirebaseError) {
public void run() {
this.b.c.FirebaseError(this.a.getMessage());
}
});
}
public void onDataChange(DataSnapshot param1DataSnapshot) {
AtomicReference<Object> atomicReference = new AtomicReference();
try {
if (param1DataSnapshot.exists()) {
atomicReference.set(param1DataSnapshot.getValue());
} else {
atomicReference.set(JsonUtil.getJsonRepresentation(this.a));
}
FirebaseDB.a(this.c).post(new Runnable(this, atomicReference) {
public void run() {
this.b.c.GotValue(this.b.b, this.a.get());
}
});
return;
} catch (JSONException jSONException) {
throw new YailRuntimeError("Value failed to convert to JSON.", "JSON Creation Error.");
}
}
});
}
@SimpleEvent
public void GotValue(String paramString, Object paramObject) {
Object object = paramObject;
if (paramObject != null) {
object = paramObject;
try {
if (paramObject instanceof String)
object = JsonUtil.getObjectFromJson((String)paramObject);
EventDispatcher.dispatchEvent(this, “GotValue”, new Object[] { paramString, object });
return;
} catch (JSONException jSONException) {
throw new YailRuntimeError(“Value failed to convert from JSON.”, “JSON Retrieval Error.”);
}
}
EventDispatcher.dispatchEvent(this, “GotValue”, new Object[] { jSONException, object });
}
public void Initialize() {
Log.i(“Firebase”, “Initalize called!”);
h = true;
a();
}
@DesignerProperty(defaultValue = “False”, editorType = “boolean”)
@SimpleProperty(description = “If true, variables will retain their values when off-line and the App exits. Values will be uploaded to Firebase the next time the App is run while connected to the network. This is useful for applications which will gather data while not connected to the network. Note: AppendValue and RemoveFirst will not work correctly when off-line, they require a network connection.
Note: If you set Persist on any Firebase component, on any screen, it makes all Firebase components on all screens persistent. This is a limitation of the low level Firebase library. Also be aware that if you want to set persist to true, you should do so before connecting the Companion for incremental development.”, userVisible = false)
public void Persist(boolean paramBoolean) {
Log.i(“Firebase”, "Persist Called: Value = " + paramBoolean);
if (i != paramBoolean) {
if (h)
throw new RuntimeException(“You cannot change the Persist value of Firebase after Application Initialization, this includes the Companion”);
Config config = Firebase.getDefaultConfig();
config.setPersistenceEnabled(paramBoolean);
Firebase.setDefaultConfig(config);
i = paramBoolean;
a();
}
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = “Gets the ProjectBucket for this FirebaseDB.”)
public String ProjectBucket() {
return this.f;
}
@DesignerProperty(defaultValue = “”, editorType = “string”)
@SimpleProperty(description = “Sets the ProjectBucket for this FirebaseDB.”)
public void ProjectBucket(String paramString) {
if (!this.f.equals(paramString)) {
this.f = paramString;
a();
}
}
@SimpleFunction(description = “Return the first element of a list and atomically remove it. If two devices use this function simultaneously, one will get the first element and the the other will get the second element, or an error if there is no available element. When the element is available, the “FirstRemoved” event will be triggered.”)
public void RemoveFirst(String paramString) {
ReturnVal returnVal = new ReturnVal();
Firebase firebase = this.l.child(paramString);
a(new Transactional(this, null, null, returnVal, returnVal) {
Transaction.Result a(MutableData param1MutableData) {
Object object = param1MutableData.getValue();
if (object == null) {
this.a.a = “Previous value was empty.”;
return Transaction.abort();
}
try {
if (object instanceof String) {
object = JsonUtil.getObjectFromJson((String)object);
if (object instanceof List) {
if (((List)object).isEmpty()) {
this.a.a = “The list was empty”;
return Transaction.abort();
}
this.a.b = ((List)object).remove(0);
try {
object = JsonUtil.getJsonRepresentation(YailList.makeList((List)object));
param1MutableData.setValue(object);
return Transaction.success(param1MutableData);
} catch (JSONException jSONException) {
this.a.a = “Could not convert value to JSON.”;
return Transaction.abort();
}
}
} else {
this.a.a = “Invalid JSON object in database (shouldn’t happen!)”;
return Transaction.abort();
}
} catch (JSONException jSONException) {
this.a.a = “Invalid JSON object in database (shouldn’t happen!)”;
return Transaction.abort();
}
this.a.a = “You can only remove elements from a list.”;
return Transaction.abort();
}
}firebase, new Runnable(this, returnVal) {
public void run() {
this.b.FirstRemoved(this.a.a());
}
});
}
@SimpleFunction
public void StoreValue(String paramString, Object paramObject) {
Object object = paramObject;
if (paramObject != null)
try {
object = JsonUtil.getJsonRepresentation(paramObject);
this.l.child(paramString).setValue(object);
return;
} catch (JSONException jSONException) {
throw new YailRuntimeError(“Value failed to convert to JSON.”, “JSON Creation Error.”);
}
this.l.child((String)jSONException).setValue(object);
}
@SimpleEvent(description = “Event triggered when we have received the list of known tags. Used with the “GetTagList” Function.”)
public void TagList(List paramList) {
EventDispatcher.dispatchEvent(this, “TagList”, new Object[] { paramList });
}
@SimpleFunction(description = “If you are having difficulty with the Companion and you are switching between different Firebase accounts, you may need to use this function to clear internal Firebase caches. You can just use the “Do It” function on this block in the blocks editor. Note: You should not normally need to use this block as part of an application.”)
public void Unauthenticate() {
if (this.l == null)
b();
this.l.unauth();
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR)
public String getFirebaseToken() {
return this.g;
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = “Gets the URL for this FirebaseDB.”)
public String getFirebaseURL() {
return this.d ? “DEFAULT” : this.b;
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR)
public void setFirebaseToken(String paramString) {
this.g = paramString;
a();
}
@SimpleProperty(category = PropertyCategory.BEHAVIOR, description = “Gets the URL for this FirebaseDB.”)
public void setFirebaseURL(String paramString) {
if (this.b.equals(paramString) || paramString.isEmpty() || paramString == null)
return;
this.d = false;
StringBuilder stringBuilder = (new StringBuilder()).append(paramString);
if (paramString.endsWith("/")) {
paramString = “”;
} else {
paramString = “/”;
}
this.b = stringBuilder.append(paramString).toString();
a();
}
private static class ReturnVal {
String a;
Object b;
private ReturnVal() {}
Object a() {
return this.b;
}
}
private static abstract class Transactional {
final Object d;
final Object e;
final FirebaseDB.ReturnVal f;
Transactional(Object param1Object1, Object param1Object2, FirebaseDB.ReturnVal param1ReturnVal) {
this.d = param1Object1;
this.e = param1Object2;
this.f = param1ReturnVal;
}
abstract Transaction.Result a(MutableData param1MutableData);
FirebaseDB.ReturnVal a() {
return this.f;
}
}
}`
it says when trying to build
[javac] Compiling 1 source file to C:\Users\oussama\extension-template\build\classes
[javac] warning: [options] bootstrap class path not set in conjunction with -source 1.7
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:1: error: ';' expected
[javac] package com.m.co/;
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:219: error: ')' expected
[javac] }firebase, null);
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:219: error: illegal start of expression
[javac] }firebase, null);
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:219: error: ';' expected
[javac] }firebase, null);
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:219: error: illegal start of expression
[javac] }firebase, null);
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:471: error: ')' expected
[javac] }firebase, new Runnable(this, returnVal) {
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:471: error: illegal start of expression
[javac] }firebase, new Runnable(this, returnVal) {
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:471: error: ';' expected
[javac] }firebase, new Runnable(this, returnVal) {
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:471: error: ';' expected
[javac] }firebase, new Runnable(this, returnVal) {
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:472: error: illegal start of expression
[javac] public void run() {
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:472: error: illegal start of expression
[javac] public void run() {
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:472: error: ';' expected
[javac] public void run() {
[javac] ^
[javac] C:\Users\oussama\extension-template\src\FirebaseDB.java:475: error: illegal start of expression
[javac] });
[javac] ^
[javac] 13 errors
[javac] 1 warning