Friday, 27 January 2017

Branding Guidelines for Angular and AngularJS

Angular
In September of last year we made several big announcements. We released version 2.0.0 of Angular and that we were adopting Semantic Versioning, meaning that developers will see version number increases in a planned and careful manner. As a result of these announcements, you’ve seen us using the term Angular to refer to all versions of the framework after 2.0.0.


We’ve had a great response from Developers about this. Bloggers and authors and discussions boards can in most contexts drop the version number from discussions of Angular, because the tutorials, tips, tricks, and content that works in version 2 will work in version 4, and likely beyond. This allows those discussing Angular to talk about the framework without becoming prematurely dated each time there’s a version bump.


Here’s an example tutorial you could write:


Correct
Angular Router Guide - Learn about how to use the Router in Angular as the basis for page animations, analytics tracking, and how to fetch parameters and data reactively from the router.
Incorrect
Angular 2 Router Guide - Learn about how to use the Angular 2 Router as the basis for page animations, analytics tracking, and how to fetch parameters and data reactively from the router.

Reasoning
By not using “Angular 2” in the title, the content still feels applicable and useful after version 4, 5, 6, 7, etc have been released, as the syntax is unlikely to change.


AngularJS
Our announcements around “It’s just Angular" were the first step in bringing consistency into the naming of the platform and the ecosystem. Our recommendation last month was to use Angular 1 for all 1.x versions of the framework and Angular for all the subsequent versions (unless a version was required for clarification in a given context). We heard from the community that because AngularJS has been used for for so long, it would be too hard and confusing to "rewrite history" across the web and the physical world.


We agree with this and we have accepted the suggestions many of you have brought up to return to our roots with the name AngularJS for any 1.x release, and Angular for any 2+ release. Our goal is to bring as much consistency as possible especially going forward, while reducing the maintenance burden caused by past branding inconsistencies.


These new guidelines match what already exists in a number of ways. If you are looking for a book on version 1.x, you’ll probably find it with the name AngularJS. And as more content is written consistently using these guidelines, it should become easier to search for what you are looking for.




What about Angular Material?
Angular Material is a project led by Google to build a great reusable component library for Angular Developers. The Material project takes Google’s design principles, and boils them down into components you can add your projects. We are continuing to invest in Material as a great choice for developers working with either Angular or AngularJS. To match the name guidelines, we’re clarifying the naming of the projects to “Angular Material” and “AngularJS Material”.


Brand Guidelines
For the full guidelines, check out our Press Kit.

We've been propagating these standards across all of our projects over the last week or so, but there's more work to be done. You can help by using these names to build consistency across the ecosystem! Here are some handy regular expressions if you'd like to help us fix the branding in your projects!
s/angular (1\.\d)/AngularJS $1/ig
s/angular 1\.x/AngularJS/ig
s/angular 1/AngularJS/ig
s/angular1/AngularJS/ig
s/angular 2\.0/Angular/ig
s/angular 2/Angular/ig
s/angular 2\.x/Angular/ig
s/angular2/Angular/ig

Share:

Thursday, 26 January 2017

Customize your Firebase Test Lab Robo tests

Doug Stevenson
Doug Stevenson
Developer Advocate

The Firebase Test Lab team is kicking off 2017 with some new features that make it easier for you to customize the testing of your Android apps. The following two enhancements are designed to save you time and money, so you can get the most out of Test Lab for your daily testing routine.
Sparse Device Matrix Selection

Previously, when selecting the combination of device and API levels, you were obliged to run against every possible valid combination of selected device and API level. For example, to run a test on a Nexus 5 and Nexus 7 on both API levels 19 and 21, the device selection matrix used to look like this: 

The above selection would have scheduled the test on a matrix with a total of four combinations of device and API level. But what if I want to test against only two configurations: a Nexus 5 with API level 21, and a Nexus 7 with API level 19? With the old UI, that was not possible. However, with the new UI, you can easily get this behavior:

