Tag Archives: Android Developer

Making Pixel better for Drivers

Posted by Marc Stogaitis and Tajinder Gadh, Software Engineers

Driving is an essential part of our daily activities. So at Google we spend a lot of time thinking how we can make Android devices better and safer for our users. How we can prevent distracted driving and together build an open ecosystem to enable safety first smartphone experiences.

Recently we launched Driving Do-Not-Disturb on the newly announced Pixel 2 generation of devices. Once enabled, Driving Do-Not-Disturb automatically puts your device into a do not disturb mode while driving. During this mode any incoming messages and notifications are silenced while you can still receive incoming calls, navigation directions and voice interactions using a connected Car bluetooth. The product is designed to limit distractions during driving while at the same time not getting in the way so users can continue to use navigation or other similar apps with minimal friction.

Behind the scenes, it uses AI powered on-device Activity Recognition that detects when a person is driving using low power signals from multiple sensors, bluetooth and WiFi. Activity Recognition uses the Android Sensor Hub to ensure low latency, low power and accurate driving detection.

This is a next step in our journey, but we are far from done. Early next year we are introducing the Activity Recognition Transition Api, which is the same Api used by Driving Do Not Disturb to build distraction-free driving experiences.

We appreciate the feedback, and will continue to listen to your feedback as the product evolves.

If you have questions about setting up the Driving Do-Not-Disturb, check out our Help Center.

Announcing Architecture Components 1.0 Stable

Posted by Lukas Bergstrom, Product Manager, Android Developer Frameworks Team

Android runs on billions of devices, from high-end phones to airplane seatbacks. The Android OS manages resources aggressively to perform well on this huge range of devices, and sometimes that can make building robust apps complicated. To make it easier, we launched a preview of Architecture Components at Google I/O to provide guidance on app architecture, with libraries for common tasks like lifecycle management and data persistence. Together, these foundational components make it possible to write modular apps with less boilerplate code, so developers can focus on innovating instead of reinventing the wheel - and we hope to keep building on this foundation in the future.

Today we're happy to announce that the Room and Lifecycle Architecture Components libraries have reached 1.0 stable. These APIs are ready for production apps and libraries, and are our recommendation for developers looking for help with app architecture and local storage (although they're only recommended, not required.) Lifecycles are now also integrated with the Support Library, so you can use them with standard classes like AppCompatActivity.

Although we're declaring them stable today, the beta components are already used in apps that together, have billions of installs. Top developers, like Zappos, have been able to spend more time on what's important thanks to Architecture Components:

Prior to the release of Android Architecture Components we had our own ViewModel implementation. We used Loaders and Dependency Injection to persist our ViewModel through config changes. We recently switched to the Architecture Components ViewModel implementation and all that boilerplate went away. We found that we were able to spend more time on design, business logic and testing, and less on writing boilerplate or worrying about Android lifecycle issues.

We've also started to use LiveData which hooks directly into the Activity lifecycle. We use it to retrieve and display network data and no longer have to concern ourselves with ​network call subscription management. - David Henry, Android Software Engineer, Zappos

Architecture Components provide a simple, flexible and practical approach that frees developers from some common problems so they can focus on building great experiences. This is based on core building blocks tied together by guidance on app architecture.

Lifecycles

Every Android developer has to deal with the operating system starting, stopping and destroying their Activities. That means managing the state of components - such as observables used to update UI - as you move through the lifecycle. Lifecycles enables the creation of lifecycle-aware components that manage their own lifecycles, reducing the possibility of leaks or crashes. The Lifecycle library is the foundation for other Architecture Components like LiveData.

LiveData

LiveData is a lifecycle-aware observable that holds data and provides updates. Your UI code subscribes to changes and provides LiveData a reference to its Lifecycle. Because LiveData is lifecycle-aware, it provides updates when its Lifecycle is started or resumed, but stops providing updates when the LifecycleOwner is destroyed. LiveData is a simple way to build reactive UIs that are safer and more performant.

ViewModel

ViewModel separates ownership of view data and logic from lifecycle-bound entities like Activities and Fragments. A ViewModel is retained until its associated Activity or Fragment is disposed of forever - that means view data survives events like a Fragment being recreated due to rotation. ViewModels not only eliminate common lifecycle issues, they help build UIs that are more modular and easier to test.

