My code uses Remote Config to check for app updates as follows:
ForceUpdateChecker.with(this).onUpdateNeeded(this).check();
final FirebaseRemoteConfig firebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
// set in-app defaults
Map<String, Object> remoteConfigDefaults = new HashMap();
remoteConfigDefaults.put(ForceUpdateChecker.KEY_UPDATE_REQUIRED, false);
remoteConfigDefaults.put(ForceUpdateChecker.KEY_CURRENT_VERSION, "2.00.229");
remoteConfigDefaults.put(ForceUpdateChecker.KEY_UPDATE_URL,
"https://play.google.com/store/apps/details?id=com.chiaramail.pento");
firebaseRemoteConfig.setDefaultsAsync(remoteConfigDefaults);
firebaseRemoteConfig.fetchAndActivate() // fetch config from server and activate
.addOnCompleteListener(new OnCompleteListener<Boolean>() {
#Override
public void onComplete(#NonNull Task<Boolean> task) {
if (task.isSuccessful()) {
Log.d(TAG, "FirebaseRemoteConfig fetched");
} else {
Log.d(TAG, "FirebaseRemoteConfig error:" + task.getResult());
}
}
});
Since I've updated the release containing this code, several users have crashed with the result 'TOO_MANY_REGISTRATIONS'. I believe I've looked at all the SO posts that relate to this problem, but none of them are using fetchAndActivate(). Also, I only have about 1200 users at this point, so hopefully the number of fetches isn't the problem; besides, as I understand it, Remote Config was built to push changes out to one's entire user base, so 1200 users (perhaps up to 6000 devices, max) should not be a problem.
Related
I cannot get my Android device to receive a test variant during the AB experiment.
What i did
In Firebase admin panel, I created a variable with this value:
And created an AB test with three variants:
Then I got an instance token as per docs:
FirebaseInstallations.getInstance().getToken(/* forceRefresh */true)
.addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
#Override
public void onComplete(#NonNull Task<InstallationTokenResult> task) {
if (task.isSuccessful() && task.getResult() != null) {
Log.d("Installations", "Installation auth token: " + task.getResult().getToken());
promise.resolve(task.getResult().getToken());
} else {
Log.e("Installations", "Unable to get Installation auth token");
}
}
});
and added it to my test devices list:
What happened
However, after rebooting the app (I also cleaned the cache and force-stopped it just in case it cached something) it still receives the original default value:
...
Map<String, Object> responseMap = new HashMap<>(2);
responseMap.put("result", result);
responseMap.put("constants", module.getConstantsForApp(FirebaseApp.DEFAULT_APP_NAME));
Log.d("REMOTECONFIG", responseMap.toString());
...
in the logs:
10-04 10:25:12.886 16964 16964 D REMOTECONFIG: {result=true, constants={minimumFetchInterval=43200, fetchTimeout=60, values={testValue=Bundle[{source=remote, value=somedefault}]}, lastFetchTime=1601796312020, lastFetchStatus=success}}
Why is that? what am I missing? I doublechecked my token, verified it with jwt.io, it is valid and not expired.
I have created some test project for learning Firebase remote config. This is settings in firebase https://monosnap.com/file/0xgQCL7oo7lyOjBs8CG3kZO0szBXh6 . Bellow my code:
final FirebaseRemoteConfig config = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(BuildConfig.DEBUG)
.build();
config.setConfigSettings(configSettings);
String onlineVersion = FirebaseRemoteConfig.getInstance().getString("android_current_version");// empty string
I dont know why i cant get value from firebase
Maybe you need to fetch the remote config first:
config.fetch(cacheExpiration)
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(MainActivity.this, "Fetch Succeeded",
Toast.LENGTH_SHORT).show();
// After config data is successfully fetched, it must be activated before newly fetched
// values are returned.
mFirebaseRemoteConfig.activateFetched();
} else {
Toast.makeText(MainActivity.this, "Fetch Failed",
Toast.LENGTH_SHORT).show();
}
String onlineVersion = FirebaseRemoteConfig.getInstance().getString("android_current_version");// empty string
}
})
In the "onComplete" method, you can get the remote config info
check this: Remote Config
I am using Cloud Firestore in my Android app. It's a quiz application where I randomly get documents from Firestore. When the internet connection is good, the app works fine. When the network gets disconnected and then again gets connected, I am unable to read the documents. When I debug, I find that my get() method is not getting executed at all.
Iterator iterator = randomIds.iterator();
while (iterator.hasNext()) {
String documentId = (String) iterator.next();
DocumentReference documentReference = db.collection(categoryName).document(documentId);
if (documentReference!=null) {
documentReference.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
System.out.println("Task successful");
DocumentSnapshot document = task.getResult();
questionDetailsObj = new QuestionDetails();
questionDetailsObj = document.toObject(QuestionDetails.class);
if (questionDetailsObj != null) {
System.out.println("Question details: " + questionDetailsObj.getQuestion_text());
// Adding the questions to a list
questionsList.add(questionDetailsObj);
}
} else {
Log.d("MainActivity", "get() failed with " + task.getException());
}
}
});
}
}
I want to retrieve 10 documents. Sometimes, few documents are retrieved successfully and for the others I get the exception
get() failed with com.google.firebase.firestore.FirebaseFirestoreException:
Failed to get document because the client is offline.
I don't understand why would some documents come successfully and some fail to get retrieved. Please help me understand if any code changes are required.
Im working on a android app with email-password login.
The user is created in a local sqlite db and in firebase + auth.
Situation: The user uninstalls the app, the local db is deleted. Then the user re-installs the app and wants to login using old credentials, But the user does not exist locally thus the app tries to create a new. - but the user already exist remote in my firebase users table + auth.
Question: How do I query either firebase auth or firebase for the user info only using email, pass and perhaps a few extras.
Most answers I found refer to using the update event from firebase, but at this point it´s not possible as the user is not yet authenticated
I solved it myself.
It was simple and not at all. A part of my fix is below. But in short. I get the user from firebase, then make an update to firebase and then I restore the user in a addValueEventListener(new ValueEventListener()
_fbAuth.signInWithEmailAndPassword(_email, _password).addOnCompleteListener(LoginActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Firebase login success");
FirebaseUser fbUser = _fbAuth.getCurrentUser();
String uid = fbUser.getUid();
FireBaseWriteHelper wh = new FireBaseWriteHelper();
FireBaseReadHelper fireBaseReadHelper = new FireBaseReadHelper(getApplicationContext(), uid, Util.VERSION_KEY_FREE);
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
Date date = new Date();
wh.UpdateUserLastLogIn(uid, format.format(date));
_user = _userHelper.CheckUserExist(_email, _password);
mPasswordView.setError(null);
mEmailView.setError(null);
} else {
try {
throw task.getException();
} catch (FirebaseAuthInvalidUserException e) {
} catch (FirebaseAuthInvalidCredentialsException e) {
} catch (FirebaseNetworkException e) {
} catch (Exception e) {
}
}
}
});
You can use the Firebase in Offline mode. You don't need to use two databases. Guide here.
In my case, Firestore database looks like below, where each Android client will have one document mapped to his/her device Document_sdfljkhsdio ( specific to Android User 1 )
FireStoreCollection
Document_sdfljkhsdio ( specific to Android User 1 )
Collection_xyz
Document_xyz
Document_kjjkssefd ( specific to Android User 2 )
Collection_xyz
Document_xyz
Document_sqdfwdfsme ( specific to Android User 3 )
Collection_xyz
Document_xyz
I am not implementing Google Auth, but instead want to send document name Document_sdfljkhsdio as request data and match it with some rules at Firebase Console
service cloud.firestore {
match /databases/{database}/documents {
match /document/{document_sent_from_client}/ {
allow read, write: if request.document_sent_from_client == document_sent_from_client;
}
}
}
Am not sure if it is possible to send document name from Android device ,if yes, please suggest.
And also suggest if it is the correct approach, suggest if you have any better approach ?
Thanks for your help in advance.
Sounds totally feasible. To pass the document_sent_from_client from an Android client, just build a DocumentReference with a path to /document/document_sent_from_client. Modified from the documentation:
DocumentReference docRef = db.collection("document").document("document_sent_from_client");
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
Log.d(TAG, "DocumentSnapshot data: " + task.getResult().getData());
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
But the security rules don't help here: if the client requests an existing document (i.e. if they know the path to a document), they will get a result. If they request a non-existing document (i.e. if they don't know the path to a document), the task will fail.
You're essentially depending on the key in document_sent_from_client to be reasonably unguessable. Such "security by obscurity" is fairly common in the absence of an authenticated user.