The above selection will only schedule the two selected combinations of device and API level. You are no longer obliged to test on every possible combination of selected device and API. With this new UI, you can now be much more specific about the configurations you want. This makes it faster and less expensive to retry tests on only those configurations where your app previously encountered errors.
Saved Matrix Templates

If you use Test Lab frequently and are tired of entering the same device matrix information repeatedly, you can now save a matrix configuration as a template, and refer to that template when running a test. There is a new templates tab available on the Test Lab feature home screen:


Here, you can create and manage your device matrix templates. Then, when you go to run a test, you can select from a list of your templates to apply to the test:

Custom Text Input for Robo Test

If you're already using Firebase Test Lab for Android to run its automated Robo test, you've probably already gotten a lot of mileage out of its ability to intelligently crawl your app running on our devices. But for some of you, Robo wasn't a very useful option, because it was unable to bypass a custom login screen, or enter some specific text at the right place.


Now, you can configure a Robo test to use specific strings at key locations in your app. Here's an example of the Firebase console UI that specifies both a credential for a custom login form, and a search term to be used in a search box:
This UI is available as an "advanced option" when running a test.


This configuration is telling the Robo test to type the string "test_lab_user" into every EditText widget with the Android resource ID named "tv_username". It will do similarly for the tv_password and tv_search EditText widgets. This type of customization will make it easier for Robo log into your app and perform a search where those named widgets are observed. You can have text prepared for any EditText in your app that has a resource ID, as long as you're able to provide its name. However, this does not work for WebView elements.

Keep thinking about app quality!

The Firebase team wants your app to be successful, and a great way to make that happen is by using features provided by Firebase. So make 2017 a year of high quality for your app!


Share:

Thursday, 19 January 2017

Firebase Remote Config loading strategies

Todd Kerpleman
Todd Kerpelman
Developer Advocate
If you're a fan of our FirebaseDevelopers channel, you might have noticed that we just published a video all about how to best load up Remote Config values in your app:


But we know there are some people out there who would rather read than watch a video, so we thought we'd provide this for you in convenient blog form, too!

So if you've done any Remote Config work in the past, you probably noticed there are three main steps to implementing Remote Config in your app:
  1. You supply remote config with a bunch of default values. This is done locally on the device, either in code or by pulling in values from a local plist or xml file.
  2. You then call fetch() to download any new values from the cloud
  3. Finally, you call activateFetched() to apply these downloaded values on top of the default values you originally supplied.
At this point, when you query remote config for a particular value, you'll either get the updated value from the cloud, or whatever default you've supplied locally. And this is nice, because you can wire up your app to grab allof its values through Remote Config. You're still keeping your network calls nice and small, because you're only downloading the values that are different than your defaults, but you now have the flexibility to change any aspect of your app later through the cloud.

Seems pretty straightforward, right? And, for the most part, it is. The problem is that step 2 up there requires making a network call, and out in the real world, where people are using your app in tunnels, elevators, deserts, or places with poor network connections, you never really know how long it's going to take for that network call to complete. You can't guarantee that this process will be finished before your user starts interacting with your app.

So with that said, here are three strategies you can employ:

Strategy #1: Activate and refresh

This strategy is the most straightforward, which is generally why you'll see it in our sample apps and tutorials. The idea is that, once you've downloaded these new values from the cloud, you can call activateFetched() in your completion handler to immediately apply them, and then you tell your app to just go ahead update itself.


This strategy is nice in that it allows your user to get right into your app. But it's a little weird in that you potentially have your app changing things like button text, UI placement, or other critical values while your user is in the middle of using it, which can be a poor user experience. This is why many developers will opt to choose a solution like...

Strategy #2: Add a loading screen

A fairly common strategy is to display a loading screen when your user first starts up your app. Just like before, you'd call activateFetched in your completion handler to immediately apply these values, but instead of telling your app to refresh its interface, you would tell your app to dismiss the loading screen and transition to the main content. This is nice in that by the time your users make it past your loading screen and into your app, you're almost guaranteed to have fresh values from the cloud downloaded and ready to go.



