
Read more »

Until recently, developers were required to update their Android tools to make use of new versions of the local maven repository that contains Play services compile dependencies. Only after updating were the Android build tools able to locate them. Now, the dependencies are available directly from maven.google.com. You can update your app's Gradle build scripts to use this repository by simply configuring the build like this:
allprojects {
repositories {
jcenter()
maven { url 'https://maven.google.com' }
}
}
Note the new Google maven repository. This is where dependencies are now hosted. Using Gradle 4.0 and later, you can simply specify google() as a shortcut instead. Once configured like this, Gradle will be able to locate, download, and cache the correct Play services dependencies without requiring an update to the Android build tools. Play services SDKs going back to version 3.1.36 will be available in this repo.
You can read more about Google's maven repo here.
compileSdkVersion must be at least 26When you upgrade your app's Play services dependencies to 11.2.0 or later, your app's build.gradle must also be updated to specify a compileSdkVersion of at least 26 (Android O). This will not change the way your app runs. You will not be required to update targetSdkVersion. If you do update compileSdkVersionto 26, you may receive an error in your build with the following message referring to the Android support library:
This support library should should not use a different version (25) than the compileSdkVersion (26).
This error can be resolved by upgrading your support library dependencies to at least version 26.0.0. Generally speaking, the compileSdkVersion of your app should always match the major version number of your Android support library dependencies. In this case, you'll need to make them both 26.

