Android - setup multiple Firebase projects with different services within one application - android

How do I integrate two Firebase projects within one Android app, so that both will still work independently?
The background:
Within my company's app I was using until now some old Firebase project mainly for GCM purposes. Now the decision within my organization has changed and we decided to move most of the services to the new Firebase project, with higher pricing plan - unfortunately the upgrade wasn't an option.
At this very moment I have:
a legacy project for Cloud Messaging stuff related to some marketing service,
a new Firebase project that will be used for Crashlytics, Remote Config flags and some more.
We don't want to move with Cloud Messaging due to the restrictions the switch causes - all the users would need to register to new notifications channel again. For Marketing reasons that's something unacceptable.
For now I was trying to use the new project's JSON configuration file initialized automagically by Gradle plugin and manual approach to register to the legacy FCM service like this:
FirebaseOptions fo = new FirebaseOptions.Builder()
.setApplicationId(appId)
.setApiKey(apiKey)
.setGcmSenderId(legacySenderId)
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(context, fo, "legacy");
HandlerThread thread = new HandlerThread("getLegacyTokenThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
handler.post(() -> {
try {
String token = FirebaseInstanceId.getInstance(firebaseApp).getToken(legacySenderId, "FCM");
L.w("Received token: " + token);
} catch (IOException e) {
e.printStackTrace();
}
});
But this approach seems to be overriding my default project configuration, so the exceptions are not reported to Crashlytics belonging to the new project.
Can anyone suggest how do I make it to run both projects successfully?

Following #Frank's comment above, I didn't manage to make this kind of integration successful.
We ended up in creating a new app in the marketing service that is using new credentials instead of changing the previous ones, what would result in invalidation of the integration. This way we can target both old app's users who didn't update as well as the new ones.

Related

Amplify.observe not updating based on changes to DynamoDB

I am currently making a call to my server to make a change in the Datastore and listening for another change to it. I do not receive any new changes from the DB despite the database being changed correctly on the backend.
I recently upgraded amplify from 1.4.2 to 1.6.8 and this is when the issue started to show up.
Amplify.DataStore.observe(Profile::class.java,
{ observationCancelable ->
//ERROR
},
{ changedItem ->
when (changedItem.item().state) {
//DO Business logic
}
},
{ exception ->
//ERROR
},
{
}
)
When I query the datastore I am getting outdated results that are not the same as the data on DynamoDB. Is there any way to figure out why the local datastore is not being updated? Could it be an issue with the configuration with the server? Or is there some setup step that I have missed?
Edit: Added some extra details below
So a few more details I wanted to add to this that seem way more relevant as well as updates based on my research. I am switching between endpoints(dev to testing environments). It would seem that the dev environment is working fine with the application, using the datastore correctly and doing the proper AppSync. But in the new testing environment, when the app starts, it gets the latest version of the datastore but it fails to do any AppSync despite being able to make changes to the backend.
Here is an error I am getting when the app attempts to subscribe to the Profile object in the back end
amplify:aws-datastore: Unauthorized failure for ON_CREATE Profile
amplify:aws-datastore: Releasing latch due to an error: Subscription error for Profile: [GraphQLResponse.Error{message='Not Authorized to access onCreateProfile on type Subscription', locations='null', path='null', extensions='{errorType=Unauthorized}'}]
Is there some config file that I should be looking at to compare with to make sure that the endpoints match or some access key that the app needs?

Can two different Firebase project be used in one Android app, specifically crashlytics, messaging and performance extensions

For a couple of reasons we had to use multiple Firebase projects in one app. At the moment we have implemented auth extension to user one Firebase project and via code initialisation and crashlytics, performance and messaging to use another via the config file. We would like to make crashlytics and performance extensions to use the project that the auth extension uses and messaging to use the same one that it uses now.
I went through some initialisation examples but could not find anything related to crashlytics or performance extensions.
This is how I initialise different project for auth extension.
// credentials for auth project on Firebase
final String authAppName = BuildConfig.AUTH_APP_NAME;
final String authAppApplicationId = BuildConfig.AUTH_APPLICATION_ID;
final String authAppApiKey = BuildConfig.AUTH_APPLICATION_KEY;
List<FirebaseApp> listOfActiveApps = FirebaseApp.getApps(context);
if (!listOfActiveApps.isEmpty()) {
for (FirebaseApp app : listOfActiveApps) {
if (authAppApiKey.equals(app.getOptions().getApiKey())) {
return app;
}
}
}
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId(authAppApplicationId)
.setApiKey(authAppApiKey)
.build();
return FirebaseApp.initializeApp(context, options, authAppName);
Fabric/Firebaser here, great question - this behavior is generally not supported today, due to the way Crashlytics and Performance need to initialize, particularly when mixed with Auth.

Multiple public Firebase Database Instances in Android

I'm working on an assignment. I've to use Database provided by a provider 'hacker-news'. Also i've to use Firebase Authentication. I've setup a new project in my own account. Retrieving data from Hacker-news database works with below line. I'm able to fetch publicly accessible data with firebase child() APIs is
database = FirebaseDatabase.getInstance("https://hacker-news.firebaseio.com/");
But when i implemented Firebase Authentication and once user logs in it is giving error
Provided authentication credentials are invalid. This usually indicates your FirebaseApp instance was not initialized correctly. Make sure your google-services.json file has the correct firebase_url and api_key
I've spent lot of time on internet and found a link to implement multiple databases in single project -
Working with multiple Firebase projects in an Android app by Google
This works only if you are the owner of those Databases. Is there anyway i can access Hacker-news Database using SDK not REST-API?
FirebaseOptions options = new FirebaseOptions.Builder()
.setDatabaseUrl(getResources().getString(R.string.dbURL))
.setApiKey(getResources().getString(R.string.api))
.setApplicationId(getResources().getString(R.string.appID))
.setProjectId(getResources().getString(R.string.projectId))
.setStorageBucket(getResources().getString(R.string.storageBucket)).build();
//set all variable above as your need
boolean hasBeenInitialized=false;
List<FirebaseApp> fireBaseApps = FirebaseApp.getApps(getApplicationContext());
for(FirebaseApp app : fireBaseApps){
if(app.getName().equals("any_name")){
hasBeenInitialized=true;
}
}
if (!hasBeenInitialized) {
smaTeacher = FirebaseApp.initializeApp(this, options, "any_name");
}
database=FirebaseDatabase.getInstance(FirebaseApp.getInstance("any_name"));

New Google Sign-In Implementation with App Engine Backend

Google has just released a new way to let users sign in to an application with their google account:
http://android-developers.blogspot.de/2016/05/improving-security-and-user-experience.html
https://developers.google.com/identity/sign-in/android/start-integrating
Since it's recommended to use the new API, I'd like to do so. However, I'm not quite sure yet about some of the steps. It's clear to me how to implement the sign in workflow itself (the sample application is quite easy to understand). However, how do I get the API service handle for my backend service?
Until now, I used to do it like this: First, get a GoogleAccountCredential like this:
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(
context, "server:client_id:" + WEB_CLIENT_ID);
credential.setSelectedAccountName("example#gmail.com");
Then, I passed these credentials on to the automatically generated android client library for the app engine endpoints:
User.Builder b = new User.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), CREDENTIALS_FROM_STEP_1).setApplicationName("App");
That was it. However, I have no idea how to get the GoogleAccountCredential when using the new sign in workflow. Has anyone got an idea? Do I need to update the backend as well? As I said, the whole OAuth2 communication and authorization with my backend is done by the auto-generated client libraries.

