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.
We've all been in this situation before: you work tirelessly to build a great app, you spend countless hours beta testing and fixing bugs, and you even put together a comprehensive marketing plan in time for your app's launch. Months of anticipation finally culminate when you submit your app to the app store… but instead of celebrating the new release, you find out that your app didn't meet the right criteria for listing so it got rejected 😱.
There's nothing quite as deflating as tripping at the finish line.
App store guidelines can be complicated and hard to remember because they're constantly changing, but developers still need to follow them in order to get their apps approved. Sometimes, these guidelines get overlooked or lost in the shuffle of all the other important pre-launch tasks. To help you avoid unnecessary delays and rejection, we're excited to introduce fastlane precheck for iOS apps! You can count on us to remember the rules so you can submit your app with confidence.
Often, apps get rejected from app stores because of simple, solvable issues with their metadata (such as title, description, changelog, keywords, etc.). Once rejected, you have to resubmit your app and it can take days before it's reviewed again. This wastes time and can throw off your schedule.
Instead of risking rejection or painstakingly auditing your own metadata, you can now use fastlane precheck to save you the time and hassle. fastlane will review your app for the most common causes of rejection 👍.
For example, we'll check your metadata to ensure it follows iOS app store rules such as:
If we detect any issues, we'll flag them for you so you can resolve them before you submit your app to the app store. And since fastlane can automatically download your app's metadata, this whole process takes only seconds!
fastlane precheck is the first new tool we've added to our app automation toolkit since joining Google - and we have even more exciting updates planned! Now that we've settled into our new home, we can't wait to move fastlane forward with our passionate community of iOS and Android developers.
In the meantime, install fastlane or update your version of fastlane (just run `fastlane update_fastlane`) to try precheck and submit your app with confidence and peace of mind 🚀.
Many Firebase developers focus on their apps alone, usually for Android, iOS, or the Web (or all three!). If you're like me, and you spend most of your time on the client side, it can be a hassle to also deal with any backend components. Now that we have Cloud Functions for Firebase, it's super easy and fun to write and deploy backend code in JavaScript without having to manage servers. Personally, my comfort zone is with Android. So, to get acquainted with Cloud Functions, I spent some time brushing up on my JavaScript and learning node.js, which Cloud Functions uses to run backend code.
As part of that period of ramping up, I learned a new way of managing asynchronous work in JavaScript. If you've had experience working with JavaScript in the browser or with Cloud Functions, you may already be familiar with a class called Promise. A promise is a very common way to handle async work. The closest concept for Android developers is the Task API that you sometimes use when dealing with Firebase APIs.
A promise lets you respond to a unit of work that's executing asynchronously, such as a database write or a network request. Cloud Functions understand promises; if you want a function to stay alive during async work, you can do this by returning a promise from the function (except for HTTP/S triggers, which require a response sent to the client). When you return a promise, be sure to return a promise that is "resolved" after all asynchronous work performed in that function is fully complete. Many developers have found this video from the Firebase channel on YouTube very helpful for understanding how promises work with Cloud Functions:
In the video, Jen describes two main ways of dealing with promises. First, there's using the then() method on a promise to chain items of work in sequence, where the next item of work depends on the results from the previous item. Second, there's Promise.all() which creates a new promise that resolves after multiple items of work happening in parallel are all complete. Between these two mechanisms, you can manage most work that normally occurs in a function. When the work is complete, you return the final promise from the function so that the Cloud Functions environment knows when to clean up.
then()
Promise.all()
For simple functions, this works out pretty easily. But many of you (including myself) have discovered that complicated functions can be really difficult to manage when there's a lot of work (with lots of promises) going on. One of the symptoms of mismanaged promises is seeing the following error in the function log in the Firebase console:
Error: read ECONNRESET
This error could mean a few different things. In some cases it could be a bug in a client library. In other cases, it's a symptom of a common mistake when dealing with promises.
If a function is terminated before its network connections are finished, that means those open connections could be forced to close, leaving an ECONNRESET in the log. Here's a situation when that can occur.
ECONNRESET
Imagine you want to start three items of async work, and the work is kicked off in a function called doSomeAsync(), which returns a promise that's resolved upon completion, and you return the promise from the third task like this:
doSomeAsync()
doSomeAsync(x) doSomeAsync(y) return doSomeAsync(z)
Returning a Promise from the function is good. But Cloud Functions needs a promise that resolves when all of the work is fully complete. If we don't have a guarantee that the last item of work will always finish after the other two, then Cloud Functions may clean up the function prematurely, causing problems. Instead, we need to combine all of the promises from all of the work into a new promise that resolves only after all of the others resolve, like this:
const promise_x = doSomeAsync(x) const promise_y = doSomeAsync(y) const promise_z = doSomeAsync(z) return Promise.all([promise_x, promise_y, promise_z])
If you're not tracking every single item of asynchronous work that you kick off in a function, you could see the dreaded ECONNRESET error in your log, and things may not work the way you expect. It really can take some diligence to keep all your promises!
If you want to see an example of a more complicated function, I have an open source tic-tac-toe web game that I wrote for a session I gave at Google I/O '17 that talks about how it was built entirely with Firebase.
For more tutorials and content about Cloud Functions, and other Firebase products, be sure to check out the Firebase channel on YouTube and the Firebase Blog.
Just two weeks ago, we hosted our party at WWDC to celebrate app development with the iOS community. We were thrilled to meet many of you including tons of talented developers from Apple, Uber, Spotify, Tinder, and more. With over a thousand RSVPs, it was amazing to see the excitement among the community!
Since we can't travel back in time, here are some highlights so you can relive the night of fun.
We love our customers - so what better way to show our appreciation then rolling out the red carpet? We also made sure to have friendly hosts to greet you at the door and security guards as rigorous as an IDS.
We noticed most of you felt right at home at Forager. It was great to see all of you mingle with each other and with us to and discuss app development and all the WWDC announcements of the day. Whether we found you at the stand up tables, or hanging out on the blue and yellow sofas: everyone was having fun!
Thank you to all those who submitted creative names for our cocktails and congrats to the winners! The Minty Multithread and Nulltonic Expression were hits and went great with the finger-licking good appetizers.
Many of you shared your passion projects with other developers on the flat screens throughout the venue. And we couldn't keep ourselves from grinning at some of the pics from the paparazzi style photo booth. See all the photo booth moments here.
Over half of you played AppShip3000 - our flagship cooperative multiplayer game. You either flexed your knowledge muscle, or learned a thing or two about Firebase. And many of you also saw one of our engineers live-code an app. Was it a hotdog? Or not? What do you think?
Since it's dub dub, we crafted custom designed iPhone protective cases for you to take home (in case cocktails and holding-onto-phones don't mix). Stylish tees included as usual.
Thank you to all those who joined us for the night - we were glad to share all the laughter with you. Check out our full photo album. (photos credit: Yvonne TNT)
Here's to next year!
In their words:
Firebase party is fancy one. there is a line 🤳💪🤸♀️🎉 pic.twitter.com/gsIyoM5NP1— Marcin Krzyzanowski (@krzyzanowskim) June 6, 2017
Firebase party is fancy one. there is a line 🤳💪🤸♀️🎉 pic.twitter.com/gsIyoM5NP1
Cool setup at the Firebase/Fabric party 🎉 pic.twitter.com/pTyC3QBmT9— Adam Oxner (@adoxner) June 6, 2017
Cool setup at the Firebase/Fabric party 🎉 pic.twitter.com/pTyC3QBmT9
Thanks @Firebase + @fabric for hosting tonight. We @apponboardinc had a blast meeting all the great developers! #wwdc2017 #wwdc pic.twitter.com/9V0eMaK0hR— Matt Chin (@mattchinni) June 6, 2017
Thanks @Firebase + @fabric for hosting tonight. We @apponboardinc had a blast meeting all the great developers! #wwdc2017 #wwdc pic.twitter.com/9V0eMaK0hR
Amazing part thrown by @Firebase #wwdc17 #firebaseparty pic.twitter.com/HbE5EqcEVg— NIkant Vohra (@nikant_vohra) June 6, 2017
Amazing part thrown by @Firebase #wwdc17 #firebaseparty pic.twitter.com/HbE5EqcEVg
Firebase Party was 🔥 https://t.co/MWmnQgw9n9— /Users/tomn/ (@tomn94) June 6, 2017
Firebase Party was 🔥 https://t.co/MWmnQgw9n9
#firebase party 🔥#WWDC17 https://t.co/g4EbybfgxW— Adrien Coye (@acoye) June 6, 2017
#firebase party 🔥#WWDC17 https://t.co/g4EbybfgxW
Icing on the #firebaseparty cake - Firebase and Fabric-branded M&Ms pic.twitter.com/aXhGXBk5i7— Dave Air (@dave_air) June 6, 2017
Icing on the #firebaseparty cake - Firebase and Fabric-branded M&Ms pic.twitter.com/aXhGXBk5i7
As the developer or the administrator of an app built on Firebase, you may need to perform various user management tasks. These include:
The Firebase Admin SDK provides a powerful API for performing these kinds of user management tasks from privileged environments. Using the Admin SDK, you can program these capabilities directly into your admin consoles, dashboards and other backend services. Unlike the Firebase client SDK, the Admin SDK is initialized with a service account credential, which grants the SDK elevated privileges necessary to perform user management operations.
This is not a brand new feature. The Firebase Admin Node.js SDK has had a user management API for a while. However, we are happy to announce that this API is now also available in our Admin Java SDK starting from version 5.1.0. This is one of the most requested features for the Admin Java SDK, and we are certain many Firebase app developers are going to find it useful.
The Java user management API closely mirrors its Node.js counterpart. Specifically, it consists of five new methods:
getUser()
getUserByEmail()
createUser()
updateUser()
deleteUser()
Following code snippet shows how to use some of these new methods in practice. In this example we retrieve an existing user account, and update some of its attributes:
final FirebaseAuth auth = FirebaseAuth.getInstance(); Task task = auth.getUserByEmail("editor@example.com") .addOnSuccessListener(userRecord -> { System.out.println("Successfully fetched user data: " + userRecord.getUid()); UpdateRequest update = userRecord.updateRequest() .setDisabled(false) // Enable the user account .setEmailVerified(true); // Set the email verification status auth.updateUser(update); }) .addOnFailureListener(e -> { System.err.println("Error fetching user data: " + e.getMessage()); });
You can learn more about the Firebase user management API from the Admin SDK documentation. Additionally, head over to our Github repo to see how it is implemented. (Yes, it's all open source!). You can also help us further improve this API by providing us feedback and reporting issues. As always, we are open to all sorts of contributions including pull requests to our codebase. Happy coding with Firebase!