If you haven't tried Firebase Performance Monitoring yet, many Firebase developers have found it to be a helpful way to get a sense of some of the performance characteristics of their iOS or Android app, without writing many extra lines of code. To get more detailed information beyond what's collected automatically, you'll eventually have to write some custom traces and counters. Traces are a report of performance data within a distinct period of time in your app, and counters let you measure performance-related events during a trace. In today's perf tip, I'll propose a way to add potentially many more traces to your Android app without writing very much code at all.
Android apps are typically made up of a collection of activities that present some task or data to the user. For the purpose of hunting down potential performance problems, it can be handy to define a trace for every Activity in your app, so you can study the results later in the Firebase console. If your app has lots of activities, it might be kind of a pain to write the code for all of them. Instead, you can write a little bit of code that instruments all of them with their own trace.
Android gives you a way to listen in on the lifecycle of every single Activity in your app. The listeners are implementations of the interface ActivityLifecycleCallbacks, and you can register one with the Application.registerLifecycleCallbacks()method. For measuring performance, I suggest creating a trace that corresponds to the onStart() and onStop() lifecycle methods. When an activity is "started", that means it's visible on screen, and when it's "stopped", it's no longer visible, so I think this is a good place to define a trace that tracks an activity while it's actually doing things. Here's the start of an implementation of ActivityLifecycleCallbacks that keeps track of traces for each of your activities. First we'll make it a singleton so it can be easily accessed everywhere (or you might want to use some form of dependency injection):
public class PerfLifecycleCallbacks
implements Application.ActivityLifecycleCallbacks {
private static final PerfLifecycleCallbacks instance =
new PerfLifecycleCallbacks();
private PerfLifecycleCallbacks() {}
public static PerfLifecycleCallbacks getInstance() {
return instance;
}
}
Then, inside that class, I'll add some members that manage custom traces for each Activity:
private final HashMap<Activity, Trace> traces = new HashMap<>();
@Override
public void onActivityStarted(Activity activity) {
String name = activity.getClass().getSimpleName();
Trace trace = FirebasePerformance.startTrace(name);
traces.put(activity, trace);
}
@Override
public void onActivityStopped(Activity activity) {
Trace trace = traces.remove(activity);
trace.stop();
}
// ...empty implementations of other lifecycle methods...
This will start a trace when any activity is started, and stop the same trace when the activity is stopped. For the name of the trace, I'm using the simple class name of the activity object, which is just the class name without the full java package. (Note: if you do this, make sure that your Activity class names are unique, if they're spread across Java packages!)
I'll add one more method to it that will return the trace of a given Activity object. That can be used in any activity to get a hold of the current trace so that counters can be added to it:
@Nullable
public Trace getTrace(Activity activity) {
return traces.get(activity);
}
This class should be registered before any Activity starts. A ContentProvider is a good place to do that. If you're not familiar with how that works, you can read about how Firebase uses a ContentProvider to initialize.
public class PerfInitContentProvider extends ContentProvider {
@Override
public boolean onCreate() {
context = getContext();
if (context != null) {
Application app = (Application) context.getApplicationContext();
app.registerActivityLifecycleCallbacks(
PerfLifecycleCallbacks.getInstance());
}
}
}
Don't forget to add the ContentProvider to your app's manifest! This will ensure that it gets created before any Activity in your app.
Once this ContentProvider is in place, your app will automatically create traces for all your activities. If you want to add counters to one of them, simply use the getTrace() method from the PerfLifecycleCallbacks singleton using the current Activity object. For example:
private Trace trace;
@Override
protected void onCreate(Bundle savedInstanceState) {
trace = PerfLifecycleCallbacks.getInstance().getTrace(this);
// use the trace to tally counters...
}
Be sure to think carefully about the counters you want to log! You'll want to measure things that will give you information that helps inform a decision about how the user experience could be improved in your app. For example, you could record the ratio of cache hits to misses to help tune the amount of memory for the cache. And be sure to follow Firebase on Twitter to get more Firebase Performance Monitoring tips.
Sometimes the worst bugs to track down are the ones that seem to be impossible to reproduce. Or worse, inconsistent performance problems that can cause "Application Not Responding" errors in Android apps. No matter how much test code you write, these types of errors seem to have a way of sneaking into your app and causing problems for your users. However, with some clever use of Android's StrictModeAPI, alongside Firebase Test Lab for Android, you can find out about these problems before they reach production!
Over the years since Android was first available, a number of best practices have been observed for writing solid apps. For example, you shouldn't be performing blocking I/O on the main thread, and you shouldn't store references to Activity objects that are held after the Activity is destroyed. While it's likely that no one will force you to observe these practices (and you may never see a problem during development), enabling StrictMode in your app will let you know where you've made a mistake. These are called "policy violations", and you configure these policies with code in your app.
Personally, I don't want any of my code to cause any StrictMode violations. In fact, I'd like to consider them bugs that are just as serious as a regular crash, because they could crash my app in some cases! And, in fact, I can configure all StrictMode violations to crash the app. The Java code for that looks like this:
private static final StrictMode.ThreadPolicy FATAL_THREAD_POLICY =
new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.penaltyDeath()
.build();
private static final StrictMode.VmPolicy FATAL_VM_POLICY =
new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.penaltyDeath()
.build();
public static void enableFatalStrictMode() {
if (shouldEnableFatalStrictMode()) {
StrictMode.setThreadPolicy(FATAL_THREAD_POLICY);
StrictMode.setVmPolicy(FATAL_VM_POLICY);
}
}
Here I have both a ThreadPolicy(for the main thread) and a VmPolicy(for the entire app) that look for all known violations, and will both log that violation and crash the app. Take a look through the javadoc for those builders to learn about all the situations they can catch.
Also notice that I'm enabling the policies conditionally. You probably don't want an accidental violation to crash on your users in production, so the method shouldEnableFatalStrictMode() typically looks like this, which activates it for your debug builds only:
private static boolean shouldEnableFatalStrictMode() {
return BuildConfig.DEBUG;
}
What I'd like to do is take this further and have StrictMode crash my app also when it's running in Firebase Test Lab. This is handy because the crash will fail the test, and I'll get a report about that in the test results. For that to happen, I can change the method to query a system setting on the device that's unique to devices in Test Lab. Note that this requires an Android Context to obtain a ContentResolver:
private static boolean shouldEnableFatalStrictMode() {
ContentResolver resolver = context.getContentResolver();
String isInTestLab = Settings.System.getString(resolver, "firebase.test.lab");
return BuildConfig.DEBUG || "true".equals(isInTestLab);
}
Now, my instrumented tests (and the automated Robo test) will crash with any StrictMode violations, and I'll see those very clearly in my Test Lab report. Here's an app that crashed in Test Lab with a StrictMode violation during a Robo test:
This doesn't tell you exactly what happened, though. Digging into the logs in the test report, I see the details of the violation right before the crash:
D/StrictMode(6996): StrictMode policy violation; ~duration=80 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=327743 violation=2
D/StrictMode(6996): at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1415)
D/StrictMode(6996): at java.io.UnixFileSystem.checkAccess(UnixFileSystem.java:251)
D/StrictMode(6996): at java.io.File.exists(File.java:807)
D/StrictMode(6996): at android.app.ContextImpl.getDataDir(ContextImpl.java:2167)
D/StrictMode(6996): at android.app.ContextImpl.getPreferencesDir(ContextImpl.java:498)
D/StrictMode(6996): at android.app.ContextImpl.getSharedPreferencesPath(ContextImpl.java:692)
D/StrictMode(6996): at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:360)
D/StrictMode(6996): at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:167)
D/StrictMode(6996): at com.google.firebasesandbox.MainActivity.onCreate(MainActivity.java:25)
D/StrictMode(6996): at android.app.Activity.performCreate(Activity.java:6982)
D/StrictMode(6996): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
D/StrictMode(6996): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
D/StrictMode(6996): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
D/StrictMode(6996): at android.app.ActivityThread.-wrap11(Unknown Source:0)
D/StrictMode(6996): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
D/StrictMode(6996): at android.os.Handler.dispatchMessage(Handler.java:105)
D/StrictMode(6996): at android.os.Looper.loop(Looper.java:164)
D/StrictMode(6996): at android.app.ActivityThread.main(ActivityThread.java:6541)
D/StrictMode(6996): at java.lang.reflect.Method.invoke(Native Method)
D/StrictMode(6996): at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
D/StrictMode(6996): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
So we've discovered here that an activity's onCreate() called getSharedPreferences(), and this method ends up reading the device filesystem. Blocking the main thread like this could be the source of some jank in the app, so it's worth figuring out a good way to move that I/O to another thread.
Now we have a way to check for StrictMode violations during a test, but there's still a few more details to work out.
If you do this immediately when the app launches (in an Application subclass or a ContentProvider), there is a subtle bug in some versions of Android that may need to be worked around in order to avoid losing your StrictMode policies when the first Activity appears.
There might be some times when you know there is a violation, but you can't fix the code right away for whatever reason (for example, it's in a library you don't control). In that case, you might want to temporarily suspend the crashing behavior and simply log it instead. To temporarily suspend the crash, you can define a couple other non-fatal policies and swap them in where you know there's an issue to ignore:
private static final StrictMode.ThreadPolicy NONFATAL_THREAD_POLICY =
new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build();
private static final StrictMode.VmPolicy NONFATAL_VM_POLICY =
new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build();
public static void disableStrictModeFatality() {
StrictMode.setThreadPolicy(NONFATAL_THREAD_POLICY);
StrictMode.setVmPolicy(NONFATAL_VM_POLICY);
}
Similarly, you may not want to track all the possible violations all the time. In that case, you might want to instruct the policy builder to only detect a subset of the potential issues.
While StrictMode violations are not always the worst thing for your users, I've always found it educational to enable StrictMode in order to find out where my app might be causing problems. In combination with Firebase Test lab, it's a great tool for maximizing the quality of your app.

