Posted by Sam Spencer, Technical Program Manager, Google Play
The Android Ice Cream Sandwich (ICS) platform is seven years old and the active device count has been below 1% for some time. Consequently, we are deprecating support for ICS in future releases of Google Play services. For devices running ICS, the Google Play Store will no longer update Play Services APK beyond version 14.7.99.
What does this mean as an Application developer:
The Google Play services SDK contains the interfaces to the functionality provided by the Google Play services APK, running as background services. The functionality required by the current, released SDK versions is already present on ICS devices with Google Play services and will continue to work without change.
With the SDK version changes earlier this year, each library can be independently released and may update its own minSdkVersion. Individual libraries are not required to change based on this deprecation. Newer SDK components may continue to support API levels 14 and 15 but many will update to require the higher API level. For applications that support API level 16 or greater, you will not need to make any changes to your build. For applications that support API levels 14 or 15, you may continue to build and publish your app to devices running ICS, but you will encounter build errors when updating to newer SDK versions. The error will look like this:
Error:Execution failed for task ':app:processDebugManifest'. > Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version 16 declared in library [com.google.android.gms:play-services-FOO:16.X.YY] Suggestion: use tools:overrideLibrary="com.google.android.gms:play_services" to force usage
Unfortunately, the stated suggestion will not help you successfully run your app on older devices. In order to use the newer SDK, you will need to use one of the following options:
1. Target API level 16 as the minimum supported API level.
This is the recommended course of action. To discontinue support for API levels that will no longer receive Google Play services updates, simply increase the minSdkVersion value in your app's build.gradle to at least 16. If you update your app in this way and publish it to the Play Store, users of devices with less than that level of support will not be able to see or download the update. However, they will still be able to download and use the most recently published version of the app that does target their device.
A very small percentage of all Android devices are using API levels less than 16. You can read more about the current distribution of Android devices. We believe that many of these old devices are not actively being used.
If your app still has a significant number of users on older devices, you can use multiple APK support in Google Play to deliver an APK that uses Google Play services 14.7.99. This is described below.
2. Build multiple APKs to support devices with an API level less than 16.
Along with some configuration and code management, you can build multiple APKs that support different minimum API levels, with different versions of Google Play services. You can accomplish this with build variants in Gradle. First, define build flavors for legacy and newer versions of your app. For example, in your build.gradle, define two different product flavors, with two different compile dependencies for the stand-in example play-services-FOO component:
productFlavors { legacy { minSdkVersion 14 versionCode 1401 // Min API level 14, v01 } current { minSdkVersion 16 versionCode 1601 // Min API level 16, v01 } } dependencies { legacyCompile 'com.google.android.gms:play-services-FOO:16.0.0' currentCompile 'com.google.android.gms:play-services-FOO:17.0.0' }
In the above situation, there are two product flavors being built against two different versions of play-services-FOO. This will work fine if only APIs are called that are available in the 16.0.0 library. If you need to call newer APIs made available with 17.0.0, you will have to create your own compatibility library for the newer API calls so that they are only built into the version of the application that can use them:
After building a release APK for each flavor, you then publish them both to the Play Store, and the device will update with the most appropriate version for that device. Read more about multiple APK support in the Play Store.
We hope you're enjoying the first developer preview of Android P. We wanted to specifically call out some backward-incompatible changes we plan to make to the cryptographic capabilities in Android P, which you can see in the developer preview.
Starting in Android P, we plan to deprecate some functionality from the BC provider that's duplicated by the AndroidOpenSSL (also known as Conscrypt) provider. This will only affect applications that specify the BC provider explicitly when calling getInstance() methods. To be clear, we aren't doing this because we are concerned about the security of the implementations from the BC provider, rather because having duplicated functionality imposes additional costs and risks while not providing much benefit.
getInstance()
If you don't specify a provider in your getInstance() calls, no changes are required.
If you specify the provider by name or by instance—for example, Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC") or Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"))—the behavior you get in Android P will depend on what API level your application targets. For apps targeting an API level before P, the call will return the BC implementation and log a warning in the application log. For apps targeting Android P or later, the call will throw NoSuchAlgorithmException.
Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC")
Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"))
NoSuchAlgorithmException
To resolve this, you should stop specifying a provider and use the default implementation.
In a later Android release, we plan to remove the deprecated functionality from the BC provider entirely. Once removed, any call that requests that functionality from the BC provider (whether by name or instance) will throw NoSuchAlgorithmException.
In a previous post, we announced that the Crypto provider was deprecated beginning in Android Nougat. Since then, any request for the Crypto provider by an application targeting API 23 (Marshmallow) or before would succeed, but requests by applications targeting API 24 (Nougat) or later would fail. In Android P, we plan to remove the Crypto provider entirely. Once removed, any call to SecureRandom.getInstance("SHA1PRNG", "Crypto") will throw NoSuchProviderException. Please ensure your apps have been updated.
SecureRandom.getInstance("SHA1PRNG", "Crypto")
NoSuchProviderException
Since announcing ConstraintLayout at Google I/O last year, we've continued to improve the layout's stability and layout editor support. We've also added new features specific to ConstraintLayout that help you build various type of layouts, such as introducing chains and setting size as a ratio. In addition to these features, there is a notable performance benefit by using ConstraintLayout. In this post, we'll walk through how you can benefit from these performance improvements.
ConstraintLayout
To better understand the performance of ConstraintLayout, let's take a step back and see how Android draws views.
When a user brings an Android view into focus, the Android framework directs the view to draw itself. This drawing process comprises 3 phases:
The system completes a top-down traversal of the view tree to determine how large each ViewGroup and View element should be. When a ViewGroup is measured, it also measures its children.
ViewGroup
Another top-down traversal occurs, with each ViewGroup determining the positions of its children using the sizes determined in the measure phase.
The system performs yet another top-down traversal. For each object in the view tree, a Canvas object is created to send a list of drawing commands to the GPU. These commands include the ViewGroup and View objects' sizes and positions, which the system determined during the previous 2 phases.
Canvas
View
Each phase within the drawing process requires a top-down traversal of the view tree. Therefore, the more views you embed within each other (or nest) into the view hierarchy, the more time and computation power it takes for the device to draw the views. By keeping a flat hierarchy in your Android app layouts, you can create a fast and responsive user interface for your app.
With that explanation in mind, let's create a traditional layout hierarchy that uses LinearLayout and RelativeLayout objects.
LinearLayout
RelativeLayout
Let's say we want to build a layout like the image above. If you build it with traditional layouts, the XML file contains an element hierarchy similar to the following (for this example, we've omitted the attributes):
<RelativeLayout> <ImageView /> <ImageView /> <RelativeLayout> <TextView /> <LinearLayout> <TextView /> <RelativeLayout> <EditText /> </RelativeLayout> </LinearLayout> <LinearLayout> <TextView /> <RelativeLayout> <EditText /> </RelativeLayout> </LinearLayout> <TextView /> </RelativeLayout> <LinearLayout > <Button /> <Button /> </LinearLayout> </RelativeLayout>
Although there's usually room for improvement in this type of view hierarchy, you'll almost certainly still need to create a hierarchy with some nested views.
As discussed before, nested hierarchies can adversely affect performance. Let's take a look at how the nested views actually affect the UI performance using Android Studio's Systrace tool. We called the measure and layout phases for each ViewGroup (ConstraintLayout and RelativeLayout) programmatically and triggered Systrace while the measure and layout calls are executing. The following command generates an overview file that contains key events, such as expensive measure/layout passes, that occur during a 20-second interval:
python $ANDROID_HOME/platform-tools/systrace/systrace.py --time=20 -o ~/trace.html gfx view res
For more details about how you can use Systrace, see the Analyzing UI Performance with Systrace guide.
Systrace automatically highlights the (numerous) performance problems with this layout, as well as suggestions for fixing them. By clicking the "Alerts" tab, you will find that drawing this view hierarchy requires 80 expensive passes through the measure and layout phases!
Triggering that many expensive measure and layout phases is far from ideal; such a large amount of drawing activity could result in skipped frames that users notice. We can conclude that the layout has poor performance due to the nested hierarchy as well as the characteristic of RelativeLayout, which measures each of its children twice.
You can check the entire code on how we performed these measurements in our GitHub repository.
If you create the same layout using ConstraintLayout, the XML file contains an element hierarchy similar to the following (attributes again omitted):
<android.support.constraint.ConstraintLayout> <ImageView /> <ImageView /> <TextView /> <EditText /> <TextView /> <TextView /> <EditText /> <Button /> <Button /> <TextView /> </android.support.constraint.ConstraintLayout>
As this example shows, the layout now has a completely flat hierarchy. This is because ConstraintLayout allows you to build complex layouts without having to nest View and ViewGroup elements.
For example, let's look at the TextView and EditText in the middle of the layout:
TextView
EditText
<LinearLayout android:id="@+id/camera_area" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_below="@id/title" > <TextView android:text="@string/camera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:id="@+id/cameraLabel" android:labelFor="@+id/cameraType" android:layout_marginStart="16dp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/cameraType" android:ems="10" android:inputType="textPersonName" android:text="@string/camera_value" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginTop="8dp" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" /> </RelativeLayout> </LinearLayout>
By using ConstraintLayout instead, you can achieve the same effect just by adding a constraint from the baseline of the TextView to the baseline of the EditText without creating another ViewGroup:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_creator="1" app:layout_constraintBaseline_creator="1" app:layout_constraintLeft_toLeftOf="@+id/activity_main_done" app:layout_constraintBaseline_toBaselineOf="@+id/cameraType" />
When running the Systrace tool for the version of our layout that uses ConstraintLayout, you see far fewer expensive measure/layout passes during the same 20-second interval. This improvement in performance makes sense, now that we're keeping the view hierarchy flat!
On a related note, we built the ConstraintLayout variant of our layout using just the layout editor instead of editing the XML by hand. To achieve the same visual effect using RelativeLayout, we probably would have needed to edit the XML by hand.
We analyzed how long every measure and layout pass took for two type of layouts, ConstraintLayout and RelativeLayout, by using OnFrameMetricsAvailableListener, which was introduced in Android 7.0 (API level 24). This class allows you to collect frame-by-frame timing information about your app's UI rendering.
OnFrameMetricsAvailableListener
By calling the following code, you can start recording per-frame UI actions:
window.addOnFrameMetricsAvailableListener( frameMetricsAvailableListener, frameMetricsHandler);
After timing information becomes available, the app triggers the frameMetricsAvailableListener() callback. We are interested in the measure/layout performance, so we call FrameMetrics.LAYOUT_MEASURE_DURATION when retrieving the actual frame duration.
frameMetricsAvailableListener()
FrameMetrics.LAYOUT_MEASURE_DURATION
Window.OnFrameMetricsAvailableListener { _, frameMetrics, _ -> val frameMetricsCopy = FrameMetrics(frameMetrics); // Layout measure duration in nanoseconds val layoutMeasureDurationNs = frameMetricsCopy.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION);
To learn more about the other types of duration information that FrameMetrics can receive, see the FrameMetrics API reference.
FrameMetrics
Our performance comparison shows that ConstraintLayout performs about 40% better in the measure/layout phase than RelativeLayout:
As these results show, ConstraintLayout is likely to be more performant than traditional layouts. Moreover, ConstraintLayout has other features that help you build complex and performant layouts, as discussed in the benefits of a ConstraintLayout object section. For details, see the Build a Responsive UI with ConstraintLayout guide. We recommend that you use ConstraintLayout when designing your app's layouts. In almost all cases when you would have previously need a deeply-nested layout, ConstraintLayout should be your go-to layout for optimal performance and ease of use.
All the measurements above were performed in the following environment.
Check out the developer guide, the API reference documentation, and the article on Medium to fully understand what ConstraintLayout can provide for you. And once again, thank you to all who submitted feedback and issues over the months since our alpha release of ConstraintLayout. We're truly grateful that we were able to release the production-ready 1.0 version of ConstraintLayout earlier this year. As we continue to improve ConstraintLayout, please continue to send us feedback using the Android issue tracker.
Posted by Lily Sheringham, Google Play team
Inovidea Magna Global, is the developer of PicMix, a photo and video editing app, which has now evolved into an interest based social media platform powered by content discovery and social commerce. It has 27 million users worldwide, 65% of which are outside of its home market in Indonesia.
Hear Calvin Kizana, CEO, and Sandy Colondam, Co-founder, explain how they used Google Play tools, such as Store Listing Experiments and Material Design, to create a high quality app which appeals to a global audience.
Learn more about store listing experiments and find out how to get started with Material Design. Also, get the Playbook for Developers app and stay up-to-date with more features and best practices that will help you grow a successful business on Google Play.
minimalHeight
minimalWidth