Room

Nearly all apps need to store data locally. While Android has bundled SQLite with the platform since version 1, using it directly can be painful. Room is a simple object-mapping layer that provides the full power of SQlite with less boilerplate. Features like compile-time query verification and built-in migration make it easier to build a robust persistence layer, while integration with LiveData lets Room provide database-backed, lifecycle-aware observables. Room blends of simplicity, power and robustness for managing local storage, and we hope you give it a try.

Guide to App Architecture and more

Last but not least, we created a Guide to App Architecture that provides core principles applicable to all developers, and specific guidance on using Architecture Components together. Because we've heard from you that clear and consistent guidance is important, today we're updating developer documentation to point to Architecture Components where appropriate. We also have a rich set of videos, codelabs and sample apps available at the Architecture Components site, with more to come.

Watch this space

Although the first set of Architecture Components is now stable, we know there's more work to do. Over the last few months, we've listened to your feedback and made improvements. We also recently launched a new Architecture Component, PagedList, to alpha, in response to your feedback that handling large datasets with RecyclerView is too difficult. This is just the beginning - we have more major components under development that we're looking to announce in the upcoming months.

Our hope with Architecture Components is to free developers to focus on providing unique new experiences for mobile devices. We're glad we can finally announce them as stable for production use. We'd like to thank the community, which has given such great feedback along the way, and we look forward to continuing the discussion in the comments of this post. Finally, for those of you who've been waiting for this stable launch, get started today.

Update on Kotlin for Android

Posted by James Lau, Product Manager (twitter.com/jmslau)

Today is the beginning of KotlinConf. It's been almost 6 months since we announced Kotlin as a first-class language for Android at Google I/O. During this period, the number of apps on Google Play using Kotlin has more than doubled. More than 17% of the projects in Android Studio 3.0 are now using Kotlin. We are really excited about the strong momentum, and we are thrilled that Android developers all over the world are discovering the joy of Kotlin programming.

Kotlin for Android is production-ready. From startups to Fortune 500 companies, developers are already using Kotlin to build their apps. Developers from Pinterest, to Expedia, to Basecamp -- and many others -- are finding their use of Kotlin is increasing productivity and their overall developer happiness levels. Take a look at some of their experiences with Kotlin below.

With the recent release of Android Studio 3.0, there is now a stable version of our IDE that has Kotlin support built-in. With Support Library 27, we have started adding nullability annotations to make the APIs friendlier to use in Kotlin. We recently published the Android Kotlin Guides on GitHub to provide some guidance for Android Kotlin style and interop. We have also been porting some of our Android samples to Kotlin, and we are adding Kotlin to our official documentation.

Android Studio 3.0

Last week, we released Android Studio 3.0 on the stable channel. This is the first stable release of Android Studio that has Kotlin support built-in. Building on the strength of IntelliJ's Kotlin support, many critical IDE features like code completion and syntax highlighting work well for Kotlin. You can choose to convert Java code to Kotlin by using CodeConvert Java File to Kotlin File, or you can convert snippets of code just by pasting Java code into a Kotlin file.

Project and code templates have also been updated with Kotlin support. When you create a new project or add a new code file, you can choose Kotlin as one of the language options.

The tooling experience with Kotlin is by no means perfect yet. We are aware of several known issues, and we will continue to improve the IDE support for Kotlin in future releases.

Android Kotlin Guides

There are two separate Android Kotlin Guides:

  1. Style guide - details a set of rules and coding standards that Google recommends when writing Kotlin for Android. The guide addresses naming conventions, formatting, structure of the source contents, and much more.
  2. Interop guide - provides a set of rules for creating APIs in the Java and Kotlin programming languages, so that the consuming code in the other language will feel idiomatic.

We intend these guides to be living documents and will evolve them over time. They are hosted on GitHub and we welcome your contributions.

Nullability Annotations