GoogleCredential won't build without GoogleCredential.Builder

In the Google documentation for OAuth2, building a GoogleCredential with an auth token is described here:
Credential and Credential Store
In particular this code snippet is offered:
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Plus plus = Plus.builder(new NetHttpTransport(), new JacksonFactory())
.setApplicationName("Google-PlusSample/1.0")
.setHttpRequestInitializer(credential)
.build()
When I try to build a GoogleCredential in this way I am tersely informed:
Please use the Builder and call setJsonFactory, setTransport and setClientSecrets
in the message field of an exception. I downloaded the libraries for this last week so I am not sure what is happening. Is the documentation simply outdated, and if so, what method has replaced this one as best practice for building from an existing auth token and refresh token?
Incidentally, the reason using the Builder was not an option was that there WAS no client secret provided by the Google application console; it says that they are no longer provided for Android apps and the like. setClientSecrets(...), therefore, couldn't be called.
I met this problem recently and figured out the solution for my case.
Here is the running conditions: the program is running on Android 4.0 and does not use Google Drive SDK, because it could not allow our program to read the files on Google Drive which are not created by our program. I use the com.google.api.services.drive.* and com.google.api.client.googleapis.auth.oauth2.* Java libraries.
the code arose this problem is like below :
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET, Arrays.asList(DriveScopes.DRIVE))
.setAccessType("offline")
.setApprovalPrompt("auto").build();
GoogleTokenResponse response = null;
try {
response = flow.newTokenRequest(authorizationCode).setRedirectUri(REDIRECT_URI).execute();
} catch (IOException e) {
e.printStackTrace();
}
GoogleCredential credential = new GoogleCredential().setFromTokenResponse(response);
but above code worked well if the parameter to setAccessType("online");
and the resolution for this issue depends on what kind of accessType you want.
if you want "onLine" as the accessType, then use setFromTokenResponse()should be ok.
if you want "offline" as the accessType, then you need to use blow code :
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.build()
.setFromTokenResponse(response);
One thing need to be mentioned is that you need to keep the accessType setting to be consistent for GoogleTokenResponse and GoogleAuthorizationCodeFlow creation.
You need to set up your Android app key in Google Dev Console.
Choose your project, select API & Auth, then click Credentials
Create new client id (though it has other client ids)
Select installed app -> android
Fill in your package name and SHA1 correctly
Create new Key (though it has other client keys)
Select Android key
Fill in the SHA1;packageName like this: 45:B5:E4:6F:36:AD:0A:98:94:B4:02:66:2B:12:17:F2:56:26:A0:E0;com.example
Your problem will be automatically solved. Be sure to create client id and key with both your debug keystore and release keystore.
Check the Android quickstart sample in the Google Drive SDK documentation for step-by-step instructions to correctly setup GoogleCredential:
https://developers.google.com/drive/quickstart-android

Categories

Resources