docs: M Preview Content Sync #1
This change list is a snapshot of work in progress on other change lists. If you have conflicts with this change, you should prefer your own changes over what is contained in this change. Change-Id: Ied44713d5078c938fab10d29a3b6e720559144b4
This commit is contained in:
338
docs/html/preview/api-changes.jd
Normal file
338
docs/html/preview/api-changes.jd
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
page.title=Behavior Changes
|
||||||
|
page.keywords=preview,sdk,compatibility
|
||||||
|
sdk.platform.apiLevel=23
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<div id="qv-wrapper">
|
||||||
|
<div id="qv">
|
||||||
|
|
||||||
|
<h2>In this document</h2>
|
||||||
|
|
||||||
|
<ol id="toc44" class="hide-nested">
|
||||||
|
<li><a href="#behavior-runtime-permissions">Runtime Permissions</a></li>
|
||||||
|
<li><a href="#behavior-notifications">Notifications</a></li>
|
||||||
|
<li><a href="#behavior-openssl">OpenSSL</a></li>
|
||||||
|
<li><a href="#behavior-project-volta">Project Volta</a>
|
||||||
|
<ol>
|
||||||
|
<li><a href="#behavior-doze">Doze Mode</a></li>
|
||||||
|
<li><a href="#behavior-app-standby">App Standby Mode</a></li>
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
<li><a href="#behavior-adoptable-storage">Adoptable Storage Devices</a></li>
|
||||||
|
<li><a href="#behavior-apache-http-client">Apache HTTP Client Removal</a></li>
|
||||||
|
<li><a href="#behavior-audiomanager-Changes">AudioManager Changes</a></li>
|
||||||
|
<li><a href="#behavior-test-selection">Text Selection</a></li>
|
||||||
|
<li><a href="#behavior-keystore">Android Keystore Changes</a></li>
|
||||||
|
<li><a href="#behavior-themeable-colorstatelists">Themeable ColorStateLists</a></li>
|
||||||
|
<li><a href="#night-mode">Night Mode</a></li>
|
||||||
|
<li><a href="#behavior-art-runtime">ART Runtime</a></li>
|
||||||
|
<li><a href="#behavior-afw">Android for Work Changes</a></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>API Differences</h2>
|
||||||
|
<ol>
|
||||||
|
<li><a href="">API level 22 to M »</a> </li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>See Also</h2>
|
||||||
|
<ol>
|
||||||
|
<li><a href="{@docRoot}preview/api-overview.html">M Developer Preview API Overview</a> </li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>API Level: M</p>
|
||||||
|
<p>Along with new features and capabilities, M includes a variety of
|
||||||
|
system changes and API behavior changes. This document highlights
|
||||||
|
some of the key changes that you should be understand and account for in your apps.</p>
|
||||||
|
|
||||||
|
<p>If you have previously published an app for Android, be aware that your app
|
||||||
|
might be affected by these changes in M.</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-runtime-permissions">Runtime Permissions</h1>
|
||||||
|
<p>This release introduces a new runtime permissions model, where users can now directly manage
|
||||||
|
their app permissions at runtime. This model gives users improved visibility and control over
|
||||||
|
permissions, while streamlining the installation and auto-update processes for app developers.
|
||||||
|
Users can set permissions on or off for all apps running on Android M. However, apps that don’t
|
||||||
|
target M cannot request permissions at runtime.</p>
|
||||||
|
|
||||||
|
<p>On your apps that target M, make sure to check and request for permissions at
|
||||||
|
runtime. To determine if your app has been granted a permission, call the
|
||||||
|
new {@code Context.checkSelfPermission()} method. To request for a permission, call the new
|
||||||
|
{@code Activity.requestPermission()} method.</p>
|
||||||
|
|
||||||
|
<p>For more information on supporting the new permissions model in your app, see the
|
||||||
|
<a href="{@docRoot}preview/features/runtime-permissions.html">
|
||||||
|
Android M Runtime Permissions guide</a>.</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-openssl">OpenSSL</h2>
|
||||||
|
<p>Android is moving away from OpenSSL to the
|
||||||
|
<a href="https://boringssl.googlesource.com/boringssl/" class="external-link">BoringSSL</a>
|
||||||
|
library. If you’re using the Android NDK in your app, don't link against cryptographic libraries
|
||||||
|
that are not a part of the NDK API, such as {@code libcrypto.so} and {@code libssl.so}. These
|
||||||
|
libraries are not public APIs, and may change or break without notice across releases and devices.
|
||||||
|
In addition, you may expose yourself to security vulnerabilities. Instead, modify your
|
||||||
|
native code to call the Java cryptography APIs via JNI or to statically link against a
|
||||||
|
cryptography library of your choice.</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-project-volta">Project Volta</h2>
|
||||||
|
<p>This release introduces new power-saving optimizations for idle devices and apps.</p>
|
||||||
|
|
||||||
|
<h3 id="behavior-doze">Doze mode</h3>
|
||||||
|
<p>If a device is unplugged and not used for up to an hour, it goes into <em>doze</em> mode where
|
||||||
|
it attempts to keep the system in a sleep state. In this mode, devices may briefly resume normal
|
||||||
|
operations for up to 5 minutes every few hours so that app syncing can occur and the system can
|
||||||
|
perform any pending operations.</p>
|
||||||
|
|
||||||
|
<p>The following restrictions apply to your apps while in device doze mode:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Network access is disabled</li>
|
||||||
|
<li>Alarms scheduled with the {@link android.app.AlarmManager} class are disabled, except for
|
||||||
|
alarms that you've set with the
|
||||||
|
{@link android.app.AlarmManager#setAlarmClock(android.app.AlarmManager.AlarmClockInfo,android.app.PendingIntent) setAlarmClock()}
|
||||||
|
method</li>
|
||||||
|
<li>WiFi scans are not performed</li>
|
||||||
|
<li>Syncs and jobs for your sync adapters and {@link android.app.job.JobScheduler} are not
|
||||||
|
permitted to run</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p>When the system comes out of doze mode, it executes jobs and syncs that are pending.</p>
|
||||||
|
|
||||||
|
<h3 id="behavior-app-standby">App standby mode</h3>
|
||||||
|
<p>In M, the system may determine that apps are idle when they are not in active use by the user.
|
||||||
|
Your app goes into <em>app standby</em> mode after two days unless the system detects any of these
|
||||||
|
signals:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The app has a process currently in the foreground (either as an activity or foreground service,
|
||||||
|
or in use by another activity or foreground service)</li>
|
||||||
|
<li>The app generates a notification that the user can see</li>
|
||||||
|
<li>The user explicitly asks for the app to remain running</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>If the system is running on battery power, apps that are in standby mode will have their
|
||||||
|
network access disabled and their syncs and jobs suspended. When the system is plugged into a power
|
||||||
|
supply, it brings an app out of standby mode and executes any jobs and syncs that are pending.</p>
|
||||||
|
|
||||||
|
<p>Apps that use <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> will
|
||||||
|
continue to receive messages even if they are idle. When the system is plugged into a power
|
||||||
|
supply, apps resume normal operations and can run any pending syncs and jobs.</p>
|
||||||
|
|
||||||
|
<p>You can test this feature by connecting a device running M to your development machine and
|
||||||
|
calling the following commands:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
$ adb shell am broadcast -a android.os.action.DISCHARGING
|
||||||
|
$ adb shell am set-idle <packageName> true
|
||||||
|
$ adb shell am set-idle <packageName> false
|
||||||
|
$ adb shell am get-idle <packageName>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="behavior-adoptable-storage">Adoptable Storage Devices</h2>
|
||||||
|
<p>
|
||||||
|
In M, users can adopt external storage devices such as SD cards. Adopting an external storage
|
||||||
|
device encrypts and formats the device to behave like internal storage. This feature allows users
|
||||||
|
to move both apps and private data of those apps between storage devices. When moving apps, the
|
||||||
|
system respects the <a href="{@docRoot}guide/topics/manifest/manifest-element.html#install">
|
||||||
|
{@code android:installLocation}</a> preference in the manifest.</p>
|
||||||
|
|
||||||
|
<p>If your app accesses the following APIs or fields, be aware that the file paths they return
|
||||||
|
will dynamically change when the app is moved between internal and external storage devices.
|
||||||
|
When building file paths, it is strongly recommended that you always call these APIs dynamically.
|
||||||
|
Don’t use hardcoded file paths or persist fully-qualified file paths that were built previously.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>{@link android.content.Context} methods:
|
||||||
|
<ul>
|
||||||
|
<li>{@link android.content.Context#getFilesDir() getFilesDir()}</li>
|
||||||
|
<li>{@link android.content.Context#getCacheDir() getCacheDir()}</li>
|
||||||
|
<li>{@link android.content.Context#getCodeCacheDir() getCodeCacheDir()}</li>
|
||||||
|
<li>{@link android.content.Context#getDatabasePath(java.lang.String) getDatabasePath()}</li>
|
||||||
|
<li>{@link android.content.Context#getDir(java.lang.String,int) getDir()}</li>
|
||||||
|
<li>{@link android.content.Context#getNoBackupFilesDir() getNoBackupFilesDir()}</li>
|
||||||
|
<li>{@link android.content.Context#getFileStreamPath(java.lang.String) getFileStreamPath()}</li>
|
||||||
|
<li>{@link android.content.Context#getPackageCodePath() getPackageCodePath()}</li>
|
||||||
|
<li>{@link android.content.Context#getPackageResourcePath() getPackageResourcePath()}</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>{@link android.content.pm.ApplicationInfo} fields:
|
||||||
|
<ul>
|
||||||
|
<li>{@link android.content.pm.ApplicationInfo#dataDir dataDir}</li>
|
||||||
|
<li>{@link android.content.pm.ApplicationInfo#sourceDir sourceDir}</li>
|
||||||
|
<li>{@link android.content.pm.ApplicationInfo#nativeLibraryDir nativeLibraryDir}</li>
|
||||||
|
<li>{@link android.content.pm.ApplicationInfo#publicSourceDir publicSourceDir}</li>
|
||||||
|
<li>{@link android.content.pm.ApplicationInfo#splitSourceDirs splitSourceDirs}</li>
|
||||||
|
<li>{@link android.content.pm.ApplicationInfo#splitPublicSourceDirs splitPublicSourceDirs}</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>To debug this feature in the developer preview, you can enable adoption of a USB drive that is
|
||||||
|
connected to an Android device through a USB On-The-Go (OTG) cable, by running these
|
||||||
|
commands:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
$ adb root
|
||||||
|
$ sleep 2
|
||||||
|
$ adb shell setprop persist.fw.force_adoptable 1
|
||||||
|
$ adb reboot
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="behavior-apache-http-client">Apache HTTP Client Removal</h2>
|
||||||
|
<p>This release removes support for the Apache HTTP client. If your app is using this client and
|
||||||
|
targets Android 2.3 (API level 9) or higher, use the {@link java.net.HttpURLConnection} class
|
||||||
|
instead. This API is more efficient because it reduces network use through transparent compression
|
||||||
|
and response caching, and minimizes power consumption. To continue using the Apache HTTP APIs, you
|
||||||
|
must first declare the following compile-time dependency in your {@code build.gradle} file:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
android {
|
||||||
|
compileSdkVersion M
|
||||||
|
useLibrary 'org.apache.http.legacy'
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="behavior-audiomanager-Changes">AudioManager Changes</h2>
|
||||||
|
<p>Setting the volume directly or muting specific streams via the {@link android.media.AudioManager}
|
||||||
|
class is no longer supported. The {@link android.media.AudioManager#setStreamSolo(int,boolean)
|
||||||
|
setStreamSolo()} method is deprecated, and you should call the
|
||||||
|
{@code AudioManager.requestAudioFocus()} method instead. Similarly, the
|
||||||
|
{@link android.media.AudioManager#setStreamMute(int,boolean) setStreamMute()} method is
|
||||||
|
deprecated; instead, call the {@code AudioManager.adjustStreamVolume()} method
|
||||||
|
and pass in the direction value {@code ADJUST_MUTE} or {@code ADJUST_UNMUTE}.</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-test-selection">Text Selection</h2>
|
||||||
|
|
||||||
|
<img src="{@docRoot}preview/images/text-selection.gif"
|
||||||
|
style="float:right; margin:0 0 20px 30px" width="270" height="480" />
|
||||||
|
|
||||||
|
<p>When users selects text in your app, you can now display text selection actions such as
|
||||||
|
<em>Cut</em>, <em>Copy</em>, and <em>Paste</em> in a
|
||||||
|
<a href="http://www.google.com/design/spec/patterns/selection.html#selection-text-selection"
|
||||||
|
class="external-link">floating toolbar</a>. The user interaction implementation is similar to that
|
||||||
|
for the contextual action bar, as described in
|
||||||
|
<a href="{@docRoot}guide/topics/ui/menus.html#CABforViews">
|
||||||
|
Enabling the contextual action mode for individual views</a>.</p>
|
||||||
|
|
||||||
|
<p>To implement a floating toolbar for text selection, make the following changes in your existing
|
||||||
|
apps:</p>
|
||||||
|
<ol>
|
||||||
|
<li>In your {@link android.view.View} or {@link android.app.Activity} object, change your
|
||||||
|
{@link android.view.ActionMode} calls from
|
||||||
|
{@code startActionMode(Callback)} to {@code startActionMode(Callback, ActionMode.TYPE_FLOATING)}.</li>
|
||||||
|
<li>Take your existing implementation of ActionMode.Callback and make it extend
|
||||||
|
{@code ActionMode.Callback2} instead.</li>
|
||||||
|
<li>Override the {@code Callback2.onGetContentRect()} method to provide the coordinates of the
|
||||||
|
content {@link android.graphics.Rect} object (such as a text selection rectangle) in the view.</li>
|
||||||
|
<li>If the rectangle positioning is no longer valid, and this is the only element to be invalidated,
|
||||||
|
call the {@code ActionMode.invalidateContentRect()} method.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>If you are using <a href="{@docRoot}tools/support-library/index.html">
|
||||||
|
Android Support Library</a> revision 22.2, be aware that floating toolbars are not
|
||||||
|
backward-compatible and appcompat takes control over {@link android.view.ActionMode} objects by
|
||||||
|
default. This prevents floating toolbars from being displayed in M. To enable
|
||||||
|
{@link android.view.ActionMode} support in an
|
||||||
|
{@link android.support.v7.app.AppCompatActivity}, call
|
||||||
|
{@code android.support.v7.app.AppCompatActivity.getDelegate()}, then call
|
||||||
|
{@code android.support.v7.app.AppCompatDelegate.setHandleNativeActionModesEnabled()} on the returned
|
||||||
|
{@link android.support.v7.app.AppCompatDelegate} object and set the input
|
||||||
|
parameter to {@code false}. This call returns control of {@link android.view.ActionMode} objects to
|
||||||
|
the framework. In devices running M, that allows the framework to support
|
||||||
|
{@link android.support.v7.app.ActionBar} or floating toolbar modes, while on pre-M devices, only the
|
||||||
|
{@link android.support.v7.app.ActionBar} modes are supported.</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-keystore">Android Keystore Changes</h2>
|
||||||
|
<p>Starting this release, the
|
||||||
|
<a href="{@docRoot}training/articles/keystore.html">Android Keystore provider</a> no longer supports
|
||||||
|
DSA. ECDSA is still supported.</p>
|
||||||
|
|
||||||
|
<p>Keys which do not require encryption at rest will no longer be deleted when secure lock screen
|
||||||
|
is disabled or reset (for example, by the user or a Device Administrator). Keys which require
|
||||||
|
encryption at rest will be deleted during these events.</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-themeable-colorstatelists">Themeable ColorStateLists</h2>
|
||||||
|
<p>Theme attributes are now supported in
|
||||||
|
{@link android.content.res.ColorStateList} for devices running M. The
|
||||||
|
{@link android.content.res.Resources#getColorStateList(int) getColorStateList()} and
|
||||||
|
{@link android.content.res.Resources#getColor(int) getColor()} methods have been deprecated. If
|
||||||
|
you are calling these APIs, call the new {@code Context.getColorStateList()} or
|
||||||
|
{@code Context.getColor()} methods instead. These methods are also available in the
|
||||||
|
v4 appcompat library via {@link android.support.v4.content.ContextCompat}.</p>
|
||||||
|
|
||||||
|
<h2 id="night-mode">Night Mode (User-configurable Dark Theme)</h2>
|
||||||
|
<p>
|
||||||
|
Support for the {@code -night} resource qualifier has been updated in M. Previously, night mode was
|
||||||
|
only available when a device was docked and in car mode. Starting in M, night mode is available on
|
||||||
|
all devices and is user-configurable via <em>Settings > Display > Theme</em>. You can adjust this
|
||||||
|
setting globally using {@link android.app.UiModeManager#setNightMode(int) setNightMode()}. The
|
||||||
|
Dark theme corresponds to {@link android.app.UiModeManager#MODE_NIGHT_YES}. When the device is in
|
||||||
|
night mode, the resource framework will prefer resources that have the -night qualifier. To
|
||||||
|
take advantage of user-configurable Dark mode in your app, extend from the
|
||||||
|
{@code Theme.Material.DayNight} set of themes rather than {@code Theme.Material} or
|
||||||
|
{@code Theme.Material.Light}.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-art-runtime">ART Runtime</h2>
|
||||||
|
<p>The ART runtime now properly implements access rules for the
|
||||||
|
{@link java.lang.reflect.Constructor#newInstance(java.lang.Object...) newInstance()} method. This
|
||||||
|
change fixes a problem where Dalvik was checking access rules incorrectly in previous versions.
|
||||||
|
If your app uses the
|
||||||
|
{@link java.lang.reflect.Constructor#newInstance(java.lang.Object...) newInstance()} method and you
|
||||||
|
want to override access checks, call the
|
||||||
|
{@link java.lang.reflect.Constructor#setAccessible(boolean) setAccessible()} method with the input
|
||||||
|
parameter set to {@code true}. If your app uses the
|
||||||
|
<a href="{@docRoot}tools/support-library/features.html#v7">v7 appcompat library</a> or the
|
||||||
|
<a href="{@docRoot}tools/support-library/features.html#v7-recyclerview">v7 recyclerview library</a>,
|
||||||
|
you must update your app to use to the latest versions of these libraries. Otherwise, make sure that
|
||||||
|
any custom classes referenced from XML are updated so that their class constructors are accessible.</p>
|
||||||
|
|
||||||
|
<p>The M release updates the behavior of the dynamic linker. The dynamic linker now understands the
|
||||||
|
difference between a library’s {@code soname} and its path
|
||||||
|
(<a href="https://code.google.com/p/android/issues/detail?id=6670" class="external-link">
|
||||||
|
public bug 6670</a>), and search by {@code soname} is now
|
||||||
|
implemented. Apps which previously worked that have bad {@code DT_NEEDED} entries
|
||||||
|
(usually absolute paths on the build machine’s file system) may fail when loaded on M.</p>
|
||||||
|
|
||||||
|
<p>The {@code dlopen(3) RTLD_LOCAL} flag is now correctly implemented in M. Note that
|
||||||
|
{@code RTLD_LOCAL} is the default, so calls to {@code dlopen(3)} that didn’t explicitly use
|
||||||
|
{@code RTLD_LOCAL} will be affected (unless your app explicitly used {@code RTLD_GLOBAL}). With
|
||||||
|
{@code RTLD_LOCAL}, symbols will not be made available to libraries loaded by later calls to
|
||||||
|
{@code dlopen(3)} (as opposed to being referenced by {@code DT_NEEDED} entries).</p>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="behavior-afw">Android for Work Changes</h2>
|
||||||
|
<p>This release includes the following behavior changes for Android for Work:</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Work contacts in personal contexts.</strong> Google Messenger and the Google Dialer
|
||||||
|
Call Log now display work contacts when the user views past messages or calls. Furthermore, both
|
||||||
|
work and personal contacts are now available to devices over Bluetooth, but you can hide work
|
||||||
|
profile contacts through a device policy by calling the new
|
||||||
|
{@code DevicePolicyManager.setBluetoothContactSharingDisabled()} method. Initiating a call or
|
||||||
|
creating a new message will only show personal contacts, as consistent with the experience in
|
||||||
|
Android 5.0.
|
||||||
|
</li>
|
||||||
|
<li><strong>WiFi configuration removal:</strong> WiFi configurations added by a Profile Owner
|
||||||
|
(for example, through calls to the
|
||||||
|
{@link android.net.wifi.WifiManager#addNetwork(android.net.wifi.WifiConfiguration)
|
||||||
|
addNetwork()} method) are now removed if that work profile is deleted.</li>
|
||||||
|
<li><strong>WiFi configuration lockdown:</strong> Any WiFi configuration created by an active Device
|
||||||
|
Owner can no longer be modified or deleted by the user. The user can still create and
|
||||||
|
modify their own WiFi configurations, so long as the {@link android.os.UserManager} constant
|
||||||
|
{@link android.os.UserManager#DISALLOW_CONFIG_WIFI} has not been set for that user.</li>
|
||||||
|
<li><strong>VPN in Settings:</strong> VPN apps are now visible in <em>Settings > More > VPN</em>.
|
||||||
|
Additionally, the notifications that accompany VPN usage are now specific to whether that VPN is
|
||||||
|
configured for a managed profile or the entire device.</li>
|
||||||
|
<li><strong>Work status notification:</strong> A status bar briefcase icon now appears whenever
|
||||||
|
an app from the managed profile has an activity in the foreground. Furthermore, if the device is
|
||||||
|
unlocked directly to the activity of an app in the managed profile, a toast is displayed notifying
|
||||||
|
the user that they are within the work profile.
|
||||||
|
</li>
|
||||||
|
<li><strong>Download Work Policy Controller via Google account addition:</strong> When a Google
|
||||||
|
account that requires management via a Work Policy Controller (WPC) app is added to a device
|
||||||
|
outside of a managed context, the add account flow now prompts the user to install the
|
||||||
|
appropriate WPC. This behavior also applies to accounts added via
|
||||||
|
<em>Settings > Accounts</em> in the initial device setup wizard.</li>
|
||||||
|
</ul>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
page.title=API Overview
|
page.title=API Overview
|
||||||
page.keywords=preview,sdk,compatibility
|
page.keywords=preview,sdk,compatibility
|
||||||
sdk.platform.apiLevel=22
|
sdk.platform.apiLevel=23
|
||||||
@jd:body
|
@jd:body
|
||||||
|
|
||||||
|
|
||||||
@@ -13,24 +13,24 @@ sdk.platform.apiLevel=22
|
|||||||
<span class="less" style="display:none">show less</span></a></h2>
|
<span class="less" style="display:none">show less</span></a></h2>
|
||||||
|
|
||||||
<ol id="toc44" class="hide-nested">
|
<ol id="toc44" class="hide-nested">
|
||||||
<li><a href="#">Important Behavior Changes</a>
|
<li><a href="#backup">Auto Backup for Apps</a></li>
|
||||||
<ol>
|
<li><a href="#notifications">Notifications</a></li>
|
||||||
<li><a href="#">change 1</a></li>
|
<li><a href="#authentication">Authentication</a>
|
||||||
<li><a href="#">change 2</a></li>
|
<ul>
|
||||||
</ol>
|
<li><a href="#fingerprint-authentication">Fingerprint Authentication</a></li>
|
||||||
</li>
|
<li><a href="#confirm-credentials">Confirm Credentials</a></li>
|
||||||
<li><a href="#">Feature Group 1</a>
|
</ul>
|
||||||
<ol>
|
|
||||||
<li><a href="#">change 1</a></li>
|
|
||||||
<li><a href="#">change 2</a></li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
<li><a href="#">Feature Group 2</a>
|
|
||||||
<ol>
|
|
||||||
<li><a href="#">change 1</a></li>
|
|
||||||
<li><a href="#">change 2</a></li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
</li>
|
||||||
|
<li><a href="#direct-share">Direct Share</a></li>
|
||||||
|
<li><a href="#voice-interactions">Voice Interactions</a></li>
|
||||||
|
<li><a href="#bluetooth-stylus">Bluetooth Stylus Support</a></li>
|
||||||
|
<li><a href="#audio">New Audio Features</a></li>
|
||||||
|
<li><a href="#afw">New Android for Work Features</a></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2>API Differences</h2>
|
||||||
|
<ol>
|
||||||
|
<li><a href="">API level 22 to M »</a> </li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -54,65 +54,313 @@ methods that do not yet have reference material available on <a
|
|||||||
href="{@docRoot}">developer.android.com</a>. These API elements are
|
href="{@docRoot}">developer.android.com</a>. These API elements are
|
||||||
formatted in {@code code style} in this document (without hyperlinks). For the
|
formatted in {@code code style} in this document (without hyperlinks). For the
|
||||||
preliminary API documentation for these elements, download the <a
|
preliminary API documentation for these elements, download the <a
|
||||||
href="http://storage.googleapis.com/androiddevelopers/preview/l-developer-preview-reference.zip">preview
|
href="http://storage.googleapis.com/androiddevelopers/preview/m-developer-preview-reference.zip">
|
||||||
reference</a>.</p>
|
preview reference</a>.</p>
|
||||||
|
|
||||||
<h2 id="Behaviors">Important Behavior Changes</h2>
|
<h3>Important behavior changes</h3>
|
||||||
|
|
||||||
<p>If you have previously published an app for Android, be aware that your app
|
<p>If you have previously published an app for Android, be aware that your app might be affected
|
||||||
might be affected by changes in the upcoming release.</p>
|
by changes in M.</p>
|
||||||
|
|
||||||
<h3 id="id">Behavior Change 1</h3>
|
<p>Please see <a href="api-changes.html">Behavior Changes</a> for complete information.</p>
|
||||||
|
|
||||||
<p>
|
<h2 id="backup">Auto Backup for Apps</h2>
|
||||||
Bacon ipsum dolor amet biltong picanha t-bone, jowl salami tri-tip jerky kielbasa sirloin boudin
|
<p>The system now performs automatic full data backup and restore for apps. This behavior is
|
||||||
porchetta fatback cow meatloaf capicola. Short ribs kielbasa pig drumstick rump boudin jowl chuck
|
enabled by default for apps targeting M; you do not need to add any additional code. If users
|
||||||
beef ribs doner tenderloin biltong swine.
|
delete their Google account, their backup data is deleted as well.</p>
|
||||||
|
<p>To learn how this feature works and how to configure what to back up on the file system,
|
||||||
|
see the <a href="">App Backup for Apps guide</a>.</p>
|
||||||
|
|
||||||
|
<h2 id="notifications">Notifications</h2>
|
||||||
|
<p>M adds the following API changes for notifications:</p>
|
||||||
|
<ul>
|
||||||
|
<li>New {@code NotificationListenerService.INTERRUPTION_FILTER_ALARMS} filter level that
|
||||||
|
corresponds to the new <em>Alarms only</em> do not disturb mode.</li>
|
||||||
|
<li>New {@code Notification.CATEGORY_REMINDER} category value that is used to distinguish
|
||||||
|
user-scheduled reminders from other events
|
||||||
|
({@link android.app.Notification#CATEGORY_EVENT}) and alarms
|
||||||
|
({@link android.app.Notification#CATEGORY_ALARM}).</li>
|
||||||
|
<li>New {@code android.graphics.drawable.Icon} class which can be attached to your notifications
|
||||||
|
via the Notification.Builder.setIcon() and Notification.Builder.setLargeIcon() methods.</li>
|
||||||
|
<li>New {@code NotificationManager.getActiveNotifications()} method that allows your apps to
|
||||||
|
find out which of their notifications are currently alive.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="authentication">Authentication</h2>
|
||||||
|
<p>The M release offers new APIs to let you authenticate users by using their fingerprint scans on
|
||||||
|
supported devices, and check how recently the user was last authenticated using a device unlocking
|
||||||
|
mechanism (such as a lockscreen password). Use these APIs in conjunction with
|
||||||
|
the <a href="{@docRoot}training/articles/keystore.html">Android Keystore system</a>.</p>
|
||||||
|
|
||||||
|
<h3 id="fingerprint-authentication">Fingerprint Authentication</h3>
|
||||||
|
|
||||||
|
<p>To authenticate users via fingerprint scan, get an instance of the new
|
||||||
|
{@code android.hardware.fingerprint.FingerprintManager} class and call the
|
||||||
|
{@code FingerprintManager.authenticate()} method. Your app must be running on a device with a
|
||||||
|
fingerprint sensor. You must implement the user interface for the fingerprint
|
||||||
|
authentication flow on your app, and use the standard fingerprint Android icon in your UI.
|
||||||
|
If you are developing multiple apps that use fingerprint authentication, note that each app must
|
||||||
|
authenticate the user’s fingerprint independently.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<img src="{@docRoot}preview/images/fingerprint-screen_2x.png"
|
||||||
|
srcset="{@docRoot}preview/images/fingerprint-screen.png 1x, preview/images/fingerprint-screen_2x.png 2x"
|
||||||
|
style="margin:0 0 10px 20px" width="282" height="476" />
|
||||||
|
|
||||||
|
<p>To use this feature in your app, first add the {@code USE_FINGERPRINT} permission in your
|
||||||
|
manifest.</p>
|
||||||
|
|
||||||
<h2 id="id">Feature Group 1</h2>
|
<pre>
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.USE_FINGERPRINT" />
|
||||||
|
</pre>
|
||||||
|
|
||||||
<h3 id="id">Feature item 1</h3>
|
<p>The following snippet shows how you might listen for fingerprint events in your
|
||||||
|
{@code FingerprintManager.AuthenticationCallback} implementation.</p>
|
||||||
|
|
||||||
<p>
|
<pre>
|
||||||
Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
|
// Call this to start listening for fingerprint events
|
||||||
alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
|
public void startListening(FingerprintManager.CryptoObject cryptoObject) {
|
||||||
jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
|
if (!isFingerprintAuthAvailable()) {
|
||||||
turducken. Tongue brisket ham shoulder:
|
return;
|
||||||
|
}
|
||||||
|
mCancellationSignal = new CancellationSignal();
|
||||||
|
mSelfCancelled = false;
|
||||||
|
mFingerprintManager.authenticate(cryptoObject,
|
||||||
|
mCancellationSignal, this, 0 /* flags */);
|
||||||
|
// Icon to display when prompting users to start a fingerprint scan
|
||||||
|
mIcon.setImageResource(R.drawable.ic_fp_40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to check if the device supports fingerprint
|
||||||
|
// scanning and if the user has enrolled at least one fingerprint.
|
||||||
|
public boolean isFingerprintAuthAvailable() {
|
||||||
|
return mFingerprintManager.isHardwareDetected()
|
||||||
|
&& mFingerprintManager.hasEnrolledFingerprints();
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h3 id="confirm-credentials">Confirm Credentials</h3>
|
||||||
|
<p>Your app can authenticate users based on how recently they last unlocked their device. You can
|
||||||
|
use the same public or secret key to authenticate users into multiple apps. This feature frees
|
||||||
|
users from having to remember additional app-specific passwords, and avoids the need for you to
|
||||||
|
implement your own authentication user interface.</p>
|
||||||
|
|
||||||
|
<p>You can set your own authentication policy by setting constraints against the key that you are
|
||||||
|
generating or importing. To set the constraints for using a key, use the
|
||||||
|
{@code android.security.KeyPairGeneratorSpec.Builder} and
|
||||||
|
{@code android.security.KeyGeneratorSpec.Builder} classes for public key pairs and secret keys
|
||||||
|
respectively. If you are importing keys, use the {@link android.security.KeyStoreParameter.Builder}
|
||||||
|
class to set your constraints.</p>
|
||||||
|
|
||||||
|
<p>The following example shows how you might create a symmetric key in the Keystore which can only be
|
||||||
|
used if the user has successfully unlocked the device within the last 5 minutes.</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
private void createKey() {
|
||||||
|
// Generate a key to decrypt payment credentials, tokens, etc.
|
||||||
|
// This will most likely be a registration step for the user when
|
||||||
|
// they are setting up your app.
|
||||||
|
try {
|
||||||
|
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
|
||||||
|
ks.load(null);
|
||||||
|
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES",
|
||||||
|
"AndroidKeyStore");
|
||||||
|
keyGenerator.init(new KeyGeneratorSpec.Builder(this)
|
||||||
|
// Alias of the entry in Android KeyStore where the key will appear
|
||||||
|
.setAlias(KEY_NAME)
|
||||||
|
// Key use constraints
|
||||||
|
.setPurposes(KeyStoreKeyProperties.Purpose.ENCRYPT
|
||||||
|
| KeyStoreKeyProperties.Purpose.DECRYPT)
|
||||||
|
.setBlockModes("CBC")
|
||||||
|
.setUserAuthenticationRequired(true)
|
||||||
|
// Require that the user has unlocked in the last 5 minutes
|
||||||
|
.setUserAuthenticationValidityDurationSeconds(5 * 60)
|
||||||
|
.setEncryptionPaddings("PKCS7Padding")
|
||||||
|
.build());
|
||||||
|
keyGenerator.generateKey();
|
||||||
|
} catch (NoSuchAlgorithmException | NoSuchProviderException
|
||||||
|
| InvalidAlgorithmParameterException | KeyStoreException
|
||||||
|
| CertificateException | IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>To determine the last time users logged into their account, call the
|
||||||
|
{@code android.accounts.AccountManager.confirmCredentials()} method. If the call is successful, the
|
||||||
|
method returns an bundle that includes a {@code KEY_LAST_AUTHENTICATED_TIME} value which indicates
|
||||||
|
the last time, in milliseconds, that the credential for that account was validated or created.</p>
|
||||||
|
|
||||||
|
<h2 id="direct-share">Direct Share</h2>
|
||||||
|
|
||||||
|
<img src="{@docRoot}preview/images/direct-share-screen_2x.png"
|
||||||
|
srcset="{@docRoot}preview/images/direct-share-screen.png 1x, preview/images/direct-share-screen_2x.png 2x"
|
||||||
|
style="float:right; margin:0 0 20px 30px" width="312" height="385" />
|
||||||
|
|
||||||
|
<p>This release provides you with APIs to makes sharing intuitive and quick for users. You can now
|
||||||
|
define <em>deep links</em> that target a specific activity in your app. These deep links are
|
||||||
|
exposed to users via the <em>Share</em> menu. This feature allows users to share content to
|
||||||
|
targets, such as contacts, within other apps. For example, the deep link might launch an
|
||||||
|
activity in another social network app, which lets the user share content directly to a specific
|
||||||
|
friend or community in that app.</p>
|
||||||
|
|
||||||
|
<p>To enable sharing via deep links, you must define a class that extends the
|
||||||
|
{@code android.service.} <br>
|
||||||
|
{@code chooser.ChooserTargetService} class. Declare your
|
||||||
|
{@code ChooserTargetService} in the manifest. Within that declaration, specify the
|
||||||
|
{@code BIND_CHOOSER_TARGET_SERVICE} permission and an intent filter with the
|
||||||
|
{@code SERVICE_INTERFACE} action.</p>
|
||||||
|
<p>The following example shows how you might declare the {@code ChooserTargetService} in your
|
||||||
|
manifest.</p>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<pre>
|
||||||
|
<service android:name=".ChooserTargetService"
|
||||||
|
android:label="@string/service_name"
|
||||||
|
android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.service.chooser.ChooserTargetService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>For each activity that you want to expose to the {@code ChooserTargetService}, add a
|
||||||
|
{@code <meta-data>} element with the name
|
||||||
|
{@code "android.service.chooser.chooser_target_service"} in your app manifest.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="id">Feature item 2</h3>
|
<pre>
|
||||||
|
<activity android:name=".MyShareActivity”
|
||||||
|
android:label="@string/share_activity_label">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data
|
||||||
|
android:name="android.service.chooser.chooser_target_service"
|
||||||
|
android:value=".ChooserTargetService" />
|
||||||
|
</activity>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="voice-interactions">Voice Interactions</h2>
|
||||||
<p>
|
<p>
|
||||||
Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
|
This release provides a new voice interaction API which, together with
|
||||||
alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
|
<a href="https://developers.google.com/voice-actions/" class="external-link">Voice Actions</a>,
|
||||||
jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
|
allows you to build conversational voice experiences into your apps. Call the
|
||||||
turducken. Tongue brisket ham shoulder:
|
{@code android.app.Activity.isVoiceInteraction()} method to determine if your activity was
|
||||||
|
started in response to a voice action. If so, your app can use the
|
||||||
|
{@code android.app.VoiceInteractor} class to request a voice confirmation from the user, select
|
||||||
|
from a list of options, and more.</p>
|
||||||
|
<p>To learn more about implementing voice actions, see the voice interaction API
|
||||||
|
<a href="https://developers.google.com/voice-actions/interaction/"
|
||||||
|
class="external-link">guide</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="id">Feature Group 2</h2>
|
<h2 id="bluetooth-stylus">Bluetooth Stylus Support</h2>
|
||||||
|
<p>The M release provides improved support for user input using a Bluetooth stylus. If the user
|
||||||
|
touches a stylus with a button on the screen of your app, the
|
||||||
|
{@link android.view.MotionEvent#getToolType(int) getTooltype()} method now returns
|
||||||
|
{@code TOOL_TYPE_STYLUS}. The {@link android.view.MotionEvent#getButtonState() getButtonState()}
|
||||||
|
method returns {@link android.view.MotionEvent#BUTTON_SECONDARY} when the user
|
||||||
|
presses the primary stylus button. If the stylus has a second button, the same method returns
|
||||||
|
{@link android.view.MotionEvent#BUTTON_TERTIARY} when the user presses it. If the user presses
|
||||||
|
both buttons simultaneously, the method returns both these values. In addition, the system reports
|
||||||
|
the user button-press action to the new {@code View.onStylusButtonPressListener} and
|
||||||
|
{@code GestureDetector.OnStylusButtonPressListener} callbacks in your activity, if you have
|
||||||
|
registered these listeners in your app.</p>
|
||||||
|
|
||||||
<h3 id="id">Feature item 1</h3>
|
<h2 id="audio">New Audio Features</h2>
|
||||||
|
|
||||||
<p>
|
|
||||||
Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
|
|
||||||
alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
|
|
||||||
jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
|
|
||||||
turducken. Tongue brisket ham shoulder:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="id">Feature item 2</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Bacon ipsum dolor amet landjaeger capicola tail sausage shank swine biltong pork andouille t-bone
|
|
||||||
alcatra chicken. Strip steak bacon tongue beef bresaola landjaeger. Shankle boudin pork belly
|
|
||||||
jowl pig. Rump swine ham hock frankfurter pork shankle. Shank corned beef alcatra doner flank
|
|
||||||
turducken. Tongue brisket ham shoulder:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
<p>This release adds enhancements to audio processing on Android, including: </p>
|
||||||
|
<ul>
|
||||||
|
<li>Support for the <a href="http://en.wikipedia.org/wiki/MIDI" class="external-link">MIDI</a>
|
||||||
|
protocol, with the new {@code android.media.midi} APIs. Use these APIs to send and receive MIDI
|
||||||
|
events.</li>
|
||||||
|
<li>New {@code android.media.AudioRecord.Builder} and {@code android.media.AudioTrack.Builder}
|
||||||
|
classes to create digital audio capture and playback objects respectively, and configure audio
|
||||||
|
source and sink properties to override the system defaults.</li>
|
||||||
|
<li>API hooks for associating audio and input devices. This is particularly useful if your app
|
||||||
|
allows users to start a voice search from a game controller or remote control connected to Android
|
||||||
|
TV. The system invokes the new {@code android.app.Activity.onSearchRequested()} callback when the
|
||||||
|
user starts a search. To determine if the user's input device has a built-in microphone, retrieve
|
||||||
|
the {@link android.view.InputDevice} object from that callback, then call the new
|
||||||
|
{@code InputDevice.hasMic()} method.</li>
|
||||||
|
<li>New {@code android.media.AudioDevicesManager} class which lets you retrieve a list of all
|
||||||
|
attached source and sink audio devices. You can also specify an
|
||||||
|
{@code android.media.OnAudioDeviceConnectionListener} object if you want your app to be notified
|
||||||
|
when an audio device is connected or disconnected.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="afw">New Android for Work Features</h2>
|
||||||
|
<p>This release includes the following new APIs for Android for Work:</p>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Enhanced controls for Corporate-Owned, Single-Use devices:</strong> The Device Owner
|
||||||
|
can now control the following settings to improve management of
|
||||||
|
Corporate-Owned, Single-Use (COSU) devices:
|
||||||
|
<ul>
|
||||||
|
<li>Disable or re-enable the keyguard with the
|
||||||
|
{@code DevicePolicyManager.setKeyguardEnabledState()} method.</li>
|
||||||
|
<li>Disable or re-enable the status bar (including quick settings, notifications, and the
|
||||||
|
navigation swipe-up gesture that launches Google Now) with the
|
||||||
|
{@code DevicePolicyManager.setStatusBarEnabledState()} method.</li>
|
||||||
|
<li>Disable or re-enable safe boot with the {@link android.os.UserManager} constant
|
||||||
|
{@code DISALLOW_SAFE_BOOT}.</li>
|
||||||
|
<li>Prevent the screen from turning off while plugged in with the
|
||||||
|
{@link android.provider.Settings.Global} constant {@code STAY_ON_WHILE_PLUGGED_IN}.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><strong>Silent install and uninstall of apps by Device Owner:</strong> A Device Owner can now
|
||||||
|
silently install and uninstall applications using the {@link android.content.pm.PackageInstaller}
|
||||||
|
APIs, independent of Google Play for Work. You can now provision devices through a Device Owner that
|
||||||
|
fetches and installs apps without user interaction. This feature is useful for enabling one-touch
|
||||||
|
provisioning of kiosks or other such devices without activating a Google account.</li>
|
||||||
|
<li><strong>Silent enterprise certificate access: </strong> When an app calls
|
||||||
|
{@link android.security.KeyChain#choosePrivateKeyAlias(android.app.Activity,android.security.KeyChainAliasCallback,java.lang.String[],java.security.Principal[],java.lang.String,int,java.lang.String) choosePrivateKeyAlias()},
|
||||||
|
prior to the user being prompted to select a certificate, the Profile or Device Owner can now call
|
||||||
|
the {@code DeviceAdminReceiver.onChoosePrivateKeyAlias()} method to provide the alias silently to
|
||||||
|
the requesting application. This feature lets you grant managed apps access to certificates
|
||||||
|
without user interaction.</li>
|
||||||
|
<li><strong>Auto-acceptance of system updates.</strong> By setting a system update policy with
|
||||||
|
{@code DevicePolicyManager.setSystemUpdatePolicy()}, a Device Owner can now auto-accept a system
|
||||||
|
update, for instance in the case of a kiosk device, or postpone the update and prevent it being
|
||||||
|
taken by the user for up to 30 days. Furthermore, an administrator can set a time window in which an
|
||||||
|
update must be taken, for example during the hours when a kiosk device is not in use. When a
|
||||||
|
system update is available, the system checks if the Work Policy Controller app has set a system
|
||||||
|
update policy, and behaves accordingly.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Delegated certificate installation.</strong> A Profile or Device Owner can now grant a
|
||||||
|
third-party app the ability to call these {@link android.app.admin.DevicePolicyManager} certificate
|
||||||
|
management APIs:
|
||||||
|
<ul>
|
||||||
|
<li>{@link android.app.admin.DevicePolicyManager#getInstalledCaCerts(android.content.ComponentName)
|
||||||
|
getInstalledCaCerts()}</li>
|
||||||
|
<li>{@link android.app.admin.DevicePolicyManager#hasCaCertInstalled(android.content.ComponentName,byte[])
|
||||||
|
hasCaCertInstalled()}</li>
|
||||||
|
<li>{@link android.app.admin.DevicePolicyManager#installCaCert(android.content.ComponentName,byte[])
|
||||||
|
installCaCert()}</li>
|
||||||
|
<li>{@link android.app.admin.DevicePolicyManager#uninstallCaCert(android.content.ComponentName,byte[])
|
||||||
|
uninstallCaCert()}</li>
|
||||||
|
<li>{@link android.app.admin.DevicePolicyManager#uninstallAllUserCaCerts(android.content.ComponentName)
|
||||||
|
uninstallAllUserCaCerts()}</li>
|
||||||
|
<li>{@link android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName,java.security.PrivateKey,java.security.cert.Certificate,java.lang.String)
|
||||||
|
installKeyPair()}</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><strong>Enterprise factory reset protection.</strong> When provisioning a Device Owner, you can
|
||||||
|
now configure parameters for bypassing Factory Reset Protection (FRP), by setting the
|
||||||
|
{@code DeviceManagerPolicy.EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS} bundle. An NFC Programmer
|
||||||
|
app can provide these parameters after a device has been reset to bypass FRP and provision the device,
|
||||||
|
without requiring the previously configured Google account. If you don't modify these parameters,
|
||||||
|
FRP remains in-place and prevents the device from being activated without the previously activated
|
||||||
|
Google credentials.</li>
|
||||||
|
<li><strong>Data usage tracking.</strong> A Profile or Device Owner can now query for the data
|
||||||
|
usage statistics visible in <em>Settings > Data</em> usage by using the new
|
||||||
|
{@code android.app.usage.NetworkStatsManager} methods. Profile Owners are automatically granted
|
||||||
|
permission to query data on the profile they manage, while Device Owners get access to usage data
|
||||||
|
of the managed primary user.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<p class="note">
|
<p class="note">
|
||||||
For a detailed view of all API changes in the M Developer Preview, see the <a href=
|
For a detailed view of all API changes in the M Developer Preview, see the <a href=
|
||||||
|
|||||||
300
docs/html/preview/backup/index.jd
Normal file
300
docs/html/preview/backup/index.jd
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
page.title=Automatic App Data Backup
|
||||||
|
page.tags=backup
|
||||||
|
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Users often invest significant time and effort collecting data and setting preferences within
|
||||||
|
apps. Preserving that data for users if they replace a broken device or upgrade to a new one is
|
||||||
|
an important part of ensuring a great user experience. The Android M Preview system helps ensure
|
||||||
|
a good experience for users in this circumstances by automatically backing up app data to the
|
||||||
|
cloud.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This behavior is enabled by default for all apps installed on devices running Android M or
|
||||||
|
higher. No additional app code is required. The system provides users with the ability opt out of
|
||||||
|
automatic data backups for individual apps. You can also choose to limit what data from your app
|
||||||
|
is backed up.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This document describes the new system behavior and how to specify what data is backed up for
|
||||||
|
your app.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Overview</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The automatic backup feature preserves the data your app creates on a user device by uploading to
|
||||||
|
the user’s Google Drive account and encrypting it. There is no charge to you or the user for data
|
||||||
|
storage and the saved data does not count towards the user's personal Drive quota. During the M
|
||||||
|
Preview period, users can store up to 25MB per Android app.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Automatic backups occur every 24 hours, when the device is idle, charging, and connected to a
|
||||||
|
Wi-Fi network. When these conditions are met, the Backup Manager service uploads all available
|
||||||
|
backup data to the cloud. When the user transitions to a new device, or uninstalls and reinstalls
|
||||||
|
the backed up application, a restore operation will take place, copying the backed up data into
|
||||||
|
the newly installed application’s data directory.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Automatically Excluded Data Files</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Not all app data should be backed up, such as temporary files and caches, so the automatic backup
|
||||||
|
service excludes certain data files by default:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Files in the directories referred to by the <code><a href=
|
||||||
|
"{@docRoot}reference/android/content/Context.html#getCacheDir()">getCacheDir()</a></code> and
|
||||||
|
<code><a href=
|
||||||
|
"{@docRoot}reference/android/content/ContextWrapper.html#getCodeCacheDir()">getCodeCacheDir()</a></code>
|
||||||
|
methods.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>Files located on external storage, unless they reside in the directory referred to by the
|
||||||
|
<code><a href=
|
||||||
|
"{@docRoot}reference/android/content/Context.html#getExternalFilesDir(java.lang.String)">getExternalFilesDir()</a></code>
|
||||||
|
method.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>Files located in the directory referred to by the <code><a href=
|
||||||
|
"{@docRoot}reference/android/content/Context.html#getNoBackupFilesDir()">getNoBackupFilesDir()</a></code>
|
||||||
|
method.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Configuring Data Backup</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The data created by any app installed on an M device is backed up, except for the automatically
|
||||||
|
excluded files listed in the previous section. You can further limit and configure what data gets
|
||||||
|
backed up from your app using settings in your app manifest.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Including or Excluding Data</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Depending on what data your application needs and how you save it, you may need to set specific
|
||||||
|
rules for including or excluding certain files or directories. The automatic backup service
|
||||||
|
supports setting these backup rules through use of an XML configuration file and the app
|
||||||
|
manifest. In the app manifest, you can specify a backup scheme configuration file as shown in the
|
||||||
|
following example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="com.my.appexample">
|
||||||
|
<uses-sdk android:minSdkVersion="9"/>
|
||||||
|
<uses-sdk android:targetSdkVersion="android-MNC"/>
|
||||||
|
<application ...
|
||||||
|
<strong> android:fullBackupContent="@xml/mybackupscheme"></strong>
|
||||||
|
</application>
|
||||||
|
...
|
||||||
|
</manifest>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In this example code, the android:fullBackupContent attribute specifies an XML file, located in
|
||||||
|
the <code>res/xml/</code> directory of your app development project, named
|
||||||
|
<code>mybackupscheme.xml</code>. This configuration file can include rules for what files are
|
||||||
|
backed up. The following example code shows a configuration file that excludes a specific file
|
||||||
|
from backups:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<full-backup-content>
|
||||||
|
<exclude domain="database" path="device_info.db"/>
|
||||||
|
</full-backup-content>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This backup configuration only excludes a specific database file from being backed up. All other
|
||||||
|
files are backed up.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4>Backup Configuration Syntax</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The backup service configuration allows you to specify what files to include or exclude from
|
||||||
|
backup. The syntax for the data backup configuration xml file is as follows:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<full-backup-content>
|
||||||
|
<include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" />
|
||||||
|
<exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" />
|
||||||
|
</full-backup-content>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following elements and attributes allow you to specify the files to include and exclude from
|
||||||
|
backup:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code><include></code>. Use this element if you want to specify a set of resources to
|
||||||
|
back up, instead of having the system back up all data in your app by default. When you specify
|
||||||
|
an <code><include></code> tag, the system backs up only the resources specified with this
|
||||||
|
element.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code><exclude></code>. Use this element to specify a set of resources to exclude from
|
||||||
|
backup. The system backs up all data in your app, except for resources specified with this
|
||||||
|
element.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>domain.</code> The type of resource you want to include or exclude from backup. The valid
|
||||||
|
values you can specify for this attribute include:
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li style="list-style: none">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>root</code>. Specifies that the resource is in the app’s root directory.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>file</code>. Corresponds to a resource in the directory returned by the
|
||||||
|
<code><a href="{@docRoot}reference/android/content/Context.html#getFilesDir()">getFilesDir()</a></code>
|
||||||
|
method.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>database</code>. Corresponds to a database returned by the <code><a href=
|
||||||
|
"{@docRoot}reference/android/content/Context.html#getDatabasePath(java.lang.String)">getDatabasePath()</a></code>
|
||||||
|
method or by using the <code><a href=
|
||||||
|
"{@docRoot}reference/android/database/sqlite/SQLiteOpenHelper.html">SQLiteOpenHelper</a></code>
|
||||||
|
class.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>sharedpref</code>. Corresponds to a <code><a href=
|
||||||
|
"{@docRoot}reference/android/content/SharedPreferences.html">SharedPreferences</a></code>
|
||||||
|
object returned by the <code><a href=
|
||||||
|
"{@docRoot}reference/android/content/Context.html#getSharedPreferences(java.lang.String,%20int)">
|
||||||
|
getSharedPreferences()</a></code> method.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>external</code>. Specifies that the resource is in external storage, and corresponds
|
||||||
|
to a file in the directory returned by the <code><a href=
|
||||||
|
"{@docRoot}reference/android/content/Context.html#getExternalFilesDir(java.lang.String)">getExternalFilesDir()</a></code>
|
||||||
|
method.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>path</code>. The file path to a resource that you want to include or exclude from
|
||||||
|
backup.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Prohibiting Data Backups</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can choose to prevent automatic backups of any of your app data by setting the
|
||||||
|
<code>android:allowBackup</code> attribute to <code>false</code> in the application element of
|
||||||
|
your manifest. This setting is illustrated in the following example code:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="com.my.appexample">
|
||||||
|
<uses-sdk android:minSdkVersion="9"/>
|
||||||
|
<uses-sdk android:targetSdkVersion="android-MNC"/>
|
||||||
|
<application ...
|
||||||
|
<strong> android:allowBackup="false"></strong>
|
||||||
|
</application>
|
||||||
|
...
|
||||||
|
</manifest>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Testing Backup Configuration</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Once you have created a backup configuration, you should test it to make sure your app saves data
|
||||||
|
and can be restored properly.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Enabling Backup Logging</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To help determine how the backup feature is parsing your XML file, enable logging before
|
||||||
|
performing a test backup:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>$ adb shell setprop log.tag.BackupXmlParserLogging VERBOSE</pre>
|
||||||
|
|
||||||
|
<h4>Testing Backup</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To manually enable a backup, call the following command, specifying the package name for your app
|
||||||
|
as the <code><PACKAGE></code> parameter:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>$ adb shell bmgr fullbackup <PACKAGE></pre>
|
||||||
|
|
||||||
|
<h4>Testing Restore</h4>
|
||||||
|
<p>
|
||||||
|
To manually initiate a restore after your app data is backed-up, call the following command,
|
||||||
|
specifying the package name for your app as the <code><PACKAGE></code> parameter:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>$ adb shell bmgr restore <PACKAGE></pre>
|
||||||
|
|
||||||
|
<p class="warning">
|
||||||
|
<b>Warning:</b> This action stops your app and wipes its data before performing the restore
|
||||||
|
operation.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You initiate the restore process for your app by uninstalling and reinstalling your app. The app
|
||||||
|
data is automatically restored from the cloud once the app installation is complete.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h4>Troubleshooting Backups</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you run into issues, clear the backup data and associated metadata by calling this command.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>$ adb shell bmgr wipe <TRANSPORT> <PACKAGE></pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <code><TRANSPORT></code> value must be prefixed by <code>com.google.android.gms</code>.
|
||||||
|
To get the list of transports, call the following command:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>$ adb shell bmgr list transports</pre>
|
||||||
|
|
||||||
|
<h2>Known Issues</h2>
|
||||||
|
|
||||||
|
<p>The following are known issues with the automatic backup service:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>For apps that use Google Cloud Messaging for push notifications, there is a known issue where
|
||||||
|
backing up the registration id returned by Google Cloud Messaging registration can break push
|
||||||
|
notifications for the restored application. It is important to query the API for a new
|
||||||
|
registration id after being installed on a new device - which will not be the case if the old
|
||||||
|
registration id was backed up. To avoid this, exclude the registration id from the set of backed
|
||||||
|
up files.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
352
docs/html/preview/features/runtime-permissions.jd
Normal file
352
docs/html/preview/features/runtime-permissions.jd
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
page.title=Android M Preview Runtime Permissions
|
||||||
|
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The M Developer Preview introduces a new app permissions model which makes it
|
||||||
|
less frustrating for users to install and upgrade apps. If an app running on
|
||||||
|
M supports the new permissions model, the user does not have to grant any
|
||||||
|
permissions when they install or upgrade the app. Instead, the app requests
|
||||||
|
permissions as they are needed, and the system shows a dialog to the user
|
||||||
|
asking for the permission.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If an app supports the new permissions model, it can still be installed and
|
||||||
|
run on devices running older versions of Android, using the old permissions
|
||||||
|
model on those devices.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
Overview
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If an app's target SDK version is the M developer preview, that indicates
|
||||||
|
that the app uses the new permissions model:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Permissions are divided into <em>permission groups</em>, based on their
|
||||||
|
functionality. For example, all permissions relating to the camera and photo
|
||||||
|
roll are grouped in the Camera permission group,
|
||||||
|
[link]android.permission-group.CAMERA[/link].
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>The app declares all the permissions it needs in the manifest, as in
|
||||||
|
earlier Android platforms.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>When the user installs or updates the app, the app is granted just those
|
||||||
|
permissions it requests that fall under <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_NORMAL">
|
||||||
|
<code>PROTECTION_NORMAL</code></a>, as well as signature and system permissions, as
|
||||||
|
described below. The user is <em>not</em> prompted to grant any permissions
|
||||||
|
at this time.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>When the app needs to perform any action that requires a permission, it
|
||||||
|
first checks whether it has that permission already. If it does not, it
|
||||||
|
requests to be granted that permission.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>When the app requests a permission, the system shows a dialog box to the
|
||||||
|
user, then calls the app's callback function to notify it whether the
|
||||||
|
permission was granted. If a user grants a permission, the app is given all
|
||||||
|
permissions in that permission's functional area that were declared in the
|
||||||
|
app manifest.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>If the app is not granted an appropriate permission, it should handle the
|
||||||
|
failure cleanly. For example, if the permission is just needed for an added
|
||||||
|
feature, the app can disable that feature. If the permission is essential for
|
||||||
|
the app to function, the app might disable all its functionality and inform
|
||||||
|
the user that they need to grant that permission.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>Users can always go to the app's <b>Settings</b> screen and turn on or
|
||||||
|
off any of the app's permissions.
|
||||||
|
<!-- insert screenshot of settings screen-->
|
||||||
|
If a user turns off an app's permissions, the app is
|
||||||
|
<em>not</em> notified.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
System Apps and Signature Permissions
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Ordinarily, an app is just granted the <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_NORMAL">
|
||||||
|
<code>PROTECTION_NORMAL</code></a> permissions when it is installed. However,
|
||||||
|
under some circumstances the app is granted more permissions:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>If an app is part of the system image, it is automatically granted all
|
||||||
|
the permissions listed in its manifest.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>Apps are granted all permissions listed in the manifest that fall under
|
||||||
|
<a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_SIGNATURE">
|
||||||
|
PROTECTION_SIGNATURE</a>, if the app's signature matches the signature of
|
||||||
|
the app that declares the permissions.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In both cases, the user can still revoke permissions at any time by going to
|
||||||
|
the app's <b>Settings</b> screen, so the app should continue to check for
|
||||||
|
permissions at run time and request them if necessary.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Forwards and Backwards Compatibility
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If an app does not target the M developer preview, it continues to use the
|
||||||
|
old permissions model even on M devices. When the app is installed, the
|
||||||
|
system asks the user to grant all permissions listed in the app's manifest.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If an app using the new permissions model is run on a pre-M device, the
|
||||||
|
system treats it the same as any other app. Once again, the system asks the
|
||||||
|
user to grant all declared permissions at install time.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="">Coding for Runtime Permissions</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If your app targets the new M Developer Preview, you must use the new
|
||||||
|
permissions model. This means that in addition to declaring your needed
|
||||||
|
permissions in the manifest, you must also check to see if you have the
|
||||||
|
permissions at run time, and request the permissions if you do not already
|
||||||
|
have them.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Enabling the New Permissions Model
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To enable the new M Developer Preview permissions model, set the app's
|
||||||
|
<a href=
|
||||||
|
"http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target">
|
||||||
|
targetSdkVersion</a> attribute to "M". Doing this enables all the new
|
||||||
|
permissions features.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- TODO: Insert manifest snippet -->
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Designating a Permission for M Only
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can use the new <code><uses-permission-sdk-m></code> element in the
|
||||||
|
app manifest to indicate that a permission is only needed on the M platform.
|
||||||
|
If you declare a permission this way, then whenever the app is installed on
|
||||||
|
an older device, the user is not prompted to grant the permission and the
|
||||||
|
permission is not granted to the app. This allows you to add new permissions
|
||||||
|
to updated versions of your app without forcing users to grant permissions
|
||||||
|
when they install the update.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If the app is running on a device with the M developer preview,
|
||||||
|
<code><uses-permission-sdk-m></code> behaves the same as
|
||||||
|
<code><uses-permission></code>. The user is not prompted to grant any
|
||||||
|
permissions when the app is installed, and the app requests permissions as
|
||||||
|
they are needed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="prompting">
|
||||||
|
Prompting for Permissions on the M Preview
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If your app uses the new M Developer Preview permissions model, the user is
|
||||||
|
not asked to grant all permissions when the app is first launched on a device
|
||||||
|
running the M Preview. Instead, your app requests permissions as they are
|
||||||
|
needed. When your app requests a permission, the system shows a dialog to the
|
||||||
|
user.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
An app should follow this workflow to request permissions on an Android M
|
||||||
|
device. The device can check what platform it's running on by checking the
|
||||||
|
value of {@link android.os.Build.VERSION#SDK_INT Build.VERSION.SDK_INT}. If
|
||||||
|
the device is running the M Developer Preview, {@link
|
||||||
|
android.os.Build.VERSION#SDK_INT SDK_INT} is 23.
|
||||||
|
<!-- TODO: Confirm this number -->
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li>When the user tries to do something that requires a permission, the app
|
||||||
|
checks to see if it currently has permission to perform this operation. To do
|
||||||
|
this, the app calls
|
||||||
|
<a href="https://android-preview.googleplex.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)"><code>Context.CheckSelfPermission(<em>permission_name</em>)</code></a> . The
|
||||||
|
app should do this even if it knows the user has already granted that
|
||||||
|
permission, since the user can revoke an app's permissions at any time. For
|
||||||
|
example, if a user wants to use an app to take a picture, the app calls
|
||||||
|
<a href="https://android-preview.googleplex.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)"><code>Context.CheckSelfPermission(Manifest.permission.CAMERA)</code></a>.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- TODO: Full list of permissions (or link to that list),
|
||||||
|
and how they break down by functional area]-->
|
||||||
|
|
||||||
|
<li>If the permission is not already granted to the app, the app calls
|
||||||
|
<a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
|
||||||
|
<code>requestPermissions()</code></a> to request the
|
||||||
|
appropriate permission or permissions. This method functions
|
||||||
|
asynchronously.
|
||||||
|
<!-- TODO: insert code snippet showing permission check and request -->
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>The system presents a dialog box to the user.
|
||||||
|
<!-- TODO: insert screenshot of permissions dialog box -->
|
||||||
|
When the user responds, the system calls <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#onRequestPermissionsResult(int,%20java.lang.String[],%20int[])">
|
||||||
|
<code>Activity.onRequestPermissionsResult()</code></a> with the
|
||||||
|
results; your app needs to override that method. The callback is passed the
|
||||||
|
same request code you passed to <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
|
||||||
|
<code>requestPermissions()</code></a>.
|
||||||
|
<!-- TODO: Insert code snippet of callback method -->
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>If the user grants a permission, the app is given all permissions
|
||||||
|
in that functional area that are listed in the app manifest.
|
||||||
|
If the request is denied, you should take appropriate action. For
|
||||||
|
example, you might disable any menu actions that depend on this permission.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
When the system asks the user to grant a permission, the user has the option
|
||||||
|
of telling the system not to ask for that permission again. In that case,
|
||||||
|
when an app asks for that permission with <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
|
||||||
|
<code>requestPermissions()</code></a>, the
|
||||||
|
system immediately denies the request. For this reason, your app cannot
|
||||||
|
assume that any direct interaction with the user has taken place.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If your app runs on a device that has SDK 22 or lower, the app uses the old
|
||||||
|
permissions model. When the user installs the app, they are prompted to grant
|
||||||
|
all the permissions your app requests in its manifest, except for those
|
||||||
|
permissions which are labeled with <code><uses-permission-sdk-m></code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="">Best Practices</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The new permissions model gives users a smoother experience, and makes it
|
||||||
|
easier for them to install apps and feel comfortable with what the apps are
|
||||||
|
doing. We recommend the following best practices to take full advantage of
|
||||||
|
the new model.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Don't Overwhelm the User
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you confront the user with a lot of permissions requests at once, you may
|
||||||
|
overwhelm the user and cause them to quit your app. Instead, you should ask
|
||||||
|
for permissions as you need them.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In some cases, one or more permissions might be absolutely essential to your
|
||||||
|
app. In that case, it might make sense to ask for all the permissions as soon
|
||||||
|
as the app launches.
|
||||||
|
<!-- TODO: insert screenshot of dialog box asking for several permissions -->
|
||||||
|
For example, if you make a photography app, the app would
|
||||||
|
need access to the device camera. When the user launches the app for the
|
||||||
|
first time, they won't be surprised to be asked to give permission to use the
|
||||||
|
camera. But if the same app also had a feature to share photos with the
|
||||||
|
user's contacts, you probably should <em>not</em> ask for that permission at
|
||||||
|
first launch. Instead, wait until the user tries to use the "sharing" feature
|
||||||
|
and ask for the permission then.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If your app provides a tutorial, it may make sense to request app's essential
|
||||||
|
permissions at the end of the tutorial sequence.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Explain Why You Need Permissions
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The permissions screen shown by the system when you call <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
|
||||||
|
<code>requestPermissions()</code></a> says what permission your app wants,
|
||||||
|
but doesn't say why you want it. In some cases, the user may find that
|
||||||
|
puzzling. It's a good idea to explain to the user why your app wants the
|
||||||
|
permissions before you call <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
|
||||||
|
<code>requestPermissions()</code></a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For example, a photography app might want to use location services, so it can
|
||||||
|
geotag the photos. A typical user might not understand that a photo can
|
||||||
|
contain location information, and would be puzzled why their photography app
|
||||||
|
wanted to know the location. So in this case, it's a good idea for the app to
|
||||||
|
tell the user about this feature <em>before</em> calling
|
||||||
|
<a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
|
||||||
|
<code>requestPermissions()</code></a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As noted, one way to do this is to incorporate these requests into an app
|
||||||
|
tutorial. The tutorial can show each of the app's features in turn, and as it
|
||||||
|
does this, it can explain what permissions are needed. For example, the
|
||||||
|
photography app's tutorial demonstrate its "share photos with your contacts"
|
||||||
|
feature, then tell the user that they'll need to give permission for the app
|
||||||
|
to see the user's contacts, and <em>then</em> call <a href=
|
||||||
|
"https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)">
|
||||||
|
<code>requestPermissions()</code></a>
|
||||||
|
to get that access. Of course, some users will want to skip the tutorial, so
|
||||||
|
you'll still need to check for and request permissions during the app's
|
||||||
|
normal operation.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
Opt Out If Necessary
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Until you are ready to use the new permissions model, you can opt out simply
|
||||||
|
by setting your app's <a href=
|
||||||
|
"http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target">
|
||||||
|
targetSdkVersion</a> to 22 or less. If you do this, the system will use the
|
||||||
|
old permissions model. When the user downloads the app, they will be prompted
|
||||||
|
to grant all the permissions listed in the manifest.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
With the M Developer Preview, users can turn off permissions for <em>any</em>
|
||||||
|
app from the app's Settings page, regardless of what SDK version the app
|
||||||
|
targets. For this reason, it's a good idea to follow the steps described in
|
||||||
|
<a href="#prompting">"Prompting for Permissions on the M Preview"</a> even if
|
||||||
|
your app doesn't fully support the new permissions model.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="note">
|
||||||
|
<strong>Note:</strong> If a user turns off permissions for a legacy app, the system
|
||||||
|
silently disables the appropriate functionality. When the app attempts to
|
||||||
|
perform an operation that requires that permission, the operation will not
|
||||||
|
necessarily cause an exception. Instead, it might return an empty data set or
|
||||||
|
otherwise signal an error.
|
||||||
|
</p>
|
||||||
BIN
docs/html/preview/images/direct-share-screen.png
Normal file
BIN
docs/html/preview/images/direct-share-screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
BIN
docs/html/preview/images/direct-share-screen_2x.png
Normal file
BIN
docs/html/preview/images/direct-share-screen_2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
BIN
docs/html/preview/images/fingerprint-screen.png
Normal file
BIN
docs/html/preview/images/fingerprint-screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
BIN
docs/html/preview/images/fingerprint-screen_2x.png
Normal file
BIN
docs/html/preview/images/fingerprint-screen_2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
docs/html/preview/images/text-selection.gif
Normal file
BIN
docs/html/preview/images/text-selection.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
@@ -15,10 +15,34 @@
|
|||||||
API Overview</a></div>
|
API Overview</a></div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-section">
|
||||||
|
<div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/api-changes.html">
|
||||||
|
Behavior Changes</a></div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-section">
|
||||||
|
<div class="nav-section-header empty">
|
||||||
|
<a href="<?cs var:toroot ?>preview/features/runtime-permissions.html">
|
||||||
|
Runtime Permissions</a></div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-section">
|
||||||
|
<div class="nav-section-header empty">
|
||||||
|
<a href="<?cs var:toroot ?>preview/backup/index.html">
|
||||||
|
Automatic Backups</a></div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-section">
|
||||||
|
<div class="nav-section-header empty">
|
||||||
|
<a href="<?cs var:toroot ?>preview/data-binding/guide.html">
|
||||||
|
Data Binding</a></div>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/samples.html">
|
<div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/samples.html">
|
||||||
Samples</a></div>
|
Samples</a></div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/reference.html">
|
<div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/reference.html">
|
||||||
Reference</a></div>
|
Reference</a></div>
|
||||||
|
|||||||
@@ -13,25 +13,72 @@ page.title=Samples
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="id">Sample 1</h3>
|
<h3 id="RuntimePermissions">Runtime Permissions</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This sample demonstrates how to turducken frankfurter boudin, ham brisket alcatra kielbasa pork
|
Android M changes the way system permissions work. Users are asked to approve permission
|
||||||
loin pork. Jowl kielbasa kevin, sausage landjaeger corned beef cow spare ribs pastrami leberkas
|
requests at runtime instead of during installation. This sample shows how to request these
|
||||||
drumstick.
|
permissions.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><a href="#">Get it on GitHub</a></p>
|
<p><a href="https://github.com/googlesamples/android-RuntimePermissions">Get it on GitHub</a></p>
|
||||||
|
|
||||||
|
<h3 id="RuntimePermissionsCompat">Runtime Permissions Compat</h3>
|
||||||
<h3 id="id">Sample 2</h3>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This sample demonstrates how to turducken frankfurter boudin, ham brisket alcatra kielbasa pork
|
To support devices on previous versions of Android, this sample demonstrates how to work with the
|
||||||
loin pork. Jowl kielbasa kevin, sausage landjaeger corned beef cow spare ribs pastrami leberkas
|
new permissions system introduced in Android M by using a support library.
|
||||||
drumstick.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><a href="#">Get it on GitHub</a></p>
|
<p><a href="https://github.com/googlesamples/android-RuntimePermissionsCompat">Get it on
|
||||||
|
GitHub</a></p>
|
||||||
|
|
||||||
|
<h3 id="VoiceCamera">Voice Camera</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This sample demonstrates how to implement the "OK Google, take a selfie" voice command and confirm
|
||||||
|
the user intent with the <code>VoiceInteraction</code> API.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="https://github.com/googlesamples/android-VoiceCamera">Get it on GitHub</a></p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="DeepLinkSharing">Deep Link Sharing</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This sample shows how to handle content shared via deep links in your app. It demonstrates how to
|
||||||
|
implement the <code>ChooserTargetService</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="https://github.com/googlesamples/android-DeepLinkSharing">Get it on GitHub</a></p>
|
||||||
|
|
||||||
|
<h3 id="NotificationBuilder">Notification Builder</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This sample demonstrates the improved
|
||||||
|
<a href="{@docRoot}reference/android/app/Notification.html"><code>Notification</code></a>
|
||||||
|
memory footprint and simplified creation of notifications with custom views.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="https://github.com/googlesamples/android-NotificationBuilder">Get it on GitHub</a></p>
|
||||||
|
|
||||||
|
<h3 id="ActiveNotification">Active Notification</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This sample demonstrates how the
|
||||||
|
<a href="{@docRoot}reference/android/app/NotificationManager.html"><code>NotificationManager</code></a>
|
||||||
|
can tell you how many notifications your app is currently showing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="https://github.com/googlesamples/android-ActiveNotification">Get it on GitHub</a></p>
|
||||||
|
|
||||||
|
<h3 id="VoiceSynthesizer">Voice Synthesizer</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This sample demonstrates how to use the <code>NativeAudio</code> APIs to demonstrate low-latency
|
||||||
|
audio processing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="https://github.com/googlesamples/android-VoiceSynthesizer">Get it on GitHub</a></p>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -192,16 +192,18 @@ App</a> training lesson first.</a></p>
|
|||||||
|
|
||||||
<h2 id="setupHardware">Set Up Hardware and AVDs</h2>
|
<h2 id="setupHardware">Set Up Hardware and AVDs</h2>
|
||||||
|
|
||||||
<p>The Android M Developer Preview provides you with 32-bit system images
|
<p>The Android M Developer Preview provides you with system images
|
||||||
to flash the following devices:
|
to flash the following devices:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Nexus 5</li>
|
<li>Nexus 5</li>
|
||||||
<li>Nexus 7 Wi-Fi (version 2, released in 2013)</li>
|
<li>Nexus 6</li>
|
||||||
|
<li>Nexus 9</li>
|
||||||
|
<li>Nexus Player</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>In addition, you also get the emulator system images, which includes
|
<p>In addition, the Preview SDK provides emulator system images, which include
|
||||||
experimental 64-bit system images along with standard 32-bit system images.
|
experimental 64-bit system images along with standard 32-bit system images.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -213,37 +215,54 @@ folder.</p>
|
|||||||
|
|
||||||
<h3 id="installImage">Install the M Preview System Image</h3>
|
<h3 id="installImage">Install the M Preview System Image</h3>
|
||||||
|
|
||||||
<p class="warning"><b>Warning:</b> This is a preview version of the Android
|
<p class="warning"><b>Warning:</b> The following Android system images are
|
||||||
system image, and is subject to change. Your use of this system image is
|
previews and are subject to change. Your use of these system images is
|
||||||
governed by the Android SDK Preview License Agreement. The Android preview
|
governed by the Android SDK Preview License Agreement. The Android preview
|
||||||
system image is not a stable release, and may contain errors and defects that
|
system images are not stable releases, and may contain errors and defects that
|
||||||
can result in damage to your computer systems, devices, and data. The preview
|
can result in damage to your computer systems, devices, and data. The preview
|
||||||
Android system image is not subject to the same testing as the factory OS and
|
Android system images are not subject to the same testing as the factory OS and
|
||||||
can cause your phone and installed services and applications to stop working.
|
can cause your phone and installed services and applications to stop working.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Download and uncompress the Android Developer Preview package.
|
<li>Download and uncompress the Android Developer Preview package.
|
||||||
<table style="width:860px">
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Device</th>
|
<th scope="col">Device</th>
|
||||||
<th scope="col">Download</th>
|
<th scope="col">Download / Checksums</th>
|
||||||
<th scope="col">Checksum</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="hammerhead">
|
<tr id="hammerhead">
|
||||||
<td>Nexus 5 (GSM/LTE) <br>"hammerhead"</td>
|
<td>Nexus 5 (GSM/LTE) <br>"hammerhead"</td>
|
||||||
<td><a href="#top" onclick="onDownload(this)"
|
<td><a href="#top" onclick="onDownload(this)"
|
||||||
>hammerhead-lpv79-preview-ac1d8a8e.tgz</a></td>
|
>hammerhead-mpv79-preview-ac1d8a8e.tgz</a><br>
|
||||||
<td>MD5: <code>5a6ae77217978cb7b958a240c2e80b57</code>
|
MD5: 5a6ae77217978cb7b958a240c2e80b57<br>
|
||||||
<br>SHA-1: <code>ac1d8a8e4f4a1dca5864dc733caa940bffc28616</code></td>
|
SHA-1: ac1d8a8e4f4a1dca5864dc733caa940bffc28616
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="razor">
|
<tr id="shamu">
|
||||||
<td>Nexus 7 (Wifi) <br>"razor"</td>
|
<td>Nexus 6 <br>"shamu"</td>
|
||||||
<td><a href="#top" onclick="onDownload(this)"
|
<td><a href="#top" onclick="onDownload(this)"
|
||||||
>razor-lpv79-preview-d0ddf8ce.tgz</a></td>
|
>shamu-mpv79-preview-ac1d8a8e.tgz</a><br>
|
||||||
<td>MD5: <code>b293a5d3a4e07beabebcc0be85ad68a2</code>
|
MD5: 5a6ae77217978cb7b958a240c2e80b57<br>
|
||||||
<br><nobr>SHA-1: <code>d0ddf8ce733ba2a34279cdff8827fd604762c2342d</nobr></td>
|
SHA-1: ac1d8a8e4f4a1dca5864dc733caa940bffc28616
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="volantis">
|
||||||
|
<td>Nexus 9 <br>"volantis"</td>
|
||||||
|
<td><a href="#top" onclick="onDownload(this)"
|
||||||
|
>volantis-mpv79-preview-ac1d8a8e.tgz</a><br>
|
||||||
|
MD5: 5a6ae77217978cb7b958a240c2e80b57<br>
|
||||||
|
SHA-1: ac1d8a8e4f4a1dca5864dc733caa940bffc28616
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="fugu">
|
||||||
|
<td>Nexus Player <br>"fugu"</td>
|
||||||
|
<td><a href="#top" onclick="onDownload(this)"
|
||||||
|
>fugu-mpv79-preview-d0ddf8ce.tgz</a><br>
|
||||||
|
MD5: b293a5d3a4e07beabebcc0be85ad68a2<br>
|
||||||
|
SHA-1: d0ddf8ce733ba2a34279cdff8827fd604762c2342d
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</li>
|
</li>
|
||||||
@@ -278,11 +297,10 @@ image to your device.</p>
|
|||||||
<a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with AVD
|
<a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with AVD
|
||||||
Manager</a>. Use the following settings:
|
Manager</a>. Use the following settings:
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>Device:</b> Either Nexus 5 or Nexus 7</li>
|
<li><b>Device:</b> Nexus 5, Nexus 6, Nexus 9, or Nexus Player</li>
|
||||||
<li><b>Target:</b> <!-- Confirm exact text when we have final distro -->
|
<li><b>Target:</b>
|
||||||
Android M (Preview) - API Level M</li>
|
Android M (Preview) - API Level M</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- Confirm this works when you can download image through SDK manager! -->
|
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user