Null-safety is an important feature of the Kotlin language. It helps developers avoid NullPointerExceptions and improves the quality of their apps. Null-safety is a bit more complicated when using Java code from Kotlin. Since any reference in Java may be null, Kotlin's requirement for strict null-safety becomes impractical for Java objects. Types declared in Java that do not contain nullability annotations are called platform types - this means the Kotlin compiler does not know whether it is nullable or not. When calling methods with variables of platform types, the Kotlin compiler relaxes null-safety checks. That means the overall null-safety of your app is weakened.

To let developers take more advantage of Kotlin's strict null-safety, we have started adding nullability annotations in Support Library 27. The Support Library contains a huge API surface area, and we will continue to expand the nullability annotation coverage in the next several releases. In addition, we will also be adding nullability annotations to other Android APIs over time.

While the Kotlin adoption growth is fantastic, our commitment to the Java and C++ programming languages remains unchanged. We've added Java 8 language features support in Android Studio 3.0, and we've added more Java 8 language APIs in Android Oreo. We are also continuing to improve our support for C++17 in the NDK. So even if you are not using Kotlin, your language support will continue to improve.

It's an exciting time to be an Android developer. If you haven't had a chance to try Kotlin, you can get started by learning the basic syntax and by playing with the excellent Kotlin Koans. When you are ready to use Kotlin in your Android app, you can jump to the Android Kotlin page for more resources. With Kotlin's Java interoperability and Android Studio's Java to Kotlin converter, it's easy to start using Kotlin in your project.

Happy Kotlin-ing!

Working with Multiple JobServices

Posted by Isai Damier, Software Engineer, Android DA

Working with Multiple JobServices

In its continuous effort to improve user experience, the Android platform has introduced strict limitations on background services starting in API level 26. Basically, unless your app is running in the foreground, the system will stop all of your app's background services within minutes.

As a result of these restrictions on background services, JobScheduler jobs have become the de facto solution for performing background tasks. For people familiar with services, JobScheduler is generally straightforward to use: except in a few cases, one of which we shall explore presently.

Imagine you are building an Android TV app. Since channels are very important to TV Apps, your app should be able to perform at least five different background operations on channels: publish a channel, add programs to a channel, send logs about a channel to your remote server, update a channel's metadata, and delete a channel. Prior to Android 8.0 (Oreo) each of these five operations could be implemented within background services. Starting in API 26, however, you must be judicious in deciding which should be plain old background Services and which should be JobServices.

In the case of a TV app, of the five operations mentioned above, only channel publication can be a plain old background service. For some context, channel publication involves three steps: first the user clicks on a button to start the process; second the app starts a background operation to create and submit the publication; and third, the user gets a UI to confirm subscription. So as you can see, publishing channels requires user interactions and therefore a visible Activity. Hence, ChannelPublisherService could be an IntentService that handles the background portion. The reason you should not use a JobService here is because JobService will introduce a delay in execution, whereas user interaction usually requires immediate response from your app.

For the other four operations, however, you should use JobServices; that's because all of them may execute while your app is in the background. So respectively, you should have ChannelProgramsJobService, ChannelLoggerJobService, ChannelMetadataJobService, and ChannelDeletionJobService.

Avoiding JobId Collisions

Since all the four JobServices above deal with Channel objects, it should be convenient to use the channelId as the jobId for each one of them. But because of the way JobServices are designed in the Android Framework, you can't. The following is the official description of jobId

Application-provided id for this job. Subsequent calls to cancel, 
or jobs created with the same jobId, will update the pre-existing 
job with the same id. This ID must be unique across all clients 
of the same uid (not just the same package). You will want to 
make sure this is a stable id across app updates, so probably not 
based on a resource ID.

What the description is telling you is that even though you are using 4 different Java objects (i.e. -JobServices), you still cannot use the same channelId as their jobIds. You don't get credit for class-level namespace.

This indeed is a real problem. You need a stable and scalable way to relate a channelId to its set of jobIds. The last thing you want is to have different channels overwriting each other's operations because of jobId collisions. Were jobId of type String instead of Integer, the solution would be easy: jobId= "ChannelPrograms" + channelId for ChannelProgramsJobService, jobId= "ChannelLogs" + channelId for ChannelLoggerJobService, etc. But since jobId is an Integer and not a String, you have to devise a clever system for generating reusable jobIds for your jobs. And for that, you can use something like the following JobIdManager.

JobIdManager is a class that you tweak according to your app's needs. For this present TV app, the basic idea is to use a single channelId over all jobs dealing with Channels. To expedite clarification: let's first look at the code for this sample JobIdManager class, and then we'll discuss.

public class JobIdManager {

   public static final int JOB_TYPE_CHANNEL_PROGRAMS = 1;
   public static final int JOB_TYPE_CHANNEL_METADATA = 2;
   public static final int JOB_TYPE_CHANNEL_DELETION = 3;
   public static final int JOB_TYPE_CHANNEL_LOGGER = 4;

   public static final int JOB_TYPE_USER_PREFS = 11;
   public static final int JOB_TYPE_USER_BEHAVIOR = 21;

   @IntDef(value = {
           JOB_TYPE_CHANNEL_PROGRAMS,
           JOB_TYPE_CHANNEL_METADATA,
           JOB_TYPE_CHANNEL_DELETION,
           JOB_TYPE_CHANNEL_LOGGER,
           JOB_TYPE_USER_PREFS,
           JOB_TYPE_USER_BEHAVIOR
   })
   @Retention(RetentionPolicy.SOURCE)
   public @interface JobType {
   }

   //16-1 for short. Adjust per your needs
   private static final int JOB_TYPE_SHIFTS = 15;

   public static int getJobId(@JobType int jobType, int objectId) {
       if ( 0 < objectId && objectId < (1<< JOB_TYPE_SHIFTS) ) {
           return (jobType << JOB_TYPE_SHIFTS) + objectId;
       } else {
           String err = String.format("objectId %s must be between %s and %s",
                   objectId,0,(1<<JOB_TYPE_SHIFTS));
           throw new IllegalArgumentException(err);
       }
   }
}

As you can see, JobIdManager simply combines a prefix with a channelId to get a jobId. This elegant simplicity, however, is just the tip of the iceberg. Let's consider the assumptions and caveats beneath.

First insight: you must be able to coerce channelId into a Short, so that when you combine channelId with a prefix you still end up with a valid Java Integer. Now of course, strictly speaking, it does not have to be a Short. As long as your prefix and channelId combine into a non-overflowing Integer, it will work. But margin is essential to sound engineering. So unless you truly have no choice, go with a Short coercion. One way you can do this in practice, for objects with large IDs on your remote server, is to define a key in your local database or content provider and use that key to generate your jobIds.

Second insight: your entire app ought to have only one JobIdManager class. That class should generate jobIds for all your app's jobs: whether those jobs have to do with Channels, Users, or Cats and Dogs. The sample JobIdManager class points this out: not all JOB_TYPEs have to do with Channel operations. One job type has to do with user prefs and one with user behavior. The JobIdManager accounts for them all by assigning a different prefix to each job type.

Third insight: for each -JobService in your app, you must have a unique and final JOB_TYPE_ prefix. Again, this must be an exhaustive one-to-one relationship.

Using JobIdManager

The following code snippet from ChannelProgramsJobService demonstrates how to use a JobIdManager in your project. Whenever you need to schedule a new job, you generate the jobId using JobIdManager.getJobId(...).

import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.os.PersistableBundle;

public class ChannelProgramsJobService extends JobService {
  
   private static final String CHANNEL_ID = "channelId";
   . . .

   public static void schedulePeriodicJob(Context context,
                                      final int channelId,
                                      String channelName,
                                      long intervalMillis,
                                      long flexMillis)
{
   JobInfo.Builder builder = scheduleJob(context, channelId);
   builder.setPeriodic(intervalMillis, flexMillis);

   JobScheduler scheduler = 
            (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
   if (JobScheduler.RESULT_SUCCESS != scheduler.schedule(builder.build())) {
       //todo what? log to server as analytics maybe?
       Log.d(TAG, "could not schedule program updates for channel " + channelName);
   }
}

private static JobInfo.Builder scheduleJob(Context context,final int channelId){
   ComponentName componentName =
           new ComponentName(context, ChannelProgramsJobService.class);
   final int jobId = JobIdManager
             .getJobId(JobIdManager.JOB_TYPE_CHANNEL_PROGRAMS, channelId);
   PersistableBundle bundle = new PersistableBundle();
   bundle.putInt(CHANNEL_ID, channelId);
   JobInfo.Builder builder = new JobInfo.Builder(jobId, componentName);
   builder.setPersisted(true);
   builder.setExtras(bundle);
   builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
   return builder;
}

   ...
}

Footnote: Thanks to Christopher Tate and Trevor Johns for their invaluable feedback

Next-generation Dex Compiler Now in Preview

Posted by James Lau, Product Manager

Android developers know that dex compilation is a key step in building an APK. This is the process of transforming .class bytecode into .dex bytecode for the Android Runtime (or Dalvik, for older versions of Android). The dex compiler mostly works under the hood in your day-to-day app development, but it directly impacts your app's build time, .dex file size, and runtime performance.

That's why we are investing in making important improvements in the dex compiler. We're excited to announce that the next-generation dex compiler, D8, is now available for preview as part of Android Studio 3.0 Beta release.

When comparing with the current DX compiler, D8 compiles faster and outputs smaller .dex files, while having the same or better app runtime performance.

* Tested with benchmark project here.
*Tested with benchmark project here.

How to try it?

D8 is available for your preview starting with Android Studio 3.0 Beta. To try it, set the following in your project's gradle.properties file:

android.enableD8=true

We have tested D8's correctness and performance on a number of apps, and the results are encouraging. We're confident enough with the results that we are switching to use D8 as the default dex compiler for building AOSP. There are currently no known issues, but we would love to hear your feedback. You can file a bug report using this link.

What's next?

We plan to preview D8 over the next several months with the Android Studio 3.0 release. During this time, we will focus on addressing any critical bug reports we receive from the community. We plan to bring D8 out of preview and enable it as the default dex compiler in Android Studio 3.1. At that time, the DX compiler will officially be put in maintenance mode. Only critical issues with DX will be fixed moving forward.

Beyond D8, we are also working on R8, which is a Proguard replacement for whole program minification and optimization. While the R8 project has already been open sourced, it has not yet been integrated with the Android Gradle plugin. We will provide more details about R8 in the near future when we are ready to preview it with the community.

Tool developers: get your bytecode tools Java 8 ready

In April, we announced Java 8 language features with desugaring. The desugaring step currently happens immediately after Java compilation (javac) and before any bytecode reading or rewriting tools are run. Over the next couple of months, the desugar step will move to a later stage in the pipeline, as part of D8. This will allow us to further reduce the overall build time and produce more optimized code. This change means that any bytecode reading or rewriting tools will run before the desugar step. If you develop .class bytecode reading or rewriting tools for Android, you will need to make sure they can handle the Java 8 bytecode format so they can continue to work properly when we move desugaring into D8.

Happy dex'ing!

Semantic Time support now available on the Awareness APIs

Posted by Ritesh Nayak M, Product Manager

Last year at I/O we launched the Awareness API, a simple yet powerful API that let developers use signals such as Location, Weather, Time and User Activity to build contextually relevant app experiences.

Available via Google Play services, the Awareness API offers two ways to take advantage of context signals within your app. The Snapshot API lets your app request information about the user's current context, while the Fence API lets your app react to changes in user's context, and when it matches a certain set of conditions. For example, "tell me whenever the user is walking and their headphone is plugged in".

Until now, you could specify a time fence on the Awareness APIs but were restricted to using absolute/canonical representation of time. Based on developer feedback, we realized that the flexibility of the API in regards to building time fences did not support higher level abstractions people use when they think and talk about time. "This weekend", "on the next holiday", "after sunset", are all very common and colloquial ways of expressing time. That's why we're adding Semantic time support to these APIs starting today

For e.g., if you were building a fitness app and wanted a way to prompt users everyday morning to start their routine, or if you're a reading app that wants to turn on night mode after dusk; you would have to query a 3p API for sunrise/sunset information at the user location and then write up an Awareness fence with those canonical time values. With our latest update, you can use our TIME_INSTANT_SUNRISE and TIME_INSTANT_SUNSET constants and let the platform manage all the complexity for you.

Let's look at an example. Suppose you're building a fitness app which prompts users on Tuesday, and Thursday around sunrise to begin their morning work out. You can set up this triggering using the following lines of code.

// A sun-state-based fence that is TRUE only on Tuesday and Thursday during Sunrise 
AwarenessFence.and(
    TimeFence.aroundTimeInstant(TimeFence.TIME_INSTANT_SUNRISE,
            -10 * ONE_MINUTE_MILLIS, 5 * ONE_MINUTE_MILLIS),
    AwarenessFence.or(
        TimeFence.inIntervalOfDay(TimeFence.DAY_OF_WEEK_TUESDAY,
                0, ONE_DAY_MILLIS),
        TimeFence.inIntervalOfDay(TimeFence.DAY_OF_WEEK_THURSDAY,
                0, ONE_DAY_MILLIS)));

One of our favorite semantic time features is public holidays. Every country and regions within it have different holidays. Assume you were a local hiking & adventure app that wants to show users activities they can indulge in on a holiday that falls on a Friday or a Monday. You can use a combination of Days and Holiday flags to identify this state for all your users around the world. You can do this with just 3 lines of code and have this work in any part of the world.

// A local-time fence that is TRUE only on public holidays in the
// device locale that fall on Fridays or Mondays.
AwarenessFence.and(
    TimeFence.inTimeInterval(TimeFence.TIME_INTERVAL_HOLIDAY),
    AwarenessFence.or(
        TimeFence.inIntervalOfDay(TimeFence.DAY_OF_WEEK_FRIDAY,
                9 * ONE_HOUR_MILLIS, 11 * ONE_HOUR_MILLIS),
        TimeFence.inIntervalOfDay(TimeFence.DAY_OF_WEEK_MONDAY,
                9 * ONE_HOUR_MILLIS, 11 * ONE_HOUR_MILLIS)));

In both example cases, Awareness does the heavy lifting of localizing time and holidays based on the device locale settings.

We're excited to see what problems you'll solve using this powerful API. Please join our mailing list to get updates about this and other Context APIs at Google.

Java 8 Language Features Support Update

Posted by James Lau, Product Manager

Yesterday, we released Android Studio 2.4 Preview 6. Java 8 language features are now supported by the Android build system in the javac/dx compilation path. Android Studio's Gradle plugin now desugars Java 8 class files to Java 7-compatible class files, so you can use lambdas, method references and other features of Java 8.

For those of you who tried the Jack compiler, we now support the same set of Java 8 language features but with faster build speed. You can use Java 8 language features together with tools that rely on bytecode, including Instant Run. Using libraries written with Java 8 is also supported.

We first added Java 8 desugaring in Android Studio 2.4 Preview 4. Preview 6 includes important bug fixes related to Java 8 language features support. Many of these fixes were made in response to bug reports you filed. We really appreciate your help in improving Android development tools for the community!

It's easy to try using Java 8 language features in your Android project. Just download Android Studio 2.4 Preview 6, and update your project's target and source compatibility to Java version 1.8. You can find more information in our preview documentation.

Happy lambda'ing!

Calling all early adopters for Android Studio previews

Posted by Scott Main, Technical Writer

If you love trying out all of the newest features in Android Studio and helping us make it a better IDE, we're making it even easier to download early preview builds with a new website. Here, you can download and stay up to date on all the latest Android Studio previews and other tools announcements.



Android Studio previews give you early access to new features in all aspects of the IDE, plus early versions of other tools such as the Android Emulator and platform SDK previews. You can install multiple versions of Android Studio side-by-side, so if a bug in the preview build blocks your app development, you can keep working on the same project from the stable version.

The latest preview for Android Studio 2.4 just came out last week, and it includes new features to support development with the Android O Developer Preview. You can download and set up the O preview SDK from inside Android Studio, and then use Android O’s XML font resources and autosizing TextView in the Layout Editor.

By building your apps with the Android Studio preview, you're also helping us create a better version of Android Studio. We want to hear from you if you encounter any bugs.

5 Tips for launching successful apps and games on Google Play

Posted by Adam Gutterman, Go-To-Market Strategic Lead, Google Play Games

Last month at the Game Developers Conference (GDC), we held a developer panel focused on sharing best practices for building successful app and game businesses. Check out 5 tips for developers, both large and small, as shared by our gaming partners at Electronic Arts (EA), Hutch Games, Nix Hydra, Space Ape Games and Omnidrone.



1. Test, test, test

The best time to test, is before you launch; so test boldly and test a lot! Nix Hydra recommends testing creative, including art style and messaging, as well as gameplay mechanics, onboarding flows and anything else you're not sure about. Gathering feedback from real users in advance of launching can highlight what's working and what can be improved to ensure your game's in the best shape possible at launch.

2. Store listing experiments

Run experiments on all of your store listing page assets. Taking bold risks instead of making assumptions allows you to see the impact of different variables with your actual user base on Google Play. Test in different regions to ensure your store listing page is optimized for each major market, as they often perform differently.

3. Early Access program

Space Ape Games recently used Early Access to test different onboarding experiences and gameplay control methods in their game. Finding the right combination led them to double-digit growth in D1 retention. Gathering these results in advance of launch helped the team fine tune and polish the game, minimizing risk before releasing to the masses.

"Early Access is cool because you can ask the big questions and get real answers from real players," Joe Raeburn, Founding Product Guy at Space Ape Games.

Watch the Android Developer Story below to hear how Omnidrone benefits from Early Access using strong user feedback to improve retention, engagement and monetization in their game.


Mobile game developer Omnidrone benefits from Early Access.

4. Pre-registration

Electronic Arts has run more than 5 pre-registration campaigns on Google Play. Pre-registration allows them to start marketing and build awareness for titles with a clear call-to-action before launch. This gives them a running start on launch day having built a group of users to activate upon the game's release resulting in a jump in D1 installs.

5. Seek feedback

All partners strongly recommended seeking feedback early and often. Feedback tells both sides of the story, by pointing out what's broken as well as what you're doing right. Find the right time and channels to request feedback, whether they be in-game, social, email, or even through reading and responding to reviews within the Google Play store.

If you're a startup who has an upcoming launch on Google Play or has launched an app or game recently and you're interested in opportunities like Early Access and pre-registration, get in touch with us so we can work with you.

Watch sessions from Google Developer Day at GDC17 on the Android Developers YT channel to learn tips for success. Also, visit the Android Developers website to stay up-to-date with features and best practices that will help you grow a successful business on Google Play.


How useful did you find this blogpost?
        


Publish your app with confidence from the Google Play Developer Console

Posted by Kobi Glick, Product Manager, Google Play

Publishing a new app, or app update, is an important and exciting milestone for every developer. In order to make the process smoother and more trackable, we're announcing the launch of a new way to publish apps on Google Play with some new features. The changes will give you the ability to manage your app releases with more confidence via a new manage releases page in the Google Play Developer Console.




Manage your app updates with clarity and control

The new manage releases page is where you upload alpha, beta, and production releases of your app. From here, you can see important information and the status of all your releases across tracks.

The new manage releases page.
Easier access to existing and new publishing features

Publishing an app or update is a big step, and one that every developer wants to have confidence in taking. To help, we've added two new features.
First, we've added a validation step that highlights potential issues before you publish. The new "review and rollout" page will appear before you confirm the roll out of a new app and flag if there are validation errors or warnings. This new flow will make the app release process easier, especially for apps using multi-APK. It also provides new information; for example, in cases where you added new permissions to your app, the system will highlight it.


Second, it's now simpler to perform and track staged roll-outs during the publishing flow. With staged rollouts, you can release your update to a growing % of users, giving you a chance to catch and address any issues before affecting your whole audience.

If you want to review the history of your releases, it is now possible to track them granularly and download previous APKs.

Finally we've added a new artifacts library under manage releases where you can find all the files that help you manage a release.
Start using the new manage releases page today
You can access the new manage releases page in the Developer Console. Visit the Google Play Developer Help Center for more information. With these changes, we're helping you to publish, track and manage your app with confidence on Google Play.


How useful did you find this blogpost?