Obviously, the big drawback here is that now you have a loading screen. This requires time and effort to build, and is also a barrier to your users getting into your app. But if your app already has a loading screen because you have to perform other work and/or network calls at startup, then this could be a good strategy. Just fetch your remote config values alongside whatever other startup work you're doing.

However, if your app doesn't already have a loading screen, I'd recommend trying an alternate strategy instead. Something like...

Strategy #3: Load values for next time

This one seems a little counter-intuitive, but hear me out: When your user starts up your app, you immediately call activateFetched(). This will apply any old values you've previously fetched from the cloud. And then your user can immediately start interacting with your app.
In the meantime, you kick off an asynchronous fetch() call to fetch new values from the cloud. And in the completion handler for this call… you do nothing. Heck, you don't even need add a completion handler in the first place. Those values you fetched from the cloud will remain stored locally on the device until your user calls activateFetched the next time they start your app.



This strategy is really nice in that your users can immediately start using their app, and there's no weird behavior where your app's interface suddenly changes out from under them. The obvious drawback is that it takes two sessions for your users to see your updated remote config values. You'll need to decide for yourself whether or not this is the right behavior for your app.
If you're using Remote Config to, say, fine-tune some values in your tower defense game, this is probably fine. If you're using it to deliver a message-of-the-day, or content specific to certain dates (like a holiday re-skin of your app) it might not be.

Strategy #3.5: Some hybrid of strategies 2 and 3. Or 1 and 3.

One nice thing about Remote Config is that it can tell you whenyour last successful fetch() call was performed. And so you can build some hybrid strategy where you first check how old your most recently fetched Remote Config data was. If it's fairly recent (say, in the last 48 hours or so), you can go ahead and run the "apply the latest batch of values and perform another fetch for next time" strategy. Otherwise, you can fall back to one of the earlier two strategies.



Let's talk about caching

As long as we're talking about loading strategies, let me hit on a related topic; caching. It sometimes confuses developers that values from remote config are cached for 12 hours instead of being grabbed immediately every time you call fetch(). And while you can reduce this cache time somewhat, if you start making network calls too frequently, your app might start getting throttled, either by the client, or the Remote Config service.

So, why do we have all of this caching and throttling behavior in the first place?

Well, partly it's a way to ensure we can keep this service free, even if your app scales to millions upon millions of users. By adding in some well-behaved caching, we can make sure that our service can handle your app for free, no matter how popular it gets.

It's also a nice way to protect the service from bad code. There are some developers out there (not you, of course) who might accidentally call fetch()too frequently. And we don't want the entire service getting slammed because one developer out there is accidentally DDoSing it. Having the client-side library serve up cached values and/or throttle frequent network calls helps keep the service safe.

But it's also good for your users. A good caching strategy prevents your app from using up your user's battery and/or data plan by making too many unnecessary network calls, which is always a good thing.

Obviously, while you're developing and testing your Remote Config implementation, this can be inconvenient, which is why you can override the local throttling behavior by turning on developer mode. But out in the real world, even if your users are using your app every single day, this kind of caching behavior is usually just fine.

But what if you want to push out values more frequently than that? What if you're trying to deliver a "Message of the hour" kind of feature through Remote Config? Well, frankly, this might be a sign that the Remote Config service isn't the ideal solution for you, and you should consider using the Realtime Database instead for something a little more timely.

On the other hand, there may be times when you want to infrequently apply an urgent Remote Config update. Perhaps you've accidentally broken your in-app economy with your latest batch of changes and you want everybody to get new values right away. How can you get around the cache and force your clients to perform a fetch?

One solution is to use Firebase Cloud Messaging. With FCM, you can send a data-only notification to all of your devices, letting them know that there's an urgent update pending. Your apps can respond to this incoming notification by storing some kind of flag locally. The next time your user starts up your app, it can look for this flag. If it's set to true, your app can perform a fetch with a cache time of 0 to ensure an immediate fetch. Just make sure you set this flag back when you're done, so your app can resume its usual caching behavior.