Testing your application is a great way to help maximize its quality, and many of you know that Firebase Test Lab for Android has some useful tools for testing Android apps. If you're the type of engineer who likes to maximize test coverage by writing instrumented tests (and regular unit tests), you can send those to Test Lab for execution. Even if you don't like writing tests, you have some options. You can record instrumented tests by interacting with your app using Espresso Test Recorder in Android Studio. And there's almost no effort required at all to run a Robo test that automatically crawls your app.
These tests are helpful for data-driven apps because there are robust test frameworks that understand how to navigate the Android platform widgets used to receive input and display data on screen. However, most games don't work with platform widgets. Games typically take over the screen using their own UI elements, and provide their own touch controls. As a result, it's extremely difficult to write instrumented tests for testing games, and Robo test won't know how to navigate the game at all.
To help deal with these challenges with testing games, the Test Lab team has come up with a way for game developers to test their games effectively across many of the devices that Test Lab offers. It's a new type of test called a Game Loop Test, and it's available today in beta.
If you've seen arcade video games operate, you know that they're always showing something on screen, typically some automated demo of the game, called "attract mode". With Firebase Test Lab, game developers can now use this concept of attract mode to construct test scenarios, and Test Lab will arrange for those scenarios to be invoked in sequence. This gives developers the opportunity to test a wide variety of game levels and situations in a single test run on all the devices provided by Test Lab. If there are any problems with a scenario, you'll find out which ones are problematic, so you can focus your efforts on improving that specific case.
Even better, Test Lab now provides performance data with every report. Of particular interest to game developers is a graph of the rendered frame rate over time throughout the test, tied to a video of the device display. This helps you quickly identify the parts of your game that aren't rendering at an acceptable FPS.
In addition to FPS, there are other performance metrics available for all apps. You'll be able to see your app's CPU utilization, memory usage, and network ingress and egress. Notice how you can jump directly to the point in the video where you're observing performance problems.
If you're a game developer, now is a great time to check out Firebase Test Lab for Android to see what it can do to help the quality of your game.









onMessageReceived()and onTokenRefresh() have a guaranteed life cycle limited to 10 seconds (same as a Broadcast Receiver).@OverrideWe hope this helps you understand how to use FCM to schedule long-running background operations. This solution greatly helps Android to preserve battery life and ensures that your application works fine on Android O. In case you have any questions don't hesitate to ask us on our support channels.
public void onMessageReceived(RemoteMessage remoteMessage) {
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
/**
* Schedule a job using FirebaseJobDispatcher.
*/
private void scheduleJob() {
FirebaseJobDispatcher dispatcher =
new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("my-job-tag")
.build();
dispatcher.mustSchedule(myJob);
}
/**
* Perform and immediate, but quick, processing of the message.
*/
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}

FirebaseAuth auth = FirebaseAuth.getInstance();
if (auth.getCurrentUser() != null) {
startActivity(SignedInActivity.createIntent(this, null));
finish();
}
@OnClick(R.id.sign_in)
public void signIn(View view) {
startActivityForResult(
AuthUI.getInstance().createSignInIntentBuilder()
.setTheme(getSelectedTheme())
.setLogo(getSelectedLogo())
.setProviders(getSelectedProviders())
.setTosUrl(getSelectedTosUrl())
.setIsSmartLockEnabled(mEnableSmartLock.isChecked())
.build(),
RC_SIGN_IN);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
handleSignInResponse(resultCode, data);
return;
}
showSnackbar(R.string.unknown_response);
}
private void handleSignInResponse(int resultCode, Intent data) {
IdpResponse response = IdpResponse.fromResultIntent(data);
// Successfully signed in
if (resultCode == ResultCodes.OK) {
startActivity(SignedInActivity.createIntent(this, response));
finish();
return;
} else {
// handle failure conditions
}
}
<style name="DarkTheme" parent="FirebaseUI">
<item name="colorPrimary">@color/material_gray_900</item>
<item name="colorPrimaryDark">@android:color/black</item>
…
</style>
@OnClick(R.id.sign_in)
public void signIn(View view) {
startActivityForResult(
AuthUI.getInstance().createSignInIntentBuilder()
.setTheme(R.style.DarkTheme)
.setLogo(getSelectedLogo())