You might be tempted to have your clients respond to this incoming notification by immediately waking up and fetching new values from the Remote Config service, but if every instance of your app did that at once, there's a very good chance it will hit the server-side throttle, so I don't recommend this. Stick with the above strategy instead; that will spread out the network calls across the time period it takes for all of your users to open up your app.

So there ya go, folks! A few tips and tricks for loading up your values from Remote Config. Got any tips of your own? Feel free to share them in the comments on our YouTube video, or head on over to the Firebase Talk group and let us know how you're coming along with your Remote Config implementation.

Yes, that was kind of a pun. Cache hits; get it?

Share:

Wednesday, 18 January 2017

Welcoming Fabric to Google

Francis Ma
Francis Ma
Firebase Product Manager
Almost eight months ago, we launchedthe expansion of Firebase to help developers build high-quality apps, grow their user base, and earn more money across iOS, Android and the Web. We've already seen great adoption of the platform, which brings together the best of Google's core businesses from Cloud to mobile advertising.

Our ultimate goal with Firebase is to free developers from so much of the complexity associated with modern software development, giving them back more time and energy to focus on innovation.

As we work towards that goal, we've continued to improve Firebase, working closely with our user community. We recently introducedmajor enhancements to many core features, including Firebase Analytics, Test Lab and Cloud Messaging, as well as added support for game developers with a C++ SDK and Unity plug-in.


We're deeply committed to Firebase and are doubling down on our investment to solve developer challenges.
Fabric and Firebase Joining Forces

Today, we're excited to announce that we've signed an agreement to acquire Fabric to continue the great work that Twitter put into the platform. Fabric will join Google's Developer Product Group, working with the Firebase team. Our missions align closely: help developers build better apps and grow their business.


As a popular, trusted tool over many years, we expect that Crashlytics will become the main crash reporting offering for Firebase and will augment the work that we have already done in this area. While Fabric was built on the foundation of Crashlytics, the Fabric team leveraged its success to launch a broad set of important tools, including Answers and Fastlane. We'll share further details in the coming weeks after we close the deal, as we work closely together with the Fabric team to determine the most efficient ways to further combine our strengths. During the transition period, Digits, the SMS authentication services, will be maintained by Twitter.


The integration of Fabric is part of our larger, long-term effort of delivering a comprehensive suite of features for iOS, Android and mobile Web app development.

This is a great moment for the industry and a unique opportunity to bring the best of Firebase with the best of Fabric. We're committed to making mobile app development seamless, so that developers can focus more of their time on building creative experiences.
Share:

Tuesday, 17 January 2017

Ionic 2 Mobile App using Angular 2 and TypeScript Tutorial

Ionic is an open-source front-end SDK framework made for building hybrid mobile apps on cross platforms. Ionic is used for developing hybrid mobile apps using web technologies like HTML 5, CSS, Cordova and Sass, it is made of AngularJS 2. Both ionic and AngularJS provides some pre- built in components, which allows us to easily develop mobile apps. Here is the demo for creating mobile app using AngularJS and typescript on ionic V2 framework. The demo used here is my 9lessons.info blog as a mobile app. Follow this tutorial to easily build mobile app.

Ionic Angular 2 typscript tutorial

Read more »
Share:

Friday, 13 January 2017

Understanding AOT and Dynamic Components

This is a guest post from Sean Landsman at ag-Grid. Sean is the lead engineer on ag-Grid's Angular integration. -- Stephen Fluin


Motivation

ag-Grid is an enterprise datagrid that works with Angular. As ag-Grid works with many frameworks, the internals of the grid had to allow for Angular rendering inside the grid despite ag-Grid not being written in Angular itself. This was done using Angular Dynamic Components and we managed to do it while still supporting AOT. This blog details what we learnt along the way.

The Setup

To explain we present a simple sample application that isolates what we are trying to do. In our example below we are going to develop two main Modules - one will be a Library (in our case this was ag-Grid) that will display an array of dynamically created Components (similar to how ag-Grid displays Angular components inside the grid's cells), and the other will be our actual Application.
The end result will be look like this:




You can find all the code for this example over at GitHub, and the live example over at GitHub.io
One further note - when we return to "user" below, we are referring to a user (or client) of the Library we're writing.

The Library

Our Library is going to be a simple one - all it does is display an array of dynamically created Angular Components. The main component looks like this:

@Component({
selector: 'grid-component',
template: `
<div class="row" *ngFor="let cellComponentType of cellComponentTypes">
<div class="col-lg-12">
<grid-cell [componentType]="cellComponentType"></grid-cell>
</div>
</div>
`
})
export class Grid {
@Input() componentTypes: any;

cellComponentTypes: any[] = [];

addDynamicCellComponent(selectedComponentType:any) {
this.cellComponentTypes.push(selectedComponentType);
}
}

As you can see it's a pretty simple component - all it does is display the current cellComponentTypes. These are the user supplied components, and they can be any Angular Component.

The interesting part of the Library is in the Cell Component:

@Component({
selector: 'grid-cell',
template: ''
})
export class Cell implements OnInit {
@Input() componentType: any;

constructor(private viewContainerRef: ViewContainerRef,
private cfr: ComponentFactoryResolver) {
}

ngOnInit() {
let compFactory = this.cfr.resolveComponentFactory(this.componentType);
this.viewContainerRef.createComponent(compFactory);
}
}
You'll notice that we don't have a template here - that's deliberate as the Cell doesn't have any     content of its own - all it does is serve up the user supplied Component. The important part of this Component are     these two lines:

let compFactory = this.cfr.resolveComponentFactory(this.componentType);
This line asks the ComponentFactoryResolver to find the ComponentFactory for the provided     Component. We'll use this factory next to create the actual component:

this.viewContainerRef.createComponent(compFactory);
And that's all there is to it from the Library Component side of things - we find the factory for the Component, and     then create a new instance of the Component. Easy!

For this to work we need to tell Angular's AOT Compiler to create factories for the user provided Components, or ComponentFactoryResolver won't find them. We can make use of NgModule.entryComponents for this - this will ensure that the AOT compiler creates the necessary factories, but for you purposes there is an easier way, especially from a users perspective:

@NgModule({
imports: [
BrowserModule,
FormsModule
],
declarations: [
Grid,
Cell
],
exports: [
Grid
]
})
export class GridModule {
static withComponents(components: any[]) {
return {
ngModule: GridModule,
providers: [
{provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: components, multi: true}
]
}
}
}
By making use of ANALYZE_FOR_ENTRY_COMPONENTS here, we are able to add multiple components to the NgModule.entryComponents    entry dynamically, in a user friendly way.

The Application

From the application side of things, the first thing we need to do is create the components we want to use in the Library - these can be any valid Angular Component. In our case we have three similar Components:

@Component({
selector: 'dynamic-component',
template: '<div class="img-rounded" style="background-color: lightskyblue;margin: 5px"> Blue Dynamic Component! </div>',
})
export class BlueDynamicComponent {
}
All these components do is display a little styled text.
To register these in both our Application, and in the Library, we need to switch to the Application Module:

@NgModule({
imports: [
BrowserModule,
FormsModule,
GridModule.withComponents([
BlueDynamicComponent,
GreenDynamicComponent,
RedDynamicComponent
])
],
declarations: [
AppComponent,
BlueDynamicComponent,
GreenDynamicComponent,
RedDynamicComponent
],
bootstrap: [AppComponent]
})
export class AppModule {
}
We declare our Components in the usual way, but we additionally need to register them with the Library (remember,     this is the part where they'll be added to the     Library's NgModule.entryComponent entry). We do this in this part of the module:

GridModule.withComponents([
BlueDynamicComponent,
GreenDynamicComponent,
RedDynamicComponent
])
Finally, we can take a look at the main Application Component:

@Component({
selector: 'my-app',
template: `
<div class="container-fluid">
<div class="page-header">
<h1>Creating AOT Friendly Dynamic Components with Angular
</div>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">Application Code</div>
<div class="panel-body">
<div class="input-group">
<span class="input-group-btn">
<button type="button" class="btn btn-primary" (click)="grid.addDynamicCellComponent(selectedComponentType)">Add Dynamic Grid component
</span>

<select class="form-control" [(ngModel)]="selectedComponentType">
<option *ngFor="let cellComponentType of componentTypes" [ngValue]="cellComponentType">{{cellComponentType.name}}
</select>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">Library Code</div>
<div class="panel-body">
<grid-component #grid></grid-component>
</div>
</div>
</div>
</div>
</div>
`
})
export class AppComponent implements OnInit {
@Input() componentTypes: any[] = [BlueDynamicComponent, GreenDynamicComponent, RedDynamicComponent];
@Input() selectedComponentType: any;

ngOnInit(): void {
// default to the first available option
this.selectedComponentType = this.componentTypes ? this.componentTypes[0] : null;
}
}

It may look like theres a lot going on here, but the bulk of the template is to make it look pretty. The key parts of this Component are:

<button type="button" class="btn btn-primary" (click)="grid.addDynamicCellComponent(selectedComponentType)">Add Dynamic Grid component

This will ask the Library to add a create a new instance of the supplied Component, and in turn render it.

<grid-component #grid></grid-component>
And this line is our Library Component.

That's it - easy to write and use (from both an Application and Library perspective), and AOT (and JIT!) friendly.

Benefits of using AOT

The speed and size of the resulting application when using AOT can be significant. In our ag-grid-ng2-example project, we estimate the size of the resulting application went from 3.9Mb down to 2.4Mb - a reduction of just under 40%, without optimising for size or being particularly aggressive with rollup.

Speed-wise, the loading time when using AOT is significantly more responsive on startup - this makes sense given that Angular doesn't have to compile all the code once again. Take a look at the examples project and try both the JIT and AOT versions out for yourself!

There's so much more you can do if you decide to combine Angular Components with ag-Grid - powerful functionality, fast grid and easy configuration. What are you waiting for?!
Share:

Wednesday, 4 January 2017

Some Tips for Boosting your App's Quality in 2017



Doug Stevenson
Doug Stevenson
Developer Advocate

I've got to come clean with everyone: I'm making no new year's resolutions for 2017. Nor did I make any in 2016. In fact, I don't think I've ever made one! It's not so much that I take a dim view of new year's resolutions. I simply suspect that I would likely break them by the end of the week, and feel bad about it!

One thing I've found helpful in the past is to see the new year as a pivoting point to try new things, and also improve the work I'm already doing. For me (and I hope for you too!), 2017 will be a fresh year for boosting app quality.

The phrase "app quality" can take a bunch of different meanings, based on what you value in the software you create and use. As a developer, traditionally, this means fixing bugs that cause problems for your users. It could also be a reflection of the amount of delight your users take in your app. All of this gets wrapped up into the one primary metric that we have to gauge the quality of a mobile app, which is your app's rating on the store where it's published. I'm sure every one of you who has an app on a storefront has paid much attention to the app's rating at some point!

Firebase provides some tools you can use to boost your app's quality, and if you're not already using them, maybe a fresh look at those tools would be helpful this year?

Firebase Crash Reporting

The easiest tool to get started with is Firebase Crash Reporting. It takes little to no lines of code to integrate it into your iOS and Android app, and once you do, the Firebase console will start showing crashes that are happening to your users. This gives you a "hit list" of problems to fix.
One thing I find ironic about being involved with the Crash Reporting team is how we view the influx of total crashes received as we monitor our system. Like any good developer product, we strive to grow adoption, which means we celebrate graphs that go "up and to the right". So, in a strange sense, we like to see more crashes, because that means more developers are using our stuff! But for all of you developers out there, more crashes is obviously a *bad* thing, and you want to make those numbers go down! So, please, don't be like us - make your crash report graphs go down and to the right in 2017!

Firebase Test Lab for Android

Even better than fixing problems for your users is fixing those problems before they even reach your users. For your Android apps, you can use Firebase Test Lab to help ensure that your apps work great for your users among a growing variety of actual devices that we manage. Traditionally, it's been kind of a pain to acquire and manage a good selection of devices for testing. However, with Test Lab, you simply upload your APK and tests, and it will install and run them to our devices. After the tests complete, we'll provide all the screenshots, videos, and logs of everything that happened for you to examine in the Firebase console.

With Firebase Test Lab for Android now available with generous daily quotas at no charge for projects on the free Spark tier, 2017 is a great time to get started with that. And, if you haven't set up your Android app builds in a continuous integration environment, you could set that up, then configure it to run your tests automatically on Test Lab.

If you're the kind of person who likes writing tests for your code (which is, admittedly, not very many of us!), it's natural to get those tests running on Test Lab. But, for those of us who aren't maintaining a test suite with our codebase, we can still use Test Lab's automated Robo test to get automated test coverage right away, with no additional lines of code required. That's not quite that same as having a comprehensive suite of tests, so maybe 2017 would be a good time to learn more about architecting "testable" apps, and how those practices can raise the bar of quality for your app. I'm planning on writing more about this later this year, so stay tuned to the Firebase Blog for more!

Firebase Remote Config

At its core, Firebase Remote Config is a tool that lets you configure your app using parameters that you set up in the Firebase console. It can be used to help manage the quality of your app, and there's a couple neat tricks you can do with it. Maybe this new year brings new opportunities to give them a try!

First of all, you can use Remote Config to carefully roll out a new feature to your users. It works like this:
  1. Code your new feature and restrict its access to the user by a Remote Config boolean parameter. If the value is 'false', your users don't see the feature. Make 'false' the default value in the app.
  2. Configure that parameter in the Firebase console to also be initially 'false' for everyone.
  3. Publish your app to the store.
  4. When it's time to start rolling out the new feature to a small segment of users, configure the parameter to be 'true' for, say, five percent of your user base.
  5. Stay alert for new crashes in Firebase Crash Reporting, as well as feedback from your users.
  6. If there is a problem with the new feature, immediately roll back the new feature by setting the parameter to 'false' in the console for everyone.
  7. Or, if things are looking good, increase the percentage over time until you reach 100% of your users.




This is much safer than publishing your new feature to everyone with a single app update, because now you have the option to immediately disable a serious problem, and without having to build and publish a whole new version of your app. And, if you can act quickly, most of your users will never encounter the problem to begin with. This works well with the email alerts you get from Firebase Crash Reporting when a new crash is observed.

Another feature of Remote Config is the ability to experiment with some aspect of your app in order to find out what works better for the users of your app, then measure the results in Firebase Analytics. I don't know about you, but I'm typically pretty bad at guessing what people actually prefer, and sometimes I'm surprised at how people might actually *use* an app! Don't guess - instead, do an experiment and know /for certain/ what delights your users more! It stands to reason that apps finely tuned like this can get better ratings and make more money.

Firebase Realtime Database

It makes sense that if you make it easier for you user to perform tasks in your app, they will enjoy using it more, and they will come back more frequently. One thing I have always disliked is having to check for new information by refreshing, or navigating back and forward again. Apps that are always fresh and up to date, without requiring me to take action, are more pleasant to use.

You can achieve this for your app by making effective use of Firebase Realtime Databaseto deliver relevant data directly to your users at the moment it changes in the database. Realtime Database is reactive by nature, because the client API is designed for you set up listeners at data locations that get triggered in the event of a change. This is far more convenient than having to poll an API endpoint repeatedly to check for changes, and also much more respectful of the user's mobile data and battery life. Users associate this feeling of delight with apps of high quality.

What does 2017 have in store for your app?

I hope you'll join me this year in putting more effort into making our users even more delighted. If you're with me, feel free to tweet me at @CodingDoug and tell me what you're up to in 2017!
Share: