Merge branch 'mnc-mr-docs' into mnc-ub-dev

Large merge to reconnect automerger for docs branch to mainline.

 Conflicts:
	docs/html-intl/intl/es/index.jd
	docs/html-intl/intl/es/preview/download.jd
	docs/html-intl/intl/es/preview/index.jd
	docs/html-intl/intl/ja/index.jd
	docs/html-intl/intl/ja/preview/download.jd
	docs/html-intl/intl/ja/preview/index.jd
	docs/html-intl/intl/ko/index.jd
	docs/html-intl/intl/ko/preview/download.jd
	docs/html-intl/intl/ko/preview/index.jd
	docs/html-intl/intl/pt-br/index.jd
	docs/html-intl/intl/pt-br/preview/download.jd
	docs/html-intl/intl/pt-br/preview/index.jd
	docs/html-intl/intl/ru/index.jd
	docs/html-intl/intl/ru/preview/download.jd
	docs/html-intl/intl/ru/preview/index.jd
	docs/html-intl/intl/zh-cn/index.jd
	docs/html-intl/intl/zh-cn/preview/download.jd
	docs/html-intl/intl/zh-cn/preview/index.jd
	docs/html-intl/intl/zh-tw/index.jd
	docs/html-intl/intl/zh-tw/preview/download.jd
	docs/html-intl/intl/zh-tw/preview/index.jd
	docs/html/guide/topics/manifest/compatible-screens-element.jd
	docs/html/guide/topics/manifest/uses-feature-element.jd
	docs/html/preview/download.jd
	docs/html/preview/features/runtime-permissions.jd
	docs/html/sdk/index.jd
	docs/html/tools/revisions/studio.jd
	docs/html/tools/sdk/eclipse-adt.jd
	docs/html/tools/support-library/features.jd
	telephony/java/android/telephony/TelephonyManager.java

Bug: 28000173
Change-Id: Iacab0481175f1b32e0ac3bab98cde9e994100e94
This commit is contained in:
Trevor Johns
2016-04-05 19:43:35 -07:00
2121 changed files with 368238 additions and 97297 deletions

View File

@@ -948,6 +948,42 @@ $(static_doc_index_redirect): \
$(full_target): $(static_doc_index_redirect)
$(full_target): $(framework_built)
# ==== static html in the sdk, reference only ===============================
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
LOCAL_MODULE := offline-refonly
LOCAL_DROIDDOC_OPTIONS:=\
$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-offlinemode \
-title "Android SDK" \
-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
-sdkvalues $(OUT_DOCS) \
-hdf android.whichdoc offline \
-referenceonly
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-refonly
include $(BUILD_DROIDDOC)
static_doc_index_redirect := $(out_dir)/index.html
$(static_doc_index_redirect): \
$(LOCAL_PATH)/docs/docs-preview-index.html | $(ACP)
$(hide) mkdir -p $(dir $@)
$(hide) $(ACP) $< $@
$(full_target): $(static_doc_index_redirect)
$(full_target): $(framework_built)
# ==== docs for the web (on the androiddevdocs app engine server) =======================
include $(CLEAR_VARS)
@@ -1032,41 +1068,42 @@ LOCAL_DROIDDOC_OPTIONS:= \
-devsite \
-toroot / \
-hdf android.whichdoc online \
-useUpdatedTemplates \
-hdf devsite true
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-dev
include $(BUILD_DROIDDOC)
# ==== docs for the ndk =======================
# ==== site updates for docs (on the androiddevdocs app engine server) =======================
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
LOCAL_DROIDDOC_HTML_DIR:=docs/html-ndk
LOCAL_DROIDDOC_HTML_DIR:=$(framework_docs_LOCAL_DROIDDOC_HTML_DIR)
LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
# specify a second html input dir and an output path relative to OUT_DIR)
LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl/intl /
LOCAL_ADDITIONAL_HTML_DIR:=docs/html-intl /
LOCAL_MODULE := online-ndk
LOCAL_MODULE := online-sdk-dev
LOCAL_DROIDDOC_OPTIONS:= \
$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
-toroot / \
-hdf android.whichdoc online \
$(sample_groups) \
-useUpdatedTemplates \
-hdf android.hasSamples true \
-samplesdir $(samples_dir)
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-dev
include $(BUILD_DROIDDOC)
# ==== docs that have all of the stuff that's @hidden =======================
include $(CLEAR_VARS)

View File

@@ -186,7 +186,7 @@ import java.util.List;
*
* <p>An activity has essentially four states:</p>
* <ul>
* <li> If an activity in the foreground of the screen (at the top of
* <li> If an activity is in the foreground of the screen (at the top of
* the stack),
* it is <em>active</em> or <em>running</em>. </li>
* <li>If an activity has lost focus but is still visible (that is, a new non-full-sized
@@ -660,7 +660,7 @@ import java.util.List;
* independently of the activity lifecycle itself. An example may be a camera
* application that allows you to upload a picture to a web site. The upload
* may take a long time, and the application should allow the user to leave
* the application will it is executing. To accomplish this, your Activity
* the application while it is executing. To accomplish this, your Activity
* should start a {@link Service} in which the upload takes place. This allows
* the system to properly prioritize your process (considering it to be more
* important than other non-visible applications) for the duration of the
@@ -3784,28 +3784,10 @@ public class Activity extends ContextThemeWrapper
* result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}.
* </p>
* <p>
* A sample permissions request looks like this:
* The <a href="http://developer.android.com/samples/RuntimePermissions/index.html">
* RuntimePermissions</a> sample app demonstrates how to use this method to
* request permissions at run time.
* </p>
* <code><pre><p>
* private void showContacts() {
* if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
* != PackageManager.PERMISSION_GRANTED) {
* requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
* PERMISSIONS_REQUEST_READ_CONTACTS);
* } else {
* doShowContacts();
* }
* }
*
* {@literal @}Override
* public void onRequestPermissionsResult(int requestCode, String[] permissions,
* int[] grantResults) {
* if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS
* && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
* showContacts();
* }
* }
* </code></pre></p>
*
* @param permissions The requested permissions.
* @param requestCode Application specific request code to match with a result

View File

@@ -16,7 +16,7 @@ provide a {@link android.content.BroadcastReceiver} that receives the {@link
android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE} intent
and provide some metadata about the app widget. Android provides the
{@link android.appwidget.AppWidgetProvider} class, which extends {@link
android.content.BroadcastReceiver}, as a convenience class to define the app widget behavrio and aid
android.content.BroadcastReceiver}, as a convenience class to define the app widget behavior and aid
in handling the broadcasts.</p>
<p>App widget hosts are the containers in which widgets can be placed. Most of the look and feel

View File

@@ -115,7 +115,7 @@ import java.util.Set;
* </li>
* <li> <p><b>{@link #ACTION_VIEW} <i>tel:123</i></b> -- Display
* the phone dialer with the given number filled in. Note how the
* VIEW action does what what is considered the most reasonable thing for
* VIEW action does what is considered the most reasonable thing for
* a particular URI.</p>
* </li>
* <li> <p><b>{@link #ACTION_DIAL} <i>tel:123</i></b> -- Display
@@ -186,7 +186,7 @@ import java.util.Set;
*
* <p>There are a variety of standard Intent action and category constants
* defined in the Intent class, but applications can also define their own.
* These strings use java style scoping, to ensure they are unique -- for
* These strings use Java-style scoping, to ensure they are unique -- for
* example, the standard {@link #ACTION_VIEW} is called
* "android.intent.action.VIEW".</p>
*
@@ -339,7 +339,7 @@ import java.util.Set;
* &lt;action android:name="{@link #ACTION_EDIT android.intent.action.EDIT}" /&gt;
* &lt;action android:name="{@link #ACTION_PICK android.intent.action.PICK}" /&gt;
* &lt;category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
* &lt;data mimeType:name="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
* &lt;data android:mimeType="vnd.android.cursor.dir/<i>vnd.google.note</i>" /&gt;
* &lt;/intent-filter&gt;</pre>
* <p>This declares the things that the activity can do on a directory of
* notes. The type being supported is given with the &lt;type&gt; tag, where
@@ -358,7 +358,7 @@ import java.util.Set;
* &lt;category android:name="{@link #CATEGORY_DEFAULT android.intent.category.DEFAULT}" /&gt;
* &lt;data android:mimeType="vnd.android.cursor.item/<i>vnd.google.note</i>" /&gt;
* &lt;/intent-filter&gt;</pre>
* <p>This filter describes the ability return to the caller a note selected by
* <p>This filter describes the ability to return to the caller a note selected by
* the user without needing to know where it came from. The data type
* <code>vnd.android.cursor.item/vnd.google.note</code> is a URI from which
* a Cursor of exactly one (<code>vnd.android.cursor.item</code>) item can
@@ -1287,14 +1287,14 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.extra.ASSIST_INPUT_DEVICE_ID";
/**
* Activity Action: List all available applications
* Activity Action: List all available applications.
* <p>Input: Nothing.
* <p>Output: nothing.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
/**
* Activity Action: Show settings for choosing wallpaper
* Activity Action: Show settings for choosing wallpaper.
* <p>Input: Nothing.
* <p>Output: Nothing.
*/
@@ -1902,7 +1902,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast Action: An existing application package has been removed from
* the device. The data contains the name of the package. The package
* that is being installed does <em>not</em> receive this Intent.
* that is being removed does <em>not</em> receive this Intent.
* <ul>
* <li> {@link #EXTRA_UID} containing the integer uid previously assigned
* to the package.
@@ -1936,9 +1936,9 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_PACKAGE_FULLY_REMOVED
= "android.intent.action.PACKAGE_FULLY_REMOVED";
/**
* Broadcast Action: An existing application package has been changed (e.g.
* a component has been enabled or disabled). The data contains the name of
* the package.
* Broadcast Action: An existing application package has been changed (for
* example, a component has been enabled or disabled). The data contains
* the name of the package.
* <ul>
* <li> {@link #EXTRA_UID} containing the integer uid assigned to the package.
* <li> {@link #EXTRA_CHANGED_COMPONENT_NAME_LIST} containing the class name
@@ -2010,9 +2010,9 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_UID_REMOVED = "android.intent.action.UID_REMOVED";
/**
* Broadcast Action: Sent to the installer package of an application
* when that application is first launched (that is the first time it
* is moved out of the stopped state). The data contains the name of the package.
* Broadcast Action: Sent to the installer package of an application when
* that application is first launched (that is the first time it is moved
* out of the stopped state). The data contains the name of the package.
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
@@ -2040,8 +2040,9 @@ public class Intent implements Parcelable, Cloneable {
public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED";
/**
* Broadcast Action: Sent to the system intent filter verifier when an intent filter
* needs to be verified. The data contains the filter data hosts to be verified against.
* Broadcast Action: Sent to the system intent filter verifier when an
* intent filter needs to be verified. The data contains the filter data
* hosts to be verified against.
* <p class="note">
* This is a protected intent that can only be sent by the system.
* </p>

View File

@@ -1110,7 +1110,7 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device has professional audio level of functionality, performance, and acoustics.
* The device has professional audio level of functionality and performance.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
@@ -1359,7 +1359,7 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The heart rate sensor on this device is an Electrocargiogram.
* {@link #hasSystemFeature}: The heart rate sensor on this device is an Electrocardiogram.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_SENSOR_HEART_RATE_ECG =

View File

@@ -398,17 +398,24 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* this camera device.</p>
* <p>For devices at the LEGACY level or above:</p>
* <ul>
* <li>This list will always include (30, 30).</li>
* <li>Also, for constant-framerate recording, for each normal
* <li>
* <p>For constant-framerate recording, for each normal
* {@link android.media.CamcorderProfile CamcorderProfile}, that is, a
* {@link android.media.CamcorderProfile CamcorderProfile} that has
* {@link android.media.CamcorderProfile#quality quality} in
* the range [{@link android.media.CamcorderProfile#QUALITY_LOW QUALITY_LOW},
* {@link android.media.CamcorderProfile#QUALITY_2160P QUALITY_2160P}], if the profile is
* supported by the device and has
* {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} <code>x</code>, this list will
* always include (<code>x</code>,<code>x</code>).</li>
* <li>For preview streaming use case, this list will always include (<code>min</code>, <code>max</code>) where
* <code>min</code> &lt;= 15 and <code>max</code> &gt;= 30.</li>
* always include (<code>x</code>,<code>x</code>).</p>
* </li>
* <li>
* <p>Also, a camera device must either not support any
* {@link android.media.CamcorderProfile CamcorderProfile},
* or support at least one
* normal {@link android.media.CamcorderProfile CamcorderProfile} that has
* {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} <code>x</code> &gt;= 24.</p>
* </li>
* </ul>
* <p>For devices at the LIMITED level or above:</p>
* <ul>

View File

@@ -513,7 +513,7 @@ public final class CameraManager {
* {@link CameraManager#registerAvailabilityCallback} to be notified of such availability
* changes.</p>
*
* @see registerAvailabilityCallback
* @see #registerAvailabilityCallback
*/
public static abstract class AvailabilityCallback {

View File

@@ -118,7 +118,7 @@ public final class InputManager {
* </p><p>
* The <code>android:name</code> attribute specifies an identifier by which
* the keyboard layout will be known in the package.
* The <code>android:label</code> attributes specifies a human-readable descriptive
* The <code>android:label</code> attribute specifies a human-readable descriptive
* label to describe the keyboard layout in the user interface, such as "English (US)".
* The <code>android:keyboardLayout</code> attribute refers to a
* <a href="http://source.android.com/tech/input/key-character-map-files.html">

View File

@@ -36,9 +36,9 @@ import android.util.Log;
*
* <div class="special reference">
* <h3>Developer Guide</h3>
* For a general introduction into the topic of card emulation,
* please read the <a href="{@docRoot}guide/topics/nfc/ce.html">
* NFC card emulation developer guide.</a></p>
* For a general introduction to card emulation, see
* <a href="{@docRoot}guide/topics/connectivity/nfc/hce.html">
* Host-based Card Emulation</a>.</p>
* </div>
*
* <h3>NFC Protocols</h3>

View File

@@ -113,10 +113,10 @@ public final class NfcBarcode extends BasicTagTechnology {
* <p>Does not cause any RF activity and does not block.
*
* @return a byte array containing the barcode
* @see <a href="http://www.kovio.com/docs/kovionfcbarcode.pdf">
* Kovio 128-bit NFC barcode datasheet</a>
* @see <a href="http://kovio.com/docs/kovio-128-nfc-barcode-data-format.pdf">
* Kovio 128-bit NFC barcode data format</a>
* @see <a href="http://www.thinfilm.no/docs/thinfilm-nfc-barcode-datasheet.pdf">
* Thinfilm NFC Barcode tag specification (previously Kovio NFC Barcode)</a>
* @see <a href="http://www.thinfilm.no/docs/thinfilm-nfc-barcode-data-format.pdf">
* Thinfilm NFC Barcode data format (previously Kovio NFC Barcode)</a>
*/
public byte[] getBarcode() {
switch (mType) {

View File

@@ -1417,15 +1417,17 @@ public final class Settings {
}
/**
* An app can use this method to check if it is currently allowed to draw on top of other
* apps. In order to be allowed to do so, an app must first declare the
* {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission in its manifest. If it
* is currently disallowed, it can prompt the user to grant it this capability through a
* management UI by sending an Intent with action
* {@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}.
* Checks if the specified context can draw on top of other apps. As of API
* level 23, an app cannot draw on top of other apps unless it declares the
* {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission in its
* manifest, <em>and</em> the user specifically grants the app this
* capability. To prompt the user to grant this approval, the app must send an
* intent with the action
* {@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}, which
* causes the system to display a permission management screen.
*
* @param context A context
* @return true if the calling app can draw on top of other apps, false otherwise.
* @param context App context.
* @return true if the specified context can draw on top of other apps, false otherwise
*/
public static boolean canDrawOverlays(Context context) {
int uid = Binder.getCallingUid();
@@ -3707,14 +3709,16 @@ public final class Settings {
Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS;
/**
* An app can use this method to check if it is currently allowed to write or modify system
* settings. In order to gain write access to the system settings, an app must declare the
* {@link android.Manifest.permission#WRITE_SETTINGS} permission in its manifest. If it is
* currently disallowed, it can prompt the user to grant it this capability through a
* management UI by sending an Intent with action
* {@link android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}.
* Checks if the specified app can modify system settings. As of API
* level 23, an app cannot modify system settings unless it declares the
* {@link android.Manifest.permission#WRITE_SETTINGS}
* permission in its manifest, <em>and</em> the user specifically grants
* the app this capability. To prompt the user to grant this approval,
* the app must send an intent with the action {@link
* android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}, which causes
* the system to display a permission management screen.
*
* @param context A context
* @param context App context.
* @return true if the calling app can write to system settings, false otherwise
*/
public static boolean canWrite(Context context) {

View File

@@ -18,7 +18,7 @@ package android.text;
/**
* This interface should be added to a span object that should not be copied
* into a new Spenned when performing a slice or copy operation on the original
* into a new Spanned when performing a slice or copy operation on the original
* Spanned it was placed in.
*/
public interface NoCopySpan {

View File

@@ -331,7 +331,7 @@ public class Time {
* @throws IllegalArgumentException if {@link #allDay} is true but {@code
* hour}, {@code minute}, and {@code second} are not 0.
* @return a negative result if {@code a} is earlier, a positive result if
* {@code a} is earlier, or 0 if they are equal.
* {@code b} is earlier, or 0 if they are equal.
*/
public static int compare(Time a, Time b) {
if (a == null) {

View File

@@ -2002,7 +2002,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
/**
* Return the pointer identifier associated with a particular pointer
* data index is this event. The identifier tells you the actual pointer
* data index in this event. The identifier tells you the actual pointer
* number associated with the data, accounting for individual pointers
* going up and down since the start of the current gesture.
* @param pointerIndex Raw index of pointer to retrieve. Value may be from 0

View File

@@ -159,7 +159,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* that set them will vary among the different subclasses of views. Note that
* properties that are known at build time can be set in the XML layout
* files.</li>
* <li><strong>Set focus:</strong> The framework will handled moving focus in
* <li><strong>Set focus:</strong> The framework will handle moving focus in
* response to user input. To force focus to a specific view, call
* {@link #requestFocus}.</li>
* <li><strong>Set up listeners:</strong> Views allow clients to set listeners

View File

@@ -333,7 +333,8 @@
<!-- ====================================================================== -->
<eat-comment />
<!-- Used for runtime permissions related to user's contacts and profile. -->
<!-- Used for runtime permissions related to contacts and profiles on this
device. -->
<permission-group android:name="android.permission-group.CONTACTS"
android:icon="@drawable/perm_group_contacts"
android:label="@string/permgrouplab_contacts"
@@ -891,7 +892,7 @@
<!-- =============================================================== -->
<eat-comment />
<!-- Allows an application to modify and remove existing voicemails in the system
<!-- Allows an application to modify and remove existing voicemails in the system.
<p>Protection level: system|signature
-->
<permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
@@ -908,7 +909,7 @@
<!-- ======================================= -->
<eat-comment />
<!-- Allows an application to access extra location provider commands
<!-- Allows an application to access extra location provider commands.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
@@ -954,7 +955,7 @@
android:label="@string/permlab_createNetworkSockets"
android:protectionLevel="normal" />
<!-- Allows applications to access information about networks
<!-- Allows applications to access information about networks.
<p>Protection level: normal
-->
<permission android:name="android.permission.ACCESS_NETWORK_STATE"
@@ -1090,7 +1091,15 @@
<eat-comment />
<!-- Allows access to the list of accounts in the Accounts Service.
<p>Protection level: normal
<p class="note"><strong>Note:</strong> Beginning with Android 6.0 (API level
23), if an app shares the signature of the authenticator that manages an
account, it does not need <code>"GET_ACCOUNTS"</code> permission to read
information about that account. On Android 5.1 and lower, all apps need
<code>"GET_ACCOUNTS"</code> permission to read information about any
account.</p>
<p>Protection level: dangerous
-->
<permission android:name="android.permission.GET_ACCOUNTS"
android:permissionGroup="android.permission-group.CONTACTS"
@@ -1461,11 +1470,21 @@
<!-- ================================== -->
<eat-comment />
<!-- Allows an application to open windows using the type
<!-- Allows an app to create windows using the type
{@link android.view.WindowManager.LayoutParams#TYPE_SYSTEM_ALERT},
shown on top of all other applications. Very few applications
shown on top of all other apps. Very few apps
should use this permission; these windows are intended for
system-level interaction with the user. -->
system-level interaction with the user.
<p class="note"><strong>Note:</strong> If the app
targets API level 23 or higher, the app user must explicitly grant
this permission to the app through a permission management screen. The app requests
the user's approval by sending an intent with action
{@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}.
The app can check whether it has this authorization by calling
{@link android.provider.Settings#canDrawOverlays
Settings.canDrawOverlays()}.
<p>Protection level: signature -->
<permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
android:label="@string/permlab_systemAlertWindow"
android:description="@string/permdesc_systemAlertWindow"
@@ -1588,7 +1607,16 @@
android:protectionLevel="signature|privileged|development" />
<!-- Allows an application to read or write the system settings.
<p>Protection level: signature
<p class="note"><strong>Note:</strong> If the app targets API level 23
or higher, the app user
must explicitly grant this permission to the app through a permission management screen.
The app requests the user's approval by sending an intent with action
{@link android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}. The app
can check whether it has this authorization by calling {@link
android.provider.Settings.System#canWrite Settings.System.canWrite()}.
<p>Protection level: signature
-->
<permission android:name="android.permission.WRITE_SETTINGS"
android:label="@string/permlab_writeSettings"
@@ -1968,7 +1996,7 @@
<permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
android:protectionLevel="signature" />
<!-- Must be required by a TextService (e.g. SpellCheckerService)
<!-- Must be required by a TextService (eg SpellCheckerService)
to ensure that only the system can bind to it.
<p>Protection level: signature
-->

View File

@@ -3366,7 +3366,7 @@ i
property is set to true by default but should be set to false if your adapter
will display items of varying heights. When this property is set to true and
your adapter displays items of varying heights, the scrollbar thumb will
change size as the user scrolls through the list. When set to fale, the list
change size as the user scrolls through the list. When set to false, the list
will use only the number of items in the adapter and the number of items visible
on screen to determine the scrollbar's properties. -->
<attr name="smoothScrollbar" format="boolean" />

View File

@@ -2194,7 +2194,7 @@
<attr name="name" />
</declare-styleable>
<!-- Associate declared KeySets with upgrading capability -->
<!-- Associate declared KeySets with upgrading capability. -->
<declare-styleable name="AndroidManifestUpgradeKeySet" parent="AndroidManifest">
<attr name="name" />
</declare-styleable>

View File

@@ -1,9 +1,9 @@
<html>
<head>
<meta http-equiv="refresh" content="0;url=documentation.html">
<meta http-equiv="refresh" content="0;url=reference/packages.html">
</head>
<body>
<a href="documentation.html">click here if you are not redirected</a>
<a href="reference/packages.html">click here if you are not redirected</a>
</body>
</html>

View File

@@ -0,0 +1,103 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
<title>Android N Developer Preview</title>
<!-- STYLESHEETS -->
<link rel="stylesheet"
href="http://fonts.googleapis.com/css?family=Roboto+Condensed">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold"
title="roboto">
<link href="assets/css/default.css?v=17" rel="stylesheet" type="text/css">
<!-- JAVASCRIPT -->
<script src="https://www.google.com/jsapi" type="text/javascript"></script>
<script src="assets/js/android_3p-bundle.js" type="text/javascript"></script>
<script type="text/javascript">
var toRoot = "../";
var metaTags = ["develop, getstarted, sdk, appquality, landing"];
var devsite = false;
</script>
<script src="assets/js/docs.js?v=3" type="text/javascript"></script>
</head>
<body>
<div id="header-wrapper">
<div class="dac-header" id="header">
<div class="dac-header-inner">
<a class="dac-nav-toggle" data-dac-toggle-nav="" href="javascript:;"
title="Open navigation">
<span class="dac-nav-hamburger">
<span class="dac-nav-hamburger-top"></span>
<span class="dac-nav-hamburger-mid"></span>
<span class="dac-nav-hamburger-bot"></span>
</span>
</a>
<a class="dac-header-logo" href="index.html">
<img class="dac-header-logo-image" src="assets/images/android_logo.png"
srcset="assets/images/android_logo@2x.png 2x" width="32" height="36"
alt="Android"> Developers
</a>
</div>
</div>
</div>
<nav class="dac-nav">
<div class="dac-nav-dimmer" data-dac-toggle-nav=""></div>
<ul class="dac-nav-list" data-dac-nav="">
<li class="dac-nav-item dac-nav-head">
<a class="dac-nav-link dac-nav-logo" data-dac-toggle-nav=""
href="javascript:;" title="Close navigation">
<img class="dac-logo-image" src="assets/images/android_logo.png"
srcset="assets/images/android_logo@2x.png 2x" width="32" height="36"
alt="Android"> Developers
</a>
</li>
<li class="dac-nav-item develop">
<a class="dac-nav-link" href="reference/packages.html"
>API Reference</a>
</li>
</ul>
</nav>
<section class="dac-expand" style="padding-top:40px;background-color:#eee">
<div class="wrap" style="max-width:1100px;margin-top:0;height:100%">
<div class="cols dac-hero-content" style="padding-bottom:1em;">
<div class="col-11of16">
<h1>Android N Developer Preview</h1>
<p>
Get ready for Android N!
<strong>Test your apps</strong> on Nexus devices. Support new system
behaviors to <strong>save power and memory</strong>.
Extend your apps with <strong>multi-window UI</strong>,
<strong>direct reply notifications</strong> and more.
</p>
<h2>Get Started</h2>
<ul>
<li>View the <a href="reference/packages.html">API Reference</a></li>
<li>Read Diff Reports:</a>
<ul>
<li><a href="sdk/api_diff/n-preview-1/changes.html"
>API 23 --> Preview 1</a></li>
</ul>
</li>
<li>Downloads and additional documentation are available at the
<a href="http://developer.android.com/preview/index.html">
Android N Developer Preview site</a></li>
<li>For information about Developer Preview 1, visit the
<a href="http://developer.android.com/preview/support.html">Support</a>
page.</li>
</ul>
</div>
</div>
</div>
</section>
</body>
</html>

View File

@@ -14,8 +14,8 @@ creatividad e ideas de diseño. Desvíese de lo tradicional con un propósito.
<h2 id="enchant-me">Cautívame</h2>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="delight-me">Deléitame de formas sorprendentes</h4>
<p>Una superficie atractiva, una animación colocada en el lugar correcto o un efecto de sonido bien sincronizado suelen ser experiencias
@@ -23,7 +23,7 @@ placenteras. Los efectos sutiles contribuyen a crear un sentimiento de facilidad
poderosa.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_delight.png">
@@ -32,15 +32,15 @@ poderosa.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="real-objects-more-fun">Los objetos reales son más divertidos que los botones y los menús</h4>
<p>Permita que los usuarios toquen y manipulen directamente los objetos de su aplicación. Esto reduce el esfuerzo cognitivo
<p>Permite que los usuarios toquen y manipulen directamente los objetos de tu aplicación. Esto reduce el esfuerzo cognitivo
que se necesita para llevar a cabo una tarea que resulte satisfactoria a nivel emocional.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_real_objects.png">
@@ -49,16 +49,16 @@ que se necesita para llevar a cabo una tarea que resulte satisfactoria a nivel e
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="make-it-mine">Permíteme darle un toque personal</h4>
<p>A los usuarios les gusta agregar toques personales, ya que esto los ayuda a sentirse cómodos y a sentir que tienen el control. Ofrezca
opciones predeterminadas prácticas y atractivas, pero también tenga en cuenta personalizaciones opcionales y divertidas que no entorpezcan las
<p>A los usuarios les gusta agregar toques personales, ya que esto los ayuda a sentirse cómodos y a sentir que tienen el control. Ofrece
opciones predeterminadas prácticas y atractivas, pero también ten en cuenta personalizaciones opcionales y divertidas que no entorpezcan las
tareas principales.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_it_mine.png">
@@ -67,15 +67,15 @@ tareas principales.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="get-to-know-me">Conóceme</h4>
<p>Con el paso del tiempo, conozca las preferencias de los usuarios. En lugar de pedirles a los usuarios que elijan las mismas cosas una y otra
<p>Con el paso del tiempo, conoce las preferencias de los usuarios. En lugar de pedirles a los usuarios que elijan las mismas cosas una y otra
vez, permita que puedan acceder fácilmente a las opciones que ya eligieron antes.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_get_to_know_me.png">
@@ -84,14 +84,14 @@ vez, permita que puedan acceder fácilmente a las opciones que ya eligieron ante
<h2 id="simplify-my-life">Simplifica mi vida</h2>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="keep-it-brief">Sé breve</h4>
<p>Utilice frases cortas con palabras simples. Las personas tienden a omitir las oraciones largas.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_keep_it_brief.png">
@@ -100,15 +100,15 @@ vez, permita que puedan acceder fácilmente a las opciones que ya eligieron ante
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="pictures-faster-than-words">Las imágenes son más prácticas que las palabras</h4>
<p>Considere la idea de utilizar imágenes para explicar las ideas. Las imágenes atraen la atención de las personas y pueden ser mucho más eficientes
<p>Considera la idea de utilizar imágenes para explicar las ideas. Las imágenes atraen la atención de las personas y pueden ser mucho más eficientes
que las palabras.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_pictures.png">
@@ -117,15 +117,15 @@ que las palabras.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="decide-for-me">Decide por mí, pero permíteme tener la última palabra</h4>
<p>Siga su instinto y actúe sin preguntar primero. Tener que elegir demasiadas veces y tomar muchas decisiones hace que las personas
se sientan molestas. Permita que los usuarios puedan deshacer sus elecciones en caso de que no sean lo que ellos desean.</p>
<p>Sigue su instinto y actúa sin preguntar primero. Tener que elegir demasiadas veces y tomar muchas decisiones hace que las personas
se sientan molestas. Permite que los usuarios puedan deshacer sus elecciones en caso de que no sean lo que ellos desean.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_decide_for_me.png">
@@ -134,15 +134,15 @@ se sientan molestas. Permita que los usuarios puedan deshacer sus elecciones en
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="only-show-when-i-need-it">Solo muéstrame lo que necesito, cuando lo necesito</h4>
<p>Los usuarios se sienten abrumados cuando se les presenta demasiada información al mismo tiempo. Divida las tareas y la información en fragmentos pequeños
y fáciles de digerir. Oculte las opciones que no son fundamentales en el momento y capacite a los usuarios sobre la marcha.</p>
<p>Los usuarios se sienten abrumados cuando se les presenta demasiada información al mismo tiempo. Divide las tareas y la información en fragmentos pequeños
y fáciles de digerir. Oculta las opciones que no son fundamentales en el momento y capacita a los usuarios sobre la marcha.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_information_when_need_it.png">
@@ -151,15 +151,15 @@ y fáciles de digerir. Oculte las opciones que no son fundamentales en el moment
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="always-know-where-i-am">Siempre debo saber dónde me encuentro</h4>
<p>Haga que los usuarios sientan que conocen el camino de regreso. Para ello, diseñe las distintas partes de su aplicación de modo tal que se vean diferentes y
utilice transiciones para mostrar la relación entre las pantallas. Proporcione comentarios sobre las tareas que están en curso.</p>
<p>Haz que los usuarios sientan que conocen el camino de regreso. Para ello, diseña las distintas partes de su aplicación de modo tal que se vean diferentes y
utiliza transiciones para mostrar la relación entre las pantallas. Proporciona comentarios sobre las tareas que están en curso.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_navigation.png">
@@ -168,16 +168,16 @@ utilice transiciones para mostrar la relación entre las pantallas. Proporcione
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="never-lose-my-stuff">Nunca pierdas lo que es mío</h4>
<p>Guarde aquellas cosas que los usuarios crearon y permítales acceder a ellas desde cualquier lugar. Recuerde las configuraciones,
<p>Guarda aquellas cosas que los usuarios crearon y permíteles acceder a ellas desde cualquier lugar. Recuerda las configuraciones,
los toques personales y las creaciones en todos los teléfonos, las tablets y las computadoras. Esta es la forma de hacer que las actualizaciones
sean lo más simple del mundo.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_never_lose_stuff.png">
@@ -186,15 +186,15 @@ sean lo más simple del mundo.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="looks-same-should-act-same">Si se ve igual, debe funcionar de la misma manera</h4>
<p>Ayude a los usuarios a distinguir las diferencias funcionales al lograr que se vean diferentes en lugar de sutiles.
<p>Ayuda a los usuarios a distinguir las diferencias funcionales al lograr que se vean diferentes en lugar de sutiles.
Evite los modos, que son sitios que lucen similar pero actúan diferente ante la misma entrada.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_looks_same.png">
@@ -203,15 +203,15 @@ Evite los modos, que son sitios que lucen similar pero actúan diferente ante la
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="interrupt-only-if-important">Solo interrúmpeme si es importante</h4>
<p>Al igual que un buen asistente personal, evite a los usuarios los pormenores poco importantes. Las personas desean estar
concentradas y, a menos que sea fundamental y esté sujeta a un plazo de tiempo, una interrupción puede resultar agobiante y frustrante.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_important_interruption.png">
@@ -220,16 +220,16 @@ concentradas y, a menos que sea fundamental y esté sujeta a un plazo de tiempo,
<h2 id="make-me-amazing">Permíteme ser asombroso</h2>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="give-me-tricks">Ofréceme trucos que funcionen en todos lados</h4>
<p>Las personas se sienten muy bien cuando descubren cosas por sí mismos. Logre que su aplicación sea más simple de utilizar al
<h4 id="give-me-tricks">Ofrézame trucos que funcionen en todos lados</h4>
<p>Las personas se sienten muy bien cuando descubren cosas por sí mismos. Logra que su aplicación sea más simple de utilizar al
aprovechar los patrones visuales y la memoria muscular de otras aplicaciones de Android. Por ejemplo, el gesto de deslizar rápidamente
puede ser un buen acceso directo de navegación.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_tricks.png">
@@ -238,16 +238,16 @@ puede ser un buen acceso directo de navegación.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="its-not-my-fault">No es mi culpa</h4>
<p>Sea sutil cuando les solicite a los usuarios que realicen correcciones. Ellos desean sentirse inteligentes cuando usan la
aplicación que usted creó. Si hacen algo mal, bríndeles instrucciones claras de recuperación, pero evite darles detalles técnicos.
Sería incluso mejor que usted lo solucione en segundo plano.</p>
<p>Sé sutil cuando solicites a los usuarios que realicen correcciones. Ellos desean sentirse inteligentes cuando usan la
aplicación que creaste. Si hacen algo mal, bríndales instrucciones claras de recuperación, pero evita darles detalles técnicos.
Sería incluso mejor que tú lo soluciones en segundo plano.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_error.png">
@@ -256,15 +256,15 @@ Sería incluso mejor que usted lo solucione en segundo plano.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="sprinkle-encouragement">Fomenta lo simple</h4>
<p>Desglose las tareas complejas en pasos más pequeños que se puedan cumplir fácilmente. Ofrezca comentarios sobre las acciones,
<p>Desglosa las tareas complejas en pasos más pequeños que se puedan cumplir fácilmente. Ofrece comentarios sobre las acciones,
incluso si es simplemente un halago sutil.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
@@ -273,16 +273,16 @@ incluso si es simplemente un halago sutil.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="do-heavy-lifting-for-me">Haz el trabajo pesado por mí</h4>
<p>Haga que los principiantes se sientan como expertos al permitirles hacer cosas que pensaron que nunca podrían hacer. Por
ejemplo, a través de los accesos directos en los que se combinan múltiples efectos de fotografías, puede lograr que las fotografías de principiantes se vean maravillosas
<p>Haz que los principiantes se sientan como expertos al permitirles hacer cosas que pensaron que nunca podrían hacer. Por
ejemplo, a través de los accesos directos en los que se combinan múltiples efectos de fotografías, puedes lograr que las fotografías de principiantes se vean maravillosas
en solo algunos pasos.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_heavy_lifting.png">
@@ -291,15 +291,15 @@ en solo algunos pasos.</p>
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="make-important-things-fast">Haz que lo importante sea rápido</h4>
<p>No todas las acciones son iguales. Decida qué es lo más importante en su aplicación y haga
<p>No todas las acciones son iguales. Decide qué es lo más importante en tu aplicación y haz
que los usuarios lo puedan encontrar fácilmente y utilizar de forma rápida, como el obturador de una cámara o el botón de pausa de un reproductor de música.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_important_fast.png">

View File

@@ -1,7 +1,7 @@
page.title=Material Design
page.title=Material Design para Android
page.tags=Material,design
page.type=design
page.image=design/material/images/MaterialLight.png
page.image=images/cards/design-material-for-android_2x.jpg
@jd:body
@@ -41,11 +41,11 @@ page.image=design/material/images/MaterialLight.png
<p itemprop="description">Material Design es una guía integral para el diseño visual, de movimientos y
de interacción en distintas plataformas y dispositivos. Android ahora es compatible con las aplicaciones de
Material Design. Para usar Material Design en sus aplicaciones de Android, siga las pautas descritas
en la <a href="http://www.google.com/design/spec">especificación de Material Design</a> y use los
Material Design. Para usar Material Design en tus aplicaciones de Android, sigue las pautas descritas
en la <a href="http://www.google.com/design/spec">especificación de Material Design</a> y usa los
nuevos componentes y funcionalidades disponibles en Android 5.0 (nivel de API 21) y versiones posteriores.</p>
<p>En Android, se proporcionan los siguientes elementos que le permitirán crear aplicaciones en Material Design:</p>
<p>En Android, se proporcionan los siguientes elementos que te permitirán crear aplicaciones en Material Design:</p>
<ul>
<li>un tema nuevo;</li>
@@ -53,13 +53,13 @@ nuevos componentes y funcionalidades disponibles en Android 5.0 (nivel de API 21
<li>nuevas API (interfaces de programación de aplicaciones) para sombras y animaciones personalizadas.</li>
</ul>
<p>Para obtener más información sobre la implementación de Material Design en Android, consulte
<p>Para obtener más información sobre la implementación de Material Design en Android, consulta
<a href="{@docRoot}training/material/index.html">Creación de aplicaciones con Material Design</a>.</p>
<h3>Tema Material</h3>
<p>El tema Material le ofrece un nuevo estilo para su aplicación, widgets del sistema que le permiten configurar
<p>El tema Material te ofrece un nuevo estilo para tu aplicación, widgets del sistema que te permiten configurar
la paleta de colores y animaciones predeterminadas para información táctil y transiciones de actividades.</p>
<!-- two columns -->
@@ -79,7 +79,7 @@ la paleta de colores y animaciones predeterminadas para información táctil y t
<br style="clear:left"/>
</div>
<p>Para obtener más información, consulte <a href="{@docRoot}training/material/theme.html">Uso del tema
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/theme.html">Uso del tema
Material</a>.</p>
@@ -97,13 +97,13 @@ animaciones de Material Design:</p>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/card_travel.png" width="500" height="426" />
<p>El nuevo widget <code>CardView</code> le permite mostrar extractos de información importante dentro de
<p>El nuevo widget <code>CardView</code> te permite mostrar extractos de información importante dentro de
tarjetas que tienen apariencia y estilo coherentes.</p>
</div>
<br style="clear:left"/>
</div>
<p>Para obtener más información, consulte <a href="{@docRoot}training/material/lists-cards.html">Creación de listas
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/lists-cards.html">Creación de listas
y tarjetas</a>.</p>
@@ -126,24 +126,24 @@ propiedad Z. Esta propiedad nueva representa la elevación de una vista, que det
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<em>Para volver a reproducir la película, haga clic en la pantalla del dispositivo.</em>
<em>Para volver a reproducir la película, haz clic en la pantalla del dispositivo.</em>
</div>
</div>
<p>Para obtener más información, consulte <a href="{@docRoot}training/material/shadows-clipping.html">Definición
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/shadows-clipping.html">Definición
de vistas de recorte y sombras</a>.</p>
<h3>Animaciones</h3>
<p>Las nuevas API de animaciones le permiten crear animaciones personalizadas para la información táctil en los controles de IU,
<p>Las nuevas API de animaciones te permiten crear animaciones personalizadas para la información táctil en los controles de IU,
además de realizar cambios en el estado de las vistas y transiciones entre actividades.</p>
<p>Estas API le permiten hacer lo siguiente:</p>
<p>Estas API te permiten hacer lo siguiente:</p>
<ul>
<li style="margin-bottom:15px">
responder a los eventos táctiles de sus vistas mediante animaciones de <strong>información táctil</strong>;
responder a los eventos táctiles de tus vistas mediante animaciones de <strong>información táctil</strong>;
</li>
<li style="margin-bottom:15px">
ocultar y mostrar vistas con animaciones con <strong>efecto circular</strong>;
@@ -163,24 +163,24 @@ mostrar animaciones en los <strong>elementos de diseño de la lista de estados</
</ul>
<p>Las animaciones de la información táctil se concentran en diferentes vistas estándar, como los botones. Las nuevas API
le permiten personalizar estas animaciones y agregarlas a sus vistas personalizadas.</p>
te permiten personalizar estas animaciones y agregarlas a tus vistas personalizadas.</p>
<p>Para obtener más información, consulte <a href="{@docRoot}training/material/animations.html">Definición de animaciones
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/animations.html">Definición de animaciones
personalizadas</a>.</p>
<h3>Elementos de diseño</h3>
<p>Estas nuevas capacidades para los elementos de diseño le permiten implementar aplicaciones de Material Design:</p>
<p>Estas nuevas capacidades para los elementos de diseño te permiten implementar aplicaciones de Material Design:</p>
<ul>
<li>Los <strong>dibujables en vector</strong> se pueden escalar sin perder definición y son perfectos
para los iconos de las aplicaciones de un solo color.</li>
<li>El <strong>teñido de los dibujables</strong> le permite definir mapas de bits como máscaras alfa y pintarlos con
<li>El <strong>teñido de los dibujables</strong> te permite definir mapas de bits como máscaras alfa y pintarlos con
un color durante el tiempo de ejecución.</li>
<li>La <strong>extracción de color</strong> le permite extraer automáticamente colores prominentes de una
<li>La <strong>extracción de color</strong> te permite extraer automáticamente colores prominentes de una
imagen del mapa de bits.</li>
</ul>
<p>Para obtener más información, consulte <a href="{@docRoot}training/material/drawables.html">Trabajo con
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/drawables.html">Trabajo con
elementos de diseño</a>.</p>

View File

@@ -0,0 +1,70 @@
page.title=Compatibilidad con versiones anteriores
page.tags="support"
page.metaDescription=Notas sobre cómo Android 4.x adapta la IU diseñada para versiones de hardware y de SO anteriores.
@jd:body
<a class="notice-developers" href="{@docRoot}training/basics/supporting-devices/index.html">
<div>
<h3>Documentos para desarrolladores</h3>
<p>Compatible con diferentes dispositivos</p>
</div>
</a>
<p>Estos son algunos de los cambios importantes en Android 3.0:</p>
<ul>
<li>Se dejan de usar las teclas físicas de menú (Atrás, Menú, Búsqueda, Inicio) en favor de la navegación
mediante controles virtuales (Back, Home, Recents).</li>
<li>Patrón sólido para el uso de menús en las barras de acción.</li>
</ul>
<p>Android 4.0 incorpora estos cambios para tablets en la plataforma del teléfono.</p>
<h2 id="older-hardware">Adaptar Android 4.0 a hardware y aplicaciones anteriores</h2>
<div class="cols">
<div class="col-6">
<h4>Teléfonos con controles de navegación virtuales</h4>
<p>Las aplicaciones de Android escritas para Android 3.0 y versiones posteriores muestran acciones en la barra de acciones. Las acciones que no
caben en la barra de acciones o que no son lo suficientemente importantes para que se las muestre en el nivel superior aparecen en la
ampliación de acciones (action overflow).</p>
<p>Los usuarios acceden a la ampliación de acciones (action overflow) tocando la barra de acciones.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_virtual_nav.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Teléfonos con teclas de navegación físicas</h4>
<p>Los teléfonos con Android que tienen teclas físicas de navegación no muestran la barra de navegación virtual en
la parte inferior de la pantalla. En cambio, la ampliación de acciones (action overflow) está disponible desde la tecla física de menú. La
ventana emergente con acciones que se muestra tiene el mismo estilo que la del ejemplo anterior, pero aparece en la parte inferior de la pantalla.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_physical_buttons.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Aplicaciones heredadas en teléfonos con controles de navegación virtuales</h4>
<p>Cuando se ejecuta una aplicación que fue generada para Android 2.3 o versiones anteriores en un teléfono con controles de
navegación virtuales, aparece un control de ampliación de acciones (action overflow) a la derecha de la barra de navegación virtual. Se
puede tocar el control para ver las acciones de la aplicación con el estilo del menú tradicional de Android.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_legacy_apps.png">
</div>
</div>

View File

@@ -2,14 +2,14 @@ page.title=Confirmación y reconocimiento
page.tags=dialog,toast,notification
@jd:body
<p>En algunos casos, cuando un usuario invoca una acción desde su aplicación, se recomienda <em>confirmar</em> o proporcionar un <em>reconocimiento</em> de dicha acción a través del texto.</p>
<p>En algunos casos, cuando un usuario invoca una acción desde tu aplicación, se recomienda <em>confirmar</em> o proporcionar un <em>reconocimiento</em> de dicha acción a través del texto.</p>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<div class="cols">
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_confirming.png">
<p><strong>Confirmación</strong> es solicitarle al usuario que verifique que realmente desea proceder con una acción que acaba de invocar. En algunos casos, la confirmación se presenta junto con una advertencia o mensaje con información importante relacionada con la acción que el usuario debe aprobar.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
<p>El <strong>reconocimiento</strong> hace referencia al hecho de mostrar un determinado texto para informarle al usuario que la acción que acaba de invocar ya se completó. De este modo, se elimina la incertidumbre sobre las operaciones implícitas que lleva a cabo el sistema. En algunos casos, el reconocimiento se presenta junto con una opción para deshacer la acción.</p>
</div>
@@ -18,18 +18,18 @@ page.tags=dialog,toast,notification
<p>Comunicarse con los usuarios de este modo permite reducir la incertidumbre respecto de acciones pasadas o futuras. Mediante la confirmación o el reconocimiento también se puede evitar que los usuarios cometan errores de los que podrían arrepentirse.</p>
<h2>Cuándo se debe solicitar una confirmación o proporcionar un reconocimiento de las acciones de los usuarios</h2>
<p>No es necesario que se solicite una confirmación o se proporcione un reconocimiento para todas las acciones. Utilice este diagrama de flujo cuando tenga que tomar decisiones relacionadas con el diseño.</p>
<p>No es necesario que se solicite una confirmación o se proporcione un reconocimiento para todas las acciones. Utiliza este diagrama de flujo cuando tengas que tomar decisiones relacionadas con el diseño.</p>
<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
<h2>Confirmación</h2>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<div class="cols">
<div class="col-6">
<h4>Ejemplo: Google Play Books</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_books.png">
<p>En este ejemplo, el usuario solicitó eliminar un libro de su biblioteca de Google Play. Aparecerá una <a href="{@docRoot}design/building-blocks/dialogs.html#alerts">alerta</a> para confirmar esta acción porque es importante que el usuario comprenda que el libro ya no estará disponible desde ningún dispositivo.</p>
<p>Cuando diseñe un cuadro de diálogo de confirmación, asegúrese de que el título sea significativo y que incluya la acción solicitada.</p>
<p>Cuando diseñes un cuadro de diálogo de confirmación, asegúrate de que el título sea significativo y que incluya la acción solicitada.</p>
</div>
<div class="layout-content-col span-7">
<div class="col-7">
<h4>Ejemplo: Android Beam</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
<p>No es necesario que las confirmaciones se presenten en todas las alertas con dos botones. Luego de iniciar Android Beam, se le solicita al usuario que seleccione el contenido que desea compartir (en este ejemplo, se trata de una fotografía). Si el usuario decide no continuar, simplemente se descartará el teléfono de la lista.</p>
@@ -37,15 +37,15 @@ page.tags=dialog,toast,notification
</div>
<h2>Reconocimiento</h2>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<div class="cols">
<div class="col-6">
<h4>Ejemplo: Borrador de Gmail abandonado y guardado</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
<p>En este ejemplo, si el usuario navega con los botones Back o Up desde la pantalla de redacción de Gmail, posiblemente ocurrirá algo inesperado: el borrador actual se guardará automáticamente. Esto se mostrará a través de un reconocimiento en forma de aviso. Dicho aviso desaparece luego de algunos segundos.</p>
<p>En este caso, no se puede incluir la opción de deshacer porque el almacenamiento fue iniciado por la aplicación, no por el usuario. Gracias a esto, se puede continuar redactando el mensaje de forma rápida y fácil con solo navegar hasta la lista de borradores.</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<h4>Ejemplo: Conversación de Gmail eliminada</h4>
<img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
<p>Después de que el usuario elimina una conversación de la lista de Gmail, aparece un mensaje de reconocimiento con la opción de deshacer la acción. Dicho reconocimiento seguirá en pantalla hasta que el usuario lleve a cabo una acción no relacionada, como desplazarse por la lista.</p>
@@ -53,14 +53,14 @@ page.tags=dialog,toast,notification
</div>
<h2>Sin confirmación ni reconocimiento</h2>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<div class="cols">
<div class="col-6">
<h4>Ejemplo: Hacer +1</h4>
<img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
<p><strong>No se necesita confirmación</strong>. Si el usuario hizo +1 sin querer, esto no es un problema. Simplemente, puede tocar el botón de nuevo para deshacer la acción.</p>
<p><strong>No se necesita confirmación</strong>. Si el usuario eligió +1 sin querer, esto no es un problema. Simplemente, puede tocar el botón de nuevo para deshacer la acción.</p>
<p><strong>No se necesita un reconocimiento</strong>. El usuario verá que el botón +1 parpadea y cambia a color rojo. Esa es una señal muy clara.</p>
</div>
<div class="layout-content-col span-7">
<div class="col-7">
<h4>Ejemplo: Eliminación de una aplicación de la pantalla de inicio</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
<p><strong>No se necesita confirmación</strong>. Esta es una acción intencionada: el usuario debe arrastrar y colocar un elemento en un destino relativamente grande y aislado. Por lo tanto, es poco probable que se cometan errores. No obstante, si el usuario se arrepiente de la decisión que tomó, solo demorará algunos segundos en recuperar lo eliminado.</p>

View File

@@ -12,10 +12,10 @@ page.image=/design/media/navigation_between_siblings_gmail.png
<p itemprop="description">La navegación coherente es un componente fundamental de la experiencia general del usuario. Pocas situaciones frustran más a los
usuarios que la navegación básica que se comporta de forma irregular e inesperada. En Android 3.0,
se introdujeron cambios significativos en el comportamiento global de la navegación. Si sigue detalladamente
las pautas de navegación con los botones Back y Up, la navegación en su aplicación será predecible y confiable para los usuarios.</p>
se introdujeron cambios significativos en el comportamiento global de la navegación. Si sigues detalladamente
las pautas de navegación con los botones Back y Up, la navegación en tu aplicación será predecible y confiable para los usuarios.</p>
<p>En Android 2.3 y versiones anteriores, se confió en el botón <em>Back</em> del sistema para respaldar la navegación dentro de una
aplicación. Con la introducción de las barras de acciones en Android 3.0, apareció un segundo mecanismo de navegación:
aplicación. Con la introducción de las barras de acción en Android 3.0, apareció un segundo mecanismo de navegación:
el botón <em>Up</em>, que consiste en el icono de la aplicación y una pequeña flecha a la izquierda.</p>
<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
@@ -26,7 +26,7 @@ el botón <em>Up</em>, que consiste en el icono de la aplicación y una pequeña
entre pantallas. Por ejemplo, si en la pantalla A se muestra una lista de elementos y, si se selecciona un elemento, se conduce al usuario a la
pantalla B (en la que se presenta ese elemento de forma más detallada), entonces en la pantalla B se debe mostrar el botón Up para regresar
a la pantalla A.</p>
<p>Si una pantalla aparece en la parte superior de una aplicación (es decir, en el inicio de la aplicación), no debe incluir el botón Up
<p>Si una pantalla aparece en la parte superior de una aplicación (es decir, en el inicio de la aplicación), no debes incluir el botón Up
.</p>
<p>El botón Back del sistema se utiliza para navegar, en orden cronológico inverso, por el historial
@@ -47,11 +47,11 @@ le permite al usuario regresar a la pantalla de inicio o, incluso, a otra aplica
<li>descartar las barras de acción contextuales y eliminar el resaltado de los elementos seleccionados;</li>
<li>ocultar el teclado en la pantalla (IME [Editores de métodos de entrada]).</li>
</ul>
<h2 id="within-app">Navegación dentro de su aplicación</h2>
<h2 id="within-app">Navegación dentro de tu aplicación</h2>
<h4>Navegación hacia pantallas con múltiples puntos de entrada</h4>
<p>En algunos casos, las pantallas no tienen una posición fija dentro de la jerarquía de la aplicación, y se puede acceder a ellas
desde múltiples puntos de entrada (como la pantalla Configuración, a la que se puede acceder desde cualquier otra pantalla
desde múltiples puntos de entrada (como la pantalla de configuración, a la que se puede acceder desde cualquier otra pantalla
de la aplicación). En este caso, el botón Up debe permitir regresar a la pantalla remitente, por lo que se comportaría
de forma idéntica al botón Back.</p>
<h4>Cambio de vista dentro de una pantalla</h4>
@@ -66,7 +66,7 @@ en el mismo lugar dentro de la jerarquía de la aplicación y no se crea ningún
<li>modificación de las características de la pantalla (como el zoom).</li>
</ul>
<h4>Navegación entre pantallas relacionadas</h4>
<p>Si su aplicación es compatible con la navegación desde una lista de elementos hacia una vista de detalles de alguno de esos elementos, generalmente,
<p>Si tu aplicación es compatible con la navegación desde una lista de elementos hacia una vista de detalles de alguno de esos elementos, generalmente,
es preferible respaldar la navegación de dirección desde ese elemento a otro anterior
o siguiente en la lista. Por ejemplo, en Gmail, es fácil deslizarse hacia la izquierda o la derecha desde una conversación
para ver una conversación anterior o más nueva en la misma bandeja de entrada. Al igual que cuando se cambia la vista dentro de una pantalla, en este tipo de
@@ -82,17 +82,17 @@ estas pantallas relacionadas y navegar hacia la pantalla del contenedor visitada
<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
<p>Usted puede lograr que el comportamiento del botón Up sea incluso más inteligente teniendo en cuenta sus conocimientos de la vista
<p>Puedes lograr que el comportamiento del botón Up sea incluso más inteligente teniendo en cuenta tus conocimientos de la vista
detallada. Si extendemos el ejemplo de Play Store mencionado antes, imaginemos que el usuario navegó desde el último
libro visto hacia los detalles de la adaptación de la película. En ese caso, mediante el botón Up podrá regresar a un contenedor
libro visto hacia los detalles de la adaptación de la película. En ese caso, mediante el botón Up podrás regresar a un contenedor
(Películas) por el que el usuario no navegó anteriormente.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
<h2 id="into-your-app">Navegación dentro de la aplicación a través de los widgets y las notificaciones de la pantalla de inicio</h2>
<p>Podrá utilizar los widgets y las notificaciones de la pantalla de inicio para ayudar a los usuarios a navegar directamente hacia las pantallas
que se encuentran en posiciones más profundas dentro de la jerarquía de su aplicación. Por ejemplo, tanto el widget de la bandeja de entrada de Gmail como las notificaciones de los mensajes nuevos
<p>Podrás utilizar los widgets y las notificaciones de la pantalla de inicio para ayudar a los usuarios a navegar directamente hacia las pantallas
que se encuentran en posiciones más profundas dentro de la jerarquía de tu aplicación. Por ejemplo, tanto el widget de la bandeja de entrada de Gmail como las notificaciones de los mensajes nuevos
pueden omitir la pantalla Bandeja de entrada y llevar al usuario directamente hacia una vista de conversación.</p>
<p>En ambos casos, el botón Up se debe utilizar de la siguiente manera:</p>
@@ -100,12 +100,12 @@ que se encuentran en posiciones más profundas dentro de la jerarquía de su apl
<ul>
<li><em>Si a la pantalla de destino generalmente se llega desde una determinada pantalla dentro de su
aplicación</em>, el botón Up debe permitir la navegación hacia esa pantalla.</li>
<li><em>De lo contrario, </em>el botón Up debe permitir la navegación hacia la pantalla que está en el nivel superior ("Inicio") de su aplicación.</li>
<li><em>De lo contrario, </em>el botón Up debe permitir la navegación hacia la pantalla que está en el nivel superior ("Inicio") de tu aplicación.</li>
</ul>
<p>En el caso del botón Back, la navegación debe ser más predecible. Para ello, coloque en la
<p>En el caso del botón Back, la navegación debe ser más predecible. Para ello, coloca en la
pila de retroceso de la tarea la ruta completa de la navegación ascendente hacia la pantalla que se encuentra en el nivel superior de la aplicación. De este modo, los usuarios que
no recuerdan cómo ingresaron a su aplicación podrán navegar hacia la pantalla del nivel superior de la aplicación antes de
no recuerdan cómo ingresaron a tu aplicación podrán navegar hacia la pantalla del nivel superior de la aplicación antes de
salir.</p>
<p>A modo de ejemplo, el widget de la pantalla Inicio de Gmail posee un botón para llevar al usuario directamente a la pantalla de
@@ -116,7 +116,7 @@ por medio del botón Back.</p>
<h4>Notificaciones indirectas</h4>
<p>Cuando su aplicación necesita presentar información sobre múltiples eventos de forma simultánea, puede utilizar una
<p>Cuando tu aplicación necesita presentar información sobre múltiples eventos de forma simultánea, puede utilizar una
sola notificación que dirija al usuario a una pantalla intersticial. En esta pantalla, se resumen dichos
eventos y se proporcionan rutas para que el usuario navegue más profundamente por la aplicación. Las notificaciones de este estilo se
denominan <em>notificaciones indirectas</em>.</p>
@@ -127,11 +127,11 @@ pantallas adicionales en la pila de retroceso. Una vez que el usuario se dirige
pantalla intersticial, los botones Up y Back se comportan del mismo modo que lo hacen en las notificaciones estándar, como se describió antes:
navegan dentro de la aplicación en lugar de regresar a la pantalla intersticial.</p>
<p>Por ejemplo, supongamos que un usuario de Gmail recibe una notificación indirecta del calendario Si se toca
<p>Por ejemplo, supongamos que un usuario de Gmail recibe una notificación indirecta del calendario. Si se toca
esta notificación, se abrirá la pantalla intersticial, en la que se mostrarán recordatorios de varios
eventos diferentes. Si se toca Back desde la pantalla intersticial, el usuario volverá a Gmail. Si se toca un evento
en particular, el usuario saldrá de la pantalla intersticial e ingresará en la aplicación Calendario, donde se mostrarán detalles del
evento. En la pantalla de detalles del evento, es posible navegar con los botones Up y Back hacia la vista superior del calendario.</p>
evento. En la pantalla de detalles del evento, es posible navegar con los botones Up y Back hacia la visomunmenteta superior del calendario.</p>
<img src="{@docRoot}design/media/navigation_indirect_notification.png">
@@ -154,19 +154,19 @@ mientras se navega por la aplicación.</p>
<p>Una de las principales ventajas del sistema Android es la capacidad de las aplicaciones de activarse
mutuamente, por lo que el usuario puede navegar directamente desde una aplicación hacia otra. Por ejemplo, una
aplicación que debe tomar una fotografía puede activar la aplicación de la cámara, la cual mostrará la fotografía
aplicación que debe tomar una fotografía puede area appactivar la aplicación de la cámara, la cual mostrará la fotografía
en la aplicación que la activó. Esto representa una gran ventaja tanto para el desarrollador, quien puede aprovechar fácilmente el
código de otras aplicaciones, y también para el usuario, quien disfruta de una experiencia coherente para acciones
código de otras aplicaciones, como para el usuario, quien disfruta de una experiencia coherente para acciones
que se realizan comúnmente.</p>
<p>Para comprender la navegación entre aplicaciones, es importante que entienda el comportamiento del marco de Android,
<p>Para comprender la navegación entre aplicaciones, es importante que se entienda el comportamiento del framework de Android,
que se explica a continuación.</p>
<h4>Actividades, tareas e intentos</h4>
<p>En Android, una <strong>actividad</strong> es un componente de la aplicación que define una pantalla de
información y todas las acciones relacionadas que el usuario puede llevar a cabo. Su aplicación es un conjunto de
actividades formado por las actividades que usted crea y aquellas que reutiliza de otras aplicaciones.</p>
información y todas las acciones relacionadas que el usuario puede llevar a cabo. Tu aplicación es un conjunto de
actividades formado por las actividades que creas y aquellas que reutilizas de otras aplicaciones.</p>
<p>Una <strong>tarea</strong> es la secuencia de actividades que un usuario realiza para lograr un objetivo. En
una sola tarea, se pueden utilizar actividades de una sola aplicación o se pueden utilizar actividades de varias
@@ -179,10 +179,10 @@ que pueden cumplir con esta solicitud.</p>
<h4>Ejemplo: navegación entre aplicaciones para respaldar el uso compartido</h4>
<p>Para comprender cómo las actividades, las tareas y los intentos funcionan en conjunto, considere cómo una aplicación les permite a los usuarios
compartir contenido a través de otra aplicación. Por ejemplo, si ejecuta la aplicación Play Store desde la pantalla de inicio, se iniciará
una nueva tarea A (vea la imagen a continuación). Después de navegar por Play Store y de tocar un libro promocionado
para ver la información detallada, el usuario permanece en la misma tarea y la extiende al agregar actividades. Si se desencadena la acción
<p>Para comprender cómo las actividades, las tareas y los intentos (intents) funcionan en conjunto, considera cómo una aplicación les permite a los usuarios
compartir contenido a través de otra aplicación. Por ejemplo, si se ejecuta la aplicación Play Store desde la pantalla de inicio, se iniciará
una nueva tarea A (consulta la imagen a continuación). Después de navegar por Play Store y de tocar un libro promocionado
para ver su información detallada, el usuario permanece en la misma tarea y la extiende al agregar actividades. Si se desencadena la acción
Compartir, se le mostrará al usuario un cuadro de diálogo con una lista de todas las actividades (provenientes de diferentes aplicaciones)
que se registraron para concretar el intento de compartir.</p>
@@ -208,6 +208,6 @@ a la pantalla Inicio, por lo que, si se toca el botón Back desde la lista de co
Recientes). Si Gmail ya estaba ejecutando su propia tarea en segundo plano, esta se reemplazará con la
tarea B, y el contexto anterior se abandonará para darle preferencia al nuevo objetivo del usuario.</p>
<p>Cuando su aplicación se registre para manipular los intentos de una actividad que se encuentra en un nivel profundo dentro de la jerarquía de la aplicación,
consulte <a href="#into-your-app">Navegación dentro de la aplicación a través de los widgets y
<p>Cuando tu aplicación se registre para manipular los intentos de una actividad que se encuentra en un nivel profundo dentro de la jerarquía de la aplicación,
consulta <a href="#into-your-app">Navegación dentro de la aplicación a través de los widgets y
las notificaciones de la pantalla de inicio</a> para obtener información sobre cómo especificar la navegación del botón Up.</p>

View File

@@ -5,42 +5,81 @@ page.customHeadTag=<meta name="google-site-verification" content="sa-bIAI6GKvct3
@jd:body
<!-- <div class="dac-hero-carousel" data-carousel-query="collection:index/carousel">
</div> -->
<section class="dac-hero-carousel">
<script>
$(document).ready(function() {
if (useUpdatedTemplates) {
$("#useUpdatedTemplates").css("display","block");
} else {
$("#useOldTemplates").css("display","block");
}
})
</script>
<!-- <article class="dac-expand dac-hero dac-invert active" style="background-color: rgb(38, 50, 56);"> -->
<article class="dac-expand dac-hero dac-invert dac-darken mprev active" style="background-color: #75d1ff;">
<a href="/preview/index.html">
<section class="dac-expand dac-hero dac-invert" style="background-color:#455A64">
<div class="wrap" style="max-width:1100px;margin-top:0">
<div class="cols dac-hero-content">
<div class="col-8of16 col-push-6of16 dac-hero-figure mprev">
</div>
<div class="col-8of16 col-pull-7of16">
<div class="dac-hero-tag"></div>
<h1 class="dac-hero-title" style="white-space:nowrap;">Android 6.0 Marshmallow</h1>
<p class="dac-hero-description">Prepárese para la próxima versión de
Android. Pruebe sus aplicaciones en Nexus 5, 6, 9 y Player. </p>
<a class="dac-hero-cta" href="{@docRoot}preview/index.html">
<div class="col-7of16 col-push-9of16" style="padding-left:2em;">
<a href="{@docRoot}preview/index.html">
<h1 class="dac-hero-title">Android N Developer Preview</h1>
<p class="dac-hero-description">
Get ready for the next version of Android!
<strong>Test your apps</strong> on Nexus and other devices. Support new system
behaviors to <strong>save power and memory</strong>.
Extend your apps with <strong>multi-window UI</strong>,
<strong>direct reply notifications</strong> and more.
</p>
<a class="dac-hero-cta" href="/preview/index.html">
<span class="dac-sprite dac-auto-chevron"></span>
¡Empiece hoy mismo!</a><br>
<a class="dac-hero-cta" href="{@docRoot}preview/support.html">
Learn more
</a><!--<br>
<a class="dac-hero-cta" href="/preview/support.html">
<span class="dac-sprite dac-auto-chevron"></span>
Developer Preview 3 (final SDK)</a>
Update to Developer Preview (final SDK)
</a><br>-->
</a>
</div>
<div class="col-9of16 col-pull-7of16 dac-hero-figure" style="margin-top:0em;padding-right:1.5em;">
<a href="{@docRoot}preview/index.html">
<img style="" class="dac-hero-image" src="/images/home/n-preview-hero.png"
srcset="/images/home/n-preview-hero.png 1x,
/images/home/n-preview-hero_2x.png 2x">
</a>
</div>
</div>
</div>
</a>
</article></section>
</section>
<div class="actions-bar dac-expand dac-invert">
<div id="useUpdatedTemplates" style="display:none" class="dac-section dac-slim dac-gray dac-expand">
<div class="wrap dac-offset-parent">
<a class="dac-fab dac-scroll-button" data-scroll-button href="#build-apps">
<i class="dac-sprite dac-arrow-down-gray"></i>
</a>
<ul class="dac-actions">
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}sdk/index.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Get the SDK
</a>
</li>
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}samples/index.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Browse sample code
</a>
</li>
<li class="dac-action">
<a class="dac-action-link" href="{@docRoot}distribute/stories/index.html">
<i class="dac-action-sprite dac-sprite dac-auto-chevron-large"></i>
Watch stories
</a>
</li>
</ul>
</div><!-- end .wrap -->
</div><!-- end .dac-actions -->
<div id="useOldTemplates" style="display:none" class="actions-bar dac-expand dac-invert">
<div class="wrap dac-offset-parent">
<a class="dac-fab dac-scroll-button" data-scroll-button="" href="#build-apps">
<i class="dac-sprite dac-arrow-down-gray"></i>
</a>
<div class="actions">
<div><a href="{@docRoot}sdk/index.html">
<span class="dac-sprite dac-auto-chevron-large"></span>
@@ -50,17 +89,15 @@ Android. Pruebe sus aplicaciones en Nexus 5, 6, 9 y Player. </p>
<span class="dac-sprite dac-auto-chevron-large"></span>
Browse Samples
</a></div>
<div><a href="//www.youtube.com/user/androiddevelopers">
<div><a href="{@docRoot}distribute/stories/index.html">
<span class="dac-sprite dac-auto-chevron-large"></span>
Watch Videos
Watch Stories
</a></div>
</div><!-- end .actions -->
</div><!-- end .wrap -->
</div><!-- end .actions-bar -->
</div>
<section class="dac-section dac-section-light" id="build-apps"><div class="wrap">
<section class="dac-section dac-light" id="build-apps"><div class="wrap">
<h1 class="dac-section-title">Build Beautiful Apps</h1>
<div class="dac-section-subtitle">
Resources to get you started with designing and developing for Android.

View File

@@ -1,521 +0,0 @@
page.title=Información general de la API
page.keywords=preview,sdk,compatibility
page.tags=previewresources, androidm
sdk.platform.apiLevel=22-mnc
page.image=images/cards/card-api-overview_16-9_2x.png
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento<a href="#" onclick="hideNestedItems('#toc44',this);return false;" class="header-toggle">
<span class="more">mostrar más</span>
<span class="less" style="display:none">mostrar menos</span></a></h2>
<ol id="toc44" class="hide-nested">
<li><a href="#app-linking">Vinculación de la aplicación</a></li>
<li><a href="#backup">Copia de seguridad automática para aplicaciones</a></li>
<li><a href="#authentication">Autenticación</a>
<ol>
<li><a href="#fingerprint-authentication">Autenticación por huellas dactilares</a></li>
<li><a href="#confirm-credential">Confirmar credencial</a></li>
</ol>
</li>
<li><a href="#direct-share">Compartir de forma directa</a></li>
<li><a href="#voice-interactions">Interacciones de voz</a></li>
<li><a href="#assist">Asistencia de API</a></li>
<li><a href="#notifications">Notificaciones</a></li>
<li><a href="#bluetooth-stylus">Soporte del lápiz Bluetooth</a></li>
<li><a href="#ble-scanning">Exploración mejorada de Bluetooth de bajo consumo</a></li>
<li><a href="#hotspot">Soporte de Hotspot 2.0 versión 1</a></li>
<li><a href="#4K-display">Modo de pantalla 4K</a></li>
<li><a href="#behavior-themeable-colorstatelists">ColorStateLists para poder aplicar temas</a></li>
<li><a href="#audio">Características de audio</a></li>
<li><a href="#video">Características de video</a></li>
<li><a href="#camera">Características de la cámara</a>
<ol>
<li><a href="#flashlight">API para luz de flash</a></li>
<li><a href="#reprocessing">Reprocesamiento de la cámara</a></li>
</ol>
</li>
<li><a href="#afw">Características de Android for Work</a></li>
</ol>
<h2>Diferencias de las API</h2>
<ol>
<li><a href="{@docRoot}preview/download.html">Nivel de API 22 para la versión preliminar de Android M &raquo;</a> </li>
</ol>
</div>
</div>
<p>M Developer Preview le brinda una perspectiva avanzada de la próxima versión de la plataforma Android, que ofrece nuevas características para usuarios y desarrolladores de aplicaciones.
En este documento, se brinda una introducción sobre las API más distinguidas.</p>
<p>M Developer Preview está destinado a <strong>usuarios desarrolladores principiantes</strong> y <strong>evaluadores</strong>.
Si le interesa influenciar la dirección del marco de trabajo de Android,
<a href="{@docRoot}preview/setup-sdk.html">pruebe M Developer Preview y</a> envíenos sus comentarios.
</p>
<p class="caution"><strong>Advertencia:</strong> No publique las aplicaciones que utilizan M Developer Preview en la tienda de Google Play.
</p>
<p class="note"><strong>Nota:</strong> Este documento, a menudo, hace referencia a clases y métodos que aún no cuentan con materiales de referencia disponibles en <a href="{@docRoot}">developer.android.com</a>.
Estos elementos de API tienen el formato {@code code style} en este documento (sin hipervínculos).
Para obtener la documentación preliminar de la API para estos elementos, descargue la <a href="{@docRoot}preview/download.html#docs"> referencia de la versión preliminar</a>.
</p>
<h3>Importantes cambios en los comportamientos</h3>
<p>Si publicó anteriormente una aplicación para Android, tenga en cuenta que su aplicación podría verse afectada por los cambios en la plataforma.
</p>
<p>Consulte la sección <a href="behavior-changes.html">Cambios en los comportamientos</a> para obtener información detallada.</p>
<h2 id="app-linking">Vinculación de la aplicación</h2>
<p>Esta versión preliminar mejora el sistema de intentos de Android al proporcionar una vinculación más sólida de la aplicación. Esta característica le permite asociar una aplicación con un dominio web propio.
Según esta asociación, la plataforma puede determinar la aplicación predeterminada que se debe utilizar para controlar un vínculo web en particular y omitir el paso de pedirles a los usuarios que seleccionen una aplicación. Para aprender a implementar esta característica, consulte la sección
<a href="{@docRoot}preview/features/app-linking.html">Vinculación de la aplicación</a>.
<h2 id="backup">Copia de seguridad automática para aplicaciones</h2>
<p>Ahora, el sistema realiza restauraciones y copias de seguridad de datos completas y automáticas para las aplicaciones. Este comportamiento se habilita de forma predeterminada para las aplicaciones que tienen como destino la versión preliminar de Android M; usted no necesita agregar ningún código adicional.
Si los usuarios eliminan sus cuentas de Google, también se eliminarán sus datos de copias de seguridad.
Para obtener información sobre cómo funciona esta característica y cómo configurar qué elementos incluir en la copia de seguridad del sistema de archivo, consulte la sección
<a href="{@docRoot}preview/backup/index.html">Copia de seguridad automática para aplicaciones</a>.
</p>
<h2 id="authentication">Autenticación</h2>
<p>Esta versión preliminar ofrece nuevas API para permitirle autenticar usuarios al usar escaneos de huellas dactilares en los dispositivos compatibles y verificar cuán reciente es la última autenticación del usuario al utilizar un mecanismo de desbloqueo de dispositivos (como una contraseña de pantalla de bloqueo).
Use estas API junto con el <a href="{@docRoot}training/articles/keystore.html">sistema Android Keystore</a>.
</p>
<h3 id="fingerprint-authentication">Autenticación por huellas dactilares</h3>
<p>Para autenticar usuarios mediante el escaneo de huellas dactilares, obtenga una instancia de la nueva clase
{@code android.hardware.fingerprint.FingerprintManager} y llame al método
{@code FingerprintManager.authenticate()}. Su aplicación se debe ejecutar en un dispositivo compatible con un sensor de huellas dactilares.
Debe implementar la interfaz de usuario para el flujo de autenticación por huellas dactilares en su aplicación y debe utilizar el ícono de huella dactilar estándar de Android en la UI. El ícono de huella dactilar de Android ({@code c_fp_40px.png}) se incluye en la
<a href="https://github.com/googlesamples/android-FingerprintDialog" class="external-link">aplicación de muestra</a>. Si está desarrollando múltiples aplicaciones que utilizan la autenticación por huellas dactilares, tenga en cuenta que cada aplicación debe autenticar la huella dactilar del usuario de manera independiente.
</p>
<p>Para utilizar esta característica en su aplicación, primero agregue el permiso {@code USE_FINGERPRINT} en su manifiesto.
</p>
<pre>
&lt;uses-permission
android:name="android.permission.USE_FINGERPRINT" /&gt;
</pre>
<img src="{@docRoot}preview/images/fingerprint-screen.png" srcset="{@docRoot}preview/images/fingerprint-screen.png 1x, {@docRoot}preview/images/fingerprint-screen_2x.png 2x" style="float:right; margin:0 0 10px 20px" width="282" height="476" />
<p>Para ver cómo una aplicación implementa la autenticación por huellas dactilares, consulte la sección
<a href="https://github.com/googlesamples/android-FingerprintDialog" class="external-link">
Ejemplo de diálogo de huella dactilar</a>.</p>
<p>Si está evaluando esta característica, siga estos pasos:</p>
<ol>
<li>Instale la Revisión de herramientas del SDK de Android versión 24.3, si todavía no la instaló.</li>
<li>Registre una huella dactilar nueva en el emulador; para hacerlo, vaya a
<strong>Settings &gt; Security &gt; Fingerprint</strong>, luego siga las instrucciones de registro.</li>
<li>Use un emulador para emular eventos táctiles de huellas dactilares con el siguiente comando.
Utilice el mismo comando para emular eventos táctiles de huellas dactilares en la pantalla de bloqueo o en su aplicación.
<pre class="no-prettyprint">
adb -e emu finger touch &lt;finger_id&gt;
</pre>
<p>En Windows, posiblemente tenga que ejecutar {@code telnet 127.0.0.1 &lt;emulator-id&gt;} seguido de
{@code finger touch &lt;finger_id&gt;}.
</p>
</li>
</ol>
<h3 id="confirm-credential">Confirmar credencial</h3>
<p>Su aplicación puede autenticar usuarios según el tiempo que haya pasado desde que desbloquearon su dispositivo por última vez. Esta característica evita que los usuarios tengan que recordar contraseñas adicionales específicas de la aplicación y elimina la necesidad de que usted tenga que implementar su propia interfaz de usuario de autenticación.
Su aplicación debe utilizar esta característica junto con una implementación de clave pública o secreta para la autenticación del usuario.
</p>
<p>Para definir la duración del tiempo de espera en el que se puede volver a usar la misma clave después de que un usuario se haya autenticado correctamente, llame al nuevo método
{@code android.security.keystore.KeyGenParameterSpec.setUserAuthenticationValidityDurationSeconds()}
cuando configure {@link javax.crypto.KeyGenerator} o
{@link java.security.KeyPairGenerator}.
Esta característica actualmente funciona para operaciones criptográficas simétricas.
</p>
<p>Evite mostrar el diálogo de nueva autenticación de forma excesiva: sus aplicaciones deben intentar utilizar el objeto criptográfico primero y, si se agota el tiempo de espera, deben usar el método
{@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence) createConfirmDeviceCredentialIntent()}
para volver a autenticar el usuario dentro de su aplicación.
</p>
<p>Para ver cómo la aplicación implementa esta característica, consulte la sección
<a href="https://github.com/googlesamples/android-ConfirmCredential" class="external-link">
Ejemplo de cómo confirmar la credencial</a>.</p>
<h2 id="direct-share">Compartir de forma directa</h2>
<img src="{@docRoot}preview/images/direct-share-screen.png" srcset="{@docRoot}preview/images/direct-share-screen.png 1x, {@docRoot}preview/images/direct-share-screen_2x.png 2x" style="float:right; margin:0 0 20px 30px" width="312" height="329" />
<p>Esta versión preliminar le proporciona API para que la acción de compartir sea intuitiva y rápida para los usuarios. Ahora, puede definir <em>destinos para compartir de forma directa</em> que inician una actividad específica en su aplicación. Estos destinos para compartir de forma directa se exponen a los usuarios a través del menú <em>Share</em>.
Esta característica les permite a los usuarios compartir contenido con los destinos, como contactos, dentro de otras aplicaciones.
Por ejemplo, el destino para compartir de forma directa podría iniciar una actividad en otra aplicación de red social, lo que le permite al usuario compartir contenido directamente con una comunidad o un amigo específicos de esa aplicación.
</p>
<p>Para habilitar destinos para compartir de forma directa, debe definir una clase que extienda el
{@code android.service.} <br>
Clase {@code chooser.ChooserTargetService}. Declare su
{@code ChooserTargetService} en el manifiesto. En esa declaración, especifique el permiso
{@code BIND_CHOOSER_TARGET_SERVICE} y un filtro de intento con la acción
{@code SERVICE_INTERFACE}.</p>
<p>El ejemplo a continuación muestra de qué manera podría declarar {@code ChooserTargetService} en su manifiesto.
</p>
<pre>
&lt;service android:name=".ChooserTargetService"
android:label="&#64;string/service_name"
android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.service.chooser.ChooserTargetService" /&gt;
&lt;/intent-filter&gt;
&lt;/service&gt;
</pre>
<p>Para cada actividad que desee exponer a {@code ChooserTargetService}, agregue un elemento
{@code &lt;meta-data&gt;} con el nombre
{@code "android.service.chooser.chooser_target_service"} en el manifiesto de su aplicación.
</p>
<pre>
&lt;activity android:name=".MyShareActivity”
android:label="&#64;string/share_activity_label"&gt;
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEND" /&gt;
&lt;/intent-filter>
&lt;meta-data
android:name="android.service.chooser.chooser_target_service"
android:value=".ChooserTargetService" /&gt;
&lt;/activity>
</pre>
<h2 id="voice-interactions">Interacciones de voz</h2>
<p>
Esta versión preliminar proporciona una nueva API de interacción de voz que, junto con las
<a href="https://developers.google.com/voice-actions/" class="external-link">acciones de voz</a>,
le permite compilar experiencias de conversaciones de voz en sus aplicaciones. Llame al método
{@code android.app.Activity.isVoiceInteraction()} para determinar si su actividad se inició en respuesta a una acción de voz.
De ser así, su aplicación puede utilizar la clase
{@code android.app.VoiceInteractor} para solicitar una confirmación de voz por parte del usuario, realizar una selección de una lista de opciones y mucho más.
Para obtener más información sobre cómo implementar acciones de voz, consulte el
<a href="https://developers.google.com/voice-actions/interaction/" class="external-link">sitio para desarrolladores de acciones de voz</a>.
</p>
<h2 id="assist">Asistencia de API</h2>
<p>
Esta versión preliminar ofrece una nueva manera para que los usuarios interactúen con sus aplicaciones a través de un asistente. Si desea utilizar esta característica, el usuario debe habilitar el asistente para utilizar el contexto actual.
Una vez habilitado, para invocar al asistente dentro de cualquier aplicación, el usuario debe mantener presionado el botón <strong>Home</strong>.
</p>
<p>Su aplicación puede optar por no compartir el contexto actual con el asistente al configurar la marca
{@link android.view.WindowManager.LayoutParams#FLAG_SECURE}. Además del conjunto de información estándar que la plataforma le pasa al asistente, su aplicación puede compartir información adicional usando la nueva clase {@code android.app.Activity.AssistContent}.
</p>
<p>Para proporcionarle al asistente contexto adicional desde su aplicación, siga estos pasos:</p>
<ol>
<li>Implemente la interfaz {@link android.app.Application.OnProvideAssistDataListener}.</li>
<li>Registre esta escucha usando
{@link android.app.Application#registerOnProvideAssistDataListener(android.app.Application.OnProvideAssistDataListener) registerOnProvideAssistDataListener()}.</li>
<li>Para proporcionar información contextual específica de la actividad, invalide la devolución de llamada
{@link android.app.Activity#onProvideAssistData(android.os.Bundle) onProvideAssistData()}
y, opcionalmente, la nueva devolución de llamada {@code Activity.onProvideAssistContent()}.
</ol>
<h2 id="notifications">Notificaciones</h2>
<p>Esta versión preliminar agrega los siguientes cambios de API para las notificaciones:</p>
<ul>
<li>Nuevo nivel de filtro {@code NotificationListenerService.INTERRUPTION_FILTER_ALARMS} que corresponde al nuevo modo ocupado <em>Solo alarmas</em>.
</li>
<li>Nuevo valor de categoría {@code Notification.CATEGORY_REMINDER} que se utiliza para distinguir recordatorios programados por el usuario de otros eventos
({@link android.app.Notification#CATEGORY_EVENT}) y alarmas
({@link android.app.Notification#CATEGORY_ALARM}).
</li>
<li>Nueva clase {@code android.graphics.drawable.Icon} que se puede adjuntar a sus notificaciones a través de los métodos {@code Notification.Builder.setSmallIcon(Icon)} y
{@code Notification.Builder.setLargeIcon(Icon)}.
</li>
<li>Nuevo método {@code NotificationManager.getActiveNotifications()} que permite que sus aplicaciones descubran qué notificaciones se encuentran actualmente activas.
Para ver una implementación de la aplicación que utilice esta característica, consulte la sección <a href="https://github.com/googlesamples/android-ActiveNotifications" class="external-link">Ejemplo de notificaciones activas</a>.
</li>
</ul>
<h2 id="bluetooth-stylus">Compatibilidad del lápiz Bluetooth</h2>
<p>Esta versión preliminar ofrece soporte mejorado para las entradas de usuarios que utilizan un lápiz Bluetooth. Los usuarios pueden sincronizar y conectar un lápiz Bluetooth compatible con su teléfono o tablet.
Mientras está conectado, la información de posición de la pantalla táctil se fusiona con la información de los botones y la presión del lápiz para proporcionar una mayor variedad de expresiones que al utilizar la pantalla táctil solamente.
Su aplicación puede obedecer cuando se presiona el botón del lápiz y cuando se realizan acciones secundarias al registrar las nuevas devoluciones de llamadas
{@code View.onStylusButtonPressListener} y {@code GestureDetector.OnStylusButtonPressListener}
en su actividad.
</p>
<p>Utilice las constantes y los métodos {@link android.view.MotionEvent} para detectar las interacciones del botón del lápiz:
</p>
<ul>
<li>Si el usuario toca un lápiz con un botón en la pantalla de su aplicación, el método
{@link android.view.MotionEvent#getToolType(int) getTooltype()} devuelve
{@link android.view.MotionEvent#TOOL_TYPE_STYLUS}.</li>
<li>Para las aplicaciones que tienen como destino la versión preliminar de Android M, el método
{@link android.view.MotionEvent#getButtonState() getButtonState()}
devuelve {@code MotionEvent.STYLUS_BUTTON_PRIMARY} cuando el usuario presiona el botón principal del lápiz.
Si el lápiz tiene un segundo botón, el mismo método devuelve
{@code MotionEvent.STYLUS_BUTTON_SECONDARY} cuando el usuario lo presiona. Si el usuario presiona ambos botones simultáneamente, el método devuelve ambos valores juntos separados por “OR” ({@code STYLUS_BUTTON_PRIMARY|STYLUS_BUTTON_SECONDARY}).
</li>
<li>
Para las aplicaciones que tienen como destino una versión anterior de la plataforma, el método
{@link android.view.MotionEvent#getButtonState() getButtonState()} devuelve
{@link android.view.MotionEvent#BUTTON_SECONDARY} (cuando se presiona el botón principal),
{@link android.view.MotionEvent#BUTTON_TERTIARY} (cuando se presiona el botón secundario) o ambos.
</li>
</ul>
<h2 id="ble-scanning">Exploración mejorada de Bluetooth de bajo consumo</h2>
<p>
Si su aplicación realiza exploraciones de Bluetooth de bajo consumo, puede utilizar el nuevo método
{@code android.bluetooth.le.ScanSettings.Builder.setCallbackType()} para especificar que usted desea que las devoluciones de llamadas se notifiquen solo cuando se encuentre por primera vez un paquete de anuncio que coincida con el conjunto
{@link android.bluetooth.le.ScanFilter} y cuando no se vea durante un período determinado.
Este enfoque de exploración es más eficaz en cuanto al consumo de energía que la que se proporciona en la versión anterior de la plataforma.
</p>
<h2 id="hotspot">Soporte de Hotspot 2.0 versión 1</h2>
<p>
Esta versión preliminar agrega soporte para la especificación de Hotspot 2.0 versión 1 en los dispositivos Nexus 6 y Nexus 9. Para proveer credenciales de Hotspot 2.0 en su aplicación, use los métodos nuevos de la clase
{@link android.net.wifi.WifiEnterpriseConfig}, como {@code setPlmn()} y
{@code setRealm()}.
En el objeto {@link android.net.wifi.WifiConfiguration}, puede configurar los campos
{@link android.net.wifi.WifiConfiguration#FQDN} y {@code providerFriendlyName}. La nueva propiedad {@code ScanResult.PasspointNetwork} indica si una red detectada representa un punto de acceso de Hotspot 2.0.
</p>
<h2 id="4K-display">Modo de pantalla 4K</h2>
<p>Ahora, la plataforma permite que las aplicaciones soliciten que la resolución de pantalla se actualice a una representación 4K en el hardware compatible.
Para consultar la resolución física actual, use las nuevas API
{@code android.view.Display.Mode}. Si la UI se establece en una resolución lógica más baja y se aumenta a una resolución física más alta, tenga en cuenta que la resolución física que devuelve el método
{@code Display.Mode.getPhysicalWidth()} puede ser diferente de la resolución lógica informada por {@link android.view.Display#getSize(android.graphics.Point) getSize()}.
</p>
<p>Puede pedirle al sistema que cambie la resolución física en su aplicación mientras se ejecuta y, para ello, debe configurar la propiedad {@code WindowManager.LayoutParams.preferredDisplayModeId} de la ventana de su aplicación.
Esta característica resulta útil si desea cambiar a la resolución de pantalla 4K.
Mientras se encuentra en el modo de pantalla 4K, la UI se continúa representando en la resolución original (como 1080p) y se aumenta a 4K, pero los objetos
{@link android.view.SurfaceView} pueden mostrar contenido en la resolución nativa.
</p>
<h2 id="behavior-themeable-colorstatelists">ColorStateLists para poder aplicar temas</h2>
<p>Ahora, los atributos de tema se admiten en
{@link android.content.res.ColorStateList} para los dispositivos que ejecutan la versión preliminar de Android M. Los métodos
{@link android.content.res.Resources#getColorStateList(int) getColorStateList()} y
{@link android.content.res.Resources#getColor(int) getColor()} se dejaron de usar. Si desea llamar a estas API, en su lugar, llame a los métodos nuevos {@code Context.getColorStateList()} o
{@code Context.getColor()}.
Estos métodos también se encuentran disponibles en la biblioteca AppCompat v4 vía {@link android.support.v4.content.ContextCompat}.
</p>
<h2 id="audio">Características de audio</h2>
<p>Esta versión preliminar agrega mejoras al procesamiento de audio en Android, lo que incluye lo siguiente: </p>
<ul>
<li>Soporte para el protocolo <a href="http://en.wikipedia.org/wiki/MIDI" class="external-link">MIDI</a>
, con las nuevas API {@code android.media.midi}. Utilice estas API para enviar y recibir eventos MIDI.
</li>
<li>Clases nuevas {@code android.media.AudioRecord.Builder} y {@code android.media.AudioTrack.Builder}
para crear capturas de audio digital y objetos de reproducción respectivamente, y configurar propiedades de receptores y fuentes de audio para invalidar los valores predeterminados del sistema.
</li>
<li>Enlaces de API para asociar dispositivos de entrada y de audio. Esto resulta particularmente útil si su aplicación les permite a los usuarios iniciar una búsqueda por voz desde un controlador para juegos o un control remoto conectados a un TV con Android. El sistema invoca la nueva devolución de llamada {@code android.app.Activity.onSearchRequested()} cuando el usuario inicia una búsqueda.
Para determinar si el dispositivo de entrada del usuario tiene un micrófono incorporado, recupere el objeto {@link android.view.InputDevice} de esa devolución de llamada y luego llame al nuevo método
{@code InputDevice.hasMic()}.
</li>
<li>Nueva clase {@code android.media.AudioDevicesManager}, que le permite recuperar una lista de todos los dispositivos de audio receptores y fuente adjuntos.
También puede especificar un objeto
{@code android.media.OnAudioDeviceConnectionListener} si desea que su aplicación reciba una notificación cuando se conecta o desconecta un dispositivo de audio.
</li>
</ul>
<h2 id="video">Características de video</h2>
<p>Esta versión preliminar agrega nuevas capacidades a las API de procesamiento de video, entre ellas, las siguientes:</p>
<ul>
<li>Nueva clase {@code android.media.MediaSync} que ayuda a las aplicaciones a representar de forma sincrónica transmisiones de audio y video.
Los búferes de audio se envían de manera que no generan bloqueo y regresan mediante una devolución de llamada.
Además, admite una velocidad de reproducción dinámica.
</li>
<li>Nuevo evento {@code MediaDrm.EVENT_SESSION_RECLAIMED}, que indica cuando una sesión abierta por la aplicación es reclamada por el administrador de recursos.
Si su aplicación utiliza sesiones DRM, debe controlar este evento y asegurarse de no utilizar una sesión reclamada.
</li>
<li>Nuevo código de error {@code MediaCodec.CodecException.ERROR_RECLAIMED}, que indica que el administrador de recursos reclamó el recurso multimedia utilizado por el códec.
Con esta excepción, se debe liberar el códec, ya que pasó al estado terminal.
</li>
<li>Nueva interfaz {@code MediaCodecInfo.CodecCapabilities.getMaxSupportedInstances()} para obtener una indicación de la cantidad máxima de instancias concurrentes de códec admitidas.
</li>
<li>Nuevo método {@code MediaPlayer.setPlaybackParams()} para configurar la velocidad de reproducción multimedia para reproducciones rápidas o lentas.
Además, alarga o acelera la reproducción de audio de forma automática junto con el video.
</li>
</ul>
<h2 id="camera">Características de la cámara</h2>
<p>Esta versión preliminar incluye las siguientes API nuevas para acceder a la luz de flash de la cámara y para el reprocesamiento de imágenes de la cámara:
</p>
<h3 id="flashlight">API para luz de flash</h3>
<p>Si un dispositivo de cámara cuenta con una unidad de flash, puede llamar al método {@code CameraManager.setTorchMode()}
para activar o desactivar el modo linterna de una unidad de flash sin abrir el dispositivo de cámara. La aplicación no tiene propiedad exclusiva de la unidad de flash ni del dispositivo de cámara.
El modo linterna se desactiva y deja de estar disponible cuando la cámara no se encuentra disponible o cuando otros recursos de la cámara que mantienen la linterna encendida dejan de estar disponibles.
Otras aplicaciones también pueden llamar a {@code setTorchMode()}
para desactivar el modo linterna. Cuando se cierra la última aplicación que activó el modo linterna, este modo se desactiva.
</p>
<p>Si desea registrar una devolución de llamada para recibir una notificación sobre el estado del modo linterna, llame al método
{@code CameraManager.registerTorchCallback()}. La primera vez que se registra la devolución de llamada, se llama inmediatamente con el estado del modo linterna de todos los dispositivos de cámara que se conocen actualmente y que tengan una unidad de flash.
Si el modo linterna se activa o desactiva correctamente, se invoca al método
{@code CameraManager.TorchCallback.onTorchModeChanged()}.</p>
<h3 id="reprocessing">API de reprocesamiento</h3>
<p>La API {@link android.hardware.camera2 Camera2} se extiende para admitir el reprocesamiento de imágenes privadas de formato opaco y YUV.
Su aplicación determina si las capacidades de reprocesamiento se encuentran disponibles vía {@code CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES}.
Si un dispositivo admite el reprocesamiento, usted puede crear una sesión de captura de cámara reprocesable llamando a
{@code CameraDevice.createReprocessableCaptureSession()} y puede crear solicitudes para el reprocesamiento de búferes de entrada.
</p>
<p>Utilice la clase {@code ImageWriter} para conectar el flujo del búfer de entrada a la entrada de reprocesamiento de la cámara.
Para obtener un búfer vacío, siga el modelo de programación que se indica a continuación:</p>
<ol>
<li>Llame al método {@code ImageWriter.dequeueInputImage()}.</li>
<li>Complete los datos en el búfer de entrada.</li>
<li>Envíe el búfer a la cámara llamando al método {@code ImageWriter.queueInputImage()}.</li>
</ol>
<p>Si está utilizando un objeto {@code ImageWriter} junto con una imagen
{@code android.graphics.ImageFormat.PRIVATE}, su aplicación no puede acceder a los datos de la imagen de forma directa.
En cambio, pase la imagen {@code ImageFormat.PRIVATE} directamente a
{@code ImageWriter} llamando al método {@code ImageWriter.queueInputImage()} sin ninguna copia del búfer.
</p>
<p>La clase {@code ImageReader} ahora admite secuencias de imagen de formato {@code android.graphics.ImageFormat.PRIVATE}.
Este soporte le permite que su aplicación mantenga una cola de imagen circular de imágenes de salida
{@code ImageReader}, seleccione una o más imágenes y las envíe a
{@code ImageWriter} para el reprocesamiento de la cámara.</p>
<h2 id="afw">Características de Android for Work</h2>
<p>Esta versión preliminar incluye las siguientes API nuevas para Android for Work:</p>
<ul>
<li><strong>Controles mejorados para dispositivos corporativos de uso único:</strong> El propietario de dispositivo ahora puede controlar las configuraciones que se describen a continuación para mejorar la administración de los dispositivos corporativos de uso único (Corporate-Owned, Single-Use, COSU).
<ul>
<li>Deshabilitar o volver a habilitar la protección de seguridad con el método
{@code DevicePolicyManager.setKeyguardEnabledState()}.</li>
<li>Deshabilitar o volver a habilitar la barra de estado (lo que incluye configuraciones rápidas, notificaciones y el gesto de navegación al deslizar el dedo hacia arriba para iniciar Google Now) con el método
{@code DevicePolicyManager.setStatusBarEnabledState()}.
</li>
<li>Deshabilitar o volver a habilitar el inicio seguro con la constante {@link android.os.UserManager}
{@code DISALLOW_SAFE_BOOT}.</li>
<li>Evitar que se apague la pantalla mientras el dispositivo se encuentra conectado con la constante
{@link android.provider.Settings.Global} {@code STAY_ON_WHILE_PLUGGED_IN}.</li>
</ul>
</li>
<li><strong>Instalación y desinstalación automáticas de aplicaciones por parte del propietario de dispositivo:</strong> Un propietario de dispositivo ahora puede instalar y desinstalar aplicaciones de manera automática con las API {@link android.content.pm.PackageInstaller}
, independiente de Google Play for Work.
Ahora, puede aprovisionar los dispositivos a través de un propietario de dispositivo que obtiene e instala aplicaciones sin interacción del usuario.
Esta característica es útil para habilitar el aprovisionamiento con un toque de quioscos u otros dispositivos similares sin activar una cuenta de Google.
</li>
<li><strong>Acceso automático al certificado de empresa:</strong> Ahora cuando una aplicación llama a
{@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()}, antes de que se indique al usuario que seleccione un certificado, el propietario de dispositivo o perfil puede llamar al método {@code DeviceAdminReceiver.onChoosePrivateKeyAlias()} para proporcionar el alias de forma automática a la aplicación que realiza la solicitud.
Esta característica le permite conceder a las aplicaciones gestionadas acceso a certificados sin interacción del usuario.
</li>
<li><strong>Aceptación automática de actualizaciones del sistema:</strong> Al configurar una directiva de actualización del sistema con
{@code DevicePolicyManager.setSystemUpdatePolicy()}, el propietario de dispositivo ahora puede aceptar automáticamente una actualización del sistema, por ejemplo, en el caso de un dispositivo de quiosco, o posponer la actualización y evitar que el usuario la ejecute durante un plazo de hasta 30 días.
Además, un administrador puede configurar un período de tiempo diario en el que se debe ejecutar una actualización, por ejemplo, durante las horas en que no se usa el dispositivo de quiosco.
Cuando hay una actualización del sistema disponible, el sistema verifica si la aplicación Work Policy Controller definió una directiva de actualización del sistema y se comporta según corresponda.
</li>
<li>
<strong>Instalación delegada de certificados:</strong> Ahora, un propietario de dispositivo o perfil puede concederle a una aplicación de terceros la capacidad de llamar a estas API de administración de certificados {@link android.app.admin.DevicePolicyManager}:
<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>Protección de restablecimiento de la configuración predeterminada de fábrica:</strong> Al aprovisionar a un propietario de dispositivo, ahora podrá configurar parámetros para desbloquear la protección de restablecimiento de la configuración predeterminada de fábrica (Factory Reset Protection, FRP) configurando el paquete
{@code DeviceManagerPolicy.EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS}.
Una aplicación de Programador NFC puede proporcionar estos parámetros después del restablecimiento de un dispositivo para desbloquear la FRP y aprovisionar al dispositivo sin requerir la cuenta de Google configurada previamente.
Si no modifica estos parámetros, la FRP se conserva y evita que el dispositivo se active sin las credenciales de Google activadas previamente.
<p>Además, al configurar las restricciones de la aplicación en los servicios de Google Play, los propietarios de dispositivos pueden especificar cuentas de Google alternativas para desbloquear la FRP y reemplazar las que se encuentran activadas en el dispositivo.
</p>
</li>
<img src="{@docRoot}preview/images/work-profile-screen.png" srcset="{@docRoot}preview/images/work-profile-screen.png 1x, {@docRoot}preview/images/work-profile-screen_2x.png 2x" style="float:right; margin:0 0 10px 20px" width="282" height="476" />
<li><strong>Seguimiento del uso de datos:</strong> Ahora, un propietario de dispositivo o perfil puede consultar las estadísticas de uso de datos que se pueden ver en <strong>Settings &gt; Data</strong> utilizando los nuevos métodos
{@code android.app.usage.NetworkStatsManager}.
A los propietarios de perfiles se les concede automáticamente permiso para consultar los datos del perfil que administran, mientras que los propietarios de dispositivo obtienen acceso a los datos de uso del usuario principal administrado.
</li>
<li><strong>Administración de permisos de tiempo de ejecución:</strong>
<p>Un propietario de dispositivo o perfil puede configurar una directiva de permisos para todas las solicitudes de tiempo de ejecución de todas las aplicaciones que utilizan
{@code DevicePolicyManager.setPermissionPolicy()}, a fin de pedirle confirmación al usuario para conceder el permiso de manera normal, o bien, para conceder o negar el permiso automáticamente sin notificarlo.
Si se configura la última directiva, el usuario no puede modificar la selección realizada por el propietario de dispositivo o perfil dentro de la pantalla de permisos de la aplicación en <strong>Settings</strong>.
</p></li>
<li><strong>VPN en Settings:</strong> Las aplicaciones de la VPN (red privada virtual) ahora se pueden ver en
<strong>Settings &gt; More &gt; VPN</strong>. Además, las notificaciones que acompañan el uso de la VPN ahora son específicas para la manera en que dicha VPN está configurada.
Para el propietario de perfil, las notificaciones son específicas dependiendo de si la VPN se configura para un perfil administrado, un perfil personal o ambos.
Para un propietario de dispositivo, las notificaciones son específicas dependiendo de si la VPN se configura para todo el dispositivo.
</li>
<li><strong>Notificación del estado del trabajo:</strong> Ahora aparecerá un ícono de maletín en la barra de estado siempre que una aplicación del perfil administrado tenga una actividad en primer plano.
Además, si el dispositivo se desbloquea directamente para la actividad de una aplicación del perfil administrado, se mostrará una notificación del sistema para informarle al usuario que se encuentra dentro del perfil de trabajo.
</li>
</ul>
<p class="note">
Para obtener una vista detallada de todos los cambios de la API en M Developer Preview, consulte el <a href="{@docRoot}preview/download.html">Informe de diferencias de las API</a>.
</p>

View File

@@ -1,327 +0,0 @@
page.title=Copia de seguridad automática para aplicaciones
page.tags=copia de seguridad, recursos de la versión preliminar, androidm
page.keywords=copia de seguridad, copia de seguridad automática, versión preliminar
page.image=images/cards/card-auto-backup_2x.png
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento</h2>
<ol>
<li><a href="#overview">Información general</a></li>
<li><a href="#configuring">Configuración de la copia de seguridad de datos</a></li>
<li><a href="#testing">Pruebas de la configuración de copia de seguridad</a></li>
<li><a href="#issues">Problemas conocidos</a></li>
</ol>
</div>
</div>
<p>
A menudo, los usuarios invierten tiempo y esfuerzo significativos para crear datos y configurar preferencias dentro de las aplicaciones.
Preservar los datos de los usuarios en caso de que reemplacen un dispositivo averiado o se actualicen a uno nuevo es una parte importante para garantizar una excelente experiencia del usuario.
Los dispositivos que ejecutan el sistema de la versión preliminar de Android M ayudan a garantizar una buena experiencia para los usuarios en estas circunstancias al realizar automáticamente copias de seguridad de los datos de la aplicación en Google Drive.
Los datos de la aplicación se restauran automáticamente si un usuario cambia o actualiza un dispositivo.
</p>
<p>
Las copias de seguridad automáticas se habilitan para todas las aplicaciones instaladas en dispositivos que ejecuten la versión preliminar de Android M. No se requiere ningún código de aplicación adicional.
El sistema les proporciona a los usuarios la capacidad de desactivar las copias de seguridad de datos automáticas.
También puede optar por limitar qué datos de su aplicación se incluyen en la copia de seguridad.
</p>
<p>
En este documento, se describe el nuevo comportamiento del sistema y el modo de especificar qué datos incluir en la copia de seguridad de la aplicación.
</p>
<h2 id="overview">Información general</h2>
<p>
Para preservar los datos que su aplicación crea en un dispositivo de usuario, la característica de copia de seguridad automática los carga a la cuenta de Google Drive del usuario y los cifra.
No se aplican cargos para usted ni para el usuario por el almacenamiento de datos y los datos guardados no se consideran al calcular la capacidad máxima de la cuenta personal de Google Drive del usuario.
Durante el período de la versión preliminar de Android M, los usuarios pueden almacenar hasta 25 MB por aplicación de Android.
</p>
<p>
Las copias de seguridad automáticas se realizan cada 24 horas, cuando el dispositivo está inactivo, se está cargando y está conectado a una red Wi-Fi.
Cuando se cumplen estas condiciones, el servicio Backup Manager carga todos los datos de copia de seguridad disponibles a la nube.
Cuando el usuario pasa a un dispositivo nuevo, o desinstala y vuelve a instalar la aplicación de la copia de seguridad, una operación de restauración copia los datos incluidos en la copia de seguridad en el directorio de datos de la aplicación recientemente instalada.
</p>
<p class="note">
<strong>Nota:</strong> Si su aplicación utiliza el <a href="{@docRoot}google/backup/index.html">servicio Android Backup</a> heredado, este nuevo comportamiento no se aplica y el comportamiento de copia de seguridad existente funciona de manera habitual.
</p>
<h3 id="auto-exclude">Archivos de datos automáticamente excluidos</h3>
<p>
No todos los datos de la aplicación se deben incluir en la copia de seguridad, como los archivos temporales y los cachés, por lo que el servicio de copias de seguridad automáticas excluye ciertos archivos de datos de manera predeterminada:
</p>
<ul>
<li>Archivos de los directorios a los que hacen referencia los métodos {@link android.content.Context#getCacheDir
getCacheDir()} y {@link android.content.ContextWrapper#getCodeCacheDir getCodeCacheDir()}
.
</li>
<li>Archivos ubicados en almacenamiento externo, salvo que residan en el directorio al que hace referencia el método
{@link android.content.Context#getExternalFilesDir getExternalFilesDir()}
.
</li>
<li>Archivos ubicados en el directorio a los que hace referencia el método
{@link android.content.Context#getNoBackupFilesDir getNoBackupFilesDir()}.
</li>
</ul>
<h2 id="configuring">Configuración de la copia de seguridad de datos</h2>
<p>
Las copias de seguridad se realizan para los datos creados por cualquier aplicación instalada en un dispositivo con la versión preliminar de Android M, excepto en el caso de los archivos excluidos automáticamente que se mencionaron en la sección anterior.
Usted puede limitar y configurar aún más los datos que se incluyen en la copia de seguridad de su aplicación y, para ello, debe utilizar configuraciones en el manifiesto de su aplicación.
</p>
<h3 id="include-exclude">Cómo incluir o excluir datos</h3>
<p>
De acuerdo con los datos que su aplicación necesita y el modo en que usted guarda estos datos, es posible que tenga que definir reglas específicas para incluir o excluir ciertos archivos o directorios.
El servicio de copias de seguridad automáticas admite la configuración de estas reglas de copias de seguridad a través del uso de un archivo de configuración XML y el manifiesto de la aplicación.
En el manifiesto de la aplicación, puede especificar un archivo de configuración de esquema de la copia de seguridad, como se muestra en el siguiente ejemplo:
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.my.appexample"&gt;
&lt;uses-sdk android:minSdkVersion="MNC"/&gt;
&lt;uses-sdk android:targetSdkVersion="MNC"/&gt;
&lt;app ...
<strong> android:fullBackupContent="&#64;xml/mybackupscheme"&gt;</strong>
&lt;/app&gt;
...
&lt;/manifest&gt;
</pre>
<p>
En este código de ejemplo, el atributo <code>android:fullBackupContent</code> especifica un archivo XML, ubicado en el directorio <code>res/xml/</code> del proyecto de desarrollo de su aplicación, con el nombre <code>mybackupscheme.xml</code>.
Este archivo de configuración incluye reglas sobre los archivos para los que se realiza una copia de seguridad.
El siguiente código de ejemplo muestra un archivo de configuración que excluye un archivo específico de las copias de seguridad:
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;full-backup-content&gt;
&lt;exclude domain="database" path="device_info.db"/&gt;
&lt;/full-backup-content&gt;
</pre>
<p>
Este ejemplo de configuración de copia de seguridad solo excluye un archivo específico de base de datos que no se incluirá en la copia de seguridad.
Todos los demás archivos se incluirán en la copia de seguridad.
</p>
<h4>Sintaxis de la configuración de copia de seguridad</h4>
<p>
La configuración del servicio de copias de seguridad le permite especificar qué archivos incluir en la copia de seguridad o excluir de ella.
La sintaxis del archivo de configuración XML de copia de seguridad de datos es la siguiente:
</p>
<pre>
&lt;full-backup-content&gt;
&lt;include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" /&gt;
&lt;exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" /&gt;
&lt;/full-backup-content&gt;
</pre>
<p>
Los siguientes elementos y atributos le permiten especificar qué archivos incluir de la copia de seguridad o excluir de ella:
</p>
<ul>
<li>
<code>&lt;include&gt;</code>. Use este elemento si desea especificar un conjunto de recursos para realizar una copia de seguridad, en lugar de hacer que el sistema realice una copia de seguridad de todos los datos de su aplicación de forma predeterminada.
Cuando especifica una etiqueta <code>&lt;include&gt;</code>, el sistema realiza una copia de seguridad <em>solo de los recursos que se especifican</em>
con este elemento.
</li>
<li>
<code>&lt;exclude&gt;</code>. Use este elemento para especificar un conjunto de recursos para excluir de la copia de seguridad.
El sistema realizará una copia de seguridad de todos los datos de su aplicación, excepto de los recursos que se especifican con este elemento.
</li>
<li>
<code>domain.</code> El tipo de recurso que desea incluir en la copia de seguridad o excluir de esta. Entre los valores válidos que usted puede especificar para este atributo se incluyen los siguientes:
</li>
<li style="list-style: none">
<ul>
<li>
<code>root</code>. Especifica que el recurso se encuentra en el directorio raíz de la aplicación.
</li>
<li>
<code>file</code>. Corresponde a un recurso del directorio devuelto por el método
{@link android.content.Context#getFilesDir getFilesDir()}.
</li>
<li>
<code>database</code>. Corresponde a una base de datos devuelta por el método
{@link android.content.Context#getDatabasePath getDatabasePath()} o mediante el uso de la clase
{@link android.database.sqlite.SQLiteOpenHelper}.
</li>
<li>
<code>sharedpref</code>. Corresponde a un objeto {@link android.content.SharedPreferences} devuelto por el método {@link android.content.Context#getSharedPreferences getSharedPreferences()}
.
</li>
<li>
<code>external</code>. Especifica que el recurso se encuentra en almacenamiento externo y corresponde a un archivo del directorio devuelto por el método
{@link android.content.Context#getExternalFilesDir getExternalFilesDir()}.
</li>
<li>
<code>path</code>. La ruta de archivo para un recurso que desea incluir en la copia de seguridad o excluir de esta.
</li>
</ul>
</li>
</ul>
<h3 id="prohibit">Cómo prohibir las copias de seguridad de datos</h3>
<p>
Puede optar por impedir que se realicen copias de seguridad automáticas de los datos de su aplicación y, para ello, debe configurar el atributo
<code>android:allowBackup</code> en <code>false</code> en el elemento de la aplicación de su manifiesto.
Esta configuración se ilustra en el siguiente código de ejemplo:
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.my.appexample"&gt;
&lt;uses-sdk android:minSdkVersion="MNC"/&gt;
&lt;uses-sdk android:targetSdkVersion="MNC"/&gt;
&lt;app ...
<strong> android:allowBackup="false"&gt;</strong>
&lt;/app&gt;
...
&lt;/manifest&gt;
</pre>
<h2 id="testing">Pruebas de la configuración de copia de seguridad</h2>
<p>
Cuando haya creado una configuración de copia de seguridad, debe probarla para garantizar que su aplicación guarde los datos y se pueda restaurar correctamente.
</p>
<h4>Cómo habilitar un registro de copias de seguridad</h4>
<p>
Para ayudar a determinar la manera en que la característica de copia de seguridad está analizando su archivo XML, habilite el registro antes de realizar una copia de seguridad de prueba:
</p>
<pre class="noprettyprint">
$ adb shell setprop log.tag.BackupXmlParserLogging VERBOSE
</pre>
<h4>Cómo probar la copia de seguridad</h4>
<p>Para ejecutar manualmente una copia de seguridad, primero debe inicializar Backup Manager llamando al siguiente comando:
</p>
<pre class="noprettyprint">
$ adb shell bmgr run
</pre>
<p>
Luego, realice una copia de seguridad de su aplicación manualmente utilizando el comando que se indica a continuación y especificando el nombre de paquete para su aplicación como el parámetro <code>&lt;PACKAGE&gt;</code>:
</p>
<pre class="noprettyprint">
$ adb shell bmgr fullbackup &lt;PACKAGE&gt;</pre>
<h4>Cómo probar la restauración</h4>
<p>
Para iniciar una restauración manualmente después de realizar una copia de seguridad de los datos, llame al comando que se indica a continuación y especifique el nombre de paquete para su aplicación como el parámetro <code>&lt;PACKAGE&gt;</code>:
</p>
<pre class="noprettyprint">
$ adb shell bmgr restore &lt;PACKAGE&gt;
</pre>
<p class="warning">
<b>Advertencia:</b> Esta acción detiene la aplicación y borra sus datos antes de realizar la operación de restauración.
</p>
<p>
Para iniciar el proceso de restauración de su aplicación, desinstale su aplicación y vuelva a instalarla. Los datos de la aplicación se restaurarán automáticamente desde la nube una vez que se complete la instalación.
</p>
<h4>Solución de problemas de las copias de seguridad</h4>
<p>
Si tiene algún problema, borre los datos de la copia de seguridad y los metadatos asociados; para hacerlo, desactive y vuelva a activar la copia de seguridad en <strong>Settings &gt; Backup</strong>, restablezca el dispositivo a la configuración predeterminada de fábrica o llame al siguiente comando:
</p>
<pre>$ adb shell bmgr wipe &lt;TRANSPORT&gt; &lt;PACKAGE&gt;</pre>
<p>
El valor <code>&lt;TRANSPORT&gt;</code> debe estar precedido por <code>com.google.android.gms</code>.
Para obtener una lista de transportes, llame al siguiente comando:
</p>
<pre>$ adb shell bmgr list transports</pre>
<h2 id="issues">Problemas conocidos</h2>
<p>Los siguientes son problemas conocidos del servicio de copias de seguridad automáticas:</p>
<ul>
<li><strong>Google Cloud Messaging</strong>: En las aplicaciones que utilizan Google Cloud Messaging para notificaciones push, existe un problema conocido en el que al realizar una copia de seguridad de la Id. de registro devuelta por el registro de Google Cloud Messaging, se pueden romper las notificaciones push de la aplicación restaurada. Es importante realizar una consulta a la API para obtener una nueva Id. de registro después de realizar la instalación en un dispositivo nuevo, lo que no sucede si se realizó una copia de seguridad de la Id. de registro anterior.
Para evitar esta situación, excluya la Id. de registro del conjunto de archivos para incluir en la copia de seguridad.
</li>
</ul>

View File

@@ -1,403 +0,0 @@
page.title=Cambios en los comportamientos
page.keywords=versión preliminar,sdk,compatibilidad
sdk.platform.apiLevel=MNC
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento</h2>
<ol id="toc44" class="hide-nested">
<li><a href="#behavior-runtime-permissions">Permisos de tiempo de ejecución</a></li>
<li><a href="#behavior-power">Optimizaciones de ahorro de energía</a>
<ol>
<li><a href="#behavior-doze">Doze</a></li>
<li><a href="#behavior-app-standby">App Standby</a></li>
</ol>
</li>
<li><a href="#behavior-adoptable-storage">Dispositivos de almacenamiento adoptables</a></li>
<li><a href="#behavior-apache-http-client">Eliminación del cliente HTTP de Apache</a></li>
<li><a href="#behavior-audiomanager-Changes">Cambios en AudioManager</a></li>
<li><a href="#behavior-test-selection">Selección de texto</a></li>
<li><a href="#behavior-keystore">Cambios en Android Keystore</a></li>
<li><a href="#behavior-network">Cambios en las funciones de red y Wi-Fi</a></li>
<li><a href="#behavior-camera">Cambios en el servicio de cámara</a></li>
<li><a href="#behavior-art-runtime">Tiempo de ejecución de ART</a></li>
<li><a href="#behavior-apk-validation">Validación de APK</a></li>
<li><a href="#behavior-afw">Cambios en Android for Work</a></li>
</ol>
<h2>Diferencias de las API</h2>
<ol>
<li><a href="{@docRoot}preview/download.html">Nivel de API 22 para la versión preliminar de Android M &raquo;</a> </li>
</ol>
<h2>Consulte también</h2>
<ol>
<li><a href="{@docRoot}preview/api-overview.html">Información general de la API de M Developer Preview</a> </li>
</ol>
</div>
</div>
<p>Además de nuevas características y capacidades, M Developer Preview incluye diversos cambios en el sistema y cambios en los comportamientos de la API.
En este documento, se destacan algunos de los cambios principales que debe comprender y justificar en sus aplicaciones.
</p>
<p>Si publicó anteriormente una aplicación para Android, tenga en cuenta que su aplicación podría verse afectada por estos cambios en la plataforma.
</p>
<h2 id="behavior-runtime-permissions">Permisos de tiempo de ejecución</h1>
<p>Esta versión preliminar introduce un nuevo modelo de permisos en el que los usuarios ahora pueden administrar directamente los permisos de la aplicación en tiempo de ejecución.
Este modelo les proporciona a los usuarios mayor visibilidad y control sobre los permisos y, al mismo tiempo, simplifica los procesos de instalación y actualización automática para los desarrolladores de aplicaciones. Los usuarios pueden conceder o revocar permisos de forma individual para las aplicaciones instaladas.
</p>
<p>En sus aplicaciones que tienen como destino la versión preliminar de Android M, asegúrese de comprobar y solicitar los permisos en tiempo de ejecución.
Para determinar si se concedió un permiso a su aplicación, llame al nuevo método {@code Context.checkSelfPermission()}.
Para solicitar un permiso, llame al nuevo método
{@code Activity.requestPermission()}. Incluso si su aplicación no tiene como destino la versión preliminar de Android M, debería probar su aplicación de acuerdo con el nuevo modelo de permisos.
</p>
<p>Para obtener detalles sobre la compatibilidad del nuevo modelo de permisos en su aplicación, consulte la página
<a href="{@docRoot}preview/features/runtime-permissions.html">
Permisos</a> de la versión preliminar para desarrolladores. Para obtener consejos sobre cómo evaluar el impacto en su aplicación, consulte la <a href="{@docRoot}preview/testing/guide.html#runtime-permissions">Guía de prueba</a>.
</p>
<h2 id="behavior-power">Optimizaciones de ahorro de energía</h2>
<p>Esta versión preliminar introduce nuevas optimizaciones de ahorro de energía para aplicaciones y dispositivos inactivos.</p>
<h3 id="behavior-doze">Doze</h3>
<p>Si un dispositivo está desconectado y permanece quieto con la pantalla apagada durante un período determinado, pasará al modo <em>Doze</em>, en el que el dispositivo intenta mantener el sistema en estado de suspensión.
En este modo, los dispositivos reanudan periódicamente el funcionamiento normal durante períodos breves, de manera que la aplicación se pueda sincronizar y el sistema pueda realizar las operaciones pendientes.
</p>
<p>Durante el modo Doze, se aplican las siguientes restricciones a sus aplicaciones:</p>
<ul>
<li>Se deshabilita el acceso a la red, salvo que su aplicación reciba una señal de prioridad alta de Google Cloud Messaging (envío de mensajes a través de la nube de Google).
</li>
<li>Se ignoran los <a href="{@docRoot}reference/android/os/PowerManager.WakeLock.html">Wakelocks</a>.</li>
<li>Se deshabilitan las alarmas programadas con la clase {@link android.app.AlarmManager}, salvo las alarmas que haya configurado con el método {@link android.app.AlarmManager#setAlarmClock setAlarmClock()}
y con {@code AlarmManager.setAndAllowWhileIdle()}.
</li>
<li>No se realiza la detección de Wi-Fi.</li>
<li>No se permite la ejecución de sincronizaciones ni trabajos para sus adaptadores de sincronización y {@link android.app.job.JobScheduler}.
</li>
</ul>
</p>
<p>Al salir del modo Doze, el dispositivo ejecuta los trabajos y las sincronizaciones pendientes.</p>
<p>Para probar esta característica, conecte un dispositivo que esté ejecutando la versión preliminar de Android M a su equipo de desarrollo y llame a los siguientes comandos:
</p>
<pre class="no-prettyprint">
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
$ adb shell dumpsys deviceidle -h
</pre>
<p class="note"><strong>Nota:</strong> La próxima versión de
<a href="https://developers.google.com/cloud-messaging/" class="external-link">
Google Cloud Messaging</a> le permite designar mensajes de prioridad alta.
Si su aplicación recibe mensajes de GCM de prioridad alta, se le concede un breve acceso a la red, incluso cuando el dispositivo se encuentra en modo Doze.
</p>
<p>Consulte la
<a href="{@docRoot}preview/testing/guide.html#doze-standby">Guía de prueba</a> para obtener consejos sobre cómo probar el modo Doze en su aplicación.
</p>
<h3 id="behavior-app-standby">App Standby</h3>
<p>Con esta versión preliminar, el sistema puede determinar que las aplicaciones se encuentran inactivas cuando no están en uso activo.
La aplicación se considera inactiva después de un cierto período, salvo que el sistema detecte alguna de las siguientes señales:
</p>
<ul>
<li>El usuario inicia explícitamente la aplicación.</li>
<li>La aplicación actualmente tiene un proceso en primer plano (ya sea como una actividad o un servicio en primer plano, o en uso por parte de otra actividad u otro servicio en primer plano).
</li>
<li>La aplicación genera una notificación que los usuarios ven en la pantalla de bloqueo o en la bandeja de notificaciones.
</li>
<li>El usuario solicita explícitamente que la aplicación esté exenta de optimizaciones mediante las <strong>Configuraciones</strong>.
</li>
</ul>
<p>Si el dispositivo está desconectado, las aplicaciones que se consideren inactivas tendrán deshabilitado el acceso a la red y se suspenderán sus sincronizaciones y trabajos.
Cuando el dispositivo se conecte a un sistema de alimentación, estas aplicaciones se podrán conectar a la red y podrán ejecutar los trabajos y las sincronizaciones pendientes.
Si el dispositivo queda inactivo durante períodos prolongados, las aplicaciones inactivas pueden acceder a la red aproximadamente una vez al día.
</p>
<p>Para probar esta característica, conecte un dispositivo que esté ejecutando la versión preliminar de Android M a su equipo de desarrollo y llame a los siguientes comandos:
</p>
<pre class="no-prettyprint">
$ adb shell dumpsys battery unplug
$ adb shell am set-idle &lt;packageName&gt; true
$ adb shell am set-idle &lt;packageName&gt; false
$ adb shell am get-idle &lt;packageName&gt;
</pre>
<p class="note"><strong>Nota:</strong> La próxima versión de
<a href="https://developers.google.com/cloud-messaging/" class="external-link">
Google Cloud Messaging</a> (GCM) le permite designar mensajes de prioridad alta.
Si su aplicación recibe mensajes de GCM de prioridad alta, se le concede un breve acceso a la red, incluso cuando la aplicación está inactiva.
</p>
<p>Consulte la
<a href="{@docRoot}preview/testing/guide.html#doze-standby">Guía de prueba</a> para obtener consejos sobre cómo probar el modo App Standby en sus aplicaciones.
</p>
<h2 id="behavior-adoptable-storage">Dispositivos de almacenamiento adoptables</h2>
<p>
Con esta versión preliminar, los usuarios pueden <em>adoptar</em> dispositivos de almacenamiento externo, como tarjetas SD. Al adoptar un dispositivo de almacenamiento externo, el dispositivo se cifra y se formatea para que actúe como un elemento de almacenamiento interno.
Esta característica les permite a los usuarios mover tanto las aplicaciones como los datos privados de esas aplicaciones entre dispositivos de almacenamiento.
Al mover aplicaciones, el sistema respeta la preferencia
<a href="{@docRoot}guide/topics/manifest/manifest-element.html#install">{@code android:installLocation}</a>
del manifiesto.
</p>
<p>Si su aplicación accede a las API o a los campos que se indican a continuación, tenga en cuenta que las rutas de archivo que devuelven se modificarán dinámicamente cuando la aplicación se mueva entre dispositivos de almacenamiento interno y externo. Al crear rutas de archivo, lo más recomendable es que siempre llame a estas API de forma dinámica. No use rutas de archivo codificadas de forma rígida ni continúe usando rutas de archivo completas que se hayan creado anteriormente.
</p>
<ul>
<li>Métodos {@link android.content.Context}:
<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>Campos {@link android.content.pm.ApplicationInfo}:
<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>Para depurar esta característica en la versión preliminar para desarrolladores, puede habilitar la opción de adoptar una unidad USB que esté conectada a un dispositivo Android mediante un cable USB On-The-Go (OTG) y para habilitarla puede ejecutar el siguiente comando:
</p>
<pre class="no-prettyprint">
$ adb shell sm set-force-adoptable true
</pre>
<h2 id="behavior-apache-http-client">Eliminación del cliente HTTP de Apache</h2>
<p>Esta versión preliminar elimina el soporte del cliente HTTP de Apache. Si su aplicación utiliza este cliente y tiene como destino Android 2.3 (API de nivel 9) o una versión posterior, use, en su lugar, la clase {@link java.net.HttpURLConnection}.
Esta API es más eficaz porque reduce el uso de la red mediante compresión y almacenamiento de respuesta en caché transparentes, y minimiza el consumo de energía.
Para continuar utilizando las API HTTP de Apache, primero debe declarar la siguiente dependencia en tiempo de compilación en su archivo {@code build.gradle}:
</p>
<pre>
android {
useLibrary 'org.apache.http.legacy'
}
</pre>
<p>Android está migrando de la biblioteca OpenSSL a
<a href="https://boringssl.googlesource.com/boringssl/" class="external-link">BoringSSL</a>
. Si utiliza Android NDK en su aplicación, no vincule bibliotecas criptográficas que no forman parte de la API de NDK, como {@code libcrypto.so} y {@code libssl.so}.
Estas bibliotecas no son API públicas y se pueden modificar o interrumpir sin aviso en todas las versiones y todos los dispositivos. Además, puede exponerse a vulnerabilidades de seguridad.
En cambio, modifique su código nativo para llamar a las API de criptografía de Java a través de JNI o para vincular estáticamente una biblioteca criptográfica de su elección.
</p>
<h2 id="behavior-audiomanager-Changes">Cambios en AudioManager</h2>
<p>Ya no se admitirán las funciones de ajustar el volumen de forma directa o silenciar secuencias específicas por medio de la clase {@link android.media.AudioManager}
. El método {@link android.media.AudioManager#setStreamSolo(int,boolean)
setStreamSolo()} es obsoleto, por lo que debe llamar al método
{@code AudioManager.requestAudioFocus()} en su lugar. Del mismo modo, el método
{@link android.media.AudioManager#setStreamMute(int,boolean) setStreamMute()} es obsoleto; en su lugar, llame al método{@code AudioManager.adjustStreamVolume()} y pase los valores de dirección {@code ADJUST_MUTE} o {@code ADJUST_UNMUTE}.
</p>
<h2 id="behavior-test-selection">Selección de texto</h2>
<img src="{@docRoot}preview/images/text-selection.gif" style="float:right; margin:0 0 20px 30px" width="360" height="640" />
<p>Ahora, cuando los usuarios seleccionen texto en su aplicación, usted puede mostrar acciones de selección de texto, como
<em>cortar</em>, <em>copiar</em> y <em>pegar</em> en una
<a href="http://www.google.com/design/spec/patterns/selection.html#selection-text-selection" class="external-link">barra de herramientas flotante</a>. La implementación de la interacción del usuario es similar a la de la barra de acciones contextuales, como se describe en la sección
<a href="{@docRoot}guide/topics/ui/menus.html#CABforViews">
Habilitación del modo de acción contextual para vistas individuales</a>.
</p>
<p>Si desea implementar una barra de herramientas flotante para selección de texto, realice los siguientes cambios en sus aplicaciones existentes:
</p>
<ol>
<li>En su objeto {@link android.view.View} o {@link android.app.Activity}, cambie sus llamados
{@link android.view.ActionMode} de
{@code startActionMode(Callback)} a {@code startActionMode(Callback, ActionMode.TYPE_FLOATING)}.</li>
<li>Tome su implementación existente de {@code ActionMode.Callback} y, en su lugar, haga que sea extendida
{@code ActionMode.Callback2}.</li>
<li>Invalide el método {@code Callback2.onGetContentRect()} para proporcionar las coordenadas del objeto {@link android.graphics.Rect} de contenido (como un rectángulo de selección de texto) en la vista.
</li>
<li>Si el posicionamiento del rectángulo ya no es válido y este es el único elemento por invalidar, llame al método {@code ActionMode.invalidateContentRect()}.
</li>
</ol>
<p>Si utiliza la biblioteca <a href="{@docRoot}tools/support-library/index.html">
Android Support Library</a> versión 22.2, tenga en cuenta que las barras de herramientas flotantes no son compatibles con versiones anteriores y AppCompat toma el control de los objetos {@link android.view.ActionMode} de forma predeterminada.
Esto impide que se muestren las barras de herramientas flotantes. Para permitir la compatibilidad de
{@link android.view.ActionMode} en
{@link android.support.v7.app.AppCompatActivity}, llame a
{@code android.support.v7.app.AppCompatActivity.getDelegate()}, luego llame a
{@code android.support.v7.app.AppCompatDelegate.setHandleNativeActionModesEnabled()} en el objeto
{@link android.support.v7.app.AppCompatDelegate} devuelto y configure el parámetro de entrada como {@code false}.
Esta llamada devuelve el control de los objetos {@link android.view.ActionMode} al marco de trabajo.
En los dispositivos que ejecutan la versión preliminar de Android M, eso permite que el marco de trabajo admita los modos de barras de herramientas flotantes o
{@link android.support.v7.app.ActionBar}, mientras que en los dispositivos anteriores a la versión preliminar de Android M solo se admiten los modos {@link android.support.v7.app.ActionBar}.
</p>
<h2 id="behavior-keystore">Cambios en Android Keystore</h2>
<p>Con esta versión preliminar, el
<a href="{@docRoot}training/articles/keystore.html">proveedor de Android Keystore</a> ya no admite DSA.
Aún se admite ECDSA.</p>
<p>Las claves que no requieren cifrado de datos estáticos ya no se eliminarán cuando se restablezca o deshabilite la pantalla de bloqueo seguro (por ejemplo, cuando lo haga el usuario o el administrador del dispositivo).
Las claves que requieren el cifrado de datos estáticos se eliminarán durante estos eventos.
</p>
<h2 id="behavior-network">Cambios en las funciones de red y Wi-Fi</h2>
<p>Esta versión preliminar introduce en las API de redes y Wi-Fi los siguientes cambios en los comportamientos.</p>
<ul>
<li>Ahora sus aplicaciones pueden cambiar el estado de los objetos {@link android.net.wifi.WifiConfiguration} solo si usted creó estos objetos.
Usted no puede modificar ni eliminar objetos
{@link android.net.wifi.WifiConfiguration} creados por el usuario o por otras aplicaciones.
</li>
<li>
Anteriormente, si una aplicación forzaba al dispositivo a conectarse a una red Wi-Fi específica utilizando
{@link android.net.wifi.WifiManager#enableNetwork(int,boolean) enableNetwork()} con la configuración
{@code disableAllOthers=true}, el dispositivo se desconectaba de otras redes, como los datos móviles.
En esta versión preliminar, el dispositivo ya no se desconectará de otras redes como estas. Si {@code targetSdkVersion} de su aplicación es {@code “20”} o inferior, se anclará a la red Wi-Fi seleccionada.
Si {@code targetSdkVersion} de su aplicación es {@code “21”} o posterior, use las API de redes múltiples (como
{@link android.net.Network#openConnection(java.net.URL) openConnection()},
{@link android.net.Network#bindSocket(java.net.Socket) bindSocket()} y el nuevo método
{@code ConnectivityManager.bindProcessToNetwork()}) para garantizar que el tráfico de su red se envíe a la red seleccionada.
</li>
</ul>
<h2 id="behavior-camera">Cambios en el servicio de cámara</h2>
<p>En esta versión preliminar, el modelo para acceder a los recursos compartidos en el servicio de cámara se cambió del modelo de acceso anterior “por orden de llegada” a un modelo de acceso en el que se favorecen los procesos de prioridad alta.
Los cambios en el comportamiento del servicio incluyen los siguientes:</p>
<ul>
<li>El acceso a los recursos del subsistema de la cámara, lo que incluye abrir y configurar un dispositivo de cámara, se concede según la “prioridad” del proceso de la aplicación cliente.
Por lo general, los procesos de la aplicación con actividades en primer plano o visibles para el usuario, reciben una prioridad más alta, lo que hace que el uso y la adquisición de recursos de la cámara sean más dependientes.
</li>
<li>Los clientes con cámara activa para aplicaciones de menor prioridad pueden ser “expulsados” cuando una aplicación de mayor prioridad intenta utilizar la cámara.
En la API {@link android.hardware.Camera} obsoleta, esto hace que se llame al método
{@link android.hardware.Camera.ErrorCallback#onError(int,android.hardware.Camera) onError()} para el cliente expulsado.
En la API {@link android.hardware.camera2 Camera2}, esto hace que se llame al método
{@link android.hardware.camera2.CameraDevice.StateCallback#onDisconnected(android.hardware.camera2.CameraDevice) onDisconnected()}
para el cliente expulsado.</li>
<li>En los dispositivos con hardware de cámara correcto, distintos procesos de la aplicación pueden abrir y utilizar de forma independiente dispositivos de cámara separados al mismo tiempo.
Sin embargo, ahora el servicio de cámara detecta y no permite los casos de uso de procesos múltiples, donde el acceso simultáneo genera una degradación considerable del rendimiento o de las capacidades de cualquiera de los dispositivos de cámara abiertos.
Este cambio puede generar “expulsiones” de clientes de menor prioridad, incluso cuando ninguna otra aplicación esté intentando acceder directamente al mismo dispositivo de cámara.
</li>
<li>
Cambiar el usuario actual provoca que se expulsen los clientes con cámara activa en las aplicaciones que pertenecen a la cuenta de usuario anterior.
El acceso a la cámara se limita a perfiles de usuario que pertenecen al usuario actual del dispositivo. En la práctica, esto significa que una cuenta de “invitado”, por ejemplo, no podrá abandonar los procesos en ejecución que utilicen el subsistema de la cámara cuando el usuario haya cambiado a otra cuenta.
</li>
</ul>
<h2 id="behavior-art-runtime">Tiempo de ejecución de ART</h2>
<p>El tiempo de ejecución de ART ahora implementa correctamente reglas de acceso para el método
{@link java.lang.reflect.Constructor#newInstance(java.lang.Object...) newInstance()}. Este cambio soluciona el problema que ocurría con Dalvik, que comprobaba las reglas de acceso incorrectamente en las versiones anteriores. Si su aplicación utiliza el método
{@link java.lang.reflect.Constructor#newInstance(java.lang.Object...) newInstance()} y usted desea invalidar comprobaciones de acceso, llame al método
{@link java.lang.reflect.Constructor#setAccessible(boolean) setAccessible()} con el parámetro de entrada configurado en {@code true}.
Si su aplicación utiliza la
<a href="{@docRoot}tools/support-library/features.html#v7-appcompat">biblioteca AppCompat versión 7</a> o la
<a href="{@docRoot}tools/support-library/features.html#v7-recyclerview">biblioteca RecyclerView versión 7</a>, debe actualizar su aplicación para utilizar las versiones más recientes de estas bibliotecas.
De lo contrario, asegúrese de que las clases personalizadas a las que se haga referencia desde el XML estén actualizadas, de manera que se pueda acceder a sus constructores de clases.
</p>
<p>Esta versión preliminar actualiza el comportamiento del vinculador dinámico. El vinculador dinámico ahora entiende la diferencia entre {@code soname} de una biblioteca y su ruta de acceso (<a href="https://code.google.com/p/android/issues/detail?id=6670" class="external-link">
error público 6670</a>), y ahora se implementa la búsqueda por {@code soname}.
Las aplicaciones que anteriormente funcionaban y que tenían entradas {@code DT_NEEDED} incorrectas (generalmente, rutas absolutas en el sistema de archivo del equipo de compilación) pueden generar error al cargarse.
</p>
<p>Ahora se implementa correctamente la marca {@code dlopen(3) RTLD_LOCAL}. Tenga en cuenta que
{@code RTLD_LOCAL} es lo predeterminado, por lo que se verán afectadas las llamadas a {@code dlopen(3)} que no utilizaron explícitamente
{@code RTLD_LOCAL} (salvo que su aplicación haya usado {@code RTLD_GLOBAL} explícitamente). Con
{@code RTLD_LOCAL}, los símbolos no estarán disponibles para las bibliotecas cargadas por llamadas posteriores a
{@code dlopen(3)} (a diferencia de lo que sucede al hacer referencia mediante entradas {@code DT_NEEDED}).</p>
</p>
<h2 id="behavior-apk-validation">Validación de APK</h2>
<p>Ahora la plataforma realiza validaciones más estrictas de APK. El APK se considera dañado si un archivo está declarado en el manifiesto, pero no está presente en el APK en sí.
Si se elimina algún contenido, se debe volver a firmar el APK.
</p>
<h2 id="behavior-afw">Cambios en Android for Work</h2>
<p>Esta versión preliminar incluye los siguientes cambios en los comportamientos para Android for Work:</p>
<ul>
<li><strong>Contactos de trabajo en contextos personales:</strong> Ahora, el registro de llamadas de Google Dialer muestra los contactos de trabajo cuando el usuario ve las llamadas anteriores. Si se configura {@code DevicePolicyManager.setCrossProfileCallerIdDisabled()} en {@code true}, se ocultan los contactos de perfiles de trabajo en el registro de llamadas de Google Dialer.
Los contactos de trabajo se pueden mostrar junto con los contactos personales en los dispositivos a través de Bluetooth solo si usted configura {@code DevicePolicyManager.setBluetoothContactSharingDisabled()} en {@code false}.
De forma predeterminada, se configura en {@code true}.
</li>
<li><strong>Eliminación de configuraciones de Wi-Fi:</strong> Las configuraciones de Wi-Fi agregadas por un propietario de perfil (por ejemplo, al llamar al método
{@link android.net.wifi.WifiManager#addNetwork(android.net.wifi.WifiConfiguration)
addNetwork()}) ahora se borran si se elimina ese perfil de trabajo.
</li>
<li><strong>Bloqueo de configuraciones de Wi-Fi:</strong> El usuario ya no puede modificar ni eliminar las configuraciones de Wi-Fi creadas por un propietario activo del dispositivo.
El usuario aún puede crear y modificar sus propias configuraciones de Wi-Fi, siempre que no se haya definido la constante {@link android.os.UserManager}
{@link android.os.UserManager#DISALLOW_CONFIG_WIFI} para ese usuario.
</li>
<li><strong>Descarga de Work Policy Controller mediante la incorporación de una cuenta de Google:</strong> Cuando una cuenta de Google que requiere gestión a través de una aplicación de Work Policy Controller (WPC) se agrega a un dispositivo fuera de un contexto administrado, el flujo de incorporación de la cuenta ahora le pide al usuario que instale el WPC apropiado. Este comportamiento también se aplica a las cuentas agregadas mediante
<strong>Settings &gt; Accounts</strong> en el asistente para instalación inicial del dispositivo.
</li>
<li><strong>Cambios en comportamientos específicos de la API DevicePolicyManager:</strong>
Llamar al método {@link android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName,boolean) setCameraDisabled()}
afecta la cámara solo del usuario que lo llama; llamarlo desde el perfil administrado no afecta las aplicaciones de cámara que se ejecutan en el usuario principal.
Asimismo, el método
{@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures(android.content.ComponentName,int) setKeyguardDisabledFeatures()}
ahora se encuentra disponible para propietarios de perfiles, además de propietarios de dispositivos. Un propietario de perfil puede configurar las siguientes restricciones de protección de seguridad:
<ul>
<li>{@link android.app.admin.DevicePolicyManager#KEYGUARD_DISABLE_TRUST_AGENTS} y
{@link android.app.admin.DevicePolicyManager#KEYGUARD_DISABLE_FINGERPRINT}, que afectan las configuraciones de protección de seguridad para el usuario primario del perfil.
</li>
<li>{@link android.app.admin.DevicePolicyManager#KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, que solo afecta las notificaciones generadas por aplicaciones en el perfil administrado.
</li>
</ul>
</li>
</ul>

View File

@@ -1,362 +0,0 @@
page.title=Descargas
page.image=images/cards/card-download_16-9_2x.png
@jd:body
<div style="position:relative; min-height:600px">
<div class="wrap" id="tos" style="position:absolute;display:none;width:inherit;">
<p class="sdk-terms-intro">Antes de descargar e instalar los componentes del SDK de la versión preliminar de Android, debe aceptar los términos y las condiciones que se describen a continuación.
</p>
<h2 class="norule">Términos y condiciones</h2>
<div class="sdk-terms" onfocus="this.blur()" style="width:678px">
Este es el Contrato de licencia de la versión preliminar del SDK de Android (el “Contrato de licencia”). 1.
Introducción 1.1 Se le otorga la licencia de la versión preliminar del SDK de Android (denominada “Versión preliminar” en este Contrato de licencia y que incluye específicamente los archivos de sistema de Android, las API agrupadas y los archivos de biblioteca de la Versión preliminar, si se encuentran disponibles), sujeto a los términos del Contrato de licencia.
El Contrato de licencia establece una relación legal vinculante entre usted y Google en relación con el uso que usted realice de la Versión preliminar. 1.2 “Android” hace referencia al conjunto de soluciones Android para dispositivos, según se encuentre disponible en el Proyecto de código abierto de Android (Android Open Source Project), que se encuentra en la siguiente URL: http://source.android.com/, y según se actualiza periódicamente. 1.3 “Google” hace referencia a Google Inc., una corporación de Delaware, con sede principal en 1600 Amphitheatre Parkway, Mountain View, CA 94043, Estados Unidos. 2.
Aceptación del Contrato de licencia 2.1 Para poder utilizar la Versión preliminar, primero debe aceptar el Contrato de licencia.
Si no acepta el Contrato de licencia, no podrá utilizar la Versión preliminar. 2.2 Al hacer clic para aceptar o utilizar la Versión preliminar, por medio del presente, usted acepta los términos del Contrato de licencia. 2.3 Usted no puede utilizar la Versión preliminar ni aceptar el Contrato de licencia si tiene prohibido recibir la Versión preliminar en virtud de las leyes de los Estados Unidos o de otros países, lo que incluye el país donde es residente o desde el que utilizará la Versión preliminar. 2.4 Si usted utilizará la Versión preliminar de forma interna, dentro de su compañía u organización, usted acepta quedar sujeto al Contrato de licencia en representación de su empleador u otra entidad, y expresa y garantiza que tiene plena autoridad legal para vincular a su empleador o a dicha entidad al Contrato de licencia.
Si no posee la autoridad exigida, no podrá aceptar el Contrato de licencia ni usar la Versión preliminar en representación de su empleador u otra entidad. 3.
Licencia de la Versión preliminar de Google 3.1 Sujeto a los términos del Contrato de licencia, Google le otorga una licencia libre de regalías, no asignable, no exclusiva, no transferible a terceros, limitada y revocable para utilizar la Versión preliminar, de forma personal o interna dentro de su compañía u organización, únicamente para desarrollar aplicaciones para ejecutar en la plataforma de Android. 3.2 Usted acepta que Google u otros terceros poseen todos los derechos legales, títulos e intereses en relación con la Versión preliminar, incluidos los Derechos de propiedad intelectual que existan en la Versión preliminar.
Los “Derechos de propiedad intelectual” hacen referencia a todos y cada uno de los derechos en virtud de las leyes de patentes, derechos de autor, secreto comercial y marca comercial, y todos los demás derechos de propiedad. Google se reserva todos los derechos que no se le otorguen expresamente. 3.3 No podrá utilizar la Versión preliminar para ningún otro propósito que no esté expresamente permitido en el Contrato de licencia.
Excepto en la medida que lo exijan las licencias correspondientes de terceros, no podrá: (a) copiar (excepto con fines de copia de seguridad), modificar, adaptar, redistribuir, descompilar, utilizar técnicas de ingeniería inversa, desarmar ni crear trabajos derivados de la Versión preliminar ni de ninguna de sus partes; ni (b) cargar ninguna parte de la Versión preliminar en un teléfono móvil ni en ningún otro dispositivo de hardware (a excepción de una computadora personal), ni podrá combinar ninguna parte de la Versión preliminar con otro software, ni distribuir algún software o dispositivo que incorpore alguna parte de la Versión preliminar. 3.4 Usted acepta que no tomará medidas que pudieran provocar la fragmentación de Android, incluidas, entre otras, la distribución y la participación en la creación o la promoción de un kit de desarrollo de software derivado de la Versión preliminar. 3.5 El uso, la reproducción y la distribución de los componentes de la Versión preliminar con licencia de software de código abierto están regidos exclusivamente por los términos de la licencia de ese software de código abierto y no de este Contrato de licencia.
Usted acepta mantener la licencia en buenas condiciones con respecto a dichas licencias de software de código abierto en virtud de todos los derechos otorgados y acepta abstenerse de realizar alguna acción que pueda poner fin, suspender o violar dichos derechos. 3.6 Usted acepta que la forma y la naturaleza de la Versión preliminar que proporciona Google pueden cambiar sin brindarle aviso previo y que las versiones futuras de la Versión preliminar pueden ser incompatibles con las aplicaciones desarrolladas en versiones anteriores de la Versión preliminar.
Usted acepta que Google puede (de forma permanente o temporal) dejar de proporcionarles la Versión preliminar (o cualquiera de las características incluidas en ella) a usted o a los usuarios, generalmente, a criterio exclusivo de Google, sin brindarle aviso previo. 3.7 Ninguna declaración de este Contrato de licencia le otorga el derecho de utilizar alguno de los nombres comerciales, las marcas comerciales, las marcas de servicio, los logotipos, los nombres de dominio ni otras características distintivas de marca de Google. 3.8 Usted acepta que no eliminará, ocultará ni alterará ninguno de los avisos de derechos de propiedad (lo que incluye los avisos de marca comercial y derechos de autor) que pudieran estar anexados o incluidos en la Versión preliminar. 4.
Uso que usted realiza de la Versión preliminar 4.1 Google acepta que ninguna declaración del Contrato de licencia le concede a Google derecho, título o interés alguno de su parte (o de parte de sus licenciantes), en virtud del Contrato de licencia, con respecto a las aplicaciones de software que usted desarrolle mediante el uso de la Versión preliminar, lo que incluye los derechos de propiedad intelectual que conlleven esas aplicaciones. 4.2 Usted acepta utilizar la Versión preliminar y escribir aplicaciones únicamente conforme a lo que permite (a) este Contrato de licencia y (b) las leyes, regulaciones, o prácticas y pautas generalmente aceptadas pertinentes en las jurisdicciones relevantes (lo que incluye las leyes sobre la exportación de datos o software hacia los Estados Unidos u otros países relevantes y desde ellos). 4.3 Usted acepta que si utiliza la Versión preliminar para desarrollar aplicaciones, protegerá la privacidad y los derechos legales de los usuarios.
Si los usuarios le proporcionan sus nombres de usuario, contraseñas u otra información de inicio de sesión o información personal, debe comunicarles a los usuarios que la información se encontrará disponible para su aplicación, y debe proporcionarles a dichos usuarios un aviso de privacidad con protección y validez legal. Si su aplicación almacena información personal o confidencial proporcionada por los usuarios, lo debe hacer de forma segura. Si los usuarios le proporcionan información sobre la cuenta de Google, su aplicación solo puede usar esa información para acceder a la cuenta de Google del usuario siempre que este le haya otorgado permiso para hacerlo y con los fines para los que se lo haya otorgado. 4.4 Usted acepta que no participará en ninguna actividad con la Versión preliminar (lo que incluye el desarrollo o la distribución de una aplicación) que interfiera, interrumpa, dañe o acceda sin autorización a servidores, redes u otras propiedades o servicios de Google o de algún tercero. 4.5 Usted acepta que es el único responsable (y que Google no asume responsabilidades hacia usted ni terceros) de los datos, el contenido o los recursos que usted cree, transmita o muestre a través de Android o las aplicaciones para Android, y de las consecuencias de sus acciones (lo que incluye la pérdida o el daño que Google pudiera sufrir) al hacerlo. 4.6 Usted acepta que es el único responsable (y que Google no asume responsabilidades hacia usted ni terceros) de cualquier incumplimiento de sus obligaciones en virtud de este Contrato de licencia, los contratos aplicables de terceros o los términos del servicio, o cualquier ley o regulación pertinentes, y de las consecuencias (lo que incluye las pérdidas o los daños que pudieran sufrir Google o algún tercero) de dichos incumplimientos. 4.7 La Versión preliminar se encuentra en desarrollo, y sus pruebas y comentarios son una parte importante del proceso de desarrollo.
Al utilizar la Versión preliminar, usted reconoce que la implementación de algunas características aún se encuentra en desarrollo y que no debe confiar en que la Versión preliminar contará con todas las funcionalidades de una versión estable. Usted acepta no distribuir públicamente ni enviar ninguna aplicación que utilice esta Versión preliminar, ya que esta Versión preliminar ya no se admitirá tras el lanzamiento del SDK oficial de Android. 5.
Sus credenciales de desarrollador 5.1 Usted acepta que es responsable de mantener la confidencialidad de toda credencial de desarrollador que Google pudiera otorgarle o que usted pudiera escoger, y que será el único responsable de todas las aplicaciones que se desarrollen con sus credenciales de desarrollador. 6.
Privacidad e información 6.1 A fin de poder innovar y mejorar de forma continua la Versión preliminar, Google podría recopilar ciertas estadísticas de uso del software, lo que incluye, entre otras características, un identificador único, la dirección IP asociada, el número de versión del software e información sobre las herramientas o los servicios de la Versión preliminar que se estén utilizando y la manera en que se estén utilizando.
Antes de que se recopile esta información, la Versión preliminar se lo notificará y le solicitará su permiso. Si no otorga su permiso, no se recopilará la información. 6.2 Los datos recopilados se analizan en el agregado para mejorar la Versión preliminar y se conservan de acuerdo con la política de privacidad de Google que se encuentra en el sitio http://www.google.com/policies/privacy/. 7.
Aplicaciones de terceros 7.1 Si utiliza la Versión preliminar para ejecutar aplicaciones desarrolladas por un tercero o que accedan a datos, contenido o recursos proporcionados por un tercero, usted acepta que Google no es responsable de esas aplicaciones, datos, contenido ni recursos.
Usted comprende que todos los datos, contenidos o recursos a los que podría acceder a través de esas aplicaciones de terceros son exclusiva responsabilidad de la persona que los origina y que Google no es responsable de las pérdidas ni los daños que usted pudiera experimentar como consecuencia del uso o acceso de cualquiera de esas aplicaciones, datos, contenido o recursos de terceros. 7.2 Usted debe saber que los datos, el contenido y los recursos que se le presentan a través de esa aplicación de un tercero pueden estar protegidos por derechos de propiedad intelectual que les pertenecen a sus proveedores (o a otras personas o compañías en representación de estos).
No puede modificar, alquilar, arrendar, prestar, vender, distribuir ni crear obras derivadas basadas en esos datos, contenidos o recursos (en su totalidad o en parte), a menos que los propietarios pertinentes le hayan otorgado permiso específicamente para hacerlo. 7.3 Usted acepta que el uso que haga de las aplicaciones, los datos, el contenido o los recursos de ese tercero puede estar sujeto a términos independientes entre usted y el tercero correspondiente. 8.
Uso de las API de Google 8.1 API de Google 8.1.1 Si utiliza alguna API para recuperar datos de Google, usted acepta que los datos pueden estar protegidos por derechos de propiedad intelectual que le pertenecen a Google o a las partes que proporcionan esos datos (o a otras personas o empresas en representación de estos).
El uso que realice de cualquiera de esas API puede estar sujeto a términos de servicio adicionales. No puede modificar, alquilar, arrendar, prestar, vender, distribuir ni crear obras derivadas basadas en esos datos (en su totalidad o en parte), a menos que los términos de servicio correspondientes lo permitan. 8.1.2 Si utiliza alguna API para recuperar datos de un usuario de Google, usted acepta y acuerda que solo podrá recuperar datos con el consentimiento explícito del usuario y solo con los fines limitados para los que el usuario le haya otorgado permiso para hacerlo. 9.
Finalización del Contrato de licencia 9.1 Este Contrato de licencia tendrá vigencia hasta que lo revoquen usted o Google, como se indica a continuación. 9.2 Si desea rescindir el Contrato de licencia, puede hacerlo al interrumpir el uso que realiza de la Versión preliminar y de las credenciales de desarrollador pertinentes. 9.3 Google puede, en cualquier momento, rescindir el Contrato de licencia, con causa o sin ella, después de notificárselo a usted. 9.4 El Contrato de licencia finalizará automáticamente, sin previo aviso ni acción alguna, tras la primera de las siguientes situaciones: (A) cuando Google deje de proporcionar la Versión preliminar o ciertas partes de esta a los usuarios en el país donde usted reside o desde el que utiliza el servicio; y (B) cuando Google emita una versión final del SDK de Android. 9.5 Si el Contrato de licencia se rescinde, se revocará la licencia que usted recibió en virtud de dicho contrato; usted deberá suspender inmediatamente todo uso de la Versión preliminar y las disposiciones de los párrafos 10, 11, 12 y 14 seguirán vigentes indefinidamente. 10.
EXENCIONES DE RESPONSABILIDAD 10.1 USTED COMPRENDE Y ACEPTA EXPRESAMENTE QUE EL USO QUE REALICE DE LA VERSIÓN PRELIMINAR ES BAJO SU PROPIO RIESGO Y QUE LA VERSIÓN PRELIMINAR SE PROPORCIONA “EN LAS CONDICIONES EN LAS QUE SE ENCUENTRA” Y “SUJETA A DISPONIBILIDAD” SIN GARANTÍAS DE NINGÚN TIPO POR PARTE DE GOOGLE. 10.2 EL USO QUE USTED REALICE DE LA VERSIÓN PRELIMINAR Y DE TODO MATERIAL DESCARGADO U OBTENIDO DE ALGUNA OTRA MANERA MEDIANTE EL USO DE LA VERSIÓN PRELIMINAR ES A SU ENTERO RIESGO Y DISCRECIÓN, Y USTED ES EL ÚNICO RESPONSABLE DE CUALQUIER DAÑO QUE PUDIERA SUFRIR SU SISTEMA INFORMÁTICO U OTRO DISPOSITIVO, O DE LA PÉRDIDA DE DATOS COMO CONSECUENCIA DE DICHO USO.
SIN PERJUICIO DE LO MENCIONADO ANTERIORMENTE, USTED COMPRENDE QUE LA VERSIÓN PRELIMINAR NO ES UNA VERSIÓN ESTABLE, Y PUEDE CONTENER ERRORES, DEFECTOS Y VULNERABILIDADES DE SEGURIDAD QUE PUEDEN PROVOCAR DAÑOS SIGNIFICATIVOS, LO QUE INCLUYE LA PÉRDIDA COMPLETA E IRRECUPERABLE DEL USO DE SU SISTEMA INFORMÁTICO U OTRO DISPOSITIVO. 10.3 GOOGLE TAMBIÉN RECHAZA TODAS LAS GARANTÍAS Y CONDICIONES DE CUALQUIER TIPO, EXPRESAS O IMPLÍCITAS, INCLUIDAS, ENTRE OTRAS, LAS GARANTÍAS Y CONDICIONES DE COMERCIABILIDAD, IDONEIDAD PARA UN FIN DETERMINADO Y NO VIOLACIÓN. 11.
LIMITACIÓN DE RESPONSABILIDADES 11.1 USTED COMPRENDE Y ACEPTA EXPRESAMENTE QUE GOOGLE, SUS SUBSIDIARIAS Y FILIALES, Y SUS LICENCIANTES NO SERÁN RESPONSABLES ANTE USTED, EN VIRTUD DE NINGUNA TEORÍA DE RESPONSABILIDAD, POR NINGÚN DAÑO DIRECTO, INDIRECTO, INCIDENTAL, ESPECIAL, RESULTANTE NI PUNITIVO EN EL QUE PODRÍA HABER INCURRIDO, LO QUE INCLUYE LA PÉRDIDA DE DATOS, YA SEA QUE SE LE HAYA NOTIFICADO O NO A GOOGLE O A SUS REPRESENTANTES, O SOBRE CUYA POSIBILIDAD ESTOS DEBERÍAN HABER SABIDO. 12.
Indemnización 12.1 Hasta el grado máximo que permita la ley, usted acepta defender, indemnizar y eximir de responsabilidades a Google, sus filiales y sus respectivos directores, funcionarios, empleados y agentes, de todo tipo de reclamo, acción legal y proceso judicial, así como de las pérdidas, responsabilidades, daños, costos y gastos (incluidos los honorarios razonables de abogados) que surjan o se acumulen (a) del uso que usted realiza de la Versión preliminar, (b) de cualquier aplicación que desarrolle en la Versión preliminar que infrinja algún derecho de propiedad intelectual de cualquier persona, o que difame a cualquier persona o viole sus derechos de publicidad o privacidad, y (c) del incumplimiento por su parte del Contrato de licencia. 13.
Cambios en el Contrato de licencia 13.1 Google puede realizar cambios en el Contrato de licencia a medida que distribuye nuevas versiones de la Versión preliminar.
Cuando se realicen esos cambios, Google emitirá una nueva versión del Contrato de licencia, que estará disponible en el sitio web donde se ponga a la venta la Versión preliminar. 14.
Términos legales generales 14.1 El Contrato de licencia constituye el contrato legal integral entre usted y Google, y rige el uso que usted realice de la Versión preliminar (a excepción de los servicios que Google pueda proporcionarle en virtud de un contrato por escrito independiente), y reemplaza totalmente cualquier contrato anterior entre usted y Google en relación con la Versión preliminar. 14.2 Usted acepta que, si Google no ejerce ni impone un derecho o recurso legal especificados en el Contrato de licencia (o sobre el que Google tenga beneficios conforme a cualquier ley aplicable), esto no se considerará una renuncia formal a los derechos por parte de Google y Google aún seguirá recibiendo los beneficios de esos derechos o recursos legales. 14.3 Si algún tribunal judicial con jurisdicción para decidir sobre este asunto determina que alguna de las disposiciones de este Contrato de licencia no es válida, se eliminará esa disposición del Contrato de licencia sin que eso afecte la validez del resto del contrato.
Las disposiciones restantes del Contrato de licencia continuarán siendo válidas y aplicables. 14.4 Usted reconoce y acepta que cada miembro del grupo de compañías de las que Google es la compañía central serán terceros beneficiarios del Contrato de licencia, y que esas otras empresas tendrán el derecho de imponer directamente cualquier disposición y ampararse en las disposiciones de este Contrato de licencia que les confieran un beneficio (o que confieran derechos a su favor).
Además de esto, ninguna otra persona o compañía serán terceros beneficiarios del Contrato de licencia. 14.5 RESTRICCIONES DE EXPORTACIÓN.
LA VERSIÓN PRELIMINAR ESTÁ SUJETA A LAS LEYES Y REGULACIONES DE EXPORTACIÓN DE LOS ESTADOS UNIDOS. DEBE CUMPLIR CON TODAS LAS LEYES Y REGULACIONES DE EXPORTACIÓN NACIONALES E INTERNACIONALES QUE SE APLIQUEN A LA VERSIÓN PRELIMINAR. ESTAS LEYES INCLUYEN RESTRICCIONES EN RELACIÓN CON LOS DESTINOS, USUARIOS FINALES Y USO FINAL. 14.6 Usted no puede asignar ni transferir el Contrato de licencia sin la aprobación previa por escrito de Google y todo intento de asignación sin dicha aprobación no tendrá validez.
No podrá delegar sus responsabilidades u obligaciones otorgados en virtud del Contrato de licencia sin la aprobación previa por escrito de Google. 14.7 El Contrato de licencia y su relación con Google conforme al Contrato de licencia se regirán por las leyes del estado de California, independientemente de los principios de conflictos entre leyes.
Usted y Google aceptan presentarse ante la jurisdicción exclusiva de los tribunales del condado de Santa Clara, California, para resolver cualquier asunto legal que pudiera surgir del Contrato de licencia. Sin perjuicio de esto, usted acepta que Google aún podrá aplicar reparaciones conforme a mandato judicial (o a un tipo equivalente de desagravio legal) en cualquier jurisdicción.
</div><!-- sdk terms -->
<div id="sdk-terms-form">
<p>
<input id="agree" type="checkbox" name="agree" value="1" onclick="onAgreeChecked()" />
<label id="agreeLabel" for="agree">He leído y acepto los términos y las condiciones anteriores.</label>
</p>
<p><a href="" class="button disabled" id="downloadForRealz" onclick="return onDownloadForRealz(this);"></a></p>
</div>
</div><!-- end TOS -->
<div id="landing">
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento</h2>
<ol>
<li><a href="#sdk">Android 6.0 SDK</a></li>
<li><a href="#docs">Documentación para desarrolladores</a></li>
<li><a href="#images">Imágenes del sistema de hardware</a></li>
</ol>
<h2>Legacy downloads</h2>
<ol>
<li><a href="{@docRoot}preview/download_mp1.html">Developer Preview 1</a></li>
<li><a href="{@docRoot}preview/download_mp2.html">Developer Preview 2</a></li>
</ol>
</div>
</div>
<p>
El SDK de la versión preliminar de Android M incluye herramientas de desarrollo, archivos de sistema de Android y archivos de biblioteca que lo ayudarán a probar su aplicación y las nuevas API que se incluirán en la próxima versión de la plataforma.
En este documento, se describe la manera de obtener los componentes que se pueden descargar de la versión preliminar para probar su aplicación.
</p>
<h2 id="sdk">Android 6.0 SDK</h2>
<p>
El SDK de la versión preliminar se encuentra disponible para descargarlo a través del <a href="{@docRoot}tools/help/sdk-manager.html">Administrador de SDK de Android</a>. Para obtener más información sobre cómo descargar y configurar el SDK de la versión preliminar, consulte la sección <a href="{@docRoot}preview/setup-sdk.html#downloadSdk">Configurar el SDK de la versión preliminar</a>.
</p>
<h2 id="docs">Documentación para desarrolladores</h2>
<p>
El paquete de descarga de documentación para desarrolladores brinda información detallada de referencia sobre las API y un informe de diferencias de las API para la versión preliminar.
</p>
<table>
<tr>
<th scope="col">Description</th>
<th scope="col">Download / Checksums</th>
</tr>
<tr id="docs-dl">
<td>Android M Preview 3<br>Developer Docs</td>
<td><a href="#top" onclick="onDownload(this)"
>m-preview-3-developer-docs.zip</a><br>
MD5: d99b14b0c06d31c8dfecb25072654ca3<br>
SHA-1: 9cefeeda07676130da606a1796e1c00fffc667c1
</td>
</tr>
</table>
<h2 id="images">Imágenes del sistema de hardware</h2>
<p>
Estas imágenes del sistema le permiten instalar una versión preliminar de la plataforma en un dispositivo físico para realizar pruebas.
Al configurar un dispositivo con una de estas imágenes, puede instalar y probar su aplicación para ver cómo funciona en la próxima versión de la plataforma.
El proceso de instalación de una imagen del sistema en un dispositivo <em>elimina todos los datos del dispositivo</em>, por lo que debe hacer una copia de seguridad de los datos antes de instalar una imagen del sistema.
</p>
<p class="warning">
<b>Advertencia:</b> Las siguientes imágenes del sistema de Android son versiones preliminares y están sujetas a cambios. El uso que haga de estas imágenes del sistema se rige por el Contrato de licencia de la versión preliminar del SDK de Android.
Las imágenes del sistema de la versión preliminar de Android no son versiones estables y pueden contener errores y defectos que pueden generar daños en sus sistemas informáticos, dispositivos y datos.
Las imágenes del sistema de la versión preliminar de Android no se someten a las mismas pruebas que el OS de fábrica y podrían hacer que el teléfono, y las aplicaciones y los servicios instalados dejen de funcionar.
</p>
<table>
<tr>
<th scope="col">Device</th>
<th scope="col">Download / Checksums</th>
</tr>
<tr id="hammerhead">
<td>Nexus 5 (GSM/LTE) <br>"hammerhead"</td>
<td><a href="#top" onclick="onDownload(this)"
>hammerhead-MPA44I-preview-2ebbc049.tgz</a><br>
MD5: 91a924fb0c9f8e716e3b4c9954fd0dbb<br>
SHA-1: 2ebbc049b68c4da8baeee3e42bb94d7a965ba4a3
</td>
</tr>
<tr id="shamu">
<td>Nexus 6 <br>"shamu"</td>
<td><a href="#top" onclick="onDownload(this)"
>shamu-MPA44I-preview-62b9c486.tgz</a><br>
MD5: ac6e58da86125073d9c395257fd42664<br>
SHA-1: 62b9c486fd7a5020e228d53ca5acd5c1857e48ff
</td>
</tr>
<tr id="volantis">
<td>Nexus 9 <br>"volantis"</td>
<td><a href="#top" onclick="onDownload(this)"
>volantis-MPA44I-preview-5c30a6e2.tgz</a><br>
MD5: 7f83768757913d3fea945a661020d185<br>
SHA-1: 5c30a6e2acd11a81f4105b12d23ff654f534f699
</td>
</tr>
<tr id="fugu">
<td>Nexus Player <br>"fugu"</td>
<td><a href="#top" onclick="onDownload(this)"
>fugu-MPA44I-preview-2860040a.tgz</a><br>
MD5: 438da8d37da9e341a69cfb16a4001ac5<br>
SHA-1: 2860040a326582f1ff5f702bf9a1ef002717fc98
</td>
</tr>
</table>
<h3 id="install-image">Instalar una imagen en un dispositivo</h3>
<p>
Si desea utilizar una imagen del dispositivo para realizar pruebas, debe instalarla en un dispositivo compatible. Siga las instrucciones que se ofrecen a continuación para instalar una imagen del sistema:
</p>
<ol>
<li>Descargue y descomprima uno de los paquetes de imágenes del sistema que se enumeran aquí.</li>
<li>Realice una copia de seguridad de los datos del dispositivo que desee conservar.</li>
<li>Siga las instrucciones que se describen en el sitio <a href="https://developers.google.com/android/nexus/images#instructions">developers.google.com/android</a>
para actualizar la imagen en su dispositivo.
</li>
</ol>
<p class="note">
<strong>Nota:</strong> Cuando haya actualizado un dispositivo de desarrollo con la imagen del sistema de la versión preliminar, se actualizará automáticamente con la próxima versión preliminar a través de actualizaciones OTA.
</p>
<h3 id="revertDevice">Restablecer las especificaciones de fábrica en un dispositivo</h3>
<p>
Si desea desinstalar la versión preliminar y restablecer las especificaciones de fábrica en un dispositivo, visite el sitio <a href="http://developers.google.com/android/nexus/images">developers.google.com/android</a> y descargue la imagen con la que desea actualizar su dispositivo.
Siga las instrucciones que se describen en esa página para actualizar la imagen en su dispositivo.
</p>
</div><!-- landing -->
</div><!-- relative wrapper -->
<script>
var urlRoot = "http://storage.googleapis.com/androiddevelopers/shareables/preview/";
function onDownload(link) {
$("#downloadForRealz").html("Download " + $(link).text());
$("#downloadForRealz").attr('href', urlRoot + $(link).text());
$("#tos").fadeIn('fast');
$("#landing").fadeOut('fast');
return true;
}
function onAgreeChecked() {
/* verify that the TOS is agreed */
if ($("input#agree").is(":checked")) {
/* reveal the download button */
$("a#downloadForRealz").removeClass('disabled');
} else {
$("a#downloadForRealz").addClass('disabled');
}
}
function onDownloadForRealz(link) {
if ($("input#agree").is(':checked')) {
/*
$("#tos").fadeOut('fast');
$("#landing").fadeIn('fast');
*/
ga('send', 'event', 'M Preview', 'System Image', $("#downloadForRealz").html());
/*
location.hash = "";
*/
return true;
} else {
return false;
}
}
$(window).hashchange( function(){
if (location.hash == "") {
location.reload();
}
});
</script>

View File

@@ -1,123 +0,0 @@
page.title=Vínculos de la aplicación
page.image=images/cards/card-app-linking_2x.png
page.keywords=vínculo de la aplicación, vínculos profundos, intentos
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento</h2>
<ol>
<li><a href="#web-assoc">Declarar la asociación de un sitio web</a></li>
<li><a href="#verfy-links">Solicitar verificación del vínculo de la aplicación</a></li>
<li><a href="#user-manage">Gestionar las configuraciones del vínculo de la aplicación</a></li>
</ol>
</div>
</div>
<p>
El sistema Android Intent es un mecanismo flexible para permitir a las aplicaciones controlar contenido y solicitudes.
Es posible que múltiples aplicaciones declaren modelos URI coincidentes en sus filtros de intento. Cuando un usuario hace clic en un vínculo web que no tiene un controlador de inicio predeterminado, la plataforma puede mostrar un diálogo para que el usuario seleccione una opción de una lista de aplicaciones que han declarado filtros de intento coincidentes.
</p>
<p>
Android M Developer Preview ofrece soporte para los vínculos de la aplicación, lo que mejora los controles de vínculos existentes al permitir a los desarrolladores de la aplicación asociar una aplicación con un dominio web propio.
Cuando los desarrolladores crean esta asociación, la plataforma puede determinar automáticamente la aplicación predeterminada utilizada para controlar un vínculo web particular y omitir el paso de solicitarles esta información a los usuarios.
</p>
<h2 id="web-assoc">Declarar una asociación de sitio web</h2>
<p>
Los propietarios de un sitio web deben declarar las asociaciones con las aplicaciones a fin de establecer el vínculo de una aplicación. El propietario del sitio declara la relación con una aplicación al alojar un archivo JSON, denominado {@code statements.json}, en la ubicación conocida del domino:
</p>
<pre>http://&lt;domain&gt;:&lt;optional port&gt;/.well-known/statements.json</pre>
<p class="note">
<strong>Nota:</strong>
Durante el período de M Developer Preview, el archivo JSON se verifica vía el protocolo http. Para la versión oficial de la plataforma, el archivo se verifica mediante el protocolo https cifrado.
</p>
<p>
Este archivo JSON indica la aplicación Android que se debe utilizar como el controlador predeterminado para las URL de este dominio.
Identifica la aplicación según estos campos:
</p>
<ul>
<li>{@code package_name}: El nombre de paquete declarado en el manifiesto de la aplicación.</li>
<li>{@code sha256_cert_fingerprints}: La huella dactilar SHA256 del certificado de firma de su aplicación.
Puede usar la herramienta Keytool de Java para generar la huella dactilar mediante el siguiente comando:
<pre>keytool -list -v -keystore my-release-key.keystore</pre>
</li>
</ul>
<p>
El siguiente listado de archivo muestra un ejemplo de los contenidos y del formato de un archivo
{@code statements.json}:
</p>
<pre>
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "<strong>&lt;package name&gt;</strong>",
"sha256_cert_fingerprints": ["<strong>6C:EC:C5:0E:34:AE....EB:0C:9B</strong>"]
}
}]
</pre>
<h2 id="verfy-links">Solicitar verificación del vínculo de la aplicación</h2>
<p>
Una aplicación puede solicitar que la plataforma verifique automáticamente cualquier vínculo de aplicación definido por los nombres de host en los elementos de datos de sus filtros de intento, comparando con los archivos {@code statements.json} alojados en los respectivos dominios web.
Para solicitar la verificación del vínculo de la aplicación, agregue un atributo {@code android:autoVerify} a cada filtro de intento deseado en el manifiesto, como se muestra en el siguiente fragmento de código de manifiesto:
</p>
<pre>
&lt;activity ...&gt;
&lt;intent-filter <strong>android:autoVerify="true"</strong>&gt;
&lt;action android:name="android.intent.action.VIEW" /&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;category android:name="android.intent.category.BROWSABLE" /&gt;
&lt;data android:scheme="http" android:host="www.android.com" /&gt;
&lt;data android:scheme="https" android:host="www.android.com" /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>
<p>
Cuando el atributo {@code android:autoVerify} está presente en un manifiesto de aplicación, la plataforma intenta verificar los vínculos de la aplicación al instalar la aplicación.
Si la plataforma no puede verificar exitosamente los vínculos de la aplicación, la aplicación no se configura como la aplicación preferida para controlar los vínculos web.
La próxima vez que un usuario abra uno de estos vínculos, la plataforma recurrirá a mostrar al usuario un diálogo.
</p>
<p class="note">
<strong>Nota:</strong> Durante la prueba, existe la posibilidad de un falso positivo si la verificación falla, pero el usuario ha habilitado explícitamente la aplicación para que abra los vínculos compatibles sin preguntar, utilizando la aplicación de Configuraciones del sistema. En este caso, no se muestra el diálogo y el vínculo se dirige directamente a su aplicación, pero solo debido a la configuración del usuario y no porque la verificación se haya realizado correctamente.
</p>
<h2 id="user-manage">Gestionar las configuraciones del vínculo de la aplicación</h2>
<p>
Los usuarios pueden cambiar las configuraciones del vínculo de la aplicación de manera que las URL se controlen como ellos lo prefieran. Puede revisar y gestionar los vínculos de la aplicación en la aplicación de Configuraciones del sistema, en <strong>Settings &gt; Apps &gt; App Info &gt; Open by default</strong>.
</p>

View File

@@ -1,794 +0,0 @@
page.title=Permisos
page.tags=previewresources, androidm
page.keywords=permissions, runtime, preview
page.image={@docRoot}preview/features/images/permissions_check.png
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>Si su aplicación tiene como destino el SDK de la versión preliminar de Android M, se solicitará a los usuarios que concedan permisos durante el tiempo de ejecución, en lugar de durante la instalación.
</li>
<li>Los usuarios pueden cancelar los permisos en cualquier momento desde la pantalla Settings de la aplicación.
</li>
<li>La aplicación necesita controlar los permisos cada vez que se ejecuta.
</li>
</ul>
<h2>Contenido del documento</h2>
<ol>
<li><a href="#overview">Información general</a></li>
<li><a href="#coding">Codificación para permisos de tiempo de ejecución</a></li>
<li><a href="#testing">Prueba de permisos de tiempo de ejecución</a></li>
<li><a href="#best-practices">Mejores prácticas</a></li>
</ol>
<!--
<h2>Related Samples</h2>
<ol>
<li></li>
</ol>
-->
<!--
<h2>See also</h2>
<ol>
<li></li>
</ol>
-->
</div> <!-- qv -->
</div> <!-- qv-wrapper -->
<p>
M Developer Preview introduce un nuevo modelo de permisos de la aplicación que facilita a los usuarios el proceso de instalación y actualización de aplicaciones.
Si una aplicación que se ejecuta en la versión preliminar de Android M es compatible con el nuevo modelo de permisos, el usuario no tiene que conceder ningún permiso al instalar o actualizar la aplicación. En su lugar, la aplicación solicitará los permisos a medida que los vaya necesitado y el sistema mostrará al usuario un diálogo en el que le solicitará los permisos necesarios.
</p>
<p>
Si la aplicación es compatible con el nuevo modelo de permisos, podrá instalarse y ejecutarse en los dispositivos con versiones anteriores de Android, utilizando el modelo de permisos anterior en esos dispositivos.
</p>
<h2 id="overview">
Información general
</h2>
<p>
En M Developer Preview, la plataforma introduce un nuevo modelo
de permisos de la aplicación. A continuación, se presenta un resumen de los componentes principales de este nuevo modelo:
</p>
<ul>
<li>
<strong>Declaración de los permisos:</strong> Al igual que en las plataformas anteriores de Android, la aplicación declara todos los permisos que necesita en el manifiesto.
</li>
<li>
<strong>Grupos de permisos:</strong> Según su función, los permisos se dividen en
<em>grupos de permisos</em>. Por ejemplo, el grupo de permisos
<code>CONTACTS</code> contiene permisos para leer y escribir los contactos y la información de perfil del usuario.
</li>
<li>
<p><strong>Permisos limitados concedidos durante la instalación:</strong> Cuando el usuario instala o actualiza la aplicación, el sistema le concede a la aplicación todos los permisos que la aplicación solicita que corresponden a {@link
android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}.
Por ejemplo, los permisos para la alarma y los permisos de intento corresponden a {@link
android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}, por lo que se conceden automáticamente durante la instalación.
</p>
<p>El sistema puede concederle a la aplicación permisos de firma y de sistema, como se especifica en la sección <a href="#system-apps">Permisos de firma y de sistema de la aplicación</a>.
Al usuario <em>no</em> se le solicitará conceder ningún permiso durante la instalación.
</p>
</li>
<li>
<strong>Solicitud de permisos al usuario durante el tiempo de ejecución:</strong> Cuando la aplicación solicita un permiso, el sistema le muestra al usuario un diálogo y luego llama a la función de devolución de llamada de la aplicación para notificarle si el permiso se otorgó.
Si el usuario concede un permiso, la aplicación recibe todos los permisos del área funcional de dicho permiso, los cuales fueron declarados en el manifiesto de la aplicación.
</li>
</ul>
<p>
Este modelo de permisos cambia la forma en la que la aplicación se comporta para características que requieren permisos.
A continuación, se presenta un resumen de las prácticas de desarrollo que debe seguir para ajustarse a este modelo:
</p>
<ul>
<li>
<strong>Siempre compruebe los permisos:</strong> Siempre que una aplicación necesite realizar una acción que requiere algún permiso, primero debe comprobar si ya tiene otorgado ese permiso.
En caso de no tenerlo, solicitará que se le otorgue ese permiso.
</li>
<li>
<strong>Administre la falta de permisos correctamente:</strong> Si la aplicación no recibe un permiso adecuado, deberá administrar la falla sin errores.
Por ejemplo, si se necesita el permiso solo para una característica añadida, la aplicación puede desactivar esa característica.
Si el permiso es fundamental para que la aplicación funcione, la aplicación podrá desactivar toda su funcionalidad e informar al usuario que se deben conceder dichos permisos.
</li>
<div class="figure" style="width:220px" id="fig-perms-screen">
<img src="{@docRoot}preview/features/images/app-permissions-screen_2x.png" srcset="{@docRoot}preview/features/images/app-permissions-screen.png 1x, {@docRoot}preview/features/images/app-permissions-screen_2x.png 2x" alt="" width="220">
<p class="img-caption">
<strong>Figura 1</strong> Pantalla de permisos en Settings de la aplicación.
</p>
</div>
<li>
<strong>Los permisos son revocables:</strong> Los usuarios pueden revocar los permisos en cualquier momento.
Si un usuario desactiva los permisos de una aplicación, la aplicación <em>no</em> recibe ningún aviso.
Nuevamente, la aplicación deberá verificar que cuenta con los permisos necesarios antes de realizar cualquier acción restringida.
</li>
</ul>
<p class="note">
<strong>Nota:</strong> Si una aplicación tiene como destino M Developer Preview, <em>debe</em> utilizar el nuevo modelo de permisos.
</p>
<p>
A partir del lanzamiento de M Developer Preview, no todas las aplicaciones de Google implementarán por completo el nuevo modelo de permisos.
Google actualiza estas aplicaciones durante el transcurso de M Developer Preview para respetar adecuadamente las configuraciones de alternancia de los permisos.
</p>
<p class="note">
<strong>Nota:</strong> Si la aplicación cuenta con su propia superficie de API, no transmita permisos sin antes asegurarse de que el iniciador de la llamada cuente con los permisos requeridos para acceder a esa información.
</p>
<h3 id="system-apps">
Permisos de las aplicaciones de firma y de sistema
</h3>
<p>
Generalmente, cuando el usuario instala una aplicación, el sistema solo otorga a la aplicación
{@link android.content.pm.PermissionInfo#PROTECTION_NORMAL
PROTECTION_NORMAL}. Sin embargo, en ciertas circunstancias, el sistema le concede a la aplicación más permisos:
</p>
<ul>
<li>Si una aplicación es parte de la imagen del sistema, la aplicación recibe automáticamente todos los permisos enumerados en el manifiesto.
</li>
<li>Si la aplicación solicita permisos en el manifiesto que corresponden a {@link
android.content.pm.PermissionInfo#PROTECTION_SIGNATURE PROTECTION_SIGNATURE} y la aplicación está firmada con el mismo certificado que el de la aplicación que declaró dichos permisos, el sistema le concede a la aplicación que los solicita esos permisos durante la instalación.
</li>
</ul>
<p>
En ambos casos, el usuario aún puede revocar los permisos en cualquier momento si accede a la pantalla <strong>Settings</strong> del sistema y selecciona <strong>Apps &gt;</strong>
<i>app_name</i> <strong>&gt; Permissions</strong>. La aplicación debe seguir controlando los permisos al momento de la ejecución y solicitarlos si fuese necesario.
</p>
<h3 id="compatibility">
Compatibilidad con modelos anteriores y posteriores
</h3>
<p>
Si una aplicación no tiene como destino M Developer Preview, la aplicación continúa utilizando el modelo de permisos anterior, incluso en dispositivos con la versión preliminar de Android M.
Cuando el usuario instala la aplicación, el sistema le solicita al usuario que otorgue todos los permisos enumerados en el manifiesto de la aplicación.
</p>
<p class="note">
<strong>Nota:</strong> En dispositivos que ejecutan M Developer Preview, el usuario puede desactivar los permisos para cualquier aplicación (incluso para aplicaciones heredadas) desde la pantalla Settings de la aplicación.
Si un usuario desactiva permisos para una aplicación heredada, el sistema desactiva las funciones correspondientes de forma automática.
Cuando la aplicación intenta realizar una operación que requiere ese permiso, la operación no generará necesariamente una excepción.
En su lugar, devolverá un conjunto de datos vacíos, indicará un error o, de lo contrario, mostrará un comportamiento inesperado.
Por ejemplo, si realiza una consulta sobre el calendario sin permisos, el método devuelve un conjunto de datos vacíos.
</p>
<p>
Si instala una aplicación que utiliza el nuevo modelo de permisos en un dispositivo que no ejecuta la versión preliminar de Android M, el sistema la trata como cualquier otra aplicación: el sistema le pide al usuario, durante la instalación, que conceda los permisos declarados.
</p>
<p class="note">
<strong>Nota:</strong> Para el lanzamiento de la versión preliminar, debe configurar la versión mínima del SDK en M Preview SDK para compilar con la versión del SDK preliminar.
Esto significa que no podrá probar dichas aplicaciones en plataformas anteriores durante la versión preliminar para desarrolladores.
</p>
<h3 id="perms-vs-intents">Permisos frente a intentos</h3>
<p>
En muchas situaciones, puede elegir entre dos formas para que sus aplicaciones realicen una tarea.
Puede hacer que su aplicación solicite permiso para realizar la operación por sí misma.
De lo contrario, puede hacer que la aplicación utilice un intento para que otra aplicación realice la tarea.
</p>
<p>
Por ejemplo, supongamos que su aplicación necesita poder tomar fotografías con la cámara del dispositivo.
Su aplicación puede solicitar el permiso
<code>android.permission.CAMERA</code>, lo que le permite a su aplicación acceder a la cámara directamente.
Entonces, su aplicación utilizará las API de la cámara para controlar la cámara y tomar una fotografía.
Este enfoque le otorga a su aplicación total control del proceso de fotografía y le permite incorporar la UI de la cámara en su aplicación.
</p>
<p>
Sin embargo, si no necesita dicho control, puede utilizar {@link
android.provider.MediaStore#ACTION_IMAGE_CAPTURE ACTION_IMAGE_CAPTURE} para solicitar una imagen.
Cuando ejecute el intento, se le solicita al usuario que elija una aplicación de cámara (en caso de que no haya una aplicación de cámara predeterminada) y esa aplicación tomará la fotografía.
La aplicación de cámara devuelve la fotografía al método {@link
android.app.Activity#onActivityResult onActivityResult()} de su aplicación.
</p>
<p>
De manera similar, si necesita realizar una llamada telefónica, acceder a los contactos del usuario, etc., lo puede hacer creando intentos apropiados o puede solicitar los permisos e ingresar directamente a los objetos apropiados.
Cada enfoque tiene ventajas y desventajas.
</p>
<p>
Si utiliza los permisos:
</p>
<ul>
<li>La aplicación posee total control sobre la experiencia del usuario cuando usted realiza la operación.
Sin embargo, un control tan amplio complica su tarea, ya que usted deberá diseñar una UI apropiada.
</li>
<li>Se le solicita al usuario otorgar el permiso una vez, la primera vez que usted realiza la operación.
Luego, su aplicación puede realizar la operación sin requerir interacción adicional por parte del usuario.
Sin embargo, si el usuario no concede el permiso (o lo revoca luego), su aplicación queda inhabilitada para realizar la operación.
</li>
</ul>
<p>
Si utiliza un intento:
</p>
<ul>
<li>No debe diseñar la UI para la operación. La aplicación que controla el intento provee la UI. Sin embargo, esto significa que usted no tiene control sobre la experiencia del usuario.
El usuario podrá interactuar con una aplicación que usted no conoce.
</li>
<li>Si el usuario no tiene una aplicación predeterminada para la operación, el sistema le solicita al usuario que elija una aplicación. Si el usuario no designa un controlador predeterminado, es probable que surja un diálogo adicional cada vez que realice la operación.
</li>
</ul>
<h2 id="coding">Codificación para permisos de tiempo de ejecución</h2>
<p>
Si su aplicación tiene como destino el nuevo M Developer Preview, deberá usar el nuevo modelo de permisos.
Esto significa que, además de declarar los permisos necesarios en el manifiesto, también debe comprobar si tiene los permisos de tiempo de ejecución y solicitarlos en caso de no tenerlos.
</p>
<h3 id="enabling">
Habilitar el nuevo modelo de permisos
</h3>
<p>
Para habilitar el nuevo modelo de permisos de M Developer Preview, configure el atributo
<code>targetSdkVersion</code> de la aplicación en <code>"MNC"</code> y
<code>compileSdkVersion</code> en <code>"android-MNC"</code>. Al hacerlo, se habilitan todas las características de los nuevos permisos.
</p>
<p>
Para el lanzamiento de la versión preliminar, debe establecer <code>minSdkVersion</code> en
<code>"MNC"</code> para compilar con el SDK preliminar.
</p>
<h3 id="m-only-perm">
Establecer un permiso solo para la versión preliminar de Android M
</h3>
<p>
Puede utilizar el nuevo elemento <code>&lt;uses-permission-sdk-m&gt;</code> en el manifiesto de la aplicación para indicar que se necesita un permiso solo para M Developer Preview.
Si declara un permiso de esta manera, cuando la aplicación se instale en un dispositivo anterior, el sistema no le solicitará al usuario el permiso ni se lo otorgará a la aplicación. Al usar el elemento <code>&lt;uses-permission-sdk-m&gt;</code>, puede añadir nuevos permisos a las versiones actualizadas de su aplicación sin forzar a los usuarios a otorgar permisos cuando instalen la actualización.
</p>
<p>
Si la aplicación se ejecuta en un dispositivo con M Developer Preview,
<code>&lt;uses-permission-sdk-m&gt;</code> se comporta al igual que
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>.
El sistema no le solicita al usuario que otorgue ningún permiso al instalar la aplicación y la aplicación solicita los permisos a medida que se necesiten.
</p>
<h3 id="prompting">
Solicitar permisos
</h3>
<p>
Si su aplicación utiliza el nuevo modelo de permisos de M Developer Preview, no se le pedirá al usuario que otorgue todos los permisos cuando la aplicación se ejecute por primera vez en un dispositivo con la versión preliminar de Android M.
En su lugar, su aplicación solicita los permisos a medida que los necesita.
Cuando su aplicación solicita un permiso, el sistema le muestra un diálogo al usuario.
</p>
<p>
Si su aplicación se ejecuta en un dispositivo con SDK 22 o anterior, la aplicación utiliza el modelo de permisos anterior.
Cuando el usuario instala la aplicación, se le solicita que otorgue todos los permisos que la aplicación requiere en su manifiesto, excepto aquellos permisos marcados con <code>&lt;uses-permission-sdk-m&gt;</code>.
</p>
<h4 id="check-platform">Controlar en qué plataforma se ejecuta la aplicación</h4>
<p>
Este modelo de permisos es compatible solamente con dispositivos que ejecutan M Developer Preview.
Antes de llamar a cualquiera de estos métodos, la aplicación debe verificar en qué plataforma se está ejecutando y, para hacerlo, se controla el valor de {@link android.os.Build.VERSION#CODENAME
Build.VERSION.CODENAME}.
Si el dispositivo ejecuta M Developer Preview,
{@link android.os.Build.VERSION#CODENAME CODENAME} es <code>"MNC"</code>.
</p>
<h4 id="check-for-permission">Controlar si la aplicación cuenta con los permisos necesarios</h4>
<p>Cuando el usuario intenta realizar algo que requiere un permiso, la aplicación controla si ya tiene el permiso para realizar esa operación.
Para hacerlo, la aplicación llama a <code>Context.checkSelfPermission(
<i>permission_name</i>)</code>. La aplicación debe realizar este control incluso si sabe que el usuario ya ha concedido ese permiso, ya que el usuario puede revocar los permisos de una aplicación en cualquier momento.
Por ejemplo, si un usuario quiere usar una aplicación para tomar una fotografía, la aplicación llama a <code>Context.checkSelfPermission(Manifest.permission.CAMERA)</code>.
</p>
<p class="table-caption" id="permission-groups">
<strong>Tabla 1.</strong> Permisos y grupo de permisos.</p>
<table>
<tr>
<th scope="col">Grupo de permisos</th>
<th scope="col">Permisos</th>
</tr>
<tr>
<td><code>android.permission-group.CALENDAR</code></td>
<td>
<ul>
<li>
<code>android.permission.READ_CALENDAR</code>
</li>
</ul>
<ul>
<li>
<code>android.permission.WRITE_CALENDAR</code>
</li>
</ul>
</td>
</tr>
<tr>
<td><code>android.permission-group.CAMERA</code></td>
<td>
<ul>
<li>
<code>android.permission.CAMERA</code>
</li>
</ul>
</td>
</tr>
<tr>
<td><code>android.permission-group.CONTACTS</code></td>
<td>
<ul>
<li>
<code>android.permission.READ_CONTACTS</code>
</li>
<li>
<code>android.permission.WRITE_CONTACTS</code>
</li>
<li>
<code>android.permission.READ_PROFILE</code>
</li>
<li>
<code>android.permission.WRITE_PROFILE</code>
</li>
</ul>
</td>
</tr>
<tr>
<td><code>android.permission-group.LOCATION</code></td>
<td>
<ul>
<li>
<code>android.permission.ACCESS_FINE_LOCATION</code>
</li>
<li>
<code>android.permission.ACCESS_COARSE_LOCATION</code>
</li>
</ul>
</td>
</tr>
<tr>
<td><code>android.permission-group.MICROPHONE</code></td>
<td>
<ul>
<li>
<code>android.permission.RECORD_AUDIO</code>
</li>
</ul>
</td>
</tr>
<tr>
<td><code>android.permission-group.PHONE</code></td>
<td>
<ul>
<li>
<code>android.permission.READ_PHONE_STATE</code>
</li>
<li>
<code>android.permission.CALL_PHONE</code>
</li>
<li>
<code>android.permission.READ_CALL_LOG</code>
</li>
<li>
<code>android.permission.WRITE_CALL_LOG</code>
</li>
<li>
<code>com.android.voicemail.permission.ADD_VOICEMAIL</code>
</li>
<li>
<code>android.permission.USE_SIP</code>
</li>
<li>
<code>android.permission.PROCESS_OUTGOING_CALLS</code>
</li>
</ul>
</td>
</tr>
<tr>
<td><code>android.permission-group.SENSORS</code></td>
<td>
<ul>
<li>
<code>android.permission.BODY_SENSORS</code>
</li>
</ul>
<ul>
<li>
<code>android.permission.USE_FINGERPRINT</code>
</li>
</ul>
</td>
</tr>
<tr>
<td><code>android.permission-group.SMS</code></td>
<td>
<ul>
<li>
<code>android.permission.SEND_SMS</code>
</li>
<li>
<code>android.permission.RECEIVE_SMS</code>
</li>
<li>
<code>android.permission.READ_SMS</code>
</li>
<li>
<code>android.permission.RECEIVE_WAP_PUSH</code>
</li>
<li>
<code>android.permission.RECEIVE_MMS</code>
</li>
<li>
<code>android.permission.READ_CELL_BROADCASTS</code>
</li>
</ul>
</td>
</tr>
</table>
<h4 id="request-permissions">Solicitar permisos si se necesitan</h4>
<p>Si la aplicación no posee los permisos que necesita, llama al método
<code>Activity.requestPermissions(String[], int)</code> para solicitar el permiso o los permisos apropiados.
La aplicación pasa el permiso o los permisos que necesita y un “código de solicitud” entero.
Este método funciona de manera asincrónica: realiza la devolución inmediatamente y cuando el usuario responde a la ventana de diálogo, el sistema llama al método de devolución de llamada de la aplicación con los resultados, y pasa el mismo “código de solicitud” que pasó la aplicación a
<code>requestPermissions()</code>.
</p>
<p>El siguiente código verifica si la aplicación tiene permisos para leer los contactos del usuario y solicita los permisos de ser necesario:
</p>
<pre>
if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant
return;
}
</pre>
<h4 id="handle-response">Administrar la respuesta a la solicitud de permisos</h4>
<p>
Cuando una aplicación solicita permisos, el sistema le muestra al usuario una ventana de diálogo.
Cuando el usuario responde, el sistema invoca
<code>Activity.onRequestPermissionsResult(int, String[], int[])</code>
de su aplicación y le transfiere la respuesta del usuario. Su aplicación necesita invalidar ese método. La devolución de llamada pasa el mismo código de solicitud que usted pasó a <code>requestPermissions()</code>.
Por ejemplo, si una aplicación solicita acceso <code>READ_CONTACTS</code>, es posible que tenga el siguiente método de devolución de llamada:
</p>
<pre>
&#64;Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! do the
// calendar task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'switch' lines to check for other
// permissions this app might request
}
}
</pre>
<p>Si el usuario concede un permiso, el sistema le otorga a la aplicación todos los permisos enumerados en el manifiesto para esa área funcional.
Se deben tomar acciones apropiadas si el usuario rechaza la solicitud.
Por ejemplo, usted podría desactivar cualquier acción del menú que dependa de este permiso.
</li>
</p>
<p>
Cuando el sistema le solicita al usuario que otorgue un permiso, el usuario tiene la opción de indicarle al sistema que no solicite ese permiso de nuevo.
En ese caso, cuando la aplicación utiliza <code>requestPermissions()</code> para solicitar ese permiso, el sistema rechaza la solicitud inmediatamente.
En este caso, el sistema llama a su <code>onRequestPermissionsResult()</code> de la misma manera en que lo haría si el usuario hubiese rechazado explícitamente su solicitud nuevamente.
Por esta razón, su aplicación no puede asumir que se ha llevado a cabo algún tipo de interacción con el usuario.
</p>
<h2 id="testing">Prueba de permisos de tiempo de ejecución</h2>
<p>
Si su aplicación tiene como destino M Developer Preview, debe probar que administre los permisos correctamente.
No debe asumir que su aplicación tiene algún permiso en particular cuando se ejecuta.
Cuando la aplicación se ejecuta por primera vez, es muy probable que no tenga permisos y el usuario puede revocar o reestablecer los permisos en cualquier momento.
</p>
<p>
Debe probar su aplicación para asegurarse de que funciona correctamente en todas las situaciones de permisos.
Con el SDK de la versión preliminar de Android M, hemos brindado nuevos comandos <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge (adb)</a> que le permitirán probar su aplicación con cualquier configuración de permisos que necesite probar.
</p>
<h3>
Nuevas opciones y comandos adb
</h3>
<p>
Las herramientas de plataforma del SDK de la versión preliminar de Android M contienen varios comandos nuevos que le permiten probar la manera en que su aplicación administra los permisos.
</p>
<h4>
Instalar con permisos
</h4>
<p>
Puede utilizar la nueva opción <code>-g</code> del comando <a href="{@docRoot}tools/help/adb.html#move"><code>adb
install</code></a>, que instala la aplicación y concede todos los permisos enumerados en el manifiesto de la aplicación:
</p>
<pre class="no-pretty-print">
$ adb install -g &lt;path_to_apk&gt;
</pre>
<h4>
Conceder y revocar permisos
</h4>
<p>
Puede utilizar los comandos ADB nuevos <a href="{@docRoot}tools/help/adb.html#pm">package manager (pm)</a> para conceder y revocar permisos a una aplicación instalada. Esta funcionalidad puede resultar útil para pruebas automáticas.
</p>
<p>
Para conceder un permiso, utilice el comando <code>grant</code> de package manager:
</p>
<pre class="no-pretty-print">
$ adb pm grant &lt;package_name&gt; &lt;permission_name&gt;
</pre>
<p>
Por ejemplo, para conceder el paquete de permisos com.example.myapp para grabar audio utilice este comando:
</p>
<pre class="no-pretty-print">
$ adb pm grant com.example.myapp android.permission.RECORD_AUDIO
</pre>
<p>
Para revocar un permiso, utilice el comando <code>revoke</code> de package manager:
</p>
<pre class="no-pretty-print">
$ adb pm revoke &lt;package_name&gt; &lt;permission_name&gt;
</pre>
<h2 id="best-practices">Mejores prácticas</h2>
<p>
El nuevo modelo de permisos brinda a los usuarios una experiencia más fluida y les facilita la instalación de aplicaciones, además de hacerlos sentir cómodos con las actividades de sus aplicaciones.
Sugerimos las siguientes mejores prácticas para obtener el mayor beneficio del nuevo modelo.
</p>
<h3 id="bp-what-you-need">Solicite solo los permisos que necesite</h3>
<p>
Cada vez que solicite un permiso, usted obliga al usuario a tomar una decisión.
La funcionalidad de su aplicación se verá reducida si el usuario rechaza la solicitud.
Debe minimizar la cantidad de veces que realiza estas solicitudes.
</p>
<p>
Por ejemplo, a menudo, su aplicación puede obtener la funcionalidad necesaria a través de un <a href="{@docRoot}guide/components/intents-filters.html">intento</a> en lugar de una solicitud de permiso.
Si su aplicación necesita tomar fotografías con la cámara del teléfono, la aplicación puede utilizar un intento {@link
android.provider.MediaStore#ACTION_IMAGE_CAPTURE
MediaStore.ACTION_IMAGE_CAPTURE}.
Cuando su aplicación ejecuta el intento, el sistema le solicita al usuario que elija una aplicación para la cámara que ya está instalada a fin de tomar la fotografía.
</p>
<h3 id="bp-dont-overwhelm">
No abrume al usuario
</h3>
<p>
Si expone al usuario a muchas solicitudes de permisos al mismo tiempo, lo abrumará y hará que deje de usar su aplicación. Por el contrario, debe pedir permisos en la medida que los necesite.
</p>
<p>
A veces, uno o más permisos pueden ser absolutamente necesarios para la aplicación. En ese caso, es recomendable pedir todos los permisos no bien se inicie la aplicación.
Por ejemplo, si crea una aplicación de fotografía, la aplicación necesitará acceso a la cámara del dispositivo.
Cuando el usuario inicie la aplicación por primera vez, no se sorprenderá si la aplicación le solicita permiso para usar la cámara.
Sin embargo, si la misma aplicación además tuviese una característica para compartir fotografías con los contactos del usuario, <em>no</em> solicite ese permiso la primera vez que se ejecute.
En su lugar, espere hasta que el usuario utilice la característica “compartir” para solicitar el permiso en ese momento.
</p>
<p>
Si su aplicación proporciona un tutorial, se recomienda que se pidan los permisos esenciales de la aplicación al final del tutorial.
</p>
<h3 id="bp-explain">
Explique por qué se necesitan los permisos
</h3>
<p>
El diálogo de permisos que muestra el sistema cuando llama a
<code>requestPermissions()</code> informa qué permisos necesita su aplicación pero no establece el motivo.
A veces, el usuario puede confundirse.
Es una buena idea explicarle al usuario los motivos por los que la aplicación necesita esos permisos antes de llamar a <code>requestPermissions()</code>.
</p>
<p>
Por ejemplo, una aplicación de fotografía puede solicitar servicios de ubicación para añadir una etiqueta geográfica a las fotografías.
Es posible que un usuario típico no sepa que una fotografía puede contener información sobre la ubicación y se confundiría si una aplicación de fotografía solicita la ubicación.
En este caso, es recomendable que la aplicación le informe al usuario acerca de esta característica <em>antes</em> de llamar a
<code>requestPermissions()</code>.
</p>
<p>
Una forma de hacerlo es incorporar estas solicitudes en el tutorial de la aplicación. El tutorial puede mostrar todas las características de la aplicación, una por vez, y mientras lo hace explicar los permisos que son necesarios.
Por ejemplo, el tutorial de la aplicación de fotografía puede mostrar la característica “compartir fotografías con contactos” y luego explicarle al usuario que debe otorgar permisos para que la aplicación vea los contactos del usuario.
La aplicación puede entonces llamar a <code>requestPermissions()</code> para solicitarle al usuario ese acceso.
Por supuesto, no todos los usuarios siguen el tutorial, por lo que aun así debe controlar y solicitar los permisos durante el funcionamiento normal de la aplicación.
</p>

View File

@@ -1,72 +0,0 @@
page.title=Android M Developer Preview
page.tags="preview",
meta.tags="preview, M preview", androidm
fullpage=true
section.landing=true
header.hide=1
footer.hide=1
@jd:body
<section class="dac-expand dac-hero dac-light" >
<div class="wrap">
<div class="cols dac-hero-content">
<div class="col-9of16 col-push-7of16 dac-hero-figure">
<img class="dac-hero-image" src="{@docRoot}images/home/devices-hero_620px_2x.png" srcset="{@docRoot}images/home/devices-hero_620px.png 1x,
{@docRoot}images/home/devices-hero_620px_2x.png 2x">
</div>
<div class="col-7of16 col-pull-9of16">
<h1 class="dac-hero-title">Android M Developer Preview</h1>
<p class="dac-hero-description">
Prepárese para la próxima versión de Android. Pruebe sus aplicaciones en Nexus 5, 6, 9 y Player.
Explore las novedades en los&mdash; <strong>permisos de ejecución</strong>, las características de ahorro de energía <strong>Doze</strong> y <strong>App Standby</strong>, la nueva <strong>tecnología de asistencia</strong> y mucho más.
</p>
<a class="dac-hero-cta" href="{@docRoot}preview/overview.html">
<span class="dac-sprite dac-auto-chevron"></span>
¡Empiece hoy mismo!</a>
<br>
<a class="dac-hero-cta" href="{@docRoot}preview/support.html">
<span class="dac-sprite dac-auto-chevron"></span>
Developer Preview 3 (final SDK)</a>
</div>
</div>
<div class="dac-section dac-small">
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:preview/landing/resources"
data-cardSizes="6x2"
data-maxResults="6"></div>
</div>
</div>
</section>
<section class="dac-section dac-gray"><div class="wrap">
<h1 class="dac-section-title">Recursos</h1>
<div class="dac-section-subtitle">
Información esencial para ayudarlo a preparar sus aplicaciones para Android M.
</div>
<div class="resource-widget resource-flow-layout col-16"
data-query="collection:preview/landing/more"
data-cardSizes="6x6"
data-maxResults="16"></div>
<ul class="dac-section-links">
<li class="dac-section-link">
<a href="https://code.google.com/p/android-developer-preview/">
<span class="dac-sprite dac-auto-chevron"></span>
Informe los problemas
</a>
</li>
<li class="dac-section-link"><a href="http://g.co/dev/AndroidMDevPreview">
<span class="dac-sprite dac-auto-chevron"></span>
Únase a la comunidad en G+ </a>
</li>
</ul>
</div>
</section>

View File

@@ -1,143 +0,0 @@
page.title=Contrato de licencia
@jd:body
<p>
Para comenzar con la versión preliminar del SDK de Android, debe aceptar los términos y las condiciones que se describen a continuación.
Como se describe a continuación, tenga en cuenta que esta es una versión preliminar del SDK de Android, que está sujeta a cambios y que usted utiliza bajo su cuenta y riesgo. La versión preliminar del SDK de Android no es una versión estable y puede contener errores y defectos que pueden provocar daños graves a sus sistemas informáticos, dispositivos y datos.
</p>
<p>
Este es el Contrato de licencia de la versión preliminar del SDK de Android (el “Contrato de licencia”).
</p>
<div class="sdk-terms" style="height:auto;border:0;padding:0;width:700px">
1. Introducción
1.1 Se le otorga la licencia de la versión preliminar del SDK de Android (denominada “Versión preliminar” en el Contrato de licencia e incluye específicamente los archivos de sistema de Android, las API agrupadas y los archivos de biblioteca de la Versión preliminar, si se encuentran disponibles), sujeto a los términos del Contrato de licencia. El Contrato de licencia establece una relación legal vinculante entre usted y Google en relación con el uso que usted realice de la Versión preliminar.
1.2 “Android” hace referencia al conjunto de soluciones Android para dispositivos, según se encuentre disponible en el Proyecto de código abierto de Android (Android Open Source Project), que se encuentra en la siguiente URL: http://source.android.com/, y según se actualiza periódicamente.
1.3 “Google” hace referencia a Google Inc., una corporación de Delaware, con sede principal en 1600 Amphitheatre Parkway, Mountain View, CA 94043, Estados Unidos.
2. Aceptación del Contrato de licencia
2.1 Para poder utilizar la Versión preliminar, primero debe aceptar el Contrato de licencia. Si no acepta el Contrato de licencia, no podrá utilizar la Versión preliminar.
2.2 Al hacer clic para aceptar o utilizar la Versión preliminar, por medio del presente, usted acepta los términos del Contrato de licencia.
2.3 Usted no puede utilizar la Versión preliminar ni aceptar el Contrato de licencia si tiene prohibido recibir la Versión preliminar en virtud de las leyes de los Estados Unidos o de otros países, lo que incluye el país donde es residente o desde el que utilizará la Versión preliminar.
2.4 Si usted utilizará la Versión preliminar de forma interna, dentro de su compañía u organización, usted acepta quedar sujeto al Contrato de licencia en representación de su empleador u otra entidad, y expresa y garantiza que tiene plena autoridad legal para vincular a su empleador o a dicha entidad al Contrato de licencia. Si no posee la autoridad exigida, no podrá aceptar el Contrato de licencia ni usar la Versión preliminar en representación de su empleador u otra entidad.
3. Licencia de la Versión preliminar de Google
3.1 Sujeto a los términos del Contrato de licencia, Google le otorga una licencia libre de regalías, no asignable, no exclusiva, no transferible a terceros, limitada y revocable para utilizar la Versión preliminar, de forma personal o interna dentro de su compañía u organización, únicamente para desarrollar aplicaciones para ejecutar en la plataforma de Android.
3.2 Usted acepta que Google u otros terceros poseen todos los derechos legales, títulos e intereses en relación con la Versión preliminar, incluidos los Derechos de propiedad intelectual que existan en la Versión preliminar. Los “Derechos de propiedad intelectual” hacen referencia a todos y cada uno de los derechos en virtud de las leyes de patentes, derechos de autor, secreto comercial y marca comercial, y todos los demás derechos de propiedad. Google se reserva todos los derechos que no se le otorguen expresamente.
3.3 No podrá utilizar la Versión preliminar para ningún otro propósito que no esté expresamente permitido en el Contrato de licencia. Excepto en la medida que lo exijan las licencias correspondientes de terceros, no podrá: (a) copiar (excepto con fines de copia de seguridad), modificar, adaptar, redistribuir, descompilar, utilizar técnicas de ingeniería inversa, desarmar ni crear trabajos derivados de la Versión preliminar ni de ninguna de sus partes; ni (b) cargar ninguna parte de la Versión preliminar en un teléfono móvil ni en ningún otro dispositivo de hardware (a excepción de una computadora personal), ni podrá combinar ninguna parte de la Versión preliminar con otro software, ni distribuir algún software o dispositivo que incorpore alguna parte de la Versión preliminar.
3.4 Usted acepta que no tomará medidas que pudieran provocar la fragmentación de Android, incluidas, entre otras, la distribución y la participación en la creación o la promoción de un kit de desarrollo de software derivado de la Versión preliminar.
3.5 El uso, la reproducción y la distribución de los componentes de la Versión preliminar con licencia de software de código abierto están regidos exclusivamente por los términos de la licencia de ese software de código abierto y no de este Contrato de licencia. Usted acepta mantener la licencia en buenas condiciones con respecto a dichas licencias de software de código abierto en virtud de todos los derechos otorgados y acepta abstenerse de realizar alguna acción que pueda poner fin, suspender o violar dichos derechos.
3.6 Usted acepta que la forma y la naturaleza de la Versión preliminar que proporciona Google pueden cambiar sin brindarle aviso previo y que las versiones futuras de la Versión preliminar pueden ser incompatibles con las aplicaciones desarrolladas en versiones anteriores de la Versión preliminar. Usted acepta que Google puede (de forma permanente o temporal) dejar de proporcionarles la Versión preliminar (o cualquiera de las características incluidas en ella) a usted o a los usuarios, generalmente, a criterio exclusivo de Google, sin brindarle aviso previo.
3.7 Ninguna declaración de este Contrato de licencia le otorga el derecho de utilizar alguno de los nombres comerciales, las marcas comerciales, las marcas de servicio, los logotipos, los nombres de dominio ni otras características distintivas de marca de Google.
3.8 Usted acepta que no eliminará, ocultará ni alterará ninguno de los avisos de derechos de propiedad (lo que incluye los avisos de marca comercial y derechos de autor) que pudieran estar anexados o incluidos en la Versión preliminar.
4. Uso que usted realiza de la Versión preliminar
4.1 Google acepta que ninguna declaración del Contrato de licencia le concede a Google derecho, título o interés alguno de su parte (o de parte de sus licenciantes), en virtud del Contrato de licencia, con respecto a las aplicaciones de software que usted desarrolle mediante el uso de la Versión preliminar, lo que incluye los derechos de propiedad intelectual que conlleven esas aplicaciones.
4.2 Usted acepta utilizar la Versión preliminar y escribir aplicaciones únicamente conforme a lo que permite (a) este Contrato de licencia y (b) las leyes, regulaciones, o prácticas y pautas generalmente aceptadas pertinentes en las jurisdicciones relevantes (lo que incluye las leyes sobre la exportación de datos o software hacia los Estados Unidos u otros países relevantes y desde ellos).
4.3 Usted acepta que si utiliza la Versión preliminar para desarrollar aplicaciones, protegerá la privacidad y los derechos legales de los usuarios. Si los usuarios le proporcionan sus nombres de usuario, contraseñas u otra información de inicio de sesión o información personal, debe comunicarles a los usuarios que la información se encontrará disponible para su aplicación, y debe proporcionarles a dichos usuarios un aviso de privacidad con protección y validez legal. Si su aplicación almacena información personal o confidencial proporcionada por los usuarios, lo debe hacer de forma segura. Si los usuarios le proporcionan información sobre la cuenta de Google, su aplicación solo puede usar esa información para acceder a la cuenta de Google del usuario siempre que este le haya otorgado permiso para hacerlo y con los fines para los que se lo haya otorgado.
4.4 Usted acepta que no participará en ninguna actividad con la Versión preliminar (lo que incluye el desarrollo o la distribución de una aplicación) que interfiera, interrumpa, dañe o acceda sin autorización a servidores, redes u otras propiedades o servicios de Google o de algún tercero.
4.5 Usted acepta que es el único responsable (y que Google no asume responsabilidades hacia usted ni terceros) de los datos, el contenido o los recursos que usted cree, transmita o muestre a través de Android o las aplicaciones para Android, y de las consecuencias de sus acciones (lo que incluye la pérdida o el daño que Google pudiera sufrir) al hacerlo.
4.6 Usted acepta que es el único responsable (y que Google no asume responsabilidades hacia usted ni terceros) de cualquier incumplimiento de sus obligaciones en virtud de este Contrato de licencia, los contratos aplicables de terceros o los términos del servicio, o cualquier ley o regulación pertinentes, y de las consecuencias (lo que incluye las pérdidas o los daños que pudieran sufrir Google o algún tercero) de dichos incumplimientos.
4.7 La Versión preliminar se encuentra en desarrollo, y sus pruebas y comentarios son una parte importante del proceso de desarrollo. Al utilizar la Versión preliminar, usted reconoce que la implementación de algunas características aún se encuentra en desarrollo y que no debe confiar en que la Versión preliminar contará con todas las funcionalidades de una versión estable. Usted acepta no distribuir públicamente ni enviar ninguna aplicación que utilice esta Versión preliminar, ya que esta Versión preliminar ya no se admitirá tras el lanzamiento del SDK oficial de Android.
5. Sus credenciales de desarrollador
5.1 Usted acepta que es responsable de mantener la confidencialidad de toda credencial de desarrollador que Google pudiera otorgarle o que usted pudiera escoger, y que será el único responsable de todas las aplicaciones que se desarrollen con sus credenciales de desarrollador.
6. Privacidad e información
6.1 A fin de poder innovar y mejorar de forma continua la Versión preliminar, Google podría recopilar ciertas estadísticas de uso del software, lo que incluye, entre otras características, un identificador único, la dirección IP asociada, el número de versión del software e información sobre las herramientas o los servicios de la Versión preliminar que se estén utilizando y la manera en que se estén utilizando. Antes de que se recopile esta información, la Versión preliminar se lo notificará y le solicitará su permiso. Si no otorga su permiso, no se recopilará la información.
6.2 Los datos recopilados se analizan en el agregado para mejorar la Versión preliminar y se conservan de acuerdo con la política de privacidad de Google que se encuentra en el sitio http://www.google.com/policies/privacy/.
7. Aplicaciones de terceros
7.1 Si utiliza la Versión preliminar para ejecutar aplicaciones desarrolladas por un tercero o que accedan a datos, contenido o recursos proporcionados por un tercero, usted acepta que Google no es responsable de esas aplicaciones, datos, contenido ni recursos. Usted comprende que todos los datos, contenidos o recursos a los que podría acceder a través de esas aplicaciones de terceros son exclusiva responsabilidad de la persona que los origina y que Google no es responsable de las pérdidas ni los daños que usted pudiera experimentar como consecuencia del uso o acceso de cualquiera de esas aplicaciones, datos, contenido o recursos de terceros.
7.2 Usted debe saber que los datos, el contenido y los recursos que se le presentan a través de esa aplicación de un tercero pueden estar protegidos por derechos de propiedad intelectual que les pertenecen a sus proveedores (o a otras personas o compañías en representación de estos). No puede modificar, alquilar, arrendar, prestar, vender, distribuir ni crear obras derivadas basadas en esos datos, contenidos o recursos (en su totalidad o en parte), a menos que los propietarios pertinentes le hayan otorgado permiso específicamente para hacerlo.
7.3 Usted acepta que el uso que haga de las aplicaciones, los datos, el contenido o los recursos de ese tercero puede estar sujeto a términos independientes entre usted y el tercero correspondiente.
8. Uso de las API de Google
8.1 API de Google
8.1.1 Si utiliza alguna API para recuperar datos de Google, usted acepta que los datos pueden estar protegidos por derechos de propiedad intelectual que le pertenecen a Google o a las partes que proporcionan esos datos (o a otras personas o empresas en representación de estos). El uso que realice de cualquiera de esas API puede estar sujeto a términos de servicio adicionales. No puede modificar, alquilar, arrendar, prestar, vender, distribuir ni crear obras derivadas basadas en esos datos (en su totalidad o en parte), a menos que los términos de servicio correspondientes lo permitan.
8.1.2 Si utiliza alguna API para recuperar datos de un usuario de Google, usted acepta y acuerda que solo podrá recuperar datos con el consentimiento explícito del usuario y solo con los fines limitados para los que el usuario le haya otorgado permiso para hacerlo.
9. Finalización del Contrato de licencia
9.1 Este Contrato de licencia tendrá vigencia hasta que lo revoquen usted o Google, como se indica a continuación.
9.2 Si desea rescindir el Contrato de licencia, puede hacerlo al interrumpir el uso que realiza de la Versión preliminar y de las credenciales de desarrollador pertinentes.
9.3 Google puede, en cualquier momento, rescindir el Contrato de licencia, con causa o sin ella, después de notificárselo a usted.
9.4 El Contrato de licencia finalizará automáticamente, sin previo aviso ni acción alguna, tras la primera de las siguientes situaciones:
(A) cuando Google deje de proporcionar la Versión preliminar o ciertas partes de esta a los usuarios en el país donde usted reside o desde el que utiliza el servicio; y
(B) cuando Google emita una versión final del SDK de Android.
9.5 Si el Contrato de licencia se rescinde, se revocará la licencia que usted recibió en virtud de dicho contrato; usted deberá suspender inmediatamente todo uso de la Versión preliminar y las disposiciones de los párrafos 10, 11, 12 y 14 seguirán vigentes indefinidamente.
10. EXENCIONES DE RESPONSABILIDAD
10.1 USTED COMPRENDE Y ACEPTA EXPRESAMENTE QUE EL USO QUE REALICE DE LA VERSIÓN PRELIMINAR ES BAJO SU PROPIO RIESGO Y QUE LA VERSIÓN PRELIMINAR SE PROPORCIONA “EN LAS CONDICIONES EN LAS QUE SE ENCUENTRA” Y “SUJETA A DISPONIBILIDAD” SIN GARANTÍAS DE NINGÚN TIPO POR PARTE DE GOOGLE.
10.2 EL USO QUE USTED REALICE DE LA VERSIÓN PRELIMINAR Y DE TODO MATERIAL DESCARGADO U OBTENIDO DE ALGUNA OTRA MANERA MEDIANTE EL USO DE LA VERSIÓN PRELIMINAR ES A SU ENTERO RIESGO Y DISCRECIÓN, Y USTED ES EL ÚNICO RESPONSABLE DE CUALQUIER DAÑO QUE PUDIERA SUFRIR SU SISTEMA INFORMÁTICO U OTRO DISPOSITIVO, O DE LA PÉRDIDA DE DATOS COMO CONSECUENCIA DE DICHO USO. SIN PERJUICIO DE LO MENCIONADO ANTERIORMENTE, USTED COMPRENDE QUE LA VERSIÓN PRELIMINAR NO ES UNA VERSIÓN ESTABLE, Y PUEDE CONTENER ERRORES, DEFECTOS Y VULNERABILIDADES DE SEGURIDAD QUE PUEDEN PROVOCAR DAÑOS SIGNIFICATIVOS, LO QUE INCLUYE LA PÉRDIDA COMPLETA E IRRECUPERABLE DEL USO DE SU SISTEMA INFORMÁTICO U OTRO DISPOSITIVO.
10.3 GOOGLE TAMBIÉN RECHAZA TODAS LAS GARANTÍAS Y CONDICIONES DE CUALQUIER TIPO, EXPRESAS O IMPLÍCITAS, INCLUIDAS, ENTRE OTRAS, LAS GARANTÍAS Y CONDICIONES DE COMERCIABILIDAD, IDONEIDAD PARA UN FIN DETERMINADO Y NO VIOLACIÓN.
11. LIMITACIÓN DE RESPONSABILIDADES
11.1 USTED COMPRENDE Y ACEPTA EXPRESAMENTE QUE GOOGLE, SUS SUBSIDIARIAS Y FILIALES, Y SUS LICENCIANTES NO SERÁN RESPONSABLES ANTE USTED, EN VIRTUD DE NINGUNA TEORÍA DE RESPONSABILIDAD, POR NINGÚN DAÑO DIRECTO, INDIRECTO, INCIDENTAL, ESPECIAL, RESULTANTE NI PUNITIVO EN EL QUE PODRÍA HABER INCURRIDO, LO QUE INCLUYE LA PÉRDIDA DE DATOS, YA SEA QUE SE LE HAYA NOTIFICADO O NO A GOOGLE O A SUS REPRESENTANTES, O SOBRE CUYA POSIBILIDAD ESTOS DEBERÍAN HABER SABIDO.
12. Indemnización
12.1 Hasta el grado máximo que permita la ley, usted acepta defender, indemnizar y eximir de responsabilidades a Google, sus filiales y sus respectivos directores, funcionarios, empleados y agentes, de todo tipo de reclamo, acción legal y proceso judicial, así como de las pérdidas, responsabilidades, daños, costos y gastos (incluidos los honorarios razonables de abogados) que surjan o se acumulen (a) del uso que usted realiza de la Versión preliminar, (b) de cualquier aplicación que desarrolle en la Versión preliminar que infrinja algún derecho de propiedad intelectual de cualquier persona, o que difame a cualquier persona o viole sus derechos de publicidad o privacidad, y (c) del incumplimiento por su parte del Contrato de licencia.
13. Cambios en el Contrato de licencia
13.1 Google puede realizar cambios en el Contrato de licencia a medida que distribuye nuevas versiones de la Versión preliminar. Cuando se realicen esos cambios, Google emitirá una nueva versión del Contrato de licencia, que estará disponible en el sitio web donde se ponga a la venta la Versión preliminar.
14. Términos legales generales
14.1 El Contrato de licencia constituye el contrato legal integral entre usted y Google, y rige el uso que usted realice de la Versión preliminar (a excepción de los servicios que Google pueda proporcionarle en virtud de un contrato por escrito independiente), y reemplaza totalmente cualquier contrato anterior entre usted y Google en relación con la Versión preliminar.
14.2 Usted acepta que, si Google no ejerce ni impone un derecho o recurso legal especificados en el Contrato de licencia (o sobre el que Google tenga beneficios conforme a cualquier ley aplicable), esto no se considerará una renuncia formal a los derechos por parte de Google y Google aún seguirá recibiendo los beneficios de esos derechos o recursos legales.
14.3 Si algún tribunal judicial con jurisdicción para decidir sobre este asunto determina que alguna de las disposiciones de este Contrato de licencia no es válida, se eliminará esa disposición del Contrato de licencia sin que eso afecte la validez del resto del contrato. Las disposiciones restantes del Contrato de licencia continuarán siendo válidas y aplicables.
14.4 Usted reconoce y acepta que cada miembro del grupo de compañías de las que Google es la compañía central serán terceros beneficiarios del Contrato de licencia, y que esas otras empresas tendrán el derecho de imponer directamente cualquier disposición y ampararse en las disposiciones de este Contrato de licencia que les confieran un beneficio (o que confieran derechos a su favor). Además de esto, ninguna otra persona o compañía serán terceros beneficiarios del Contrato de licencia.
14.5 RESTRICCIONES DE EXPORTACIÓN. LA VERSIÓN PRELIMINAR ESTÁ SUJETA A LAS LEYES Y REGULACIONES DE EXPORTACIÓN DE LOS ESTADOS UNIDOS. DEBE CUMPLIR CON TODAS LAS LEYES Y REGULACIONES DE EXPORTACIÓN NACIONALES E INTERNACIONALES QUE SE APLIQUEN A LA VERSIÓN PRELIMINAR. ESTAS LEYES INCLUYEN RESTRICCIONES EN RELACIÓN CON LOS DESTINOS, USUARIOS FINALES Y USO FINAL.
14.6 Usted no puede asignar ni transferir el Contrato de licencia sin la aprobación previa por escrito de Google y todo intento de asignación sin dicha aprobación no tendrá validez. No podrá delegar sus responsabilidades u obligaciones otorgadas en virtud del Contrato de licencia sin la aprobación previa por escrito de Google.
14.7 El Contrato de licencia y su relación con Google conforme al Contrato de licencia se regirán por las leyes del estado de California, independientemente de los principios de conflictos entre leyes. Usted y Google aceptan presentarse ante la jurisdicción exclusiva de los tribunales del condado de Santa Clara, California, para resolver cualquier asunto legal que pudiera surgir del Contrato de licencia. Sin perjuicio de esto, usted acepta que Google aún podrá aplicar reparaciones conforme a mandato judicial (o a un tipo equivalente de desagravio legal) en cualquier jurisdicción.
</div>

View File

@@ -1,389 +0,0 @@
page.title=Información general del programa
page.metaDescription=Bienvenido a Android M Developer Preview, el programa que le brinda todo lo que necesita para probar y optimizar sus aplicaciones para la próxima versión de Android.
page.image=images/cards/card-preview_16-9_2x.png
page.tags="preview", "developer", "android"
@jd:body
<div class="cols" style=
"background-color:#ffebc3; padding: 5px 0;margin-bottom:1em; text-align:center;">
<h3>
Developer Preview 2 is now available
</h3>
<ul class="dac-section-links">
<li class="dac-section-link">
<a href="{@docRoot}preview/support.html#preview2-notes">
<span class="dac-sprite dac-auto-chevron"></span>
Read the Notes</a>
</li>
<li class="dac-section-link">
<a href="{@docRoot}preview/support.html#preview2-get">
<span class="dac-sprite dac-auto-chevron"></span>
Get the Update</a>
</li>
<li class="dac-section-link">
<a href="https://code.google.com/p/android-developer-preview/">
<span class="dac-sprite dac-auto-chevron"></span>
Report Issues</a>
</li>
</ul>
</div>
<p>
Bienvenido a <strong>Android M Developer Preview</strong>, el programa que le brinda todo lo que necesita para probar y optimizar sus aplicaciones para la próxima versión de Android.
Es gratis y puede comenzar a utilizarlo ahora mismo. Solo tiene que descargar las herramientas de M Developer Preview.
</p>
<div style="background-color:#eceff1;padding:1em;">
<div class="wrap">
<div class="cols">
<div class="col-4of12">
<h5>
Imágenes del sistema emulador y de hardware
</h5>
<p>
Ejecute y pruebe sus aplicaciones en Nexus 5, 6, 9 y Player (para TV), además del emulador.
</p>
</div>
<div class="col-4of12">
<h5>
Último código de la plataforma
</h5>
<p>
Durante la versión preliminar, ofreceremos múltiples actualizaciones, por lo que usted realizará la prueba comparando los últimos cambios de la plataforma.
</p>
</div>
<div class="col-4of12">
<h5>
Actualizaciones vía OTA
</h5>
<p>
Luego de actualizar su dispositivo a la versión preliminar inicial, usted podrá obtener actualizaciones por red inalámbrica (over-the-air, OTA).
</p>
</div>
</div>
<div class="cols">
<div class="col-4of12">
<h5>
Nuevos comportamientos y capacidades
</h5>
<p>
Inicie el funcionamiento con anticipación para admitir los comportamientos de la nueva plataforma como el nuevo modelo de permisos de tiempos de ejecución y las opciones de ahorro de energía.
</p>
</div>
<div class="col-4of12">
<h5>
Ventana de prioridad para los problemas informados por los desarrolladores
</h5>
<p>
Durante las primeras semanas, daremos prioridad a los problemas informados por los desarrolladores; por lo tanto, realice las pruebas y envíe sus comentarios lo antes posible.
</p>
</div>
<div class="col-4of12">
<h5>
Comentarios y soporte
</h5>
<p>
Infórmenos los problemas y envíenos comentarios a través de nuestro <a href="https://code.google.com/p/android-developer-preview/">seguimiento de problemas</a>.
Póngase en contacto con otros desarrolladores de la comunidad <a href="http://g.co/dev/AndroidMDevPreview">M&nbsp;Developer Community</a>.
</p>
</div>
</div>
</div>
</div>
<!--
<p>
With the M Developer Preview, you'll get an early start on testing your apps,
with enough time to make adjustments before the public platform release later
in the year. We'll provide several updates to the Preview tools in the weeks
ahead, so you can keep in sync with the latest changes as the platform moves
toward launch.
</p>
<img src="{@docRoot}preview/images/m-preview-timeline.png" alt=
"Preview program timeline" id="timeline">
<p>
You can help us improve the platform by <a href=
"https://code.google.com/p/android-developer-preview/">reporting issues</a>
through our feedback channels. This is especially
critical in the first month of the preview, when we’ll be giving priority to
developer-reported issues and feedback.
</p> -->
<h2 id="timeline">
Escala de tiempo y actualizaciones
</h2>
<img src="{@docRoot}preview/images/m-preview-timeline-crop.png" alt="Preview program timeline" id="timeline">
<p>
M Developer Preview estará disponible a partir del 28 de mayo hasta la versión final del SDK de Android M, que lanzaremos al poco tiempo del lanzamiento público durante el tercer trimestre de 2015.
</p>
<p>
En momentos clave del desarrollo, lanzaremos actualizaciones para sus dispositivos de prueba.
Los momentos clave tentativos son los siguientes:
</p>
<ul>
<li>
<strong>Preview&nbsp;1</strong> (lanzamiento inicial de la versión preliminar, fines de mayo)
</li>
<li>
<strong>Preview&nbsp;2</strong> (fines de junio, comienzos de julio)
</li>
<li>
<strong>Preview&nbsp;3</strong> (casi la versión final, a fines de julio)
</li>
</ul>
<p>
Estas actualizaciones terminan con el <strong>SDK final</strong> (más adelante durante el tercer trimestre), lo que proporcionará tanto las API oficiales para la nueva versión de Android como los comportamientos y las características finales del sistema.
</p>
<p>
A medida que usted prueba y desarrolla en Android M, le recomendamos que <strong>mantenga su entorno de desarrollo actualizado</strong> a medida que se lanzan las actualizaciones de la versión preliminar.
Para que el proceso sea más fácil, lanzaremos <strong>actualizaciones OTA</strong> para los dispositivos que ya hayan sido actualizados a una compilación de la versión preliminar y brindaremos imágenes del sistema que puede descargar y actualizar manualmente.
</p>
<p class="note">
<strong>Nota:</strong> El SDK final y las imágenes del sistema no se pueden proporcionar vía OTA y deberán <strong>actualizarse manualmente</strong> en sus dispositivos de prueba.</strong>
</p>
<p>
Le informaremos cuando las actualizaciones de la versión preliminar se encuentren disponibles a través del blog de Android para desarrolladores (<a href="http://android-developers.blogspot.com/">Android Developers Blog</a>), de este sitio y de la comunidad de desarrolladores <a href="http://g.co/dev/AndroidMDevPreview">Android M Developer Community</a>.
</p>
<h2 id="preview_tools">
¿Qué ofrece la versión preliminar?
</h2>
<p>
M Developer Preview incluye todo lo que necesita para probar sus aplicaciones actuales en una variedad de tamaños de pantalla, de tecnologías de redes, de conjuntos de chip CPU/GPU y de arquitecturas de hardware.
</p>
<h4>
Herramientas del SDK
</h4>
<p>
Estos componentes se pueden descargar mediante SDK Manager en <a href="{@docRoot}sdk/installing/adding-packages.html">Android Studio</a>:
</p>
<ul>
<li><strong>Herramientas del SDK</strong> de M Developer Preview
</li>
<li><strong>Imagen del sistema emulador</strong> (32-bit y 64-bit) de M Developer Preview
</li>
<li><strong>Imagen del sistema emulador para Android TV</strong> (32-bit) de M Developer Preview
</li>
</ul>
<h4>
Imágenes del sistema de hardware
</h4>
<p>
Puede descargar estas imágenes del sistema de hardware para dispositivos Nexus desde la <a href="download.html">página de Descargas</a>:
</p>
<ul>
<li>
<strong>Nexus 5</strong> (GSM/LTE) imagen del sistema del dispositivo “hammerhead”
</li>
<li>
<strong>Nexus 6</strong> imagen del sistema del dispositivo “shamu”
</li>
<li>
<strong>Nexus 9</strong> (Wi-Fi) imagen del sistema del dispositivo “volantis”
</li>
<li>
<strong>Nexus Player</strong> (Android TV) imagen del sistema del dispositivo “fugu”
</li>
</ul>
<h4>
Documentación y código de muestra
</h4>
<p>
Estos recursos de documentación lo ayudan a obtener información sobre la versión preliminar:
</p>
<ul>
<li>
<a href="setup-sdk.html">Configurar el SDK</a>: contiene instrucciones paso a paso para comenzar.
</li>
<li>
<a href="{@docRoot}preview/testing/guide.html">Guía de prueba</a> y <a href="behavior-changes.html">Cambios en los comportamientos</a>: le indican las áreas más importantes que debe probar.
</li>
<li>Documentación sobre las nuevas API, lo que incluye <a href="api-overview.html">Información general de la API</a>, <a href="{@docRoot}preview/download.html#docs">Referencia de la API</a> que se puede descargar y guías detalladas para desarrolladores sobre características clave como <a href="{@docRoot}preview/features/runtime-permissions.html">permisos</a>, <a href="{@docRoot}preview/backup/index.html">copias de seguridad de la aplicación</a>, entre otras.
</li>
<li>
<a href="{@docRoot}preview/samples.html">Código de ejemplo</a>: indica cómo admitir permisos y otras características nuevas.
</li>
<li>
<a href="{@docRoot}preview/support.html#release-notes">Notas de la versión</a> para la versión actual de M Developer Preview, lo que incluye notas sobre los cambios e informes de diferencias.
</li>
</ul>
<h4>
Recursos de soporte
</h4>
<p>
Utilice los siguientes recursos de soporte durante el proceso de prueba y desarrollo en M Developer Preview:
</p>
<ul>
<li><a href="https://code.google.com/p/android-developer-preview/">El seguimiento de problemas de M Developer Preview</a> es su<strong> canal principal de comentarios.</strong>
A través de este seguimiento de problemas, usted puede informarnos errores o problemas de rendimiento, y enviarnos comentarios generales.
También puede buscar <a href="https://code.google.com/p/android-developer-preview/wiki/KnownIssues">problemas recurrentes</a> y encontrar soluciones alternativas detalladas.
</li>
<li><a href="http://g.co/dev/AndroidMDevPreview">Android M Developer Community</a> es una comunidad en Google+ donde usted puede <strong>contactarse con otros desarrolladores</strong> que estén trabajando con Android M. Puede compartir comentarios o ideas, o encontrar respuestas a sus dudas sobre Android M.
</li>
</ul>
<h2 id="preview_apis_and_publishing">
Selección del destino, API preliminares y publicación
</h2>
<p>
Android M Developer Preview es una versión solo para desarrollo y <strong>no tiene un nivel de API estándar</strong>.
Si quiere darse de baja de los comportamientos de compatibilidad para probar su aplicación (lo que es muy recomendado), puede elegir como destino M Developer Preview estableciendo <code><a href=
"/guide/topics/manifest/uses-sdk-element.html">targetSdkVersion</a></code> de su aplicación como <code>“MNC”</code>.
</p>
<p>
Android M Developer Preview ofrece <strong>API preliminares</strong>
&mdash; las API no serán oficiales hasta que se lance el SDK final, lo que actualmente está planeado para el tercer trimestre de 2015.
Esto quiere decir que surgirán <strong>cambios menores en la API</strong> con el tiempo, particularmente durante las primeras semanas del programa.
Con cada actualización de Android M Developer Preview, proporcionaremos un resumen con los cambios realizados.
</p>
<p class="note">
Tenga en cuenta que aunque las API preliminares pueden modificarse, los comportamientos del sistema subyacente, como los permisos de tiempo de ejecución y las opciones de ahorro de energía, se mantienen estables y disponibles para cualquier prueba inmediata.
</p>
<p>
En cuanto a la publicación, Google Play <strong>no permite que se publiquen aplicaciones que tienen como destino M Developer Preview</strong>.
Una vez que el SDK final de Android M esté disponible, podrá seleccionar como destino el nivel de API oficial de Android M y publicar su aplicación en Google Play.
Mientras tanto, si desea distribuir una aplicación con Android M como destino a otros evaluadores, lo puede hacer por correo electrónico o mediante descarga directa desde su sitio.
</p>
<h2 id="get_started">
¿Cómo comenzar?
</h2>
<p>
Para comenzar a probar su aplicación:
</p>
<ol>
<li>Revise el artículo <a href="{@docRoot}preview/api-overview.html">Información general de la API</a> y <a href="{@docRoot}preview/behavior-changes.html">Cambios en los comportamientos</a> para obtener una idea sobre las novedades y cómo estas pueden afectar sus aplicaciones.
En especial, infórmese sobre el nuevo modelo de <a href="{@docRoot}preview/features/runtime-permissions.html">permisos de tiempo de ejecución</a>, las opciones de ahorro de energía y las copias de seguridad automáticas.
</li>
<li>Configure su entorno siguiendo las instrucciones para <a href="{@docRoot}preview/setup-sdk.html">Configurar el SDK de la versión preliminar</a> y configurar los dispositivos de prueba.
</li>
<li>Siga las <a href="https://developers.google.com/android/nexus/images">instrucciones de actualización</a> para actualizar la última imagen del sistema del desarrollador de Android M para Nexus 5, 6, 9 y Player.
Cuando haya actualizado su dispositivo de desarrollo, recibirá las actualizaciones de la versión preliminar mediante actualizaciones OTA.</a>
</li>
<li>Descargue la <a href="{@docRoot}preview/download.html#docs">Referencia de la API de M Preview</a> y los <a href="{@docRoot}preview/samples.html">Ejemplos de M Preview</a> para obtener más información sobre las nuevas características de la API y sobre cómo utilizarlas en su aplicación.
</li>
<li>Únase a la comunidad <a href="http://g.co/dev/AndroidMDevPreview">Android M Developer Community</a> para recibir las últimas noticias y para contactarse con otros desarrolladores que estén trabajando con la nueva plataforma.
</li>
</ol>
<p>
¡Agradecemos su participación en el programa Android M Developer Preview!
</p>

View File

@@ -1,70 +0,0 @@
page.title=Ejemplos
page.image=images/cards/samples-new_2x.png
@jd:body
<p>
Los siguientes códigos de ejemplo se proporcionan para M Developer Preview. Para descargar los ejemplos en Android Studio, seleccione la opción del menú <b>File &gt; Import Samples</b>.
</p>
<p class="note">
<strong>Nota:</strong> Estos proyectos que se pueden descargar están diseñados para usarlos con Gradle y Android Studio.
</p>
<h3 id="RuntimePermissions">Permisos de tiempo de ejecución</h3>
<p>
Android M modifica la manera en que funcionan los permisos del sistema. Los usuarios deben aprobar solicitudes de permiso durante la ejecución, en lugar de durante la instalación.
Este ejemplo muestra cómo solicitar estos permisos.
</p>
<p><a href="https://github.com/googlesamples/android-RuntimePermissions">Obtener en GitHub</a></p>
<h3 id="ConfirmCredentials">Confirmar credencial</h3>
<p>
Este ejemplo muestra cómo usar las credenciales del dispositivo como método de autenticación en su aplicación.
</p>
<p><a href="https://github.com/googlesamples/android-ConfirmCredential">Obtener en GitHub</a>
</p>
<h3 id="FingerprintDialog">Diálogo de huellas dactilares</h3>
<p>
Este ejemplo muestra cómo reconocer huellas dactilares registradas para autenticar al usuario en su aplicación.
</p>
<p><a href="https://github.com/googlesamples/android-FingerprintDialog">Obtener en GitHub</a></p>
<h3 id="AutomaticBackup">Copia de seguridad automática para aplicaciones</h3>
<p>
Android M incorpora la copia de seguridad automática para las configuraciones de la aplicación. Este ejemplo muestra cómo agregar reglas de filtrado en una aplicación para administrar la copia de seguridad de las configuraciones.
</p>
<p><a href="https://github.com/googlesamples/android-AutoBackupForApps">Obtener en GitHub</a></p>
<h3 id="CameraRaw">Camera 2 Raw</h3>
<p>
Muestra cómo usar la API <code>Camera2</code> para capturar imágenes fotográficas RAW y guardarlas como archivos <code>DNG</code>.
</p>
<p><a href="https://github.com/googlesamples/android-Camera2Raw">Obtener en GitHub</a></p>
<h3 id="ActiveNotification">Notificación activa</h3>
<p>
Este ejemplo muestra cómo <a href="{@docRoot}reference/android/app/NotificationManager.html"><code>NotificationManager</code></a> puede indicarle cuántas notificaciones está mostrando actualmente su aplicación.
</p>
<p><a href="https://github.com/googlesamples/android-ActiveNotifications">Obtener en GitHub</a></p>

View File

@@ -1,207 +0,0 @@
page.title=Configurar el SDK de la versión preliminar
page.image=images/cards/card-set-up_16-9_2x.png
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento</h2>
<ol>
<li><a href="#get-as13">Obtener Android Studio 1.3</a></li>
<li><a href="#get-sdk">Obtener el SDK de la versión preliminar</a></li>
<li><a href="#create-update">Crear o actualizar un proyecto</a></li>
<li><a href="#setup-test">Configurar para realizar pruebas</a></li>
</ol>
</div>
</div>
<p>M Developer Preview SDK se encuentra disponible desde Android SDK Manager. En este documento, se asume que usted está familiarizado con el desarrollo de aplicaciones de Android, como el uso de Android SDK Manager y la creación de proyectos.
Si no está familiarizado con Android, consulte primero la sección de capacitación <a href="{@docRoot}training/basics/firstapp/index.html">Desarrollo de su primera aplicación</a>.</a>
</p>
<h2 id="get-as13">Obtener Android Studio 1.3</h2>
<p>La versión preliminar para desarrolladores funciona mejor con Android Studio 1.3, que es una versión preliminar.
Se recomienda que instale la versión preliminar de Android Studio 1.3 para trabajar con el SDK de la versión preliminar.
</p>
<p class="caution"><strong>Advertencia:</strong> La versión preliminar Canary de Android Studio 1.3 aún se encuentra en desarrollo activo.
Si utiliza su equipo de desarrollo principal para probar la versión preliminar para desarrolladores, puede instalar una segunda instancia de Android para realizar las pruebas.
</p>
<p>Para instalar la versión preliminar de Android Studio 1.3:</p>
<ol>
<li>Descargue y ejecute <a href="{@docRoot}tools/studio/index.html">Android Studio</a>
</li>
<li>Abra la ventana <strong>Settings</strong> (en Windows, puede hacerlo desde <strong>File &gt; Settings</strong>).
Seleccione el panel <strong>Appearance &amp; Behavior &gt; System Settings &gt; Updates</strong>.
<p class="aside">En OSX, puede encontrar el panel <strong>Appearance &amp; Behavior</strong> en la ventana <strong>Preferences</strong> de Android Studio.
</p>
</li>
<li> En el panel <strong>Updates</strong>, elija la opción <strong>Automatically check updates for:
Canary Channel</strong>.
</li>
<li>En el panel <strong>Updates</strong>, elija <strong>Check Now</strong> para verificar la última compilación de Canary.
Descargue e instale la compilación cuando se lo pida.
</li>
</ol>
<h2 id="get-sdk">Obtener el SDK de la versión preliminar</h2>
<p>Para añadir los componentes del SDK de la versión preliminar a su entorno de desarrollo:</p>
<ol>
<li>Ejecute la versión preliminar de Android Studio 1.3.
</li>
<li>Abra la ventana <strong>Settings</strong> (en Windows, puede hacerlo desde <strong>File &gt; Settings</strong>).
Seleccione el panel <strong>Appearance &amp; Behavior &gt; System Settings &gt; Updates</strong>.
<p class="aside">En OSX, puede encontrar el panel <strong>Appearance &amp; Behavior</strong> en la ventana <strong>Preferences</strong> de Android Studio.
</p>
</li>
<li>En el panel <strong>Updates</strong>, elija las opciones <strong>Automatically check updates for:
Canary Channel</strong> y <strong>Automatically check updates for Android SDK:
Preview Channel</strong>.
</li>
<li>Ejecute <strong>Android SDK Manager</strong>. (En Android Studio 1.3, SDK Manager está integrado a Android Studio, en lugar de ser una aplicación independiente).
</li>
<li>En la sección <strong>Platforms</strong>, elija <strong>Android MNC Preview</strong>.
</li>
<li>En la sección <strong>Tools</strong>, elija las últimas <strong>SDK Tools</strong>, <strong>Platform-tools</strong> y <strong>Build-tools</strong> de Android.
</li>
<li>Seleccione <strong>Install packages</strong> y acepte el contrato de licencia para todos los paquetes.
</li>
<li>Verifique que M Developer Preview esté instalado; para hacerlo, abra la ventana <strong>Settings</strong> y elija el panel <strong>Appearance &amp; Behavior &gt; System Settings &gt; Android SDK</strong>.
</li>
<li>En el panel <strong>Android SDK</strong>, elija la pestaña <strong>SDK Platforms</strong>.
<strong>Android MNC Preview</strong> deberá figurar como <em>Installed</em>.
Luego, abra la pestaña <strong>SDK Tools</strong> para verificar que estén instaladas las últimas herramientas.
</li>
</ol>
<p>Después de completar estos pasos, los componentes de la versión preliminar ya estarán disponibles en su entorno de desarrollo.
</p>
<h2 id="create-update">Crear o actualizar un proyecto</h2>
<p>
Si desea utilizar las API de la versión preliminar, debe crear o actualizar un proyecto de desarrollo para utilizar los componentes de la versión preliminar.
</p>
<h3 id="create">Crear un proyecto nuevo</h3>
<p>
Recomendamos que utilice Android Studio para crear un proyecto con la versión preliminar. Siga los pasos que se describen en <a href="{@docRoot}sdk/installing/create-project.html">Crear un proyecto</a> hasta que llegue a la pantalla <em>Form Factors</em> en el asistente.
Luego, realice los siguientes pasos para crear un proyecto configurado para la versión preliminar.
</p>
<ul>
<li>Seleccione <strong>Phone and Tablet</strong>.</li>
<li>Seleccione <strong>MNC: Android M (Preview)</strong> en <strong>Minimum SDK</strong>.
</li>
</ul>
<h3 id="update">Actualizar un proyecto existente</h3>
<p>
Para proyectos existentes, debe modificar la configuración del proyecto para habilitar las API de la versión preliminar. En su entorno de desarrollo, abra el archivo
<code>build.gradle</code> para su módulo y configure estos valores de la siguiente manera:
</p>
<ul>
<li><code>compileSdkVersion</code> se configura en <code>'android-MNC'</code></li>
<li><code>minSdkVersion</code> se configura en <code>'MNC'</code></li>
<li><code>targetSdkVersion</code> se configura en <code>'MNC'</code></li>
</ul>
<h2 id="setup-test">Configurar para realizar pruebas</h2>
<p>
Probar una aplicación con la versión preliminar requiere un dispositivo o un dispositivo virtual configurado con la versión preliminar de la plataforma.
Si tiene un dispositivo compatible, puede instalar la plataforma de la versión preliminar para realizar la prueba.
De lo contrario, puede configurar un dispositivo virtual para realizar la prueba.
</p>
<h3 id="setup-device">Configurar un dispositivo físico</h3>
<p>
Si tiene un Nexus 5, Nexus 6, Nexus 9 o Android TV, puede instalar una imagen de sistema de la versión preliminar en estos dispositivos para probar su aplicación. Con la herramienta Android Virtual Device Manager, puede configurar un dispositivo virtual con la versión preliminar de la plataforma desde Android Studio
</p>
<p class="caution">
<strong>Importante:</strong> El proceso de instalación de una imagen preliminar en un dispositivo <em>elimina todos los datos del dispositivo</em>, por lo que debe hacer una copia de seguridad de los datos antes de instalar una imagen preliminar.
</p>
<h3 id="setupAVD">Configurar un dispositivo virtual</h3>
<p>
Con la herramienta Android Virtual Device, puede configurar un dispositivo virtual para la versión preliminar de la plataforma desde Android Studio.
</p>
<p>Crear un AVD (dispositivo virtual de Android) con AVD Manager:</p>
<ol>
<li>Instale el SDK de la versión preliminar en su entorno de desarrollo, como se detalla en <a href="{@docRoot}preview/setup-sdk.html">Configurar el SDK de la versión preliminar</a>.
</li>
<li>Siga los pasos en <a href="{@docRoot}tools/devices/managing-avds.html">Administración de los ADV con ADV Manager</a>.
Utilice las siguientes configuraciones:
<ul>
<li><strong>Dispositivo:</strong> Nexus 5, Nexus 6, Nexus 9 o Android TV</li>
<li><strong>Destino:</strong>
Android M (versión preliminar) - Nivel de API M</li>
<li><strong>ABI:</strong> x86</li>
</ul>
</li>
</ol>
<p>
Para obtener más información sobre cómo crear dispositivos virtuales para realizar pruebas, consulte <a href="{@docRoot}tools/devices/index.html">Administración de dispositivos virtuales.</a>
</p>

View File

@@ -1,187 +0,0 @@
page.title=Guía de prueba
page.image=images/cards/card-build_16x9_2x.png
page.keywords=recursos de la versión preliminar,androidm,pruebas,permisos
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento</h2>
<ol>
<li><a href="#runtime-permissions">Prueba de los permisos</a></li>
<li><a href="#doze-standby">Prueba de los modos Doze y App Standby</a></li>
<li><a href="#ids">Copia de seguridad automática e identificadores de dispositivos</a></li>
</ol>
</div>
</div>
<p>
Android M Developer Preview le brinda la oportunidad de garantizar que sus aplicaciones funcionen con la próxima versión de la plataforma.
Esta versión preliminar incluye diversas API y cambios en los comportamientos que pueden tener impactos en su aplicación, como se describe en las secciones <a href="{@docRoot}preview/api-overview.html">Información general de la API</a> y <a href="{@docRoot}preview/behavior-changes.html">Cambios en los comportamientos</a>.
Al probar su aplicación con la versión preliminar, se debe centrar en algunos cambios específicos del sistema para garantizar que los usuarios disfruten de una buena experiencia.
</p>
<p>
En esta guía, se describen qué y cómo probar las características preliminares con su aplicación. Debe priorizar la prueba de estas características específicas preliminares, puesto que podrían tener un alto impacto en el comportamiento de su aplicación:
</p>
<ul>
<li><a href="#runtime-permissions">Permisos</a>
</li>
<li><a href="#doze-standby">Modos Doze y App Standby</a>
</li>
<li><a href="#ids">Copia de seguridad automática e identificadores de dispositivos</a></li>
</ul>
<p>
Para obtener más información sobre cómo configurar dispositivos o dispositivos virtuales con una imagen del sistema de la versión preliminar para realizar pruebas, consulte la sección <a href="{@docRoot}preview/setup-sdk.html">Configurar el SDK de la versión preliminar</a>.
</p>
<h2 id="runtime-permissions">Prueba de los permisos</h2>
<p>
El nuevo modelo de <a href="{@docRoot}preview/features/runtime-permissions.html">permisos</a> cambia el modo en que el usuario asigna permisos a su aplicación.
En lugar de conceder todos los permisos durante el procedimiento de instalación, su aplicación debe solicitar al usuario los permisos individuales en el tiempo de ejecución.
Para los usuarios, este comportamiento ofrece más control granular sobre las actividades de cada aplicación, así como un mejor contexto para comprender por qué la aplicación está solicitando un permiso específico.
Los usuarios pueden conceder o revocar los permisos concedidos a una aplicación de forma individual en cualquier momento.
Es muy probable que esta característica de la versión preliminar tenga un impacto en el comportamiento de su aplicación y puede hacer que algunas características de su aplicación no funcionen o funcionen en un estado degradado.
</p>
<p class="caution">
Este cambio afecta a todas las aplicaciones que se ejecutan en la nueva plataforma, incluso a aquellas que no tienen como destino la nueva versión de la plataforma.
La plataforma ofrece un comportamiento de compatibilidad limitada para las aplicaciones heredadas, pero usted debe comenzar a planificar ahora la migración de su aplicación al nuevo modelo de permisos, con el objetivo de publicar una versión actualizada de su aplicación cuando se lance la plataforma oficial.
</p>
<h3 id="permission-test-tips">Consejos para pruebas</h3>
<p>
Use los siguientes consejos para pruebas como ayuda para planificar y ejecutar las pruebas de su aplicación con el nuevo comportamiento de permisos.
</p>
<ul>
<li>Identifique los permisos actuales de su aplicación y las rutas de códigos relacionadas.</li>
<li>Pruebe los flujos del usuario en los datos y servicios protegidos por permisos.</li>
<li>Realice pruebas con varias combinaciones de permisos concedidos/revocados.</li>
<li>Use la herramienta {@code adb} para administrar permisos desde la línea de comando:
<ul>
<li>Enumere los permisos y estados por grupo:
<pre>adb shell pm list permissions -d -g</pre>
</li>
<li>Conceda o revoque un permiso o más permisos utilizando la siguiente sintaxis:<br>
<pre>adb shell pm [grant|revoke] &lt;permission.name&gt; ...</pre>
</li>
</ul>
</li>
<li>Analice su aplicación para detectar servicios que utilizan permisos.</li>
</ul>
<h3 id="permission-test-strategy">Estrategia de prueba</h3>
<p>
El cambio en los permisos afecta la estructura y el diseño de su aplicación, además de la experiencia del usuario y los flujos que usted proporciona a los usuarios.
Debe evaluar el uso de los permisos actuales de su aplicación y comenzar a planificar los nuevos flujos que desea ofrecer.
La versión oficial de la plataforma proporciona un comportamiento de compatibilidad, pero debe prever la actualización de su aplicación y no depender de estos comportamientos.
</p>
<p>
Identifique los permisos que su aplicación verdaderamente necesita y utiliza, y luego busque las diversas rutas de códigos que utilizan los servicios protegidos por permisos.
Puede realizar esto mediante una combinación de pruebas en la plataforma nueva y análisis de códigos.
Al realizar las pruebas, debe centrarse en incluir permisos de tiempo de ejecución cambiando {@code targetSdkVersion} de la aplicación a la versión preliminar.
Para obtener más información, consulte la sección <a href="{@docRoot}preview/setup-sdk.html#">Configurar el SDK de la versión preliminar</a>.
</p>
<p>
Realice pruebas con diversas combinaciones de permisos revocados y agregados, a fin de destacar los flujos del usuario que dependen de permisos.
Cuando una dependencia no sea obvia ni lógica, debe considerar la opción de refactorizar o compartimentar ese flujo para eliminar la dependencia o aclarar por qué se necesita el permiso.
</p>
<p>
Para obtener más información sobre el comportamiento de los permisos de tiempo de ejecución, las pruebas y las mejores prácticas, consulte la página <a href="{@docRoot}preview/features/runtime-permissions.html">Permisos</a> de la versión preliminar para desarrolladores.
</p>
<h2 id="doze-standby">Prueba de los modos Doze y App Standby</h2>
<p>
Las características de ahorro de energía de los modos Doze y App Standby limitan la cantidad de procesamiento en segundo plano que puede realizar su aplicación cuando un dispositivo se encuentra en estado inactivo o mientras su aplicación no está en foco.
Entre las restricciones que el sistema puede imponer en las aplicaciones se incluyen el acceso limitado a la red o denegación de acceso, suspensión de las tareas en segundo plano, suspensión de notificaciones, y alarmas y solicitudes de reactivación ignoradas.
Para garantizar que su aplicación tenga un comportamiento correcto con estas optimizaciones de ahorro de energía, debe probar su aplicación simulando estos estados de bajo consumo.
</p>
<h4 id="doze">Cómo probar la aplicación en modo Doze</h4>
<p>Para probar el modo Doze con su aplicación, realice lo siguiente:</p>
<ol>
<li>Configure un dispositivo de hardware o un dispositivo virtual con una imagen del sistema de la versión preliminar de Android M.</li>
<li>Conecte el dispositivo a su equipo de desarrollo e instale la aplicación.</li>
<li>Ejecute su aplicación y déjela activa.</li>
<li>Simule la activación del modo Doze en el dispositivo ejecutando los siguientes comandos:
<pre>
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
$ adb shell dumpsys deviceidle -h
</pre>
</li>
<li>Observe el comportamiento de su aplicación cuando se reactive el dispositivo. Asegúrese de que se recupere correctamente cuando el dispositivo salga del modo Doze.
</li>
</ol>
<h4 id="standby">Cómo probar aplicaciones en modo App Standby</h4>
<p>Para probar el modo App Standby con su aplicación, realice lo siguiente:</p>
<ol>
<li>Configure un dispositivo de hardware o un dispositivo virtual con una imagen del sistema de la versión preliminar de Android M.</li>
<li>Conecte el dispositivo a su equipo de desarrollo e instale su aplicación.</li>
<li>Ejecute su aplicación y déjela activa.</li>
<li>Simule la activación del modo App Standby en la aplicación ejecutando los siguientes comandos:
<pre>
$ adb shell am broadcast -a android.os.action.DISCHARGING
$ adb shell am set-idle &lt;packageName&gt; true
</pre>
</li>
<li>Simule la activación de su aplicación con el siguiente comando:
<pre>$ adb shell am set-idle &lt;packageName&gt; false</pre>
</li>
<li>Observe el comportamiento de su aplicación al reactivarse. Asegúrese de que se recupere correctamente del modo App Standby.
En particular, debe comprobar si los trabajos en segundo plano y las notificaciones de su aplicación continúan funcionando de la manera esperada.
</li>
</ol>
<h2 id="ids">Copia de seguridad automática para aplicaciones e identificadores específicos del dispositivo</h2>
<p>Si su aplicación continúa teniendo algún identificador específico del dispositivo, como la Id. de registro de Google Cloud Messaging, en el almacenamiento interno, asegúrese de seguir las mejores prácticas para excluir la ubicación de almacenamiento de la copia de seguridad automática, como se describe en la sección <a href="{@docRoot}preview/backup/index.html">Copia de seguridad automática para aplicaciones</a>.
</p>

View File

@@ -1,656 +0,0 @@
page.title=Prueba de rendimiento de video
page.image=images/cards/card-test-performance_2x.png
page.keywords=rendimiento, fotogramas por segundo, herramientas
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Contenido del documento</h2>
<ol>
<li><a href="#measure">Medición del rendimiento de la UI</a>
<ul>
<li><a href="#aggregate">Incorporación de Frame Stats</a></li>
<li><a href="#timing-info">Información precisa del intervalo del fotograma</a></li>
<li><a href="#timing-dump">Volcado simple del intervalo del fotograma</a></li>
<li><a href="#collection-window">Control del período de recopilación de datos</a></li>
<li><a href="#diagnose">Diagnóstico de regresiones de rendimiento</a></li>
<li><a href="#resources">Recursos adicionales</a></li>
</ul>
</li>
<li><a href="#automate">Automatización de las pruebas de rendimiento de la UI</a>
<ul>
<li><a href="#ui-tests">Configuración de las pruebas de UI</a></li>
<li><a href="#automated-tests">Configuración de las pruebas automatizadas de UI</a></li>
<li><a href="#triage">Clasificación y solución de problemas detectados</a></li>
</ul>
</li>
</ol>
</div>
</div>
<p>
La prueba de rendimiento de la UI le garantiza que su aplicación no solo cumpla con los requisitos funcionales sino que la interacción del usuario con su aplicación sea fluida y funcione constantemente a 60 fotogramas por segundo (<a href="https://www.youtube.com/watch?v=CaMTIgxCSqU&amp;index=25&amp;list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">Why 60fps?</a>) sin disminuir o retrasar fotogramas (lo que llamamos <em>“jank”</em>).
Este documento explica las herramientas disponibles para medir el rendimiento de la UI y establece un enfoque para integrar las medidas de rendimiento de la UI en sus prácticas de prueba.
</p>
<h2 id="measure">Medición del rendimiento de la UI</h2>
<p>
Para mejorar el rendimiento, primero necesita poder medir el rendimiento de su sistema y, luego, diagnosticar e identificar los problemas que puedan surgir debido a las varias secciones de su canalización.
</p>
<p>
<em><a href="https://source.android.com/devices/tech/debug/dumpsys.html">dumpsys</a></em> es una herramienta de Android que se ejecuta en el dispositivo y vuelca información útil sobre el estado de los servicios del sistema.
Al pasar el comando <em>gxinfo</em> a dumsys, se obtiene una salida de logcat con información de rendimiento en relación con los fotogramas de animación que ocurren durante la fase de grabado.
</p>
<pre>
&gt; adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt;
</pre>
<p>
Este comando puede crear múltiples variantes diferentes de datos del intervalo del fotograma.
</p>
<h3 id="aggregate">Incorporación de Frame Stats</h3>
<p>
En la versión preliminar de Android M, el comando emite un análisis adicional a logcat sobre los datos del fotograma. Estos datos se recopilan en toda la duración del proceso.
Por ejemplo:
</p>
<pre class="noprettyprint">
Stats since: 752958278148ns
Total frames rendered: 82189
Janky frames: 35335 (42.99%)
90th percentile: 34ms
95th percentile: 42ms
99th percentile: 69ms
Number Missed Vsync: 4706
Number High input latency: 142
Number Slow UI thread: 17270
Number Slow bitmap uploads: 1542
Number Slow draw: 23342
</pre>
<p>
Estas estadísticas de alto nivel representan, en un nivel avanzado, el rendimiento de representación de la aplicación y su estabilidad en muchos fotogramas.
</p>
<h3 id="timing-info">Información precisa del intervalo del fotograma</h3>
<p>
La versión preliminar de Android M ofrece un nuevo comando para gfxinfo, es <em>framestats</em> que brinda información extremadamente detallada sobre el intervalo del fotograma reciente, de manera que usted puede localizar y depurar errores de manera más precisa.
</p>
<pre>
&gt;adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt; framestats
</pre>
<p>
Este comando emite información sobre el intervalo del fotograma, medida en nanosegundos, de los últimos 120 fotogramas que produjo la aplicación. A continuación, se muestra un ejemplo sin formato de adb dumpsys gxinfo &lt;PACKAGE_NAME&gt; framestats:
</p>
<pre class="noprettyprint">
0,49762224585003,49762241251670,9223372036854775807,0,49762257627204,49762257646058,49762257969704,49762258002100,49762265541631,49762273951162,49762300914808,49762303675954,
0,49762445152142,49762445152142,9223372036854775807,0,49762446678818,49762446705589,49762447268818,49762447388037,49762453551527,49762457134131,49762474889027,49762476150120,
0,49762462118845,49762462118845,9223372036854775807,0,49762462595381,49762462619287,49762462919964,49762462968454,49762476194547,49762476483454,49762480214964,49762480911527,
0,49762479085548,49762479085548,9223372036854775807,0,49762480066370,49762480099339,49762481013089,49762481085850,49762482232152,49762482478350,49762485657620,49762486116683,
</pre>
<p>
Cada línea de esta salida representa un fotograma producido por la aplicación. Cada línea tiene un número fijo de columnas que describen el tiempo transcurrido en cada etapa de la canalización de producción de fotogramas.
En la siguiente sección, se describe este formato en detalle y se explica qué representa cada columna.
</p>
<h4 id="fs-data-format">Formato de datos de framestats</h4>
<p>
Debido a que el bloque de datos se emite en formato CSV, es muy sencillo pegarlo en su herramienta de hoja de cálculo preferida, o recopilar y redistribuir con un script.
La siguiente tabla explica el formato de las columnas de los datos de salida.
Las marcas de tiempo están en nanosegundos.
</p>
<ul>
<li>FLAGS
<ul>
<li>El tiempo total del fotograma de las filas con “0” en la columna FLAGS se puede calcular restando la columna INTENDED_VSYNC a la columna FRAME_COMPLETED.
</li>
<li>Si el resultado no es cero, la fila se debe ignorar, ya que se ha determinado que el fotograma contiene un valor atípico de rendimiento, donde se espera que el diseño y la imagen tomen más de 16 ms.
Razones por las que esto puede suceder:
<ul>
<li>Se cambió el diseño de la ventana (ya sea el primer fotograma de la aplicación o luego de una rotación)
</li>
<li>También es posible que se haya omitido el fotograma. En ese caso, alguno de los valores tendrán marcas de tiempo no utilizables.
Se puede omitir un fotograma si, por ejemplo, supera los 60 fotogramas por segundo o si no había nada desfasado en pantalla. Esto no necesariamente indica que la aplicación tenga algún problema.
</li>
</ul>
</li>
</ul>
</li>
<li>INTENDED_VSYNC
<ul>
<li>El punto de partida previsto del fotograma. Si este valor es diferente de VSYNC, el subproceso de la interfaz de usuario se encontraba ocupado, lo que evitó la respuesta a la señal vsync de manera oportuna.
</li>
</ul>
</li>
<li>VSYNC
<ul>
<li>El valor de tiempo que se utilizó en todas las escuchas vsync y las imágenes para el fotograma (devolución de llamada del fotograma Choreographer, animaciones, View.getDrawingTime(), etc.).
</li>
<li>Para obtener más información sobre VSYNC y cómo influye en su aplicación, consulte el video <a href="https://www.youtube.com/watch?v=1iaHxmfZGGc&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=23">
Understanding VSYNC</a>.
</li>
</ul>
</li>
<li>OLDEST_INPUT_EVENT
<ul>
<li>La marca de tiempo del evento de entrada más antiguo de la cola de entrada, o Long.MAX_VALUE en caso de que el fotograma no tengan ninguna entrada.
</li>
<li>Este valor está diseñado principalmente para trabajar en la plataforma y tiene utilidad limitada para los desarrolladores de aplicaciones.
</li>
</ul>
</li>
<li>NEWEST_INPUT_EVENT
<ul>
<li>La marca de tiempo del evento de entrada más reciente de la cola de entrada, o 0 en caso de que el fotograma no contenga ninguna entrada.
</li>
<li>Este valor está diseñado principalmente para trabajar en la plataforma y tiene utilidad limitada para los desarrolladores de aplicaciones.
</li>
<li>Sin embargo, puede obtener una idea general sobre la cantidad de latencia que la aplicación está añadiendo consultando (FRAME_COMPLETED - NEWEST_INPUT_EVENT).
</li>
</ul>
</li>
<li>HANDLE_INPUT_START
<ul>
<li>La marca de tiempo en que el evento de entrada se distribuye a la aplicación.
</li>
<li>Al observar el tiempo entre esto y ANIMATION_START, se puede medir cuánto tiempo dedicó la aplicación a la administración de eventos de entrada.
</li>
<li>Si este valor es alto (mayor a 2 ms), esto significa que la aplicación dedica tiempo poco común al proceso de los eventos de entrada, como View.onTouchEvent(), lo que indica que este proceso se debe optimizar o descargar a otro subproceso.
Tenga en cuenta que, en algunas ocasiones, como cuando al hacer clic en un evento que lanza nuevas actividades o algo parecido, se espera y es aceptable que este valor sea alto.
</li>
</ul>
</li>
<li>ANIMATION_START
<ul>
<li>La marca de tiempo en la que se ejecutaron las animaciones registradas con Choreographer.
</li>
<li>Al observar el tiempo entre esto y PERFORM_TRANVERSALS_START, se puede determinar cuánto tiempo llevó evaluar todos los mecanismos de animación (los más comunes son ObjectAnimator, ViewPropertyAnimator y Transitions) que se estén ejecutando.
</li>
<li>Si este valor es alto (mayor a 2 ms), controle si su aplicación escribió alguna animación personalizada o qué campos está animando ObjectAnimators y asegúrese de que su animación sea adecuada.
</li>
<li>Para obtener más información sobre Choreographer, consulte el video <a href="https://developers.google.com/events/io/sessions/325418001">For Butter or Worse</a>.
</li>
</ul>
</li>
<li>PERFORM_TRAVERSALS_START
<ul>
<li>Si a este valor le resta DRAW_START, puede saber cuánto tardaron en completarse las fases de medición y diseño. (Durante el desplazamiento o la animación, este número deberá ser cercano a cero).
</li>
<li>Para obtener más información sobre las fases de medición y diseño de la canalización de representación, consulte el video <a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=27">
Invalidations, Layouts and Performance</a>.
</li>
</ul>
</li>
<li>DRAW_START
<ul>
<li>El momento en que comenzó la fase de dibujo de performTraversals. Este es el punto inicial de grabación de la listas de visualización de cualquier vista invalidada.
</li>
<li>El tiempo entre esto y SYNC_START muestra cuánto se tardó en llamar a View.draw() en todas las vistas invalidadas en el árbol.
</li>
<li>Para obtener más información sobre el modelo de dibujo, consulte los videos <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#hardware-model">Hardware Acceleration</a>
o <a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=27">
Invalidations, Layouts and Performance.</a>
</li>
</ul>
</li>
<li>SYNC_START
<ul>
<li>El momento en que comenzó la fase de sincronización del dibujo.
</li>
<li>Si el tiempo entre esto e ISSUE_DRAW_COMMANDS_START es muy alto (mayor a 0,4 ms o similar), generalmente esto significa que se dibujaron muchos mapas de bits que se deben subir a GPU.
</li>
<li>Para obtener más información sobre la fase de sincronización, consulte el video <a href="https://www.youtube.com/watch?v=VzYkVL1n4M8&amp;index=24&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu">
Profile GPU Rendering.</a>
</li>
</ul>
</li>
<li>ISSUE_DRAW_COMMANDS_START
<ul>
<li>El momento en que el representador de hardware comenzó a enviar comandos de dibujo a GPU.
</li>
<li>El tiempo entre esto y FRAME_COMPLETED permite obtener una idea general sobre cuánto trabajo le genera la aplicación a GPU.
Aquí aparecen los problemas como el exceso de dibujos o efectos de representación ineficientes.
</li>
</ul>
</li>
<li>SWAP_BUFFERS
<ul>
<li>El momento en que se llamó a eglSwapBuffers, generalmente de poca importancia fuera del trabajo en plataforma.
</li>
</ul>
</li>
<li>FRAME_COMPLETED
<ul>
<li>¡Todo listo! El tiempo total dedicado al trabajo en este fotograma se puede calcular al hacer FRAME_COMPLETED - INTENDED_VSYNC.
</li>
</ul>
</li>
</ul>
<p>
Puede utilizar esta información de distintas maneras. Un método de visualización simple pero eficaz es el histograma que muestra la distribución de los tiempos del fotograma (FRAME_COMPLETED - INTENDED_VSYNC) en distintos bloques de latencia; vea la siguiente figura.
Este gráfico indica brevemente que la mayoría de los fotogramas estuvieron muy bien, es decir, por debajo del límite de 16 ms (marcado en rojo). Sin embargo, algunos fotogramas estuvieron muy por arriba del límite.
En el histograma, podemos observar los cambios con el correr del tiempo para ver la creación de los cambios totales o los nuevos valores atípicos.
También puede graficar la latencia de entrada, el tiempo dedicado al diseño o cualquier otra medición interesante similar sobre las marcas de tiempo en los datos.
</p>
<img src="{@docRoot}preview/images/perf-test-framestats.png">
<h3 id="timing-dump">Volcado simple del intervalo del fotograma</h3>
<p>
Si, en las Opciones de Desarrollador, <strong>Profile GPU rendering</strong> se configura en <strong>In adb shell dumpsys gfinfo</strong>, el comando <code>adb shell dumpsys gfxinfo</code> emite sobre el tiempo de los 120 fotogramas más recientes y los agrupa en algunas categorías diferentes con valores separados por tabulación.
Esta información puede resultar útil para indicar qué partes de la canalización del dibujo podrían funcionar lento en un nivel alto.
</p>
<p>
Al igual que <a href="#fs-data-format">framestats</a>, es muy sencillo pegar esta información en su herramienta de hoja de cálculo preferida, o recolectar y redistribuir con un script.
El siguiente gráfico detalla dónde pasaron tiempo muchos de los fotogramas generados por la aplicación.
</p>
<img src="{@docRoot}preview/images/perf-test-frame-latency.png">
<p>
El resultado de ejecutar gfxinfo, copiar la salida, pegar en una aplicación de hoja de cálculo y graficar la información en forma de barras apiladas.
</p>
<p>
Cada barra vertical representa un fotograma de animación, su altura representa la cantidad de milisegundos que le llevó calcular ese fotograma de animación.
Cada segmento de color de la barra representa una etapa diferente de la canalización de representación, de manera que usted pueda observar qué partes de su aplicación pueden estar creando un cuello de botella.
Para obtener más información sobre la canalización de representación y cómo optimizarla, consulte el video <a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;index=27&amp;list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">
Invalidations Layouts and Performance</a>.
</p>
<h3 id="collection-window">Control del período de recopilación de datos</h3>
<p>
Los intervalos de framestats y del fotograma simple recopilan datos durante un período muy breve: aproximadamente dos segundos que valen la pena representar.
Para poder controlar este período con precisión, por ejemplo para limitar los datos a una animación en particular, puede restablecer todos los contadores y agregar los datos recopilados.
</p>
<pre>
&gt;adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt; reset
</pre>
<p>
Esto se puede usar junto con los comandos de volcado para recopilar y restablecer a una cadencia normal a fin de capturar continuamente períodos de fotogramas de menos de dos segundos.
</p>
<h3 id="diagnose">Diagnóstico de regresiones de rendimiento</h3>
<p>
La identificación de regresiones es un buen primer paso para localizar los problemas y mantener la aplicación funcionando correctamente.
Sin embargo, dumpsys solo identifica la existencia y la gravedad relativa de los problemas.
Usted todavía debe diagnosticar la causa particular de los problemas de rendimiento y encontrar las soluciones adecuadas.
Para esto, es sumamente recomendable que utilice la herramienta <a href="{@docRoot}tools/help/systrace.html">systrace</a>.
</p>
<h3 id="resources">Recursos adicionales</h3>
<p>
Para obtener más información sobre el funcionamiento de la canalización de representación de Android, los problemas comunes que puede encontrar y cómo solucionarlos, es posible que algunos de los siguientes recursos le resulten útiles:
</p>
<ul>
<li>Rendering Performance 101
</li>
<li>Why 60fps?
</li>
<li>Android UI and the GPU
</li>
<li>Invalidations Layouts and performance
</li>
<li>Analyzing UI Performance with Systrace
</li>
</ul>
<h2 id="automate">Pruebas automatizadas de rendimiento de la UI</h2>
<p>
Un enfoque para realizar la prueba de rendimiento de la UI es solicitar a un evaluador que realice una serie de operaciones de usuario en la aplicación objetivo para identificar visualmente jank, o bien, pasar mucho tiempo utilizando un enfoque basado en alguna herramienta para encontrar jank.
Sin embargo, este enfoque manual tiene sus riesgos, la habilidad humana para percibir cambios en los índices de los fotogramas varía de manera alarmante. Además, este proceso lleva mucho tiempo, es tedioso y propenso a errores.
</p>
<p>
Un método más eficiente es registrarse y analizar las mediciones de rendimiento clave a partir de pruebas automatizadas de UI.
Android M Developer Preview incluye nuevas capacidades de registro que facilitan la determinación de la cantidad y gravedad de jank en las animaciones de su aplicación y pueden utilizarse para crear un proceso estricto a fin de determinar su rendimiento actual y realizar un seguimiento de futuros objetivos de rendimiento.
</p>
<p>
Este artículo lo guía a través de un enfoque recomendado para utilizar esa información a fin de automatizar su prueba de rendimiento.
</p>
<p>
Esto se divide básicamente en dos acciones clave. Primero, identificar qué está probando y cómo lo prueba. Segundo, configurar y mantener un entorno de prueba automatizado.
</p>
<h3 id="ui-tests">Configuración de pruebas de UI</h3>
<p>
Antes de comenzar con las pruebas automatizadas, es importante establecer algunas decisiones de alto nivel para entender correctamente el espacio de prueba y las necesidades que puede tener.
</p>
<h4>
Identifique flujos/animaciones clave que desea probar
</h4>
<p>
Recuerde que el usuario visualiza el rendimiento negativo cuando una animación fluida se interrumpe.
Por lo tanto, al identificar qué tipo de acciones de UI desea probar, se recomienda centrarse en aquellas animaciones clave que el usuario ve más o que son más importantes para su experiencia.
Por ejemplo, a continuación, se mencionan situaciones comunes que es útil identificar:
</p>
<ul>
<li>Desplazamiento por ListView o RecyclerView principales
</li>
<li>Animaciones durante ciclos de espera no sincronizados
</li>
<li>Animaciones que puedan contener manipulación o carga de mapa de bits
</li>
<li>Animaciones que incluyan combinación alfa
</li>
<li>Dibujos personalizados con Canvas
</li>
</ul>
<p>
Trabaje con los ingenieros, diseñadores y gerentes de productos de su equipo a fin de priorizar estas animaciones clave para la cobertura de la prueba.
</p>
<h4>
Establezca sus objetivos futuros y realice un seguimiento en virtud de ellos
</h4>
<p>
Desde un nivel alto, puede ser crítico identificar sus metas de rendimiento específicas y concentrarse en escribir pruebas y recopilar datos sobre ellas.
Por ejemplo:
</p>
<ul>
<li>¿Simplemente desea comenzar a realizar un seguimiento del rendimiento de la UI por primera vez para obtener más información?
</li>
<li>¿Desea evitar regresiones que podrían aparecer en el futuro?
</li>
<li>¿Se encuentra hoy en un 90 % de fluidez de fotogramas y quiere alcanzar un 98 % en este trimestre?
</li>
<li>¿Se encuentra en un 98 % de fluidez de fotogramas y no quiere retroceder?
</li>
<li>¿Tiene como objetivo mejorar el rendimiento en dispositivos de gama baja?
</li>
</ul>
<p>
Para todas estas situaciones, es recomendable realizar un seguimiento que muestre el rendimiento en múltiples versiones de su aplicación.
</p>
<h4>
Identifique los dispositivos en los que desea realizar la prueba
</h4>
<p>
El rendimiento de la aplicación varía según el dispositivo en el que se ejecuta. Algunos dispositivos pueden tener menos memoria, GPU menos potentes o CPU más lentos.
Esto significa que las animaciones que funcionan bien en un conjunto de hardware pueden no hacerlo en otros, o peor, pueden provocar un cuello de botella en diferentes secciones de la canalización.
Por lo tanto, para justificar esta variación en lo que un usuario puede ver, seleccione una serie de dispositivos, tanto de alta gama como de baja, tablets, etc., en los que ejecutará las pruebas.
Busque variedad en rendimiento de CPU, memoria RAM, resolución de pantalla, tamaño, etc.
Las pruebas exitosas en un dispositivo de alta gama pueden fallar en uno de baja gama.
</p>
<h4>
Marcos básicos para pruebas de UI
</h4>
<p>
Algunos conjuntos de herramientas, como <a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a> y <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso</a>, están diseñados para ayudar a automatizar el desplazamiento de un usuario por su aplicación.
Estos son marcos simples que imitan la interacción del usuario con el dispositivo.
Para utilizar estos marcos, debe crear con éxito scripts únicos que se ejecuten en un conjunto de acciones de usuarios y reproducirlos en el dispositivo en sí.
</p>
<p>
Al combinar estas pruebas automatizadas junto con <code>dumpsys gfxinfo</code>, puede crear rápidamente un sistema reproducible que le permite ejecutar una prueba y medir la información de rendimiento de esa condición particular.
</p>
<h3 id="automated-tests">Configurar pruebas automatizadas de UI</h3>
<p>
Una vez que pueda ejecutar una prueba de UI y una canalización para recopilar datos de una sola prueba, el próximo paso importante es elegir un marco que pueda ejecutar esa prueba muchas veces en múltiples dispositivos y agregar los datos de rendimiento resultantes para que su equipo de desarrollo los analice mejor.
</p>
<h4>
Un marco para la automatización de pruebas
</h4>
<p>
Vale la pena mencionar que los marcos para pruebas de UI (como <a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a>) se ejecutan directamente en el emulador/dispositivo objetivo.
A la recopilación de información de rendimiento realizada por
<em>dumpsys gfxinfo</em> la impulsa un equipo de host que envía comandos por ADB. Para ayudar a unir la automatización de estas entidades separadas, se diseñó el marco <a href="{@docRoot}tools/help/monkeyrunner_concepts.html">MonkeyRunner.</a> Un sistema de scripts que se ejecuta en su equipo de host y que puede emitir comandos a un conjunto de dispositivos conectados y recibir datos de ellos.
</p>
<p>
Al crear un conjunto de scripts para la automatización adecuada de las pruebas de rendimiento de UI, usted podrá, como mínimo, utilizar MonkeyRunner para realizar con éxito las siguientes tareas:
</p>
<ul>
<li>Cargar e iniciar un APK deseado en un dispositivo objetivo, en múltiples dispositivos o en un emulador.
</li>
<li>Iniciar una prueba de UI automatizada y permitir que se ejecute.
</li>
<li>Recopilar información de rendimiento mediante <em>dumpsys gfxinfo</em><em>.</em>
</li>
<li>Añadir información y presentársela de manera útil al desarrollador.
</li>
</ul>
<h3 id="triage">Clasificar y solucionar problemas detectados</h3>
<p>
Una vez que se identifican los patrones de problemas o las regresiones, el paso siguiente es identificar y aplicar la solución.
Si su marco de pruebas automatizadas preserva detalles precisos del intervalo para los fotogramas, puede ayudarlo a investigar cambios sospechosos de código o diseño (en el caso de una regresión), o delimitar la parte del sistema que está analizando al cambiar a una investigación manual.
Para realizar una investigación manual, <a href="{@docRoot}tools/help/systrace.html">systrace</a> es un buen lugar para comenzar, ya que muestra información precisa sobre cada etapa de la canalización de representación, cada subproceso y núcleo del sistema, además de cualquier marca de evento personalizada que usted defina.
</p>
<h4>
Descripción adecuada de intervalos temporales
</h4>
<p>
Es importante mencionar las dificultades para obtener y medir los intervalos que son producto del rendimiento de la representación.
Estos números son, por naturaleza, no deterministas y, a menudo, fluctúan según el estado del sistema, la cantidad de memoria disponible, el límite térmico y la última vez que un rayo solar tocó el área de la tierra donde se encuentra.
El punto es que puede ejecutar la misma prueba dos veces y obtener números apenas diferentes que pueden estar cerca pero no ser iguales.
</p>
<p>
Para recopilar y definir datos correctamente de esta manera, deberá ejecutar la misma prueba muchas veces y acumular los resultados como un promedio o un valor promedio (para que resulte más fácil, lo llamaremos un “lote”). Esto le ofrece una aproximación estimada del rendimiento de la prueba, sin requerir intervalos exactos.
</p>
<p>
Los lotes se pueden usar entre cambios de código para verificar el impacto relativo que esos cambios tienen en el rendimiento.
Si el índice de fotograma promedio para el lote previo al cambio es que el lote después del cambio, entonces, generalmente está en presencia de un incremento general en relación con el rendimiento para ese cambio particular.
</p>
<p>
Esto significa que cualquier prueba automatizada de UI que lleve a cabo debería tener en cuenta este concepto, además de justificar cualquier anomalía que pudiera surgir durante una prueba.
Por ejemplo, si el rendimiento de su aplicación disminuye repentinamente debido a algún problema con el dispositivo (que no sea provocado por la aplicación), deberá volver a ejecutar el lote para obtener intervalos menos caóticos.
</p>
<p>
Entonces, ¿cuántas veces debe ejecutar una prueba para que los resultados sean significativos? El mínimo debe ser 10 veces y con números más altos, como 50 o 100, para obtener resultados más precisos (por supuesto, ahora cambia el tiempo por la precisión).
</p>

View File

@@ -0,0 +1,550 @@
page.title=Definir animaciones personalizadas
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#Touch">Personalizar la respuesta táctil</a></li>
<li><a href="#Reveal">Usar el efecto Revelar</a></li>
<li><a href="#Transitions">Personalizar transiciones de actividades</a></li>
<li><a href="#ViewState">Animar cambios de estados de las vistas</a></li>
<li><a href="#AnimVector">Animar interfaces dibujables en vector</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Las animaciones en Material Design proporcionan a los usuarios comentarios sobre sus acciones y continuidad visual
a medida que los usuarios interactúan con su aplicación. El tema material proporciona algunas animaciones predeterminadas
para botones y transiciones de actividades; Android 5.0 (API nivel 21) y superior te permite personalizar estas
animaciones y crear unas nuevas:</p>
<ul>
<li>Respuesta táctil</li>
<li>Efecto revelar circular</li>
<li>Transiciones de actividades</li>
<li>Movimiento curvo</li>
<li>Ver cambios de estados</li>
</ul>
<h2 id="Touch">Personalizar la respuesta táctil</h2>
<p>La respuesta táctil en Material Design proporciona una confirmación visual instantánea en el punto
de contacto cuando los usuarios interactúan con los elementos de la IU. Las animaciones predeterminadas de la respuesta táctil para
botones usan la nueva clase {@link android.graphics.drawable.RippleDrawable}, que realiza una transición
entre diferentes estados con un efecto de ondas.</p>
<p>En la mayoría de los casos, debes aplicar esta funcionalidad en la vista XML especificando el fondo
de la vista como:</p>
<ul>
<li><code>?android:attr/selectableItemBackground</code> para un efecto de ondas con límites.</li>
<li><code>?android:attr/selectableItemBackgroundBorderless</code> para un efecto de ondas que se extiende más allá de
la vista. Se lo dibujará en la vista primaria más cercana de la vista (que lo limitará) con un fondo de valor no
nulo.</li>
</ul>
<p class="note"><strong>Nota:</strong> <code>selectableItemBackgroundBorderless</code> es un nuevo
atributo introducido en la API de nivel 21.</p>
<p>Alternativamente, puedes definir un {@link android.graphics.drawable.RippleDrawable}
como un recurso XML que usa el elemento <code>ripple</code>.</p>
<p>Puedes asignar un color a los objetos {@link android.graphics.drawable.RippleDrawable}. Para cambiar
el color predeterminado de la respuesta táctil, usa el atributo <code>android:colorControlHighlight</code>
del tema.</p>
<p>Para más información, consulta la referencia de la API para la clase {@link
android.graphics.drawable.RippleDrawable}.</p>
<h2 id="Reveal">Usar el efecto revelar</h2>
<p>Las animaciones del efecto revelar proporcionan a los usuarios una continuidad visual cuando muestras u ocultas un grupo de elementos
de la IU. El método {@link android.view.ViewAnimationUtils#createCircularReveal
ViewAnimationUtils.createCircularReveal()} te permite animar un círculo de recorte para
revelar u ocultar una vista.</p>
<p>Para revelar una vista previamente invisible usando este efecto:</p>
<pre>
// previously invisible view
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
</pre>
<p>Para ocultar una vista previamente invisible usando este efecto:</p>
<pre>
// previously visible view
final View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
&#64;Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
</pre>
<h2 id="Transitions">Personalizar transiciones de actividades</h2>
<!-- shared transition video -->
<div style="width:290px;margin-left:35px;float:right">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay="">
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4">
<source src="{@docRoot}design/material/videos/ContactsAnim.webm">
<source src="{@docRoot}design/material/videos/ContactsAnim.ogv">
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<p class="img-caption" style="margin-top:3px;margin-bottom:10px"><strong>Figura 1</strong>: una
transición con elementos compartidos.</p>
<em>Para volver a reproducir la película, haz clic en la pantalla del dispositivo.</em>
</div>
</div>
<p>Las transiciones de actividades en las aplicaciones de Material Design proporcionan conexiones visuales entre diferentes estados
mediante el movimiento y las transformaciones entre elementos comunes. Puedes especificar las animaciones personalizadas para
entrar y salir de las transiciones y para las transiciones de elementos compartidos entre actividades.</p>
<ul>
<li>Una transición de <strong>entrada</strong> determina cómo entran en escena las vistas en una actividad.
Por ejemplo, en la transición de entrada <em>expandir</em>, las vistas entran en escena desde el exterior
y vuelan hacia el centro de la pantalla.</li>
<li>Una transición de <strong>salida</strong> determina cómo salen de escena las vistas en una actividad. Por
ejemplo, en la transición de salida <em>expandir</em>, las vistas salen de escena lejos del
centro.</li>
<li>Una transición de <strong>elementos compartidos</strong> determina cómo las vistas que están compartidas entre
dos actividades realizan la transición entre estas. Por ejemplo, si dos actividades tienen la misma
imagen en diferentes posiciones y tamaños, la transición de elementos compartidos <em>changeImageTransform</em>
traduce y escala la imagen suavemente entre estas actividades.</li>
</ul>
<p>Android 5.0 (API nivel 21) admite estas transiciones de entrada y salida:</p>
<ul>
<li><em>expandir</em>: desplaza vistas hacia adentro o hacia afuera del centro de la escena.</li>
<li><em>deslizar</em>: desplaza vistas hacia adentro o hacia afuera de uno de los bordes de la escena.</li>
<li><em>difuminar</em>: agrega o quita una vista de la escena al cambiar su opacidad.</li>
</ul>
<p>Toda transición que extiende la clase {@link android.transition.Visibility} se admite
como una transición de entrada o salida. Para más información, consulta la referencia de la API para la clase
{@link android.transition.Transition}.</p>
<p>Android 5.0 (API nivel 21) también admite estas transiciones de elementos compartidos:</p>
<ul>
<li><em>changeBounds</em>: anima los cambios en los límites de las vistas de destino.</li>
<li><em>changeClipBounds</em>: anima los cambios en los límites de recorte de las vistas de destino.</li>
<li><em>changeTransform</em>: anima los cambios en escala y rotación de las vistas de destino.</li>
<li><em>changeImageTransform</em>: anima los cambios de tamaño y escala de imágenes de destino.</li>
</ul>
<p>Cuando habilitas las transiciones de actividades en tu aplicación, la transición entre difuminados predeterminada se
activa entre las actividades que ingresan y salen.</p>
<img src="{@docRoot}training/material/images/SceneTransition.png" alt="" width="600" height="405" style="margin-top:20px" />
<p class="img-caption">
  <strong>Figura 2</strong>: una transición de escena con un elemento compartido.
</p>
<h3>Especificar transiciones personalizadas</h3>
<p>Primero, habilita las transiciones de contenido de la ventana con el atributo <code>android:windowContentTransitions</code>
cuando definas un estilo que herede del tema material. También puedes especificar
transiciones de entrada, salida y elementos compartidos en tu definición de estilo:</p>
<pre>
&lt;style name="BaseAppTheme" parent="android:Theme.Material">
&lt;!-- enable window content transitions -->
&lt;item name="android:windowContentTransitions">true&lt;/item>
&lt;!-- specify enter and exit transitions -->
&lt;item name="android:windowEnterTransition">@transition/explode&lt;/item>
&lt;item name="android:windowExitTransition">@transition/explode&lt;/item>
&lt;!-- specify shared element transitions -->
&lt;item name="android:windowSharedElementEnterTransition">
&#64;transition/change_image_transform&lt;/item>
&lt;item name="android:windowSharedElementExitTransition">
&#64;transition/change_image_transform&lt;/item>
&lt;/style>
</pre>
<p>La transición <code>change_image_transform</code> en este ejemplo se define en la siguiente forma:</p>
<pre>
&lt;!-- res/transition/change_image_transform.xml -->
&lt;!-- (see also Shared Transitions below) -->
&lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
&lt;changeImageTransform/>
&lt;/transitionSet>
</pre>
<p>El elemento <code>changeImageTransform</code> corresponde a la clase
{@link android.transition.ChangeImageTransform}. Para más información, consulta la referencia de la
API para {@link android.transition.Transition}.</p>
<p>Para habilitar las transiciones del contenido de las ventanas en tu código, llama al método
{@link android.view.Window#requestFeature Window.requestFeature()}:</p>
<pre>
// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// set an exit transition
getWindow().setExitTransition(new Explode());
</pre>
<p>Para especificar transiciones en tu código, llama a estos métodos con un objeto {@link
android.transition.Transition}:</p>
<ul>
<li>{@link android.view.Window#setEnterTransition Window.setEnterTransition()}</li>
<li>{@link android.view.Window#setExitTransition Window.setExitTransition()}</li>
<li>{@link android.view.Window#setSharedElementEnterTransition
Window.setSharedElementEnterTransition()}</li>
<li>{@link android.view.Window#setSharedElementExitTransition
Window.setSharedElementExitTransition()}</li>
</ul>
<p>Los métodos {@link android.view.Window#setExitTransition setExitTransition()} y {@link
android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} definen
la transición de salida para la actividad que realiza la llamada. Los métodos {@link android.view.Window#setEnterTransition
setEnterTransition()} y {@link android.view.Window#setSharedElementEnterTransition
setSharedElementEnterTransition()} definen la transición de entrada para la actividad invocada.</p>
<p>Para obtener el efecto completo de una transición, debes habilitar las transiciones de contenido de las ventanas tanto para las
actividades que realizan la llamada como para aquellas que son invocadas. De lo contrario, la actividad que realiza la llamada comenzará la transición de salida,
pero luego observarás una ventana de transición (como escalar o difuminar).</p>
<p>Para comenzar una transición de entrada lo antes posible, usa el método
{@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()}
en la actividad invocada. Esto te permite tener transiciones de entrada más intensas.</p>
<h3>Iniciar una actividad mediante el uso de transiciones</h3>
<p>Si permites transiciones y estableces una transición de salida para una actividad, la transición se activa
cuando inicias otra actividad, como alguna de las siguientes:</p>
<pre>
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
</pre>
<p>Si estableciste una transición de entrada para la segunda actividad, la transición también se activa
cuando se inicia la actividad. Para deshabilitar las transiciones cuando inicias otra actividad, proporciona
una agrupación de opciones <code>null</code>.</p>
<h3>Iniciar una actividad con un elemento compartido</h3>
<p>Para realizar una animación de transiciones de pantallas entre dos actividades que tienen un elemento compartido:</p>
<ol>
<li>Habilita las transiciones de contenido de ventanas en tu tema.</li>
<li>Especifica una transición de elementos compartidos en tu estilo.</li>
<li>Define tu transición como un recurso XML.</li>
<li>Asigna un nombre en común para los elementos compartidos en ambos diseños con el atributo
<code>android:transitionName</code>.</li>
<li>Usa el método {@link android.app.ActivityOptions#makeSceneTransitionAnimation
ActivityOptions.makeSceneTransitionAnimation()}.</li>
</ol>
<pre>
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);
// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);
// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
&#64;Override
public void onClick(View view) {
Intent intent = new Intent(this, Activity2.class);
// create the transition animation - the images in the layouts
// of both activities are defined with android:transitionName="robot"
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(this, androidRobotView, "robot");
// start the new activity
startActivity(intent, options.toBundle());
}
});
</pre>
<p>Para las vistas dinámicas compartidas que generas en tu código, usa el método
{@link android.view.View#setTransitionName View.setTransitionName()} para especificar un nombre de
elemento en común en ambas actividades.</p>
<p>Para invertir la animación de transición de escenas cuando terminas la segunda actividad, llama al método
{@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()}
en lugar del {@link android.app.Activity#finish Activity.finish()}.</p>
<h3>Iniciar una actividad con múltiples elementos compartidos</h3>
<p>Para realizar una animación de transición de escenas entre dos actividades que tienen más de un elemento
compartido, define los elementos compartidos en ambos diseños con el atributo <code>android:transitionName</code>
(o usa el método {@link android.view.View#setTransitionName View.setTransitionName()}
en ambas actividades) y crea un objeto {@link android.app.ActivityOptions} como se indica a continuación:</p>
<pre>
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
Pair.create(view1, "agreedName1"),
Pair.create(view2, "agreedName2"));
</pre>
<h2 id="CurvedMotion">Usar movimiento curvo</h2>
<p>Las animaciones en Material Design se basan en curvas para la interpolación de tiempo y los modelos de movimiento
espacial. Con Android 5.0 (API nivel 21) y superior, puedes definir las curvas de sincronización personalizadas y
los modelos de movimientos curvos para las animaciones.</p>
<p>La clase {@link android.view.animation.PathInterpolator} es un nuevo interpolador que se basa en una curva
Bézier o un objeto {@link android.graphics.Path}. Este interpolador especifica una curva de movimiento
en un cuadrado de 1x1, con puntos de anclaje a (0,0) y (1,1), y puntos de control según lo especificado en los argumentos del
constructor. También puedes definir un interpolador para la ruta de acceso como un recurso XML:</p>
<pre>
&lt;pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:controlX1="0.4"
android:controlY1="0"
android:controlX2="1"
android:controlY2="1"/>
</pre>
<p>El sistema proporciona recursos XML para las tres curvas básicas en la especificación
de Material Design:</p>
<ul>
<li><code>&#64;interpolator/fast_out_linear_in.xml</code></li>
<li><code>&#64;interpolator/fast_out_slow_in.xml</code></li>
<li><code>&#64;interpolator/linear_out_slow_in.xml</code></li>
</ul>
<p>Puedes pasar un objeto {@link android.view.animation.PathInterpolator} al método {@link
android.animation.Animator#setInterpolator Animator.setInterpolator()}.</p>
<p>La clase {@link android.animation.ObjectAnimator} tiene nuevos constructores que te permiten animar
coordenadas junto a una ruta de acceso, usando dos o más propiedades a la vez. Por ejemplo, el siguiente animador
usa un objeto{@link android.graphics.Path} para animar las propiedades X e Y de una vista:</p>
<pre>
ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();
</pre>
<h2 id="ViewState">Animar cambios de estados de las vistas</h2>
<p>La clase {@link android.animation.StateListAnimator} te permite definir los animadores que se ejecutan cuando
cambia el estado de una vista. En el siguiente ejemplo, se muestra cómo definir un {@link
android.animation.StateListAnimator} como un recurso XML:</p>
<pre>
&lt;!-- animate the translationZ property of a view when pressed -->
&lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
&lt;item android:state_pressed="true">
&lt;set>
&lt;objectAnimator android:propertyName="translationZ"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="2dp"
android:valueType="floatType"/>
&lt;!-- you could have other objectAnimator elements
here for "x" and "y", or other properties -->
&lt;/set>
&lt;/item>
&lt;item android:state_enabled="true"
android:state_pressed="false"
android:state_focused="true">
&lt;set>
&lt;objectAnimator android:propertyName="translationZ"
android:duration="100"
android:valueTo="0"
android:valueType="floatType"/>
&lt;/set>
&lt;/item>
&lt;/selector>
</pre>
<p>Para adjuntar animaciones personalizadas de los estados de visualizaciones, define un animador usando el elemento
<code>selector</code> en un archivo de recurso XML como en este ejemplo y asígnalo a tu
vista con el atributo <code>android:stateListAnimator</code>. Para asignar un animador de lista de estados
a una vista en tu código, usa el método {@link android.animation.AnimatorInflater#loadStateListAnimator
AnimationInflater.loadStateListAnimator()} y asigna el animador a tu vista con el método
{@link android.view.View#setStateListAnimator View.setStateListAnimator()}.</p>
<p>Cuando tu tema extiende al tema material, los botones tendrán una animación Z de manera predeterminada. Para evitar este
comportamiento en los botones, establece el atributo <code>android:stateListAnimator</code> en
<code>@null</code>.</p>
<p>La clase {@link android.graphics.drawable.AnimatedStateListDrawable} te permite crear elementos de diseño
que muestren animaciones entre los cambios de estados de la vista asociada. Algunos de los widgets del sistema en
Android 5.0 usan estas animaciones de manera predeterminada. En el siguiente ejemplo, se muestra cómo
definir un {@link android.graphics.drawable.AnimatedStateListDrawable} como un recurso XML:</p>
<pre>
&lt;!-- res/drawable/myanimstatedrawable.xml -->
&lt;animated-selector
xmlns:android="http://schemas.android.com/apk/res/android">
&lt;!-- provide a different drawable for each state-->
&lt;item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
android:state_pressed="true"/>
&lt;item android:id="@+id/focused" android:drawable="@drawable/drawableF"
android:state_focused="true"/>
&lt;item android:id="@id/default"
android:drawable="@drawable/drawableD"/>
&lt;!-- specify a transition -->
&lt;transition android:fromId="@+id/default" android:toId="@+id/pressed">
&lt;animation-list>
&lt;item android:duration="15" android:drawable="@drawable/dt1"/>
&lt;item android:duration="15" android:drawable="@drawable/dt2"/>
...
&lt;/animation-list>
&lt;/transition>
...
&lt;/animated-selector>
</pre>
<h2 id="AnimVector">Animar interfaces dibujables en vector</h2>
<p>Las <a href="{@docRoot}training/material/drawables.html#VectorDrawables">interfaces dibujables en vector</a> son
escalables sin perder definición. La clase {@link android.graphics.drawable.AnimatedVectorDrawable}
te permite animar las propiedades de un elemento de diseño en vector.</p>
<p>Generalmente, las interfaces animadas dibujables en vector se definen en tres archivos XML:</p>
<ul>
<li>Una interfaz dibujable en vector con el elemento <code>&lt;vector&gt;</code> en
<code>res/drawable/</code></li>
<li>Una interfaz dibujable animada en vector con el elemento <code>&lt;animated-vector&gt;</code> en
<code>res/drawable/</code></li>
<li>Uno o más animadores de objeto con el elemento <code>&lt;objectAnimator&gt;</code> en
<code>res/anim/</code></li>
</ul>
<p>Las interfaces animadas dibujables en vector pueden animar los atributos de los elementos <code>&lt;group&gt;</code> y
<code>&lt;path&gt;</code>. Los elementos <code>&lt;group&gt;</code> definen un conjunto de
rutas de acceso o subgrupos y el elemento <code>&lt;path&gt;</code> define rutas de acceso para dibujar.</p>
<p>Cuando definas una interfaz dibujable en vector que desees animar, usa el atributo <code>android:name</code>
para asignar un nombre único a grupos o rutas de acceso, de manera que puedas hacer referencia a ellos desde tus definiciones del
animador. Por ejemplo:</p>
<pre>
&lt;!-- res/drawable/vectordrawable.xml -->
&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="64dp"
android:width="64dp"
android:viewportHeight="600"
android:viewportWidth="600">
&lt;group
<strong>android:name="rotationGroup"</strong>
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="45.0" >
&lt;path
<strong>android:name="v"</strong>
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
&lt;/group>
&lt;/vector>
</pre>
<p>La definición de la interfaz animada dibujable en vector hace referencia a grupos y rutas de acceso en el elemento de diseño en vector
por sus nombres:</p>
<pre>
&lt;!-- res/drawable/animvectordrawable.xml -->
&lt;animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vectordrawable" >
&lt;target
android:name="rotationGroup"
android:animation="@anim/rotation" />
&lt;target
android:name="v"
android:animation="@anim/path_morph" />
&lt;/animated-vector>
</pre>
<p>Las definiciones de animación representan objetos {@link android.animation.ObjectAnimator} o {@link
android.animation.AnimatorSet}. El primer animador en este ejemplo rota el grupo
objetivo unos 360 grados:</p>
<pre>
&lt;!-- res/anim/rotation.xml -->
&lt;objectAnimator
android:duration="6000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360" />
</pre>
<p>El segundo animador en este ejemplo transforma la ruta de acceso de la interfaz dibujable en vector de una forma a
otra. Ambas rutas de acceso deben ser compatibles para transformarse: deben tener el mismo número de comandos
y el mismo número de parámetros para cada comando.</p>
<pre>
&lt;!-- res/anim/path_morph.xml -->
&lt;set xmlns:android="http://schemas.android.com/apk/res/android">
&lt;objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType" />
&lt;/set>
</pre>
<p>Para más información, consulta la referencia de la API para {@link
android.graphics.drawable.AnimatedVectorDrawable}.</p>

View File

@@ -0,0 +1,168 @@
page.title=Mantener la compatibilidad
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#Theme">Definir estilos alternativos</a></li>
<li><a href="#Layouts">Proporcionar diseños alternativos</a></li>
<li><a href="#SupportLib">Usar la Biblioteca de soporte</a></li>
<li><a href="#CheckVersion">Comprobar la versión del sistema</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Algunas características de Material Design, como el tema material y las transiciones de actividades personalizadas, solo
están disponibles en Android 5.0 (API nivel 21) y superior. Sin embargo, puedes diseñar tus aplicaciones para
usar estas características cuando se ejecutan en dispositivos que admiten Material Design y aún son compatibles
con dispositivos que ejecutan versiones anteriores de Android.</p>
<h2 id="Theme">Definir estilos alternativos</h2>
<p>Puedes configurar tu aplicación para usar el tema material en los dispositivos que los admiten y revertir
a un tema anterior en los dispositivos que ejecutan versiones anteriores de Android:</p>
<ol>
<li>Define un tema que herede de un tema anterior (como Holo) en
<code>res/values/styles.xml</code>.</li>
<li>Define un tema con el mismo nombre que hereda del tema material en
<code>res/values-v21/styles.xml</code>.</li>
<li>Establece este tema como el tema de tu aplicación en el archivo de manifiesto.</li>
</ol>
<p class="note"><strong>Nota:</strong>
Si tu aplicación usa el tema material pero no proporciona un tema alternativo,
tu aplicación no se ejecutará en versiones de Android anteriores a la versión 5.0.
</p>
<h2 id="Layouts">Proporcionar diseños alternativos</h2>
<p>Si los diseños que realizas de acuerdo con las pautas de Material Design no usan ninguno de
los nuevos atributos XML introducidos en Android 5.0 (API nivel 21), estos trabajarán en
versiones anteriores de Android. De lo contrario, puedes proporcionar diseños alternativos. También puedes proporcionar diseños
alternativos para personalizar la apariencia de tu aplicación en versiones anteriores de Android.</p>
<p>Crea tus archivos de diseño para Android 5.0 (API nivel 21) dentro de <code>res/layout-v21/</code> y
tus archivos de diseño alternativo para versiones anteriores de Android dentro de <code>res/layout/</code>.
Por ejemplo, <code>res/layout/my_activity.xml</code> es un diseño alternativo para
<code>res/layout-v21/my_activity.xml</code>.</p>
<p>Para evitar duplicación de código, define tus estilos en <code>res/values/</code>, modifica
estilos en <code>res/values-v21/</code> para las nuevas API y usa transmisión por herencia de estilos, definiendo estilos
base en <code>res/values/</code> y heredando de los que están en <code>res/values-v21/</code>.</p>
<h2 id="SupportLib">Usar la Biblioteca de soporte</h2>
<p>Las <a href="{@docRoot}tools/support-library/features.html#v7">Bibliotecas de soporte v7</a>
r21 y superiores incluyen las siguientes características de Material Design:</p>
<ul>
<li><a href="{@docRoot}training/material/theme.html">Estilos de Material Design</a> para algunos widgets
del sistema cuando aplicas uno de los temas <code>Theme.AppCompat</code>.</li>
<li><a href="{@docRoot}training/material/theme.html#ColorPalette">Atributos del tema de la paleta de colores</a>
en los temas <code>Theme.AppCompat</code>.</li>
<li>El widget {@link android.support.v7.widget.RecyclerView} para <a href="{@docRoot}training/material/lists-cards.html#RecyclerView">mostrar conjuntos
de datos</a>.</li>
<li>El widget {@link android.support.v7.widget.CardView} para <a href="{@docRoot}training/material/lists-cards.html#CardView">crear tarjetas</a>.</li>
<li>La clase {@link android.support.v7.graphics.Palette} para <a href="{@docRoot}training/material/drawables.html#ColorExtract">extraer colores prominentes de
imágenes</a>.</li>
</ul>
<h3>Widgets del sistema</h3>
<p>Los temas <code>Theme.AppCompat</code> proporcionan estilos de Material Design para estos widgets:</p>
<ul>
<li>{@link android.widget.EditText}</li>
<li>{@link android.widget.Spinner}</li>
<li>{@link android.widget.CheckBox}</li>
<li>{@link android.widget.RadioButton}</li>
<li>{@link android.support.v7.widget.SwitchCompat}</li>
<li>{@link android.widget.CheckedTextView}</li>
</ul>
<h3>Paleta de colores</h3>
<p>Para obtener estilos de Material Design y personalizar la paleta de colores con la Biblioteca de soporte
v7 de Android, aplica uno de los temas <code>Theme.AppCompat</code>:</p>
<pre>
&lt;!-- extend one of the Theme.AppCompat themes -->
&lt;style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
&lt;!-- customize the color palette -->
&lt;item name="colorPrimary">@color/material_blue_500&lt;/item>
&lt;item name="colorPrimaryDark">@color/material_blue_700&lt;/item>
&lt;item name="colorAccent">@color/material_green_A200&lt;/item>
&lt;/style>
</pre>
<h3>Listas y tarjetas</h3>
<p>Los widgets {@link android.support.v7.widget.RecyclerView} y {@link
android.support.v7.widget.CardView} están disponible en versiones anteriores de Android mediante
la Biblioteca de soporte v7 con estas limitaciones:</p>
<ul>
<li>{@link android.support.v7.widget.CardView} regresa a una implementación de sombras programáticas
mediante el uso de espaciado adicional.</li>
<li>{@link android.support.v7.widget.CardView} no recorta las vistas de sus hijos que forman intersecciones
con esquinas redondeadas.</li>
</ul>
<h3>Dependencias</h3>
<p>Para usar estas características en versiones de Android anteriores a la 5.0 (API nivel 21), incluye
en tu proyecto la Biblioteca de soporte v7 de Android como una <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependencia de Gradle</a>:</p>
<pre>
dependencies {
compile 'com.android.support:appcompat-v7:21.0.+'
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>
<h2 id="CheckVersion">Comprobar la versión del sistema</h2>
<p>Las siguientes características están disponibles solo en Android 5.0 (nivel de API 21) y superior:</p>
<ul>
<li>Transiciones de actividades</li>
<li>Respuesta táctil</li>
<li>Animaciones con el efecto revelar</li>
<li>Animaciones basadas en rutas</li>
<li>Interfaces dibujables en vector</li>
<li>Matiz de la interfaz dibujable</li>
</ul>
<p>Para conservar la compatibilidad con versiones anteriores de Android, comprueba la {@link
android.os.Build.VERSION#SDK_INT version} del sistema en tiempo de ejecución antes de invocar las API para cualquiera de estas
características:</p>
<pre>
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Call some material design APIs here
} else {
// Implement this feature without material design
}
</pre>
<p class="note"><strong>Nota:</strong> Para especificar qué versiones de Android admite tu aplicación,
usa los atributos <code>android:minSdkVersion</code> y <code>android:targetSdkVersion</code>
en tu archivo de manifiesto. Para usar las características de Material Design en Android 5.0, establece el
atributo <code>android:targetSdkVersion</code> en <code>21</code>. Para más información, consulta
la <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">guía de &lt;uses-sdk&gt; de la
API</a>.</p>

View File

@@ -0,0 +1,126 @@
page.title=Trabajar con interfaces dibujables
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#DrawableTint">Cambiar el matiz de los recursos dibujables</a></li>
<li><a href="#ColorExtract">Extraer colores prominentes de una imagen</a></li>
<li><a href="#VectorDrawables">Crear interfaces dibujables en vector</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Diseño material en Android</a></li>
</ul>
</div>
</div>
<p>Las siguientes capacidades para las interfaces dibujables te ayudan a implementar Material Design en tus aplicaciones:</p>
<ul>
<li>Matiz de la interfaz dibujable</li>
<li>Extracción de color prominente</li>
<li>Interfaces dibujables en vector</li>
</ul>
<p>Esta lección te muestra cómo usar estas características en tu aplicación.</p>
<h2 id="DrawableTint">Cambiar el matiz de los recursos dibujables</h2>
<p>Con Android 5.0 (API nivel 21) y superior, puedes cambiar el matiz de los mapas de bits y nueve parches definidos como
máscaras alfa. Puedes cambiar el matiz con recursos de colores o atributos de temas que se resuelven a
recursos de colores (por ejemplo, <code>?android:attr/colorPrimary</code>). Generalmente, puedes crear estos recursos
solo una vez y agregarles color automáticamente para que coincidan con tu tema.</p>
<p>Puedes aplicar un matiz a los objetos {@link android.graphics.drawable.BitmapDrawable} o {@link
android.graphics.drawable.NinePatchDrawable} con el método {@code setTint()}. También puedes
establecer el color de matiz y el modo en tus diseños con los atributos <code>android:tint</code> y
<code>android:tintMode</code>.</p>
<h2 id="ColorExtract">Extraer colores prominentes de una imagen</h2>
<p>La Biblioteca de soporte de Android r21 y superiores incluye la clase {@link
android.support.v7.graphics.Palette}, que te permite extraer colores prominentes de una imagen.
Esta clase extrae los siguientes colores prominentes:</p>
<ul>
<li>Brillante</li>
<li>Oscuro brillante</li>
<li>Claro brillante</li>
<li>Apagado</li>
<li>Oscuro apagado</li>
<li>Claro apagado</li>
</ul>
<p>Para extraer estos colores, pasa un objeto {@link android.graphics.Bitmap} al método estático
{@link android.support.v7.graphics.Palette#generate Palette.generate()} en el subproceso en
segundo plano en donde cargas tus imágenes. Si no puedes usar dicho subproceso, llama al método
{@link android.support.v7.graphics.Palette#generateAsync Palette.generateAsync()} y proporciona
un gestor de eventos en su lugar.</p>
<p>Puedes recuperar los colores prominentes de la imagen mediante los métodos de obtención en la clase
<code>Palette</code>, como <code>Palette.getVibrantColor</code>.</p>
<p>Para usar la clase {@link android.support.v7.graphics.Palette} en tu proyecto, agrega la siguiente
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Dependencia Gradle</a> al módulo de
tu aplicación:</p>
<pre>
dependencies {
...
compile 'com.android.support:palette-v7:21.0.0'
}
</pre>
<p>Para más información, consulta la referencia de la API para la clase {@link android.support.v7.graphics.Palette}.
</p>
<h2 id="VectorDrawables">Crear interfaces dibujables en vector</h2>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=wlFVIIstKmA" style="margin-top:18px">
<div>
<h3>Video</h3>
<p>Gráficos en vector de Android</p>
</div>
</a>
<p>En Android 5.0 (API nivel 21) y superiores, puedes definir las interfaces dibujables en vector, que escalan sin
perder definición. Solo necesitas un archivo de recurso para una imagen en vector, en oposición a un archivo de recurso para
la densidad de cada pantalla en el caso de imágenes de mapa de bits. Para crear una imagen en vector, defines los detalles
de la forma dentro de un elemento XML <code>&lt;vector&gt;</code>.</p>
<p>El siguiente ejemplo define una imagen en vector con la forma de un corazón:</p>
<pre>
&lt;!-- res/drawable/heart.xml -->
&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
&lt;!-- intrinsic size of the drawable -->
android:height="256dp"
android:width="256dp"
&lt;!-- size of the virtual canvas -->
android:viewportWidth="32"
android:viewportHeight="32">
&lt;!-- draw a path -->
&lt;path android:fillColor="#8fff"
android:pathData="M20.5,9.5
c-1.955,0,-3.83,1.268,-4.5,3
c-0.67,-1.732,-2.547,-3,-4.5,-3
C8.957,9.5,7,11.432,7,14
c0,3.53,3.793,6.257,9,11.5
c5.207,-5.242,9,-7.97,9,-11.5
C25,11.432,23.043,9.5,20.5,9.5z" />
&lt;/vector>
</pre>
<p>Las imágenes en vector están representadas en Android como objetos {@link android.graphics.drawable.VectorDrawable}.
Para más información sobre la sintaxis <code>pathData</code>, consulta la <a href="http://www.w3.org/TR/SVG11/paths.html#PathData">referencia de ruta de acceso SVG</a>. Para más información
sobre la animación de las propiedades de las interfaces dibujables en vector, consulta
<a href="{@docRoot}training/material/animations.html#AnimVector">Animación de interfaces dibujables en vector</a>.</p>

View File

@@ -0,0 +1,171 @@
page.title=Comencemos
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#ApplyTheme">Aplicar el tema Material</a></li>
<li><a href="#Layouts">Realizar tus diseños</a></li>
<li><a href="#Depth">Especificar la elevación en tus vistas</a></li>
<li><a href="#ListsCards">Crear listas y tarjetas</a></li>
<li><a href="#Animations">Personalizar tus animaciones</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Para crear aplicaciones con Material Design:</p>
<ol>
<li style="margin-bottom:10px">
Revisar la <a href="http://www.google.com/design/spec">especificación de Material Design</a>.</li>
<li style="margin-bottom:10px">
Aplicar el <strong>tema</strong> material a tu aplicación.</li>
<li style="margin-bottom:10px">
Crear tus <strong>diseños</strong> siguiendo las pautas de Material Design.</li>
<li style="margin-bottom:10px">
Especificar la <strong>elevación</strong> de tus vistas para convertir sombras.</li>
<li style="margin-bottom:10px">
Usar <strong>widgets</strong> del sistema para listas y tarjetas.</li>
<li style="margin-bottom:10px">
Personalizar las <strong>animaciones</strong> en tu aplicación.</li>
</ol>
<h3>Mantener la compatibilidad con versiones anteriores</h3>
<p>Puedes agregar muchas características de Material Design a tu aplicación mientras mantienes la compatibilidad con las
versiones anteriores a Android 5.0. Para más información, consulta
<a href="{@docRoot}training/material/compatibility.html">Mantener la compatibilidad</a>.</p>
<h3>Actualización de tu aplicación con Material Design</h3>
<p>Para actualizar una aplicación existente para incorporar Material Design, actualiza tus diseños siguiendo
las pautas de Material Design. Además, asegúrate de incorporar profundidad, respuesta táctil y
animaciones.</p>
<h3>Crear nuevas aplicaciones con Material Design</h3>
<p>Si creas una nueva aplicación con las características de Material Design, las <a href="http://www.google.com/design/spec">pautas de Material Design</a> te proporcionan un framework
de diseño cohesivo. Sigue estas pautas y usa la nueva funcionalidad del framework de
Android para diseñar y desarrollar tu aplicación.</p>
<h2 id="ApplyTheme">Aplicar el tema Material</h2>
<p>Para aplicar el tema material en tu aplicación, especifica el estilo que hereda de
<code>android:Theme.Material</code>:</p>
<pre>
&lt;!-- res/values/styles.xml -->
&lt;resources>
&lt;!-- your theme inherits from the material theme -->
&lt;style name="AppTheme" parent="android:Theme.Material">
&lt;!-- theme customizations -->
&lt;/style>
&lt;/resources>
</pre>
<p>El tema material proporciona widgets de sistema actualizados y te permite establecer la paleta de colores y las animaciones
predeterminadas para la respuesta táctil y las transiciones de actividades. Para obtener más detalles, consulta
<a href="{@docRoot}training/material/theme.html">Usar el tema Material</a>.</p>
<h2 id="Layouts">Realizar tus diseños</h2>
<p>Además de aplicar y personalizar el tema material, tus diseños deben cumplir con
las <a href="http://www.google.com/design/spec">pautas de Material Design</a>. Cuando realices
tus diseños, presta especial atención a lo siguiente:</p>
<ul>
<li>Cuadrículas de referencia</li>
<li>Líneas clave</li>
<li>Espaciado</li>
<li>Tamaño del objetivo táctil</li>
<li>Estructura del diseño</li>
</ul>
<h2 id="Depth">Especificar la elevación en tus vistas</h2>
<p>Las vistas pueden proyectar sombras y el valor de elevación de una vista
determina el tamaño de su sombra y el orden en que será dibujada. Para establecer la elevación de una vista, usa el atributo
<code>android:elevation</code> en tus diseños:</p>
<pre>
&lt;TextView
android:id="&#64;+id/my_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/next"
android:background="&#64;color/white"
android:elevation="5dp" />
</pre>
<p>La nueva propiedad <code>translationZ</code> te permite crear animaciones que reflejen cambios
temporales en la elevación de una vista. Los cambios de elevación pueden ser útiles cuando
<a href="{@docRoot}training/material/animations.html#ViewState">responden a gestos
táctiles</a>.</p>
<p>Para obtener más detalles, consulta <a href="{@docRoot}training/material/shadows-clipping.html">Definir
vistas de recorte y sombras</a>.</p>
<h2 id="ListsCards">Crear listas y tarjetas</h2>
<p>{@link android.support.v7.widget.RecyclerView} es una versión más acoplable de {@link
android.widget.ListView} que admite diferentes tipos de diseños y proporciona mejoras en el rendimiento.
{@link android.support.v7.widget.CardView} te permite mostrar partes de información dentro de las tarjetas con
una apariencia uniforme entre distintas aplicaciones. El siguiente ejemplo de códigos muestra cómo incluir un
{@link android.support.v7.widget.CardView} en tu diseño:</p>
<pre>
&lt;android.support.v7.widget.CardView
android:id="&#64;+id/card_view"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardCornerRadius="3dp">
...
&lt;/android.support.v7.widget.CardView>
</pre>
<p>Para obtener más información, consulta <a href="{@docRoot}training/material/lists-cards.html">Crear listas
y tarjetas</a>.</p>
<h2 id="Animations">Personalizar tus animaciones</h2>
<p>Android 5.0 (API nivel 21) incluye nuevas API para crear animaciones personalizadas en tu aplicación.
Por ejemplo, puedes habilitar las transiciones de actividades y definir una transición de salida dentro de una
actividad:</p>
<pre>
public class MyActivity extends Activity {
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// enable transitions
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
setContentView(R.layout.activity_my);
}
public void onSomeButtonClicked(View view) {
getWindow().setExitTransition(new Explode());
Intent intent = new Intent(this, MyOtherActivity.class);
startActivity(intent,
ActivityOptions
.makeSceneTransitionAnimation(this).toBundle());
}
}
</pre>
<p>Cuando comienzas otra actividad desde esta actividad, se activa la transición de salida.</p>
<p>Para más información sobre las nuevas API de animación, consulta <a href="{@docRoot}training/material/animations.html">Definir animaciones personalizadas</a>.</p>

View File

@@ -0,0 +1,60 @@
page.title=Material Design para desarrolladores
page.image=images/cards/material_2x.png
page.metaDescription=Aprende a aplicar Material Design a tus aplicaciones.
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dependencias y requisitos previos</h2>
<ul>
<li>Android 5.0 (API nivel 21)</li>
</ul>
</div>
</div>
<p>Material Design es una guía integral para el diseño visual, de movimientos y de interacción en distintas
plataformas y dispositivos. Para usar Material Design en tus aplicaciones de Android, sigue las pautas
descritas en la
<a href="http://www.google.com/design/spec/material-design/introduction.html">especificación de Material
Design</a> y usa los nuevos componentes y funcionalidades disponibles en Android 5.0
(API nivel 21).</p>
<p>Esta clase muestra cómo crear aplicaciones de Material Design con los siguientes elementos:</p>
<ul>
<li>Tema Material</li>
<li>Widget para tarjetas y listas</li>
<li>Personalizar sombras y ver recortes</li>
<li>Interfaces dibujables en vector</li>
<li>Animaciones personalizadas</li>
</ul>
<p>Esta clase también te enseña cómo mantener la compatibilidad con versiones anteriores de Android
5.0 (API nivel 21) cuando usas las características de Material Design en tu aplicación.</p>
<h2>Lecciones</h2>
<dl>
<dt><a href="{@docRoot}training/material/get-started.html">Comencemos</a></dt>
<dd>Aprende a actualizar tu aplicación con las características de Material Design.</dd>
<dt><a href="{@docRoot}training/material/theme.html">Usar el tema Material</a></dt>
<dd>Aprende a aplicar los estilos de Material Design a tu aplicación.</dd>
<dt><a href="{@docRoot}training/material/lists-cards.html">Crear listas y tarjetas</a></dt>
<dd>Aprende a crear listas y tarjetas con un aspecto consistente mediante el uso de widgets del sistema.</dd>
<dt><a href="{@docRoot}training/material/shadows-clipping.html">Definir vistas de recorte y sombras</a></dt>
<dd>Aprende a establecer la elevación para tus vistas para crear sombras personalizadas y cómo recortar vistas.</dd>
<dt><a href="{@docRoot}training/material/drawables.html">Trabajar con interfaces dibujables</a></dt>
<dd>Aprende cómo crear interfaces dibujables en vector y cómo agregar un matiz a los recursos dibujables.</dd>
<dt><a href="{@docRoot}training/material/animations.html">Definir animaciones personalizadas</a></dt>
<dd>Aprende a crear animaciones personalizadas para vistas y transiciones de actividades con elementos compartidos.</dd>
<dt><a href="{@docRoot}training/material/compatibility.html">Mantener la compatibilidad</a></dt>
<dd>Aprende a mantener la compatibilidad con versiones de plataforma anteriores a Android 5.0.</dd>
</dl>

View File

@@ -0,0 +1,266 @@
page.title=Crear listas y tarjetas
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#RecyclerView">Crear listas</a></li>
<li><a href="#CardView">Crear tarjetas</a></li>
<li><a href="#Dependencies">Agregar dependencias</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Para crear listas completas y tarjetas con estilos de Material Design en tus aplicaciones, puedes usar los widgets
{@link android.support.v7.widget.RecyclerView} y {@link android.support.v7.widget.CardView}.
</p>
<h2 id="RecyclerView">Crear listas</h2>
<p>El widget {@link android.support.v7.widget.RecyclerView} es una versión más
flexible y avanzada de {@link android.widget.ListView}. Este widget es un contenedor para mostrar grandes conjuntos de
datos que se pueden desplazar de manera muy eficiente al mantener una cantidad limitada de vistas. Usa el widget
{@link android.support.v7.widget.RecyclerView} cuando tengas conjuntos de datos cuyos elementos
cambien en tiempo de ejecución sobre la base de la acción del usuario o los eventos de la red.</p>
<p>La clase {@link android.support.v7.widget.RecyclerView} simplifica la pantalla y la manipulación de grandes conjuntos de
datos al proporcionar lo siguiente:</p>
<ul>
<li>Administradores de diseño para el posicionamiento de elementos</li>
<li>Animaciones predeterminadas para las operaciones comunes con elementos, como quitar o agregar elementos</li>
</ul>
<p>También tienes la flexibilidad para definir administradores de diseño personalizados y animaciones para los widgets {@link
android.support.v7.widget.RecyclerView}.</p>
<img src="{@docRoot}training/material/images/RecyclerView.png" alt="" width="550" height="106" />
<p class="img-caption">
<strong>Figura 1</strong>. El widget <code>RecyclerView</code>.
</p>
<p>Para usar el widget {@link android.support.v7.widget.RecyclerView}, tienes que especificar un
adaptador y un administrador de diseño. Para crear un adaptador, extiende la clase {@link
android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}. Los detalles
de la implementación dependen de las especificaciones de tu conjunto de datos y los tipos de vistas. Para más
información, consulta los <a href="#RVExamples">ejemplos</a> que figuran a continuación.</p>
<div style="float:right">
<img src="{@docRoot}design/material/images/list_mail.png" alt="" width="250" height="426" />
<p class="img-caption" style="margin-left:8px">
<strong>Figura 2</strong>. Listas con <code>RecyclerView</code>.
</p>
</div>
<p>Un <strong>administrador de diseño</strong> posiciona las vistas de artículos dentro de un {@link
android.support.v7.widget.RecyclerView} y determina cuándo volver a usar las vistas de elementos que ya
no están visibles para el usuario. Para reutilizar (o <em>reciclar</em>) una vista, un administrador de diseño puede solicitarle al
adaptador que reemplace el contenido de la vista con un elemento diferente del conjunto de datos. De esta manera,
cuando se reciclan las vistas se mejora el rendimiento al evitar la creación de vistas innecesarias o
realizar búsquedas costosas de {@link android.app.Activity#findViewById findViewById()}.</p>
<p>{@link android.support.v7.widget.RecyclerView} te proporciona estos administradores de diseño incorporados:</p>
<ul>
<li>{@link android.support.v7.widget.LinearLayoutManager} muestra elementos en una lista de desplazamiento horizontal o
vertical.</li>
<li>{@link android.support.v7.widget.GridLayoutManager} muestra elementos en una cuadrícula.</li>
<li>{@link android.support.v7.widget.StaggeredGridLayoutManager} muestra elementos en una cuadrícula escalonada.</li>
</ul>
<p>Para crear un administrador de diseño personalizado, extiende la clase {@link
android.support.v7.widget.RecyclerView.LayoutManager RecyclerView.LayoutManager}.</p>
<h3>Animaciones</h3>
<p>Las animaciones para agregar o eliminar elementos están permitidas en forma predeterminada en {@link
android.support.v7.widget.RecyclerView}. Para personalizar estas animaciones, extiende la clase
{@link android.support.v7.widget.RecyclerView.ItemAnimator RecyclerView.ItemAnimator} y usa
el método {@link android.support.v7.widget.RecyclerView#setItemAnimator RecyclerView.setItemAnimator()}.
</p>
<h3 id="RVExamples">Ejemplos</h3>
<p>El siguiente ejemplo de códigos demuestra cómo agregar el widget
{@link android.support.v7.widget.RecyclerView} a un diseño:</p>
<pre>
&lt;!-- A RecyclerView with some commonly used attributes -->
&lt;android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</pre>
<p>Una vez que hayas agregado un widget {@link android.support.v7.widget.RecyclerView} a tu diseño,
obtén un identificador para el objeto, conéctalo a un administrador de diseño y adjunta un adaptador para los datos
que se van a mostrar:</p>
<pre>
public class MyActivity extends Activity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
}
...
}
</pre>
<p>El adaptador proporciona acceso a los elementos en tu conjunto de datos, crea vistas para los elementos y
reemplaza el contenido de algunas de las vistas con estos elementos de datos nuevos cuando el elemento original ya no está
visible. El siguiente ejemplo de código muestra una implementación simple para un conjunto de datos que consta
de una matriz de cadenas mostradas mediante el uso de widgets {@link android.widget.TextView}:</p>
<pre>
public class MyAdapter extends RecyclerView.Adapter&lt;MyAdapter.ViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
&#64;Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters
...
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
&#64;Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
&#64;Override
public int getItemCount() {
return mDataset.length;
}
}
</pre>
<div style="float:right;margin-top:15px;margin-left:30px">
<img src="{@docRoot}design/material/images/card_travel.png" alt="" width="225" height="383">
<p class="img-caption" style="margin-left:12px">
<strong>Figura 3</strong>. Ejemplos de tarjetas.
</p>
</div>
<h2 id="CardView">Crear tarjetas</h2>
<p>{@link android.support.v7.widget.CardView} extiende la clase {@link android.widget.FrameLayout}
y te permite mostrar información dentro de tarjetas que tienen una apariencia uniforme en la plataforma. Los widgets {@link
android.support.v7.widget.CardView} pueden tener sombras y esquinas redondeadas.</p>
<p>Para crear una tarjeta con una sombra, usa el atributo <code>card_view:cardElevation</code>.
{@link android.support.v7.widget.CardView} usa elevación real y sombras dinámicas en Android 5.0
(API nivel 21) y superior, y regresa a una implementación de sombras programáticas en versiones anteriores.
Para más información, consulta <a href="{@docRoot}training/material/compatibility.html">Mantener
la compatibilidad</a>.</p>
<p>Usa estas propiedades para personalizar la apariencia del widget
{@link android.support.v7.widget.CardView}:</p>
<ul>
<li>Para establecer el radio de la esquina en tus diseños, usa el atributo <code>card_view:cardCornerRadius</code>.
</li>
<li>Para establecer el radio en tu código, usa el método <code>CardView.setRadius</code>.</li>
<li>Para establecer el color de fondo de una tarjeta, usa el atributo <code>card_view:cardBackgroundColor</code>.
</li>
</ul>
<p>El siguiente ejemplo de código muestra cómo incluir un widget {@link android.support.v7.widget.CardView}
en tu diseño:</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
... >
&lt;!-- A CardView that contains a TextView -->
&lt;android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardCornerRadius="4dp">
&lt;TextView
android:id="@+id/info_text"
android:layout_width="match_parent"
android:layout_height="match_parent" />
&lt;/android.support.v7.widget.CardView>
&lt;/LinearLayout>
</pre>
<p>Para más información, consulta la referencia de la API para {@link android.support.v7.widget.CardView}.</p>
<h2 id="Dependencies">Agregar dependencias</h2>
<p>Los widgets {@link android.support.v7.widget.RecyclerView} y {@link android.support.v7.widget.CardView}
son parte de las <a href="{@docRoot}tools/support-library/features.html#v7">Bibliotecas de
soporte v7</a>. Para usar estos widgets en tu proyecto, agrega estas
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Dependencias de Gradle</a> al módulo
de tu aplicación:</p>
<pre>
dependencies {
...
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>

View File

@@ -0,0 +1,133 @@
page.title=Definir vistas de recorte y sombras
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#Elevation">Asignar elevación a tus vistas</a></li>
<li><a href="#Shadows">Personalizar vistas de sombras y contornos</a></li>
<li><a href="#Clip">Recortar vistas</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>Material Design introduce una elevación para los elementos de la IU. La elevación ayuda a los usuarios a comprender la
importancia relativa de cada elemento y a centrar su atención en la tarea para realizar.</p>
<p>La elevación de una vista, representada por la propiedad Z, determina la apariencia visual de su
sombra: las vistas con valores Z superiores, proyectan sombras más grandes y suaves. Las vistas con valores Z superiores ocluyen
las vistas con valores Z inferiores. Sin embargo, el valor Z de una vista no afecta el tamaño de la vista.</p>
<p>El padre de la vista elevada se encarga de dibujar las sombras y así, sujetas al recorte de vista estándar, son
recortadas por el padre de manera predeterminada.</p>
<p>La elevación también es útil para crear animaciones donde los widgets suben temporalmente sobre el
plano visual cuando realizan alguna acción.</p>
<p>Para más información sobre la elevación en Material Design, consulta
<a href="http://www.google.com/design/spec/what-is-material/objects-in-3d-space.html">Objetos
en el espacio 3D</a>.</p>
<h2 id="Elevation">Asignar elevación a tus vistas</h2>
<p>El valor Z de una vista cualquiera tiene dos componentes:
<ul>
<li>Elevación: El componente estático.</li>
<li>Traducción: El componente dinámico usado para las animaciones.</li>
</ul>
<p><code>Z = elevation + translationZ</code></p>
<img src="{@docRoot}training/material/images/shadows-depth.png" width="580" height="261" alt="" />
<p class="img-caption"><strong>Figura 1</strong>: sombras para diferentes elevaciones de vistas.</p>
<p>Para establecer la elevación de una vista al definir un diseño, usa el atributo <code>android:elevation</code>.
Para establecer la elevación de una vista en el código de una actividad, usa el método
{@link android.view.View#setElevation View.setElevation()}.</p>
<p>Para establecer la traducción de una vista, usa el método {@link android.view.View#setTranslationZ
View.setTranslationZ()}.</p>
<p>Los nuevos métodos {@link android.view.ViewPropertyAnimator#z ViewPropertyAnimator.z()} y {@link
android.view.ViewPropertyAnimator#translationZ ViewPropertyAnimator.translationZ()} te permiten
animar fácilmente la elevación de las vistas. Para más información, consulta la referencia de la API para
{@link android.view.ViewPropertyAnimator} y la guía del desarrollador <a href="{@docRoot}guide/topics/graphics/prop-animation.html">Animación de propiedades</a>.
</p>
<p>También puedes usar un {@link android.animation.StateListAnimator} para
especificar estas animaciones de manera declarativa. Esto es especialmente útil para casos en donde los cambios de
estados desencadenan animaciones, como cuando un usuario pulsa un botón. Para más información, consulta
<a href="{@docRoot}training/material/animations.html#ViewState">Animar cambios de estados de las vistas</a>.</p>
<p>Los valores Z se miden en dp (píxeles independientes de la densidad).</p>
<h2 id="Shadows">Personalizar visualización de sombras y contornos</h2>
<p>Los límites de la interfaz dibujable en segundo plano de una vista determinan la forma predeterminada de su sombra.
Los <strong>contornos</strong> representan la forma externa de un objeto gráfico y definen el área del efecto de ondas
para la respuesta táctil.</p>
<p>Examina esta vista, definida con una interfaz dibujable en segundo plano:</p>
<pre>
&lt;TextView
android:id="@+id/myview"
...
android:elevation="2dp"
android:background="@drawable/myrect" />
</pre>
<p>La interfaz dibujable en segundo plano está definida como un rectángulo con esquinas redondeadas:</p>
<pre>
&lt;!-- res/drawable/myrect.xml -->
&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
&lt;solid android:color="#42000000" />
&lt;corners android:radius="5dp" />
&lt;/shape>
</pre>
<p>La vista proyecta una sombra con esquinas redondeadas, ya que la interfaz dibujable en segundo plano
define el contorno de la vista. Un contorno personalizado reemplazaría la forma predeterminada de la sombra de una vista.</p>
<p>Para definir un contorno personalizado para una vista en tu código:<p>
<ol>
<li>Extiende la clase {@link android.view.ViewOutlineProvider}.</li>
<li>Reemplaza el método {@link android.view.ViewOutlineProvider#getOutline getOutline()}.</li>
<li>Asigna el nuevo proveedor de contornos a tu vista con el método {@link
android.view.View#setOutlineProvider View.setOutlineProvider()}.</li>
</ol>
<p>Puedes crear contornos rectangulares y ovalados con esquinas redondeadas mediante el uso de métodos en la clase
{@link android.graphics.Outline}. El proveedor de contornos predeterminado para las
vistas obtiene el contorno a partir del plano de fondo de la vista. Para evitar que una vista proyecte una sombra, establece su proveedor de contornos
en <code>null</code>.</p>
<h2 id="Clip">Recortar vistas</h2>
<p>Recortar vistas te permite cambiar fácilmente la forma de una vista. Puedes recortar vistas para
mantener la uniformidad con otros elementos del diseño o para cambiar la forma de una vista en respuesta a una señal de entrada del usuario.
Puedes recortar una vista a partir de su área de contorno mediante el método {@link android.view.View#setClipToOutline
View.setClipToOutline()} o el atributo <code>android:clipToOutline</code>. Solo
los contornos rectangulares, circulares y redondeados admiten el recorte, según lo determinado por el método
{@link android.graphics.Outline#canClip Outline.canClip()}.</p>
<p>Para recortar una vista a partir de una interfaz dibujable, establece la interfaz dibujable como el plano de fondo de la vista
(como se muestra más arriba) y llama al método {@link android.view.View#setClipToOutline View.setClipToOutline()}.
</p>
<p>Recortar vistas es una operación costosa, así que no animes la forma que usas para
recortar una vista. Para lograr este efecto, usa la animación <a href="{@docRoot}training/material/animations.html#Reveal">Efecto revelar</a>.</p>

View File

@@ -0,0 +1,131 @@
page.title=Usar el tema Material
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Esta lección te enseña a realizar lo siguiente:</h2>
<ol>
<li><a href="#ColorPalette">Personalizar la paleta de colores</a></li>
<li><a href="#StatusBar">Personalizar la barra de estado</a></li>
<li><a href="#Inheritance">Cambiar el tema de vistas individuales</a></li>
</ol>
<h2>También deberías leer</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Especificación de Material Design</a></li>
<li><a href="{@docRoot}design/material/index.html">Material Design en Android</a></li>
</ul>
</div>
</div>
<p>El nuevo tema material proporciona:</p>
<ul>
<li>Widgets del sistema que te permiten establecer la paleta de colores.</li>
<li>Animaciones para la respuesta táctil de los widgets del sistema.</li>
<li>Animaciones para transiciones de actividades</li>
</ul>
<p>Puedes personalizar la apariencia del tema material
según la identidad de tu marca, con una paleta de colores que esté bajo tu control. Puedes cambiar el matiz de la barra de acción y
la barra de estado mediante atributos de temas, como se muestra en la <a href="#fig3">figura 3</a>.</p>
<p>Los widgets del sistema tienen un nuevo diseño y animaciones para respuesta táctil. Puedes personalizar tu aplicación cambiando su
paleta de colores, las animaciones de la respuesta táctil y sus transiciones de actividades.</p>
<p>El tema material se define como:</p>
<ul>
<li><code>@android:style/Theme.Material</code> (versión oscura)</li>
<li><code>@android:style/Theme.Material.Light</code> (versión clara)</li>
<li><code>@android:style/Theme.Material.Light.DarkActionBar</code></li>
</ul>
<p>Para obtener una lista de estilos de Material, consulta la referencia de la API para
{@link android.R.style R.style}.</p>
<!-- two columns, dark/light material theme example -->
<div style="width:700px;margin-top:25px;margin-bottom:10px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238">
<div style="width:170px;margin:0 auto">
<p style="margin-top:8px;font-size:12px"><strong>Figura 1</strong>. Tema Material oscuro</p>
</div>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238">
<div style="width:170px;margin:0 auto">
<p style="margin-top:8px;font-size:12px"><strong>Figura 2</strong>. Tema Material claro</p>
</div>
</div>
<br style="clear:left">
</div>
<p class="note">
<strong>Nota:</strong> El tema material solo está disponible en Android 5.0 (API nivel 21) y
superior. Las <a href="{@docRoot}tools/support-library/features.html#v7">Bibliotecas de soporte v7</a>
proporcionan temas con estilos de Material Design para algunos widgets y admiten la personalización de la paleta de
colores. Para más información, consulta
<a href="{@docRoot}training/material/compatibility.html">Mantener la compatibilidad</a>.
</p>
<h2 id="ColorPalette">Personalizar la paleta de colores</h2>
<p style="margin-bottom:30px">Si deseas personalizar los colores base del tema para que se adapten a tu marca, define
tus colores personalizados mediante los atributos de temas cuando heredes del tema material:</p>
<pre>
&lt;resources>
&lt;!-- inherit from the material theme -->
&lt;style name="AppTheme" parent="android:Theme.Material">
&lt;!-- Main theme colors -->
&lt;!-- your app branding color for the app bar -->
&lt;item name="android:colorPrimary">@color/primary&lt;/item>
&lt;!-- darker variant for the status bar and contextual app bars -->
&lt;item name="android:colorPrimaryDark">@color/primary_dark&lt;/item>
&lt;!-- theme UI controls like checkboxes and text fields -->
&lt;item name="android:colorAccent">@color/accent&lt;/item>
&lt;/style>
&lt;/resources>
</pre>
<div style="float:right;margin-left:25px;margin-top:20px;margin-bottom:10px" id="fig3">
<img src="{@docRoot}training/material/images/ThemeColors.png" width="250" height="445" />
<p class="img-caption" style="margin-bottom:0px">
<strong>Figura 3</strong>. Personalizar el tema material.</p>
</div>
<h2 id="StatusBar">Personalizar la barra de estado</h2>
<p>El tema material te permite personalizar fácilmente la barra de estado, especifica un
color que se adapte a tu marca y proporciona suficiente contraste para mostrar los íconos de estado en blanco. Si
quieres establecer un color personalizado para la barra de estado, usa el atributo <code>android:statusBarColor</code>
cuando extiendas el tema material. <code>android:statusBarColor</code> hereda el
valor de <code>android:colorPrimaryDark</code> en forma predeterminada.</p>
<p>También puedes dibujar por detrás de la barra de estado. Por ejemplo, si quieres que la barra de estado se
muestre en forma transparente sobre una foto, aplica un sutil degradado oscuro para garantizar que los íconos
de estado blancos sigan visibles. Para hacerlo, establece el atributo <code>android:statusBarColor</code> en
<code>&#64;android:color/transparent</code> y ajusta los indicadores de la ventana según lo requerido. También puedes
usar el método {@link android.view.Window#setStatusBarColor Window.setStatusBarColor()} para
las animaciones o el difuminado.</p>
<p class="note">
<strong>Nota:</strong> La barra de estado casi siempre debe estar delimitada claramente de la
barra de herramientas principal, excepto para los casos en donde muestres imágenes de un extremo a otro o contenido multimedia detrás
de estas barras, y también cuando uses un degradado para garantizar que los íconos aún sean visibles.
</p>
<p>Cuando personalizas la barra de navegación y la barra de estado, haz que ambas sean transparentes o modifica
solo la barra de estado. La barra de navegación debe permanecer de color negro en todos los otros casos.</p>
<h2 id="Inheritance">Vistas individuales del tema</h3>
<p>Los elementos en las definiciones de diseño XML pueden especificar el atributo <code>android:theme</code>,
que hace referencia al recurso del tema. Este atributo modifica el tema para el elemento y cualquier
elemento secundario, y esto es útil para modificar las paletas de colores de los temas en una porción específica
de una interfaz.</p>

View File

@@ -0,0 +1,307 @@
page.title=Prinsip Desain Android
@jd:body
<p>Prinsip desain ini dikembangkan oleh dan untuk Tim Pengalaman Pengguna
Android agar selalu mempertimbangkan kepentingan pengguna.
Untuk pengembang dan desainer Android, mereka terus
meletakkan dasar pedoman desain yang lebih detail untuk beragam tipe
perangkat.</p>
<p>
Perhatikan prinsip-prinsip ini saat Anda menerapkan
kreativitas dan pemikiran desain sendiri. Menyimpang dengan sengaja.
</p>
<h2 id="enchant-me">Pikat Saya</h2>
<div class="cols">
<div class="col-7">
<h4 id="delight-me">Senangkan saya dengan cara yang mengejutkan</h4>
<p>Permukaan yang cantik, animasi yang ditempatkan dengan hati-hati, atau efek suara di saat yang tepat sungguh menyenangkan untuk
dinikmati. Efek yang lembut menimbulkan perasaan serba mudah dan kesadaran bahwa kekuatan yang
bisa diandalkan ada dalam genggaman.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_delight.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="real-objects-more-fun">Objek sungguhan lebih menyenangkan daripada tombol dan menu</h4>
<p>Biarkan orang langsung menyentuh dan memanipulasi objek dalam aplikasi Anda. Ini mengurangi upaya kognitif
yang diperlukan untuk menjalankan tugas sekaligus membuatnya lebih memuaskan secara emosional.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_real_objects.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="make-it-mine">Biarkan saya memilikinya</h4>
<p>Orang suka menambahkan sentuhan pribadi karena membantu mereka merasa betah dan memegang kendali. Memberikan
default yang pantas dan indah, tetapi juga mempertimbangkan penyesuaian opsional yang menyenangkan, yang tidak mengganggu
tugas utama.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_it_mine.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="get-to-know-me">Kenali saya</h4>
<p>Pelajari preferensi orang dari waktu ke waktu. Daripada meminta mereka untuk membuat pilihan yang sama
berulang-ulang, tempatkan pilihan sebelumnya agar mudah dijangkau.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_get_to_know_me.png">
</div>
</div>
<h2 id="simplify-my-life">Sederhanakan Hidup Saya</h2>
<div class="cols">
<div class="col-7">
<h4 id="keep-it-brief">Persingkat</h4>
<p>Gunakan frasa pendek dengan kata-kata sederhana. Orang cenderung melewatkan kalimat-kalimat panjang.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_keep_it_brief.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="pictures-faster-than-words">Gambar lebih cepat dibanding kata-kata</h4>
<p>Pertimbangkan menggunakan gambar untuk menjelaskan gagasan. Gambar menarik perhatian orang dan bisa jauh lebih efisien
dibanding kata-kata.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_pictures.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="decide-for-me">Putuskan untuk saya tetapi biarkan saya yang menentukan</h4>
<p>Gunakan tebakan terbaik Anda dan bertindaklah daripada meminta terlebih dahulu. Terlalu banyak pilihan dan keputusan membuat orang
tidak suka. Untuk berjaga-jaga jika Anda salah, izinkan 'pembatalan'.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_decide_for_me.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="only-show-when-i-need-it">Cukup tunjukkan yang saya perlukan ketika saya memerlukannya</h4>
<p>Orang merasa kewalahan ketika melihat terlalu banyak hal sekaligus. Uraikan tugas dan informasi menjadi potongan-potongan
kecil yang mudah dicerna. Sembunyikan opsi yang tidak perlu pada saat ini, dan ajari orang sambil jalan.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_information_when_need_it.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="always-know-where-i-am">Saya harus selalu tahu di mana saya berada</h4>
<p>Beri orang kepercayaan diri bahwa mereka tahu di mana berada. Buat agar tempat-tempat dalam aplikasi Anda terlihat berbeda dan
gunakan transisi untuk menunjukkan hubungan antar layar. Berikan umpan balik tentang tugas yang sedang berlangsung.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_navigation.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="never-lose-my-stuff">Jangan sekali-kali menghilangkan milik saya</h4>
<p>Simpan apa yang telah susah-payah dibuat orang dan biarkan mereka mengaksesnya dari mana saja. Ingat pengaturan,
sentuhan pribadi, dan kreasi lintas ponsel, tablet, dan komputer. Itu membuat pemutakhiran menjadi
hal termudah di dunia.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_never_lose_stuff.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="looks-same-should-act-same">Jika terlihat sama, seharusnya fungsinya sama</h4>
<p>Bantu orang merasakan perbedaan fungsional dengan membuat mereka terlihat berbeda daripada mirip.
Hindari mode, yaitu tempat yang terlihat mirip tetapi berbeda fungsinya pada input yang sama.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_looks_same.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="interrupt-only-if-important">Sela saya jika penting saja</h4>
<p>Layaknya asisten pribadi yang baik, lindungi orang dari detail yang tidak penting. Orang ingin tetap
fokus, dan kecuali jika memang penting dan sensitif waktu, interupsi bisa melelahkan dan menjengkelkan.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_important_interruption.png">
</div>
</div>
<h2 id="make-me-amazing">Buat Saya Terpesona</h2>
<div class="cols">
<div class="col-7">
<h4 id="give-me-tricks">Beri saya trik yang efektif di mana saja</h4>
<p>Orang merasa senang ketika mereka memahami sendiri sesuatu. Jadikan aplikasi Anda lebih mudah dipelajari dengan
memanfaatkan pola visual dan memori otot dari aplikasi Android lainnya. Misalnya, gerakan menggeser
dapat menjadi pintasan navigasi yang bagus.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_tricks.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="its-not-my-fault">Bukan salah saya</h4>
<p>Bersikap ramahlah dalam meminta orang untuk melakukan koreksi. Mereka ingin merasa pintar ketika menggunakan
aplikasi Anda. Jika terjadi kesalahan, berikan petunjuk perbaikan yang jelas tetapi lepaskan mereka dari detail teknis.
Jika Anda dapat memperbaikinya secara diam-diam, tentu lebih baik.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_error.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="sprinkle-encouragement">Berikan dorongan</h4>
<p>Uraikan tugas-tugas rumit menjadi langkah-langkah kecil yang dapat dilakukan dengan mudah. Beri umpan balik tentang tindakan,
meskipun hanya sesuatu yang sederhana.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="do-heavy-lifting-for-me">Lakukan pekerjaan yang sulit untuk saya</h4>
<p>Buatlah pemula merasa seperti ahli dengan memungkinkan mereka untuk melakukan hal-hal yang mereka pikir tidak akan bisa.
Misalnya, pintasan yang menggabungkan beberapa efek foto dapat membuat foto amatir terlihat mengagumkan hanya
dalam beberapa langkah.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_heavy_lifting.png">
</div>
</div>
<div class="vspace size-2">&nbsp;</div>
<div class="cols">
<div class="col-7">
<h4 id="make-important-things-fast">Percepat hal penting</h4>
<p>Tidak semua tindakan itu sama. Putuskan apa yang terpenting dalam aplikasi Anda dan permudah untuk menemukannya serta
cepat untuk digunakan, seperti tombol rana pada kamera, atau tombol jeda pada pemutar musik.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_important_fast.png">
</div>
</div>

View File

@@ -0,0 +1,186 @@
page.title=Material Design for Android
page.tags=Material,design
page.type=design
page.image=images/cards/design-material-for-android_2x.jpg
@jd:body
<!-- developer docs box -->
<a class="notice-developers right" href="{@docRoot}training/material/index.html">
<div>
<h3>Dokumen Pengembang</h3>
<p>Membuat Aplikasi dengan Desain Bahan</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=p4gmvHyuZzw">
<div>
<h3>Video</h3>
<p>Pengantar Desain Bahan</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=YaG_ljfzeUw">
<div>
<h3>Video</h3>
<p>Kertas dan Tinta: Bahan Penting</p>
</div>
</a>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=XOcCOBe8PTc">
<div>
<h3>Video</h3>
<p>Desain Bahan di Aplikasi Google I/O</p>
</div>
</a>
<p itemprop="description">Desain bahan adalah panduan komprehensif untuk desain visual, gerak, dan
interaksi lintas platform dan perangkat. Android kini menyertakan dukungan untuk
aplikasi desain bahan. Untuk menggunakan desain bahan di aplikasi Android, ikuti panduan yang didefinisikan
dalam <a href="http://www.google.com/design/spec">spesifikasi desain bahan</a> dan gunakan
komponen dan fungsionalitas baru yang tersedia di Android 5.0 (API level 21) ke atas.</p>
<p>Android menyediakan elemen berikut untuk membangun aplikasi desain bahan:</p>
<ul>
<li>Tema baru</li>
<li>Widget baru untuk tampilan yang kompleks</li>
<li>API baru untuk animasi dan bayangan custom</li>
</ul>
<p>Untuk informasi selengkapnya tentang mengimplementasikan desain bahan pada Android, lihat
<a href="{@docRoot}training/material/index.html">Membuat Aplikasi dengan Desain Bahan</a>.</p>
<h3>Tema Bahan</h3>
<p>Tema bahan menyediakan gaya baru untuk aplikasi Anda, widget sistem yang memungkinkan Anda mengatur
palet warnanya, dan animasi default untuk umpan balik sentuh dan transisi aktivitas.</p>
<!-- two columns -->
<div style="width:700px;margin-top:25px;margin-bottom:20px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">Tema bahan gelap</p>
</div>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">Tema bahan terang</p>
</div>
</div>
<br style="clear:left"/>
</div>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/theme.html">Menggunakan Tema
Bahan</a>.</p>
<h3>Daftar dan Kartu</h3>
<p>Android menyediakan dua widget baru untuk menampilkan kartu dan daftar dengan gaya desain bahan
dan animasi:</p>
<!-- two columns -->
<div style="width:700px;margin-top:25px;margin-bottom:20px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/list_mail.png" width="500" height="426" />
<p>Widget <code>RecyclerView</code> baru adalah versi <code>ListView</code>
yang lebih mudah dimasukkan dan mendukung beragam tipe layout serta memberikan peningkatan kinerja.</p>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/card_travel.png" width="500" height="426" />
<p>Widget <code>CardView</code> baru memungkinkan Anda menampilkan potongan informasi penting dalam
kartu yang memiliki tampilan dan cara kerja yang konsisten.</p>
</div>
<br style="clear:left"/>
</div>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar
dan Kartu</a>.</p>
<h3>Bayangan Tampilan</h3>
<p>Selain properti X dan Y, tampilan di Android kini memiliki
properti Z. Properti baru ini mewakili ketinggian tampilan, yang menentukan:</p>
<ul>
<li>Ukuran bayangan: tampilan dengan nilai Z lebih tinggi menghasilkan bayangan lebih besar.</li>
<li>Urutan penggambaran: tampilan dengan nilai Z lebih tinggi muncul di atas tampilan lainnya.</li>
</ul>
<div style="width:290px;margin-left:35px;float:right">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay>
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4"/>
<source src="{@docRoot}design/videos/ContactsAnim.webm"/>
<source src="{@docRoot}design/videos/ContactsAnim.ogv"/>
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<em>Untuk memutar ulang film, klik layar perangkat</em>
</div>
</div>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan
Bayangan dan Memangkas Tampilan</a>.</p>
<h3>Animasi</h3>
<p>API animasi baru memungkinkan Anda membuat animasi custom untuk umpan balik sentuh dalam kontrol UI,
perubahan status tampilan, dan transisi aktivitas.</p>
<p>API ini memungkinkan Anda:</p>
<ul>
<li style="margin-bottom:15px">
Merespons kejadian sentuh dalam tampilan Anda dengan animasi <strong>umpan balik sentuh</strong>.
</li>
<li style="margin-bottom:15px">
Menyembunyikan dan memperlihatkan tampilan dengan animasi <strong>membuka melingkar</strong>.
</li>
<li style="margin-bottom:15px">
Peralihan antar aktivitas dengan animasi <strong>transisi aktivitas</strong> custom.
</li>
<li style="margin-bottom:15px">
Membuat animasi yang lebih alami dengan <strong>gerak melengkung</strong>.
</li>
<li style="margin-bottom:15px">
Menganimasikan perubahan dalam satu atau beberapa properti tampilan dengan animasi <strong>perubahan status tampilan</strong>.
</li>
<li style="margin-bottom:15px">
Menampilkan animasi di <strong>drawable daftar status</strong> di antara perubahan status tampilan.
</li>
</ul>
<p>Animasi umpan balik sentuh dimasukkan ke dalam beberapa tampilan standar, misalnya tombol. API baru
ini memungkinkan Anda menyesuaikan animasi ini dan menambahkannya ke tampilan custom Anda.</p>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi
Custom</a>.</p>
<h3>Drawable</h3>
<p>Kemampuan baru untuk drawable ini membantu Anda mengimplementasikan aplikasi desain bahan:</p>
<ul>
<li><strong>Drawable vektor</strong> bisa diubah skalanya tanpa kehilangan definisi dan cocok
untuk ikon satu-warna dalam-aplikasi.</li>
<li><strong>Pewarnaan drawable</strong> memungkinkan Anda mendefinisikan bitmap sebagai alpha-mask dan mewarnainya
saat runtime.</li>
<li><strong>Ekstraksi warna</strong> memungkinkan Anda mengekstrak warna mencolok secara otomatis dari
gambar bitmap.</li>
</ul>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/drawables.html">Bekerja dengan
Drawable</a>.</p>

View File

@@ -0,0 +1,70 @@
page.title=Kompatibilitas Mundur
page.tags="support"
page.metaDescription=Catatan tentang bagaimana Android 4.x menyesuaikan UI yang didesain untuk perangkat keras dan versi OS yang lebih lama.
@jd:body
<a class="notice-developers" href="{@docRoot}training/basics/supporting-devices/index.html">
<div>
<h3>Dokumen Pengembang</h3>
<p>Mendukung Perangkat Berbeda</p>
</div>
</a>
<p>Perubahan signifikan dalam Android 3.0 meliputi:</p>
<ul>
<li>Dihilangkannya tombol perangkat keras navigasi (Back, Menu, Search, Home) untuk membantu menangani navigasi
melalui kontrol maya (Back, Home, Recents).</li>
<li>Pola yang tangguh untuk penggunaan menu pada action-bar.</li>
</ul>
<p>Android 4.0 membawa perubahan ini untuk tablet dengan platform ponsel.</p>
<h2 id="older-hardware">Menyesuaikan Android 4.0 dengan Perangkat Keras dan Aplikasi yang Lebih Lama</h2>
<div class="cols">
<div class="col-6">
<h4>Ponsel dengan kontrol navigasi virtual</h4>
<p>Aplikasi Android yang ditulis untuk Android 3.0 dan yang lebih baru menampilkan tindakan dalam action-bar. Tindakan yang tidak
muat dalam action-bar atau tidak cukup penting untuk ditampilkan di tingkat atas akan muncul dalam
action-overflow.</p>
<p>Pengguna mengakses action-overflow dengan menyentuhnya dalam action-bar.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_virtual_nav.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Ponsel dengan tombol navigasi fisik</h4>
<p>Ponsel Android dengan tombol perangkat keras navigasi biasa tidak menampilkan baris navigasi virtual di
bagian bawah layar. Sebagai gantinya, action-overflow tersedia dari tombol perangkat keras menu. Popup
tindakan yang dihasilkan memiliki gaya yang sama dengan contoh sebelumnya, tetapi ditampilkan di bagian bawah layar.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_physical_buttons.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>Aplikasi lama pada ponsel dengan kontrol navigasi virtual</h4>
<p>Bila Anda menjalankan aplikasi yang dibuat untuk Android 2.3 atau yang lebih lama pada ponsel
dengan kontrol navigasi virtual, sebuah kontrol action-overflow akan muncul di sebelah kanan baris navigasi virtual. Anda
dapat menyentuh kontrol itu untuk menampilkan tindakan aplikasi dalam gaya menu Android biasa.</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_legacy_apps.png">
</div>
</div>

View File

@@ -0,0 +1,70 @@
page.title=Mengonfirmasi &amp; Mengakui
page.tags=dialog,toast,notification
@jd:body
<p>Dalam beberapa situasi, bila pengguna memanggil suatu tindakan dalam aplikasi Anda, ada baiknya <em>mengonfirmasi</em> atau <em>mengakui</em> tindakan itu melalui teks.</p>
<div class="cols">
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_confirming.png">
<p><strong>Mengonfirmasi</strong> adalah meminta pengguna untuk memverifikasi bahwa mereka benar-benar ingin melanjutkan tindakan yang baru saja mereka panggil. Dalam beberapa kasus, konfirmasi ditampilkan bersama-sama dengan peringatan atau informasi penting yang terkait dengan tindakan yang perlu mereka pertimbangkan.</p>
</div>
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
<p><strong>Mengakui</strong> adalah menampilkan teks untuk memberi tahu pengguna bahwa tindakan yang baru mereka panggil sudah dilakukan. Ini menghilangkan ketidakpastian tentang operasi implisit yang dilakukan sistem. Dalam beberapa kasus, pengakuan ditampilkan bersama dengan opsi untuk membatalkan tindakan.</p>
</div>
</div>
<p>Berkomunikasi pada pengguna dengan cara ini bisa membantu mengurangi ketidakpastian tentang hal-hal yang sudah atau akan terjadi. Mengonfirmasi atau mengakui juga dapat mencegah pengguna melakukan kesalahan yang akan mereka sesali.</p>
<h2>Kapan Harus Mengonfirmasi atau Mengakui Tindakan Pengguna</h2>
<p>Tidak semua tindakan memerlukan konfirmasi atau pengakuan. Gunakan bagan alur ini untuk memandu keputusan desain Anda.</p>
<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
<h2>Mengonfirmasi</h2>
<div class="cols">
<div class="col-6">
<h4>Contoh: Google Play Books</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_books.png">
<p>Dalam contoh ini, pengguna telah meminta untuk menghapus sebuah buku dari perpustakaan Google Play mereka. Sebuah <a href="{@docRoot}design/building-blocks/dialogs.html#alerts">peringatan</a> muncul untuk mengonfirmasi tindakan ini karena perlu dipahami bahwa buku tersebut tidak akan tersedia lagi dari perangkat apa pun.</p>
<p>Saat membuat dialog konfirmasi, buat judul bermakna dengan mencerminkan tindakan yang diminta.</p>
</div>
<div class="col-7">
<h4>Contoh: Android Beam</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
<p>Konfirmasi tidak harus ditampilkan dalam peringatan dengan dua tombol. Setelah menjalankan Android Beam, pengguna diminta untuk menyentuh konten yang akan dibagikan (dalam contoh ini, sebuah foto). Jika mereka memutuskan untuk tidak melanjutkan, mereka tinggal memindahkan ponsel.</p>
</div>
</div>
<h2>Mengakui</h2>
<div class="cols">
<div class="col-6">
<h4>Contoh: Draf Gmail batal yang disimpan</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
<p>Dalam contoh ini, jika pengguna menyusuri ke belakang atau ke atas dari layar pembuatan email di Gmail, sesuatu yang tak diharapkan bisa terjadi: draf saat itu akan disimpan secara otomatis. Pengakuan dalam bentuk pemberitahuan akan lebih jelas. Ini menghilang setelah beberapa detik.</p>
<p>Pembatalan tidak cocok di sini karena penyimpanan dilakukan oleh aplikasi, bukan pengguna. Cepat dan mudah untuk melanjutkan penulisan pesan dengan menyusuri daftar draf.</p>
</div>
<div class="col-6">
<h4>Contoh: Percakapan Gmail dihapus</h4>
<img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
<p>Setelah pengguna menghapus percakapan dari daftar dalam Gmail, sebuah pengakuan muncul tanpa opsi pembatalan. Pengakuan tetap ada sampai pengguna melakukan tindakan yang tidak berkaitan, seperti menggulir daftar.</p>
</div>
</div>
<h2>Tidak ada Konfirmasi atau Pengakuan</h2>
<div class="cols">
<div class="col-6">
<h4>Contoh: memberikan +1</h4>
<img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
<p><strong>Konfirmasi tidak diperlukan</strong>. Jika pengguna telah memberikan +1 secara tidak sengaja, tidak masalah. Mereka cukup menyentuh kembali tombol itu untuk membatalkan tindakan.</p>
<p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan melihat tombol +1 memantul dan berubah merah. Itu tanda yang sangat jelas.</p>
</div>
<div class="col-7">
<h4>Contoh: Menghapus aplikasi dari Layar Beranda</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
<p><strong>Konfirmasi tidak diperlukan</strong>. Ini adalah tindakan yang disengaja: pengguna harus menyeret dan meletakkan sebuah item di atas target yang relatif besar dan terpisah. Karena itu, kecil kemungkinan terjadi ketidaksengajaan. Tetapi jika pengguna menyesali keputusan itu, maka hanya perlu beberapa detik untuk mengembalikannya lagi.</p>
<p><strong>Pengakuan tidak diperlukan</strong>. Pengguna akan mengetahui bahwa aplikasi itu tidak ada di Layar Beranda karena mereka menghilangkannya dengan cara menyeretnya.</p>
</div>
</div>

View File

@@ -0,0 +1,213 @@
page.title=Navigasi dengan Back dan Up
page.tags="navigation","activity","task","up navigation","back navigation"
page.image=/design/media/navigation_between_siblings_gmail.png
@jd:body
<a class="notice-developers" href="{@docRoot}training/implementing-navigation/index.html">
<div>
<h3>Dokumen Pengembang</h3>
<p>Mengimplementasikan Navigasi yang Efektif</p>
</div>
</a>
<p itemprop="description">Navigasi yang konsisten merupakan komponen penting dari keseluruhan pengalaman pengguna. Hampir tidak ada yang lebih membingungkan
pengguna selain navigasi dasar yang perilakunya tidak konsisten dan tidak sesuai harapan. Android 3.0
memperkenalkan perubahan besar dalam perilaku navigasi global. Mengikuti dengan saksama
panduan untuk Back dan Up akan membuat navigasi aplikasi Anda dapat diprediksi dan dapat diandalkan pengguna.</p>
<p>Android 2.3 dan versi sebelumnya mengandalkan tombol <em>Back</em> sistem untuk mendukung navigasi dalam
aplikasi. Dengan diperkenalkannya action-bar dalam Android 3.0, mekanisme navigasi kedua muncul:
tombol <em>Up</em>, yang terdiri dari ikon aplikasi dan tanda panah yang menunjuk ke kiri.</p>
<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
<h2 id="up-vs-back">Up vs. Back</h2>
<p>Tombol Up digunakan untuk berpindah dalam aplikasi berdasarkan hubungan hierarki
antar layar. Misalnya, jika layar A menampilkan daftar item, dan memilih sebuah item akan membuka
layar B (yang menampilkan item tersebut secara lebih detail), maka layar B akan menawarkan tombol Up untuk
kembali ke layar A.</p>
<p>Jika suatu layar merupakan yang teratas dalam aplikasi (yaitu layar Home aplikasi), maka tidak perlu menampilkan tombol
Up.</p>
<p>Tombol Back sistem digunakan untuk berpindah, dalam urutan kronologis terbalik, melalui riwayat
layar yang baru dibuka oleh pengguna. Biasanya ini berdasarkan hubungan sementara
antar layar, dan bukan hierarki aplikasi.</p>
<p>Bila layar yang dilihat sebelumnya juga merupakan induk hierarki dari layar yang sekarang, menekan tombol
Back akan sama hasilnya dengan menekan tombol Up&mdash;ini adalah kejadian
biasa. Akan tetapi, berbeda dengan tombol Up, yang memastikan pengguna tetap berada dalam aplikasi Anda, tombol Back
dapat mengembalikan pengguna ke layar Home, atau bahkan ke aplikasi lain.</p>
<img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
<p>Tombol Back juga mendukung beberapa perilaku yang tidak terkait langsung dengan navigasi antar layar:
</p>
<ul>
<li>Menghilangkan jendela mengambang (dialog, popup)</li>
<li>Menghilangkan action-bar kontekstual, dan menghapus sorotan dari item yang dipilih</li>
<li>Menyembunyikan keyboard di layar (IME)</li>
</ul>
<h2 id="within-app">Navigasi Dalam Aplikasi Anda</h2>
<h4>Berpindah ke layar yang memiliki beberapa titik masuk</h4>
<p>Kadang-kadang layar tidak memiliki posisi pasti dalam hierarki aplikasi, dan bisa dimasuki
dari berbagai titik masuk&mdash;seperti layar pengaturan yang dapat dibuka dari layar lain
dalam aplikasi Anda. Dalam hal ini, tombol Up akan memilih untuk kembali ke layar pengarah, yang cara kerjanya
sama dengan tombol Back.</p>
<h4>Mengubah tampilan dalam layar</h4>
<p>Mengubah opsi tampilan untuk layar tidak mengubah perilaku Up atau Back: layar tetap
berada di tempat yang sama dalam hierarki aplikasi, dan tidak dibuat riwayat navigasi yang baru.</p>
<p>Contoh perubahan tampilan tersebut adalah:</p>
<ul>
<li>Mengganti tampilan menggunakan tab dan/atau geser kiri dan kanan</li>
<li>Mengubah tampilan menggunakan tarik-turun (alias tab turun)</li>
<li>Memfilter daftar</li>
<li>Menyortir daftar</li>
<li>Mengubah karakteristik tampilan (seperti zoom)</li>
</ul>
<h4>Berpindah antar layar yang seinduk</h4>
<p>Bila aplikasi Anda mendukung navigasi dari daftar item ke tampilan detail salah satu item tersebut, aplikasi
juga sering diharapkan mendukung navigasi langsung dari item itu ke item sebelumnya atau
sesudahnya dalam daftar. Misalnya, dalam Gmail, begitu mudah untuk bergeser ke kiri atau kanan dari sebuah percakapan
untuk melihat percakapan yang lebih baru atau lebih lama dalam Inbox yang sama. Sama seperti saat mengubah tampilan dalam layar, navigasi
ini tidak mengubah perilaku Up atau Back.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
<p>Akan tetapi, pengecualian khusus terhadap hal ini terjadi saat menjelajah di antara tampilan detail terkait yang tidak disatukan
oleh daftar yang merujuknya&mdash;misalnya, saat menjelajahi Play Store di antara aplikasi dari
pengembang yang sama, atau album dari artis yang sama. Dalam hal ini, mengikuti setiap tautan akan membuat
riwayat, sehingga tombol Back akan menyusuri setiap layar yang dilihat sebelumnya. Tombol Up akan terus
melewatkan semua layar terkait ini dan berpindah ke layar kontainer yang terakhir dilihat.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
<p>Anda dapat menjadikan perilaku tombol Up lebih cerdas lagi berdasarkan pengetahuan Anda tentang tampilan
detail. Dengan memperluas contoh Play Store dari atas, bayangkan pengguna yang telah berpindah dari Buku
terakhir yang dilihat ke detail untuk adaptasi Film. Dalam hal itu, tombol Up dapat kembali ke kontainer
(Movies) yang sebelumnya belum dilalui pengguna.</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
<h2 id="into-your-app">Navigasi ke Aplikasi Anda melalui Widget dan Pemberitahuan Layar Home</h2>
<p>Anda bisa menggunakan widget atau pemberitahuan layar Home untuk membantu pengguna berpindah langsung ke layar
jauh dalam hierarki aplikasi Anda. Misalnya, widget Inbox dan pemberitahuan pesan baru di Gmail dapat
melewatkan layar Inbox, dan membawa pengguna langsung ke tampilan percakapan.</p>
<p>Untuk kedua kasus ini, tangani tombol Up sebagai berikut:</p>
<ul>
<li><em>Jika layar tujuan biasanya dicapai dari satu layar tertentu dalam aplikasi
Anda</em>, tombol Up akan mengarahkannya ke layar itu.</li>
<li><em>Jika tidak</em>, tombol Up akan mengarahkan ke layar teratas ("Home") dari aplikasi Anda.</li>
</ul>
<p>Dalam hal tombol Back, Anda harus membuat navigasi lebih bisa diprediksi dengan menyisipkan ke dalam
back-stack tugas path navigasi naik lengkap menuju layar teratas aplikasi. Ini memungkinkan pengguna
yang lupa cara masuk ke aplikasi Anda untuk berpindah ke layar teratas aplikasi sebelum
keluar.</p>
<p>Sebagai contoh, widget layar Home di Gmail memiliki tombol untuk menuju langsung ke layar
Compose. Tombol Up atau Back dari layar Compose akan membawa pengguna ke Inbox, dan dari sana tombol
Back berlanjut ke Home.</p>
<img src="{@docRoot}design/media/navigation_from_outside_back.png">
<h4>Pemberitahuan tidak langsung</h4>
<p>Jika aplikasi Anda perlu menampilkan informasi tentang beberapa kejadian sekaligus, aplikasi dapat menggunakan
pemberitahuan tunggal yang mengarahkan pengguna ke layar antara. Layar ini merangkum semua
kejadian tersebut, dan menyediakan path bagi pengguna untuk menjelajah ke dalam aplikasi. Pemberitahuan dengan gaya seperti ini
disebut <em>pemberitahuan tidak langsung</em>.</p>
<p>Berbeda dengan pemberitahuan standar (langsung), menekan tombol Back dari
layar antara pada pemberitahuan tidak langsung akan mengembalikan pengguna ke titik pemicu pemberitahuan tersebut&mdash;tidak ada
layar tambahan yang disisipkan ke dalam back-stack. Setelah pengguna melanjutkan ke dalam aplikasi dari
layar antara, tombol Up dan Back akan berperilaku seperti pada pemberitahuan standar, sebagaimana dijelaskan di atas:
menyusuri ke dalam aplikasi dan bukan kembali ke layar antara.</p>
<p>Misalnya, anggaplah seorang pengguna di Gmail menerima pemberitahuan tidak langsung dari Kalender. Menyentuh
pemberitahuan ini akan membuka layar antara, yang menampilkan pengingat beberapa macam
kejadian. Menyentuh Back dari layar antara akan mengembalikan pengguna ke Gmail. Menyentuh kejadian
tertentu akan membawa pengguna dari layar antara ke aplikasi Kalender lengkap untuk menampilkan detail
kejadian. Dari detail kejadian, tombol Up dan Back akan mengarahkan ke tampilan Kalender tingkat atas.</p>
<img src="{@docRoot}design/media/navigation_indirect_notification.png">
<h4>Pemberitahuan pop-up</h4>
<p><em>Pemberitahuan pop-up</em> akan melewatkan laci pemberitahuan, bukan muncul secara langsung di
hadapan pengguna. Ini jarang digunakan, dan <strong>harus dicadangkan untuk peristiwa yang memerlukan respons tepat waktu
dan diperlukan interupsi dari konteks pengguna</strong>. Misalnya,
Talk menggunakan gaya ini untuk memberi tahu pengguna tentang ajakan dari teman untuk bergabung dalam chatting video, karena
ajakan ini akan kedaluwarsa secara otomatis setelah beberapa detik.</p>
<p>Dalam hal perilaku navigasi, pemberitahuan pop-up sangat mirip perilaku pemberitahuan
tidak langsung pada layar antara. Tombol Back akan menghilangkan pemberitahuan pop-up. Jika pengguna berpindah
dari pop-up ke aplikasi yang memberi tahu, tombol Up dan Back akan mengikuti aturan pemberitahuan standar,
berpindah dalam aplikasi.</p>
<img src="{@docRoot}design/media/navigation_popup_notification.png">
<h2 id="between-apps">Navigasi Antar Aplikasi</h2>
<p>Salah satu kekuatan dasar sistem Android adalah kemampuan aplikasi untuk saling
mengaktifkan, sehingga pengguna dapat berpindah langsung dari satu aplikasi ke aplikasi lainnya. Misalnya, sebuah
aplikasi yang perlu mengambil foto dapat mengaktifkan aplikasi Kamera, yang akan mengembalikan foto
ke aplikasi perujuk. Ini sangat menguntungkan pengembang, yang bisa dengan mudah memanfaatkan
kode dari aplikasi lain, maupun pengguna, yang menikmati pengalaman konsisten untuk tindakan yang biasa
dilakukan.</p>
<p>Untuk memahami navigasi antar aplikasi, maka perlu memahami perilaku kerangka kerja Android
yang akan dibahas di bawah ini.</p>
<h4>Aktivitas, tugas, dan intent</h4>
<p>Dalam Android, <strong>aktivitas</strong> adalah komponen aplikasi yang mendefinisikan layar
informasi dan semua tindakan terkait yang dapat dilakukan pengguna. Aplikasi Anda adalah kumpulan
aktivitas, yang terdiri dari aktivitas yang Anda buat dan aktivitas yang Anda gunakan ulang dari aplikasi lain.</p>
<p><strong>Tugas</strong> adalah urutan aktivitas yang diikuti pengguna untuk mencapai tujuan.
Tugas tunggal dapat memanfaatkan aktivitas dari satu aplikasi saja, atau dapat memanfaatkan aktivitas dari sejumlah
aplikasi berbeda.</p>
<p><strong>Intent</strong> adalah mekanisme bagi satu aplikasi untuk memberi isyarat minta bantuan
aplikasi lain dalam menjalankan suatu tindakan. Aktivitas aplikasi dapat menunjukkan intent
apa saja yang dapat diresponsnya. Untuk intent umum seperti "Share", pengguna mungkin telah menginstal beberapa aplikasi
yang dapat memenuhi permintaan itu.</p>
<h4>Contoh: berpindah antar aplikasi untuk mendukung berbagi</h4>
<p>Untuk memahami cara kerja sama aktivitas, tugas, dan intent, perhatikan bagaimana sebuah aplikasi memungkinkan pengguna
untuk berbagi konten dengan menggunakan aplikasi lain. Misalnya, membuka aplikasi Play Store dari Home akan memulai
Task A baru (lihat gambar di bawah). Setelah menyusuri Play Store dan menyentuh buku yang dipromosikan
untuk melihat detailnya, pengguna tetap berada dalam tugas yang sama, memperluasnya dengan menambahkan aktivitas. Memicu
tindakan Share akan memberi tahu pengguna dengan dialog berisi daftar aktivitas (dari aplikasi berbeda)
yang telah terdaftar untuk menangani intent Share.</p>
<img src="{@docRoot}design/media/navigation_between_apps_inward.png">
<p>Bila pengguna memilih untuk berbagi melalui Gmail, aktivitas penulisan di Gmail akan ditambahkan sebagai kelanjutan dari
Task A&mdash;tidak ada tugas baru yang dibuat. Jika Gmail sedang menjalankan tugasnya di latar belakang, maka
tidak akan terpengaruh.</p>
<p>Dari aktivitas penulisan, mengirim pesan atau menyentuh tombol Back akan mengembalikan pengguna ke
aktivitas detail buku tersebut. Penyentuhan tombol Back berikutnya akan terus mengarahkan kembali melalui Play
Store, sampai akhirnya tiba di Home.</p>
<img src="{@docRoot}design/media/navigation_between_apps_back.png">
<p>Akan tetapi, dengan menyentuh tombol Up dari aktivitas penulisan, pengguna menunjukkan keinginan untuk tetap berada di
Gmail. Aktivitas daftar percakapan Gmail muncul, Task B yang baru akan dibuat untuk itu. Tugas baru
selalu terkait ke Home, maka menyentuh tombol Back dari daftar percakapan akan mengembalikan ke sana.</p>
<img src="{@docRoot}design/media/navigation_between_apps_up.png">
<p>Task A tetap berjalan di latar belakang, dan pengguna nanti dapat kembali ke sana (misalnya, melalui layar
Recents). Jika Gmail sedang menjalankan tugasnya di latar belakang, maka itu akan digantikan
dengan Task B&mdash;konteks sebelumnya akan diabaikan demi tujuan baru pengguna.</p>
<p>Jika register aplikasi Anda menangani intent dengan aktivitas yang jauh di dalam hierarki aplikasi,
lihat <a href="#into-your-app">Navigasi Aplikasi Anda melalui Widget Layar Home dan
Pemberitahuan</a> untuk panduan mengenai cara menetapkan navigasi Up.</p>

View File

@@ -0,0 +1,756 @@
page.title=Aktivitas
page.tags=aktivitas,intent
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Creating">Membuat Aktivitas</a>
<ol>
<li><a href="#UI">Mengimplementasikan antarmuka pengguna</a></li>
<li><a href="#Declaring">Mendeklarasikan aktivitas dalam manifes</a></li>
</ol>
</li>
<li><a href="#StartingAnActivity">Memulai Aktivitas</a>
<ol>
<li><a href="#StartingAnActivityForResult">Memulai aktivitas agar berhasil</a></li>
</ol>
</li>
<li><a href="#ShuttingDown">Mematikan Aktivitas</a></li>
<li><a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a>
<ol>
<li><a href="#ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li>
<li><a href="#SavingActivityState">Menyimpan status aktivitas</a></li>
<li><a href="#ConfigurationChanges">Menangani perubahan konfigurasi</a></li>
<li><a href="#CoordinatingActivities">Mengoordinasikan aktivitas</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Activity}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan
Back-Stack</a></li>
</ol>
</div>
</div>
<p>{@link android.app.Activity} adalah sebuah komponen aplikasi yang menyediakan layar yang digunakan
pengguna untuk berinteraksi guna melakukan sesuatu, misalnya memilih nomor telepon, mengambil foto, mengirim email, atau
menampilkan peta. Tiap aktivitas diberi sebuah jendela untuk menggambar antarmuka penggunanya. Jendela ini
biasanya mengisi layar, namun mungkin lebih kecil daripada layar dan mengambang di atas
jendela lain.</p>
<p> Sebuah aplikasi biasanya terdiri atas beberapa aktivitas yang terikat secara longgar
satu sama lain. Biasanya, satu aktivitas dalam aplikasi ditetapkan sebagai aktivitas "utama", yang
ditampilkan kepada pengguna saat membuka aplikasi untuk pertama kali. Tiap
aktivitas kemudian bisa memulai aktivitas lain untuk melakukan berbagai tindakan. Tiap kali
aktivitas baru dimulai, aktivitas sebelumnya akan dihentikan, namun sistem mempertahankan aktivitas
dalam sebuah tumpukan ("back-stack"). Bila sebuah aktivitas baru dimulai, aktivitas itu akan didorong ke atas back-stack dan
mengambil fokus pengguna. Back-stack mematuhi mekanisme dasar tumpukan "masuk terakhir, keluar pertama",
jadi, bila pengguna selesai dengan aktivitas saat ini dan menekan tombol <em>Back</em>, aktivitas
akan dikeluarkan dari tumpukan (dan dimusnahkan) dan aktivitas sebelumnya akan dilanjutkan. (Back-stack
dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas
dan Back-Stack</a>.)</p>
<p>Bila aktivitas dihentikan karena ada aktivitas baru yang dimulai, aktivitas lama akan diberi tahu tentang perubahan status ini
melalui metode callback daur hidupnya.
Ada beberapa metode callback yang mungkin diterima aktivitas, karena sebuah perubahan dalam
statusnya&mdash;apakah sistem sedang membuatnya, menghentikannya, melanjutkannya, atau menghapuskannya&mdash;dan
masing-masing callback memberi Anda kesempatan melakukan pekerjaan tertentu yang
sesuai untuk perubahan status itu. Misalnya, bila dihentikan, aktivitas Anda harus melepas
objek besar, seperti koneksi jaringan atau database. Bila aktivitas dilanjutkan, Anda bisa
memperoleh kembali sumber daya yang diperlukan dan melanjutkan tindakan yang terputus. Transisi status ini
semuanya bagian dari daur hidup aktivitas.</p>
<p>Bagian selebihnya dari dokumen ini membahas dasar-dasar cara membuat dan menggunakan aktivitas,
yang meliputi satu pembahasan lengkap tentang cara kerja daur hidup aktivitas, sehingga Anda bisa dengan benar mengelola
transisi di antara berbagai status aktivitas.</p>
<h2 id="Creating">Membuat Aktivitas</h2>
<p>Untuk membuat sebuah aktivitas, Anda harus membuat subkelas {@link android.app.Activity} (atau
subkelasnya yang ada). Dalam subkelas itu, Anda perlu mengimplementasikan metode-metode callback yang
dipanggil sistem saat aktivitas bertransisi di antara berbagai status daur hidupnya, misalnya saat
aktivitas sedang dibuat, dihentikan, dilanjutkan, atau dimusnahkan. Dua metode callback
terpenting adalah:</p>
<dl>
<dt>{@link android.app.Activity#onCreate onCreate()}</dt>
<dd>Anda harus mengimplementasikan metode ini. Sistem memanggilnya saat membuat
aktivitas Anda. Dalam implementasi, Anda harus menginisialisasi komponen-komponen esensial
aktivitas.
Yang terpenting, inilah tempat Anda harus memanggil {@link android.app.Activity#setContentView
setContentView()} untuk mendefinisikan layout untuk antarmuka pengguna aktivitas.</dd>
<dt>{@link android.app.Activity#onPause onPause()}</dt>
<dd>Sistem memanggil metode ini sebagai pertanda pertama bahwa pengguna sedang meninggalkan
aktivitas Anda (walau itu tidak selalu berarti aktivitas sedang dimusnahkan). Inilah biasanya tempat Anda
harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena
pengguna mungkin tidak kembali).</dd>
</dl>
<p>Ada beberapa metode callback daur hidup lainnya yang harus Anda gunakan untuk memberikan
pengalaman pengguna yang mengalir di antara aktivitas dan menangani interupsi tidak terduga yang menyebabkan aktivitas Anda
dihentikan dan bahkan dimusnahkan. Semua metode callback daur hidup akan dibahas nanti, di
bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a>.</p>
<h3 id="UI">Mengimplementasikan antarmuka pengguna</h3>
<p> Antarmuka pengguna aktivitas disediakan oleh hierarki objek&mdash;tampilan yang diturunkan
dari kelas {@link android.view.View}. Tiap tampilan mengontrol sebuah ruang persegi panjang tertentu
dalam jendela aktivitas dan bisa merespons interaksi pengguna. Misalnya, sebuah tampilan mungkin berupa sebuah
tombol yang mengawali suatu tindakan bila pengguna menyentuhnya.</p>
<p>Android menyediakan sejumlah tampilan siap-dibuat yang bisa Anda gunakan untuk mendesain dan mengatur
layout. "Widget" adalah tampilan yang menyediakan elemen-elemen visual (dan interaktif) untuk layar,
misalnya tombol, bidang teks, kotak cek, atau sekadar sebuah gambar. "Layout" adalah tampilan yang diturunkan dari {@link
android.view.ViewGroup} yang memberikan sebuah model layout unik untuk tampilan anaknya, misalnya
layout linier, layout grid, atau layout relatif. Anda juga bisa mensubkelaskan kelas-kelas {@link android.view.View} dan
{@link android.view.ViewGroup} (atau subkelas yang ada) untuk membuat widget dan
layout Anda sendiri dan menerapkannya ke layout aktivitas Anda.</p>
<p>Cara paling umum untuk mendefinisikan layout dengan menggunakan tampilan adalah dengan file layout XML yang disimpan dalam
sumber daya aplikasi Anda. Dengan cara ini, Anda bisa memelihara desain antarmuka pengguna Anda secara terpisah dari
kode yang mendefinisikan perilaku aktivitas. Anda bisa mengatur layout sebagai UI
aktivitas Anda dengan {@link android.app.Activity#setContentView(int) setContentView()}, dengan meneruskan
ID sumber daya untuk layout itu. Akan tetapi, Anda juga bisa membuat {@link android.view.View} baru dalam
kode aktivitas dan membuat hierarki tampilan dengan menyisipkan {@link
android.view.View} baru ke dalam {@link android.view.ViewGroup}, kemudian menggunakan layout itu dengan meneruskan akar
{@link android.view.ViewGroup} ke {@link android.app.Activity#setContentView(View)
setContentView()}.</p>
<p>Untuk informasi tentang cara membuat antarmuka pengguna, lihat dokumentasi <a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p>
<h3 id="Declaring">Mendeklarasikan aktivitas dalam manifes</h3>
<p>Anda harus mendeklarasikan aktivitas dalam file manifes agar file itu
bisa diakses oleh sistem. Untuk mendeklarasikan aktivitas, bukalah file manifes Anda dan tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
sebagai anak elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
. Misalnya:</p>
<pre>
&lt;manifest ... &gt;
&lt;application ... &gt;
&lt;activity android:name=".ExampleActivity" /&gt;
...
&lt;/application ... &gt;
...
&lt;/manifest &gt;
</pre>
<p>Ada beberapa atribut lain yang bisa Anda sertakan dalam elemen ini, untuk mendefinisikan properti
misalnya label untuk aktivitas, ikon untuk aktivitas, atau tema untuk memberi gaya ke
UI aktivitas. Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a>
adalah satu-satunya atribut yang diperlukan&mdash;atribut ini menetapkan nama kelas aktivitas. Setelah
Anda mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak
sebagian fungsionalitas, misalnya pintasan aplikasi (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
That Cannot Change</a>).</p>
<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
untuk informasi selengkapnya tentang cara mendeklarasikan aktivitas Anda dalam manifes.</p>
<h4>Menggunakan filter intent</h4>
<p>Elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a> juga bisa menetapkan berbagai filter intent&mdash;dengan menggunakan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> &mdash;untuk mendeklarasikan cara komponen aplikasi lain
mengaktifkannya.</p>
<p>Bila Anda membuat aplikasi baru dengan Android SDK Tools, aktivitas stub
yang dibuat untuk Anda secara otomatis menyertakan filter intent yang mendeklarasikan respons
aktivitas pada tindakan "main" (utama) dan harus diletakkan dalam kategori "launcher"). Filter intent
terlihat seperti ini:</p>
<pre>
&lt;activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>
<p>Elemen <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a> menetapkan bahwa ini adalah titik masuk "main" ke aplikasi. Elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a> menetapkan bahwa aktivitas ini harus tercantum dalam launcher aplikasi
sistem (untuk memungkinkan pengguna meluncurkan aktivitas ini).</p>
<p>Jika Anda bermaksud agar aplikasi dimuat dengan sendirinya dan tidak memperbolehkan aplikasi lain
mengaktifkan aktivitasnya, maka Anda tidak memerlukan filter intent lain. Hanya satu aktivitas yang boleh
memiliki tindakan "main" dan kategori "launcher", seperti dalam contoh sebelumnya. Aktivitas yang
tidak ingin Anda sediakan untuk aplikasi lain tidak boleh memiliki filter intent dan Anda bisa
memulai sendiri aktivitas dengan menggunakan intent secara eksplisit (seperti dibahas di bagian berikut).</p>
<p>Akan tetapi, jika ingin aktivitas Anda merespons intent implisit yang dikirim dari
aplikasi lain (dan aplikasi Anda sendiri), maka Anda harus mendefinisikan filter intent tambahan untuk
aktivitas. Untuk masing-masing tipe intent yang ingin direspons, Anda harus menyertakan sebuah <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> yang menyertakan elemen
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a> dan, opsional, sebuah elemen <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a> dan/atau elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
&lt;data&gt;}</a>. Elemen-elemen ini menetapkan tipe intent yang bisa
direspons oleh aktivitas Anda.</p>
<p>Untuk informasi selengkapnya tentang cara aktivitas Anda merespons intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>.
</p>
<h2 id="StartingAnActivity">Memulai Aktivitas</h2>
<p>Anda bisa memulai aktivitas lain dengan memanggil {@link android.app.Activity#startActivity
startActivity()}, dengan meneruskan sebuah {@link android.content.Intent} yang menjelaskan aktivitas
yang ingin Anda mulai. Intent menetapkan aktivitas persis yang ingin Anda mulai atau menjelaskan
tipe tindakan yang ingin Anda lakukan (dan sistem akan memilih aktivitas yang sesuai untuk Anda,
yang bahkan
bisa berasal dari aplikasi berbeda). Intent juga bisa membawa sejumlah kecil data untuk
digunakan oleh aktivitas yang dimulai.</p>
<p>Saat bekerja dalam aplikasi sendiri, Anda nanti akan sering meluncurkan aktivitas yang dikenal saja.
Anda bisa melakukannya dengan membuat intent yang mendefinisikan secara eksplisit aktivitas yang ingin Anda mulai,
dengan menggunakan nama kelas. Misalnya, beginilah cara satu aktivitas memulai aktivitas lain bernama {@code
SignInActivity}:</p>
<pre>
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
</pre>
<p>Akan tetapi, aplikasi Anda mungkin juga perlu melakukan beberapa tindakan, misalnya mengirim email,
pesan teks, atau pembaruan status, dengan menggunakan data dari aktivitas Anda. Dalam hal ini, aplikasi Anda mungkin
tidak memiliki aktivitasnya sendiri untuk melakukan tindakan tersebut, sehingga Anda bisa memanfaatkan aktivitas
yang disediakan oleh aplikasi lain pada perangkat, yang bisa melakukan tindakan itu untuk Anda. Inilah saatnya
intent benar-benar berharga&mdash;Anda bisa membuat intent yang menjelaskan tindakan yang ingin
dilakukan dan sistem
akan meluncurkan aktivitas yang tepat dari aplikasi lain. Jika ada
beberapa aktivitas yang bisa menangani intent itu, pengguna bisa memilih aktivitas yang akan digunakan. Misalnya,
jika Anda ingin memperbolehkan pengguna mengirim pesan email, Anda bisa membuat
intent berikut:</p>
<pre>
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
</pre>
<p>Ekstra {@link android.content.Intent#EXTRA_EMAIL} yang ditambahkan ke intent adalah sebuah larik string
alamat email yang menjadi tujuan pengiriman email. Bila aplikasi email merespons intent ini,
aplikasi itu akan membaca larik string yang disediakan dalam ekstra dan meletakkannya dalam bidang "to"
pada formulir penulisan email. Dalam situasi ini, aktivitas aplikasi email dimulai dan bila
pengguna selesai, aktivitas Anda akan dilanjutkan.</p>
<h3 id="StartingAnActivityForResult">Memulai aktivitas agar berhasil</h3>
<p>Kadang-kadang, Anda mungkin ingin menerima hasil dari aktivitas yang Anda mulai. Dalam hal itu,
mulailah aktivitas dengan memanggil {@link android.app.Activity#startActivityForResult
startActivityForResult()} (sebagai ganti {@link android.app.Activity#startActivity
startActivity()}). Untuk menerima hasil dari
aktivitas selanjutnya nanti, implementasikan metode callback {@link android.app.Activity#onActivityResult onActivityResult()}
. Bila aktivitas selanjutnya selesai, aktivitas akan mengembalikan hasil dalam {@link
android.content.Intent} kepada metode {@link android.app.Activity#onActivityResult onActivityResult()}
Anda.</p>
<p>Misalnya, mungkin Anda ingin pengguna mengambil salah satu kontaknya, sehingga aktivitas Anda bisa
melakukan sesuatu dengan informasi dalam kontak itu. Begini caranya membuat intent tersebut dan
menangani hasilnya:</p>
<pre>
private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content provider URI
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}
&#64;Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the request went well (OK) and the request was PICK_CONTACT_REQUEST
if (resultCode == Activity.RESULT_OK &amp;&amp; requestCode == PICK_CONTACT_REQUEST) {
// Perform a query to the contact's content provider for the contact's name
Cursor cursor = getContentResolver().query(data.getData(),
new String[] {Contacts.DISPLAY_NAME}, null, null, null);
if (cursor.moveToFirst()) { // True if the cursor is not empty
int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// Do something with the selected contact's name...
}
}
}
</pre>
<p>Contoh ini menunjukkan logika dasar yang harus Anda gunakan dalam metode {@link
android.app.Activity#onActivityResult onActivityResult()} Anda untuk menangani
hasil aktivitas. Syarat pertama memeriksa apakah permintaan berhasil&mdash;jika ya, maka
{@code resultCode} akan berupa {@link android.app.Activity#RESULT_OK}&mdash;dan apakah permintaan
yang direspons hasil ini dikenal&mdash;dalam hal ini, {@code requestCode} cocok dengan
parameter kedua yang dikirim dengan {@link android.app.Activity#startActivityForResult
startActivityForResult()}. Dari sana, kode akan menangani hasil aktivitas dengan membuat query
data yang dihasilkan dalam{@link android.content.Intent} (parameter {@code data}).</p>
<p>Yang terjadi adalah {@link
android.content.ContentResolver} melakukan query terhadap penyedia konten, yang menghasilkan
{@link android.database.Cursor} yang memperbolehkan data query dibaca. Untuk informasi selengkapnya, lihat dokumen
<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter
Intent</a>.</p>
<h2 id="ShuttingDown">Mematikan Aktivitas</h2>
<p>Anda bisa mematikan aktivitas dengan memanggil metode {@link android.app.Activity#finish
finish()}-nya. Anda juga bisa mematikan aktivitas terpisah yang sebelumnya Anda mulai dengan memanggil
{@link android.app.Activity#finishActivity finishActivity()}.</p>
<p class="note"><strong>Catatan:</strong> Pada umumnya, Anda tidak boleh secara eksplisit mengakhiri aktivitas
dengan menggunakan metode-metode ini. Seperti yang dibahas di bagian berikut tentang daur hidup aktivitas,
sistem Android mengelola hidup aktivitas untuk Anda, sehingga Anda tidak perlu menyelesaikan sendiri
aktivitas tersebut. Memanggil metode-metode ini bisa berpengaruh negatif pada pengalaman
pengguna yang diharapkan dan hanya boleh digunakan bila Anda benar-benar tidak ingin pengguna kembali ke
instance aktivitas ini.</p>
<h2 id="Lifecycle">Mengelola Daur Hidup Aktivitas</h2>
<p>Mengelola daur hidup aktivitas dengan mengimplementasikan metode-metode callback sangat
penting untuk mengembangkan
aplikasi yang kuat dan fleksibel. Daur hidup aktivitas dipengaruhi langsung oleh kaitannya dengan
aktivitas lain, tugasnya, serta back-stack.</p>
<p>Pada dasarnya, sebuah aktivitas bisa berada dalam tiga status:</p>
<dl>
<dt><i>Dilanjutkan</i></dt>
<dd>Aktivitas berada di latar depan layar dan mendapatkan fokus pengguna. (Status ini
kadang-kadang disebut juga dengan "running" (berjalan).)</dd>
<dt><i>Dihentikan sementara</i></dt>
<dd>Aktivitas lain berada di latar depan dan mendapat fokus, namun aktivitas ini masih terlihat. Yakni,
aktivitas lain terlihat di atas aplikasi ini dan aktivitas itu setengah transparan atau tidak
menuutpi seluruh layar. Aktivitas yang dihentikan sementara adalah benar-benar hidup (objek {@link android.app.Activity}
dipertahankan dalam memori, objek itu memelihara semua informasi status dan anggota, dan tetap dikaitkan dengan
window manager), namun bisa dimatikan oleh sistem dalam situasi memori sangat rendah.</dd>
<dt><i>Dihentikan</i></dt>
<dd>Aktivitas ditutupi sepenuhnya oleh aktivitas lain (aktivitas sekarang berada di
"latar belakang"). Aktivitas yang dihentikan juga masih hidup (objek {@link android.app.Activity}
dipertahankan dalam memori, objek itu menjaga semua informasi status dan anggota, namun <em>tidak</em>
dikaitkan dengan window manager). Akan tetapi, aktivitas tidak lagi terlihat bagi pengguna dan
bisa dimatikan oleh sistem bila memori diperlukan di lain.</dd>
</dl>
<p>Jika aktivitas dihentikan sementara atau dihentikan, sistem bisa mengeluarkannya dari memori baik dengan memintanya agar
diakhiri (memanggil metode {@link android.app.Activity#finish finish()}-nya), atau sekadar mematikan
prosesnya. Bila dibuka lagi (setelah diakhiri atau dimatikan), aktivitas harus dibuat dari
awal.</p>
<h3 id="ImplementingLifecycleCallbacks">Mengimplementasikan callback daur hidup</h3>
<p>Saat bertransisi ke dalam dan ke luar berbagai status yang dijelaskan di atas, aktivitas diberi tahu
melalui berbagai metode callback. Semua metode callback adalah sangkutan yang
bisa Anda kesampingkan untuk melakukan pekerjaan yang sesuai saat status aktivitas Anda berubah. Aktivitas skeleton
berikut menyertakan setiap metode daur hidup mendasar:</p>
<pre>
public class ExampleActivity extends Activity {
&#64;Override
public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
&#64;Override
protected void {@link android.app.Activity#onStart onStart()} {
super.onStart();
// The activity is about to become visible.
}
&#64;Override
protected void {@link android.app.Activity#onResume onResume()} {
super.onResume();
// The activity has become visible (it is now "resumed").
}
&#64;Override
protected void {@link android.app.Activity#onPause onPause()} {
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
&#64;Override
protected void {@link android.app.Activity#onStop onStop()} {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
&#64;Override
protected void {@link android.app.Activity#onDestroy onDestroy()} {
super.onDestroy();
// The activity is about to be destroyed.
}
}
</pre>
<p class="note"><strong>Catatan:</strong> Implementasi Anda terhadap metode-metode daur hidup ini harus
selalu memanggil implementasi superkelas sebelum melakukan pekerjaan apa pun, seperti yang ditampilkan dalam contoh-contoh di atas.</p>
<p>Bersama-sama, semua metode ini mendefinisikan seluruh daur hidup sebuah aktivitas. Dengan mengimplementasikan
metode-metode ini, Anda bisa memantau tiga loop tersarang (nested loop) dalam daur hidup aktivitas: </p>
<ul>
<li><b>Seluruh masa hidup</b> aktivitas berlangsung antara panggilan ke {@link
android.app.Activity#onCreate onCreate()} dan panggilan ke {@link
android.app.Activity#onDestroy}. Aktivitas Anda harus melakukan penyiapan
status "global" (misalnya mendefinisikan layout) dalam {@link android.app.Activity#onCreate onCreate()}, dan
melepas semua sisa sumber daya dalam {@link android.app.Activity#onDestroy}. Misalnya, jika
aktivitas Anda memiliki sebuah thread yang berjalan di latar belakang untuk mengunduh data dari jaringan, aktivitas itu bisa membuat
thread itu dalam {@link android.app.Activity#onCreate onCreate()} kemudian menghentikan thread dalam {@link
android.app.Activity#onDestroy}.</li>
<li><p><b>Masa pakai terlihat</b> (visible lifetime) aktivitas berlangsung antara panggilan ke {@link
android.app.Activity#onStart onStart()} dan panggilan ke {@link
android.app.Activity#onStop onStop()}. Selama ini, pengguna bisa melihat aktivitas
pada layar dan berinteraksi dengannya. Misalnya, {@link android.app.Activity#onStop onStop()} dipanggil
bila sebuah aktivitas baru dimulai dan aktivitas ini tidak lagi terlihat. Di antara dua metode ini, Anda bisa
memelihara sumber daya yang diperlukan untuk menampilkan aktivitas kepada pengguna. Misalnya, Anda bisa mendaftarkan sebuah
{@link android.content.BroadcastReceiver} dalam {@link
android.app.Activity#onStart onStart()} untuk memantau perubahan yang berdampak pada UI Anda, dan mencabut pendaftarannya
dalam {@link android.app.Activity#onStop onStop()} bila pengguna tidak bisa lagi melihat apa yang sedang Anda
tampilkan. Sistem bisa memanggil {@link android.app.Activity#onStart onStart()} dan {@link
android.app.Activity#onStop onStop()} beberapa kali selama masa pakai aktivitas, sambil
aktivitas berganti-ganti antara terlihat dan tersembunyi bagi pengguna.</p></li>
<li><p><b>Masa pakai latar depan</b> aktivitas berlangsung antara panggilan ke {@link
android.app.Activity#onResume onResume()} dan panggilan ke {@link android.app.Activity#onPause
onPause()}. Selama waktu ini, aktivitas berada di depan semua aktivitas lain pada layar dan mendapatkan
fokus input pengguna. Aktivitas bisa sering bertransisi ke dalam dan ke luar latar depan&mdash;misalnya,
{@link android.app.Activity#onPause onPause()} dipanggil bila perangkat masuk ke mode tidur atau
bila dialog muncul. Karena status ini bisa sering bertransisi, kode dalam dua metode ini harus
cukup ringan untuk menghindari transisi lamban yang membuat pengguna menunggu.</p></li>
</ul>
<p>Gambar 1 mengilustrasikan loop dan path yang mungkin diambil sebuah aktivitas di antara status-status.
Persegi panjang mewakili metode callback yang bisa Anda implementasikan untuk melakukan operasi saat
aktivitas bertransisi di antara status. <p>
<img src="{@docRoot}images/activity_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup aktivitas.</p>
<p>Metode-metode callback daur hidup yang sama tercantum dalam tabel 1, yang menjelaskan setiap metode callback
secara lebih detail dan menentukan lokasinya masing-masing dalam
daur hidup aktivitas keseluruhan, termasuk apakah sistem bisa mematikan aktivitas setelah
metode callback selesai.</p>
<p class="table-caption"><strong>Tabel 1.</strong> Rangkuman metode callback
daur hidup aktivitas.</p>
<table border="2" width="85%" frame="hsides" rules="rows">
<colgroup align="left" span="3"></colgroup>
<colgroup align="left"></colgroup>
<colgroup align="center"></colgroup>
<colgroup align="center"></colgroup>
<thead>
<tr><th colspan="3">Metode</th> <th>Keterangan</th> <th>Bisa dimatikan setelahnya?</th> <th>Berikutnya</th></tr>
</thead>
<tbody>
<tr>
<td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td>
<td>Dipanggil saat aktivitas pertama kali dibuat.
Di sinilah Anda harus melakukan semua persiapan statis normal &mdash;
membuat tampilan, mengikat data ke daftar, dan sebagainya. Metode ini diberi
sebuah objek Bundle yang berisi status aktivitas sebelumnya, jika
status itu tertangkap (lihat <a href="#actstate">Menyimpan Status Aktivitas</a>,
nanti).
<p>Selalu diikuti oleh {@code onStart()}.</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onStart()}</td>
</tr>
<tr>
<td rowspan="5" style="border-left: none; border-right: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td colspan="2" align="left"><code>{@link android.app.Activity#onRestart
onRestart()}</code></td>
<td>Dipanggil setelah aktivitas dihentikan, tepat sebelum
dimulai lagi.
<p>Selalu diikuti oleh {@code onStart()}</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onStart()}</td>
</tr>
<tr>
<td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td>
<td>Dipanggil tepat sebelum aktivitas menjadi terlihat bagi pengguna.
<p>Diikuti oleh {@code onResume()} jika aktivitas maju
ke latar depan, atau {@code onStop()} jika menjadi tersembunyi.</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td>
</tr>
<tr>
<td rowspan="2" style="border-left: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td>
<td>Dipanggil tepat sebelum aktivitas mulai
berinteraksi dengan pengguna. Pada titik ini, aktivitas berada di
puncak tumpukan aktivitas, dengan input pengguna menuju kepadanya.
<p>Selalu diikuti oleh {@code onPause()}.</p></td>
<td align="center">Tidak</td>
<td align="center">{@code onPause()}</td>
</tr>
<tr>
<td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td>
<td>Dipanggil bila sistem akan memulai pelanjutan
aktivitas lain. Metode ini biasanya digunakan untuk menerapkan (commit) perubahan yang tidak tersimpan pada
data persisten, menghentikan animasi dan hal-hal lain yang mungkin menghabiskan
CPU, dan sebagainya. Metode ini harus melakukan apa saja yang dilakukannya dengan sangat cepat, karena
aktivitas berikutnya tidak akan dilanjutkan hingga aktivitas ini kembali.
<p>Diikuti oleh {@code onResume()} jika aktivitas
kembali ke depan, atau oleh {@code onStop()} jika menjadi
tidak terlihat bagi pengguna.</td>
<td align="center"><strong style="color:#800000">Ya</strong></td>
<td align="center">{@code onResume()} <br/>atau<br/> {@code onStop()}</td>
</tr>
<tr>
<td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td>
<td>Dipanggil bila aktivitas tidak lagi terlihat bagi pengguna. Hal ini
bisa terjadi karena aktivitas sedang dimusnahkan, atau karena aktivitas lain
(aktivitas yang ada atau yang baru) telah dilanjutkan dan sedang menutupinya.
<p>Diikuti oleh {@code onRestart()} jika
aktivitas kembali untuk berinteraksi dengan pengguna, atau oleh
{@code onDestroy()} jika aktivitas ini akan menghilang.</p></td>
<td align="center"><strong style="color:#800000">Ya</strong></td>
<td align="center">{@code onRestart()} <br/>atau<br/> {@code onDestroy()}</td>
</tr>
<tr>
<td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy
onDestroy()}</code></td>
<td>Dipanggil sebelum aktivitas dimusnahkan. Inilah panggilan terakhir
yang akan diterima aktivitas. Metode ini bisa dipanggil karena
aktivitas selesai (seseorang memanggil <code>{@link android.app.Activity#finish
finish()}</code> padanya), atau karena sistem memusnahkan sementara
instance aktivitas ini untuk menghemat tempat. Anda bisa membedakan
kedua skenario ini dengan metode <code>{@link
android.app.Activity#isFinishing isFinishing()}</code>.</td>
<td align="center"><strong style="color:#800000">Ya</strong></td>
<td align="center"><em>tidak ada</em></td>
</tr>
</tbody>
</table>
<p>Kolom berlabel "Bisa dimatikan setelahnya?" menunjukkan apakah sistem bisa
atau tidak mematikan proses yang menjadi host aktivitas kapan saja <em>setelah metode kembali</em>, tanpa
menjalankan baris lain pada kode aktivitas. Tiga metode ini ditandai "ya": ({@link
android.app.Activity#onPause
onPause()}, {@link android.app.Activity#onStop onStop()}, dan {@link android.app.Activity#onDestroy
onDestroy()}). Karena {@link android.app.Activity#onPause onPause()} adalah yang pertama
dari tiga, begitu aktivitas dibuat, {@link android.app.Activity#onPause onPause()} adalah
metode terakhir yang dipastikan akan dipanggil sebelum proses <em>bisa</em> dimatikan&mdash;jika
sistem harus memulihkan memori dalam keadaan darurat, maka {@link
android.app.Activity#onStop onStop()} dan {@link android.app.Activity#onDestroy onDestroy()} mungkin
tidak dipanggil. Karena itu, Anda harus menggunakan {@link android.app.Activity#onPause onPause()} untuk menulis
data persisten yang penting (misalnya hasil edit pengguna) ke penyimpanan. Akan tetapi, Anda harus selektif dalam hal
informasi yang harus dipertahankan selama {@link android.app.Activity#onPause onPause()}, karena setiap
prosedur pemblokiran dalam metode ini akan memblokir transisi ke aktivitas berikutnya dan memperlambat
pengalaman pengguna.</p>
<p> Metode-metode yang ditandai "Tidak" dalam kolom <b>Bisa dimatikan</b> melindungi proses yang menjadi host
aktivitas dari dimatikan sejak saat metode dipanggil. Jadi, aktivitas bisa dimatikan
sejak {@link android.app.Activity#onPause onPause()} kembali hingga waktu
{@link android.app.Activity#onResume onResume()} dipanggil. Aktivitas tidak akan lagi bisa dimatikan hingga
{@link android.app.Activity#onPause onPause()} dipanggil lagi dan kembali. </p>
<p class="note"><strong>Catatan:</strong> Aktivitas yang tidak "bisa dimatikan" secara teknis oleh
definisi dalam tabel 1 masih bisa dimatikan oleh sistem&mdash;namun itu hany terjadi dalam
situasi ekstrem bila tidak ada jalan lain. Kapan aktivitas bisa dimatikan
akan dibahas selengkapnya dalam dokumen <a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan
Threading</a>.</p>
<h3 id="SavingActivityState">Menyimpan status aktivitas</h3>
<p>Pengantar untuk <a href="#Lifecycle">Mengelola Daur Hidup Aktivitas</a> secara ringkas menyebutkan
bahwa
bila aktivitas dihentikan sementara atau dihentikan, status aktivitas akan dipertahankan. Hal itu terjadi karena
objek {@link android.app.Activity} masih ditahan dalam memori saat aktivitas dihentikan sementara atau
dihentikan&mdash;semua informasi tentang anggota dan statusnya saat ini masih hidup. Jadi, setiap perubahan
yang dibuat pengguna dalam aktivitas akan dipertahankan sehingga bila aktivitas kembali ke
latar depan (bila "dilanjutkan"), perubahan itu masih ada.</p>
<p>Akan tetapi, bila sistem memusnahkan aktivitas untuk memulihkan memori, objek {@link
android.app.Activity} akan dimusnahkan, sehingga sistem tidak bisa sekadar melanjutkan aktivitas dengan status
tidak berubah. Sebagai gantinya, sistem harus membuat ulang objek {@link android.app.Activity} jika pengguna
menyusuri kembali ke aktivitas tersebut. Namun, pengguna tidak menyadari
bahwa sistem memusnahkan aktivitas dan membuatnya kembali dan, karena itu, mungkin
mengharapkan aktivitas untuk sama persis dengan sebelumnya. Dalam situasi ini, Anda bisa memastikan bahwa
informasi penting tentang status aktivitas tetap terjaga dengan mengimplementasikan
metode callback tambahan yang memungkinkan Anda menyimpan informasi tentang status aktivitas: {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()}.</p>
<p>Sistem memanggil {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
sebelum membuat aktivitas rawan terhadap pemusnahan. Sistem meneruskan ke metode ini
sebuah {@link android.os.Bundle} tempat Anda bisa menyimpan
informasi status tentang aktivitas sebagai pasangan nama-nilai, dengan menggunakan metode-metode misalnya {@link
android.os.Bundle#putString putString()} dan {@link
android.os.Bundle#putInt putInt()}. Kemudian, jika sistem mematikan proses aplikasi Anda
dan pengguna menyusuri kembali ke aktivitas tersebut, sistem akan membuat kembali aktivitas dan meneruskan
{@link android.os.Bundle} ke {@link android.app.Activity#onCreate onCreate()} maupun {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}. Dengan menggunakan salah satu
metode ini, Anda bisa mengekstrak status tersimpan dari {@link android.os.Bundle} dan memulihkan
status aktivitas. Jika tidak ada informasi status untuk dipulihkan, maka {@link
android.os.Bundle} yang diteruskan kepada adalah Anda null (yang akan terjadi bila aktivitas dibuat untuk
pertama kali).</p>
<img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" />
<p class="img-caption"><strong>Gambar 2.</strong> Ada dua cara yang bisa digunakan aktivitas untuk kembali ke fokus pengguna
dengan status tetap: aktivitas dimusnahkan, kemudian dibuat kembali, dan aktivitas harus memulihkan
status yang disimpan sebelumnya, atau aktivitas dihentikan, kemudian dilanjutkan dengan status aktivitas
tetap.</p>
<p class="note"><strong>Catatan:</strong> Tidak ada jaminan bahwa {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} akan dipanggil sebelum
aktivitas Anda dimusnahkan, karena bisa saja terjadi aktivitas tidak perlu menyimpan status
(misalnya saat pengguna meninggalkan aktivitas Anda dengan menggunakan tombol <em>Back</em>, karena pengguna menutup aktivitas
secara eksplisit
). Jika sistem memanggil {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()}, ini akan dilakukan sebelum {@link
android.app.Activity#onStop onStop()} dan mungkin sebelum {@link android.app.Activity#onPause
onPause()}.</p>
<p>Akan tetapi, sekalipun Anda tidak melakukan apa-apa dan tidak mengimplementasikan {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()}, beberapa status aktivitas
akan dipulihkan oleh implementasi default {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} dalam kelas {@link android.app.Activity}. Khususnya,
implementasi default akan memanggil metode {@link
android.view.View#onSaveInstanceState onSaveInstanceState()} yang sesuai untuk setiap {@link
android.view.View} dalam layout, yang memungkinkan setiap tampilan untuk memberi informasi tentang dirinya
yang harus disimpan. Hampir setiap widget dalam kerangka kerja Android mengimplementasikan metode ini
sebagaimana mestinya, sehingga setiap perubahan yang terlihat pada UI akan disimpan dan dipulihkan secara otomatis bila
aktivitas Anda dibuat kembali. Misalnya, widget {@link android.widget.EditText} menyimpan teks apa saja
yang dimasukkan oleh pengguna dan widget {@link android.widget.CheckBox} menyimpan baik teks itu diperiksa maupun
tidak. Satu-satunya pekerjaan yang Anda perlukan adalah memberikan ID unik (dengan atribut <a href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a>
) untuk masing-masing widget yang ingin disimpan statusnya. Jika widget tidak memiliki ID, maka sistem
tidak bisa menyimpan statusnya.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>Anda juga bisa menghentikan secara eksplisit sebuah tampilan dalam layout Anda agar tidak menyimpan statusnya dengan mengatur atribut
{@link android.R.attr#saveEnabled android:saveEnabled} ke {@code "false"} atau dengan memanggil
metode {@link android.view.View#setSaveEnabled setSaveEnabled()}. Biasanya, Anda tidak boleh
menonaktifkannya, namun Anda boleh melakukannya jika ingin memulihkan status UI aktivitas secara berbeda.</p>
</div>
</div>
<p>Walaupun implementasi default {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} menyimpan informasi yang berguna tentang
UI aktivitas, Anda mungkin masih perlu mengesampingkannya untuk menyimpan informasi tambahan.
Misalnya, Anda mungkin perlu menyimpan nilai-nilai anggota yang berubah selama masa pakai aktivitas (yang
mungkin berkorelasi dengan nilai-nilai yang dipulihkan dalam UI, namun anggota-anggota yang menyimpan nilai-nilai UI itu tidak
dipulihkan, secara default).</p>
<p>Karena implementasi default {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} membantu menyimpan status UI, jika
Anda mengesampingkan metode ini untuk menyimpan informasi tambahan status, Anda harus selalu memanggil
implementasi superkelas {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
sebelum melakukan pekerjaan apa pun. Demikian pula, Anda juga harus memanggil implementasi superkelas {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} jika Anda mengesampingkannya, sehingga
implementasi default bisa memulihkan status tampilan.</p>
<p class="note"><strong>Catatan:</strong> Karena {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()} tidak dijamin
akan dipanggil, Anda harus menggunakannya hanya untuk mencatat status aktivitas sementara (transient) (status
UI)&mdash;Anda tidak boleh menggunakannya untuk menyimpan data persisten. Sebagai gantinya, Anda harus menggunakan {@link
android.app.Activity#onPause onPause()} untuk menyimpan data persisten (misalnya data yang harus disimpan
ke database) saat pengguna meninggalkan aktivitas.</p>
<p>Salah satu cara yang baik untuk menguji kemampuan aplikasi dalam memulihkan statusnya adalah cukup dengan memutar
perangkat sehingga orientasi layarnya berubah. Bila orientasi layar berubah, sistem
akan memusnahkan dan membuat kembali aktivitas untuk menerapkan sumber daya alternatif yang mungkin tersedia
untuk konfigurasi layar baru. Karena alasan ini saja, sangat penting bahwa aktivitas Anda
memulihkan statusnya secara lengkap saat dibuat kembali, karena pengguna memutar layar secara rutin saat
menggunakan aplikasi.</p>
<h3 id="ConfigurationChanges">Menangani perubahan konfigurasi</h3>
<p>Sebagian konfigurasi perangkat bisa berubah saat runtime (misalnya orientasi layar, ketersediaan keyboard
, dan bahasa). Bila terjadi perubahan demikian, Android akan membuat kembali aktivitas yang berjalan
(sistem akan memanggil {@link android.app.Activity#onDestroy}, kemudian segera memanggil {@link
android.app.Activity#onCreate onCreate()}). Perilaku ini
didesain untuk membantu aplikasi Anda menyesuaikan diri dengan konfigurasi baru dengan cara memuat ulang
aplikasi Anda secara otomatis dengan sumber daya alternatif yang telah Anda sediakan (misalnya layout yang berbeda untuk
layar orientasi dan ukuran yang berbeda).</p>
<p>Jika Anda mendesain aktivitas dengan benar untuk menangani restart karena perubahan orientasi layar dan
memulihkan status aktivitas seperti yang dijelaskan di atas, aplikasi Anda akan lebih tahan terhadap
kejadian tidak terduga lainnya dalam daur hidup aktivitas.</p>
<p>Cara terbaik menangani restart tersebut adalah
menyimpan dan memulihkan status aktivitas Anda dengan menggunakan {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} dan {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} (atau {@link
android.app.Activity#onCreate onCreate()}), seperti yang dibahas di bagian sebelumnya.</p>
<p>Untuk informasi selengkapnya tentang konfigurasi perubahan yang terjadi saat program berjalan dan cara menanganinya
, bacalah panduan untuk <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Menangani
Perubahan Runtime</a>.</p>
<h3 id="CoordinatingActivities">Mengoordinasikan aktivitas</h3>
<p>Bila suatu aktivitas memulai aktivitas lain, keduanya akan mengalami transisi daur hidup. Aktivitas pertama
akan berhenti sementara dan berhenti sama sekali (walau tidak akan berhenti jika masih terlihat di latar belakang), saat
aktivitas lain dibuat. Jika aktivitas-aktivitas ini berbagi data yang disimpan ke disk atau di tempat lain, Anda perlu
memahami bahwa aktivitas pertama tidak dihentikan sepenuhnya sebelum aktivitas kedua dibuat.
Sebagai gantinya, proses akan memulai aktivitas kedua secara tumpang tindih dengan proses penghentian
aktivitas pertama.</p>
<p>Urutan callback daur hidup didefinisikan dengan baik, khususnya bila kedua aktivitas berada dalam
proses yang sama dan salah satunya memulai yang lain. Berikut ini adalah urutan operasi yang terjadi bila Aktivitas
A memulai Aktivitas B: </p>
<ol>
<li>Metode {@link android.app.Activity#onPause onPause()} Aktivitas A berjalan.</li>
<li>Metode-metode {@link android.app.Activity#onCreate onCreate()}, {@link
android.app.Activity#onStart onStart()}, dan {@link android.app.Activity#onResume onResume()}
Aktivitas B berjalan secara berurutan. (Aktivitas B sekarang mendapatkan fokus pengguna.)</li>
<li>Kemudian, jika Aktivitas A tidak lagi terlihat di layar, metode {@link
android.app.Activity#onStop onStop()}-nya akan dijalankan.</li>
</ol>
<p>Urutan callback daur hidup yang bisa diramalkan ini memungkinkan Anda mengelola transisi
informasi dari satu aktivitas ke aktivitas lainnya. Misalnya, jika Anda harus menulis ke database saat
aktivitas pertama berhenti agar aktivitas berikutnya bisa membacanya, maka Anda harus menulis ke
database selama {@link android.app.Activity#onPause onPause()} sebagai ganti selama {@link
android.app.Activity#onStop onStop()}.</p>
<!--
<h2>Beginner's Path</h2>
<p>For more information about how Android maintains a history of activities and
enables user multitasking, continue with the <b><a
href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back
Stack</a></b> document.</p>
-->

View File

@@ -0,0 +1,658 @@
page.title=Layanan Terikat
parent.title=Layanan
parent.link=services.html
@jd:body
<div id="qv-wrapper">
<ol id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Basics">Dasar-Dasar</a></li>
<li><a href="#Creating">Membuat Layanan Terikat</a>
<ol>
<li><a href="#Binder">Memperluas kelas Binder</a></li>
<li><a href="#Messenger">Menggunakan Messenger</a></li>
</ol>
</li>
<li><a href="#Binding">Mengikat ke Layanan</a></li>
<li><a href="#Lifecycle">Mengelola Daur Hidup Layanan Terikat</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Service}</li>
<li>{@link android.content.ServiceConnection}</li>
<li>{@link android.os.IBinder}</li>
</ol>
<h2>Contoh</h2>
<ol>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
RemoteService}</a></li>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
LocalService}</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}guide/components/services.html">Layanan</a></li>
</ol>
</div>
<p>Layanan terikat adalah server di antarmuka klien-server. Layanan terikat memungkinkan komponen-komponen
(seperti aktivitas) untuk diikat ke layanan, mengirim permintaan, menerima respons, dan bahkan melakukan
komunikasi antarproses (IPC). Layanan terikat biasanya hidup hanya saat melayani
komponen aplikasi lain dan tidak berjalan di latar belakang terus-menerus.</p>
<p>Dokumen ini menampilkan cara membuat layanan terikat, termasuk cara mengikat
ke layanan dari komponen aplikasi lain. Akan tetapi, Anda juga harus mengacu dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a> untuk
informasi tambahan tentang layanan secara umum, seperti cara menyampaikan pemberitahuan dari layanan, mengatur
layanan agar berjalan di latar depan, dan lain-lain.</p>
<h2 id="Basics">Dasar-Dasar</h2>
<p>Layanan terikat adalah implementasi kelas {@link android.app.Service} yang memungkinkan
aplikasi lain diikat padanya dan berinteraksi dengannya. Untuk menyediakan pengikatan bagi sebuah
layanan, Anda harus mengimplementasikan metode callback {@link android.app.Service#onBind onBind()}. Metode ini
menghasilkan objek {@link android.os.IBinder} yang mendefinisikan antarmuka pemprograman yang
bisa digunakan klien untuk berinteraksi dengan layanan.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Mengikat ke Layanan yang Sudah Dimulai</h3>
<p>Seperti dibahas dalam dokumen <a href="{@docRoot}guide/components/services.html">Layanan</a>
, Anda bisa membuat layanan yang dimulai sekaligus diikat. Yakni, layanan bisa
dimulai dengan memanggil {@link android.content.Context#startService startService()}, yang memungkinkan
layanan berjalan terus-menerus, dan juga membolehkan klien untuk mengikat ke layanan dengan memanggil {@link
android.content.Context#bindService bindService()}.
<p>Jika Anda mengizinkan layanan dimulai dan diikat, lalu ketika layanan telah
dimulai, sistem <em>tidak</em> menghapus layanan ketika semua klien melepas ikatan. Sebagai gantinya, Anda harus
menghentikan layanan secara eksplisit, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}.</p>
<p>Walaupun Anda biasanya harus mengimplementasikan {@link android.app.Service#onBind onBind()}
<em>atau</em> {@link android.app.Service#onStartCommand onStartCommand()}, kadang-kadang perlu
mengimplementasikan keduanya. Misalnya, sebuah pemutar musik bisa merasakan manfaatnya karena layanannya boleh berjalan
terus-menerus dan juga menyediakan pengikatan. Dengan cara ini, sebuah aktivitas bisa memulai layanan untuk memutar beberapa
lagu dan musik terus dimainkan sekalipun pengguna meninggalkan aplikasi. Lalu, bila pengguna
kembali ke aplikasi, aktivitas bisa mengikat ke layanan untuk mendapatkan kembali kontrol atas pemutaran.</p>
<p>Pastikan membaca bagian tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan
Terikat</a>, untuk informasi selengkapnya tentang daur hidup layanan saat menambahkan pengikatan ke
layanan yang sudah dimulai.</p>
</div>
</div>
<p>Klien bisa mengikat ke layanan dengan memanggil {@link android.content.Context#bindService
bindService()}. Bila itu dilakukan, klien harus menyediakan implementasi {@link
android.content.ServiceConnection}, yang memantau koneksi dengan layanan. Metode {@link
android.content.Context#bindService bindService()} kembali dengan serta-merta tanpa sebuah nilai, namun
bila sistem Android membuat koneksi antara klien
dan layanan, sistem akan memanggil {@link
android.content.ServiceConnection#onServiceConnected onServiceConnected()} pada {@link
android.content.ServiceConnection} untuk mengirim {@link android.os.IBinder} yang
bisa digunakan klien untuk berkomunikasi dengan layanan.</p>
<p>Beberapa klien bisa terhubung ke layanan dengan serentak. Akan tetapi, sistem akan memanggil metode
{@link android.app.Service#onBind onBind()} layanan Anda untuk mengambil {@link android.os.IBinder} hanya
bila klien pertama mengikat. Sistem lalu memberikan {@link android.os.IBinder} yang sama ke setiap
klien tambahan yang mengikat, tanpa memanggil {@link android.app.Service#onBind onBind()} lagi.</p>
<p>Bila klien terakhir melepas ikatan dari layanan, sistem akan menghapus layanan (kecuali jika
layanan juga dimulai oleh {@link android.content.Context#startService startService()}).</p>
<p>Bila Anda mengimplementasikan layanan terikat, yang terpenting adalah mendefinisikan antarmuka
yang dihasilkan metode callback {@link android.app.Service#onBind onBind()} Anda. Ada sedikit
cara mendefinisikan antarmuka {@link android.os.IBinder} layanan Anda dan bagian berikut
akan membahas masing-masing teknik.</p>
<h2 id="Creating">Membuat Layanan Terikat</h2>
<p>Saat membuat layanan yang menyediakan pengikatan, Anda harus menyediakan {@link android.os.IBinder}
yang menyediakan antarmuka pemrograman yang bisa digunakan klien untuk berinteraksi dengan layanan. Ada
tiga cara untuk mendefinisikan antarmuka:</p>
<dl>
<dt><a href="#Binder">Memperluas kelas Binder</a></dt>
<dd>Jika layanan Anda bersifat privat untuk aplikasi Anda sendiri dan berjalan dalam proses yang sama dengan klien
(biasanya), Anda harus membuat antarmuka dengan memperluas kelas {@link android.os.Binder}
dan menghasilkan instance dari
{@link android.app.Service#onBind onBind()}. Klien akan menerima {@link android.os.Binder} dan
bisa menggunakannya untuk mengakses langsung metode publik yang tersedia dalam implementasi {@link android.os.Binder}
atau bahkan {@link android.app.Service}.
<p>Inilah teknik yang lebih disukai bila layanan Anda sekadar pekerja latar belakang untuk aplikasi Anda
sendiri. Satu-satunya alasan tidak membuat antarmuka dengan cara ini adalah karena
layanan Anda akan digunakan oleh aplikasi lain atau pada proses-proses terpisah.</dd>
<dt><a href="#Messenger">Menggunakan Messenger</a></dt>
<dd>Jika antarmuka Anda perlu bekerja lintas proses, Anda bisa membuat
antarmuka untuk layanan dengan {@link android.os.Messenger}. Dengan cara ini, layanan
mendefinisikan {@link android.os.Handler} yang akan merespons aneka tipe objek {@link
android.os.Message}. {@link android.os.Handler}
ini adalah dasar bagi {@link android.os.Messenger} yang nanti bisa berbagi {@link android.os.IBinder}
dengan klien, sehingga memungkinkan klien mengirim perintah ke layanan dengan menggunakan objek {@link
android.os.Message}. Selain itu, klien bisa mendefinisikan sendiri {@link android.os.Messenger}
sehingga layanan bisa mengirim balik pesan.
<p>Inilah cara termudah melakukan komunikasi antarproses (IPC), karena {@link
android.os.Messenger} akan mengantre semua permintaan ke dalam satu thread sehingga Anda tidak perlu mendesain
layanan agar thread-safe.</p>
</dd>
<dt>Menggunakan AIDL</dt>
<dd>AIDL (Android Interface Definition Language) melakukan semua pekerjaan untuk mengurai objek menjadi
primitif yang bisa dipahami dan diarahkan oleh sistem operasi ke berbagai proses untuk melakukan
IPC. Teknik sebelumnya, dengan menggunakan {@link android.os.Messenger}, sebenarnya berdasarkan AIDL sebagai
struktur yang mendasarinya. Seperti disebutkan di atas, {@link android.os.Messenger} membuat antrean
semua permintaan klien dalam satu thread, sehingga layanan akan menerima permintaan satu per satu. Akan tetapi,
jika ingin layanan Anda menangani beberapa permintaan sekaligus, Anda bisa menggunakan AIDL
secara langsung. Dalam hal ini, layanan Anda harus mampu multi-thread dan dibuat thread-safe.
<p>Untuk menggunakan AIDL secara langsung, Anda harus
membuat file {@code .aidl} yang mendefinisikan antarmuka pemrograman. Alat Android SDK menggunakan
file ini untuk menghasilkan kelas abstrak yang mengimplementasikan antarmuka dan menangani IPC, yang nanti
bisa Anda perluas dalam layanan.</p>
</dd>
</dl>
<p class="note"><strong>Catatan:</strong> Umumnya aplikasi <strong>tidak boleh</strong> menggunakan AIDL untuk
membuat layanan terikat, karena hal itu mungkin memerlukan kemampuan multi-thread dan
bisa mengakibatkan implementasi yang lebih rumit. Dengan demikian, AIDL tidak cocok untuk sebagian besar aplikasi
dan dokumen ini tidak membahas cara menggunakannya untuk layanan Anda. Jika Anda yakin perlu
menggunakan AIDL secara langsung, lihat dokumen <a href="{@docRoot}guide/components/aidl.html">AIDL</a>
.</p>
<h3 id="Binder">Memperluas kelas Binder</h3>
<p>Jika layanan Anda hanya digunakan oleh aplikasi lokal dan tidak perlu bekerja lintas proses,
maka Anda bisa mengimplementasikan kelas {@link android.os.Binder} Anda sendiri yang memberi klien Anda
akses langsung ke metode publik dalam layanan.</p>
<p class="note"><strong>Catatan:</strong> Hal ini hanya berhasil jika klien dan layanan berada dalam
aplikasi dan proses yang sama, suatu kondisi yang paling umum. Misalnya, cara ini sangat cocok untuk sebuah aplikasi musik
yang perlu mengikat aktivitas ke layanannya sendiri, yakni memutar musik di
latar belakang.</p>
<p>Berikut cara menyiapkannya:</p>
<ol>
<li>Dalam layanan Anda, buat sebuah instance {@link android.os.Binder} yang:
<ul>
<li>berisi metode publik yang bisa dipanggil klien</li>
<li>menghasilkan instance {@link android.app.Service} saat ini, yang memiliki metode publik yang
bisa dipanggil klien</li>
<li>atau, menghasilkan instance kelas lain yang host-nya di layanan dengan metode publik yang
bisa dipanggil klien</li>
</ul>
<li>Hasilkan instance {@link android.os.Binder} ini dari metode callback {@link
android.app.Service#onBind onBind()}.</li>
<li>Di klien, terima {@link android.os.Binder} dari metode callback {@link
android.content.ServiceConnection#onServiceConnected onServiceConnected()} dan
buat panggilan ke layanan terikat dengan menggunakan metode yang disediakan.</li>
</ol>
<p class="note"><strong>Catatan:</strong> Alasan layanan dan klien harus berada dalam aplikasi yang sama
adalah agar klien bisa mengkonversi objek yang dihasilkan dan memanggil API-nya dengan benar. Layanan
dan klien juga harus berada dalam proses yang sama, karena teknik ini tidak melakukan
pengarahan (marshalling) apa pun untuk lintas proses.</p>
<p>Misalnya, berikut ini adalah layanan yang memberi klien akses ke metode-metode dalam layanan melalui
implementasi {@link android.os.Binder}:</p>
<pre>
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
&#64;Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
</pre>
<p>{@code LocalBinder} menyediakan {@code getService()} metode bagi klien untuk mengambil
instance {@code LocalService} saat ini. Cara ini memungkinkan klien memanggil metode publik dalam
layanan. Misalnya, klien bisa memanggil {@code getRandomNumber()} dari layanan.</p>
<p>Berikut ini adalah aktivitas yang mengikat ke {@code LocalService} dan memanggil {@code getRandomNumber()}
bila tombol diklik:</p>
<pre>
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
&#64;Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
&#64;Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
&#64;Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
&#64;Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
</pre>
<p>Contoh di atas menampilkan cara klien mengikat ke layanan dengan menggunakan implementasi
{@link android.content.ServiceConnection} dan callback {@link
android.content.ServiceConnection#onServiceConnected onServiceConnected()}. Bagian
berikut menyediakan informasi selengkapnya tentang proses pengikatan ke layanan.</p>
<p class="note"><strong>Catatan:</strong> Contoh di atas tidak secara eksplisit melepas ikatan dari layanan,
namun semua klien harus melepas ikatan pada waktu yang tepat (seperti saat aktivitas sedang jeda).</p>
<p>Untuk contoh kode selengkapnya, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
LocalService.java}</a> dan kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code
LocalServiceActivities.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
<h3 id="Messenger">Menggunakan Messenger</h3>
<div class="sidebox-wrapper">
<div class="sidebox">
<h4>Dibandingkan dengan AIDL</h4>
<p>Bila Anda perlu melakukan IPC, menggunakan {@link android.os.Messenger} untuk antarmuka
lebih sederhana daripada mengimplementasikannya dengan AIDL, karena {@link android.os.Messenger} mengantre
semua panggilan ke layanan, sementara antarmuka AIDL murni mengirim permintaan serentak ke
layanan, yang nanti harus menangani multi-threading.</p>
<p>Untuk sebagian besar aplikasi, layanan tidak perlu melakukan multi-threading, jadi dengan menggunakan {@link
android.os.Messenger} memungkinkan layanan menangani panggilan satu per satu. Jika
layanan harus multi-thread, Anda harus menggunakan <a href="{@docRoot}guide/components/aidl.html">AIDL</a> untuk mendefinisikan antarmuka.</p>
</div>
</div>
<p>Jika layanan perlu berkomunikasi dengan proses jauh, Anda bisa menggunakan
{@link android.os.Messenger} untuk menyediakan antarmuka bagi layanan Anda. Teknik ini memungkinkan
Anda melakukan komunikasi antarproses (IPC) tanpa harus menggunakan AIDL.</p>
<p>Berikut ini rangkuman cara menggunakan {@link android.os.Messenger}:</p>
<ul>
<li>Layanan mengimplementasikan {@link android.os.Handler} yang menerima callback untuk tiap
panggilan dari klien.</li>
<li>{@link android.os.Handler} digunakan untuk membuat objek {@link android.os.Messenger}
(yang merupakan acuan ke {@link android.os.Handler}).</li>
<li>{@link android.os.Messenger} membuat {@link android.os.IBinder} yang
dikembalikan layanan ke klien dari {@link android.app.Service#onBind onBind()}.</li>
<li>Klien menggunakan {@link android.os.IBinder} untuk membuat instance {@link android.os.Messenger}
(yang mengacu {@link android.os.Handler} layanan), yang digunakan klien untuk mengirim
objek {@link android.os.Message} ke layanan.</li>
<li>Layanan menerima setiap {@link android.os.Message} dalam {@link
android.os.Handler}&mdash;secara spesifik, dalam metode {@link android.os.Handler#handleMessage
handleMessage()}.</li>
</ul>
<p>Dengan cara ini, tidak ada "metode" untuk dipanggil klien pada layanan. Sebagai gantinya,
klien mengirim "pesan" (objek-objek {@link android.os.Message}) yang diterima layanan dalam
{@link android.os.Handler}-nya.</p>
<p>Berikut ini contoh layanan sederhana yang menggunakan antarmuka {@link android.os.Messenger}:</p>
<pre>
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
&#64;Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
&#64;Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
</pre>
<p>Perhatikan bahwa metode {@link android.os.Handler#handleMessage handleMessage()} dalam
{@link android.os.Handler} adalah tempat layanan menerima {@link android.os.Message}
yang masuk dan memutuskan aksi yang harus dilakukan, berdasarkan anggota {@link android.os.Message#what}.</p>
<p>Klien tinggal membuat {@link android.os.Messenger} berdasarkan {@link
android.os.IBinder} yang dihasilkan layanan dan mengirim pesan menggunakan {@link
android.os.Messenger#send send()}. Misalnya, berikut ini adalah aktivitas sederhana yang mengikat ke
layanan dan mengirim pesan {@code MSG_SAY_HELLO} ke layanan:</p>
<pre>
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
&#64;Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
&#64;Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
</pre>
<p>Perhatikan bahwa contoh ini tidak menampilkan cara layanan merespons klien. Jika ingin
layanan merespons, Anda juga perlu membuat {@link android.os.Messenger} di klien. Lalu
saat menerima callback {@link android.content.ServiceConnection#onServiceConnected
onServiceConnected()}, klien akan mengirim {@link android.os.Message} ke layanan yang berisi
{@link android.os.Messenger} klien dalam parameter {@link android.os.Message#replyTo}
metode {@link android.os.Messenger#send send()}.</p>
<p>Anda bisa melihat contoh cara menyediakan pertukaran pesan dua arah dalam contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
MessengerService.java}</a> (layanan) dan <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
MessengerServiceActivities.java}</a> (klien).</p>
<h2 id="Binding">Mengikat ke Layanan</h2>
<p>Komponen-komponen aplikasi (klien) bisa mengikat ke layanan dengan memanggil
{@link android.content.Context#bindService bindService()}. Sistem Android
lalu memanggil metode {@link android.app.Service#onBind
onBind()} layanan, yang menghasilkan {@link android.os.IBinder} untuk berinteraksi dengan layanan.</p>
<p>Pengikatan ini bersifat asinkron. {@link android.content.Context#bindService
bindService()} segera kembali dan <em>tidak</em> mengembalikan {@link android.os.IBinder} ke
klien. Untuk menerima {@link android.os.IBinder}, klien harus membuat instance {@link
android.content.ServiceConnection} dan meneruskannya ke {@link android.content.Context#bindService
bindService()}. {@link android.content.ServiceConnection} berisi metode callback yang
dipanggil sistem untuk mengirim {@link android.os.IBinder}.</p>
<p class="note"><strong>Catatan:</strong> Hanya aktivitas, layanan, dan penyedia konten yang bisa mengikat
ke layanan yang&mdash;Anda <strong>tidak bisa</strong> ikat ke layanan dari penerima siaran.</p>
<p>Jadi, untuk mengikat ke layanan dari klien, Anda harus: </p>
<ol>
<li>Mengimplementasikan {@link android.content.ServiceConnection}.
<p>Implementasi Anda harus mengesampingkan dua metode callback:</p>
<dl>
<dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt>
<dd>Sistem memanggil ini untuk mengirim {@link android.os.IBinder} yang dihasilkan oleh
metode {@link android.app.Service#onBind onBind()} layanan.</dd>
<dt>{@link android.content.ServiceConnection#onServiceDisconnected
onServiceDisconnected()}</dt>
<dd>Sistem Android memanggil ini bila koneksi ke layanan putus
tanpa terduga, seperti ketika layanan mengalami crash atau dimatikan. Ini <em>tidak</em> dipanggil ketika
klien melepas ikatan.</dd>
</dl>
</li>
<li>Panggil {@link
android.content.Context#bindService bindService()}, dengan meneruskan implementasi {@link
android.content.ServiceConnection}. </li>
<li>Bila sistem memanggil metode callback {@link android.content.ServiceConnection#onServiceConnected
onServiceConnected()}, Anda bisa mulai membuat panggilan ke layanan, dengan menggunakan
metode yang didefinisikan oleh antarmuka.</li>
<li>Untuk memutus koneksi dari layanan, panggil {@link
android.content.Context#unbindService unbindService()}.
<p>Bila telah dimusnahkan (destroyed), klien Anda akan melepas ikatan dari layanan, namun Anda harus selalu melepas ikatan
bila sudah selesai berinteraksi dengan layanan atau bila aktivitas Anda sedang jeda sehingga layanan bisa
dimatikan saat tidak sedang digunakan. (Waktu yang tepat untuk mengikat dan melepas ikatan dibahas
selengkapnya di bawah ini.)</p>
</li>
</ol>
<p>Misalnya, cuplikan berikut menghubungkan klien ke layanan yang dibuat di atas dengan
<a href="#Binder">memperluas kelas Binder</a>, sehingga tinggal mengkonversi
{@link android.os.IBinder} yang dihasilkan ke kelas {@code LocalService} dan meminta instance {@code
LocalService}:</p>
<pre>
LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Because we have bound to an explicit
// service that is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "onServiceDisconnected");
mBound = false;
}
};
</pre>
<p>Dengan {@link android.content.ServiceConnection} ini, klien bisa mengikat ke layanan dengan meneruskannya
ke {@link android.content.Context#bindService bindService()}. Misalnya:</p>
<pre>
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
</pre>
<ul>
<li>Parameter pertama {@link android.content.Context#bindService bindService()} adalah sebuah
{@link android.content.Intent} yang secara eksplisit menyebutkan layanan yang akan diikat (walaupun intent
boleh implisit).</li>
<li>Parameter kedua adalah objek {@link android.content.ServiceConnection}.</li>
<li>Parameter ketiga adalah tanda (flag) yang menunjukkan opsi pengikatan. Tanda ini biasanya harus {@link
android.content.Context#BIND_AUTO_CREATE} agar dapat membuat layanan jika belum hidup.
Nilai-nilai lain yang memungkinkan adalah {@link android.content.Context#BIND_DEBUG_UNBIND}
dan {@link android.content.Context#BIND_NOT_FOREGROUND}, atau {@code 0} untuk tidak satu pun.</li>
</ul>
<h3>Catatan tambahan</h3>
<p>Berikut ini beberapa catatan penting tentang mengikat ke layanan:</p>
<ul>
<li>Anda harus selalu menjebak eksepsi {@link android.os.DeadObjectException}, yang dilontarkan
bila koneksi terputus. Inilah satu-satunya eksepsi yang dilontarkan oleh metode jauh.</li>
<li>Objek adalah acuan yang dihitung lintas proses. </li>
<li>Anda biasanya harus memasangkan pengikatan dan pelepasan ikatan selama
memasangkan momen membuat dan menghapus daur hidup klien. Misalnya:
<ul>
<li>Jika Anda hanya perlu berinteraksi dengan layanan saat aktivitas terlihat, Anda
harus mengikat selama {@link android.app.Activity#onStart onStart()} dan melepas ikatan selama {@link
android.app.Activity#onStop onStop()}.</li>
<li>Jika Anda ingin aktivitas menerima tanggapan bahkan saat dihentikan di
latar belakang, Anda bisa mengikat selama {@link android.app.Activity#onCreate onCreate()} dan melepas ikatan
selama {@link android.app.Activity#onDestroy onDestroy()}. Berhati-hatilah karena hal ini menyiratkan aktivitas
Anda perlu menggunakan layanan selama dijalankan (sekalipun di latar belakang), jadi jika
layanan berada dalam proses lain, Anda meningkatkan bobot proses dan semakin besar
kemungkinan sistem akan mematikannya.</li>
</ul>
<p class="note"><strong>Catatan:</strong> Anda biasanya <strong>tidak</strong> boleh mengikat dan melepas ikatan
selama {@link android.app.Activity#onResume onResume()} aktivitas Anda dan {@link
android.app.Activity#onPause onPause()}, karena callback ini terjadi pada setiap transisi daur hidup
dan Anda harus menjaga pemrosesan yang terjadi pada transisi ini tetap minim. Juga, jika
banyak aktivitas dalam aplikasi Anda mengikat ke layanan yang sama dan ada transisi antara
dua aktivitas, layanan bisa dimusnahkan dan dibuat lagi sambil aktivitas saat ini melepas ikatan
(selama jeda) sebelum aktivitas berikutnya mengikat (selama lanjutkan). (Transisi aktivitas ini untuk cara
aktivitas mengoordinasikan daur hidupnya dijelaskan dalam dokumen <a href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Aktivitas</a>
.)</p>
</ul>
<p>Untuk contoh kode selengkapnya, yang menampilkan cara mengikat ke layanan, lihat kelas <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
RemoteService.java}</a> dalam <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
<h2 id="Lifecycle">Mengelola Daur Hidup Layanan Terikat</h2>
<p>Bila layanan dilepas ikatannya dari semua klien, sistem Android akan menghapusnya (kecuali jika layanan juga
dimulai dengan {@link android.app.Service#onStartCommand onStartCommand()}). Dengan demikian, Anda tidak harus
mengelola daur hidup layanan jika layanan itu murni sebuah layanan
terikat&mdash;yang dikelola sistem Android untuk Anda berdasarkan apakah layanan terikat ke klien atau tidak.</p>
<p>Akan tetapi, Jika Anda memilih untuk mengimplementasikan metode callback {@link android.app.Service#onStartCommand
onStartCommand()}, maka Anda harus menghentikan layanan secara eksplisit, karena layanan
sekarang dianggap telah <em>dimulai</em>. Dalam hal ini, layanan akan berjalan hingga layanan
menghentikan dirinya sendiri dengan {@link android.app.Service#stopSelf()} atau panggilan komponen lain {@link
android.content.Context#stopService stopService()}, terlepas dari apakah layanan terikat ke
klien atau tidak.</p>
<p>Selain itu, jika layanan Anda telah dimulai dan menerima pengikatan, maka saat sistem memanggil
metode {@link android.app.Service#onUnbind onUnbind()}, Anda bisa memilih untuk mengembalikan
{@code true} jika ingin menerima panggilan ke {@link android.app.Service#onRebind
onRebind()} bila nanti klien mengikat ke layanan (sebagai ganti menerima panggilan ke {@link
android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind
onRebind()} akan menghasilkan void, namun klien tetap menerima {@link android.os.IBinder} dalam callback
{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}.
Di bawah ini adalah gambar 1 yang mengilustrasikan logika untuk jenis daur hidup ini.</p>
<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Daur hidup untuk layanan yang dimulai
dan juga memungkinkan pengikatan.</p>
<p>Untuk informasi selengkapnya tentang daur hidup layanan yang telah dimulai, lihat dokumen <a href="{@docRoot}guide/components/services.html#Lifecycle">Layanan</a>.</p>

View File

@@ -0,0 +1,812 @@
page.title=Fragmen
parent.title=Aktivitas
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Design">Filosofi Desain</a></li>
<li><a href="#Creating">Membuat Fragmen</a>
<ol>
<li><a href="#UI">Menambahkan antarmuka pengguna</a></li>
<li><a href="#Adding">Menambahkan fragmen ke aktivitas</a></li>
</ol>
</li>
<li><a href="#Managing">Mengelola Fragmen</a></li>
<li><a href="#Transactions">Melakukan Transaksi Fragmen</a></li>
<li><a href="#CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</a>
<ol>
<li><a href="#EventCallbacks">Membuat callback kejadian pada aktivitas</a></li>
<li><a href="#ActionBar">Menambahkan item ke Action-Bar</a></li>
</ol>
</li>
<li><a href="#Lifecycle">Menangani Daur Hidup Fragmen</a>
<ol>
<li><a href="#CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</a></li>
</ol>
</li>
<li><a href="#Example">Contoh</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Fragment}</li>
<li>{@link android.app.FragmentManager}</li>
<li>{@link android.app.FragmentTransaction}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}training/basics/fragments/index.html">Membangun UI Dinamis dengan Fragmen</a></li>
<li><a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet
dan Handset</a></li>
</ol>
</div>
</div>
<p>{@link android.app.Fragment} mewakili perilaku atau bagian dari antarmuka pengguna dalam
{@link android.app.Activity}. Anda bisa mengombinasikan beberapa fragmen dalam satu aktivitas untuk membangun UI
multipanel dan menggunakan kembali sebuah fragmen dalam beberapa aktivitas. Anda bisa menganggap fragmen sebagai bagian
modular dari aktivitas, yang memiliki daur hidup sendiri, menerima kejadian input sendiri, dan
yang bisa Anda tambahkan atau hapus saat aktivitas berjalan (semacam "sub aktivitas" yang
bisa digunakan kembali dalam aktivitas berbeda).</p>
<p>Fragmen harus selalu tertanam dalam aktivitas dan daur hidup fragmen secara langsung
dipengaruhi oleh daur hidup aktivitas host-nya. Misalnya, saat aktivitas dihentikan sementara,
semua fragmen di dalamnya juga dihentikan sementara, dan bila aktivitas dimusnahkan, semua fragmen juga demikian. Akan tetapi, saat
aktivitas berjalan (dalam <a href="{@docRoot}guide/components/activities.html#Lifecycle">status daur hidup</a> <em>dilanjutkan</em>, Anda bisa
memanipulasi setiap fragmen secara terpisah, seperti menambah atau menghapusnya. Saat melakukan transaksi
fragmen, Anda juga bisa menambahkannya ke back-stack yang dikelola oleh aktivitas
&mdash;setiap entri back-stack merupakan record transaksi fragmen yang
terjadi. Dengan back-stack pengguna dapat membalikkan transaksi fragmen (mengarah mundur),
dengan menekan tombol <em>Back</em>.</p>
<p>Bila Anda menambahkan fragmen sebagai bagian dari layout aktivitas, fragmen itu berada dalam {@link
android.view.ViewGroup} di hierarki tampilan aktivitas tersebut dan fragmen mendefinisikan
layout
tampilannya sendiri. Anda bisa menyisipkan fragmen ke dalam layout aktivitas dengan mendeklarasikan fragmen dalam file layout aktivitas
, sebagai elemen {@code &lt;fragment&gt;}, atau dari kode aplikasi dengan menambahkannya ke
{@link android.view.ViewGroup} yang ada. Akan tetapi, fragmen tidak harus menjadi bagian dari
layout aktivitas; Anda juga bisa menggunakan fragmen tanpa UI-nya sendiri sebagai pekerja tak terlihat untuk
aktivitas tersebut.</p>
<p>Dokumen ini menjelaskan cara membangun aplikasi menggunakan fragmen, termasuk
cara fragmen mempertahankan statusnya bila ditambahkan ke back-stack aktivitas, berbagi
kejadian dengan aktivitas, dan fragmen lain dalam aktivitas, berkontribusi pada action-bar
aktivitas, dan lainnya.</p>
<h2 id="Design">Filosofi Desain</h2>
<p>Android memperkenalkan fragmen di Android 3.0 (API level 11), terutama untuk mendukung desain UI yang lebih
dinamis dan fleksibel pada layar besar, seperti tablet. Karena
layar tablet jauh lebih besar daripada layar handset, maka lebih banyak ruang untuk mengombinasikan dan
bertukar komponen UI. Fragmen memungkinkan desain seperti itu tanpa perlu mengelola perubahan
kompleks pada hierarki tampilan. Dengan membagi layout aktivitas menjadi beberapa fragmen, Anda bisa
mengubah penampilan aktivitas saat runtime dan mempertahankan perubahan itu di back-stack
yang dikelola oleh aktivitas.</p>
<p>Misalnya, aplikasi berita bisa menggunakan satu fragmen untuk menampilkan daftar artikel di
sebelah kiri dan fragmen lainnya untuk menampilkan artikel di sebelah kanan&mdash;kedua fragmen ini muncul di satu
aktivitas, berdampingan, dan masing-masing fragmen memiliki serangkaian metode callback daur hidup dan menangani kejadian input
penggunanya sendiri. Sehingga, sebagai ganti menggunakan satu aktivitas untuk memilih
artikel dan aktivitas lainnya untuk membaca artikel, pengguna bisa memilih artikel dan membaca semuanya dalam
aktivitas yang sama, sebagaimana diilustrasikan dalam layout tablet pada gambar 1.</p>
<p>Anda harus mendesain masing-masing fragmen sebagai komponen aktivitas modular dan bisa digunakan kembali. Yakni, karena
setiap fragmen mendefinisikan layoutnya dan perilakunya dengan callback daur hidupnya sendiri, Anda bisa memasukkan
satu fragmen dalam banyak aktivitas, sehingga Anda harus mendesainnya untuk digunakan kembali dan mencegah
memanipulasi satu fragmen dari fragmen lain secara langsung. Ini terutama penting karena dengan
fragmen modular Anda bisa mengubah kombinasi fragmen untuk ukuran layar berbeda. Saat mendesain aplikasi
untuk mendukung tablet maupun handset, Anda bisa menggunakan kembali fragmen dalam
konfigurasi layout berbeda untuk mengoptimalkan pengalaman pengguna berdasarkan ruang layar yang tersedia. Misalnya
, pada handset, fragmen mungkin perlu dipisahkan untuk menyediakan UI panel tunggal
bila lebih dari satu yang tidak cocok dalam aktivitas yang sama.</p>
<img src="{@docRoot}images/fundamentals/fragments.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Contoh cara dua modul UI yang didefinisikan oleh
fragmen bisa digabungkan ke dalam satu aktivitas untuk desain tablet, namun dipisahkan untuk
desain handset.</p>
<p>Misalnya&mdash;untuk melanjutkan contoh aplikasi berita&mdash; aplikasi bisa menanamkan
dua fragmen dalam <em>Aktivitas A</em>, saat berjalan pada perangkat berukuran tablet. Akan tetapi, pada
layar berukuran handset, ruang untuk kedua fragmen tidak cukup, sehingga <em>Aktivitas A</em> hanya
menyertakan fragmen untuk daftar artikel, dan saat pengguna memilih artikel,
<em>Aktivitas B</em> akan dimulai, termasuk fragmen kedua untuk membaca artikel. Sehingga, aplikasi mendukung
tablet dan handset dengan menggunakan kembali fragmen dalam kombinasi berbeda, seperti diilustrasikan dalam
gambar 1.</p>
<p>Untuk informasi selengkapnya tentang mendesain aplikasi menggunakan kombinasi fragmen berbeda
untuk konfigurasi layar berbeda, lihat panduan untuk <a href="{@docRoot}guide/practices/tablets-and-handsets.html">Mendukung Tablet dan Handset</a>.</p>
<h2 id="Creating">Membuat Fragmen</h2>
<div class="figure" style="width:327px">
<img src="{@docRoot}images/fragment_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup fragmen (saat
aktivitasnya berjalan).</p>
</div>
<p>Untuk membuat fragmen, Anda harus membuat subkelas {@link android.app.Fragment} (atau
subkelasnya yang ada). Kelas {@link android.app.Fragment} memiliki kode yang mirip seperti
{@link android.app.Activity}. Kelas ini memiliki metode callback yang serupa dengan aktivitas, seperti
{@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()},
{@link android.app.Fragment#onPause onPause()}, dan {@link android.app.Fragment#onStop onStop()}. Sebenarnya
, jika Anda mengkonversi aplikasi Android saat ini untuk menggunakan fragmen, Anda mungkin cukup memindahkan
kode dari metode callback aktivitas ke masing-masing metode callback
fragmen.</p>
<p>Biasanya, Anda harus mengimplementasikan setidaknya metode daur hidup berikut ini:</p>
<dl>
<dt>{@link android.app.Fragment#onCreate onCreate()}</dt>
<dd>Sistem akan memanggilnya saat membuat fragmen. Dalam implementasi, Anda harus
menginisialisasi komponen penting dari fragmen yang ingin dipertahankan saat fragmen
dihentikan sementara atau dihentikan, kemudian dilanjutkan.</dd>
<dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
<dd>Sistem akan memanggilnya saat fragmen menggambar antarmuka penggunanya
untuk yang pertama kali. Untuk menggambar UI fragmen, Anda harus mengembalikan {@link android.view.View} dari metode
ini yang menjadi akar layout fragmen. Hasil yang dikembalikan bisa berupa null jika
fragmen tidak menyediakan UI.</dd>
<dt>{@link android.app.Activity#onPause onPause()}</dt>
<dd>Sistem akan memanggil metode ini sebagai indikasi pertama bahwa pengguna sedang meninggalkan
fragmen Anda (walau itu tidak selalu berarti fragmen sedang dimusnahkan). Inilah biasanya tempat Anda
harus mengikat setiap perubahan yang harus dipertahankan selepas sesi pengguna saat ini (karena
pengguna mungkin tidak kembali).</dd>
</dl>
<p>Kebanyakan aplikasi harus mengimplementasikan setidaknya tiga metode ini untuk setiap fragmen, namun ada
beberapa metode callback lain yang juga harus Anda gunakan untuk menangani berbagai tahap
daur hidup fragmen. Semua metode callback daur hidup akan dibahas secara lebih detail, di bagian
tentang <a href="#Lifecycle">Menangani Daur Hidup Fragmen</a>.</p>
<p>Ada juga beberapa subkelas yang mungkin ingin diperpanjang, sebagai ganti kelas basis {@link
android.app.Fragment}:</p>
<dl>
<dt>{@link android.app.DialogFragment}</dt>
<dd>Menampilkan dialog mengambang. Penggunaan kelas ini untuk membuat dialog merupakan alternatif yang baik dari
penggunaan metode helper dialog di kelas {@link android.app.Activity}, karena Anda bisa
menyatukan dialog fragmen ke dalam back-stack fragmen yang dikelola oleh aktivitas,
sehingga pengguna bisa kembali ke fragmen yang ditinggalkan.</dd>
<dt>{@link android.app.ListFragment}</dt>
<dd>Menampilkan daftar item yang dikelola oleh adaptor (seperti {@link
android.widget.SimpleCursorAdapter}), serupa dengan {@link android.app.ListActivity}. Menampilkan
beberapa metode pengelolaan daftar tampilan seperti callback {@link
android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} untuk
menangani kejadian klik.</dd>
<dt>{@link android.preference.PreferenceFragment}</dt>
<dd>Menampilkan hierarki objek {@link android.preference.Preference} sebagai daftar, serupa dengan
{@link android.preference.PreferenceActivity}. Hal ini berguna saat membuat aktivitas
"pengaturan" untuk aplikasi Anda.</dd>
</dl>
<h3 id="UI">Menambahkan antarmuka pengguna</h3>
<p>Fragmen biasanya digunakan sebagai bagian dari antarmuka pengguna aktivitas dan menyumbangkan
layoutnya sendiri ke aktivitas.</p>
<p>Untuk menyediakan layout fragmen, Anda harus mengimplementasikan metode callback {@link
android.app.Fragment#onCreateView onCreateView()}, yang dipanggil sistem Android
bila tiba saatnya fragmen menggambar layoutnya. Implementasi Anda atas metode ini harus mengembalikan
{@link android.view.View} yang menjadi akar layout fragmen.</p>
<p class="note"><strong>Catatan:</strong> Jika fragmen adalah subkelas {@link
android.app.ListFragment}, implementasi default akan mengembalikan {@link android.widget.ListView} dari
{@link android.app.Fragment#onCreateView onCreateView()}, sehingga Anda tidak perlu mengimplementasikannya.</p>
<p>Untuk mengembalikan layout dari {@link
android.app.Fragment#onCreateView onCreateView()}, Anda bisa memekarkannya dari <a href="{@docRoot}guide/topics/resources/layout-resource.html">sumber daya layout</a> yang didefinisikan di XML. Untuk
membantu melakukannya, {@link android.app.Fragment#onCreateView onCreateView()} menyediakan objek
{@link android.view.LayoutInflater}.</p>
<p>Misalnya, ini adalah subkelas {@link android.app.Fragment} yang memuat layout dari file
{@code example_fragment.xml}:</p>
<pre>
public static class ExampleFragment extends Fragment {
&#64;Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
</pre>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Membuat layout</h3>
<p>Dalam contoh di atas, {@code R.layout.example_fragment} merupakan acuan ke sumber daya layout
bernama {@code example_fragment.xml} yang tersimpan dalam sumber daya aplikasi. Untuk informasi tentang cara
membuat layout di XML, lihat dokumentasi
<a href="{@docRoot}guide/topics/ui/index.html">Antarmuka Pengguna</a>.</p>
</div>
</div>
<p>Parameter {@code container} yang diteruskan ke {@link android.app.Fragment#onCreateView
onCreateView()} adalah induk {@link android.view.ViewGroup} (dari layout aktivitas) tempat
layout fragmen
akan disisipkan. Parameter {@code savedInstanceState} adalah {@link android.os.Bundle} yang
menyediakan data tentang instance fragmen sebelumnya, jika fragmen dilanjutkan
(status pemulihan dibahas selengkapnya di bagian tentang <a href="#Lifecycle">Menangani
Daur Hidup Fragmen</a>).</p>
<p>Metode {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} membutuhkan
tiga argumen:</p>
<ul>
<li>ID sumber daya layout yang ingin dimekarkan.</li>
<li>{@link android.view.ViewGroup} akan menjadi induk dari layout yang dimekarkan. {@code
container} perlu diteruskan agar sistem menerapkan parameter layout ke tampilan akar layout
yang dimekarkan, yang ditetapkan dalam tampilan induk yang akan dituju.</li>
<li>Boolean yang menunjukkan apakah layout akan dimekarkan harus ditempelkan pada {@link
android.view.ViewGroup} (parameter kedua) selama pemekaran. (Dalam hal ini, ini
salah karena sistem sudah memasukkan layout yang dimekarkan ke dalam {@code
container}&mdash;meneruskan benar akan membuat tampilan grup yang berlebihan dalam layout akhir.)</li>
</ul>
<p>Anda kini telah melihat cara membuat fragmen yang menyediakan layout. Berikutnya, Anda perlu menambahkan
fragmen ke aktivitas.</p>
<h3 id="Adding">Menambahkan fragmen ke aktivitas</h3>
<p>Biasanya, fragmen berkontribusi pada sebagian UI ke aktivitas host, yang ditanamkan sebagai
bagian dari hierarki tampilan keseluruhan aktivitas. Ada dua cara untuk menambahkan fragmen ke layout
aktivitas:</p>
<ul>
<li><b>Deklarasikan fragmen dalam file layout aktivitas.</b>
<p>Dalam hal ini, Anda bisa
menetapkan properti layout fragmen seakan-akan sebuah tampilan. Misalnya, berikut ini adalah file
layout untuk aktivitas dengan dua fragmen:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"&gt;
&lt;fragment android:name="com.example.news.ArticleListFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;fragment android:name="com.example.news.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>Atribut {@code android:name} dalam {@code &lt;fragment&gt;} menetapkan kelas {@link
android.app.Fragment} untuk dibuat instance-nya dalam layout.</p>
<p>Saat sistem membuat layout aktivitas, sistem membuat instance setiap fragmen sebagaimana yang ditetapkan dalam layout
dan memanggil metode {@link android.app.Fragment#onCreateView onCreateView()} masing-masing,
untuk mengambil setiap fragmen. Sistem akan menyisipkan {@link android.view.View} yang dikembalikan langsung oleh fragmen,
menggantikan elemen {@code &lt;fragment&gt;}.</p>
<div class="note">
<p><strong>Catatan:</strong> Setiap fragmen memerlukan identifier
unik yang bisa digunakan sistem untuk memulihkan fragmen jika aktivitas dimulai kembali (dan identifier yang bisa digunakan menangkap
fragmen untuk melakukan transaksi, seperti menghapusnya). Ada tiga cara untuk memberikan
ID bagi fragmen:</p>
<ul>
<li>Memberikan atribut {@code android:id} bersama ID unik.</li>
<li>Memberikan atribut {@code android:tag} bersama string unik.</li>
<li>Jika Anda tidak memberikan dua hal tersebut, sistem akan menggunakan ID
tampilan kontainer.</li>
</ul>
</div>
</li>
<li><b>Atau, secara programatis tambahkan fragmen ke {@link android.view.ViewGroup} yang ada.</b>
<p>Kapan saja saat aktivitas berjalan, Anda bisa menambahkan fragmen ke layout aktivitas. Anda
cukup menetapkan {@link
android.view.ViewGroup} di tempat memasukkan fragmen.</p>
<p>Untuk membuat transaksi fragmen dalam aktivitas (seperti menambah, menghapus, atau mengganti
fragmen), Anda harus menggunakan API dari {@link android.app.FragmentTransaction}. Anda bisa mengambil instance
{@link android.app.FragmentTransaction} dari {@link android.app.Activity} seperti ini:</p>
<pre>
FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()}
FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
</pre>
<p>Selanjutnya Anda bisa menambahkan fragmen menggunakan metode {@link
android.app.FragmentTransaction#add(int,Fragment) add()}, dengan menetapkan fragmen yang akan ditambahkan dan
tampilan tempat menyisipkannya. Misalnya:</p>
<pre>
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
</pre>
<p>Argumen pertama yang diteruskan ke {@link android.app.FragmentTransaction#add(int,Fragment) add()}
adalah {@link android.view.ViewGroup} tempat fragmen harus dimasukkan, yang ditetapkan oleh
ID sumber daya, dan parameter kedua merupakan fragmen yang akan ditambahkan.</p>
<p>Setelah membuat perubahan dengan
{@link android.app.FragmentTransaction}, Anda harus
memanggil {@link android.app.FragmentTransaction#commit} untuk menerapkan perubahan.</p>
</li>
</ul>
<h4 id="AddingWithoutUI">Menambahkan fragmen tanpa UI</h4>
<p>Contoh di atas menampilkan cara menambahkan fragmen ke aktivitas untuk menyediakan UI. Akan tetapi,
Anda juga bisa menggunakan fragmen untuk menyediakan perilaku latar belakang bagi aktivitas tanpa menampilkan UI
tambahan.</p>
<p>Untuk menambahkan fragmen tanpa UI, tambahkan fragmen dari aktivitas menggunakan {@link
android.app.FragmentTransaction#add(Fragment,String)} (dengan menyediakan string unik "tag" untuk fragmen
, bukan ID tampilan). Ini akan menambahkan fragmen, namun, karena tidak dikaitkan dengan tampilan
dalam layout aktivitas, ini tidak akan menerima panggilan ke {@link
android.app.Fragment#onCreateView onCreateView()}. Jadi Anda tidak perlu mengimplementasikan metode itu.</p>
<p>Menyediakan tag string untuk fragmen tidak hanya untuk fragmen non-UI&mdash;Anda juga bisa
menyediakan tag string untuk fragmen yang memiliki UI&mdash;namun jika fragmen tidak memiliki UI
, maka tag string adalah satu-satunya cara untuk mengidentifikasinya. Jika Anda ingin mendapatkan fragmen dari
aktivitas nantinya, Anda perlu menggunakan {@link android.app.FragmentManager#findFragmentByTag
findFragmentByTag()}.</p>
<p>Untuk contoh aktivitas yang menggunakan fragmen sebagai pekerja latar belakang, tanpa UI, lihat sampel {@code
FragmentRetainInstance.java}, yang disertakan dalam sampel SDK (tersedia melalui
Android SDK Manager) dan terletak di sistem Anda sebagai
<code>&lt;sdk_root&gt;/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java</code>.</p>
<h2 id="Managing">Mengelola Fragmen</h2>
<p>Untuk mengelola fragmen dalam aktivitas, Anda perlu menggunakan {@link android.app.FragmentManager}. Untuk
mendapatkannya, panggil {@link android.app.Activity#getFragmentManager()} dari aktivitas Anda.</p>
<p>Beberapa hal yang dapat Anda lakukan dengan {@link android.app.FragmentManager} antara lain:</p>
<ul>
<li>Dapatkan fragmen yang ada di aktivitas dengan {@link
android.app.FragmentManager#findFragmentById findFragmentById()} (untuk fragmen yang menyediakan UI dalam
layout aktivitas) atau {@link android.app.FragmentManager#findFragmentByTag
findFragmentByTag()} (untuk fragmen yang menyediakan atau tidak menyediakan UI).</li>
<li>Tarik fragmen dari back-stack, dengan {@link
android.app.FragmentManager#popBackStack()} (mensimulasikan perintah <em>Back</em> oleh pengguna).</li>
<li>Daftarkan listener untuk perubahan pada back-stack, dengan {@link
android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedListener()}.</li>
</ul>
<p>Untuk informasi selengkapnya tentang metode ini dan hal lainnya, lihat dokumentasi kelas {@link
android.app.FragmentManager}.</p>
<p>Seperti yang ditunjukkan di bagian sebelumnya, Anda juga bisa menggunakan {@link android.app.FragmentManager}
untuk membuka {@link android.app.FragmentTransaction}, sehingga Anda bisa melakukan transaksi, seperti
menambah dan menghapus fragmen.</p>
<h2 id="Transactions">Melakukan Transaksi Fragmen</h2>
<p>Fitur menarik terkait penggunaan fragmen di aktivitas adalah kemampuan menambah, menghapus, mengganti,
dan melakukan tindakan lain dengannya, sebagai respons atas interaksi pengguna. Setiap set perubahan
yang Anda lakukan untuk aktivitas disebut transaksi dan Anda bisa melakukan transaksi menggunakan API di {@link
android.app.FragmentTransaction}. Anda juga bisa menyimpan setiap transaksi ke back-stack yang dikelola
aktivitas, sehingga pengguna bisa mengarah mundur melalui perubahan fragmen (mirip mengarah
mundur melalui aktivitas).</p>
<p>Anda bisa mengambil instance {@link android.app.FragmentTransaction} dari {@link
android.app.FragmentManager} seperti ini:</p>
<pre>
FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager()};
FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};
</pre>
<p>Setiap transaksi merupakan serangkaian perubahan yang ingin dilakukan pada waktu yang sama. Anda bisa
mengatur semua perubahan yang ingin dilakukan untuk transaksi mana saja menggunakan metode seperti {@link
android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()},
dan {@link android.app.FragmentTransaction#replace replace()}. Kemudian, untuk menerapkan transaksi
pada aktivitas, Anda harus memanggil {@link android.app.FragmentTransaction#commit()}.</p>
</dl>
<p>Akan tetapi, sebelum memanggil {@link
android.app.FragmentTransaction#commit()}, Anda mungkin perlu memanggil {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, untuk menambahkan transaksi
ke back-stack dari transaksi fragmen. Back-stack ini dikelola oleh aktivitas dan memungkinkan
pengguna kembali ke status fragmen sebelumnya, dengan menekan tombol <em>Back</em>.</p>
<p>Misalnya, berikut ini cara mengganti satu fragmen dengan yang fragmen yang lain, dan mempertahankan
status sebelumnya di back-stack:</p>
<pre>
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
</pre>
<p>Dalam contoh ini, {@code newFragment} menggantikan fragmen apa saja (jika ada) yang saat ini berada dalam
kontainer layout yang diidentifikasi oleh ID {@code R.id.fragment_container}. Dengan memanggil @link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, transaksi yang diganti
disimpan ke back-stack sehingga pengguna bisa membalikkan transaksi dan mengembalikan fragmen
sebelumnya dengan menekan tombol <em>Back</em>.</p>
<p>Jika Anda menambahkan beberapa perubahan pada transaksi (seperti {@link
android.app.FragmentTransaction#add add()} atau {@link android.app.FragmentTransaction#remove
remove()}) dan panggil {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()}, maka semua perubahan akan diterapkan
sebelum Anda memanggil {@link android.app.FragmentTransaction#commit commit()} akan ditambahkan ke
back-stack sebagai satu transaksi dan tombol <em>Back</em> akan membalikannya semua.</p>
<p>Urutan menambahkan perubahan pada {@link android.app.FragmentTransaction} tidak berpengaruh,
kecuali:</p>
<ul>
<li>Anda harus memanggil {@link android.app.FragmentTransaction#commit()} paling akhir</li>
<li>Jika Anda menambahkan beberapa fragmen ke kontainer yang sama, maka
urutan penambahannya akan menentukan urutan munculnya dalam hierarki tampilan</li>
</ul>
<p>Jika Anda tidak memanggil {@link android.app.FragmentTransaction#addToBackStack(String)
addToBackStack()} saat melakukan transaksi yang menghapus fragmen, maka fragmen itu
akan dimusnahkan bila transaksi diikat dan pengguna tidak bisa mengarah kembali ke sana. Sedangkan, jika
Anda memanggil {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} saat
menghapus fragmen, maka fragmen itu akan <em>dihentikan</em> dan akan dilanjutkan jika pengguna mengarah
kembali.</p>
<p class="note"><strong>Tip:</strong> Untuk setiap transaksi fragmen, Anda bisa menerapkan animasi
transisi, dengan memanggil {@link android.app.FragmentTransaction#setTransition setTransition()} sebelum
mengikatnya.</p>
<p>Memanggil {@link android.app.FragmentTransaction#commit()} tidak akan langsung menjalankan
transaksi. Namun sebuah jadwal akan dibuat untuk dijalankan pada thread UI aktivitas (thread "utama")
begitu thread bisa melakukannya. Akan tetapi, jika perlu Anda bisa memanggil {@link
android.app.FragmentManager#executePendingTransactions()} dari thread UI untuk segera
mengeksekusi transaksi yang diserahkan oleh {@link android.app.FragmentTransaction#commit()}. Hal itu
biasanya tidak perlu kecuali jika transaksi merupakan dependensi bagi pekerjaan dalam thread lain.</p>
<p class="caution"><strong>Perhatian:</strong> Anda bisa mengikat transaksi menggunakan {@link
android.app.FragmentTransaction#commit commit()} hanya sebelum aktivitas <a href="{@docRoot}guide/components/activities.html#SavingActivityState">menyimpan
statusnya</a> (saat pengguna meninggalkan aktivitas). Jika Anda mencoba mengikatnya setelah itu,
eksepsi akan dilontarkan. Ini karena status setelah pengikatan bisa hilang jika aktivitas
perlu dipulihkan. Untuk situasi yang memperbolehkan Anda meniadakan pengikatan (commit), gunakan {@link
android.app.FragmentTransaction#commitAllowingStateLoss()}.</p>
<h2 id="CommunicatingWithActivity">Berkomunikasi dengan Aktivitas</h2>
<p>Meskipun {@link android.app.Fragment} diimplementasikan sebagai objek yang tidak bergantung pada
{@link android.app.Activity} dan bisa digunakan dalam banyak aktivitas, instance tertentu
dari fragmen secara langsung terkait dengan aktivitas yang dimuatnya.</p>
<p>Khususnya, fragmen bisa mengakses instance {@link android.app.Activity} dengan {@link
android.app.Fragment#getActivity()} dan dengan mudah melakukan tugas-tugas seperti mencari tampilan dalam
layout aktivitas:</p>
<pre>
View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
</pre>
<p>Demikian pula, aktivitas Anda bisa memanggil metode di fragmen dengan meminta acuan ke
{@link android.app.Fragment} dari {@link android.app.FragmentManager}, menggunakan {@link
android.app.FragmentManager#findFragmentById findFragmentById()} atau {@link
android.app.FragmentManager#findFragmentByTag findFragmentByTag()}. Misalnya:</p>
<pre>
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
</pre>
<h3 id="EventCallbacks">Membuat callback kejadian pada aktivitas</h3>
<p>Dalam beberapa kasus, Anda mungkin perlu fragmen untuk berbagi kejadian dengan aktivitas. Cara yang baik untuk melakukannya
adalah mendefinisikan antarmuka callback di dalam fragmen dan mengharuskan aktivitas host
mengimplementasikannya. Saat aktivitas menerima callback melalui antarmuka, aktivitas akan bisa berbagi informasi itu
dengan fragmen lain dalam layout jika perlu.</p>
<p>Misalnya, jika sebuah aplikasi berita memiliki dua fragmen dalam aktivitas&mdash;satu untuk menampilkan daftar
artikel (fragmen A) dan satu lagi untuk menampilkan artikel (fragmen B)&mdash;maka fragmen A harus
memberi tahu aktivitas bila item daftar dipilih sehingga aktivitas bisa memberi tahu fragmen B untuk menampilkan artikel. Dalam
hal ini, antarmuka {@code OnArticleSelectedListener} dideklarasikan di dalam fragmen A:</p>
<pre>
public static class FragmentA extends ListFragment {
...
// Container Activity must implement this interface
public interface OnArticleSelectedListener {
public void onArticleSelected(Uri articleUri);
}
...
}
</pre>
<p>Selanjutnya aktivitas yang menjadi host fragmen akan mengimplementasikan antarmuka {@code OnArticleSelectedListener}
dan
mengesampingkan {@code onArticleSelected()} untuk memberi tahu fragmen B mengenai kejadian dari fragmen A. Untuk memastikan
bahwa aktivitas host mengimplementasikan antarmuka ini, metode callback fragmen A {@link
android.app.Fragment#onAttach onAttach()} (yang dipanggil sistem saat menambahkan
fragmen ke aktivitas) membuat instance {@code OnArticleSelectedListener} dengan
membuat {@link android.app.Activity} yang diteruskan ke {@link android.app.Fragment#onAttach
onAttach()}:</p>
<pre>
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
&#64;Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
}
}
...
}
</pre>
<p>Jika aktivitas belum mengimplementasikan antarmuka, maka fragmen akan melontarkan
{@link java.lang.ClassCastException}.
Jika berhasil, anggota {@code mListener} yang menyimpan acuan ke implementasi aktivitas
{@code OnArticleSelectedListener}, sehingga fragmen A bisa berbagi kejadian dengan aktivitas, dengan memanggil metode
yang didefinisikan oleh antarmuka {@code OnArticleSelectedListener}. Misalnya, jika fragmen A adalah
ekstensi dari {@link android.app.ListFragment}, maka setiap kali
pengguna mengklik item daftar, sistem akan memanggil {@link android.app.ListFragment#onListItemClick
onListItemClick()} di fragmen, yang selanjutnya memanggil {@code onArticleSelected()} untuk berbagi
kejadian dengan aktivitas:</p>
<pre>
public static class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
&#64;Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Append the clicked item's row ID with the content provider Uri
Uri noteUri = ContentUris.{@link android.content.ContentUris#withAppendedId withAppendedId}(ArticleColumns.CONTENT_URI, id);
// Send the event and Uri to the host activity
mListener.onArticleSelected(noteUri);
}
...
}
</pre>
<p>Parameter {@code id} yang diteruskan ke {@link
android.app.ListFragment#onListItemClick onListItemClick()} merupakan ID baris dari item yang diklik,
yang digunakan aktivitas (atau fragmen lain) untuk mengambil artikel dari {@link
android.content.ContentProvider} aplikasi.</p>
<p><!--To see a complete implementation of this kind of callback interface, see the <a
href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample</a>. -->Informasi selengkapnya tentang
menggunakan penyedia konten tersedia dalam dokumen <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
<h3 id="ActionBar">Menambahkan item ke Action-Bar</h3>
<p>Fragmen Anda bisa menyumbangkan item menu ke <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Menu Opsi</a> aktivitas (dan, konsekuensinya, <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>) dengan mengimplementasikan
{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. Agar
metode ini bisa menerima panggilan, Anda harus memanggil {@link
android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} selama {@link
android.app.Fragment#onCreate(Bundle) onCreate()}, untuk menunjukkan bahwa fragmen
ingin menambahkan item ke Menu Opsi (jika tidak, fragmen tidak akan menerima panggilan ke
{@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}).</p>
<p>Setiap item yang selanjutnya Anda tambahkan ke Menu Opsi dari fragmen akan ditambahkan ke item menu
yang ada. Fragmen juga menerima callback ke {@link
android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} bila item menu
dipilih.</p>
<p>Anda juga bisa mendaftarkan tampilan dalam layout fragmen untuk menyediakan menu konteks dengan memanggil {@link
android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}. Bila pengguna
membuka menu konteks, fragmen akan menerima panggilan ke {@link
android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo)
onCreateContextMenu()}. Bila pengguna memilih item, fragmen akan menerima panggilan ke @link
android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}.</p>
<p class="note"><strong>Catatan:</strong> Walaupun fragmen menerima callback pada item yang dipilih
untuk setiap item menu yang ditambahkannya, aktivitaslah yang pertama kali menerima masing-masing callback saat pengguna
memilih item menu. Jika implementasi aktivitas dari callback bila-item-dipilih,
tidak menangani item yang dipilih, maka kejadian akan diteruskan ke callback fragmen. Ini berlaku
untuk Menu Opsi dan menu konteks.</p>
<p>Untuk informasi selengkapnya tentang menu, lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html">Menu</a> dan <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>.</p>
<h2 id="Lifecycle">Menangani Daur Hidup Fragmen</h2>
<div class="figure" style="width:350px">
<img src="{@docRoot}images/activity_fragment_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 3.</strong> Efek daur hidup aktivitas pada daur hidup
fragmen.</p>
</div>
<p>Mengelola daur hidup fragmen mirip sekali dengan mengelola daur hidup aktivitas. Seperti
aktivitas, fragmen bisa berada dalam tiga status:</p>
<dl>
<dt><i>Dilanjutkan</i></dt>
<dd>Fragmen terlihat dalam aktivitas yang berjalan.</dd>
<dt><i>Dihentikan sementara</i></dt>
<dd>Aktivitas lain berada di latar depan dan memiliki fokus, namun aktivitas tempat fragmen berada
masih terlihat (aktivitas latar depan sebagian terlihat atau tidak menutupi
seluruh layar).</dd>
<dt><i>Dihentikan</i></dt>
<dd>Fragmen tidak terlihat. Aktivitas host telah dihentikan atau
fragmen telah dihapus dari aktivitas namun ditambahkan ke back-stack. Fragmen yang dihentikan
masih hidup (semua status dan informasi anggota masih disimpan oleh sistem). Akan tetapi, fragmen
tidak terlihat lagi oleh pengguna dan akan dimatikan jika aktivitas dimatikan.</dd>
</dl>
<p>Seperti halnya aktivitas, Anda bisa mempertahankan status fragmen menggunakan {@link
android.os.Bundle}, jika proses aktivitas dimatikan dan Anda harus memulihkan status
fragmen bila aktivitas dibuat kembali. Anda bisa menyimpan status selama callback {@link
android.app.Fragment#onSaveInstanceState onSaveInstanceState()} fragmen dan memulihkannya selama
{@link android.app.Fragment#onCreate onCreate()}, {@link
android.app.Fragment#onCreateView onCreateView()}, atau {@link
android.app.Fragment#onActivityCreated onActivityCreated()}. Untuk informasi selengkapnya tentang menyimpan
status, lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>
.</p>
<p>Perbedaan paling signifikan dalam daur hidup antara aktivitas dan fragmen ada
pada cara penyimpanannya dalam back-stack masing-masing. Aktivitas ditempatkan ke back-stack aktivitas
yang dikelola oleh sistem saat dihentikan, secara default (sehingga pengguna bisa mengarah kembali
ke aktivitas dengan tombol <em>Back</em>, seperti yang dibahas dalam <a href="{@docRoot}guide/components/tasks-and-back-stack.html">Tugas dan Back-Stack</a>).
Akan tetapi, fragmen yang ditempatkan ke back-stack dikelola oleh aktivitas host hanya saat
Anda secara eksplisit meminta agar instance disimpan dengan memanggil {@link
android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} selama transaksi yang
menghapus fragmen.</p>
<p>Jika tidak, pengelolaan daur hidup fragmen mirip sekali dengan mengelola daur hidup
aktivitas. Jadi, praktik yang sama untuk <a href="{@docRoot}guide/components/activities.html#Lifecycle">mengelola daur hidup
aktivitas</a> juga berlaku untuk fragmen. Namun yang perlu juga Anda pahami adalah bagaimana hidup
aktivitas memengaruhi hidup fragmen.</p>
<p class="caution"><strong>Perhatian:</strong> Jika Anda memerlukan objek {@link android.content.Context}
dalam {@link android.app.Fragment}, Anda bisa memanggil {@link android.app.Fragment#getActivity()}.
Akan tetapi, berhati-hatilah memanggil {@link android.app.Fragment#getActivity()} hanya bila fragmen
terkait dengan aktivitas. Bila fragmen belum terkait, atau terlepas selama akhir daur
hidupnya, {@link android.app.Fragment#getActivity()} akan kembali nol.</p>
<h3 id="CoordinatingWithActivity">Mengoordinasi dengan daur hidup aktivitas</h3>
<p>Daur hidup aktivitas tempat fragmen berada akan memengaruhi langsung siklus hidup
fragmen sedemikian rupa sehingga setiap callback daur hidup aktivitas menghasilkan callback yang sama untuk masing-masing
fragmen. Misalnya, bila aktivitas menerima {@link android.app.Activity#onPause}, masing-masing
fragmen dalam aktivitas akan menerima {@link android.app.Fragment#onPause}.</p>
<p>Namun fragmen memiliki beberapa callback daur hidup ekstra, yang menangani interaksi
unik dengan aktivitas untuk melakukan tindakan seperti membangun dan memusnahkan UI fragmen. Metode callback
tambahan ini adalah:</p>
<dl>
<dt>{@link android.app.Fragment#onAttach onAttach()}</dt>
<dd>Dipanggil bila fragmen telah dikaitkan dengan aktivitas ({@link
android.app.Activity} diteruskan di sini).</dd>
<dt>{@link android.app.Fragment#onCreateView onCreateView()}</dt>
<dd>Dipanggil untuk membuat hierarki tampilan yang dikaitkan dengan fragmen.</dd>
<dt>{@link android.app.Fragment#onActivityCreated onActivityCreated()}</dt>
<dd>Dipanggil bila metode {@link android.app.Activity#onCreate
onCreate()} aktivitas telah dikembalikan.</dd>
<dt>{@link android.app.Fragment#onDestroyView onDestroyView()}</dt>
<dd>Dipanggil bila hierarki tampilan yang terkait dengan fragmen dihapus.</dd>
<dt>{@link android.app.Fragment#onDetach onDetach()}</dt>
<dd>Dipanggil bila fragmen diputuskan dari aktivitas.</dd>
</dl>
<p>Aliran daur hidup fragmen, karena dipengaruhi oleh aktivitas host-nya, diilustrasikan oleh
gambar 3. Dalam gambar ini, Anda bisa melihat bagaimana setiap status aktivitas menentukan
metode callback mana yang mungkin diterima fragmen. Misalnya, saat aktivitas menerima call back {@link
android.app.Activity#onCreate onCreate()}, fragmen dalam aktivitas akan menerima tidak lebih
dari callback {@link android.app.Fragment#onActivityCreated onActivityCreated()}.</p>
<p>Setelah status aktivitas diteruskan kembali, Anda bisa bebas menambah dan menghapus fragmen untuk
aktivitas tersebut. Sehingga, hanya saat aktivitas berada dalam status dilanjutkan, daur hidup fragmen bisa
berubah secara independen.</p>
<p>Akan tetapi, saat aktivitas meninggalkan status dilanjutkan, fragmen akan kembali didorong
melalui daur hidupnya oleh aktivitas.</p>
<h2 id="Example">Contoh</h2>
<p>Untuk merangkum semua yang telah dibahas dalam dokumen ini, berikut ini contoh aktivitas
yang menggunakan dua fragmen untuk membuat layout dua panel. Aktivitas di bawah ini menyertakan satu fragmen untuk
menampilkan daftar putar Shakespeare dan fragmen lainnya menampilkan rangkuman pemutaran bila dipilih dari
daftar. Aktivitas ini juga menunjukkan cara menyediakan konfigurasi fragmen berbeda,
berdasarkan konfigurasi layar.</p>
<p class="note"><strong>Catatan:</strong> Kode sumber lengkap untuk aktivitas ini tersedia di
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code
FragmentLayout.java}</a>.</p>
<p>Aktivitas utama akan menerapkan layout seperti biasa, selama {@link
android.app.Activity#onCreate onCreate()}:</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java main}
<p>Layout yang diterapkan adalah {@code fragment_layout.xml}:</p>
{@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout}
<p>Dengan layout ini, sistem akan membuat instance {@code TitlesFragment} (yang mencantumkan
judul) segera setelah aktivitas memuat layout, sementara {@link android.widget.FrameLayout}
(lokasi penempatan fragmen untuk menampilkan rangkuman pemutaran) menempati ruang di sisi kanan
layar, namun pada awalnya masih kosong. Seperti yang akan Anda lihat di bawah ini, sampai pengguna memilih item
dari daftar maka fragmen baru akan ditempatkan ke dalam {@link android.widget.FrameLayout}.</p>
<p>Akan tetapi, tidak semua konfigurasi layar cukup lebar untuk menampilkan
daftar putar dan rangkuman secara berdampingan. Sehingga, layout di atas hanya digunakan untuk konfigurasi
layar mendatar, dengan menyimpannya di {@code res/layout-land/fragment_layout.xml}.</p>
<p>Sehingga, bila layar berada dalam orientasi tegak, sistem akan menerapkan layout berikut, yang
tersimpan di {@code res/layout/fragment_layout.xml}:</p>
{@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
<p>Layout ini hanya menyertakan {@code TitlesFragment}. Ini artinya saat perangkat berada dalam
orientasi tegak, hanya judul daftar putar yang terlihat. Jadi, saat pengguna mengklik item
daftar dalam konfigurasi ini, aplikasi akan memulai aktivitas baru untuk menampilkan rangkuman,
sebagai ganti pemuatan fragmen kedua.</p>
<p>Berikutnya, Anda bisa melihat bagaimana hal ini dilakukan dalam kelas fragmen. Pertama adalah {@code
TitlesFragment}, yang menampilkan judul daftar putar Shakespeare. Fragmen ini membuat ekstensi {@link
android.app.ListFragment} dan mengandalkannya itu untuk menangani sebagian besar pekerjaan tampilan daftar.</p>
<p>Saat Anda memeriksa kode ini, perhatikan bahwa ada dua kemungkinan perilaku saat pengguna mengklik
item daftar: bergantung pada layout mana yang aktif, bisa membuat dan menampilkan fragmen
baru untuk menampilkan detail dalam aktivitas yang sama (menambahkan fragmen ke {@link
android.widget.FrameLayout}), atau memulai aktivitas baru (tempat fragmen ditampilkan).</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles}
<p>Fragmen kedua, {@code DetailsFragment} menampilkan rangkuman pemutaran untuk item yang dipilih dari
daftar dari {@code TitlesFragment}:</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}
<p>Ingatlah dari kelas {@code TitlesFragment}, bahwa, jika pengguna mengklik item daftar dan
layout saat ini <em>tidak</em> menyertakan tampilan {@code R.id.details} (yaitu tempat
{@code DetailsFragment} berada), maka aplikasi memulai aktivitas {@code DetailsActivity}
untuk menampilkan konten item.</p>
<p>Berikut ini adalah {@code DetailsActivity}, yang hanya menanamkan {@code DetailsFragment} untuk menampilkan rangkuman pemutaran
yang dipilih saat layar dalam orientasi tegak:</p>
{@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
details_activity}
<p>Perhatikan bahwa aktivitas ini selesai sendiri jika konfigurasi mendatar, sehingga aktivitas utama
bisa mengambil alih dan menampilkan {@code DetailsFragment} bersama {@code TitlesFragment}.
Ini bisa terjadi jika pengguna memulai {@code DetailsActivity} saat dalam orientasi tegak, namun kemudian
memutarnya menjadi mendatar (yang akan memulai lagi aktivitas saat ini).</p>
<p>Untuk contoh lainnya mengenai penggunaan fragmen (dan file sumber lengkap untuk contoh ini),
lihat aplikasi contoh Demo API yang tersedia di <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">
ApiDemos</a> (bisa diunduh dari <a href="{@docRoot}resources/samples/get.html">Komponen contoh SDK</a>).</p>

View File

@@ -0,0 +1,480 @@
page.title=Dasar-Dasar Aplikasi
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Components">Komponen Aplikasi</a>
<ol>
<li><a href="#ActivatingComponents">Mengaktifkan komponen</a></li>
</ol>
</li>
<li><a href="#Manifest">File Manifes</a>
<ol>
<li><a href="#DeclaringComponents">Mendeklarasikan komponen</a></li>
<li><a href="#DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</a></li>
</ol>
</li>
<li><a href="#Resources">Sumber Daya Aplikasi</a></li>
</ol>
</div>
</div>
<p>Aplikasi Android ditulis dalam bahasa pemrograman Java. Android SDK Tools mengkompilasi
kode Anda&mdash;bersama data dan file sumber daya &mdash;ke dalam APK: <i>Paket Android</i>,
yaitu file arsip berekstensi {@code .apk}. Satu file APK berisi semua konten
aplikasi Android dan merupakan file yang digunakan perangkat berbasis Android untuk menginstal aplikasi.</p>
<p>Setelah diinstal di perangkat, setiap aplikasi Android tinggal di sandbox keamanannya sendiri: </p>
<ul>
<li>Sistem operasi Android merupakan sistem Linux multi-pengguna yang di dalamnya setiap
aplikasi adalah pengguna berbeda.</li>
<li>Secara default, sistem menetapkan ID pengguna Linux unik kepada setiap aplikasi (ID ini hanya
digunakan oleh sistem dan tidak diketahui aplikasi). Sistem menetapkan izin
bagi semua file dalam aplikasi sehingga hanya ID pengguna yang diizinkan yang bisa mengaksesnya. </li>
<li>Setiap proses memiliki mesin virtual (VM) sendiri, sehingga kode aplikasi yang berjalan secara terisolasi dari
aplikasi lainnya.</li>
<li>Secara default, setiap aplikasi berjalan dalam proses Linux-nya sendiri. Android memulai proses
bila ada komponen aplikasi yang perlu dijalankan, kemudian mematikan proses bila tidak lagi diperlukan
atau bila sistem harus memulihkan memori untuk digunakan aplikasi lain.</li>
</ul>
<p>Dengan cara ini, sistem Android mengimplementasikan <em>prinsip privilese minim</em>. Ini berarti,
secara default aplikasi hanya memiliki akses ke komponen yang diperlukannya untuk melakukan pekerjaannya dan
tidak lebih dari itu. Hal ini menghasilkan lingkungan yang sangat aman sehingga aplikasi tidak bisa mengakses bagian
sistem bila tidak diberi izin.</p>
<p>Akan tetapi, ada beberapa cara bagi aplikasi untuk berbagi data dengan aplikasi lain dan bagi aplikasi
untuk mengakses layanan sistem:</p>
<ul>
<li>Dua aplikasi bisa diatur untuk menggunakan ID pengguna Linux yang sama,
dalam hal ini keduanya bisa saling mengakses file masing-masing. Untuk menghemat sumber daya sistem, aplikasi dengan ID
pengguna yang sama juga bisa diatur agar berjalan dalam proses Linux yang sama dan menggunakan VM yang sama (
aplikasi juga harus ditandatangani dengan sertifikat yang sama).</li>
<li>Aplikasi bisa meminta izin akses ke data perangkat seperti kontak
pengguna, pesan SMS, penyimpanan lepas-pasang (kartu SD), kamera, Bluetooth, dan lainnya. Semua
izin aplikasi harus diberikan oleh pengguna saat menginstal.</li>
</ul>
<p>Hal tersebut mencakup dasar-dasar tentang cara aplikasi Android berada di dalam sistem. Bagian dokumen
selanjutnya memperkenalkan Anda pada:</p>
<ul>
<li>Komponen kerangka kerja inti yang mendefinisikan aplikasi.</li>
<li>File manifes tempat Anda mendeklarasikan komponen dan fitur yang diperlukan perangkat
untuk aplikasi.</li>
<li>Sumber daya yang terpisah dari kode aplikasi dan memungkinkan
aplikasi mengoptimalkan perilakunya untuk beragam konfigurasi perangkat.</li>
</ul>
<h2 id="Components">Komponen Aplikasi</h2>
<p>Komponen aplikasi adalah blok pembangun penting dari aplikasi Android.
Setiap komponen merupakan titik berbeda yang digunakan sistem untuk memasuki aplikasi. Tidak semua komponen
merupakan titik masuk sebenarnya bagi pengguna dan sebagian saling bergantung, namun masing-masing komponen tersedia
sebagai kesatuan sendiri dan memainkan peran tertentu&mdash;masing-masing merupakan
blok pembangun unik yang mendefinisikan perilaku aplikasi secara keseluruhan.</p>
<p>Ada empat macam tipe komponen aplikasi. Setiap tipe memiliki kegunaan tersendiri
dan daur hidupnya sendiri yang mendefinisikan cara komponen dibuat dan dimusnahkan.</p>
<p>Berikut ini empat tipe komponen aplikasi:</p>
<dl>
<dt><b>Aktivitas</b></dt>
<dd>Sebuah <i>aktivitas</i> mewakili satu layar dengan antarmuka pengguna. Misalnya,
aplikasi email mungkin memiliki satu aktivitas yang menampilkan daftar email
baru, aktivitas lain untuk menulis email, dan aktivitas satunya lagi untuk membaca email. Walaupun
semua aktivitas bekerja sama untuk membentuk pengalaman pengguna yang kohesif dalam aplikasi email,
masing-masing tidak saling bergantung. Karenanya, aplikasi berbeda bisa memulai
salah satu aktivitas ini (jika aplikasi email mengizinkannya). Misalnya, aplikasi kamera bisa memulai
aktivitas dalam aplikasi email yang membuat email baru agar pengguna bisa berbagi gambar.
<p>Aktivitas diimplementasikan sebagai subkelas {@link android.app.Activity} dan Anda bisa mengetahui selengkapnya
tentang hal ini dalam panduan pengembang <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>
.</p>
</dd>
<dt><b>Layanan</b></dt>
<dd>Sebuah <i>layanan</i> adalah komponen yang berjalan di latar belakang untuk melakukan
operasi yang berjalan lama atau untuk melakukan pekerjaan bagi proses jarak jauh. Layanan
tidak menyediakan antarmuka pengguna. Misalnya, sebuah layanan bisa memutar musik di latar belakang sementara
pengguna berada dalam aplikasi lain, atau layanan bisa menarik data lewat jaringan tanpa
memblokir interaksi pengguna dengan aktivitas. Komponen lain, seperti aktivitas, bisa memulai
layanan dan membiarkannya berjalan atau mengikat layanan untuk berinteraksi dengannya.
<p>Layanan diimplementasikan sebagai subkelas {@link android.app.Service} dan Anda bisa mengetahui selengkapnya
tentang hal ini dalam panduan
pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
</dd>
<dt><b>Penyedia konten</b></dt>
<dd>Sebuah <i>penyedia konten</i> mengelola seperangkat data-bersama aplikasi. Anda bisa menyimpan data
dalam sistem file, database SQLite, di web, atau lokasi penyimpanan permanen lainnya
yang bisa diakses aplikasi. Melalui penyedia konten, aplikasi lain bisa melakukan query atau bahkan
memodifikasi data (jika penyedia konten mengizinkannya). Misalnya, sistem Android menyediakan penyedia
konten yang mengelola informasi kontak pengguna. Karenanya, setiap aplikasi
dengan izin yang sesuai bisa melakukan query mengenai bagian dari penyedia konten (seperti {@link
android.provider.ContactsContract.Data}) untuk membaca dan menulis informasi tentang orang tertentu.
<p>Penyedia konten juga berguna untuk membaca dan menulis data privat ke aplikasi Anda
dan tidak dibagikan. Misalnya, aplikasi contoh <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> menggunakan
penyedia konten untuk menyimpan catatan.</p>
<p>Penyedia konten diimplementasikan sebagai subkelas {@link android.content.ContentProvider}
dan harus mengimplementasikan seperangkat standar API yang memungkinkan aplikasi
lain melakukan transaksi. Untuk informasi selengkapnya, lihat panduan pengembang
<a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
</dd>
<dt><b>Penerima siaran</b></dt>
<dd>Sebuah <i>penerima siaran</i> adalah komponen yang merespons pengumuman siaran dalam lingkup
sistem. Banyak siaran yang berasal dari sistem&mdash;misalnya, siaran yang mengumumkan bahwa
layar telah dimatikan, baterai lemah, atau gambar telah direkam.
Aplikasi juga bisa memulai siaran&mdash;misalnya untuk menginformasikan ke
aplikasi lain bahwa sebagian data telah diunduh ke perangkat dan bisa digunakan aplikasi lain tersebut. Walaupun penerima
siaran tidak menampilkan antarmuka pengguna, penerima bisa <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">membuat pemberitahuan baris status</a>
untuk memberi tahu pengguna kapan kejadian siaran dilakukan. Meskipun penerima siaran umumnya cuma menjadi
"gerbang" untuk komponen lain dan dimaksudkan untuk melakukan pekerjaan dalam jumlah sangat minim. Misalnya
, penerima siaran bisa menjalankan layanan untuk melakukan beberapa pekerjaan berdasarkan kejadian.
<p>Penerima siaran diimplementasikan sebagai subkelas {@link android.content.BroadcastReceiver}
dan setiap siaran dikirim sebagai objek {@link android.content.Intent}. Untuk informasi selengkapnya,
lihat kelas {@link android.content.BroadcastReceiver}.</p>
</dd>
</dl>
<p>Aspek unik dari desain sistem Android adalah aplikasi mana pun bisa memulai
komponen aplikasi lain. Misalnya, jika Anda menginginkan pengguna mengambil
foto dengan kamera perangkat, bisa saja aplikasi lain yang melakukannya dan aplikasi
Anda bisa menggunakannya, sebagai ganti mengembangkan aktivitas sendiri untuk mengambil foto. Anda tidak
harus menyatukan atau bahkan menautkan ke kode dari aplikasi kamera.
Sebagai gantinya, Anda tinggal memulai aktivitas di aplikasi kamera yang akan mengambil
foto. Bila selesai, foto akan dikembalikan ke aplikasi sehingga Anda bisa menggunakannya. Bagi pengguna,
kamera seakan menjadi bagian dari aplikasi Anda.</p>
<p>Saat sistem memulai komponen, sistem akan memulai proses untuk aplikasi itu (jika
belum berjalan) dan membuat instance kelas yang diperlukan untuk komponen. Misalnya, jika aplikasi Anda
memulai aktivitas dalam aplikasi kamera yang mengambil foto, aktivitas itu akan
berjalan dalam proses yang dimiliki oleh aplikasi kamera, bukan dalam proses aplikasi Anda.
Karenanya, tidak seperti aplikasi di sebagian besar sistem lain, aplikasi Android tidak memiliki titik
masuk tunggal (misalnya tidak ada fungsi {@code main()}).</p>
<p>Karena sistem menjalankan setiap aplikasi dalam proses terpisah dengan izin file yang
membatasi akses ke aplikasi lain, aplikasi Anda tidak bisa langsung mengaktifkan komponen dari aplikasi lain. Akan tetapi, sistem
Android bisa melakukannya. Jadi, untuk mengaktifkan
komponen dalam aplikasi lain, Anda harus mengirim pesan ke sistem yang menetapkan <em>intent</em> Anda untuk memulai
komponen tertentu. Selanjutnya sistem akan mengaktifkan komponen untuk Anda.</p>
<h3 id="ActivatingComponents">Mengaktifkan Komponen</h3>
<p>Tiga dari empat tipe komponen&mdash;aktivitas, layanan, dan
penerima siaran&mdash;diaktifkan oleh pesan asinkron yang disebut <em>intent</em>.
Intent saling mengikat setiap komponen saat runtime (Anda bisa menganggapnya
sebagai pembawa pesan yang meminta tindakan dari komponen lain), baik komponen itu milik aplikasi Anda
atau milik aplikasi lain.</p>
<p>Intent dibuat dengan objek {@link android.content.Intent}, yang mendefinisikan pesan untuk
mengaktifkan komponen tertentu atau komponen <em>tipe</em> komponen tertentu&mdash;masing-masing intent
bisa eksplisit atau implisit.</p>
<p>Untuk aktivitas dan layanan, intent mendefinisikan tindakan yang akan dilakukan (misalnya, untuk "melihat" atau
"mengirim" sesuatu) dan mungkin menetapkan URI data untuk ditindaklanjuti (salah satu hal yang mungkin perlu diketahui
oleh komponen yang akan dimulai). Misalnya, intent mungkin menyampaikan permintaan suatu
aktivitas untuk menampilkan gambar atau membuka halaman web. Dalam beberapa kasus, Anda bisa memulai
aktivitas untuk menerima hasil, dalam hal ini, aktivitas juga akan mengembalikan hasil
dalam {@link android.content.Intent} (misalnya Anda bisa mengeluarkan intent agar
pengguna bisa memilih kontak pribadi dan memintanya dikembalikan kepada Anda&mdash;intent yang dikembalikan menyertakan URI yang
menunjuk ke kontak yang dipilih).</p>
<p>Untuk penerima siaran, intent hanya mendefinisikan
pengumuman yang sedang disiarkan (misalnya, siaran untuk menunjukkan baterai perangkat hampir habis
hanya menyertakan string tindakan yang menunjukkan "baterai hampir habis").</p>
<p>Tipe komponen lainnya dan penyedia konten, tidak diaktifkan oleh intent. Melainkan
diaktifkan saat ditargetkan oleh permintaan dari {@link android.content.ContentResolver}. Resolver
konten menangani semua transaksi langsung dengan penyedia konten sehingga komponen yang melakukan
transaksi dengan penyedia tidak perlu dan sebagai gantinya memanggil metode pada objek {@link
android.content.ContentResolver}. Ini membuat lapisan abstraksi antara penyedia
konten dan komponen yang meminta informasi (demi keamanan).</p>
<p>Ada beberapa metode terpisah untuk mengaktifkan masing-masing tipe komponen:</p>
<ul>
<li>Anda bisa memulai aktivitas (atau memberinya pekerjaan baru) dengan
meneruskan {@link android.content.Intent} ke {@link android.content.Context#startActivity
startActivity()} atau {@link android.app.Activity#startActivityForResult startActivityForResult()}
(bila Anda ingin aktivitas mengembalikan hasil).</li>
<li>Anda bisa memulai layanan (atau memberikan instruksi baru ke layanan yang sedang berlangsung) dengan
meneruskan {@link android.content.Intent} ke {@link android.content.Context#startService
startService()}. Atau Anda bisa mengikat ke layanan dengan meneruskan {@link android.content.Intent} ke
{@link android.content.Context#bindService bindService()}.</li>
<li>Anda bisa memulai siaran dengan meneruskan {@link android.content.Intent} ke metode seperti
{@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link
android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()}, atau {@link
android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</li>
<li>Anda bisa melakukan query ke penyedia konten dengan memanggil {@link
android.content.ContentProvider#query query()} pada {@link android.content.ContentResolver}.</li>
</ul>
<p>Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter
Intent</a>. Informasi selengkapnya tentang mengaktifkan komponen
tertentu juga tersedia dalam dokumen berikut: <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>, <a href="{@docRoot}guide/components/services.html">Layanan</a>, {@link
android.content.BroadcastReceiver} dan <a href="{@docRoot}guide/topics/providers/content-providers.html">Penyedia Konten</a>.</p>
<h2 id="Manifest">File Manifes</h2>
<p>Sebelum sistem Android bisa memulai komponen aplikasi, sistem harus mengetahui
keberadaan komponen dengan membaca file {@code AndroidManifest.xml} aplikasi (file
"manifes"). Aplikasi Anda harus mendeklarasikan semua komponennya dalam file ini, yang harus menjadi akar
dari direktori proyek aplikasi.</p>
<p>Manifes melakukan banyak hal selain mendeklarasikan komponen aplikasi,
seperti:</p>
<ul>
<li>Mengidentifikasi izin pengguna yang diperlukan aplikasi, seperti akses Internet atau
akses-baca ke kontak pengguna.</li>
<li>Mendeklarasikan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a>
minimum yang diperlukan aplikasi, berdasarkan API yang digunakan aplikasi.</li>
<li>Mendeklarasikan fitur perangkat keras dan perangkat lunak yang diperlukan aplikasi, seperti kamera,
layanan Bluetooth, atau layar multisentuh.</li>
<li>Pustaka API aplikasi perlu ditautkan (selain
API kerangka kerja Android), seperti pustaka
<a href="http://code.google.com/android/add-ons/google-apis/maps-overview.html">Google Maps.</a></li>
<li>Dan lainnya</li>
</ul>
<h3 id="DeclaringComponents">Mendeklarasikan komponen</h3>
<p>Tugas utama manifes adalah menginformasikan komponen aplikasi pada sistem. Misalnya,
file manifes bisa mendeklarasikan aktivitas sebagai berikut: </p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;manifest ... &gt;
&lt;application android:icon="@drawable/app_icon.png" ... &gt;
&lt;activity android:name="com.example.project.ExampleActivity"
android:label="@string/example_label" ... &gt;
&lt;/activity&gt;
...
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>Dalam elemen <code><a
href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
, atribut {@code android:icon} menunjuk ke sumber daya untuk ikon yang mengidentifikasi
aplikasi.</p>
<p>Dalam elemen <code><a
href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
atribut {@code android:name} menetapkan nama kelas yang sepenuhnya memenuhi syarat subkelas {@link
android.app.Activity} dan atribut {@code android:label} menetapkan string yang akan
digunakan sebagai label yang terlihat oleh pengguna untuk aktivitas tersebut.</p>
<p>Anda harus mendeklarasikan semua komponen aplikasi dengan cara ini:</p>
<ul>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code> untuk
aktivitas</li>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code> untuk
layanan</li>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code> untuk
penerima siaran</li>
<li>Elemen <code><a
href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code> untuk
penyedia konten</li>
</ul>
<p>Aktivitas, layanan, dan penyedia konten yang Anda sertakan dalam kode sumber, namun tidak
dideklarasikan dalam manifes, tidak akan terlihat pada sistem dan, akibatnya, tidak pernah bisa berjalan. Akan tetapi,
penerima siaran
bisa dideklarasikan dalam manifes atau dibuat secara dinamis dalam kode (sebagai objek
{@link android.content.BroadcastReceiver}) dan didaftarkan pada sistem dengan memanggil
{@link android.content.Context#registerReceiver registerReceiver()}.</p>
<p>Untuk informasi selengkapnya tentang cara menstrukturkan file manifes untuk aplikasi Anda,
lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">File AndroidManifest.xml</a>. </p>
<h3 id="DeclaringComponentCapabilities">Mendeklarasikan kemampuan komponen</h3>
<p>Seperti telah dibahas di atas, dalam <a href="#ActivatingComponents">Mengaktifkan Komponen</a>, Anda bisa menggunakan
{@link android.content.Intent} untuk memulai aktivitas, layanan, dan penerima siaran. Anda bisa
melakukannya dengan menamai komponen sasaran secara eksplisit (menggunakan nama kelas komponen) dalam intent. Akan tetapi,
kemampuan intent sebenarnya ada pada konsep <em>intent implisit</em>. Intent implisit
cuma menjelaskan tipe tindakan yang akan dilakukan (dan, secara opsional, data tempat Anda ingin
melakukan tindakan) dan memungkinkan sistem untuk menemukan komponen pada perangkat yang bisa melakukan
tindakan tersebut dan memulainya. Jika ada banyak komponen yang bisa melakukan tindakan yang dijelaskan oleh intent,
maka pengguna bisa memilih komponen yang akan digunakan.</p>
<p>Cara sistem mengidentifikasi komponen yang bisa merespons intent adalah dengan membandingkan
intent yang diterima dengan <i>filter intent</i> yang disediakan dalam file manifes aplikasi lainnya pada
perangkat.</p>
<p>Bila mendeklarasikan aktivitas dalam manifes aplikasi, secara opsional Anda bisa menyertakan
filter intent yang mendeklarasikan kemampuan aktivitas agar bisa merespons intent dari
aplikasi lain. Anda bisa mendeklarasikan filter intent untuk komponen dengan
menambahkan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> sebagai anak elemen deklarasi komponen.</p>
<p>Misalnya, jika Anda telah membangun aplikasi email dengan aktivitas untuk menulis email baru, Anda bisa
mendeklarasikan filter intent untuk merespons intent "kirim" (untuk mengirim email baru) seperti ini:</p>
<pre>
&lt;manifest ... >
...
&lt;application ... &gt;
&lt;activity android:name="com.example.project.ComposeEmailActivity">
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEND" />
&lt;data android:type="*/*" />
&lt;category android:name="android.intent.category.DEFAULT" />
&lt;/intent-filter>
&lt;/activity>
&lt;/application&gt;
&lt;/manifest>
</pre>
<p>Kemudian, jika aplikasi lain membuat intent dengan tindakan {@link
android.content.Intent#ACTION_SEND} dan meneruskannya ke {@link android.app.Activity#startActivity
startActivity()}, sistem bisa memulai aktivitas Anda agar pengguna bisa menulis draf dan mengirim
email.</p>
<p>Untuk informasi selengkapnya tentang membuat filter intent, lihat dokumen <a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>.
</p>
<h3 id="DeclaringRequirements">Mendeklarasikan kebutuhan aplikasi</h3>
<p>Ada berbagai macam perangkat yang didukung oleh Android dan tidak
semuanya menyediakan fitur dan kemampuan yang sama. Agar aplikasi Anda tidak dihapus pada perangkat yang tidak memiliki
fitur yang diperlukan aplikasi, Anda harus jelas mendefinisikan profil mengenai
tipe perangkat yang didukung aplikasi dengan mendeklarasikan kebutuhan perangkat dan perangkat lunak dalam file
manifes. Kebanyakan deklarasi ini hanya bersifat informasi dan sistem tidak
membacanya, namun layanan eksternal seperti Google Play akan membacanya untuk menyediakan
penyaringan bagi pengguna saat mereka mencari aplikasi dari perangkat.</p>
<p>Misalnya, jika aplikasi memerlukan kamera dan menggunakan API yang disediakan dalam Android 2.1 (<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API Level</a> 7)
, Anda harus mendeklarasikannya sebagai kebutuhan dalam file manifes seperti ini:</p>
<pre>
&lt;manifest ... >
&lt;uses-feature android:name="android.hardware.camera.any"
android:required="true" />
&lt;uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
...
&lt;/manifest>
</pre>
<p>Sekarang, perangkat yang <em>tidak</em> memiliki kamera dan menggunakan
Android versi <em>lebih rendah</em> dari 2.1 tidak bisa menginstal aplikasi Anda dari Google Play.</p>
<p>Akan tetapi, bisa juga mendeklarasikan bahwa aplikasi Anda menggunakan kamera, namun tidak
<em>mengharuskannya</em>. Dalam hal itu, aplikasi Anda harus mengatur atribut <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#required">{@code required}</a>
ke {@code "false"} dan memeriksa saat runtime apakah
perangkat memiliki kamera dan menonaktifkan setiap fitur kamera yang sesuai.</p>
<p>Informasi selengkapnya tentang cara mengelola kompatibilitas aplikasi dengan
perangkat yang berbeda disediakan dalam dokumen
<a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>.</p>
<h2 id="Resources">Sumber Daya Aplikasi</h2>
<p>Aplikasi Android tidak hanya terdiri dari kode&mdash;Aplikasi memerlukan sumber daya yang
terpisah dari kode sumber, seperti gambar, file audio, dan apa saja yang berkaitan dengan
presentasi visual dari aplikasi. Misalnya, Anda harus mendefinisikan animasi, menu, gaya, warna,
dan layout antarmuka pengguna aktivitas dengan file XML. Penggunaan sumber daya aplikasi
mempermudah pembaruan berbagai karakteristik aplikasi Anda tanpa memodifikasi kode dan&mdash;dengan menyediakan
seperangkat sumber daya alternatif&mdash;memungkinkan Anda mengoptimalkan aplikasi untuk berbagai konfigurasi
perangkat berbeda (seperti bahasa dan ukuran layar yang berbeda).</p>
<p>Untuk setiap sumber daya yang Anda sertakan dalam proyek Android, alat bawaan SDK akan mendefinisikan ID integer
unik, yang bisa Anda gunakan untuk mengacu sumber daya dari kode aplikasi atau dari sumber daya lainnya yang
didefinisikan dalam XML. Misalnya, jika aplikasi berisi file gambar bernama {@code
logo.png} (disimpan dalam direktori {@code res/drawable/}), alat SDK akan menghasilkan ID sumber daya
bernama {@code R.drawable.logo}, yang bisa Anda gunakan untuk mengacu gambar dan memasukkannya dalam
antarmuka pengguna.</p>
<p>Salah satu aspek paling penting dari penyediaan sumber daya yang terpisah dari
kode sumber adalah kemampuan Anda menyediakan sumber daya alternatif untuk konfigurasi perangkat
yang berbeda. Misalnya, dengan mendefinisikan string UI dalam XML, Anda bisa menerjemahkan string ke dalam
bahasa lain dan menyimpan string itu dalam file terpisah. Kemudian, berdasarkan <em>qualifier</em>
bahasa yang ditambahkan ke nama direktori sumber daya (seperti {@code res/values-fr/} untuk nilai
string Prancis) dan pengaturan bahasa pengguna, sistem Android akan menerapkan string bahasa yang sesuai
untuk UI Anda.</p>
<p>Android mendukung banyak <em>qualifier</em> berbeda untuk sumber daya alternatif Anda. Qualifier
adalah string pendek yang Anda sertakan dalam nama direktori sumber
daya untuk mendefinisikan konfigurasi perangkat yang harus digunakan sumber daya tersebut. Contoh lainnya,
Anda harus sering membuat layout berbeda untuk aktivitas, bergantung pada
orientasi layar dan ukuran perangkat. Misalnya, saat layar perangkat dalam orientasi
tegak, Anda mungkin ingin layout tombolnya vertikal, tetapi saat layar dalam orientasi
mendatar, tombolnya harus sejajar horizontal. Untuk mengubah layout
sesuai orientasi, Anda bisa mendefinisikan dua layout berbeda dan menerapkan qualifier yang
tepat untuk setiap nama direktori layout. Kemudian, sistem secara otomatis menerapkan
layout yang tepat sesuai dengan orientasi perangkat saat ini.</p>
<p>Untuk informasi selengkapnya tentang berbagai jenis sumber daya yang bisa disertakan dalam aplikasi dan cara
membuat sumber daya alternatif untuk konfigurasi perangkat berbeda, bacalah <a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a>.</p>
<div class="next-docs">
<div class="col-6">
<h2 class="norule">Teruskan membaca tentang:</h2>
<dl>
<dt><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>
</dt>
<dd>Informasi tentang cara menggunakan API {@link android.content.Intent} untuk
mengaktifkan komponen aplikasi, seperti aktivitas dan layanan, dan cara menyediakan komponen aplikasi
untuk digunakan oleh aplikasi lain.</dd>
<dt><a href="{@docRoot}guide/components/activities.html">Aktivitas</a></dt>
<dd>Informasi tentang cara membuat instance kelas {@link android.app.Activity},
yang menyediakan layar tersendiri dalam aplikasi bersama antarmuka pengguna.</dd>
<dt><a href="{@docRoot}guide/topics/resources/providing-resources.html">Menyediakan Sumber Daya</a></dt>
<dd>Informasi tentang cara aplikasi Android disusun untuk memisahkan sumber daya aplikasi dari
kode aplikasi, termasuk cara Anda bisa menyediakan sumber daya alternatif untuk
konfigurasi perangkat tertentu.
</dd>
</dl>
</div>
<div class="col-6">
<h2 class="norule">Anda juga mungkin tertarik dengan:</h2>
<dl>
<dt><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a></dt>
<dd>Informasi tentang cara kerja Android pada berbagai tipe perangkat dan
pengenalan mengenai cara mengoptimalkan aplikasi untuk setiap perangkat atau membatasi ketersediaan aplikasi Anda untuk
perangkat berbeda.</dd>
<dt><a href="{@docRoot}guide/topics/security/permissions.html">Izin Sistem</a></dt>
<dd>Informasi tentang cara Android membatasi akses aplikasi pada API tertentu dengan sistem izin
yang mengharuskan persetujuan pengguna agar aplikasi dapat menggunakan API tersebut.</dd>
</dl>
</div>
</div>

View File

@@ -0,0 +1,57 @@
page.title=Komponen Aplikasi
page.landing=true
page.landing.intro=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent.
page.metaDescription=Kerangka kerja aplikasi Android memungkinkan Anda membuat aplikasi yang kaya dan inovatif menggunakan seperangkat komponen yang dapat digunakan kembali. Bagian ini menjelaskan cara membangun komponen yang mendefinisikan blok pembangun aplikasi Anda dan cara menghubungkannya bersama menggunakan intent.
page.landing.image=images/develop/app_components.png
page.image=images/develop/app_components.png
@jd:body
<div class="landing-docs">
<div class="col-6">
<h3>Artikel Blog</h3>
<a href="http://android-developers.blogspot.com/2012/05/using-dialogfragments.html">
<h4>Menggunakan DialogFragments</h4>
<p>Dalam posting ini, saya akan menunjukkan cara menggunakan DialogFragments dengan pustaka dukungan v4 (untuk kompatibilitas mundur pada perangkat sebelum Honeycomb) untuk menunjukkan dialog edit sederhana dan mengembalikan hasil ke Aktivitas pemanggil menggunakan antarmuka.</p>
</a>
<a href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html">
<h4>Fragmen Untuk Semua</h4>
<p>Hari ini kami telah merilis pustaka statis yang memperlihatkan API Fragment yang sama (serta LoaderManager baru dan beberapa kelas lain) agar aplikasi yang kompatibel dengan Android 1.6 atau yang lebih baru bisa menggunakan fragmen untuk membuat antarmuka pengguna yang kompatibel dengan tablet. </p>
</a>
<a href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html">
<h4>Multithreading untuk Kinerja</h4>
<p>Praktik yang baik dalam membuat aplikasi yang responsif adalah memastikan thread UI utama Anda
melakukan pekerjaan minimum. Setiap tugas yang berpotensi lama dan dapat membuat aplikasi mogok harus
ditangani di thread berbeda.</p>
</a>
</div>
<div class="col-6">
<h3>Pelatihan</h3>
<a href="http://developer.android.com/training/basics/activity-lifecycle/index.html">
<h4>Mengelola Daur Hidup Aktivitas</h4>
<p>Bagian ini menjelaskan pentingnya metode callback daur hidup yang diterima setiap instance Aktivitas
dan cara menggunakannya sehingga aktivitas Anda melakukan yang diharapkan pengguna dan tidak menghabiskan sumber daya sistem
saat aktivitas tidak membutuhkannya.</p>
</a>
<a href="http://developer.android.com/training/basics/fragments/index.html">
<h4>Membangun UI Dinamis dengan Fragmen</h4>
<p>Bagian ini menunjukkan kepada Anda cara membuat pengalaman pengguna yang dinamis dengan fragmen dan mengoptimalkan
pengalaman pengguna aplikasi Anda dengan berbagai ukuran layar, sekaligus terus mendukung
perangkat yang menjalankan versi sebelumnya, sesudah versi Android 1.6.</p>
</a>
<a href="http://developer.android.com/training/sharing/index.html">
<h4>Berbagi Konten</h4>
<p>Bagian ini membahas beberapa cara umum untuk mengirim dan menerima konten antar
aplikasi menggunakan API Intent dan objek ActionProvider.</p>
</a>
</div>
</div>

View File

@@ -0,0 +1,899 @@
page.title=Intent dan Filter Intent
page.tags="IntentFilter"
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Types">Tipe Intent</a></li>
<li><a href="#Building">Membangun Intent</a>
<ol>
<li><a href="#ExampleExplicit">Contoh intent eksplisit</a></li>
<li><a href="#ExampleSend">Contoh intent implisit</a></li>
<li><a href="#ForceChooser">Memaksakan pemilih aplikasi</a></li>
</ol>
</li>
<li><a href="#Receiving">Menerima Intent Implisit</a>
<ol>
<li><a href="#ExampleFilters">Contoh filter</a></li>
</ol>
</li>
<li><a href="#PendingIntent">Menggunakan Intent Tertunda</a></li>
<li><a href="#Resolution">Resolusi Intent</a>
<ol>
<li><a href="#ActionTest">Pengujian tindakan</a></li>
<li><a href="#CategoryTest">Pengujian kategori</a></li>
<li><a href="#DataTest">Pengujian data</a></li>
<li><a href="#imatch">Pencocokan intent</a></li>
</ol>
</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}training/basics/intents/index.html">Berinteraksi dengan Aplikasi Lain</a></li>
<li><a href="{@docRoot}training/sharing/index.html">Berbagi Konten</a></li>
</ol>
</div>
</div>
<p>{@link android.content.Intent} merupakan objek pertukaran pesan yang bisa Anda gunakan untuk meminta tindakan
dari <a href="{@docRoot}guide/components/fundamentals.html#Components">komponen aplikasi</a> lain.
Walaupun intent memudahkan komunikasi antarkomponen dalam beberapa cara, ada tiga
kasus-penggunaan dasar:</p>
<ul>
<li><b>Untuk memulai aktivitas:</b>
<p>{@link android.app.Activity} menyatakan satu layar dalam aplikasi. Anda bisa memulai instance
baru {@link android.app.Activity} dengan meneruskan {@link android.content.Intent}
ke {@link android.content.Context#startActivity startActivity()}. {@link android.content.Intent}
menjelaskan aktivitas yang akan dimulai dan membawa data yang diperlukan.</p>
<p>Jika Anda ingin menerima hasil dari aktivitas bila selesai,
panggil {@link android.app.Activity#startActivityForResult
startActivityForResult()}. Aktivitas Anda menerima hasil
sebagai objek {@link android.content.Intent} terpisah dalam callback {@link
android.app.Activity#onActivityResult onActivityResult()} aktivitas Anda.
Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/activities.html">Aktivitas</a>.</p></li>
<li><b>Untuk memulai layanan:</b>
<p>{@link android.app.Service} adalah komponen yang melakukan operasi di latar belakang
tanpa antarmuka pengguna. Anda bisa memulai layanan untuk melakukan operasi satu-kali
(misalnya mengunduh file) dengan meneruskan {@link android.content.Intent}
ke {@link android.content.Context#startService startService()}. {@link android.content.Intent}
menjelaskan layanan yang akan dimulai dan membawa data yang diperlukan.</p>
<p>Jika layanan didesain dengan antarmuka pengguna klien-server, Anda bisa mengikat ke layanan
dari komponen lain dengan meneruskan {@link android.content.Intent} ke {@link
android.content.Context#bindService bindService()}</code>. Untuk informasi selengkapnya, lihat panduan <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p></li>
<li><b>Untuk mengirim siaran:</b>
<p>Siaran adalah pesan yang bisa diterima aplikasi apa saja. Sistem menyampaikan beragam siaran
untuk kejadian sistem, misalnya saat sistem booting atau saat perangkat mulai mengisi daya.
Anda bisa mengirim siaran ke aplikasi lain dengan meneruskan {@link android.content.Intent}
ke {@link android.content.Context#sendBroadcast(Intent) sendBroadcast()},
{@link android.content.Context#sendOrderedBroadcast(Intent, String)
sendOrderedBroadcast()}, atau {@link
android.content.Context#sendStickyBroadcast sendStickyBroadcast()}.</p>
</li>
</ul>
<h2 id="Types">Tipe Intent</h2>
<p>Ada dua tipe intent:</p>
<ul>
<li><b>Intent eksplisit</b> menetapkan komponen untuk memulai dengan nama (
nama kelas yang sepenuhnya memenuhi syarat). Anda biasanya akan menggunakan intent eksplisit untuk memulai sebuah komponen
dalam aplikasi sendiri, karena Anda mengetahui nama kelas dari aktivitas atau layanan yang ingin dimulai.
Misalnya, mulai aktivitas baru sebagai respons terhadap tindakan pengguna atau mulai layanan untuk mengunduh
file di latar belakang.</li>
<li><b>Intent implisit</b> tidak menetapkan komponen tertentu, melainkan mendeklarasikan tindakan umum
yang dilakukan, yang memungkinkan komponen aplikasi lain untuk menanganinya. Misalnya, jika Anda ingin
menampilkan sebuah lokasi di peta pada pengguna, Anda bisa menggunakan intent implisit untuk meminta aplikasi lain
yang mampu untuk menunjukkan lokasi yang telah ditetapkan di peta tersebut.</li>
</ul>
<p>Saat Anda membuat intent eksplisit untuk memulai aktivitas atau layanan, sistem akan segera
memulai komponen aplikasi yang telah ditetapkan dalam objek {@link android.content.Intent}.</p>
<div class="figure" style="width:446px">
<img src="{@docRoot}images/components/intent-filters@2x.png" width="446" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi yang menggambarkan cara intent implisit
disampaikan melalui sistem untuk memulai aktivitas lain: <b>[1]</b> <em>Aktivitas A</em> membuat sebuah
{@link android.content.Intent} dengan keterangan tindakan dan meneruskannya ke {@link
android.content.Context#startActivity startActivity()}. <b>[2]</b> Sistem Android akan mencari semua
aplikasi untuk filter intent yang cocok dengan intent tersebut. Bila cocok, <b>[3]</b> sistem akan
memulai aktivitas mencocokkan (<em>Aktivitas B</em>) dengan memanggil metode {@link
android.app.Activity#onCreate onCreate()} dan meneruskannya ke {@link android.content.Intent}.
</p>
</div>
<p>Bila Anda membuat intent implisit, sistem Android akan menemukan komponen yang sesuai untuk memulai
dengan membandingkan konten intent dengan <em>filter intent</em> yang dideklarasikan dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> aplikasi lain di
perangkat. Jika intent cocok dengan filter intent, sistem akan memulai komponen tersebut dan mengiriminya
objek {@link android.content.Intent}. Jika banyak filter intent yang kompatibel, sistem
menampilkan dialog sehingga pengguna bisa memilih aplikasi yang akan digunakan.</p>
<p>Filter intent adalah ekspresi dalam file manifes aplikasi yang
menetapkan tipe intent yang akan diterima
komponen. Misalnya, dengan mendeklarasikan intent filter untuk aktivitas,
Anda akan memungkinkan aplikasi lain untuk langsung memulai aktivitas Anda dengan intent tertentu.
Demikian pula, jika Anda <em>tidak</em> mendeklarasikan filter intent untuk suatu aktivitas, maka aktivitas tersebut hanya bisa dimulai
dengan intent eksplisit.</p>
<p class="caution"><strong>Perhatian:</strong> Untuk memastikan aplikasi Anda aman, selalu gunakan intent
eksplisit saat memulai {@link android.app.Service} dan jangan
mendeklarasikan filter intent untuk layanan. Menggunakan intent implisit untuk memulai layanan akan menimbulkan
bahaya keamanan karena Anda tidak bisa memastikan layanan apa yang akan merespons intent,
dan pengguna tidak bisa melihat layanan mana yang dimulai. Mulai dari Android 5.0 (API level 21), sistem
melontarkan eksepsi jika Anda memanggil {@link android.content.Context#bindService bindService()}
dengan intent implisit.</p>
<h2 id="Building">Membangun Intent</h2>
<p>Objek {@link android.content.Intent} membawa informasi yang digunakan sistem Android
untuk menentukan komponen mana yang akan dimulai (misalnya nama persis dari suatu komponen atau kategori
komponen yang seharusnya menerima intent), ditambah informasi yang digunakan komponen penerima untuk
melakukan tindakan dengan benar (misalnya tindakan yang harus dilakukan dan data yang harus diolah).</p>
<p>Informasi utama yang dimuat dalam {@link android.content.Intent} adalah sebagai berikut:</p>
<dl>
<dt><b>Nama komponen</b></dt>
<dd>Nama komponen yang akan dimulai.
<p>Ini opsional, namun merupakan bagian informasi penting yang membuat intent
menjadi <b>eksplisit</b>, yaitu intent harus dikirim hanya ke komponen aplikasi
yang didefinisikan oleh nama komponen. Tanpa nama komponen, intent menjadi <b>implisit</b> dan
sistem akan memutuskan komponen mana yang harus menerima intent berdasarkan informasi intent lain
(misalnya tindakan, data, dan kategori&mdash;yang dijelaskan di bawah ini). Jadi jika Anda ingin memulai komponen
tertentu dalam aplikasi, Anda harus menetapkan nama komponen tersebut.</p>
<p class="note"><strong>Catatan:</strong> Saat memulai {@link android.app.Service}, Anda harus
<strong>selalu menetapkan nama komponen</strong>. Jika tidak, maka Anda tidak bisa memastikan layanan apa
yang akan merespons intent tersebut, dan pengguna tidak bisa melihat layanan mana yang dimulai.</p>
<p>Bidang {@link android.content.Intent} ini adalah objek
{@link android.content.ComponentName}, yang bisa Anda tetapkan menggunakan
nama kelas yang sepenuhnya memenuhi syarat dari komponen target, termasuk nama paket aplikasi. Misalnya,
{@code com.example.ExampleActivity}. Anda bisa mengatur nama komponen dengan {@link
android.content.Intent#setComponent setComponent()}, {@link android.content.Intent#setClass
setClass()}, {@link android.content.Intent#setClassName(String, String) setClassName()}, atau dengan konstruktor
{@link android.content.Intent}.</p>
</dd>
<p><dt><b>Tindakan</b></dt>
<dd>String yang menetapkan tindakan generik untuk dilakukan (misalnya <em>lihat</em> atau <em>pilih</em>).
<p>Dalam hal intent siaran, ini adalah tindakan yang terjadi dan dilaporkan.
Tindakan ini sangat menentukan bagaimana keseluruhan intent disusun&mdash;terutama
apa yang dimuat dalam data dan ekstra.
<p>Anda bisa menetapkan tindakan sendiri yang akan digunakan oleh intent dalam aplikasi Anda (atau digunakan oleh aplikasi
lain untuk memanggil komponen dalam aplikasi Anda), namun Anda harus menggunakan konstanta tindakan
yang didefinisikan oleh kelas {@link android.content.Intent} atau kelas kerangka kerja lain. Berikut ini adalah beberapa
tindakan umum untuk memulai sebuah aktivitas:</p>
<dl>
<dt>{@link android.content.Intent#ACTION_VIEW}</dt>
<dd>Gunakan tindakan ini dalam intent dengan {@link
android.content.Context#startActivity startActivity()} saat Anda memiliki beberapa informasi yang
bisa ditampilkan aktivitas kepada pengguna, misalnya foto yang bisa dilihat dalam aplikasi galeri, atau alamat
yang bisa dilihat dalam aplikasi peta.</dd>
<dt>{@link android.content.Intent#ACTION_SEND}</dt>
<dd>Juga dikenal dengan intent "berbagi", Anda harus menggunakannya dalam intent dengan {@link
android.content.Context#startActivity startActivity()} bila Anda memiliki data yang bisa digunakan pengguna untuk
berbagi melalui aplikasi lain, misalnya aplikasi email atau aplikasi jaringan sosial.</dd>
</dl>
<p>Lihat referensi kelas {@link android.content.Intent} untuk konstanta
selengkapnya yang mendefinisikan tindakan generik. Tindakan lain yang didefinisikan
di tempat lain dalam kerangka kerja Android, misalnya dalam {@link android.provider.Settings} untuk tindakan
yang membuka layar tertentu dalam aplikasi Settings di sistem.</p>
<p>Anda bisa menetapkan tindakan untuk sebuah intent dengan {@link android.content.Intent#setAction
setAction()} atau dengan konstruktor {@link android.content.Intent}.</p>
<p>Jika mendefinisikan tindakan Anda sendiri, pastikan untuk memasukkan nama paket aplikasi Anda
sebagai awalan. Misalnya:</p>
<pre>static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";</pre>
</dd>
<dt><b>Data</b></dt>
<dd>URI (objek {@link android.net.Uri}) yang mengacu data untuk diolah dan/atau
tipe MIME dari data tersebut. Tipe data yang disediakan umumnya didikte oleh tindakan intent.
Misalnya, jika tindakan merupakan {@link android.content.Intent#ACTION_EDIT}, data harus berisi
URI dari dokumen untuk diedit.
<p>Saat membuat intent,
seringkali tipe data (tipe MIME-nya) selain URI perlu ditetapkan.
Misalnya, aktivitas yang mampu menampilkan gambar mungkin tidak mampu
memutar file audio, walaupun format URI mungkin serupa.
Jadi menetapkan tipe MIME data Anda akan membantu sistem
Android menemukan komponen terbaik untuk diterima intent.
Akan tetapi, tipe MIME seringkali bisa diambil dari URI&mdash;terutama saat datanya merupakan URI
{@code content:}, yang menunjukkan data tersebut berada di perangkat dan dikontrol oleh
{@link android.content.ContentProvider}, yang membuat data tipe MIME terlihat di sistem.</p>
<p>Untuk mengatur data URI saja, panggil {@link android.content.Intent#setData setData()}.
Untuk mengatur tipe MIME saja, panggil {@link android.content.Intent#setType setType()}. Jika perlu, Anda
bisa mengatur keduanya secara eksplisit dengan {@link
android.content.Intent#setDataAndType setDataAndType()}.</p>
<p class="caution"><strong>Perhatian:</strong> Jika ingin mengatur tipe URI dan MIME,
<strong>jangan</strong> panggil {@link android.content.Intent#setData setData()} dan
{@link android.content.Intent#setType setType()} karena mereka saling menghapuskan nilai satu sama lain.
Selalu gunakan {@link android.content.Intent#setDataAndType setDataAndType()} untuk mengatur
tipe URI maupun MIME.</p>
</dd>
<p><dt><b>Kategori</b></dt>
<dd>String yang berisi informasi tambahan tentang jenis komponen
yang harus menangani intent. Keterangan kategori dalam jumlah berapa pun bisa
dimasukkan dalam intent, namun sebagian besar intent tidak memerlukan kategori.
Berikut ini adalah beberapa kategori umum:
<dl>
<dt>{@link android.content.Intent#CATEGORY_BROWSABLE}</dt>
<dd>Aktivitas target memungkinkannya dimulai oleh browser web untuk menampilkan data
yang diacu oleh tautan&mdash;misalnya gambar atau pesan e-mail.
</dd>
<dt>{@link android.content.Intent#CATEGORY_LAUNCHER}</dt>
<dd>Aktivitas tersebut adalah aktivitas awal dari sebuah tugas dan dicantumkan dalam
launcher aplikasi sistem.
</dd>
</dl>
<p>Lihat keterangan kelas {@link android.content.Intent} untuk mengetahui daftar lengkap
kategori.</p>
<p>Anda bisa menetapkan kategori dengan {@link android.content.Intent#addCategory addCategory()}.</p>
</dd>
</dl>
<p>Properti yang tercantum di atas (nama komponen, tindakan, data, dan kategori) menyatakan
karakteristik yang mendefinisikan intent. Dengan membaca properti ini, sistem Android
mampu memutuskan komponen aplikasi yang harus dimulainya.</p>
<p>Akan tetapi, intent bisa membawa informasi tambahan yang tidak memengaruhi
cara intent ditetapkan pada komponen aplikasi. Intent juga bisa menyediakan:</p>
<dl>
<dt><b>Ekstra</b></dt>
<dd>Pasangan nilai-kunci yang membawa informasi yang diperlukan untuk menghasilkan tindakan yang diminta.
Seperti halnya beberapa tindakan menggunakan jenis tertentu URI data, beberapa tindakan juga menggunakan ekstra tertentu.
<p>Anda bisa menambahkan data ekstra dengan beragam metode {@link android.content.Intent#putExtra putExtra()},
masing-masing menerima dua parameter: nama kunci dan nilainya.
Anda juga bisa membuat objek {@link android.os.Bundle} dengan semua data ekstra, kemudian memasukkan
{@link android.os.Bundle} dalam {@link android.content.Intent} dengan {@link
android.content.Intent#putExtras putExtras()}.</p>
<p>Misalnya, saat membuat intent yang akan dikirimkan bersama email
{@link android.content.Intent#ACTION_SEND}, Anda bisa menetapkan penerima "kepada" dengan kunci
{@link android.content.Intent#EXTRA_EMAIL}, dan menetapkan "subjek" dengan kunci
{@link android.content.Intent#EXTRA_SUBJECT}.</p>
<p>Kelas {@link android.content.Intent} menetapkan beberapa konstanta {@code EXTRA_*}
untuk tipe data standar. Jika Anda ingin mendeklarasikan kunci ekstra sendiri (untuk intent yang
diterima aplikasi Anda), pastikan untuk memasukkan nama paket aplikasi
sebagai awalan. Misalnya:</p>
<pre>static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";</pre>
</dd>
<dt><b>Flag</b></dt>
<dd>Flag didefinisikan dalam kelas {@link android.content.Intent} yang berfungsi sebagai metadata untuk
intent. Flag menginstruksikan cara meluncurkan aktivitas (misalnya,
<a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> mana yang harus dimiliki suatu aktivitas
) dan cara memperlakukannya setelah diluncurkan (misalnya, apakah aktivitas tersebut masuk ke dalam daftar aktivitas
terbaru) pada sistem Android.
<p>Untuk informasi selengkapnya, lihat metode {@link android.content.Intent#setFlags setFlags()} .</p>
</dd>
</dl>
<h3 id="ExampleExplicit">Contoh intent eksplisit</h3>
<p>Intent eksplisit adalah intent yang Anda gunakan untuk meluncurkan komponen aplikasi tertentu, seperti
aktivitas tertentu atau layanan dalam aplikasi Anda. Untuk membuat intent eksplisit, definisikan
nama komponen untuk objek {@link android.content.Intent} &mdash;semua
properti intent lain bersifat opsional.</p>
<p>Misalnya, jika Anda ingin membangun layanan dalam aplikasi Anda, bernama {@code DownloadService},
yang didesain untuk mengunduh file dari web, Anda bisa memulainya dengan kode berikut ini:</p>
<pre>
// Executed in an Activity, so 'this' is the {@link android.content.Context}
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData({@link android.net.Uri#parse Uri.parse}(fileUrl));
startService(downloadIntent);
</pre>
<p>Konstruktor {@link android.content.Intent#Intent(Context,Class)}
menyediakan {@link android.content.Context} aplikasi dan
objek {@link java.lang.Class} pada komponen. Dengan demikian,
intent ini memulai secara eksplisit kelas {@code DownloadService} dalam aplikasi.</p>
<p>Untuk informasi selengkapnya tentang membangun dan memulai layanan, lihat panduan
<a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
<h3 id="ExampleSend">Contoh intent implisit</h3>
<p>Intent implisit menetapkan tindakan yang bisa memanggil aplikasi pada perangkat yang mampu
melakukan tindakan. Menggunakan intent implisit berguna bila aplikasi Anda tidak bisa melakukan
tindakan, namun aplikasi lain mungkin bisa melakukannya dan Anda ingin pengguna untuk memilih aplikasi mana yang ingin digunakan.</p>
<p>Misalnya, jika memiliki konten yang Anda ingin agar pengguna berbagi konten itu dengan orang lain, buatlah intent
dengan tindakan {@link android.content.Intent#ACTION_SEND}
dan tambahkan ekstra yang menetapkan konten yang akan dibagikan. Bila Anda memanggil
{@link android.content.Context#startActivity startActivity()} dengan intent tersebut, pengguna bisa
memilih aplikasi yang akan digunakan untuk berbagi konten.</p>
<p class="caution"><strong>Perhatian:</strong> Ada kemungkinan pengguna tidak memiliki <em>suatu</em>
aplikasi yang menangani intent implisit yang Anda kirimkan ke {@link android.content.Context#startActivity
startActivity()}. Jika itu terjadi, panggilan akan gagal dan aplikasi Anda akan crash. Untuk memeriksa
apakah aktivitas bisa menerima intent, panggil {@link android.content.Intent#resolveActivity
resolveActivity()} pada objek {@link android.content.Intent} Anda. Jika hasilnya bukan nol,
berarti setidaknya ada satu aplikasi yang bisa menangani intent tersebut dan aman untuk memanggil
{@link android.content.Context#startActivity startActivity()}. Jika hasilnya nol,
Anda tidak boleh menggunakan intent tersebut dan, jika memungkinkan, Anda harus menonaktifkan fitur yang mengeluarkan
intent tersebut.</p>
<pre>
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
</pre>
<p class="note"><strong>Catatan:</strong> Dalam hal ini, URI tidak digunakan, namun tipe data intent
dideklarasikan untuk menetapkan konten yang dibawa oleh ekstra.</p>
<p>Saat {@link android.content.Context#startActivity startActivity()} dipanggil, sistem akan
memeriksa semua aplikasi yang terinstal untuk menentukan aplikasi mana yang bisa menangani intent jenis ini (
intent dengan tindakan {@link android.content.Intent#ACTION_SEND} dan yang membawa data
"teks/polos"). Jika hanya ada satu aplikasi yang bisa menanganinya, aplikasi tersebut akan langsung terbuka dan diberi
intent tersebut. Jika banyak aktivitas menerima intent, sistem akan
menampilkan dialog sehingga pengguna bisa memilih aplikasi mana yang digunakan.</p>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/training/basics/intent-chooser.png" alt="">
<p class="img-caption"><strong>Gambar 2.</strong> Dialog pemilih.</p>
</div>
<h3 id="ForceChooser">Memaksakan pemilih aplikasi</h3>
<p>Bila ada lebih dari satu aplikasi yang merespons intent implisit Anda,
pengguna bisa memilih aplikasi mana yang digunakan dan membuat aplikasi tersebut pilihan default untuk
tindakan tersebut. Ini sangat membantu saat melakukan tindakan di mana pengguna
mungkin ingin menggunakan aplikasi yang sama untuk seterusnya, seperti saat membuka halaman web (pengguna
biasanya memilih hanya satu browser web).</p>
<p>Akan tetapi, jika ada banyak aplikasi yang bisa merespons intent tersebut dan pengguna mungkin ingin menggunakan aplikasi
yang berbeda untuk setiap kalinya, Anda harus menampilkan dialog pemilih secara eksplisit. Dialog pemilih akan meminta
pengguna memilih aplikasi yang akan digunakan untuk tindakan tertentu setiap kali (pengguna tidak bisa memilih aplikasi default untuk
tindakan tersebut). Misalnya, saat aplikasi Anda melakukan "berbagi" dengan tindakan {@link
android.content.Intent#ACTION_SEND}, pengguna mungkin ingin berbagi menggunakan aplikasi berbeda sesuai
dengan situasi mereka saat itu, jadi Anda harus selalu menggunakan dialog pemilih, seperti yang ditampilkan dalam gambar 2.</p>
<p>Untuk menampilkan pemilih, buatlah {@link android.content.Intent} menggunakan {@link
android.content.Intent#createChooser createChooser()} dan teruskan ke {@link
android.app.Activity#startActivity startActivity()}. Misalnya:</p>
<pre>
Intent sendIntent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);
// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
</pre>
<p>Ini menampilkan dialog dengan daftar aplikasi yang merespons intent yang diteruskan ke metode {@link
android.content.Intent#createChooser createChooser()} dan menggunakan teks yang disediakan sebagai
judul dialog.</p>
<h2 id="Receiving">Menerima Intent Implisit</h2>
<p>Untuk mengiklankan intent implisit yang bisa diterima aplikasi Anda, deklarasikan satu atau beberapa filter intent untuk
tiap komponen aplikasi dengan elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
dalam <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">file manifes</a> Anda.
Tiap filter intent menetapkan tipe intent yang diterimanya berdasarkan tindakan intent,
data, dan kategori. Sistem akan mengirim intent implisit ke komponen aplikasi Anda hanya jika
intent tersebut bisa diteruskan melalui salah satu filter intent.</p>
<p class="note"><strong>Catatan:</strong> Intent eksplisit selalu dikirimkan ke targetnya,
apa pun filter intent yang dideklarasikan komponen.</p>
<p>Komponen aplikasi harus mendeklarasikan filter terpisah untuk setiap pekerjaan unik yang bisa dilakukannya.
Misalnya, satu aktivitas dalam aplikasi galeri gambar bisa memiliki dua filter: satu filter
untuk melihat gambar, dan filter lainnya untuk mengedit gambar. Bila aktivitas dimulai,
aktivitas akan memeriksa {@link android.content.Intent} dan menentukan cara berperilaku berdasarkan informasi
dalam {@link android.content.Intent} (misalnya menampilkan kontrol editor atau tidak).</p>
<p>Tiap filter intent didefinisikan oleh elemen <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>
dalam file manifes aplikasi, yang tersarang dalam komponen aplikasi terkait (seperti
elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
). Di dalam <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code &lt;intent-filter&gt;}</a>,
Anda bisa menetapkan tipe intent yang akan diterima dengan menggunakan salah satu atau beberapa
dari tiga elemen ini:</p>
<dl>
<dt><a href="{@docRoot}guide/topics/manifest/action-element.html">{@code &lt;action&gt;}</a></dt>
<dd>Mendeklarasikan tindakan intent yang diterima, dalam atribut {@code name}. Nilai
haruslah nilai string literal dari tindakan, bukan konstanta kelas.</dd>
<dt><a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a></dt>
<dd>Mendeklarasikan tipe data yang diterima, menggunakan salah satu atau beberapa atribut yang menetapkan beragam
aspek URI data (<code>scheme</code>, <code>host</code>, <code>port</code>,
<code>path</code>, dll.) dan tipe MIME.</dd>
<dt><a href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a></dt>
<dd>Mendeklarasikan kategori intent yang diterima, dalam atribut {@code name}. Nilai
haruslah nilai string literal dari tindakan, bukan konstanta kelas.
<p class="note"><strong>Catatan:</strong> Untuk menerima intent implisit, Anda
<strong>harus menyertakan</strong> kategori
{@link android.content.Intent#CATEGORY_DEFAULT} dalam filter intent. Metode
{@link android.app.Activity#startActivity startActivity()}dan
{@link android.app.Activity#startActivityForResult startActivityForResult()} memperlakukan semua intent
seolah-olah mendeklarasikan kategori {@link android.content.Intent#CATEGORY_DEFAULT}.
Jika tidak mendeklarasikan kategori ini dalam filter intent Anda, tidak ada intent implisit yang ditetapkan untuk
aktivitas Anda.</p>
</dd>
</dl>
<p>Misalnya, ini adalah deklarasi aktivitas dengan filter intent yang diterima intent
{@link android.content.Intent#ACTION_SEND} bila tipe data berupa teks:</p>
<pre>
&lt;activity android:name="ShareActivity">
&lt;intent-filter>
&lt;action android:name="android.intent.action.SEND"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="text/plain"/>
&lt;/intent-filter>
&lt;/activity>
</pre>
<p>Anda bisa membuat filter yang menyertakan lebih dari satu instance
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code &lt;action&gt;}</a>,
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>, atau
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code &lt;category&gt;}</a>.
Jika Anda melakukannya, Anda hanya perlu memastikan bahwa komponen bisa menangani semua kombinasi
elemen filter tersebut.</p>
<p>Bila ingin menangani beragam jenis intent, namun hanya dalam kombinasi
tindakan, data, dan tipe kategori tertentu, maka Anda harus membuat banyak filter intent.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Membatasi akses ke komponen</h2>
<p>Menggunakan filter intent bukanlah cara yang aman untuk mencegah aplikasi lain memulai
komponen Anda. Walaupun filter intent membatasi komponen agar hanya merespons
jenis intent implisit tertentu, aplikasi lain bisa saja memulai komponen aplikasi Anda
dengan menggunakan intent eksplisit jika pengembangnya menentukan nama komponen Anda.
Jika perlu <em>hanya aplikasi Anda sendiri</em> yang mampu memulai salah satu komponen,
atur atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#exported">{@code
exported}</a> ke {@code "false"} untuk komponen itu.
</p>
</div>
</div>
<p>Intent implisit diuji terhadap filter dengan membandingkan intent dengan masing-masing
dari ketiga elemen. Agar dikirim ke komponen, intent harus lolos ketiga pengujian tersebut.
Jika intent gagal dalam salah satu pengujian, sistem Android tidak akan mengirim intent ke
komponen. Akan tetapi, karena sebuah komponen dapat memiliki beberapa filter intent, intent yang tidak
lolos melalui salah satu filter komponen mungkin akan lolos di filter lain.
Informasi selengkapnya tentang cara sistem menetapkan intent disediakan dalam bagian di bawah ini
tentang <a href="#Resolution">Resolusi Intent</a>.</p>
<p class="caution"><strong>Perhatian:</strong> Untuk menghindari menjalankan
{@link android.app.Service} aplikasi yang berbeda secara tidak sengaja, selalu gunakan intent eksplisit untuk memulai layanan Anda sendiri dan jangan
deklarasikan filter intent untuk layanan Anda.</p>
<p class="note"><strong>Catatan:</strong>
Untuk semua aktivitas, Anda harus mendeklarasikan filter intent dalam file manifes.
Akan tetapi, filter untuk penerima siaran bisa didaftarkan secara dinamis dengan memanggil
{@link android.content.Context#registerReceiver(BroadcastReceiver, IntentFilter, String,
Handler) registerReceiver()}. Anda nanti bisa mencabut pendaftaran penerima dengan {@link
android.content.Context#unregisterReceiver unregisterReceiver()}. Dengan begitu aplikasi Anda
bisa mendengarkan siaran tertentu hanya selama periode waktu yang telah ditetapkan saat aplikasi Anda
berjalan.</p>
<h3 id="ExampleFilters">Contoh filter</h3>
<p>Untuk lebih memahami beberapa perilaku filter intent, lihatlah cuplikan berikut
dari file manifes aplikasi berbagi di jaringan sosial.</p>
<pre>
&lt;activity android:name="MainActivity">
&lt;!-- This activity is the main entry, should appear in app launcher -->
&lt;intent-filter>
&lt;action android:name="android.intent.action.MAIN" />
&lt;category android:name="android.intent.category.LAUNCHER" />
&lt;/intent-filter>
&lt;/activity>
&lt;activity android:name="ShareActivity">
&lt;!-- This activity handles "SEND" actions with text data -->
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.SEND"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="text/plain"/>
&lt;/intent-filter&gt;
&lt;!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.SEND"/>
&lt;action android:name="android.intent.action.SEND_MULTIPLE"/>
&lt;category android:name="android.intent.category.DEFAULT"/>
&lt;data android:mimeType="application/vnd.google.panorama360+jpg"/>
&lt;data android:mimeType="image/*"/>
&lt;data android:mimeType="video/*"/>
&lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>
<p>Aktivitas pertama, {@code MainActivity}, merupakan titik masuk utama aplikasi&mdash;aplikasi yang
terbuka saat pengguna meluncurkan aplikasi dengan ikon launcher:</p>
<ul>
<li>Tindakan {@link android.content.Intent#ACTION_MAIN}
menunjukkan ini adalah titik masuk utama dan tidak mengharapkan data intent apa pun.</li>
<li>Kategori {@link android.content.Intent#CATEGORY_LAUNCHER} menunjukjkan bahwa ikon
aktivitas ini harus ditempatkan dalam launcher aplikasi sistem. Jika elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
tidak menetapkan ikon dengan{@code icon}, maka sistem akan menggunakan ikon dari elemen
<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>.</li>
</ul>
<p>Keduanya harus dipasangkan bersama agar aktivitas muncul dalam launcher aplikasi.</p>
<p>Aktivitas kedua, {@code ShareActivity}, dimaksudkan untuk memudahkan berbagi teks dan konten
media. Walaupun pengguna mungkin memasuki aktivitas ini dengan mengarah ke aktivitas dari {@code MainActivity},
pengguna juga bisa memasukkan {@code ShareActivity} secara langsung dari aplikasi lain yang mengeluarkan intent
implisit yang cocok dengan salah satu dari kedua filter intent.</p>
<p class="note"><strong>Catatan:</strong> Tipe MIME,
<a href="https://developers.google.com/panorama/android/">{@code
application/vnd.google.panorama360+jpg}</a>, merupakan tipe data khusus yang menetapkan
foto panorama, yang bisa Anda tangani dengan API <a href="{@docRoot}reference/com/google/android/gms/panorama/package-summary.html">panorama
Google</a>.</p>
<h2 id="PendingIntent">Menggunakan Intent Tertunda</h2>
<p>Objek {@link android.app.PendingIntent} merupakan pembungkus objek {@link
android.content.Intent}. Tujuan utama {@link android.app.PendingIntent}
adalah memberikan izin pada aplikasi asing
untuk menggunakan {@link android.content.Intent} yang termuat seolah-olah dieksekusi dari
proses aplikasi Anda sendiri.</p>
<p>Kasus penggunaan utama untuk intent tertunda antara lain:</p>
<ul>
<li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan</a>
({@link android.app.NotificationManager}
sistem Android akan mengeksekusi {@link android.content.Intent}) Anda.
<li>Mendeklarasikan intent untuk dieksekusi saat pengguna melakukan tindakan dengan
<a href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a>
(aplikasi layar Home mengeksekusi {@link android.content.Intent}).
<li>Mendeklarasikan intent untuk dieksekusi di waktu yang telah ditetapkan di masa mendatang
({@link android.app.AlarmManager} sistem Android akan mengeksekusi {@link android.content.Intent}).
</ul>
<p>Karena setiap objek {@link android.content.Intent} didesain untuk ditangani oleh tipe
tertentu dari komponen aplikasi (baik {@link android.app.Activity}, {@link android.app.Service}, maupun
{@link android.content.BroadcastReceiver}), jadi {@link android.app.PendingIntent} harus
dibuat dengan pertimbangan yang sama. Saat menggunakan intent tertunda, aplikasi Anda tidak akan
mengeksekusi intent dengan panggilan seperti {@link android.content.Context#startActivity
startActivity()}. Anda harus mendeklarasikan tipe komponen yang dimaksud saat membuat
{@link android.app.PendingIntent} dengan memanggil metode kreator masing-masing:</p>
<ul>
<li>{@link android.app.PendingIntent#getActivity PendingIntent.getActivity()} untuk
{@link android.content.Intent} yang memulai {@link android.app.Activity}.</li>
<li>{@link android.app.PendingIntent#getService PendingIntent.getService()} untuk
{@link android.content.Intent} yang memulai {@link android.app.Service}.</li>
<li>{@link android.app.PendingIntent#getBroadcast PendingIntent.getBroadcast()} untuk
{@link android.content.Intent} yang memulai {@link android.content.BroadcastReceiver}.</li>
</ul>
<p>Kecuali jika aplikasi Anda <em>menerima</em> intent tertunda dari aplikasi lain,
metode di atas untuk membuat {@link android.app.PendingIntent} menjadi satu-satunya metode
{@link android.app.PendingIntent} yang mungkin Anda butuhkan.</p>
<p>Tiap metode mengambil {@link android.content.Context} aplikasi saat itu,
{@link android.content.Intent} yang ingin Anda bungkus, dan satu atau beberapa flag yang menetapkan
cara penggunaan intent (misalnya apakah intent bisa digunakan lebih dari sekali).</p>
<p>Informasi selengkapnya tentang intent tertunda disediakan pada dokumentasi untuk setiap
kasus penggunaan yang bersangkutan, seperti dalam panduan API <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
dan <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a>.</p>
<h2 id="Resolution">Resolusi Intent</h2>
<p>Saat sistem menerima intent implisit yang memulai suatu aktivitas, sistem tersebut akan mencari
aktivitas terbaik untuk intent dengan membandingkan intent dengan filter intent berdasarkan tiga aspek:</p>
<ul>
<li>Tindakan intent
<li>Data intent (baik URI maupun tipe data)
<li>Kategori intent
</ul>
<p>Bagian berikut menjelaskan cara pencocokan intent dengan komponen yang sesuai
sehubungan dengan cara pendeklarasian filter intent dalam file manifes aplikasi.</p>
<h3 id="ActionTest">Pengujian tindakan</h3>
<p>Untuk menetapkan tindakan intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a>. Misalnya:</p>
<pre>
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.EDIT" /&gt;
&lt;action android:name="android.intent.action.VIEW" /&gt;
...
&lt;/intent-filter&gt;
</pre>
<p>Untuk melewati filter ini, tindakan yang ditetapkan dalam {@link android.content.Intent}
harus sesuai dengan salah satu tindakan yang tercantum dalam filter.</p>
<p>Jika filter tidak mencantumkan tindakan apa pun, maka tidak ada intent
yang dicocokkan, jadi semua intent gagal dalam pengujian. Akan tetapi, jika sebuah {@link android.content.Intent}
tidak menetapkan suatu tindakan, maka akan lolos pengujian (asalkan filter
berisi setidaknya satu tindakan).</p>
<h3 id="CategoryTest">Pengujian kategori</h3>
<p>Untuk menetapkan kategori intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a>. Misalnya:</p>
<pre>
&lt;intent-filter&gt;
&lt;category android:name="android.intent.category.DEFAULT" /&gt;
&lt;category android:name="android.intent.category.BROWSABLE" /&gt;
...
&lt;/intent-filter&gt;
</pre>
<p>Agar intent bisa lolos pengujian kategori, setiap kategori dalam {@link android.content.Intent}
harus sesuai dengan kategori dalam filter. Kebalikannya tidak diperlukan&mdash;filter intent bisa
mendeklarasikan kategori lebih banyak daripada yang ditetapkan dalam {@link android.content.Intent} dan
{@link android.content.Intent} tetap akan lolos. Oleh karena itu, intent tanpa kategori harus
selalu lolos pengujian ini, kategori apa pun yang dideklarasikan dalam filter.</p>
<p class="note"><strong>Catatan:</strong>
Android secara otomatis menerapkan kategori {@link android.content.Intent#CATEGORY_DEFAULT}
untuk semua intent implisit yang diteruskan ke {@link
android.content.Context#startActivity startActivity()} dan {@link
android.app.Activity#startActivityForResult startActivityForResult()}.
Jadi jika ingin aktivitas Anda menerima intent implisit, aktivitas tersebut harus
menyertakan kategori untuk{@code "android.intent.category.DEFAULT"} dalam filter intent (seperti
yang ditampilkan dalam contoh{@code &lt;intent-filter&gt;} sebelumnya.</p>
<h3 id="DataTest">Pengujian data</h3>
<p>Untuk menetapkan data intent yang diterima, filter intent bisa mendeklarasikan nol atau beberapa elemen
<a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
&lt;data&gt;}</a>. Misalnya:</p>
<pre>
&lt;intent-filter&gt;
&lt;data android:mimeType="video/mpeg" android:scheme="http" ... /&gt;
&lt;data android:mimeType="audio/mpeg" android:scheme="http" ... /&gt;
...
&lt;/intent-filter&gt;
</pre>
<p>Tiap elemen <code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
bisa menetapkan struktur URI dan tipe data (tipe media MIME). Ada atribut
terpisah &mdash; {@code scheme}, {@code host}, {@code port},
dan {@code path} &mdash; untuk setiap bagian URI:
</p>
<p style="margin-left: 2em">{@code &lt;scheme&gt;://&lt;host&gt;:&lt;port&gt;/&lt;path&gt;}</p>
<p>
Misalnya:
</p>
<p style="margin-left: 2em">{@code content://com.example.project:200/folder/subfolder/etc}</p>
<p>Dalam URI ini, skemanya adalah {@code content}, host-nya adalah {@code com.example.project},
port-nya adalah {@code 200}, dan path-nya adalah {@code folder/subfolder/etc}.
</p>
<p>Tiap atribut bersifat opsional dalam elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>,
namun ada dependensi linear:</p>
<ul>
<li>Jika skema tidak ditetapkan, host akan diabaikan.</li>
<li>Jika host tidak ditetapkan, port akan diabaikan.</li>
<li>Jika skema dan host tidak ditetapkan, path akan diabaikan.</li>
</ul>
<p>Bila URI dalam intent dibandingkan dengan spesifikasi URI dalam filter,
pembandingannya hanya dengan bagian URI yang disertakan dalam filter. Misalnya:</p>
<ul>
<li>Jika sebuah filter menetapkan hanya satu skema, semua URI dengan skema tersebut akan cocok
dengan filter.</li>
<li>Jika sebuah filter menetapkan satu skema dan satu otoritas namun tanpa path, semua URI
dengan skema dan otoritas yang sama akan lolos dari filter, apa pun path-nya.</li>
<li>Jika sebuah filter menetapkan satu skema, otoritas dan path, hanya URI dengan skema,
otoritas, dan path sama yang bisa lolos dari filter.</li>
</ul>
<p class="note"><strong>Catatan:</strong> Spesifikasi path bisa berisi
wildcard bintang (*) untuk hanya mencocokkan nama path secara parsial.</p>
<p>Pengujian data membandingkan URI maupun tipe MIME dalam intent dengan URI
dan tipe MIME yang ditetapkan dalam filter. Aturannya adalah sebagai berikut:
</p>
<ol type="a">
<li>Intent yang tidak berisi URI maupun tipe MIME hanya akan lolos
pengujian jika filter tersebut tidak menetapkan URI atau tipe MIME apa pun.</li>
<li>Intent yang berisi URI namun tidak berisi tipe MIME (baik secara eksplisit maupun tidak langsung dari
URI) hanya akan lolos pengujian jika URI-nya cocok dengan format URI filter
dan filternya juga tidak menetapkan tipe MIME.</li>
<li>Intent yang berisi tipe MIME namun tidak berisi URI hanya akan lolos pengujian
jika filter mencantumkan tipe MIME yang sama dan tidak menetapkan format URI.</li>
<li>Intent yang berisi URI maupun tipe MIME (baik secara eksplisit maupun tidak langsung dari
URI) hanya akan lolos pengujian bagian tipe MIME jika
tipe tersebut cocok dengan tipe yang dicantumkan dalam filter. Ini akan lolos pengujian bagian URI
jika URI-nya cocok dengan URI dalam filter atau memiliki {@code content:}
atau URI {@code file:} dan filter tidak menetapkan URI. Dengan kata lain,
komponen dianggap mendukung data {@code content:} dan {@code file:} jika
filternya <em>hanya</em> mencantumkan tipe MIME.</p></li>
</ol>
<p>
Aturan terakhir ini, aturan (d), mencerminkan harapan
bahwa komponen mampu mendapatkan data lokal dari file atau penyedia konten.
Oleh karena itu, filter mereka mencatumkan tipe data saja dan tidak secara eksplisit
harus menamai skema {@code content:} dan {@code file:}.
Ini adalah kasus umum. Elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>
seperti berikut ini, misalnya, memberi tahu Android bahwa komponen bisa mengambil data gambar dari penyedia
konten dan menampilkannya:
</p>
<pre>
&lt;intent-filter&gt;
&lt;data android:mimeType="image/*" /&gt;
...
&lt;/intent-filter&gt;</pre>
<p>
Karena sebagian besar data yang tersedia dikeluarkan oleh penyedia konten, filter yang
menetapkan tipe data namun bukan URI mungkin adalah yang paling umum.
</p>
<p>
Konfigurasi umum yang lain adalah filter dengan skema dan tipe data. Misalnya
, elemen <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code &lt;data&gt;}</a>
seperti berikut ini akan memberi tahu Android bahwa
komponen bisa mengambil data video dari jaringan untuk melakukan tindakan:
</p>
<pre>
&lt;intent-filter&gt;
&lt;data android:scheme="http" android:type="video/*" /&gt;
...
&lt;/intent-filter&gt;</pre>
<h3 id="imatch">Pencocokan intent</h3>
<p>Intent dicocokkan dengan filter intent selain untuk menemukan komponen
target yang akan diaktifkan, juga untuk menemukan sesuatu tentang rangkaian
komponen pada perangkat. Misalnya, aplikasi Home akan menempatkan launcher aplikasi
dengan mencari semua aktivitas dengan filter intent yang menetapkan tindakan
{@link android.content.Intent#ACTION_MAIN} dan
kategori {@link android.content.Intent#CATEGORY_LAUNCHER}.</p>
<p>Aplikasi Anda bisa menggunakan pencocokan intent dengan cara serupa.
{@link android.content.pm.PackageManager} memiliki seperangkat metode {@code query...()}
yang mengembalikan semua komponen yang bisa menerima intent tertentu, dan
serangkaian metode{@code resolve...()} serupa yang menentukan komponen
terbaik untuk merespons intent. Misalnya,
{@link android.content.pm.PackageManager#queryIntentActivities
queryIntentActivities()} akan mengembalikan daftar semua aktivitas yang bisa melakukan
intent yang diteruskan sebagai argumen, dan {@link
android.content.pm.PackageManager#queryIntentServices
queryIntentServices()} akan mengembalikan daftar layanan serupa.
Tidak ada metode yang akan mengaktifkan komponen; mereka hanya mencantumkan komponen yang
bisa merespons. Ada metode serupa,
{@link android.content.pm.PackageManager#queryBroadcastReceivers
queryBroadcastReceivers()}, untuk penerima siaran.
</p>

View File

@@ -0,0 +1,494 @@
page.title=Aktivitas
parent.title=Loader
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#summary">Rangkuman Loader API</a></li>
<li><a href="#app">Menggunakan Loader dalam Aplikasi</a>
<ol>
<li><a href="#requirements"></a></li>
<li><a href="#starting">Memulai Loader</a></li>
<li><a href="#restarting">Me-restart Loader</a></li>
<li><a href="#callback">Menggunakan Callback LoaderManager</a></li>
</ol>
</li>
<li><a href="#example">Contoh</a>
<ol>
<li><a href="#more_examples">Contoh Selengkapnya</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.LoaderManager}</li>
<li>{@link android.content.Loader}</li>
</ol>
<h2>Contoh-contoh terkait</h2>
<ol>
<li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
LoaderCursor</a></li>
<li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html">
LoaderThrottle</a></li>
</ol>
</div>
</div>
<p>Diperkenalkan di Android 3.0, loader memudahkan pemuatan data asinkron
dalam aktivitas atau fragmen. Loader memiliki karakteristik ini:</p>
<ul>
<li>Loader tersedia untuk setiap {@link android.app.Activity} dan {@link
android.app.Fragment}.</li>
<li>Loader menyediakan pemuatan data asinkron.</li>
<li>Loader memantau sumber data mereka dan memberikan hasil baru bila
konten berubah.</li>
<li>Loader secara otomatis menghubungkan kembali ke kursor loader lalu saat
dibuat kembali setelah perubahan konfigurasi. Karena itu, loader tidak perlu melakukan query ulang
datanya.</li>
</ul>
<h2 id="summary">Rangkuman Loader API</h2>
<p>Ada beberapa kelas dan antarmuka yang mungkin dilibatkan dalam menggunakan
loader pada aplikasi. Semuanya dirangkum dalam tabel ini:</p>
<table>
<tr>
<th>Kelas/Antarmuka</th>
<th>Keterangan</th>
</tr>
<tr>
<td>{@link android.app.LoaderManager}</td>
<td>Kelas abstrak yang dikaitkan dengan {@link android.app.Activity} atau
{@link android.app.Fragment} untuk mengelola satu atau beberapa instance {@link
android.content.Loader}. Ini membantu aplikasi mengelola
operasi berjalan lebih lama bersamaan dengan daur hidup {@link android.app.Activity}
atau {@link android.app.Fragment}; penggunaan paling umumnya adalah dengan
{@link android.content.CursorLoader}, akan tetapi aplikasi bebas menulis loader-nya
sendiri untuk memuat tipe data lainnya.
<br />
<br />
Hanya ada satu {@link android.app.LoaderManager} per aktivitas atau fragmen. Namun {@link android.app.LoaderManager} bisa memiliki
beberapa loader.</td>
</tr>
<tr>
<td>{@link android.app.LoaderManager.LoaderCallbacks}</td>
<td>Antarmuka callback untuk klien berinteraksi dengan {@link
android.app.LoaderManager}. Misalnya, Anda menggunakan metode callback {@link
android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
untuk membuat loader baru.</td>
</tr>
<tr>
<td>{@link android.content.Loader}</td>
<td>Kelas abstrak yang melakukan pemuatan data asinkron. Ini
adalah kelas dasar untuk loader. Biasanya Anda akan menggunakan {@link
android.content.CursorLoader}, namun Anda bisa menerapkan subkelas sendiri. Selagi
loader aktif, loader harus memantau sumber datanya dan memberikan hasil
baru bila konten berubah. </td>
</tr>
<tr>
<td>{@link android.content.AsyncTaskLoader}</td>
<td>Loader abstrak yang menyediakan {@link android.os.AsyncTask} untuk melakukan pekerjaan.</td>
</tr>
<tr>
<td>{@link android.content.CursorLoader}</td>
<td>Subkelas {@link android.content.AsyncTaskLoader} yang meng-query
{@link android.content.ContentResolver} dan mengembalikan {@link
android.database.Cursor}. Kelas ini mengimplementasikan protokol {@link
android.content.Loader} dengan cara standar untuk query kursor,
yang dibuat berdasarkan {@link android.content.AsyncTaskLoader} untuk melakukan query kursor
pada thread latar belakang agar tidak memblokir UI aplikasi. Menggunakan loader
ini merupakan cara terbaik untuk memuat data secara asinkron dari {@link
android.content.ContentProvider}, sebagai ganti melakukan query terkelola melalui
fragmen atau API aktivitas.</td>
</tr>
</table>
<p>Kelas dan antarmuka dalam tabel di atas merupakan komponen
esensial yang akan Anda gunakan untuk mengimplementasikan loader dalam aplikasi Anda. Anda tidak memerlukan semuanya
untuk setiap loader yang dibuat, namun Anda akan selalu memerlukan acuan ke {@link
android.app.LoaderManager} untuk memulai loader dan implementasi
kelas {@link android.content.Loader} seperti {@link
android.content.CursorLoader}. Bagian berikut ini menunjukkan kepada Anda cara menggunakan
kelas dan antarmuka ini dalam aplikasi.</p>
<h2 id ="app">Menggunakan Loader dalam Aplikasi</h2>
<p>Bagian ini menjelaskan cara menggunakan loader dalam aplikasi Android. Aplikasi
yang menggunakan loader biasanya berisi yang berikut ini:</p>
<ul>
<li>{@link android.app.Activity} atau {@link android.app.Fragment}.</li>
<li>Instance {@link android.app.LoaderManager}.</li>
<li>{@link android.content.CursorLoader} akan memuat data yang didukung oleh {@link
android.content.ContentProvider}. Atau, Anda dapat mengimplementasikan subkelas sendiri
dari {@link android.content.Loader} atau {@link android.content.AsyncTaskLoader} untuk
memuat data dari beberapa sumber lain.</li>
<li>Implementasi untuk {@link android.app.LoaderManager.LoaderCallbacks}.
Di sinilah Anda membuat loader baru dan mengelola acuan bagi loader
yang ada.</li>
<li>Cara menampilkan data loader, seperti {@link
android.widget.SimpleCursorAdapter}.</li>
<li>Sumber data, seperti {@link android.content.ContentProvider}, saat menggunakan
{@link android.content.CursorLoader}.</li>
</ul>
<h3 id="starting">Memulai Loader</h3>
<p>{@link android.app.LoaderManager} mengelola satu atau beberapa instance {@link
android.content.Loader} dalam {@link android.app.Activity} atau
{@link android.app.Fragment}. Hanya ada satu {@link
android.app.LoaderManager} per aktivitas atau fragmen.</p>
<p>Anda biasanya
memulai {@link android.content.Loader} dalam metode {@link
android.app.Activity#onCreate onCreate()} aktivitas, atau dalam metode
{@link android.app.Fragment#onActivityCreated onActivityCreated()} fragmen. Anda
melakukannya dengan cara berikut ini:</p>
<pre>// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);</pre>
<p>Metode {@link android.app.LoaderManager#initLoader initLoader()} mengambil
parameter berikut:</p>
<ul>
<li>ID unik yang mengidentifikasi loader. Dalam contoh ini, ID-nya adalah 0.</li>
<li>Argumen opsional untuk dipasok ke loader
pada saat pembuatan (dalam contoh ini <code>null</code>).</li>
<li>Implementasi {@link android.app.LoaderManager.LoaderCallbacks}, yang
akan dipanggil {@link android.app.LoaderManager} untuk melaporkan kejadian loader. Dalam contoh
ini, kelas lokal mengimplementasikan antarmuka {@link
android.app.LoaderManager.LoaderCallbacks}, sehingga meneruskan acuan
ke dirinya sendiri, {@code this}.</li>
</ul>
<p>Panggilan {@link android.app.LoaderManager#initLoader initLoader()} memastikan bahwa loader
telah dimulai dan aktif. Ia memiliki dua kemungkinan hasil:</p>
<ul>
<li>Jika loader yang disebutkan oleh ID sudah ada, loader yang dibuat terakhir akan digunakan
kembali.</li>
<li>Jika loader yang disebutkan oleh ID <em>tidak</em> ada,
{@link android.app.LoaderManager#initLoader initLoader()} akan memicu metode
{@link android.app.LoaderManager.LoaderCallbacks} {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}.
Di sinilah Anda mengimplementasikan kode untuk membuat instance dan mengembalikan loader baru.
Untuk diskusi selengkapnya, lihat bagian <a href="#onCreateLoader">onCreateLoader</a>.</li>
</ul>
<p>Dalam hal ini, implementasi {@link android.app.LoaderManager.LoaderCallbacks}
yang ditentukan akan dikaitkan dengan loader, dan akan dipanggil bila
status loader berubah. Jika saat panggilan ini status pemanggil sudah
dimulai, dan loader yang diminta sudah ada dan telah menghasilkan
datanya, maka sistem segera memanggil {@link
android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
(selama {@link android.app.LoaderManager#initLoader initLoader()}),
sehingga Anda harus siap bila hal ini terjadi. Lihat <a href="#onLoadFinished">
onLoadFinished</a> untuk diskusi selengkapnya mengenai callback ini</p>
<p>Perhatikan bahwa metode {@link android.app.LoaderManager#initLoader initLoader()}
mengembalikan {@link android.content.Loader} yang dibuat, namun Anda tidak
perlu menangkap acuan ke sana. {@link android.app.LoaderManager} mengelola
masa hidup loader secara otomatis. {@link android.app.LoaderManager}
memulai dan menghentikan pemuatan jika perlu, dan menjaga status loader
dan konten terkaitnya. Seperti yang tersirat di sini, Anda akan jarang berinteraksi dengan loader
secara langsung (meskipun misalnya menggunakan metode loader untuk menyempurnakan perilaku
loader, lihat contoh <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a>).
Anda paling sering akan menggunakan metode {@link
android.app.LoaderManager.LoaderCallbacks} untuk mengintervensi proses
pemuatan saat terjadi kejadian tertentu. Untuk diskusi selengkapnya mengenai topik ini, lihat <a href="#callback">Menggunakan Callback LoaderManager</a>.</p>
<h3 id="restarting">Me-restart Loader</h3>
<p>Bila Anda menggunakan {@link android.app.LoaderManager#initLoader initLoader()}, seperti
ditampilkan di atas, loader yang ada akan digunakan dengan ID yang ditetapkan jika ada.
Jika tidak ada, ID akan dibuat. Namun kadang-kadang Anda perlu membuang data lama
dan mulai dari awal.</p>
<p>Untuk membuang data lama, gunakan {@link
android.app.LoaderManager#restartLoader restartLoader()}. Misalnya, implementasi
{@link android.widget.SearchView.OnQueryTextListener} ini akan me-restart
bila query pengguna berubah. Loader perlu di-restart
agar dapat menggunakan filter pencarian yang telah direvisi untuk melakukan query baru:</p>
<pre>
public boolean onQueryTextChanged(String newText) {
// Called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
getLoaderManager().restartLoader(0, null, this);
return true;
}</pre>
<h3 id="callback">Menggunakan Callback LoaderManager</h3>
<p>{@link android.app.LoaderManager.LoaderCallbacks} adalah antarmuka callback
yang memungkinkan klien berinteraksi dengan {@link android.app.LoaderManager}. </p>
<p>Loader, khususnya {@link android.content.CursorLoader}, diharapkan
mempertahankan datanya setelah dihentikan. Ini memungkinkan aplikasi mempertahankan
datanya di aktivitas atau metode {@link android.app.Activity#onStop
onStop()} fragmen dan {@link android.app.Activity#onStart onStart()}, sehingga
bila pengguna kembali ke aplikasi, mereka tidak harus menunggu data
dimuat kembali. Anda menggunakan metode {@link android.app.LoaderManager.LoaderCallbacks}
untuk mengetahui waktu membuat loader baru, dan memberi tahu aplikasi kapan
berhenti menggunakan data loader.</p>
<p>{@link android.app.LoaderManager.LoaderCallbacks} berisi metode
ini:</p>
<ul>
<li>{@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} —
Membuat instance dan mengembalikan {@link android.content.Loader} baru untuk ID yang diberikan.
</li></ul>
<ul>
<li> {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}
— Dipanggil bila loader yang dibuat sebelumnya selesai dimuat.
</li></ul>
<ul>
<li>{@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}
— Dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya
tidak tersedia.
</li>
</ul>
<p>Metode ini dijelaskan lebih detail dalam bagian berikutnya.</p>
<h4 id ="onCreateLoader">onCreateLoader</h4>
<p>Saat Anda mencoba mengakses loader (misalnya, melalui {@link
android.app.LoaderManager#initLoader initLoader()}), ia akan memeriksa untuk mengetahui adanya
loader yang ditetapkan oleh ID. Jika tidak ada, ia akan memicu metode {@link
android.app.LoaderManager.LoaderCallbacks} {@link
android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. Di
sinilah Anda membuat loader baru. Biasanya ini adalah {@link
android.content.CursorLoader}, namun Anda bisa mengimplementasikan sendiri subkelas {@link
android.content.Loader}. </p>
<p>Dalam contoh ini, metode callback {@link
android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}
akan membuat {@link android.content.CursorLoader}. Anda harus membuat
{@link android.content.CursorLoader} menggunakan metode konstruktornya, yang
memerlukan set informasi lengkap untuk melakukan query ke {@link
android.content.ContentProvider}. Secara khusus, ia memerlukan:</p>
<ul>
<li><em>uri</em> — URI untuk konten yang akan diambil. </li>
<li><em>projection</em> — Daftar berisi kolom yang akan dikembalikan. Meneruskan
<code>null</code> akan mengembalikan semua kolom, jadi tidak efisien. </li>
<li><em>selection</em> — Filter yang mendeklarasikan baris yang akan dikembalikan,
diformat sebagai klausa SQL WHERE (tidak termasuk WHERE itu sendiri). Meneruskan
<code>null</code> akan mengembalikan semua baris untuk URI yang diberikan. </li>
<li><em>selectionArgs</em> — Anda dapat menyertakan ?s dalam pilihan, yang akan
digantikan dengan nilai dari <em>selectionArgs</em>, agar muncul dalam
pilihan. Nilai-nilai akan diikat sebagai String. </li>
<li><em>sortOrder</em> — Cara menyusun baris, diformat sebagai klausa SQL
ORDER BY (tidak termasuk ORDER BY itu sendiri). Meneruskan <code>null</code> akan
menggunakan urutan sortir default, yang mungkin tidak berurutan.</li>
</ul>
<p>Misalnya:</p>
<pre>
// If non-null, this is the current filter the user has provided.
String mCurFilter;
...
public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created.  This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri;
    if (mCurFilter != null) {
        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                Uri.encode(mCurFilter));
    } else {
        baseUri = Contacts.CONTENT_URI;
    }
    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
            + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
            + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
}</pre>
<h4 id="onLoadFinished">onLoadFinished</h4>
<p>Metode ini dipanggil bila loader yang dibuat sebelumnya selesai dimuat.
Metode ini dijamin dipanggil sebelum pelepasan data terakhir
yang disediakan untuk loader ini. Di titik ini Anda harus menyingkirkan semua penggunaan
data lama (karena akan segera dilepas), namun jangan melepas sendiri
data tersebut karena loader memilikinya dan akan menanganinya.</p>
<p>Loader akan melepas data setelah mengetahui bahwa aplikasi tidak
lagi menggunakannya. Misalnya, jika data adalah kursor dari {@link
android.content.CursorLoader}, Anda tidak boleh memanggil {@link
android.database.Cursor#close close()} sendiri. Jika kursor ditempatkan
dalam {@link android.widget.CursorAdapter}, Anda harus menggunakan metode {@link
android.widget.SimpleCursorAdapter#swapCursor swapCursor()} agar
{@link android.database.Cursor} lama tidak ditutup. Misalnya:</p>
<pre>
// This is the Adapter being used to display the list's data.<br
/>SimpleCursorAdapter mAdapter;
...
public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
// Swap the new cursor in.  (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
}</pre>
<h4 id="onLoaderReset">onLoaderReset</h4>
<p>Metode ini dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya
tidak tersedia. Callback ini memungkinkan Anda mengetahui
kapan data akan dilepas sehingga dapat menghapus acuannya ke callback.  </p>
<p>Implementasi ini memanggil
{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}
dengan nilai <code>null</code>:</p>
<pre>
// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
...
public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed.  We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}</pre>
<h2 id="example">Contoh</h2>
<p>Sebagai contoh, berikut ini adalah implementasi penuh {@link
android.app.Fragment} yang menampilkan {@link android.widget.ListView} berisi
hasil query terhadap penyedia konten kontak. Ia menggunakan {@link
android.content.CursorLoader} untuk mengelola query pada penyedia.</p>
<p>Agar aplikasi dapat mengakses kontak pengguna, seperti yang ditampilkan dalam contoh ini,
manifesnya harus menyertakan izin
{@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.</p>
<pre>
public static class CursorLoaderListFragment extends ListFragment
        implements OnQueryTextListener, LoaderManager.LoaderCallbacks&lt;Cursor&gt; {
// This is the Adapter being used to display the list's data.
    SimpleCursorAdapter mAdapter;
    // If non-null, this is the current filter the user has provided.
    String mCurFilter;
    @Override public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // Give some text to display if there is no data.  In a real
        // application this would come from a resource.
        setEmptyText(&quot;No phone numbers&quot;);
        // We have a menu item to show in action bar.
        setHasOptionsMenu(true);
        // Create an empty adapter we will use to display the loaded data.
        mAdapter = new SimpleCursorAdapter(getActivity(),
                android.R.layout.simple_list_item_2, null,
                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
                new int[] { android.R.id.text1, android.R.id.text2 }, 0);
        setListAdapter(mAdapter);
        // Prepare the loader.  Either re-connect with an existing one,
        // or start a new one.
        getLoaderManager().initLoader(0, null, this);
    }
    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Place an action bar item for searching.
        MenuItem item = menu.add(&quot;Search&quot;);
        item.setIcon(android.R.drawable.ic_menu_search);
        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        SearchView sv = new SearchView(getActivity());
        sv.setOnQueryTextListener(this);
        item.setActionView(sv);
    }
    public boolean onQueryTextChange(String newText) {
        // Called when the action bar search text has changed.  Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }
    @Override public boolean onQueryTextSubmit(String query) {
        // Don't care about this.
        return true;
    }
    @Override public void onListItemClick(ListView l, View v, int position, long id) {
        // Insert desired behavior here.
        Log.i(&quot;FragmentComplexList&quot;, &quot;Item clicked: &quot; + id);
    }
    // These are the Contacts rows that we will retrieve.
    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
        Contacts._ID,
        Contacts.DISPLAY_NAME,
        Contacts.CONTACT_STATUS,
        Contacts.CONTACT_PRESENCE,
        Contacts.PHOTO_ID,
        Contacts.LOOKUP_KEY,
    };
    public Loader&lt;Cursor&gt; onCreateLoader(int id, Bundle args) {
        // This is called when a new Loader needs to be created.  This
        // sample only has one Loader, so we don't care about the ID.
        // First, pick the base URI to use depending on whether we are
        // currently filtering.
        Uri baseUri;
        if (mCurFilter != null) {
            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                    Uri.encode(mCurFilter));
        } else {
            baseUri = Contacts.CONTENT_URI;
        }
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        String select = &quot;((&quot; + Contacts.DISPLAY_NAME + &quot; NOTNULL) AND (&quot;
                + Contacts.HAS_PHONE_NUMBER + &quot;=1) AND (&quot;
                + Contacts.DISPLAY_NAME + &quot; != '' ))&quot;;
        return new CursorLoader(getActivity(), baseUri,
                CONTACTS_SUMMARY_PROJECTION, select, null,
                Contacts.DISPLAY_NAME + &quot; COLLATE LOCALIZED ASC&quot;);
    }
    public void onLoadFinished(Loader&lt;Cursor&gt; loader, Cursor data) {
        // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        mAdapter.swapCursor(data);
    }
    public void onLoaderReset(Loader&lt;Cursor&gt; loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed.  We need to make sure we are no
        // longer using it.
        mAdapter.swapCursor(null);
    }
}</pre>
<h3 id="more_examples">Contoh Selengkapnya</h3>
<p>Ada beberapa contoh berbeda dalam <strong>ApiDemos</strong> yang
mengilustrasikan cara menggunakan loader:</p>
<ul>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.html">
LoaderCursor</a> — Versi lengkap dari
cuplikan yang ditampilkan di atas.</li>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> — Contoh cara penggunaan throttling untuk
mengurangi jumlah query dari penyedia konten saat datanya berubah.</li>
</ul>
<p>Untuk informasi tentang mengunduh dan menginstal contoh SDK, lihat <a href="http://developer.android.com/resources/samples/get.html"> Mendapatkan
Contoh</a>. </p>

View File

@@ -0,0 +1,411 @@
page.title=Proses dan Thread
page.tags=daur hidup,latar belakang
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Processes">Proses</a>
<ol>
<li><a href="#Lifecycle">Daur hidup proses</a></li>
</ol>
</li>
<li><a href="#Threads">Thread</a>
<ol>
<li><a href="#WorkerThreads">Thread pekerja</a></li>
<li><a href="#ThreadSafe">Metode thread-safe</a></li>
</ol>
</li>
<li><a href="#IPC">Komunikasi antarproses</a></li>
</ol>
</div>
</div>
<p>Bila komponen aplikasi dimulai dan tidak ada komponen aplikasi lain yang
berjalan, sistem Android akan memulai proses Linux baru untuk aplikasi dengan satu thread
eksekusi. Secara default, semua komponen aplikasi yang sama berjalan dalam proses dan
thread yang sama (disebut thread "utama"). Jika komponen aplikasi dimulai dan sudah ada
proses untuk aplikasi itu (karena komponen lain dari aplikasi itu sudah ada), maka komponen
akan dimulai dalam proses itu dan menggunakan thread eksekusi yang sama. Akan tetapi, Anda bisa
mengatur komponen berbeda di aplikasi agar berjalan di proses terpisah, dan Anda bisa membuat thread tambahan untuk
setiap proses.</p>
<p>Dokumen ini membahas cara kerja proses dan thread di aplikasi Android.</p>
<h2 id="Processes">Proses</h2>
<p>Secara default, semua komponen aplikasi yang sama berjalan dalam proses yang sama dan kebanyakan
aplikasi tidak boleh mengubah ini. Akan tetapi, jika Anda merasa perlu mengontrol proses milik
komponen tertentu, Anda dapat melakukannya dalam file manifes.</p>
<p>Entri manifes untuk setiap tipe elemen komponen&mdash;<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a>, <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code
&lt;service&gt;}</a>, <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
&lt;receiver&gt;}</a>, dan <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code
&lt;provider&gt;}</a>&mdash;mendukung atribut {@code android:process} yang bisa menetapkan
dalam proses mana komponen harus dijalankan. Anda bisa mengatur atribut ini agar setiap komponen
berjalan dalam prosesnya sendiri atau agar beberapa komponen menggunakan proses yang sama sementara yang lainnya tidak. Anda juga bisa mengatur
{@code android:process} agar komponen aplikasi yang berbeda berjalan dalam proses yang sama
&mdash;sepanjang aplikasi menggunakan ID Linux yang sama dan ditandatangani
dengan sertifikat yang sama.</p>
<p>Elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code
&lt;application&gt;}</a> juga mendukung atribut {@code android:process}, untuk mengatur
nilai default yang berlaku bagi semua komponen.</p>
<p>Android bisa memutuskan untuk mematikan proses pada waktu tertentu, bila memori tinggal sedikit dan diperlukan oleh
proses lain yang lebih mendesak untuk melayani pengguna. Komponen
aplikasi yang berjalan dalam proses yang dimatikan maka sebagai konsekuensinya juga akan dimusnahkan. Proses dimulai
kembali untuk komponen itu bila ada lagi pekerjaan untuk mereka lakukan.</p>
<p>Saat memutuskan proses yang akan dimatikan, sistem Android akan mempertimbangkan kepentingan relatifnya bagi
pengguna. Misalnya, sistem lebih mudah menghentikan proses yang menjadi host aktivitas yang tidak
lagi terlihat di layar, dibandingkan dengan proses yang menjadi host aktivitas yang terlihat. Karena itu, keputusan
untuk menghentikan proses bergantung pada keadaan komponen yang berjalan dalam proses tersebut. Aturan
yang digunakan untuk menentukan proses yang akan dihentikan dibahas di bawah ini. </p>
<h3 id="Lifecycle">Daur hidup proses</h3>
<p>Sistem Android mencoba mempertahankan proses aplikasi selama mungkin, namun
pada akhirnya perlu menghapus proses lama untuk mengambil kembali memori bagi proses baru atau yang lebih penting. Untuk
menentukan proses yang akan
dipertahankan dan yang harus dimatikan, sistem menempatkan setiap proses ke dalam "hierarki prioritas" berdasarkan
komponen yang berjalan dalam proses dan status komponen tersebut. Proses yang memiliki
prioritas terendah akan dimatikan terlebih dahulu, kemudian yang terendah berikutnya, dan seterusnya, jika perlu
untuk memulihkan sumber daya sistem.</p>
<p>Ada lima tingkatan dalam hierarki prioritas. Daftar berikut berisi beberapa
tipe proses berdasarkan urutan prioritas (proses pertama adalah yang <em>terpenting</em> dan
<em>dimatikan terakhir</em>):</p>
<ol>
<li><b>Proses latar depan</b>
<p>Proses yang diperlukan untuk aktivitas yang sedang dilakukan pengguna. Proses
dianggap berada di latar depan jika salah satu kondisi berikut terpenuhi:</p>
<ul>
<li>Proses menjadi host {@link android.app.Activity} yang berinteraksi dengan pengguna dengan metode ({@link
android.app.Activity}{@link android.app.Activity#onResume onResume()} telah
dipanggil).</li>
<li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang sedang berinteraksi dengan
pengguna.</li>
<li>Proses menjadi host {@link android.app.Service} yang berjalan "di latar depan"&mdash;
layanan telah memanggil{@link android.app.Service#startForeground startForeground()}.
<li>Proses menjadi host {@link android.app.Service} yang menjalankan salah satu callback
daur hidupnya ({@link android.app.Service#onCreate onCreate()}, {@link android.app.Service#onStart
onStart()}, atau {@link android.app.Service#onDestroy onDestroy()}).</li>
<li>Proses menjadi host {@link android.content.BroadcastReceiver} yang menjalankan metode {@link
android.content.BroadcastReceiver#onReceive onReceive()}-nya.</li>
</ul>
<p>Secara umum, hanya ada beberapa proses latar depan pada waktu yang diberikan. Proses dimatikan hanya sebagai
upaya terakhir&mdash; jika memori hampir habis sehingga semuanya tidak bisa terus berjalan. Pada umumnya, pada
titik itu, perangkat dalam keadaan memory paging, sehingga menghentikan beberapa proses latar depan
diperlukan agar antarmuka pengguna tetap responsif.</p></li>
<li><b>Proses yang terlihat</b>
<p>Proses yang tidak memiliki komponen latar depan, namun masih bisa
memengaruhi apa yang dilihat pengguna di layar. Proses dianggap terlihat jika salah satu kondisi
berikut terpenuhi:</p>
<ul>
<li>Proses ini menjadi host {@link android.app.Activity} yang tidak berada di latar depan, namun masih
terlihat oleh penggunanya (metode {@link android.app.Activity#onPause onPause()} telah dipanggil).
Ini bisa terjadi, misalnya, jika aktivitas latar depan memulai dialog, sehingga
aktivitas sebelumnya terlihat berada di belakangnya.</li>
<li>Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang terlihat (atau latar
depan)</li>
</ul>
<p>Proses yang terlihat dianggap sangat penting dan tidak akan dimatikan kecuali jika hal itu
diperlukan agar semua proses latar depan tetap berjalan. </p>
</li>
<li><b>Proses layanan</b>
<p>Proses yang menjalankan layanan yang telah dimulai dengan metode {@link
android.content.Context#startService startService()} dan tidak termasuk dalam salah satu dari dua kategori
yang lebih tinggi. Walaupun proses pelayanan tidak langsung terkait dengan semua yang dilihat oleh pengguna, proses ini
umumnya melakukan hal-hal yang dipedulikan pengguna (seperti memutar musik di latar belakang
atau mengunduh data di jaringan), jadi sistem membuat proses tetap berjalan kecuali memori tidak cukup untuk
mempertahankannya bersama semua proses latar depan dan proses yang terlihat. </p>
</li>
<li><b>Proses latar belakang</b>
<p>Proses yang menampung aktivitas yang saat ini tidak terlihat oleh pengguna (metode
{@link android.app.Activity#onStop onStop()} aktivitas telah dipanggil). Proses ini tidak memiliki dampak
langsung pada pengalaman pengguna, dan sistem bisa menghentikannya kapan saja untuk memperoleh kembali memori bagi
proses latar depan, proses yang terlihat,
atau proses layanan. Biasanya ada banyak proses latar belakang yang berjalan, sehingga disimpan
dalam daftar LRU (least recently used atau paling sedikit digunakan) untuk memastikan bahwa proses dengan aktivitas yang paling baru
terlihat oleh pengguna sebagai yang terakhir untuk dimatikan. Jika aktivitas mengimplementasikan metode
daur hidupnya dengan benar, dan menyimpan statusnya saat ini, menghentikan prosesnya tidak akan memiliki efek
yang terlihat pada pengalaman pengguna, karena ketika pengguna kembali ke aktivitas, aktivitas itu memulihkan
semua statusnya yang terlihat. Lihat dokumen <a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>
untuk mendapatkan informasi tentang menyimpan dan memulihkan status.</p>
</li>
<li><b>Proses kosong</b>
<p>Sebuah proses yang tidak berisi komponen aplikasi aktif apa pun. Alasan satu-satunya mempertahankan proses
seperti ini tetap hidup adalah untuk keperluan caching, meningkatkan waktu mulai (startup) bila
nanti komponen perlu dijalankan di dalamnya. Sistem sering menghentikan proses ini untuk menyeimbangkan sumber
daya sistem secara keseluruhan antara proses cache dan cache kernel yang mendasarinya.</p>
</li>
</ol>
<p>Android sebisa mungkin memeringkat proses setinggi
mungkin, berdasarkan prioritas komponen yang sedang aktif dalam proses. Misalnya, jika suatu proses menjadi host sebuah layanan dan
aktivitas yang terlihat, proses akan diperingkat sebagai proses yang terlihat, bukan sebagai proses layanan.</p>
<p>Selain itu, peringkat proses dapat meningkat karena adanya proses lain yang bergantung padanya
&mdash;proses yang melayani proses lain tidak bisa diperingkat lebih rendah daripada proses yang
sedang dilayaninya. Misalnya, jika penyedia konten dalam proses A melayani klien dalam proses B, atau
jika layanan dalam proses A terikat dengan komponen dalam proses B, proses A selalu dipertimbangkan sebagai paling rendah
prioritasnya dibandingkan dengan proses B.</p>
<p>Karena proses yang menjalankan layanan diperingkat lebih tinggi daripada aktivitas latar belakang,
aktivitas yang memulai operasi yang berjalan lama mungkin lebih baik memulai <a href="{@docRoot}guide/components/services.html">layanan</a> untuk operasi itu, daripada hanya
membuat thread pekerja&mdash;khususnya jika operasi mungkin akan berlangsung lebih lama daripada aktivitas.
Misalnya, aktivitas yang mengunggah gambar ke situs web harus memulai layanan
untuk mengunggah sehingga unggahan bisa terus berjalan di latar belakang meskipun pengguna meninggalkan aktivitas tersebut.
Menggunakan layanan akan memastikan operasi paling tidak memiliki prioritas "proses layanan",
apa pun yang terjadi pada aktivitas. Ini menjadi alasan yang sama yang membuat penerima siaran harus
menjalankan layanan daripada hanya menempatkan operasi yang menghabiskan waktu di thread.</p>
<h2 id="Threads">Thread</h2>
<p>Bila aplikasi diluncurkan, sistem akan membuat thread eksekusi untuk aplikasi tersebut, yang diberi nama,
"main". Thread ini sangat penting karena bertugas mengirim kejadian ke widget
antarmuka pengguna yang sesuai, termasuk kejadian menggambar. Ini juga merupakan thread yang
membuat aplikasi berinteraksi dengan komponen dari Android UI toolkit (komponen dari paket {@link
android.widget} dan {@link android.view}). Karena itu, thread 'main' juga terkadang
disebut thread UI.</p>
<p>Sistem ini <em>tidak</em> membuat thread terpisah untuk setiap instance komponen. Semua
komponen yang berjalan di proses yang sama akan dibuat instance-nya dalam thread UI, dan sistem akan memanggil
setiap komponen yang dikirim dari thread itu. Akibatnya, metode yang merespons callback sistem
(seperti {@link android.view.View#onKeyDown onKeyDown()} untuk melaporkan tindakan pengguna atau metode callback daur hidup)
selalu berjalan di thread UI proses.</p>
<p>Misalnya saat pengguna menyentuh tombol pada layar, thread UI aplikasi akan mengirim kejadian
sentuh ke widget, yang selanjutnya menetapkan status ditekan dan mengirim permintaan yang tidak divalidasi ke
antrean kejadian. Thread UI akan menghapus antrean permintaan dan memberi tahu widget bahwa widget harus menggambar
dirinya sendiri.</p>
<p>Saat aplikasi melakukan pekerjaan intensif sebagai respons terhadap interaksi pengguna, model
thread tunggal ini bisa menghasilkan kinerja yang buruk kecuali jika Anda mengimplementasikan aplikasi dengan benar. Khususnya jika
semua terjadi di thread UI, melakukan operasi yang panjang seperti akses ke jaringan atau query
database akan memblokir seluruh UI. Bila thread diblokir, tidak ada kejadian yang bisa dikirim,
termasuk kejadian menggambar. Dari sudut pandang pengguna, aplikasi
tampak mogok (hang). Lebih buruk lagi, jika thread UI diblokir selama lebih dari beberapa detik
(saat ini sekitar 5 detik) pengguna akan ditampilkan dialog "<a href="http://developer.android.com/guide/practices/responsiveness.html">aplikasi tidak
merespons</a>" (ANR) yang populer karena reputasi buruknya. Pengguna nanti bisa memutuskan untuk keluar dari aplikasi dan menghapus aplikasi
jika mereka tidak suka.</p>
<p>Selain itu, toolkit Android UI <em>bukan</em> thread-safe. Jadi, Anda tidak harus memanipulasi
UI dari thread pekerja&mdash;Anda harus melakukan semua manipulasi pada antarmuka pengguna dari thread
UI. Sehingga hanya ada dua aturan untuk model thread tunggal Android:</p>
<ol>
<li>Jangan memblokir thread UI
<li>Jangan mengakses toolkit Android UI dari luar thread UI
</ol>
<h3 id="WorkerThreads">Thread pekerja</h3>
<p>Karena model thread tunggal yang dijelaskan di atas, Anda dilarang memblokir thread
UI demi daya respons UI aplikasi. Jika memiliki operasi untuk dijalankan
yang tidak seketika, Anda harus memastikan untuk melakukannya di thread terpisah (thread "latar belakang" atau
thread "pekerja").</p>
<p>Misalnya, berikut ini beberapa kode untuk listener klik yang mengunduh gambar dari
thread terpisah dan menampilkannya dalam {@link android.widget.ImageView}:</p>
<pre>
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(b);
}
}).start();
}
</pre>
<p>Awalnya hal ini tampak bekerja dengan baik, karena menciptakan thread baru untuk menangani
operasi jaringan. Akan tetapi, hal tersebut melanggar aturan kedua model thread tunggal: <em>jangan mengakses
toolkit Android UI dari luar thread UI</em>&mdash;sampel ini memodifikasi {@link
android.widget.ImageView} dari thread pekerja sebagai ganti thread UI. Ini bisa
mengakibatkan perilaku yang tidak terdefinisi dan tidak diharapkan, yang bisa menyulitkan dan menghabiskan waktu untuk melacaknya.</p>
<p>Untuk memperbaiki masalah ini, Android menawarkan beberapa cara untuk mengakses thread UI dari
thread lainnya. Berikut ini daftar metode yang bisa membantu:</p>
<ul>
<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable)
Activity.runOnUiThread(Runnable)}</li>
<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li>
<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable,
long)}</li>
</ul>
<p>Misalnya, Anda bisa memperbaiki kode di atas dengan menggunakan metode {@link
android.view.View#post(java.lang.Runnable) View.post(Runnable)}:</p>
<pre>
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
</pre>
<p>Kini implementasi ini thread-safe: operasi jaringan dilakukan terpisah dari thread
sementara {@link android.widget.ImageView} dimanipulasi dari thread UI.</p>
<p>Akan tetapi, karena operasi semakin kompleks, jenis kode seperti ini bisa semakin rumit
dan sulit dipertahankan. Untuk menangani interaksi yang lebih kompleks dengan thread pekerja, Anda bisa mempertimbangkan
penggunaan {@link android.os.Handler}di thread pekerja, untuk memproses pesan yang dikirim dari
thread UI. Mungkin solusi terbaiknya adalah memperpanjang kelas {@link android.os.AsyncTask},
yang akan menyederhanakan eksekusi tugas-tugas thread pekerja yang perlu berinteraksi dengan UI.</p>
<h4 id="AsyncTask">Menggunakan AsyncTask</h4>
<p>Dengan {@link android.os.AsyncTask}, Anda bisa melakukan pekerjaan asinkron pada antarmuka
pengguna. AsyncTask memblokir operasi di thread pekerja kemudian mempublikasikan hasilnya
di thread UI, tanpa mengharuskan Anda untuk menangani sendiri thread dan/atau handler sendiri.</p>
<p>Untuk menggunakannya, Anda harus menempatkan {@link android.os.AsyncTask} sebagai subkelas dan mengimplementasikan metode callback {@link
android.os.AsyncTask#doInBackground doInBackground()} yang berjalan di kumpulan
thread latar belakang. Untuk memperbarui UI, Anda harus mengimplementasikan {@link
android.os.AsyncTask#onPostExecute onPostExecute()}, yang memberikan hasil dari {@link
android.os.AsyncTask#doInBackground doInBackground()} dan berjalan di thread UI, jadi Anda bisa
memperbarui UI dengan aman. Selanjutnya Anda bisa menjalankan tugas dengan memanggil {@link android.os.AsyncTask#execute execute()}
dari thread UI.</p>
<p>Misalnya, Anda bisa mengimplementasikan contoh sebelumnya menggunakan {@link android.os.AsyncTask} dengan cara
ini:</p>
<pre>
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask&lt;String, Void, Bitmap&gt; {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
</pre>
<p>Kini UI aman dan kode jadi lebih sederhana, karena memisahkan pekerjaan ke
dalam bagian-bagian yang harus dilakukan pada thread pekerja dan thread UI.</p>
<p>Anda harus membaca acuan {@link android.os.AsyncTask} untuk memahami sepenuhnya
cara menggunakan kelas ini, namun berikut ini ikhtisar singkat cara kerjanya:</p>
<ul>
<li>Anda bisa menetapkan tipe parameter, nilai kemajuan, dan nilai
akhir tugas, dengan menggunakan generik</li>
<li>Metode {@link android.os.AsyncTask#doInBackground doInBackground()} berjalan secara otomatis pada
thread pekerja</li>
<li>{@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link
android.os.AsyncTask#onPostExecute onPostExecute()}, dan {@link
android.os.AsyncTask#onProgressUpdate onProgressUpdate()} semuanya dipanggil pada thread UI</li>
<li>Nilai yang dikembalikan oleh {@link android.os.AsyncTask#doInBackground doInBackground()} akan dikirim ke
{@link android.os.AsyncTask#onPostExecute onPostExecute()}</li>
<li>Anda bisa memangil {@link android.os.AsyncTask#publishProgress publishProgress()} setiap saat di {@link
android.os.AsyncTask#doInBackground doInBackground()} untuk mengeksekusi {@link
android.os.AsyncTask#onProgressUpdate onProgressUpdate()} pada thread UI</li>
<li>Anda bisa membatalkan tugas ini kapan saja, dari thread mana saja</li>
</ul>
<p class="caution"><strong>Perhatian:</strong> Masalah lain yang mungkin Anda temui saat menggunakan
thread pekerja adalah restart tak terduga dalam aktivitas karena <a href="{@docRoot}guide/topics/resources/runtime-changes.html">perubahan konfigurasi runtime</a>
(seperti saat pengguna mengubah orientasi layar), yang bisa memusnahkan thread pekerja. Untuk
melihat cara mempertahankan tugas selama restart ini dan cara membatalkan
tugas dengan benar saat aktivitas dimusnahkan, lihat kode sumber untuk aplikasi sampel <a href="http://code.google.com/p/shelves/">Shelves</a>.</p>
<h3 id="ThreadSafe">Metode thread-safe</h3>
<p> Dalam beberapa situasi, metode yang Anda implementasikan bisa dipanggil dari lebih dari satu thread,
dan karena itu harus ditulis agar menjadi thread-safe. </p>
<p>Ini terutama terjadi untuk metode yang bisa dipanggil dari jauh &mdash;seperti metode dalam <a href="{@docRoot}guide/components/bound-services.html">layanan terikat</a>. Bila sebuah panggilan pada
metode yang dijalankan dalam {@link android.os.IBinder} berasal dari proses yang sama di mana
{@link android.os.IBinder IBinder} berjalan, metode ini akan dieksekusi di thread pemanggil.
Akan tetapi, bila panggilan berasal proses lain, metode akan dieksekusi dalam thread yang dipilih dari
kumpulan (pool) thread yang dipertahankan sistem dalam proses yang sama seperti{@link android.os.IBinder
IBinder} (tidak dieksekusi dalam thread UI proses). Misalnya, karena metode
{@link android.app.Service#onBind onBind()} layanan akan dipanggil dari thread UI
proses layanan, metode yang diimplementasikan dalam objek yang dikembalikan {@link android.app.Service#onBind
onBind()} (misalnya, subkelas yang mengimplementasikan metode RPC) akan dipanggil dari thread
di pool. Karena layanan bisa memiliki lebih dari satu klien, maka lebih dari satu pool thread bisa melibatkan
metode {@link android.os.IBinder IBinder} yang sama sekaligus. Metode {@link android.os.IBinder
IBinder} karenanya harus diimplementasikan sebagai thread-safe.</p>
<p> Penyedia konten juga bisa menerima permintaan data yang berasal dalam proses lain.
Meskipun kelas {@link android.content.ContentResolver} dan {@link android.content.ContentProvider}
menyembunyikan detail cara komunikasi antarproses dikelola, metode {@link
android.content.ContentProvider} yang merespons permintaan itu&mdash;metode {@link
android.content.ContentProvider#query query()}, {@link android.content.ContentProvider#insert
insert()}, {@link android.content.ContentProvider#delete delete()}, {@link
android.content.ContentProvider#update update()}, dan {@link android.content.ContentProvider#getType
getType()}&mdash; dipanggil dari pool thread pada proses penyedia konten, bukan thread UI
untuk proses tersebut. Mengingat metode ini bisa dipanggil dari thread mana pun
sekaligus, metode-metode ini juga harus diimplementasikan sebagai thread-safe. </p>
<h2 id="IPC">Komunikasi Antarproses</h2>
<p>Android menawarkan mekanisme komunikasi antarproses (IPC) menggunakan panggilan prosedur jauh
(RPC), yang mana metode ini dipanggil oleh aktivitas atau komponen aplikasi lain, namun dieksekusi dari
jauh (di proses lain), bersama hasil yang dikembalikan ke
pemanggil. Ini mengharuskan penguraian panggilan metode dan datanya ke tingkat yang bisa
dipahami sistem operasi, mentransmisikannya dari proses lokal dan ruang alamat untuk proses jauh
dan ruang proses, kemudian merakit kembali dan menetapkannya kembali di sana. Nilai-nilai yang dikembalikan
akan ditransmisikan dalam arah berlawanan. Android menyediakan semua kode untuk melakukan transaksi IPC
ini, sehingga Anda bisa fokus pada pendefinisian dan implementasi antarmuka pemrograman RPC. </p>
<p>Untuk melakukan IPC, aplikasi Anda harus diikat ke layanan, dengan menggunakan {@link
android.content.Context#bindService bindService()}. Untuk informasi selengkapnya, lihat panduan pengembang <a href="{@docRoot}guide/components/services.html">Layanan</a>.</p>
<!--
<h2>Beginner's Path</h2>
<p>For information about how to perform work in the background for an indefinite period of time
(without a user interface), continue with the <b><a
href="{@docRoot}guide/components/services.html">Services</a></b> document.</p>
-->

View File

@@ -0,0 +1,256 @@
page.title=Layar Ikhtisar
page.tags="recents","overview"
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#adding">Menambahkan Tugas ke Layar Ikhtisar</a>
<ol>
<li><a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a></li>
<li><a href="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</a></li>
</ol>
</li>
<li><a href="#removing">Menghapus Tugas</a>
<ol>
<li><a href="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</a></li>
<li><a href="#retain-finished">Mempertahankan tugas yang telah selesai</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.ActivityManager.AppTask}</li>
<li>{@link android.content.Intent}</li>
</ol>
<h2>Kode contoh</h2>
<ol>
<li><a href="{@docRoot}samples/DocumentCentricApps/index.html">Aplikasi yang berorientasi dokumen</a></li>
</ol>
</div>
</div>
<p>Layar ikhtisar (juga disebut sebagai layar terbaru, daftar tugas terbaru, atau aplikasi terbaru)
UI tingkat sistem yang mencantumkan <a href="{@docRoot}guide/components/activities.html">
aktivitas</a> dan <a href="{@docRoot}guide/components/tasks-and-back-stack.html">tugas</a> yang baru saja diakses. Pengguna
bisa menyusuri daftar ini dan memilih satu tugas untuk dilanjutkan, atau pengguna bisa menghapus tugas dari
daftar dengan gerakan mengusap. Dengan dirilisnya Android 5.0 (API level 21), beberapa instance aktivitas yang
sama yang berisi dokumen berbeda dapat muncul sebagai tugas di layar ikhtisar. Misalnya,
Google Drive mungkin memiliki satu tugas untuk setiap beberapa dokumen Google. Setiap dokumen muncul sebagai
tugas dalam layar ikhtisar.</p>
<img src="{@docRoot}images/components/recents.png" alt="" width="284" />
<p class="img-caption"><strong>Gambar 1.</strong> Layar ikhtisar menampilkan tiga dokumen
Google Drive, masing-masing dinyatakan sebagai tugas terpisah.</p>
<p>Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan
aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini.
Akan tetapi, aplikasi Anda dapat menentukan cara dan waktu munculnya aktivitas di layar ikhtisar. Kelas
{@link android.app.ActivityManager.AppTask} memungkinkan Anda mengelola tugas, dan flag
aktivitas kelas {@link android.content.Intent} memungkinkan Anda menentukan kapan aktivitas ditambahkan atau dihapus dari
layar ikhtisar. Selain itu, atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">
&lt;activity&gt;</a></code> memungkinkan Anda menetapkan perilaku di manifes.</p>
<h2 id="adding">Menambahkan Tugas ke Layar Ikhtisar</h2>
<p>Penggunaan flag kelas {@link android.content.Intent} untuk menambahkan tugas memberi kontrol lebih besar
atas waktu dan cara dokumen dibuka atau dibuka kembali di layar ikhtisar. Bila menggunakan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, Anda dapat memilih antara selalu membuka dokumen dalam tugas baru atau menggunakan kembali tugas
yang ada untuk dokumen tersebut.</p>
<h3 id="flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</h3>
<p>Bila membuat dokumen baru untuk aktivitas, Anda memanggil metode
{@link android.app.ActivityManager.AppTask#startActivity(android.content.Context, android.content.Intent, android.os.Bundle) startActivity()}
dari kelas {@link android.app.ActivityManager.AppTask}, dengan meneruskannya ke intent yang
menjalankan aktivitas tersebut. Untuk menyisipkan jeda logis agar sistem memperlakukan aktivitas Anda sebagai tugas
baru di layar ikhtisar, teruskan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
dalam metode {@link android.content.Intent#addFlags(int) addFlags()} dari {@link android.content.Intent}
yang memulai aktivitas itu.</p>
<p class="note"><strong>Catatan:</strong> Flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
menggantikan flag {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET},
yang tidak digunakan lagi pada Android 5.0 (API level 21).</p>
<p>Jika Anda menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} saat membuat
dokumen baru, sistem akan selalu membuat tugas baru dengan aktivitas target sebagai akar.
Dengan pengaturan ini, dokumen yang sama dapat dibuka di lebih dari satu tugas. Kode berikut memperagakan
cara aktivitas utama melakukannya:</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
DocumentCentricActivity.java</a></p>
<pre>
public void createNewDocument(View view) {
final Intent newDocumentIntent = newDocumentIntent();
if (useMultipleTasks) {
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
}
startActivity(newDocumentIntent);
}
private Intent newDocumentIntent() {
boolean useMultipleTasks = mCheckbox.isChecked();
final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
return newDocumentIntent;
}
private static int incrementAndGet() {
Log.d(TAG, "incrementAndGet(): " + mDocumentCounter);
return mDocumentCounter++;
}
}
</pre>
<p class="note"><strong>Catatan:</strong> Aktivitas yang dimulai dengan flag {@code FLAG_ACTIVITY_NEW_DOCUMENT}
harus telah menetapkan nilai atribut {@code android:launchMode="standard"} (default) dalam
manifes.</p>
<p>Bila aktivitas utama memulai aktivitas baru, sistem akan mencari tugas yang intent
-nya cocok dengan nama komponen intent dalam tugas-tugas yang sudah ada dan mencari aktivitas dalam data Intent. Jika tugas
tidak ditemukan, atau intent ada dalam flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}
, tugas baru akan dibuat dengan aktivitas tersebut sebagai akarnya. Jika ditemukan, sistem akan
mengedepankan tugas itu dan meneruskan intent baru ke {@link android.app.Activity#onNewIntent onNewIntent()}.
Aktivitas baru akan mendapatkan intent dan membuat dokumen baru di layar ikhtisar, seperti dalam
contoh berikut:</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
NewDocumentActivity.java</a></p>
<pre>
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_document);
mDocumentCount = getIntent()
.getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0);
mDocumentCounterTextView = (TextView) findViewById(
R.id.hello_new_document_text_view);
setDocumentCounterText(R.string.hello_new_document_counter);
}
&#64;Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
/* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity
is reused to create a new document.
*/
setDocumentCounterText(R.string.reusing_document_counter);
}
</pre>
<h3 id="#attr-doclaunch">Menggunakan atribut Aktivitas untuk menambahkan tugas</h3>
<p>Aktivitas juga dapat menetapkan dalam manifesnya agar selalu dimulai ke dalam tugas baru dengan menggunakan
atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, <a href="{@docRoot}guide/topics/manifest/activity-element.html#dlmode">
{@code android:documentLaunchMode}</a>. Atribut ini memiliki empat nilai yang menghasilkan efek berikut
bila pengguna membuka dokumen dengan aplikasi:</p>
<dl>
<dt>"{@code intoExisting}"</dt>
<dd>Aktivitas menggunakan kembali tugas yang ada untuk dokumen tersebut. Ini sama dengan mengatur flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} <em>tanpa</em> mengatur flag
{@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, seperti dijelaskan dalam
<a href="#flag-new-doc">Menggunakan flag Intent untuk menambahkan tugas</a>, di atas.</dd>
<dt>"{@code always}"</dt>
<dd>Aktivitas ini membuat tugas baru untuk dokumen, meski dokumen sudah dibuka. Menggunakan
nilai ini sama dengan menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
maupun {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}.</dd>
<dt>"{@code none”}"</dt>
<dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Layar ikhtisar memperlakukan
aktivitas seperti itu secara default: satu tugas ditampilkan untuk aplikasi, yang
dilanjutkan dari aktivitas apa pun yang terakhir dipanggil pengguna.</dd>
<dt>"{@code never}"</dt>
<dd>Aktivitas ini tidak membuat tugas baru untuk dokumen. Mengatur nilai ini akan mengesampingkan
perilaku flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT}
dan {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, jika salah satunya ditetapkan di
intent, dan layar ikhtisar menampilkan satu tugas untuk aplikasi, yang dilanjutkan dari
aktivitas apa pun yang terakhir dipanggil pengguna.</dd>
</dl>
<p class="note"><strong>Catatan:</strong> Untuk nilai selain {@code none} dan {@code never},
aktivitas harus didefinisikan dengan {@code launchMode="standard"}. Jika atribut ini tidak ditetapkan, maka
{@code documentLaunchMode="none"} akan digunakan.</p>
<h2 id="removing">Menghapus Tugas</h2>
<p>Secara default, tugas dokumen secara otomatis dihapus dari layar ikhtisar bila aktivitasnya
selesai. Anda bisa mengesampingkan perilaku ini dengan kelas {@link android.app.ActivityManager.AppTask},
dengan flag {@link android.content.Intent} atau atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">
&lt;activity&gt;</a></code>.</p>
<p>Kapan saja Anda bisa mengecualikan tugas dari layar ikhtisar secara keseluruhan dengan menetapkan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, <a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">
{@code android:excludeFromRecents}</a> hingga {@code true}.</p>
<p>Anda bisa menetapkan jumlah maksimum tugas yang dapat disertakan aplikasi Anda dalam layar ikhtisar dengan menetapkan
atribut <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<a href="{@docRoot}guide/topics/manifest/activity-element.html#maxrecents">{@code android:maxRecents}
</a> ke satu nilai integer. Nilai default-nya adalah 16. Bila telah mencapai jumlah maksimum, tugas yang terakhir
digunakan akan dihapus dari layar ikhtisar. Nilai maksimum {@code android:maxRecents}
adalah 50 (25 pada perangkat dengan memori sedikit); nilai yang kurang dari 1 tidak berlaku.</p>
<h3 id="#apptask-remove">Menggunakan kelas AppTask untuk menghapus tugas</h3>
<p>Dalam aktivitas yang membuat tugas baru di layar ikhtisar, Anda bisa
menetapkan kapan menghapus tugas dan menyelesaikan semua aktivitas yang terkait dengannya
dengan memanggil metode {@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}.</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
NewDocumentActivity.java</a></p>
<pre>
public void onRemoveFromRecents(View view) {
// The document is no longer needed; remove its task.
finishAndRemoveTask();
}
</pre>
<p class="note"><strong>Catatan:</strong> Penggunaan metode
{@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}
akan mengesampingkan penggunaan tag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, seperti
dibahas di bawah ini.</p>
<h3 id="#retain-finished">Mempertahankan tugas yang telah selesai</h3>
<p>Jika Anda ingin mempertahankan tugas di layar ikhtisar, sekalipun aktivitas sudah selesai, teruskan
flag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} dalam metode
{@link android.content.Intent#addFlags(int) addFlags()} dari Intent yang memulai aktivitas itu.</p>
<p class="code-caption"><a href="{@docRoot}samples/DocumentCentricApps/index.html">
DocumentCentricActivity.java</a></p>
<pre>
private Intent newDocumentIntent() {
final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
return newDocumentIntent;
}
</pre>
<p>Untuk memperoleh efek yang sama, tetapkan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<a href="{@docRoot}guide/topics/manifest/activity-element.html#autoremrecents">
{@code android:autoRemoveFromRecents}</a> hingga {@code false}. Nilai default-nya adalah {@code true}
untuk aktivitas dokumen, dan {@code false} untuk aktivitas biasa. Penggunaan atribut ini akan mengesampingkan flag
{@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, yang telah dibahas sebelumnya.</p>

View File

@@ -0,0 +1,813 @@
page.title=Layanan
@jd:body
<div id="qv-wrapper">
<ol id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Basics">Dasar-Dasar</a></li>
<ol>
<li><a href="#Declaring">Mendeklarasikan layanan dalam manifes</a></li>
</ol>
<li><a href="#CreatingAService">Membuat Layanan yang Sudah Dimulai</a>
<ol>
<li><a href="#ExtendingIntentService">Memperluas kelas IntentService</a></li>
<li><a href="#ExtendingService">Memperluas kelas Layanan</a></li>
<li><a href="#StartingAService">Memulai layanan</a></li>
<li><a href="#Stopping">Menghentikan layanan</a></li>
</ol>
</li>
<li><a href="#CreatingBoundService">Membuat Layanan Terikat</a></li>
<li><a href="#Notifications">Mengirim Pemberitahuan ke Pengguna</a></li>
<li><a href="#Foreground">Menjalankan Layanan di Latar Depan</a></li>
<li><a href="#Lifecycle">Mengelola Daur Hidup Layanan</a>
<ol>
<li><a href="#LifecycleCallbacks">Mengimplementasikan callback daur hidup</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.Service}</li>
<li>{@link android.app.IntentService}</li>
</ol>
<h2>Contoh</h2>
<ol>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
ServiceStartArguments}</a></li>
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
LocalService}</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a></li>
</ol>
</div>
<p>{@link android.app.Service} adalah sebuah komponen aplikasi yang bisa melakukan
operasi yang berjalan lama di latar belakang dan tidak menyediakan antarmuka pengguna. Komponen
aplikasi lain bisa memulai layanan dan komponen aplikasi tersebut akan terus berjalan
di latar belakang walaupun pengguna beralih ke aplikasi lain. Selain itu, komponen bisa mengikat ke layanan
untuk berinteraksi dengannya dan bahkan melakukan komunikasi antarproses (IPC). Misalnya, layanan mungkin
menangani transaksi jaringan, memutar musik, melakukan file I/O, atau berinteraksi dengan penyedia konten
dari latar belakang.</p>
<p>Ada dua bentuk dasar layanan:</p>
<dl>
<dt>Sudah Dimulai</dt>
<dd>Layanan "sudah dimulai" bila komponen aplikasi (misalnya aktivitas) memulainya dengan
memanggil {@link android.content.Context#startService startService()}. Sesudah dimulai, layanan
bisa berjalan terus-menerus di latar belakang walaupun komponen yang memulainya telah dimusnahkan. Biasanya,
layanan yang sudah dimulai akan melakukan operasi tunggal dan tidak mengembalikan hasil ke pemanggilnya.
Misalnya, layanan bisa mengunduh atau mengunggah file melalui jaringan. Bila operasi selesai,
layanan seharusnya berhenti sendiri.</dd>
<dt>Terikat</dt>
<dd>Layanan "terikat" bila komponen aplikasi mengikat kepadanya dengan memanggil {@link
android.content.Context#bindService bindService()}. Layanan terikat menawarkan antarmuka
klien-server yang memungkinkan komponen berinteraksi dengan layanan tersebut, mengirim permintaan, mendapatkan hasil dan bahkan
melakukannya pada sejumlah proses dengan komunikasi antarproses (IPC). Layanan terikat hanya berjalan selama
ada komponen aplikasi lain yang terikat padanya. Sejumlah komponen bisa terikat pada layanan secara bersamaan,
namun bila semuanya melepas ikatan, layanan tersebut akan dimusnahkan.</dd>
</dl>
<p>Walaupun dokumentasi ini secara umum membahas kedua jenis layanan secara terpisah, layanan
Anda bisa menggunakan keduanya&mdash;layanan bisa dimulai (untuk berjalan terus-menerus) sekaligus memungkinkan pengikatan.
Cukup mengimplementasikan dua metode callback: {@link
android.app.Service#onStartCommand onStartCommand()} untuk memungkinkan komponen memulainya dan {@link
android.app.Service#onBind onBind()} untuk memungkinkan pengikatan.</p>
<p>Apakah aplikasi Anda sudah dimulai, terikat, atau keduanya, semua komponen aplikasi
bisa menggunakan layanan (bahkan dari aplikasi terpisah), demikian pula semua komponen bisa menggunakan
suatu aktivitas&mdash;dengan memulainya dengan {@link android.content.Intent}. Akan tetapi, Anda bisa mendeklarasikan
layanan sebagai privat, pada file manifes, dan memblokir akses dari aplikasi lain. Hal ini
dibahas selengkapnya di bagian tentang <a href="#Declaring">Mendeklarasikan layanan dalam
manifes</a>.</p>
<p class="caution"><strong>Perhatian:</strong> Layanan berjalan di
thread utama proses yang menjadi host-nya&mdash;layanan <strong>tidak</strong> membuat thread-nya sendiri
dan <strong>tidak</strong> berjalan pada proses terpisah (kecuali bila Anda tentukan demikian). Artinya,
jika layanan Anda akan melakukan pekerjaan yang membutuhkan tenaga CPU besar atau operasi yang memblokir (seperti
pemutaran MP3 atau jaringan), Anda perlu membuat thread baru dalam layanan untuk melakukan pekerjaan tersebut. Dengan menggunakan
thread terpisah, Anda mengurangi risiko terjadinya kesalahan Aplikasi Tidak Merespons (Application Not Responding/ANR) dan
thread utama aplikasi bisa tetap dikhususkan pada interaksi pengguna dengan aktivitas Anda.</p>
<h2 id="Basics">Dasar-Dasar</h2>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Haruskah menggunakan layanan atau thread?</h3>
<p>Layanan sekadar komponen yang bisa berjalan di latar belakang walaupun pengguna sedang tidak
berinteraksi dengan aplikasi Anda. Sehingga, Anda harus membuat layanan bila memang itu
yang dibutuhkan.</p>
<p>Bila Anda perlu melakukan pekerjaan di luar thread utama, namun hanya bila pengguna sedang berinteraksi
dengan aplikasi, maka Anda harus membuat thread baru sebagai ganti layanan baru. Misalnya,
bila Anda ingin memutar musik, namun hanya saat aktivitas Anda berjalan, Anda bisa membuat
thread dalam {@link android.app.Activity#onCreate onCreate()}, mulai menjalankannya di {@link
android.app.Activity#onStart onStart()}, kemudian menghentikannya di {@link android.app.Activity#onStop
onStop()}. Pertimbangkan juga untuk menggunakan {@link android.os.AsyncTask} atau {@link android.os.HandlerThread},
sebagai ganti kelas {@link java.lang.Thread} yang lazim digunakan. Lihat dokumen <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">Proses dan
Threading</a> untuk informasi selengkapnya tentang thread.</p>
<p>Ingatlah jika menggunakan layanan, layanan tersebut tetap berjalan di thread utama aplikasi Anda secara
default, jadi Anda harus tetap membuat thread baru dalam layanan bila layanan tersebut melakukan operasi yang intensif
atau operasi yang memblokir.</p>
</div>
</div>
<p>Untuk membuat layanan, Anda harus membuat subkelas {@link android.app.Service} (atau
salah satu dari subkelasnya yang ada). Dalam implementasi, Anda perlu mengesampingkan sebagian metode callback yang
menangani aspek utama daur hidup layanan dan memberikan mekanisme bagi komponen untuk mengikat
pada layanan, bila dibutuhkan. Metode callback terpenting yang perlu Anda kesampingkan adalah:</p>
<dl>
<dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
<dd>Sistem akan memanggil metode ini bila komponen lain, misalnya aktivitas,
meminta dimulainya layanan, dengan memanggil {@link android.content.Context#startService
startService()}. Setelah metode ini dieksekusi, layanan akan dimulai dan bisa berjalan di
latar belakang terus-menerus. Jika mengimplementasikan ini, Anda bertanggung jawab menghentikan layanan bila
bila pekerjaannya selesai, dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}. (Jika hanya ingin menyediakan pengikatan, Anda tidak
perlu mengimplementasikan metode ini.)</dd>
<dt>{@link android.app.Service#onBind onBind()}</dt>
<dd>Sistem akan memanggil metode ini bila komponen lain ingin mengikat pada
layanan (misalnya untuk melakukan RPC), dengan memanggil {@link android.content.Context#bindService
bindService()}. Dalam mengimplementasikan metode ini, Anda harus menyediakan antarmuka yang digunakan
klien untuk berkomunikasi dengan layanan, dengan mengembalikan {@link android.os.IBinder}. Anda harus selalu
mengimplementasikan metode ini, namun jika tidak ingin mengizinkan pengikatan, Anda perlu mengembalikan null.</dd>
<dt>{@link android.app.Service#onCreate()}</dt>
<dd>Sistem memanggil metode ini bila layanan dibuat untuk pertama kalinya, untuk melakukan prosedur
penyiapan satu kali (sebelum memanggil {@link android.app.Service#onStartCommand onStartCommand()} atau
{@link android.app.Service#onBind onBind()}). Bila layanan sudah berjalan, metode ini tidak
dipanggil.</dd>
<dt>{@link android.app.Service#onDestroy()}</dt>
<dd>Sistem memanggil metode ini bila layanan tidak lagi digunakan dan sedang dimusnahkan.
Layanan Anda perlu mengimplementasikannya untuk membersihkan sumber daya seperti thread, listener
terdaftar, penerima, dll. Ini adalah panggilan terakhir yang diterima layanan.</dd>
</dl>
<p>Bila komponen memulai layanan dengan memanggil {@link
android.content.Context#startService startService()} (yang menyebabkan panggilan ke {@link
android.app.Service#onStartCommand onStartCommand()}), maka layanan
terus berjalan hingga terhenti sendiri dengan {@link android.app.Service#stopSelf()} atau bila komponen
lain menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
<p>Bila komponen memanggil
{@link android.content.Context#bindService bindService()} untuk membuat layanan (dan {@link
android.app.Service#onStartCommand onStartCommand()} <em>tidak</em> dipanggil), maka layanan hanya berjalan
selama komponen terikat kepadanya. Setelah layanan dilepas ikatannya dari semua klien,
sistem akan menghancurkannya.</p>
<p>Sistem Android akan menghentikan paksa layanan hanya bila memori tinggal sedikit dan sistem harus memulihkan
sumber daya sistem untuk aktivitas yang mendapatkan fokus pengguna. Jika layanan terikat pada suatu aktivitas yang mendapatkan
fokus pengguna, layanan tersebut lebih kecil kemungkinannya untuk dimatikan, dan jika layanan dideklarasikan untuk <a href="#Foreground">berjalan di latar depan</a> (akan dibahas kemudian), maka sudah hampir pasti ia tidak akan dimatikan.
Sebaliknya, bila layanan sudah dimulai dan berjalan lama, maka sistem akan menurunkan posisinya
dalam daftar tugas latar belakang seiring waktu dan layanan akan sangat rentan untuk
dimatikan&mdash;bila layanan Anda dimulai, maka Anda harus mendesainnya agar bisa menangani restart
oleh sistem dengan baik. Jika sistem mematikan layanan Anda, layanan akan dimulai kembali begitu sumber daya
kembali tersedia (tetapi ini juga bergantung pada nilai yang Anda kembalikan dari {@link
android.app.Service#onStartCommand onStartCommand()}, sebagaimana akan dibahas nanti). Untuk informasi selengkapnya
tentang kapan sistem mungkin akan memusnahkan layanan, lihat dokumen
<a href="{@docRoot}guide/components/processes-and-threads.html">Proses dan Threading</a>.</p>
<p>Dalam bagian selanjutnya, Anda akan melihat bagaimana membuat masing-masing tipe layanan dan cara menggunakannya
dari komponen aplikasi lain.</p>
<h3 id="Declaring">Mendeklarasikan layanan dalam manifes</h3>
<p>Sebagaimana aktivitas (dan komponen lainnya), Anda harus mendeklarasikan semua layanan dalam file manifes
aplikasi Anda.</p>
<p>Untuk mendeklarasikan layanan Anda, tambahkan sebuah elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
sebagai anak
elemen <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>. Misalnya:</p>
<pre>
&lt;manifest ... &gt;
...
&lt;application ... &gt;
&lt;service android:name=".ExampleService" /&gt;
...
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<p>Lihat acuan elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
untuk informasi selengkapnya tentang cara mendeklarasikan layanan Anda dalam manifes.</p>
<p>Ada atribut lain yang bisa Anda sertakan dalam elemen <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> untuk
mendefinisikan properti seperti izin yang dibutuhkan untuk memulai layanan dan proses
tempat berjalannya layanan. <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> adalah satu-satunya atribut yang diperlukan
&mdash;atribut tersebut menetapkan nama kelas layanan. Setelah
mempublikasikan aplikasi, Anda tidak boleh mengubah nama ini, karena jika melakukannya, Anda bisa merusak
kode karena dependensi terhadap intent eksplisit untuk memulai atau mengikat layanan (bacalah posting blog berjudul <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
That Cannot Change</a>).
<p>Untuk memastikan aplikasi Anda aman, <strong>selalu gunakan intent eksplisit saat memulai atau mengikat
{@link android.app.Service} Anda</strong> dan jangan mendeklarasikan filter intent untuk layanan. Jika
Anda perlu membiarkan adanya ambiguitas tentang layanan mana yang dimulai, Anda bisa
menyediakan filter intent bagi layanan dan tidak memasukkan nama komponen pada {@link
android.content.Intent}, namun Anda juga harus menyesuaikan paket bagi intent tersebut dengan {@link
android.content.Intent#setPackage setPackage()}, yang memberikan klarifikasi memadai bagi
target layanan.</p>
<p>Anda juga bisa memastikan layanan tersedia hanya bagi aplikasi Anda dengan
menyertakan atribut <a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
dan mengaturnya ke {@code "false"}. Hal ini efektif menghentikan aplikasi lain agar tidak memulai
layanan Anda, bahkan saat menggunakan intent eksplisit.</p>
<h2 id="CreatingStartedService">Membuat Layanan yang Sudah Dimulai</h2>
<p>Layanan yang sudah dimulai adalah layanan yang dimulai komponen lain dengan memanggil {@link
android.content.Context#startService startService()}, yang menyebabkan panggilan ke metode
{@link android.app.Service#onStartCommand onStartCommand()} layanan.</p>
<p>Bila layanan sudah dimulai, layanan tersebut memiliki daur hidup yang tidak bergantung pada
komponen yang memulainya dan bisa berjalan terus-menerus di latar belakang walaupun
komponen yang memulainya dimusnahkan. Dengan sendirinya, layanan akan berhenti sendiri bila pekerjaannya
selesai dengan memanggil {@link android.app.Service#stopSelf stopSelf()}, atau komponen lain bisa menghentikannya
dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
<p>Komponen aplikasi seperti aktivitas bisa memulai layanan dengan memanggil {@link
android.content.Context#startService startService()} dan meneruskan {@link android.content.Intent}
yang menetapkan layanan dan menyertakan data untuk digunakan layanan. Layanan menerima
{@link android.content.Intent} ini dalam metode {@link android.app.Service#onStartCommand
onStartCommand()}.</p>
<p>Sebagai contoh, anggaplah aktivitas perlu menyimpan data ke database online. Aktivitas tersebut bisa
memulai layanan pendamping dan mengiriminya data untuk disimpan dengan meneruskan intent ke {@link
android.content.Context#startService startService()}. Layanan akan menerima intent dalam {@link
android.app.Service#onStartCommand onStartCommand()}, menghubungkan ke Internet dan melakukan
transaksi database. Bila transaksi selesai, layanan akan berhenti sendiri dan
dimusnahkan.</p>
<p class="caution"><strong>Perhatian:</strong> Layanan berjalan dalam proses yang sama dengan aplikasi
tempatnya dideklarasikan dan dalam thread utama aplikasi tersebut, secara default. Jadi, bila layanan Anda
melakukan operasi yang intensif atau operasi pemblokiran saat pengguna berinteraksi dengan aktivitas dari
aplikasi yang sama, layanan akan memperlambat kinerja aktivitas. Agar tidak memengaruhi
kinerja aplikasi, Anda harus memulai thread baru di dalam layanan.</p>
<p>Biasanya, ada dua kelas yang bisa Anda perluas untuk membuat layanan yang sudah dimulai:</p>
<dl>
<dt>{@link android.app.Service}</dt>
<dd>Ini adalah kelas dasar untuk semua layanan. Bila memperluas kelas ini, Anda perlu
membuat thread baru sebagai tempat melaksanakan semua pekerjaan layanan tersebut, karena layanan
menggunakan thread utama aplikasi Anda secara default, dan hal ini bisa memperlambat
kinerja aktivitas yang dijalankan aplikasi Anda.</dd>
<dt>{@link android.app.IntentService}</dt>
<dd>Ini adalah subkelas {@link android.app.Service} yang menggunakan thread pekerja untuk menangani
semua permintaan memulai, satu per satu. Ini adalah pilihan terbaik jika Anda tidak mengharuskan layanan
menangani beberapa permintaan sekaligus. Anda cukup mengimplementasikan {@link
android.app.IntentService#onHandleIntent onHandleIntent()}, yang menerima intent untuk setiap
permintaan memulai agar bisa melakukan pekerjaan latar belakang.</dd>
</dl>
<p>Bagian selanjutnya membahas cara mengimplementasikan layanan Anda menggunakan
salah satu dari kelas-kelas ini.</p>
<h3 id="ExtendingIntentService">Memperluas kelas IntentService</h3>
<p>Mengingat kebanyakan layanan yang sudah dimulai tidak perlu menangani beberapa permintaan
sekaligus (yang bisa berupa skenario multi-threading berbahaya), mungkin Anda sebaiknya mengimplementasikan
layanan menggunakan kelas {@link android.app.IntentService}.</p>
<p>Berikut ini yang dilakukan {@link android.app.IntentService}:</p>
<ul>
<li>Membuat thread pekerja default yang menjalankan semua intent yang disampaikan ke {@link
android.app.Service#onStartCommand onStartCommand()} terpisah dari thread utama aplikasi
Anda.</li>
<li>Membuat antrean pekerjaan yang meneruskan intent satu per satu ke implementasi {@link
android.app.IntentService#onHandleIntent onHandleIntent()}, sehingga Anda tidak perlu
mengkhawatirkan multi-threading.</li>
<li>Menghentikan layanan setelah semua permintaan memulai telah ditangani, jadi Anda tidak perlu memanggil
{@link android.app.Service#stopSelf}.</li>
<li>Menyediakan implementasi default {@link android.app.IntentService#onBind onBind()} yang
mengembalikan null.</li>
<li>Menyediakan implementasi default {@link android.app.IntentService#onStartCommand
onStartCommand()} yang mengirimkan intent ke antrean pekerjaan kemudian ke implementasi {@link
android.app.IntentService#onHandleIntent onHandleIntent()} Anda.</li>
</ul>
<p>Oleh karena itu, Anda hanya perlu mengimplementasikan {@link
android.app.IntentService#onHandleIntent onHandleIntent()} untuk melakukan pekerjaan yang diberikan oleh
klien. (Akan tetapi, Anda juga perlu menyediakan konstruktor kecil bagi layanan.)</p>
<p>Berikut ini contoh implementasi {@link android.app.IntentService}:</p>
<pre>
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
&#64;Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() &lt; endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
</pre>
<p>Anda hanya memerlukan: konstruktor dan implementasi {@link
android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
<p>Jika Anda memutuskan untuk juga mengesampingkan metode callback lain, seperti {@link
android.app.IntentService#onCreate onCreate()}, {@link
android.app.IntentService#onStartCommand onStartCommand()}, atau {@link
android.app.IntentService#onDestroy onDestroy()}, pastikan memanggil implementasi super, sehingga
{@link android.app.IntentService} bisa menangani hidup thread pekerja dengan baik.</p>
<p>Misalnya, {@link android.app.IntentService#onStartCommand onStartCommand()} harus mengembalikan
implementasi default (yang merupakan cara penyampaian intent ke {@link
android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
<pre>
&#64;Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
</pre>
<p>Selain {@link android.app.IntentService#onHandleIntent onHandleIntent()}, satu-satunya metode lain
yang tidak mengharuskan Anda memanggil super kelas adalah {@link android.app.IntentService#onBind
onBind()} (namun Anda hanya perlu mengimplementasikannya bila layanan mengizinkan pengikatan).</p>
<p>Dalam bagian berikutnya, Anda akan melihat bagaimana layanan serupa diimplementasikan saat
memperluas kelas {@link android.app.Service} basis, yang membutuhkan kode lebih banyak lagi, namun mungkin
cocok jika Anda perlu menangani beberapa permintaan memulai sekaligus.</p>
<h3 id="ExtendingService">Memperluas kelas Layanan</h3>
<p>Seperti telah Anda lihat di bagian sebelumnya, menggunakan {@link android.app.IntentService} membuat
implementasi layanan yang sudah dimulai jadi sangat sederhana. Namun, bila Anda mengharuskan layanan untuk
melakukan multi-threading (sebagai ganti memproses permintaan memulai melalui antrean pekerjaan), maka Anda
bisa memperluas kelas {@link android.app.Service} untuk menangani masing-masing intent.</p>
<p>Sebagai perbandingan, contoh kode berikut ini adalah implementasi kelas {@link
android.app.Service} yang melakukan pekerjaan yang persis sama dengan contoh di atas menggunakan {@link
android.app.IntentService}. Artinya, untuk setiap permintaan memulai, kode tersebut akan menggunakan thread pekerja
untuk melakukan pekerjaan dan memproses permintaan satu per satu.</p>
<pre>
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
&#64;Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() &lt; endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
&#64;Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
&#64;Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
&#64;Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
&#64;Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
</pre>
<p>Seperti yang bisa Anda lihat, ini membutuhkan lebih banyak pekerjaan daripada menggunakan {@link android.app.IntentService}.</p>
<p>Akan tetapi, karena Anda menangani sendiri setiap panggilan ke {@link android.app.Service#onStartCommand
onStartCommand()}, Anda bisa melakukan beberapa permintaan sekaligus. Itu bukan yang
dilakukan contoh ini, namun jika itu yang diinginkan, Anda bisa membuat thread baru untuk setiap
permintaan dan langsung menjalankannya (sebagai ganti menunggu permintaan sebelumnya selesai).</p>
<p>Perhatikan bahwa metode {@link android.app.Service#onStartCommand onStartCommand()} harus mengembalikan
integer. Integer tersebut merupakan nilai yang menjelaskan cara sistem melanjutkan layanan dalam
kejadian yang dimatikan oleh sistem (sebagaimana dibahas di atas, implementasi default {@link
android.app.IntentService} menangani hal ini untuk Anda, walaupun Anda bisa memodifikasinya). Nilai yang dikembalikan
dari {@link android.app.Service#onStartCommand onStartCommand()} harus berupa salah satu
konstanta berikut ini:</p>
<dl>
<dt>{@link android.app.Service#START_NOT_STICKY}</dt>
<dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
onStartCommand()} dikembalikan, <em>jangan</em> membuat lagi layanan tersebut, kecuali jika ada intent
tertunda yang akan disampaikan. Inilah pilihan teraman untuk menghindari menjalankan layanan Anda
bila tidak diperlukan dan bila aplikasi Anda bisa me-restart pekerjaan yang belum selesai.</dd>
<dt>{@link android.app.Service#START_STICKY}</dt>
<dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
onStartCommand()} dikembalikan, buat kembali layanan dan panggil {@link
android.app.Service#onStartCommand onStartCommand()}, namun <em>jangan</em> menyampaikan ulang intent terakhir.
Sebagai gantinya, sistem akan memanggil {@link android.app.Service#onStartCommand onStartCommand()} dengan
intent null, kecuali jika ada intent tertunda untuk memulai layanan, dan dalam hal ini,
intent tersebut disampaikan. Ini cocok bagi pemutar media (atau layanan serupa) yang tidak
mengeksekusi perintah, namun berjalan terus-menerus dan menunggu pekerjaan.</dd>
<dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
<dd>Jika sistem mematikan layanan setelah {@link android.app.Service#onStartCommand
onStartCommand()} kembali, buat kembali layanan dan panggil {@link
android.app.Service#onStartCommand onStartCommand()} dengan intent terakhir yang disampaikan ke
layanan. Intent yang tertunda akan disampaikan pada gilirannya. Ini cocok bagi layanan yang
aktif melakukan pekerjaan yang harus segera dilanjutkan, misalnya mengunduh file.</dd>
</dl>
<p>Untuk detail selengkapnya tentang nilai pengembalian ini, lihat dokumentasi acuan untuk setiap
konstanta.</p>
<h3 id="StartingAService">Memulai Layanan</h3>
<p>Anda bisa memulai layanan dari aktivitas atau komponen aplikasi lain dengan meneruskan
{@link android.content.Intent} (yang menetapkan layanan yang akan dimulai) ke {@link
android.content.Context#startService startService()}. Sistem Android akan memanggil metode {@link
android.app.Service#onStartCommand onStartCommand()} layanan dan meneruskan {@link
android.content.Intent} padanya. (Jangan sekali-kali memanggil {@link android.app.Service#onStartCommand
onStartCommand()} secara langsung.)</p>
<p>Misalnya, aktivitas bisa memulai contoh layanan di bagian sebelumnya ({@code
HelloSevice}) menggunakan intent eksplisit dengan {@link android.content.Context#startService
startService()}:</p>
<pre>
Intent intent = new Intent(this, HelloService.class);
startService(intent);
</pre>
<p>Metode {@link android.content.Context#startService startService()} segera kembali dan
sistem Android akan memanggil metode {@link android.app.Service#onStartCommand
onStartCommand()} layanan. Jika layanan belum berjalan, sistem mula-mula memanggil {@link
android.app.Service#onCreate onCreate()}, kemudian memanggil {@link android.app.Service#onStartCommand
onStartCommand()}.</p>
<p>Jika layanan juga tidak menyediakan pengikatan, intent yang disampaikan dengan {@link
android.content.Context#startService startService()} adalah satu-satunya mode komunikasi antara
komponen aplikasi dan layanan. Akan tetapi, jika Anda ingin agar layanan mengirimkan hasilnya kembali, maka
klien yang memulai layanan bisa membuat {@link android.app.PendingIntent} untuk siaran
(dengan {@link android.app.PendingIntent#getBroadcast getBroadcast()}) dan menyampaikannya ke layanan
dalam {@link android.content.Intent} yang memulai layanan. Layanan kemudian bisa menggunakan
siaran untuk menyampaikan hasil.</p>
<p>Beberapa permintaan untuk memulai layanan menghasilkan beberapa panggilan pula ke
{@link android.app.Service#onStartCommand onStartCommand()} layanan. Akan tetapi, hanya satu permintaan untuk menghentikan
layanan (dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}) dibutuhkan untuk menghentikannya.</p>
<h3 id="Stopping">Menghentikan layanan</h3>
<p>Layanan yang sudah dimulai harus mengelola daur hidupnya sendiri. Artinya, sistem tidak menghentikan atau
memusnahkan layanan kecuali jika harus memulihkan memori sistem dan layanan
terus berjalan setelah {@link android.app.Service#onStartCommand onStartCommand()} kembali. Jadi,
layanan tersebut harus berhenti sendiri dengan memanggil {@link android.app.Service#stopSelf stopSelf()} atau
komponen lain bisa menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.</p>
<p>Setelah diminta untuk berhenti dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}, sistem akan menghapus layanan
secepatnya.</p>
<p>Akan tetapi, bila layanan Anda menangani beberapa permintaan ke {@link
android.app.Service#onStartCommand onStartCommand()} sekaligus, Anda tidak boleh menghentikan
layanan bila Anda baru selesai memproses permintaan memulai, karena setelah itu mungkin Anda sudah menerima permintaan memulai
yang baru (berhenti pada permintaan pertama akan menghentikan permintaan kedua). Untuk menghindari
masalah ini, Anda bisa menggunakan {@link android.app.Service#stopSelf(int)} untuk memastikan bahwa permintaan
Anda untuk menghentikan layanan selalu berdasarkan pada permintaan memulai terbaru. Artinya, bila Anda memanggil {@link
android.app.Service#stopSelf(int)}, Anda akan meneruskan ID permintaan memulai (<code>startId</code>
yang disampaikan ke {@link android.app.Service#onStartCommand onStartCommand()}) yang terkait dengan permintaan berhenti
Anda. Kemudian jika layanan menerima permintaan memulai baru sebelum Anda bisa memanggil {@link
android.app.Service#stopSelf(int)}, maka ID tidak akan sesuai dan layanan tidak akan berhenti.</p>
<p class="caution"><strong>Perhatian:</strong> Aplikasi Anda perlu menghentikan layanannya
bila selesai bekerja untuk menghindari pemborosan sumber daya sistem dan tenaga baterai. Jika perlu,
komponen lain bisa menghentikan layanan secara eksplisit dengan memanggil {@link
android.content.Context#stopService stopService()}. Bahkan jika Anda mengaktifkan pengikatan bagi layanan,
Anda harus selalu menghentikan layanan sendiri jika layanan tersebut menerima panggilan ke {@link
android.app.Service#onStartCommand onStartCommand()}.</p>
<p>Untuk informasi selengkapnya tentang daur hidup layanan, lihat bagian di bawah ini tentang <a href="#Lifecycle">Mengelola Daur Hidup Layanan</a>.</p>
<h2 id="CreatingBoundService">Membuat Layanan Terikat</h2>
<p>Layanan terikat adalah layanan yang memungkinkan komponen aplikasi untuk mengikatnya dengan memanggil {@link
android.content.Context#bindService bindService()} guna membuat koneksi yang berlangsung lama
(dan umumnya tidak mengizinkan komponen untuk <em>memulainya</em> dengan memanggil {@link
android.content.Context#startService startService()}).</p>
<p>Anda sebaiknya membuat layanan terikat bila ingin berinteraksi dengan layanan dari aktivitas
dan komponen lain dalam aplikasi Anda atau mengeskpos sebagian fungsionalitas aplikasi Anda ke
ke aplikasi lain, melalui komunikasi antarproses (IPC).</p>
<p>Untuk membuat layanan terikat, Anda harus mengimplementasikan metode callback {@link
android.app.Service#onBind onBind()} untuk mengembalikan {@link android.os.IBinder} yang
mendefinisikan antarmuka bagi komunikasi dengan layanan. Komponen aplikasi lain kemudian bisa memanggil
{@link android.content.Context#bindService bindService()} untuk mengambil antarmuka dan
mulai memanggil metode pada layanan. Layanan hanya hidup untuk melayani komponen aplikasi yang
terikat padanya, jadi bila tidak ada komponen yang terikat pada layanan, sistem akan memusnahkannya
(Anda <em>tidak</em> perlu menghentikan layanan terikat seperti halnya bila layanan dimulai
melalui {@link android.app.Service#onStartCommand onStartCommand()}).</p>
<p>Untuk membuat layanan terikat, hal yang perlu dilakukan pertama kali adalah mendefinisikan antarmuka yang menetapkan
cara klien berkomunikasi dengan layanan. Antarmuka antara layanan
dan klien ini harus berupa implementasi {@link android.os.IBinder} dan yang harus dikembalikan
layanan Anda dari metode callback {@link android.app.Service#onBind
onBind()}. Setelah menerima {@link android.os.IBinder}, klien bisa mulai
berinteraksi dengan layanan melalui antarmuka tersebut.</p>
<p>Beberapa klien bisa mengikat ke layanan sekaligus. Bila klien selesai berinteraksi dengan
layanan, klien akan memanggil {@link android.content.Context#unbindService unbindService()} untuk melepas ikatan. Bila
tidak ada klien yang terikat pada layanan, sistem akan menghapus layanan tersebut.</p>
<p>Ada beberapa cara untuk mengimplementasikan layanan terikat dan implementasinya lebih
rumit daripada layanan yang sudah dimulai, jadi layanan terikat dibahas dalam dokumen
terpisah tentang <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>.</p>
<h2 id="Notifications">Mengirim Pemberitahuan ke Pengguna</h2>
<p>Setelah berjalan, layanan bisa memberi tahu pengguna tentang suatu kejadian menggunakan <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a>.</p>
<p>Pemberitahuan Toast adalah pesan yang muncul sebentar pada permukaan jendela saat ini
kemudian menghilang, sementara pemberitahuan baris status memberikan ikon di baris status dengan
pesan yang bisa dipilih oleh pengguna untuk melakukan suatu tindakan (misalnya memulai suatu aktivitas).</p>
<p>Biasanya, pemberitahuan baris status adalah teknik terbaik bila ada pekerjaan latar belakang yang sudah selesai
(misalnya file selesai
diunduh) dan pengguna kini bisa menggunakannya. Bila pengguna memilih pemberitahuan dari
tampilan diperluas, pemberitahuan akan bisa memulai aktivitas (misalnya menampilkan file yang baru diunduh).</p>
<p>Lihat panduan pengembang <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Pemberitahuan Toast</a> atau <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Baris Status</a>
untuk informasi selengkapnya.</p>
<h2 id="Foreground">Menjalankan Layanan di Latar Depan</h2>
<p>Layanan latar depan adalah layanan yang dianggap sebagai sesuatu yang
diketahui secara aktif oleh pengguna, jadi bukan sesuatu yang akan dihapus oleh sistem bila memori menipis. Sebuah
layanan latar depan harus memberikan pemberitahuan bagi baris status, yang ditempatkan pada
heading "Ongoing" yang artinya pemberitahuan tersebut tidak bisa diabaikan kecuali jika layanan
dihentikan atau dihapus dari latar depan.</p>
<p>Misalnya, pemutar musik yang memutar musik dari suatu layanan harus diatur untuk berjalan di
latar depan, karena pengguna mengetahui operasi tersebut
secara eksplisit. Pemberitahuan di baris status bisa menunjukkan lagu saat ini dan memungkinkan
pengguna untuk menjalankan suatu aktivitas untuk berinteraksi dengan pemutar musik.</p>
<p>Untuk meminta agar layanan Anda berjalan di latar depan, panggil {@link
android.app.Service#startForeground startForeground()}. Metode ini memerlukan dua parameter: sebuah integer
yang mengidentifikasi pemberitahuan secara unik dan {@link
android.app.Notification} untuk baris status. Misalnya:</p>
<pre>
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
</pre>
<p class="caution"><strong>Perhatian:</strong> ID integer yang Anda berikan ke {@link
android.app.Service#startForeground startForeground()} tidak boleh 0.</p>
<p>Untuk menghapus layanan dari latar depan, panggil {@link
android.app.Service#stopForeground stopForeground()}. Metode ini memerlukan boolean, yang menunjukkan
apakah pemberitahuan baris status juga akan dihapus. Metode ini <em>tidak</em> menghentikan
layanan. Akan tetapi, jika Anda menghentikan layanan saat masih berjalan di latar depan
maka pemberitahuan juga akan dihapus.</p>
<p>Untuk informasi selengkapnya tentang pemberitahuan, lihat <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Membuat Pemberitahuan
Baris Status</a>.</p>
<h2 id="Lifecycle">Mengelola Daur Hidup Layanan</h2>
<p>Daur hidup layanan jauh lebih sederhana daripada daur hidup aktivitas. Akan tetapi, lebih penting lagi adalah
memerhatikan dengan cermat bagaimana layanan Anda dibuat dan dimusnahkan, karena suatu layanan
bisa berjalan di latar belakang tanpa disadari oleh pengguna.</p>
<p>Daur hidup layanan&mdash;dari saat dibuat hingga dimusnahkan&mdash;bisa mengikuti
dua path berbeda:</p>
<ul>
<li>Layanan yang sudah dimulai
<p>Layanan dibuat bila komponen lain memanggil {@link
android.content.Context#startService startService()}. Layanan kemudian berjalan terus-menerus dan harus
berhenti sendiri dengan memanggil {@link
android.app.Service#stopSelf() stopSelf()}. Komponen lain juga bisa menghentikan
layanan dengan memanggil {@link android.content.Context#stopService
stopService()}. Bila layanan dihentikan, sistem akan menghancurkannya.</p></li>
<li>Layanan terikat
<p>Layanan dibuat bila komponen lain (klien) memanggil {@link
android.content.Context#bindService bindService()}. Klien kemudian berkomunikasi dengan layanan
melalui antarmuka {@link android.os.IBinder}. Klien bisa menutup koneksi dengan memanggil
{@link android.content.Context#unbindService unbindService()}. Sejumlah klien bisa mengikat pada
layanan yang sama dan bila semuanya melepas ikatan, sistem akan memusnahkan layanan tersebut. (Layanan
<em>tidak</em> perlu berhenti sendiri.)</p></li>
</ul>
<p>Kedua path tersebut tidak benar-benar terpisah. Artinya, Anda bisa mengikat ke layanan yang sudah
dimulai dengan {@link android.content.Context#startService startService()}. Misalnya, layanan
musik latar belakang bisa dimulai dengan memanggil {@link android.content.Context#startService
startService()} dengan {@link android.content.Intent} yang mengidentifikasi musik yang akan diputar. Kemudian,
mungkin saat pengguna ingin mengontrol pemutar musik atau mendapatkan informasi
tentang lagu yang diputar, aktivitas bisa mengikat ke layanan dengan memanggil {@link
android.content.Context#bindService bindService()}. Dalam kasus seperti ini, {@link
android.content.Context#stopService stopService()} atau {@link android.app.Service#stopSelf
stopSelf()} tidak menghentikan layanan sampai semua klien melepas ikatan. </p>
<h3 id="LifecycleCallbacks">Mengimplementasikan callback daur hidup</h3>
<p>Seperti halnya aktivitas, layanan memiliki metode callback daur hidup yang bisa Anda implementasikan
untuk memantau perubahan status layanan dan melakukan pekerjaan pada waktu yang tepat. Layanan skeleton
berikut memperagakan setiap metode daur hidup:</p>
<pre>
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
boolean mAllowRebind; // indicates whether onRebind should be used
&#64;Override
public void {@link android.app.Service#onCreate onCreate}() {
// The service is being created
}
&#64;Override
public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
// The service is starting, due to a call to {@link android.content.Context#startService startService()}
return <em>mStartMode</em>;
}
&#64;Override
public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
// A client is binding to the service with {@link android.content.Context#bindService bindService()}
return <em>mBinder</em>;
}
&#64;Override
public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
// All clients have unbound with {@link android.content.Context#unbindService unbindService()}
return <em>mAllowRebind</em>;
}
&#64;Override
public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
// A client is binding to the service with {@link android.content.Context#bindService bindService()},
// after onUnbind() has already been called
}
&#64;Override
public void {@link android.app.Service#onDestroy onDestroy}() {
// The service is no longer used and is being destroyed
}
}
</pre>
<p class="note"><strong>Catatan:</strong> Tidak seperti metode callback daur hidup aktivitas, Anda
<em>tidak</em> perlu memanggil implementasi superkelas metode callback tersebut.</p>
<img src="{@docRoot}images/service_lifecycle.png" alt="" />
<p class="img-caption"><strong>Gambar 2.</strong> Daur hidup layanan. Diagram di sebelah kiri
menampilkan daur hidup bila layanan dibuat dengan {@link android.content.Context#startService
startService()} dan diagram di sebelah kanan menampilkan daur hidup bila layanan dibuat
dengan {@link android.content.Context#bindService bindService()}.</p>
<p>Dengan mengimplementasikan metode-metode ini, Anda bisa memantau dua loop tersarang (nested loop) daur hidup layanan: </p>
<ul>
<li><strong>Seluruh masa pakai</strong> layanan terjadi antara saat {@link
android.app.Service#onCreate onCreate()} dipanggil dan saat {@link
android.app.Service#onDestroy} kembali. Seperti halnya aktivitas, layanan melakukan penyiapan awal di
{@link android.app.Service#onCreate onCreate()} dan melepaskan semua sisa sumber daya yang ada di {@link
android.app.Service#onDestroy onDestroy()}. Misalnya,
layanan pemutar musik bisa membuat thread tempat musik akan diputar dalam {@link
android.app.Service#onCreate onCreate()}, kemudian menghentikan thread tersebut dalam {@link
android.app.Service#onDestroy onDestroy()}.
<p>Metode {@link android.app.Service#onCreate onCreate()} dan {@link android.app.Service#onDestroy
onDestroy()} diperlukan semua layanan, baik yang
dibuat oleh {@link android.content.Context#startService startService()} maupun {@link
android.content.Context#bindService bindService()}.</p></li>
<li><strong>Masa pakai aktif</strong> layanan dimulai dengan panggilan ke {@link
android.app.Service#onStartCommand onStartCommand()} atau {@link android.app.Service#onBind onBind()}.
Masing-masing metode diberikan {@link
android.content.Intent} yang diteruskan ke {@link android.content.Context#startService
startService()} atau {@link android.content.Context#bindService bindService()}.
<p>Jika layanan telah dimulai, masa pakai aktif akan berakhir pada saat yang sama dengan
berakhirnya seluruh masa pakai (layanan masih aktif bahkan setelah {@link android.app.Service#onStartCommand
onStartCommand()} kembali). Jika layanan tersebut terikat, masa pakai aktifnya akan berakhir bila {@link
android.app.Service#onUnbind onUnbind()} kembali.</p>
</li>
</ul>
<p class="note"><strong>Catatan:</strong> Meskipun layanan yang sudah dimulai dihentikan dengan panggilan ke
{@link android.app.Service#stopSelf stopSelf()} atau {@link
android.content.Context#stopService stopService()}, tidak ada callback tersendiri bagi
layanan tersebut (tidak ada callback {@code onStop()}). Jadi, kecuali jika layanan terikat ke klien,
sistem akan memusnahkannya bila layanan dihentikan&mdash;{@link
android.app.Service#onDestroy onDestroy()} adalah satu-satunya callback yang diterima.</p>
<p>Gambar 2 mengilustrasikan metode callback yang lazim bagi suatu layanan. Walaupun gambar tersebut memisahkan
layanan yang dibuat oleh {@link android.content.Context#startService startService()} dari layanan
yang dibuat oleh {@link android.content.Context#bindService bindService()}, ingatlah
bahwa suatu layanan, bagaimana pun dimulainya, bisa memungkinkan klien mengikat padanya.
Jadi, suatu layanan yang awalnya dimulai dengan {@link android.app.Service#onStartCommand
onStartCommand()} (oleh klien yang memanggil {@link android.content.Context#startService startService()})
masih bisa menerima panggilan ke {@link android.app.Service#onBind onBind()} (bila klien memanggil
{@link android.content.Context#bindService bindService()}).</p>
<p>Untuk informasi selengkapnya tentang membuat layanan yang menyediakan pengikatan, lihat dokumen <a href="{@docRoot}guide/components/bound-services.html">Layanan Terikat</a>,
yang menyertakan informasi selengkapnya tentang metode callback {@link android.app.Service#onRebind onRebind()}
di bagian tentang <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">Mengelola Daur Hidup
Layanan Terikat</a>.</p>
<!--
<h2>Beginner's Path</h2>
<p>To learn how to query data from the system or other applications (such as contacts or media
stored on the device), continue with the <b><a
href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
document.</p>
-->

View File

@@ -0,0 +1,578 @@
page.title=Tugas dan Back-Stack
parent.title=Aktivitas
parent.link=activities.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#ActivityState">Menyimpan Status Aktivitas</a></li></li>
<li><a href="#ManagingTasks">Mengelola Tugas</a>
<ol>
<li><a href="#TaskLaunchModes">Mendefinisikan mode peluncuran</a></li>
<li><a href="#Affinities">Menangani afinitas</a></li>
<li><a href="#Clearing">Menghapus back-stack</a></li>
<li><a href="#Starting">Memulai tugas</a></li>
</ol>
</li>
</ol>
<h2>Artikel</h2>
<ol>
<li><a href="http://android-developers.blogspot.com/2010/04/multitasking-android-way.html">
Multitasking Ala Android</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}design/patterns/navigation.html">Desain Android:
Navigasi</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html">Elemen manifes
{@code &lt;activity&gt;}</a></li>
<li><a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a></li>
</ol>
</div>
</div>
<p>Sebuah aplikasi biasanya berisi beberapa <a href="{@docRoot}guide/components/activities.html">aktivitas</a>. Setiap aktivitas
harus didesain dengan jenis tindakan tertentu yang bisa dilakukan pengguna dan bisa memulai aktivitas
lain. Misalnya, aplikasi email mungkin memiliki satu aktivitas untuk menampilkan daftar pesan baru.
Bila pengguna memilih sebuah pesan, aktivitas baru akan terbuka untuk melihat pesan tersebut.</p>
<p>Aktivitas bahkan bisa memulai aktivitas yang ada dalam aplikasi lain di perangkat. Misalnya
, jika aplikasi Anda ingin mengirim pesan email, Anda bisa mendefinisikan intent untuk melakukan tindakan
"kirim" dan menyertakan sejumlah data, seperti alamat email dan pesan. Aktivitas dari aplikasi
lain yang mendeklarasikan dirinya untuk menangani jenis intent ini akan terbuka. Dalam hal ini, intent
tersebut untuk mengirim email, sehingga aktivitas "menulis" pada aplikasi email akan dimulai (jika beberapa aktivitas
mendukung intent yang sama, maka sistem akan memungkinkan pengguna memilih mana yang akan digunakan). Bila email telah
dikirim, aktivitas Anda akan dilanjutkan dan seolah-olah aktivitas email adalah bagian dari aplikasi Anda. Meskipun
aktivitas mungkin dari aplikasi yang berbeda, Android akan tetap mempertahankan pengalaman pengguna yang mulus
dengan menjalankan kedua aktivitas dalam <em>tugas</em> yang sama.</p>
<p>Tugas adalah kumpulan aktivitas yang berinteraksi dengan pengguna
saat melakukan pekerjaan tertentu. Aktivitas tersebut diatur dalam tumpukan (<em>back-stack</em>), dalam
urutan membuka setiap aktivitas.</p>
<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Adding fragments to a task's back stack</h3>
<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example,
suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the
other being a layout to display an item from the list (fragment B). When the user selects an item
from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be
desireable for the user to navigate back to reveal fragment B, using the <em>Back</em> button.</p>
<p>In order to add fragment B to the back stack so that this is possible, you must call {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link
android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment
C.</p>
<p>For more information about using fragments and adding them to the back stack, see the {@link
android.app.Fragment} class documentation.</p>
</div>
</div>
-->
<p>Layar Home perangkat adalah tempat memulai hampir semua tugas. Bila pengguna menyentuh ikon di launcher
aplikasi
(atau pintasan pada layar Home), tugas aplikasi tersebut akan muncul pada latar depan. Jika tidak ada
tugas untuk aplikasi (aplikasi tidak digunakan baru-baru ini), maka tugas baru
akan dibuat dan aktivitas "utama" untuk aplikasi tersebut akan terbuka sebagai aktivitas akar dalam back-stack.</p>
<p>Bila aktivitas saat ini dimulai lagi, aktivitas baru akan didorong ke atas back-stack dan
mengambil fokus. Aktivitas sebelumnya tetap dalam back-stack, namun dihentikan. Bila aktivitas
dihentikan, sistem akan mempertahankan status antarmuka penggunanya saat ini. Bila pengguna menekan tombol
<em>Back</em>
, aktivitas saat ini akan dikeluarkan dari atas back-stack (aktivitas dimusnahkan) dan
aktivitas sebelumnya dilanjutkan (status UI sebelumnya dipulihkan). Aktivitas dalam back-stack
tidak pernah disusun ulang, hanya didorong dan dikeluarkan dari back-stack&mdash;yang didorong ke back-stack saat dimulai oleh
aktivitas saat ini dan dikeluarkan bila pengguna meninggalkannya menggunakan tombol <em>Back</em>. Dengan demikian,
back-stack
beroperasi sebagai struktur objek "masuk terakhir, keluar pertama". Gambar 1 melukiskan perilaku
ini dengan jangka waktu yang menunjukkan kemajuan antar aktivitas beserta
back-stack pada setiap waktu.</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Representasi tentang cara setiap aktivitas baru dalam
tugas menambahkan item ke back-stack. Bila pengguna menekan tombol <em>Back</em>, aktivitas
saat ini
akan dimusnahkan dan aktivitas sebelumnya dilanjutkan.</p>
<p>Jika pengguna terus menekan <em>Back</em>, maka setiap aktivitas dalam back-stack akan dikeluarkan untuk
menampilkan
yang sebelumnya, sampai pengguna kembali ke layar Home (atau aktivitas mana pun yang sedang dijalankan saat tugas
dimulai. Bila semua aktivitas telah dihapus dari back-stack, maka tugas tidak akan ada lagi.</p>
<div class="figure" style="width:287px">
<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p
class="img-caption"><strong>Gambar 2.</strong> Dua tugas: Tugas B menerima interaksi pengguna
di latar depan, sedangkan Tugas A di latar belakang, menunggu untuk dilanjutkan.</p>
</div>
<div class="figure" style="width:215px">
<img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p
class="img-caption"><strong>Gambar 3.</strong> Satu aktivitas dibuat instance-nya beberapa kali.</p>
</div>
<p>Tugas adalah unit kohesif yang bisa dipindahkan ke "latar belakang" bila pengguna memulai tugas baru atau masuk ke
layar Home, melalui tombol<em>Home</em>. Sementara di latar belakang, semua aktivitas dalam
tugas
dihentikan, namun back-stack untuk tugas tidak berubah&mdash;tugas kehilangan fokus saat
tugas lain berlangsung, seperti yang ditampilkan dalam gambar 2. Kemudian, tugas bisa kembali ke "latar depan" agar pengguna
bisa melanjutkan tugas di tempat menghentikannya. Anggaplah, misalnya, tugas saat ini (Tugas A) memiliki tiga
aktivitas dalam back-stack&mdash;dua pada aktivitas saat ini. Pengguna menekan tombol <em>Home</em>
, kemudian
memulai aplikasi baru dari launcher aplikasi. Bila muncul layar Home, Tugas A akan beralih
ke latar belakang. Bila aplikasi baru dimulai, sistem akan memulai tugas untuk aplikasi tersebut
(Tugas B) dengan back-stack aktivitas sendiri. Setelah berinteraksi dengan aplikasi
tersebut, pengguna akan kembali ke Home lagi dan memilih aplikasi yang semula
memulai Tugas A. Sekarang, Tugas A muncul di
latar depan&mdash;ketiga aktivitas dalam back-stack tidak berubah dan aktivitas di atas
back-stack akan dilanjutkan. Pada
titik ini pengguna juga bisa beralih kembali ke Tugas B dengan masuk ke Home dan memilih ikon aplikasi
yang memulai tugas tersebut (atau dengan memilih tugas aplikasi dari
<a href="{@docRoot}guide/components/recents.html">layar ikhtisar</a>).
Ini adalah contoh dari melakukan multitasking di Android.</p>
<p class="note"><strong>Catatan:</strong> Beberapa tugas bisa berlangsung di latar belakang secara bersamaan.
Akan tetapi, jika pengguna menjalankan banyak tugas di latar belakang sekaligus, sistem mungkin mulai
menghapus aktivitas latar belakang untuk memulihkan memori, yang akan menyebabkan status aktivitas hilang.
Lihat bagian berikut tentang <a href="#ActivityState">Status aktivitas</a>.</p>
<p>Karena aktivitas di back-stack tidak pernah diatur ulang, jika aplikasi Anda memungkinkan
pengguna untuk memulai aktivitas tertentu dari lebih dari satu aktivitas, instance baru
aktivitas tersebut akan dibuat dan didorong ke back-stack (bukannya memunculkan instance sebelumnya dari
aktivitas ke atas). Dengan demikian, satu aktivitas pada aplikasi Anda mungkin dibuat beberapa
kali (bahkan dari beberapa tugas), seperti yang ditampilkan dalam gambar 3. Dengan demikian, jika pengguna mengarahkan mundur
menggunakan tombol <em>Back</em>, setiap instance aktivitas ini akan ditampilkan dalam urutan saat
dibuka (masing-masing
dengan status UI sendiri). Akan tetapi, Anda bisa memodifikasi perilaku ini jika tidak ingin aktivitas
dibuat instance-nya lebih dari sekali. Caranya dibahas di bagian selanjutnya tentang <a href="#ManagingTasks">Mengelola Tugas</a>.</p>
<p>Untuk meringkas perilaku default aktivitas dan tugas:</p>
<ul>
<li>Bila Aktivitas A memulai Aktivitas B, Aktivitas A dihentikan, namun sistem mempertahankan statusnya
(seperti posisi gulir dan teks yang dimasukkan ke dalam formulir).
Jika pengguna menekan tombol <em>Back</em> saat dalam Aktivitas B, Aktivitas A akan dilanjutkan dengan status
yang dipulihkan.</li>
<li>Bila pengguna meninggalkan tugas dengan menekan tombol <em>Home</em> aktivitas saat ini akan
dihentikan dan
tugas beralih ke latar belakang. Sistem akan mempertahankan status setiap aktivitas dalam tugas. Jika
nanti pengguna melanjutkan tugas dengan memilih ikon launcher yang memulai tugas, tugas tersebut akan
beralih ke latar depan dan melanjutkan aktivitas di atas back-stack.</li>
<li>Jika pengguna menekan tombol <em>Back</em>, aktivitas saat ini akan dikeluarkan dari back-stack
dan
dimusnahkan. Aktivitas sebelumnya dalam back-stack akan dilanjutkan. Bila suatu aktivitas dimusnahkan, sistem
<em>tidak akan</em>mempertahankan status aktivitas.</li>
<li>Aktivitas bisa dibuat instance-nya beberapa kali, bahkan dari tugas-tugas lainnya.</li>
</ul>
<div class="note design">
<p><strong>Desain Navigasi</strong></p>
<p>Untuk mengetahui selengkapnya tentang cara kerja navigasi aplikasi di Android, baca panduan <a href="{@docRoot}design/patterns/navigation.html">Navigasi</a> Desain Android.</p>
</div>
<h2 id="ActivityState">Menyimpan Status Aktivitas</h2>
<p>Seperti dibahas di atas, perilaku default sistem akan mempertahankan status aktivitas bila
dihentikan. Dengan cara ini, bila pengguna mengarah kembali ke aktivitas sebelumnya, antarmuka pengguna akan muncul
seperti saat ditinggalkan. Akan tetapi, Anda bisa&mdash;dan <strong>harus</strong>&mdash;secara proaktif mempertahankan
status aktivitas menggunakan metode callback, jika aktivitas ini dimusnahkan dan harus
dibuat kembali.</p>
<p>Bila sistem menghentikan salah satu aktivitas (seperti saat aktivitas baru dimulai atau tugas
dipindah ke latar belakang), sistem mungkin memusnahkan aktivitas sepenuhnya jika perlu memulihkan
memori sistem. Bila hal ini terjadi, informasi tentang status aktivitas akan hilang. Jika hal ini terjadi, sistem
masih
mengetahui bahwa aktivitas memiliki tempat di back-stack, namun saat aktivitas tersebut dibawa ke bagian teratas
back-stack, sistem harus membuatnya kembali (bukan melanjutkannya). Untuk
menghindari hilangnya pekerjaan pengguna, Anda harus secara proaktif mempertahankannya dengan menerapkan metode callback
{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
dalam aktivitas.</p>
<p>Untuk informasi selengkapnya tentang cara menyimpan status aktivitas Anda, lihat dokumen
<a href="{@docRoot}guide/components/activities.html#SavingActivityState">Aktivitas</a>.</p>
<h2 id="ManagingTasks">Mengelola Tugas</h2>
<p>Cara Android mengelola tugas dan back-stack, seperti yang dijelaskan di atas&mdash;dengan menempatkan semua
aktivitas yang dimulai secara berurutan dalam tugas yang sama dan dalam back-stack "masuk terakhir, keluar pertama"&mdash;berfungsi
dengan baik untuk kebanyakan aplikasi dan Anda tidak perlu khawatir tentang cara mengaitkan aktivitas
dengan tugas atau cara penempatannya di back-stack. Akan tetapi, Anda bisa memutuskan apakah ingin menyela
perilaku normal. Mungkin Anda ingin agar suatu aktivitas dalam aplikasi untuk memulai tugas baru bila telah
dimulai (sebagai ganti menempatkannya dalam tugas saat ini); atau, bila memulai aktivitas, Anda ingin
memajukan instance yang ada (sebagai ganti membuat instance
baru pada bagian teratas back-stack); atau, Anda ingin back-stack dihapus dari semua
aktivitas selain untuk aktivitas akar bila pengguna meninggalkan tugas.</p>
<p>Anda bisa melakukan semua ini dan lainnya, dengan atribut dalam elemen manifes
<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
dan dengan flag pada intent yang Anda teruskan ke
{@link android.app.Activity#startActivity startActivity()}.</p>
<p>Dalam hal ini, atribut<a href="{@docRoot}guide/topics/manifest/activity-element.html">
{@code &lt;activity&gt;}</a> utama yang bisa Anda gunakan adalah:</p>
<ul class="nolist">
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">
{@code taskAffinity}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">
{@code launchMode}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">
{@code clearTaskOnLaunch}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
{@code alwaysRetainTaskState}</a></li>
<li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">
{@code finishOnTaskLaunch}</a></li>
</ul>
<p>Dan flag intent utama yang bisa Anda gunakan adalah:</p>
<ul class="nolist">
<li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li>
<li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li>
<li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li>
</ul>
<p>Dalam bagian berikut, Anda akan melihat cara menggunakan beberapa atribut manifes ini dan flag
intent untuk mendefinisikan cara mengaitkan aktivitas dengan tugas dan cara perilakunya di back-stack.</p>
<p>Juga, pertimbangan cara menyatakan dan mengelola tugas dan aktivitas
dibahas secara terpisah di layar ikhtisar. Lihat <a href="{@docRoot}guide/components/recents.html">Layar Ikhtisar</a>
untuk informasi selengkapnya. Biasanya Anda harus mengizinkan sistem mendefinisikan cara menyatakan tugas dan
aktivitas di layar ikhtisar, dan Anda tidak perlu memodifikasi perilaku ini.</p>
<p class="caution"><strong>Perhatian:</strong> Kebanyakan aplikasi tidak harus menyela perilaku
default untuk aktivitas dan tugas. Jika merasa bahwa aktivitas Anda perlu memodifikasi
perilaku default, lakukan dengan hati-hati dan pastikan menguji kegunaan aktivitas selama
dijalankan dan saat mengarahkan kembali ke sana dari aktivitas dan tugas lain dengan tombol <em>Back</em>.
Pastikan menguji perilaku navigasi yang mungkin bertentangan dengan perilaku yang diharapkan pengguna.</p>
<h3 id="TaskLaunchModes">Mendefinisikan mode peluncuran</h3>
<p>Mode peluncuran memungkinkan Anda mendefinisikan cara mengaitkan instance baru dari suatu aktivitas dengan
tugas saat ini. Anda bisa mendefinisikan beragam mode peluncuran dalam dua cara:</p>
<ul class="nolist">
<li><a href="#ManifestForTasks">Menggunakan file manifes</a>
<p>Bila Anda mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas
dengan tugas-tugas saat mulai.</li>
<li><a href="#IntentFlagsForTasks">Menggunakan flag intent</a>
<p>Saat memanggil{@link android.app.Activity#startActivity startActivity()},
Anda bisa menyertakan flag dalam {@link android.content.Intent} yang menyatakan cara (atau
apakah) aktivitas baru tersebut harus dikaitkan dengan tugas saat ini.</p></li>
</ul>
<p>Dengan demikian, jika Aktivitas A memulai Aktivitas B, Aktivitas B bisa mendefinisikan dalam manifesnya cara
mengaitkan dengan tugas saat ini (jika sama sekali) dan Aktivitas A juga bisa meminta cara mengaitkan Aktivitas B
dengan tugas saat ini. Jika kedua aktivitas mendefinisikan cara mengaitkan Aktivitas B
dengan tugas, maka permintaan Aktivitas A (sebagaimana didefinisikan dalam intent) lebih dihargai daripada
permintaan Aktivitas B (sebagaimana didefinisikan dalam manifesnya).</p>
<p class="note"><strong>Catatan:</strong> Beberapa mode peluncuran yang tersedia untuk file manifes
tidak tersedia sebagai flag untuk intent dan, juga, beberapa mode peluncuran yang tersedia sebagai flag
untuk intent tidak bisa didefinisikan dalam manifest.</p>
<h4 id="ManifestForTasks">Menggunakan file manifes</h4>
<p>Saat mendeklarasikan aktivitas dalam file manifes, Anda bisa menetapkan cara mengaitkan aktivitas
dengan tugas menggunakan <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
melalui atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a> elemen.</p>
<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a> menetapkan instruksi tentang cara meluncurkan aktivitas
ke dalam tugas. Ada empat macam mode peluncuran yang bisa Anda tetapkan ke atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code>
:</p>
<dl>
<dt>{@code "standard"} (mode default)</dt>
<dd>Default. Sistem membuat instance baru aktivitas dalam tugas yang
akan menjadi tempat memulainya dan mengarahkan intent ke sana. Aktivitas ini bisa dibuat instance-nya beberapa kali,
masing-masing instance bisa dimiliki oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance.</dd>
<dt>{@code "singleTop"}</dt>
<dd>Jika instance aktivitas sudah ada di bagian teratas tugas saat ini, sistem
akan mengarahkan intent ke instance tersebut melalui panggilan ke metode {@link
android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru dari
aktivitas tersebut. Aktivitas bisa dibuat instance-nya beberapa kali, masing-masing instance bisa dimiliki
oleh tugas berbeda, dan satu tugas bisa memiliki beberapa instance (namun hanya jika
aktivitas di bagian teratas back-stack <em>bukan</em> instance yang ada dari aktivitas tersebut).
<p>Misalnya, anggaplah back-stack tugas terdiri dari aktivitas A akar dengan aktivitas B, C,
dan D di bagian teratas (back-stack adalah A-B-C-D; D yang teratas). Intent masuk untuk aktivitas tipe D.
Jika D memiliki mode peluncuran {@code "standard"} default, instance baru dari kelas ini akan diluncurkan dan
back-stack menjadi A-B-C-D-D. Namun, jika mode peluncuran D adalah {@code "singleTop"}, instance
yang ada dari D akan menerima intent melalui {@link
android.app.Activity#onNewIntent onNewIntent()}, karena ada di bagian teratas back-stack&mdash;
back-stack tetap A-B-C-D. Akan tetapi, jika intent masuk untuk aktivitas tipe B, maka
instance B baru akan ditambahkan ke back-stack, sekalipun mode peluncuran adalah{@code "singleTop"}.</p>
<p class="note"><strong>Catatan:</strong> Bila instance dari aktivitas baru telah dibuat,
pengguna bisa menekan tombol <em>Back</em> untuk kembali ke aktivitas sebelumnya. Namun bila instance
yang ada dari
aktivitas menangani intent baru, pengguna tidak bisa menekan tombol <em>Back</em> untuk kembali ke
status
aktivitas sebelum intent baru masuk di {@link android.app.Activity#onNewIntent
onNewIntent()}.</p>
</dd>
<dt>{@code "singleTask"}</dt>
<dd>Sistem membuat tugas baru dan membuat instance aktivitas di akar tugas baru.
Akan tetapi, jika instance aktivitas sudah ada dalam tugas terpisah, sistem akan mengarahkan
intent ke instance yang ada melalui panggilan ke metode {@link
android.app.Activity#onNewIntent onNewIntent()}, bukan membuat instance baru. Hanya
boleh ada satu instance aktivitas untuk setiap kalinya.
<p class="note"><strong>Catatan:</strong> Meskipun aktivitas dimulai di tugas baru, tombol
<em>Back</em> tetap akan mengembalikan pengguna ke aktivitas sebelumnya.</p></dd>
<dt>{@code "singleInstance"}.</dt>
<dd>Sama seperti {@code "singleTask"}, namun sistem tidak meluncurkan aktivitas lain ke
tugas yang menyimpan instance. Aktivitas selalu satu dan satu-satunya anggota dari tugasnya;
aktivitas apa pun yang dimulai dengan ini akan dibuka di tugas yang terpisah.</dd>
</dl>
<p>Sebagai contoh lainnya, aplikasi Browser Android mendeklarasikan bahwa aktivitas browser web harus
selalu dibuka dalam tugasnya sendiri&mdash;dengan menetapkan mode pembuka {@code singleTask} dalam elemen<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.
Ini berarti bahwa jika aplikasi Anda mengeluarkan
intent untuk membuka Browser Android, aktivitasnya <em>tidak</em> akan ditempatkan dalam tugas
yang sama seperti aplikasi Anda. Sebagai gantinya, tugas baru akan dimulai untuk Browser atau, jika Browser
sudah memiliki tugas yang berjalan di latar belakang, tugas tersebut akan dimajukan untuk menangani intent
baru.</p>
<p>Baik aktivitas dimulai dalam tugas baru atau maupun dalam tugas yang sama seperti aktivitas yang memulainya, tombol
<em>Back</em> selalu membawa pengguna ke aktivitas sebelumnya. Akan tetapi, jika
Anda memulai aktivitas yang menetapkan mode pembuka {@code singleTask}, maka jika instance
aktivitas tersebut ada dalam tugas latar belakang, seluruh tugas tersebut akan dibawa ke latar depan. Pada titik
ini, back-stack sekarang menyertakan semua aktivitas dari tugas yang dimajukan, di atas
back-stack. Gambar 4 mengilustrasikan tipe skenario ini.</p>
<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" />
<p class="img-caption"><strong>Gambar 4.</strong> Representasi tentang cara aktivitas dengan
mode pembuka "singleTask" ditambahkan ke back-stack. Jika aktivitas tersebut sudah menjadi bagian dari
tugas latar belakang dengan back-stack sendiri, maka seluruh back-stack juga
dimajukan, di atas tugas saat ini.</p>
<p>Untuk informasi selengkapnya tentang menggunakan mode pembuka dalam file manifes, lihat dokumentasi elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
, di mana atribut {@code launchMode} dan nilai-nilai yang diterima
akan dibahas selengkapnya.</p>
<p class="note"><strong>Catatan:</strong> Perilaku yang Anda tentukan untuk aktivitas dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
bisa dikesampingkan dengan flag yang disertakan bersama intent yang memulai aktivitas Anda, seperti dibahas dalam
bagian berikutnya.</p>
<h4 id="#IntentFlagsForTasks">Menggunakan flag Intent</h4>
<p>Saat memulai aktivitas, Anda bisa memodifikasi asosiasi default aktivitas pada tugasnya
dengan menyertakan flag dalam intent yang Anda kirimkan ke {@link
android.app.Activity#startActivity startActivity()}. Flag yang bisa Anda gunakan untuk memodifikasi perilaku default
adalah:</p>
<p>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt>
<dd>Memulai aktivitas dalam tugas baru. Jika tugas sudah dijalankan untuk aktivitas yang sekarang
Anda mulai, tugas tersebut akan dibawa ke latar depan dengan status terakhir yang dipulihkan dan aktivitas
akan menerima intent baru dalam {@link android.app.Activity#onNewIntent onNewIntent()}.
<p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTask"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
yang dibahas di bagian sebelumnya.</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt>
<dd>Jika aktivitas yang dimulai adalah aktivitas saat ini (di bagian teratas back-stack), maka
instance yang ada akan menerima panggilan ke {@link android.app.Activity#onNewIntent onNewIntent()}
sebagai ganti membuat instance baru aktivitas.
<p>Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTop"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
yang dibahas di bagian sebelumnya.</p></dd>
<dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt>
<dd>Jika aktivitas yang dimulai sudah berjalan dalam tugas saat ini, maka sebagai
ganti meluncurkan instance baru aktivitas tersebut, semua kegiatan lain di atasnya akan
dimusnahkan dan intent ini akan disampaikan ke instance aktivitas yang dilanjutkan (sekarang di atas),
melalui {@link android.app.Activity#onNewIntent onNewIntent()}).
<p>Tidak ada nilai untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
yang menghasilkan perilaku ini.</p>
<p>{@code FLAG_ACTIVITY_CLEAR_TOP} paling sering digunakan bersama dengan
{@code FLAG_ACTIVITY_NEW_TASK}.
Bila digunakan bersama-sama, flag ini adalah cara penempatan aktivitas yang ada
dalam tugas lain dan meletakkannya dalam posisi yang memungkinkannya merespons intent. </p>
<p class="note"><strong>Catatan:</strong> Jika mode pembuka aktivitas yang didesain adalah
{@code "standard"},
ini juga akan dihapus dari back-stack dan instance baru akan diluncurkan di tempatnya untuk menangani
intent yang masuk. Itu karena instance baru selalu dibuat untuk intent baru bila
mode peluncuran adalah {@code "standard"}. </p>
</dd>
</dl>
<h3 id="Affinities">Menangani afinitas</h3>
<p><em>Afinitas</em> menunjukkan tugas mana yang disukai aktivitas untuk dimiliki. Secara default, semua
aktivitas aplikasi yang sama memiliki afinitas untuk satu sama lain. Jadi, secara default, semua
aktivitas dalam aplikasi yang sama lebih menyukai berada dalam tugas yang sama. Akan tetapi, Anda bisa memodifikasi
afinitas default untuk suatu aktivitas. Aktivitas yang didefinisikan dalam
aplikasi yang berbeda bisa berbagi afinitas, atau aktivitas yang didefinisikan dalam aplikasi yang sama bisa
diberi afinitas tugas yang berbeda.</p>
<p>Anda bisa memodifikasi afinitas untuk setiap yang diberikan
dengan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>.</p>
<p>Atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
mengambil nilai string, yang harus unik dari nama paket default
yang dideklarasikan dalam elemen <a href="{@docRoot}guide/topics/manifest/manifest-element.html">
{@code &lt;manifest&gt;}
</a>, karena sistem menggunakan nama untuk mengidentifikasi afinitas
tugas default untuk aplikasi.</p>
<p>Afinitas berperan dalam dua keadaan:</p>
<ul>
<li>Bila intent yang meluncurkan aktivitas berisi flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
.
<p>Aktivitas baru, secara default, diluncurkan ke dalam tugas aktivitas
yang disebut {@link android.app.Activity#startActivity startActivity()}. Ini didorong ke back-stack
yang sama seperti caller. Akan tetapi, jika intent yang diteruskan ke
{@link android.app.Activity#startActivity startActivity()}
berisi flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
, maka sistem akan mencari tugas yang berbeda untuk menampung aktivitas baru. Sering kali, itu adalah tugas baru.
Akan tetapi, tidak harus demikian. Jika sudah ada tugas lama dengan afinitas yang sama seperti
aktivitas baru, aktivitas ini akan diluncurkan ke dalam tugas tersebut. Jika tidak, tugas baru akan dimulai.</p>
<p>Jika flag ini menyebabkan aktivitas memulai tugas baru dan pengguna menekan tombol <em>Home</em>
untuk meninggalkannya,
harus ada cara bagi pengguna untuk mengarahkan kembali ke tugas. Beberapa entitas (seperti
notification manager) selalu memulai aktivitas dalam tugas eksternal, tidak pernah sebagai bagian dari miliknya sendiri, jadi
selalu menempatkan {@code FLAG_ACTIVITY_NEW_TASK} dalam intent yang diteruskan ke
{@link android.app.Activity#startActivity startActivity()}.
Jika Anda memiliki aktivitas yang bisa dipanggil melalui
entitas eksternal yang mungkin menggunakan flag ini, hati-hatilah karena pengguna memiliki cara independen untuk kembali
ke tugas yang telah dimulai, seperti dengan ikon launcher (aktivitas akar dari tugas
memiliki filter intent {@link android.content.Intent#CATEGORY_LAUNCHER}; lihat bagian <a href="#Starting">Memulai tugas</a> di bawah ini).</p>
</li>
<li>Bila aktivitas memiliki atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a> sendiri yang diatur ke {@code "true"}.
<p>Dalam hal ini, aktivitas bisa berpindah dari tugas yang dimulainya ke tugas yang afinitasnya
dimilikinya, bila tugas tersebut di bawa ke latar depan.</p>
<p>Misalnya, anggaplah sebuah aktivitas melaporkan kondisi cuaca di sejumlah kota terpilih
yang didefinisikan sebagai bagian dari aplikasi perjalanan. Aktivitas memiliki afinitas yang sama dengan aktivitas lain dalam aplikasi
yang sama (afinitas aplikasi default) dan aktivitas ini memungkinkan re-parenting dengan atribut ini.
Bila salah satu aktivitas Anda memulai aktivitas laporan cuaca, awalnya aktivitas ini dimiliki oleh tugas
yang sama dengan aktivitas Anda. Akan tetapi, bila tugas aplikasi perjalanan di bawa ke latar depan,
aktivitas laporan cuaca akan ditetapkan kembali ke tugas itu dan ditampilkan di dalamnya.</p>
</li>
</ul>
<p class="note"><strong>Tip:</strong> Jika file {@code .apk} berisi lebih dari satu "aplikasi"
dari sudut pandang pengguna, Anda mungkin perlu menggunakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
untuk menetapkan afinitas berbeda pada aktivitas yang terkait dengan setiap "aplikasi".</p>
<h3 id="Clearing">Menghapus back-stack</h3>
<p>Jika pengguna meninggalkan tugas dalam waktu yang lama, sistem akan menghapus tugas semua aktivitas kecuali
aktivitas akar. Bila pengguna kembali ke tugas itu lagi, hanya aktivitas akar yang akan dipulihkan.
Sistem berperilaku seperti ini, karena, setelah sekian waktu, pengguna mungkin telah mengabaikan
apa yang mereka kerjakan sebelum dan kembali ke tugas itu untuk memulai sesuatu yang baru. </p>
<p>Ada beberapa atribut aktivitas yang bisa Anda gunakan untuk memodifikasi perilaku ini: </p>
<dl>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code>
</dt>
<dd>Jika atribut ini ditetapkan ke {@code "true"} dalam aktivitas akar tugas,
perilaku default yang baru dijelaskan tidak akan terjadi.
Tugas akan mempertahankan semua aktivitas dalam back-stack bahkan setelah sekian lama.</dd>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt>
<dd>Jika atribut ini diatur ke {@code "true"} dalam aktivitas akar tugas, back-
stack akan dihapus hingga aktivitas akar bila pengguna meninggalkan tugas
dan kembali lagi. Dengan kata lain, ini adalah lawan dari
<a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
{@code alwaysRetainTaskState}</a>. Pengguna selalu kembali ke tugas dengan
status awalnya, walaupun hanya sebentar meninggalkan tugas.</dd>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code>
</dt>
<dd>Atribut ini seperti <a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a>,
namun beroperasi pada
satu aktivitas, bukan pada seluruh tugas. Hal ini juga bisa menyebabkan aktivitas
hilang, termasuk aktivitas akar. Bila ini diatur ke {@code "true"},
aktivitas akan tetap menjadi bagian dari tugas hanya untuk sesi saat ini. Jika pengguna
keluar dan kemudian kembali ke tugas tersebut, tugas tidak akan ada lagi.</dd>
</dl>
<h3 id="Starting">Memulai tugas</h3>
<p>Anda bisa mengatur aktivitas sebagai titik masuk untuk tugas dengan memberikan filter intent dengan
{@code "android.intent.action.MAIN"} sebagai tindakan yang ditetapkan dan
{@code "android.intent.category.LAUNCHER"}
sebagai kategori yang ditetapkan. Misalnya:</p>
<pre>
&lt;activity ... &gt;
&lt;intent-filter ... &gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
...
&lt;/activity&gt;
</pre>
<p>Filter intent semacam ini akan menyebabkan ikon dan label untuk
aktivitas ditampilkan dalam launcher aplikasi, yang akan memberi cara kepada pengguna untuk meluncurkan aktivitas dan
kembali ke tugas yang dibuatnya kapan saja setelah ia telah diluncurkan.
</p>
<p>Kemampuan kedua ini penting: Pengguna harus bisa meninggalkan tugas dan kemudian kembali ke tugas tersebut
nanti dengan menggunakan launcher aktivitas ini. Karena itu, kedua <a href="#LaunchModes">mode
pembuka</a> yang menandai aktivitas selalu memulai tugas, {@code "singleTask"} dan
{@code "singleInstance"}, hanya boleh digunakan bila aktivitas memiliki filter
{@link android.content.Intent#ACTION_MAIN}
dan {@link android.content.Intent#CATEGORY_LAUNCHER}. Bayangkan, misalnya, apa yang akan
terjadi jika filter tidak ada: Intent meluncurkan aktivitas{@code "singleTask"}, memulai
tugas yang baru, dan pengguna menghabiskan lebih banyak waktu mengerjakan tugas tersebut. Pengguna kemudian menekan tombol
<em>Home</em>. Tugas kini dikirim ke latar belakang dan tidak terlihat. Sekarang pengguna tidak memiliki cara untuk kembali
ke tugas tersebut, karena tidak dinyatakan dalam launcher aplikasi.</p>
<p>Untuk kasus-kasus di mana Anda tidak ingin pengguna bisa kembali ke aktivitas, atur dalam
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
pada
<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code finishOnTaskLaunch}</a>
elemen ke {@code "true"} (lihat <a href="#Clearing">Menghapus back-stack</a>).</p>
<p>Informasi lebih jauh tentang cara menyatakan dan mengelola tugas dan aktivitas dalam
layar ikhtisar tersedia dalam<a href="{@docRoot}guide/components/recents.html">
Layar Ikhtisar</a>.</p>
<!--
<h2>Beginner's Path</h2>
<p>For more information about how to use intents to
activate other application components and publish the intents to which your components
respond, continue with the <b><a
href="{@docRoot}guide/components/intents-filters.html">Intents and Intent
Filters</a></b> document.</p>
-->

View File

@@ -0,0 +1,74 @@
page.title=Pengantar Android
@jd:body
<div class="sidebox" style="width:220px"><!-- width to match col-4 below -->
<p>Untuk mempelajari cara kerja aplikasi, mulailah dengan
<a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>.</p>
<p>Untuk langsung memulai pemrograman, bacalah <a href="{@docRoot}training/basics/firstapp/index.html">Membangun Aplikasi Pertama Anda.</a></p>
</div>
<p>Android menyediakan kerangka kerja aplikasi yang kaya dan memungkinkan Anda membangun aplikasi dan permainan
inovatif untuk perangkat seluler di lingkungan bahasa pemrograman Java. Dokumen yang tercantum di navigasi
sebelah kiri menyediakan detail tentang cara membangun aplikasi menggunakan berbagai API Android.</p>
<p>Jika Anda masih baru dengan pengembangan Android, Anda perlu memahami
konsep dasar berikut mengenai kerangka kerja aplikasi Android:</p>
<div class="landing-banner">
<div class="col-6">
<h4>Aplikasi menyediakan beberapa titik masuk</h4>
<p>Aplikasi Android dibangun sebagai kombinasi beragam komponen yang bisa dipanggil
satu per satu. Misalnya, satu <em>aktivitas</em> individual menyediakan satu
layar untuk antarmuka pengguna, dan <em>layanan</em> yang secara terpisah melakukan
tugas di latar belakang.</p>
<p>Dari satu komponen Anda dapat memulai komponen lainnya menggunakan <em>intent</em>. Anda bahkan dapat memulai
satu komponen dalam aplikasi berbeda, seperti aktivitas dalam aplikasi peta untuk menampilkan alamat. Model ini
menyediakan beberapa titik masuk untuk aplikasi tunggal dan memungkinkan setiap aplikasi untuk berfungsi sebagai "default"
pengguna bagi tindakan yang dapat dipanggil aplikasi lain.</p>
<p><b>Ketahui selengkapnya:</b></p>
<ul class="nolist">
<li><a href="{@docRoot}guide/components/fundamentals.html">Dasar-Dasar Aplikasi</a>
<li><a href="{@docRoot}guide/components/intents-filters.html">Intent dan Filter Intent</a>
<li><a href="{@docRoot}guide/components/activities.html">Aktivitas</a>
</ul>
</div>
<div class="col-6">
<h4>Aplikasi beradaptasi dengan perangkat berbeda</h4>
<p>Android menyediakan kerangka kerja aplikasi adaptif yang memungkinkan Anda menyediakan sumber daya unik
bagi konfigurasi perangkat yang berbeda-beda. Misalnya, Anda bisa membuat berbagai file layout
XML untuk ukuran layar yang berbeda-beda dan sistem akan menentukan
layout yang akan diterapkan berdasarkan ukuran layar perangkat yang ada saat ini.</p>
<p>Anda dapat melakukan query ketersediaan fitur perangkat saat dijalankan (runtime) jika ada fitur aplikasi yang memerlukan
perangkat keras spesifik seperti kamera. Jika diperlukan, Anda juga bisa mendeklarasikan fitur yang dibutuhkan aplikasi
agar pasar aplikasi seperti Google Play Store tidak mengizinkan instalasi pada perangkat yang tidak
mendukung fitur itu.</p>
<p><b>Ketahui selengkapnya:</b></p>
<ul class="nolist">
<li><a href="{@docRoot}guide/practices/compatibility.html">Kompatibilitas Perangkat</a>
<li><a href="{@docRoot}guide/topics/resources/overview.html">Ikhtisar Sumber Daya</a>
<li><a href="{@docRoot}guide/topics/ui/overview.html">Ikhtisar Antarmuka Pengguna</a>
</ul>
</div>
</div><!-- end landing-banner -->

View File

@@ -0,0 +1,517 @@
page.title=Manifes Aplikasi
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#filestruct">Struktur File Manifes</a></li>
<li><a href="#filec">Konvensi File</a>
<li><a href="#filef">Fitur File</a>
<ol>
<li><a href="#ifs">Filter Intent</a></li>
<li><a href="#iconlabel">Ikon dan Label</a></li>
<li><a href="#perms">Izin</a></li>
<li><a href="#libs">Pustaka</a></li>
</ol></li>
</ol>
</div>
</div>
<p>
Setiap aplikasi harus memiliki file AndroidManifest.xml (bernama persis seperti ini) di direktori akar.
<span itemprop="description">File manifes
menyediakan informasi penting tentang aplikasi ke sistem Android,
informasi yang harus dimiliki sistem agar bisa menjalankan setiap kode
aplikasi.</span> Di antaranya, manifes melakukan hal berikut ini:
</p>
<ul>
<li>Menamai paket Java untuk aplikasi.
Nama paket berfungsi sebagai identifier unik untuk aplikasi.</li>
<li>Menjelaskan berbagai komponen aplikasi&mdash;aktivitas,
layanan, penerima siaran, dan penyedia konten
yang membentuk aplikasi. Menamai kelas yang mengimplementasikan setiap komponen dan
mempublikasikan kemampuannya (misalnya, pesan {@link android.content.Intent
Intent} mana yang bisa ditanganinya). Deklarasi ini memberi tahu sistem Android mengenai
komponennya dan dalam kondisi apa bisa diluncurkan.</li>
<li>Menentukan proses yang akan menjadi host komponen aplikasi.</li>
<li>Mendeklarasikan izin aplikasi mana yang harus dimiliki untuk
mengakses bagian yang dilindungi pada API dan berinteraksi dengan aplikasi lain.</li>
<li>Juga mendeklarasikan izin lain yang harus dimiliki untuk
untuk berinteraksi dengan komponen aplikasi.</li>
<li>Mencantumkan daftar kelas {@link android.app.Instrumentation} yang memberikan
profil dan informasi lain saat aplikasi berjalan. Deklarasi ini
hanya ada di manifes saat aplikasi dibuat dan diuji;
deklarasi dihapus sebelum aplikasi dipublikasikan.</li>
<li>Mendeklarasikan tingkat minimum API Android yang diperlukan
aplikasi.</li>
<li>Mencantumkan daftar pustaka yang harus ditautkan aplikasi.</li>
</ul>
<h2 id="filestruct">Struktur File Manifes</h2>
<p>
Diagram di bawah ini menampilkan struktur umum file manifes dan setiap
elemen yang bisa ditampungnya. Setiap elemen, bersama
atributnya, didokumentasikan secara lengkap dalam file terpisah. Untuk melihat
informasi terperinci tentang setiap elemen, klik nama elemen dalam diagram,
dalam daftar abjad elemen yang mengikuti diagram, atau penyebutan nama
elemen lainnya.
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration /&gt;</a> <!-- ##api level 3## -->
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature /&gt;</a> <!-- ##api level 4## -->
<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens /&gt;</a> <!-- ##api level 4## -->
<a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">&lt;compatible-screens /&gt;</a> <!-- ##api level 9## -->
<a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture /&gt;</a> <!-- ##api level 11## -->
<a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;/activity&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;/activity-alias&gt;</a>
<a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data/&gt;</a>
<a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;/service&gt;</a>
<a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a>
<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a> . . . <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;/intent-filter&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;/receiver&gt;</a>
<a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a>
<a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/path-permission-element.html">&lt;path-permission /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;/provider&gt;</a>
<a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library /&gt;</a>
<a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;/application&gt;</a>
<a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;/manifest&gt;</a>
</pre>
<p>
Semua elemen yang bisa muncul dalam file manifes tercantum di bawah ini
dalam urutan abjad. Ini adalah satu-satunya elemen legal; Anda tidak bisa
menambahkan elemen atau atribut sendiri.
</p>
<p style="margin-left: 2em">
<code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code> <!-- ##api level 3## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code>
</p>
<h2 id="filec">Konvensi File</h2>
<p>
Sebagian konvensi dan aturan berlaku secara umum untuk semua elemen
dan atribut di manifes:
</p>
<dl>
<dt><b>Elemen</b></dt>
<dd>Hanya elemen
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> dan
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
yang diwajibkan, masing-masing harus ada dan hanya boleh terjadi sekali.
Umumnya elemen lain bisa terjadi berkali-kali atau sama sekali tidak terjadi &mdash; meskipun
setidaknya sebagian dari elemen itu harus ada untuk agar manifes mencapai sesuatu yang
berarti.
<p>
Jika elemen tidak berisi apa pun, berarti elemen itu berisi elemen lain.
Semua nilai diatur melalui atribut, bukan sebagai data karakter dalam elemen.
</p>
<p>
Elemen yang sama tingkatan umumnya tidak diurutkan. Misalnya, elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>, dan
<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
bisa dicampur dalam urutan apa pun. (Elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
merupakan eksepsi untuk aturan ini: Elemen ini harus mengikuti
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
ini aliasnya.)
</p></dd>
<dt><b>Atribut</b></dt>
<dd>Secara formal, semua atribut opsional. Akan tetapi, ada sebagian
yang harus ditetapkan agar elemen bisa mencapai tujuannya. Gunakan
dokumentasi sebagai panduan. Bagi atribut yang benar-benar opsional, ini menyebutkan
nilai default atau menyatakan apa yang terjadi jika tidak ada spesifikasi.
<p>Selain untuk beberapa atribut elemen akar
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>,
semua nama atribut dimulai dengan awalan {@code android:} &mdash;
misalnya, {@code android:alwaysRetainTaskState}. Karena awalan ini universal, dokumentasi umumnya meniadakannya saat mengacu atribut
dengan nama.
</p></dd>
<dt><b>Mendeklarasikan nama kelas</b></dt>
<dd>Banyak elemen berhubungan dengan objek Java, termasuk elemen
aplikasi itu sendiri (elemen
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
) dan aktivitas komponen &mdash; utamanya
(<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>),
layanan
(<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>),
penerima siaran
(<code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>),
dan penyedia konten
(<code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>).
<p>
Jika mendefinisikan subkelas, seperti yang selalu Anda definisikan untuk kelas komponen
({@link android.app.Activity}, {@link android.app.Service},
{@link android.content.BroadcastReceiver}, dan {@link android.content.ContentProvider}),
subkelas dideklarasikan melalui atribut {@code name}. Nama harus menyertakan tujuan
paket lengkap.
Misalnya, subkelas {@link android.app.Service} mungkin dideklarasikan sebagai berikut:
</p>
<pre>&lt;manifest . . . &gt;
&lt;application . . . &gt;
&lt;service android:name="com.example.project.SecretService" . . . &gt;
. . .
&lt;/service&gt;
. . .
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>
Akan tetapi, sebagai shorthand, jika karakter pertama string adalah titik,
string akan ditambahkan ke nama paket aplikasi (seperti yang ditetapkan dalam elemen
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
melalui atribut
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html#package">package</a></code>
). Penetapan berikut sama dengan di atas:
</p>
<pre>&lt;manifest package="com.example.project" . . . &gt;
&lt;application . . . &gt;
&lt;service android:name=".SecretService" . . . &gt;
. . .
&lt;/service&gt;
. . .
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>
Saat memulai komponen, Android akan membuat instance subkelas yang diberi nama.
Jika subkelas tidak ditetapkan, maka akak dibuat instance kelas dasar.
</p></dd>
<dt><b>Banyak nilai</b></dt>
<dd>Jika lebih dari satu nilai yang dapat ditetapkan, elemen ini hampir selalu
diulangi, bukan menampilkan daftar banyak nilai dalam satu elemen.
Misalnya, filter intent dapat mencantumkan beberapa tindakan:
<pre>&lt;intent-filter . . . &gt;
&lt;action android:name="android.intent.action.EDIT" /&gt;
&lt;action android:name="android.intent.action.INSERT" /&gt;
&lt;action android:name="android.intent.action.DELETE" /&gt;
. . .
&lt;/intent-filter&gt;</pre></dd>
<dt><b>Nilai sumber daya</b></dt>
<dd>Beberapa atribut memiliki nilai yang bisa ditampilkan kepada pengguna &mdash; misalnya
, label dan ikon aktivitas. Nilai atribut ini
harus dilokalkan dan karenanya ditetapkan dari sumber daya atau tema. Nilai sumber
daya dinyatakan dalam format berikut,</p>
<p style="margin-left: 2em">{@code @[<i>package</i>:]<i>type</i>:<i>name</i>}</p>
<p>
dalam hal ini nama <i>package</i> boleh dihilangkan jika sumber daya ada dalam paket yang sama dengan
dengan aplikasi, <i>type</i> adalah tipe sumber daya &mdash; seperti "string" atau
"drawable" &mdash; dan <i>name</i> adalah nama yang mengidentifikasi sumber daya tertentu.
Misalnya:
</p>
<pre>&lt;activity android:icon="@drawable/smallPic" . . . &gt</pre>
<p>
Nilai tema diekspresikan dengan cara yang sama, namun dengan awal '{@code ?}'
dan bukan '{@code @}':
</p>
<p style="margin-left: 2em">{@code ?[<i>package</i>:]<i>type</i>:<i>name</i>}
</p></dd>
<dt><b>Nilai-nilai string</b></dt>
<dd>Bila nilai atribut adalah string, dua garis miring kiri ('{@code \\}')
harus digunakan untuk meninggalkan karakter &mdash; misalnya, '{@code \\n}' untuk
baris baru atau '{@code \\uxxxx}' untuk karakter Unicode.</dd>
</dl>
<h2 id="filef">Fitur File</h2>
<p>
Bagian berikut menjelaskan cara menerapkan sebagian fitur Android
dalam file manifest.
</p>
<h3 id="ifs">Filter Intent</h3>
<p>
Komponen inti dari aplikasi (aktivitasnya, layanannya, dan penerima
siaran) diaktifkan oleh <i>intent</i>. Intent adalah
sekumpulan informasi (objek {@link android.content.Intent}) yang menjelaskan
tindakan yang diinginkan &mdash; termasuk data yang akan ditindaklanjuti, kategori
komponen yang harus melakukan tindakan, dan petunjuk terkait lainnya.
Android mencari komponen yang sesuai untuk merespons intent, meluncurkan
instance komponen baru jika diperlukan, dan meneruskannya ke
objek Intent.
</p>
<p>
Komponen mengiklankan kemampuannya &mdash; jenis intent yang bisa diresponsnya
&mdash; melalui <i>filter intent</i>. Karena sistem Android
harus mempelajari intent yang dapat ditangani komponen sebelum meluncurkan komponen,
filter intent ditetapkan dalam manifes sebagai elemen
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
. Sebuah komponen dapat memiliki filter dalam jumlah berapa saja, masing-masing menjelaskan
kemampuan yang berbeda.
</p>
<p>
Intent yang secara eksplisit menamai komponen target akan mengaktifkan komponen itu;
filter tidak berperan. Namun intent yang tidak menetapkan target
dengan nama dapat mengaktifkan komponen hanya jika dapat melewati salah satu filter
komponen.
</p>
<p>
Untuk informasi tentang cara objek Intent diuji terhadap filter intent,
lihat dokumen terpisah,
<a href="{@docRoot}guide/components/intents-filters.html">Intent
dan Filter Intent</a>.
</p>
<h3 id="iconlabel">Ikon dan Label</h3>
<p>
Sejumlah elemen memiliki atribut {@code icon} dan {@code label} untuk
ikon kecil dan label teks yang bisa ditampilkan kepada pengguna. Sebagian ada juga yang memiliki atribut
{@code description}untuk teks penjelasan yang lebih panjang yang juga bisa
ditampilkan pada layar. Misalnya, elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
memiliki ketiga atribut ini, jadi saat pengguna ditanya apakah akan
memberi izin bagi aplikasi yang memintanya, ikon yang mewakili
izin, nama izin, dan keterangan yang
mengikutinya bisa ditampilkan kepada pengguna.
</p>
<p>
Dalam setiap kasus, ikon dan label yang ditetapkan dalam elemen yang memuatnya menjadi
{@code icon} default dan pengaturan {@code label} untuk semua subelemen kontainer ini.
Karena itu, ikon dan label yang ditetapkan dalam elemen
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
adalah ikon dan label default untuk setiap komponen aplikasi.
Demikian pula, ikon dan label yang ditetapkan untuk komponen &mdash; misalnya, elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
&mdash; adalah pengaturan default untuk setiap elemen komponen
<code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
. Jika elemen
<code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
menetapkan label, namun suatu aktivitas dan filter intent-nya tidak menetapkan label,
maka label aplikasi akan dianggap sama-sama sebagai label aktvitas dan
filter intent.
</p>
<p>
Ikon dan label yang ditetapkan untuk filter intent digunakan untuk mewakili komponen
kapan saja komponen ditampilkan kepada pengguna saat memenuhi fungsi yang
diiklankan oleh filter. Misalnya, filter dengan pengaturan
"{@code android.intent.action.MAIN}" dan
"{@code android.intent.category.LAUNCHER}" mengiklankan aktivitas
sebagai aktivitas yang memulai aplikasi&mdash;, yaitu
sebagai salah satu aktivitas yang harus ditampilkan dalam launcher aplikasi. Ikon dan label yang
diatur dalam filter karenanya adalah ikon dan label yang ditampilkan dalam launcher.
</p>
<h3 id="perms">Izin</h3>
<p>
Sebuah <i>izin</i> adalah pembatasan yang membatasi akses ke bagian
kode atau ke data pada perangkat. Pembatasan diberlakukan untuk melindungi data dan kode
penting yang bisa disalahgunakan untuk mengganggu atau merusak pengalaman pengguna.
</p>
<p>
Setiap izin diidentifikasi melalui label yang unik. Sering kali, label menunjukkan
tindakan yang dibatasi. Misalnya, berikut ini adalah beberapa izin yang didefinisikan
oleh Android:
</p>
<p style="margin-left: 2em">{@code android.permission.CALL_EMERGENCY_NUMBERS}
<br/>{@code android.permission.READ_OWNER_DATA}
<br/>{@code android.permission.SET_WALLPAPER}
<br/>{@code android.permission.DEVICE_POWER}</p>
<p>
Sebuah fitur bisa dilindungi paling banyak oleh satu izin.
</p>
<p>
Jika aplikasi memerlukan akses ke fitur yang dilindungi oleh izin,
aplikasi harus mendeklarasikan bahwa aplikasi memerlukan izin itu dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
dalam manifes. Kemudian, bila aplikasi telah diinstal pada
perangkat, installer akan menentukan apakah izin yang diminta akan diberikan atau tidak
dengan memeriksa otoritas yang menandatangani
sertifikat aplikasi dan, dalam beberapa kasus, bertanya pada pengguna.
Jika izin diberikan, aplikasi tersebut bisa menggunakan
fitur yang dilindungi. Jika tidak, upaya aplikasi untuk mengakses fitur tersebut akan gagal
tanpa ada pemberitahuan apa pun kepada pengguna.
</p>
<p>
Aplikasi juga bisa melindungi komponennya sendiri (aktivitas, layanan,
penerima siaran, dan penyedia konten) dengan izin. Aplikasi bisa menerapkan
izin mana pun yang didefinisikan oleh Android (tercantum dalam
{@link android.Manifest.permission android.Manifest.permission}) atau dideklarasikan
oleh aplikasi lain. Atau aplikasi bisa mendefinisikannya sendiri. Izin baru dideklarasikan
dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
. Misalnya, aktivitas dapat dilindungi sebagai berikut:
</p>
<pre>
&lt;manifest . . . &gt;
&lt;permission android:name="com.example.project.DEBIT_ACCT" . . . /&gt;
&lt;uses-permission android:name="com.example.project.DEBIT_ACCT" /&gt;
. . .
&lt;application . . .&gt;
&lt;activity android:name="com.example.project.FreneticActivity"
android:permission="com.example.project.DEBIT_ACCT"
. . . &gt;
. . .
&lt;/activity&gt;
&lt;/application&gt;
&lt;/manifest&gt;
</pre>
<p>
Perhatikan, dalam contoh ini izin {@code DEBIT_ACCT} tidak hanya
dideklarasikan dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
, penggunaannya juga diminta dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
. Penggunaannya harus diminta agar komponen
aplikasi lainnya bisa menjalankan aktivitas yang dilindungi, meskipun perlindungan itu
diberlakukan oleh aplikasi itu sendiri.
</p>
<p>
Dalam contoh yang sama, jika atribut {@code permission} ditetapkan
untuk izin yang dideklarasikan di tempat lain
lain (seperti {@code android.permission.CALL_EMERGENCY_NUMBERS}, maka atribut
tidak perlu mendeklarasikannya lagi dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
. Akan tetapi, penggunaannya masih perlu dengan
<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>.
</p>
<p>
Elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
mendeklarasikan namespace untuk grup izin yang akan didefinisikan dalam
kode. Dan
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
mendefinisikan label untuk seperangkat izin (yang sama-sama dideklarasikan dalam manifes dengan elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
dan yang dideklarasikan di tempat lain). Ini hanya memengaruhi cara izin
dikelompokkan saat ditampilkan kepada pengguna. Elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
tidak menetapkan izin mana dimiliki grup;
elemen hanya memberi nama grup. Izin ditempatkan dalam grup
dengan memberikan nama grup ke elemen
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
melalui atribut
<code><a href="{@docRoot}guide/topics/manifest/permission-element.html#pgroup">permissionGroup</a></code>
.
</p>
<h3 id="libs">Pustaka</h3>
<p>
Setiap aplikasi ditautkan dengan pustaka default Android, yang
menyertakan paket dasar untuk membangun aplikasi (dengan kelas umum
seperti Activity, Service, Intent, View, Button, Application, ContentProvider,
dan sebagainya).
</p>
<p>
Akan tetapi, sebagian paket berada dalam pustakanya sendiri. Jika aplikasi Anda
menggunakan kode salah satu paket ini, aplikasi secara eksplisit meminta untuk ditautkan dengan
paket tersebut. Manifes harus berisi elemen
<code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code> yang
terpisah untuk menamai setiap pustaka. (Nama pustaka bisa ditemukan
dalam dokumentasi paket.)
</p>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,108 @@
page.title=Penyedia konten
@jd:body
<div id="qv-wrapper">
<div id="qv">
<!-- In this document -->
<h2>Topik</h2>
<ol>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Dasar-Dasar Penyedia Konten</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
Membuat Penyedia Konten</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/calendar-provider.html">Penyedia Kalender</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/contacts-provider.html">Penyedia Kontak</a>
</li>
</ol>
<!-- Related Samples -->
<h2>Contoh-Contoh Terkait</h2>
<ol>
<li>
<a href="{@docRoot}resources/samples/ContactManager/index.html">
Aplikasi Contact Manager</a>
</li>
<li>
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html">
"Kursor (Orang)"
</a>
</li>
<li>
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html">
"Kursor (Telepon)"</a>
</li>
<li>
<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">
Contoh Adaptor Sinkronisasi</a>
</li>
</ol>
</div>
</div>
<p>
Penyedia konten mengelola akses ke set data terstruktur. Penyedia ini membungkus
data, dan menyediakan mekanisme untuk mendefinisikan keamanan data. Penyedia konten adalah antarmuka
standar yang menghubungkan data dalam satu proses dengan kode yang berjalan dalam proses lain.
</p>
<p>
Bila Anda ingin mengakses data di penyedia konten, Anda menggunakan
{@link android.content.ContentResolver} objek dalam
{@link android.content.Context} aplikasi untuk berkomunikasi dengan penyedia sebagai klien.
Objek {@link android.content.ContentResolver} berkomunikasi dengan objek penyedia, yakni
instance kelas yang mengimplementasikan {@link android.content.ContentProvider}. Objek penyedia
menerima permintaan data dari klien, melakukan tindakan yang diminta, dan
mengembalikan hasilnya.
</p>
<p>
Anda tidak perlu mengembangkan penyedia sendiri jika tidak bermaksud untuk berbagi data dengan
aplikasi lain. Akan tetapi, Anda memerlukan penyedia buatan sendiri untuk menyediakan saran pencarian custom
dalam aplikasi Anda sendiri. Anda juga memerlukan penyedia sendiri jika ingin menyalin dan
menempelkan data atau file yang kompleks dari aplikasi Anda ke aplikasi lain.
</p>
<p>
Android sendiri berisi penyedia konten yang mengelola data seperti informasi audio, video, gambar, dan
kontak pribadi. Anda bisa melihat sebagian informasi ini tercantum dalam dokumentasi
acuan untuk paket
<code><a href="{@docRoot}reference/android/provider/package-summary.html">android.provider</a>
</code>. Dengan beberapa batasan, semua penyedia ini bisa diakses oleh aplikasi Android
apa saja.
</p><p>
Topik-topik berikut menjelaskan penyedia konten secara lebih detail:
</p>
<dl>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Dasar-Dasar Penyedia Konten</a></strong>
</dt>
<dd>
Cara mengakses data di penyedia konten bila data disusun dalam tabel.
</dd>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/content-provider-creating.html">
Membuat Penyedia Konten</a></strong>
</dt>
<dd>
Cara membuat penyedia konten sendiri.
</dd>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/calendar-provider.html">
Penyedia Kalender</a></strong>
</dt>
<dd>
Cara mengakses Penyedia Kalender yang merupakan bagian dari platform Android.
</dd>
<dt>
<strong><a href="{@docRoot}guide/topics/providers/contacts-provider.html">
Penyedia Kontak</a></strong>
</dt>
<dd>
Cara mengakses Penyedia Kontak yang merupakan bagian dari platform Android.
</dd>
</dl>

View File

@@ -0,0 +1,916 @@
page.title=Storage Access Framework
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini
<a href="#" onclick="hideNestedItems('#toc44',this);return false;" class="header-toggle">
<span class="more">tampilkan maksimal</span>
<span class="less" style="display:none">tampilkan minimal</span></a></h2>
<ol id="toc44" class="hide-nested">
<li>
<a href="#overview">Ikhtisar</a>
</li>
<li>
<a href="#flow">Arus Kontrol</a>
</li>
<li>
<a href="#client">Menulis Aplikasi Klien</a>
<ol>
<li><a href="#search">Mencari dokumen</a></li>
<li><a href="#process">Memproses hasil</a></li>
<li><a href="#metadata">Memeriksa metadata dokumen</a></li>
<li><a href="#open">Membuka dokumen</a></li>
<li><a href="#create">Membuat dokumen baru</a></li>
<li><a href="#delete">Menghapus dokumen</a></li>
<li><a href="#edit">Mengedit dokumen</a></li>
<li><a href="#permissions">Mempertahankan izin</a></li>
</ol>
</li>
<li><a href="#custom">Menulis Penyedia Dokumen Custom</a>
<ol>
<li><a href="#manifest">Manifes</a></li>
<li><a href="#contract">Kontrak</a></li>
<li><a href="#subclass">Subkelas DocumentsProvider</a></li>
<li><a href="#security">Keamanan</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.provider.DocumentsProvider}</li>
<li>{@link android.provider.DocumentsContract}</li>
</ol>
<h2>Video</h2>
<ol>
<li><a href="http://www.youtube.com/watch?v=zxHVeXbK1P4">
DevBytes: Android 4.4 Storage Access Framework: Penyedia</a></li>
<li><a href="http://www.youtube.com/watch?v=UFj9AEz0DHQ">
DevBytes: Android 4.4 Storage Access Framework: Klien</a></li>
</ol>
<h2>Contoh Kode</h2>
<ol>
<li><a href="{@docRoot}samples/StorageProvider/index.html">
Penyedia Penyimpanan</a></li>
<li><a href="{@docRoot}samples/StorageClient/index.html">
Klien Penyimpanan</a></li>
</ol>
<h2>Lihat Juga</h2>
<ol>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html">
Dasar-Dasar Penyedia Konten
</a>
</li>
</ol>
</div>
</div>
<p>Android 4.4 (API level 19) memperkenalkan Storage Access Framework (SAF, Kerangka Kerja Akses Penyimpanan). SAF
memudahkan pengguna menyusuri dan membuka dokumen, gambar, dan file lainnya
di semua penyedia penyimpanan dokumen pilihannya. UI standar yang mudah digunakan
memungkinkan pengguna menyusuri file dan mengakses yang terbaru dengan cara konsisten di antara berbagai aplikasi dan penyedia.</p>
<p>Layanan penyimpanan cloud atau lokal bisa dilibatkan dalam ekosistem ini dengan mengimplementasikan sebuah
{@link android.provider.DocumentsProvider} yang membungkus layanannya. Aplikasi klien
yang memerlukan akses ke dokumen sebuah penyedia bisa berintegrasi dengan SAF cukup dengan beberapa
baris kode.</p>
<p>SAF terdiri dari berikut ini:</p>
<ul>
<li><strong>Penyedia dokumen</strong>&mdash;Penyedia konten yang memungkinkan
layanan penyimpanan (seperti Google Drive) untuk menampilkan file yang dikelolanya. Penyedia dokumen
diimplementasikan sebagai subkelas dari kelas {@link android.provider.DocumentsProvider}.
Skema penyedia dokumen berdasarkan hierarki file biasa,
walaupun cara penyedia dokumen Anda secara fisik menyimpan data adalah terserah Anda.
Platform Android terdiri dari beberapa penyedia dokumen bawaan, seperti
Downloads, Images, dan Videos.</li>
<li><strong>Aplikasi klien</strong>&mdash;Aplikasi custom yang memanggil intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan/atau
{@link android.content.Intent#ACTION_CREATE_DOCUMENT} dan menerima
file yang dihasilkan penyedia dokumen.</li>
<li><strong>Picker</strong>&mdash;UI sistem yang memungkinkan pengguna mengakses dokumen dari semua
penyedia dokumen yang memenuhi kriteria pencarian aplikasi klien.</li>
</ul>
<p>Beberapa fitur yang disediakan oleh SAF adalah sebagai berikut:</p>
<ul>
<li>Memungkinkan pengguna menyusuri konten dari semua penyedia dokumen, bukan hanya satu aplikasi.</li>
<li>Memungkinkan aplikasi Anda memiliki akses jangka panjang dan tetap ke
dokumen yang dimiliki oleh penyedia dokumen. Melalui akses ini pengguna bisa menambah, mengedit,
menyimpan, dan menghapus file pada penyedia.</li>
<li>Mendukung banyak akun pengguna dan akar jangka pendek seperti penyedia penyimpanan
USB, yang hanya muncul jika drive itu dipasang. </li>
</ul>
<h2 id ="overview">Ikhtisar</h2>
<p>SAF berpusat di seputar penyedia konten yang merupakan
subkelas dari kelas {@link android.provider.DocumentsProvider}. Dalam <em>penyedia dokumen</em>, data
distrukturkan sebagai hierarki file biasa:</p>
<p><img src="{@docRoot}images/providers/storage_datamodel.png" alt="data model" /></p>
<p class="img-caption"><strong>Gambar 1.</strong> Model data penyedia dokumen. Root menunjuk ke satu Document,
yang nanti memulai pemekaran seluruh pohon.</p>
<p>Perhatikan yang berikut ini:</p>
<ul>
<li>Setiap penyedia dokumen melaporkan satu atau beberapa
"akar" yang merupakan titik awal penyusuran pohon dokumen.
Masing-masing akar memiliki sebuah {@link android.provider.DocumentsContract.Root#COLUMN_ROOT_ID} yang unik,
dan menunjuk ke satu dokumen (satu direktori)
yang mewakili konten di bawah akar itu.
Akar sengaja dibuat dinamis untuk mendukung kasus penggunaan seperti multiakun,
perangkat penyimpanan USB jangka pendek, atau masuk/keluar pengguna.</li>
<li>Di bawah tiap akar terdapat satu dokumen. Dokumen itu menunjuk ke dokumen-dokumen 1-ke-<em>N</em>,
yang nanti masing-masing bisa menunjuk ke dokumen 1-ke-<em>N</em>. </li>
<li>Tiap backend penyimpanan memunculkan
masing-masing file dan direktori dengan mengacunya lewat sebuah
{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang unik.
ID dokumen harus unik dan tidak berubah setelah dibuat, karena ID ini digunakan untuk
URI persisten yang diberikan pada saat reboot perangkat.</li>
<li>Dokumen bisa berupa file yang bisa dibuka (dengan tipe MIME tertentu), atau
direktori yang berisi dokumen tambahan (dengan tipe MIME
{@link android.provider.DocumentsContract.Document#MIME_TYPE_DIR}).</li>
<li>Tiap dokumen bisa mempunyai kemampuan berbeda, sebagaimana yang dijelaskan oleh
{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS COLUMN_FLAGS}.
Misalnya, {@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE},
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE}, dan
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_THUMBNAIL}.
{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} yang sama bisa
dimasukkan dalam beberapa direktori.</li>
</ul>
<h2 id="flow">Arus Kontrol</h2>
<p>Seperti dinyatakan di atas, model data penyedia dokumen dibuat berdasarkan hierarki file
biasa. Akan tetapi, Anda bisa menyimpan secara fisik data dengan cara apa pun yang disukai,
selama data bisa diakses melalui API {@link android.provider.DocumentsProvider}. Misalnya, Anda
bisa menggunakan penyimpanan cloud berbasis tag untuk data Anda.</p>
<p>Gambar 2 menampilkan contoh cara aplikasi foto bisa menggunakan SAF
untuk mengakses data tersimpan:</p>
<p><img src="{@docRoot}images/providers/storage_dataflow.png" alt="app" /></p>
<p class="img-caption"><strong>Gambar 2.</strong> Arus Storage Access Framework</p>
<p>Perhatikan yang berikut ini:</p>
<ul>
<li>Di SAF, penyedia dan klien tidak berinteraksi
secara langsung. Klien meminta izin untuk berinteraksi
dengan file (yakni, membaca, mengedit, membuat, atau menghapus file).</li>
<li>Interaksi dimulai bila sebuah aplikasi (dalam contoh ini adalah aplikasi foto) mengeluarkan intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} atau {@link android.content.Intent#ACTION_CREATE_DOCUMENT}. Intent bisa berisi filter
untuk mempersempit kriteria&mdash;misalnya, "beri saya semua file yang bisa dibuka
yang memiliki tipe MIME 'gambar'".</li>
<li>Setelah intent dibuat, picker sistem akan pergi ke setiap penyedia yang terdaftar
dan menunjukkan kepada pengguna akar konten yang cocok.</li>
<li>Picker memberi pengguna antarmuka standar untuk mengakses dokumen,
walaupun penyedia dokumen dasar bisa sangat berbeda. Misalnya, gambar 2
menunjukkan penyedia Google Drive, penyedia USB, dan penyedia cloud.</li>
</ul>
<p>Gambar 3 menunjukkan picker yang di digunakan pengguna mencari gambar telah memilih
akun Google Drive:</p>
<p><img src="{@docRoot}images/providers/storage_picker.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
<p class="img-caption"><strong>Gambar 3.</strong> Picker</p>
<p>Bila pengguna memilih Google Drive, gambar-gambar akan ditampilkan, seperti yang ditampilkan dalam
gambar 4. Dari titik itu, pengguna bisa berinteraksi dengan gambar dengan cara apa pun
yang didukung oleh penyedia dan aplikasi klien.
<p><img src="{@docRoot}images/providers/storage_photos.png" width="340" alt="picker" style="border:2px solid #ddd" /></p>
<p class="img-caption"><strong>Gambar 4.</strong> Gambar</p>
<h2 id="client">Menulis Aplikasi Klien</h2>
<p>Pada Android 4.3 dan yang lebih rendah, jika Anda ingin aplikasi mengambil file dari
aplikasi lain, aplikasi Anda harus memanggil intent seperti {@link android.content.Intent#ACTION_PICK}
atau {@link android.content.Intent#ACTION_GET_CONTENT}. Pengguna nanti harus memilih
satu aplikasi yang akan digunakan untuk mengambil file dan aplikasi yang dipilih harus menyediakan antarmuka pengguna
bagi untuk menyusuri dan mengambil dari file yang tersedia. </p>
<p>Pada Android 4.4 dan yang lebih tinggi, Anda mempunyai opsi tambahan dalam menggunakan intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT},
yang menampilkan UI picker yang dikontrol oleh sistem yang memungkinkan pengguna
menyusuri semua file yang disediakan aplikasi lain. Dari satu UI ini, pengguna
bisa mengambil file dari aplikasi apa saja yang didukung.</p>
<p>{@link android.content.Intent#ACTION_OPEN_DOCUMENT}
tidak dimaksudkan untuk menjadi pengganti {@link android.content.Intent#ACTION_GET_CONTENT}.
Yang harus Anda gunakan bergantung pada kebutuhan aplikasi:</p>
<ul>
<li>Gunakan {@link android.content.Intent#ACTION_GET_CONTENT} jika Anda ingin aplikasi
cuma membaca/mengimpor data. Dengan pendekatan ini, aplikasi akan mengimpor salinan data,
misalnya file gambar.</li>
<li>Gunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT} jika Anda ingin aplikasi
memiliki akses jangka panjang dan jangka pendek ke dokumen yang dimiliki oleh penyedia
dokumen. Contohnya adalah aplikasi pengeditan foto yang memungkinkan pengguna mengedit
gambar yang tersimpan dalam penyedia dokumen. </li>
</ul>
<p>Bagian ini menjelaskan cara menulis aplikasi klien berdasarkan
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan
intent {@link android.content.Intent#ACTION_CREATE_DOCUMENT}.</p>
<h3 id="search">Mencari dokumen</h3>
<p>
Cuplikan berikut menggunakan {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
untuk mencari penyedia dokumen yang
berisi file gambar:</p>
<pre>private static final int READ_REQUEST_CODE = 42;
...
/**
* Fires an intent to spin up the &quot;file chooser&quot; UI and select an image.
*/
public void performFileSearch() {
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's file
// browser.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// Filter to only show results that can be &quot;opened&quot;, such as a
// file (as opposed to a list of contacts or timezones)
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only images, using the image MIME data type.
// If one wanted to search for ogg vorbis files, the type would be &quot;audio/ogg&quot;.
// To search for all documents available via installed storage providers,
// it would be &quot;*/*&quot;.
intent.setType(&quot;image/*&quot;);
startActivityForResult(intent, READ_REQUEST_CODE);
}</pre>
<p>Perhatikan yang berikut ini:</p>
<ul>
<li>Saat aplikasi mengeluarkan intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT}
, aplikasi akan menjalankan picker yang menampilkan semua penyedia dokumen yang cocok.</li>
<li>Menambahkan kategori {@link android.content.Intent#CATEGORY_OPENABLE} ke
intent akan menyaring hasil agar hanya menampilkan dokumen yang bisa dibuka, seperti file gambar.</li>
<li>Pernyataan {@code intent.setType("image/*")} menyaring lebih jauh agar hanya
menampilkan dokumen yang memiliki tipe data MIME gambar.</li>
</ul>
<h3 id="results">Memproses Hasil</h3>
<p>Setelah pengguna memilih dokumen di picker,
{@link android.app.Activity#onActivityResult onActivityResult()} akan dipanggil.
URI yang menunjuk ke dokumen yang dipilih dimasukkan dalam parameter {@code resultData}
. Ekstrak URI dengan {@link android.content.Intent#getData getData()}.
Setelah mendapatkannya, Anda bisa menggunakannya untuk mengambil dokumen yang diinginkan pengguna. Misalnya
:</p>
<pre>&#64;Override
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
// The ACTION_OPEN_DOCUMENT intent was sent with the request code
// READ_REQUEST_CODE. If the request code seen here doesn't match, it's the
// response to some other intent, and the code below shouldn't run at all.
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
// The document selected by the user won't be returned in the intent.
// Instead, a URI to that document will be contained in the return intent
// provided to this method as a parameter.
// Pull that URI using resultData.getData().
Uri uri = null;
if (resultData != null) {
uri = resultData.getData();
Log.i(TAG, "Uri: " + uri.toString());
showImage(uri);
}
}
}
</pre>
<h3 id="metadata">Memeriksa metadata dokumen</h3>
<p>Setelah Anda memiliki URI untuk dokumen, Anda akan mendapatkan akses ke metadatanya. Cuplikan
ini memegang metadata sebuah dokumen yang disebutkan oleh URI, dan mencatatnya:</p>
<pre>public void dumpImageMetaData(Uri uri) {
// The query, since it only applies to a single document, will only return
// one row. There's no need to filter, sort, or select fields, since we want
// all fields for one document.
Cursor cursor = getActivity().getContentResolver()
.query(uri, null, null, null, null, null);
try {
// moveToFirst() returns false if the cursor has 0 rows. Very handy for
// &quot;if there's anything to look at, look at it&quot; conditionals.
if (cursor != null &amp;&amp; cursor.moveToFirst()) {
// Note it's called &quot;Display Name&quot;. This is
// provider-specific, and might not necessarily be the file name.
String displayName = cursor.getString(
cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
Log.i(TAG, &quot;Display Name: &quot; + displayName);
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
// If the size is unknown, the value stored is null. But since an
// int can't be null in Java, the behavior is implementation-specific,
// which is just a fancy term for &quot;unpredictable&quot;. So as
// a rule, check if it's null before assigning to an int. This will
// happen often: The storage API allows for remote files, whose
// size might not be locally known.
String size = null;
if (!cursor.isNull(sizeIndex)) {
// Technically the column stores an int, but cursor.getString()
// will do the conversion automatically.
size = cursor.getString(sizeIndex);
} else {
size = &quot;Unknown&quot;;
}
Log.i(TAG, &quot;Size: &quot; + size);
}
} finally {
cursor.close();
}
}
</pre>
<h3 id="open-client">Membuka dokumen</h3>
<p>Setelah mendapatkan URI dokumen, Anda bisa membuka dokumen atau melakukan apa saja
yang diinginkan padanya.</p>
<h4>Bitmap</h4>
<p>Berikut ini adalah contoh cara membuka {@link android.graphics.Bitmap}:</p>
<pre>private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
</pre>
<p>Perhatikan bahwa Anda tidak boleh melakukan operasi ini pada thread UI. Lakukan hal ini di latar belakang
, dengan menggunakan {@link android.os.AsyncTask}. Setelah membuka bitmap, Anda
bisa menampilkannya dalam {@link android.widget.ImageView}.
</p>
<h4>Mendapatkan InputStream</h4>
<p>Berikut ini adalah contoh cara mendapatkan {@link java.io.InputStream} dari URI. Dalam cuplikan ini
, baris-baris file dibaca ke dalam sebuah string:</p>
<pre>private String readTextFromUri(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(
inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
fileInputStream.close();
parcelFileDescriptor.close();
return stringBuilder.toString();
}
</pre>
<h3 id="create">Membuat dokumen baru</h3>
<p>Aplikasi Anda bisa membuat dokumen baru dalam penyedia dokumen dengan menggunakan intent
{@link android.content.Intent#ACTION_CREATE_DOCUMENT}
. Untuk membuat file, Anda memberikan satu tipe MIME dan satu nama file pada intent, dan
menjalankannya dengan kode permintaan yang unik. Selebihnya akan diurus untuk Anda:</p>
<pre>
// Here are some examples of how you might call this method.
// The first parameter is the MIME type, and the second parameter is the name
// of the file you are creating:
//
// createFile("text/plain", "foobar.txt");
// createFile("image/png", "mypicture.png");
// Unique request code.
private static final int WRITE_REQUEST_CODE = 43;
...
private void createFile(String mimeType, String fileName) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
// Filter to only show results that can be &quot;opened&quot;, such as
// a file (as opposed to a list of contacts or timezones).
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Create a file with the requested MIME type.
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(intent, WRITE_REQUEST_CODE);
}
</pre>
<p>Setelah membuat dokumen baru, Anda bisa mendapatkan URI-nya dalam
{@link android.app.Activity#onActivityResult onActivityResult()}, sehingga Anda
bisa terus menulis ke dokumen itu.</p>
<h3 id="delete">Menghapus dokumen</h3>
<p>Jika Anda memiliki URI dokumen dan
{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS Document.COLUMN_FLAGS}
dokumen berisi
{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE SUPPORTS_DELETE},
Anda bisa menghapus dokumen tersebut. Misalnya:</p>
<pre>
DocumentsContract.deleteDocument(getContentResolver(), uri);
</pre>
<h3 id="edit">Mengedit dokumen</h3>
<p>Anda bisa menggunakan SAF untuk mengedit dokumen teks langsung di tempatnya.
Cuplikan ini memicu
intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT} dan menggunakan
kategori {@link android.content.Intent#CATEGORY_OPENABLE} untuk menampilkan
dokumen yang bisa dibuka saja. Ini akan menyaring lebih jauh untuk menampilkan file teks saja:</p>
<pre>
private static final int EDIT_REQUEST_CODE = 44;
/**
* Open a file for writing and append some text to it.
*/
private void editDocument() {
// ACTION_OPEN_DOCUMENT is the intent to choose a file via the system's
// file browser.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// Filter to only show results that can be &quot;opened&quot;, such as a
// file (as opposed to a list of contacts or timezones).
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only text files.
intent.setType(&quot;text/plain&quot;);
startActivityForResult(intent, EDIT_REQUEST_CODE);
}
</pre>
<p>Berikutnya, dari {@link android.app.Activity#onActivityResult onActivityResult()}
(lihat <a href="#results">Memproses hasil</a>) Anda bisa memanggil kode untuk mengedit.
Cuplikan berikut mendapatkan {@link java.io.FileOutputStream}
dari {@link android.content.ContentResolver}. Secara default, snipet menggunakan mode “tulis”.
Inilah praktik terbaik untuk meminta jumlah akses minimum yang Anda perlukan, jadi jangan meminta
baca/tulis jika yang Anda perlukan hanyalah tulis:</p>
<pre>private void alterDocument(Uri uri) {
try {
ParcelFileDescriptor pfd = getActivity().getContentResolver().
openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream =
new FileOutputStream(pfd.getFileDescriptor());
fileOutputStream.write(("Overwritten by MyCloud at " +
System.currentTimeMillis() + "\n").getBytes());
// Let the document provider know you're done by closing the stream.
fileOutputStream.close();
pfd.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}</pre>
<h3 id="permissions">Mempertahankan izin</h3>
<p>Bila aplikasi Anda membuka file untuk membaca atau menulis, sistem akan memberi
aplikasi Anda izin URI untuk file itu. Pemberian ini berlaku hingga perangkat pengguna di-restart.
Namun anggaplah aplikasi Anda adalah aplikasi pengeditan gambar, dan Anda ingin pengguna bisa
mengakses 5 gambar terakhir yang dieditnya, langsung dari aplikasi Anda. Jika perangkat pengguna telah
di-restart, maka Anda harus mengirim pengguna kembali ke picker sistem untuk menemukan
file, hal ini jelas tidak ideal.</p>
<p>Untuk mencegah terjadinya hal ini, Anda bisa mempertahankan izin yang diberikan
sistem ke aplikasi Anda. Secara efektif, aplikasi Anda akan "mengambil" pemberian izin URI yang bisa dipertahankan
yang ditawarkan oleh sistem. Hal ini memberi pengguna akses kontinu ke file
melalui aplikasi Anda, sekalipun perangkat telah di-restart:</p>
<pre>final int takeFlags = intent.getFlags()
&amp; (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(uri, takeFlags);</pre>
<p>Ada satu langkah akhir. Anda mungkin telah menyimpan
URI terbaru yang diakses aplikasi, namun URI itu mungkin tidak lagi valid,&mdash;aplikasi lain
mungkin telah menghapus atau memodifikasi dokumen. Karena itu, Anda harus selalu memanggil
{@code getContentResolver().takePersistableUriPermission()} untuk memeriksa
data terbaru.</p>
<h2 id="custom">Menulis Penyedia Dokumen Custom</h2>
<p>
Jika Anda sedang mengembangkan aplikasi yang menyediakan layanan penyimpanan untuk file (misalnya
layanan penyimpanan cloud), Anda bisa menyediakan file melalui
SAF dengan menulis penyedia dokumen custom. Bagian ini menjelaskan
caranya.</p>
<h3 id="manifest">Manifes</h3>
<p>Untuk mengimplementasikan penyedia dokumen custom, tambahkan yang berikut ini ke manifes aplikasi
Anda:</p>
<ul>
<li>Target berupa API level 19 atau yang lebih tinggi.</li>
<li>Elemen <code>&lt;provider&gt;</code> yang mendeklarasikan penyedia penyimpanan custom
Anda. </li>
<li>Nama penyedia Anda, yaitu nama kelasnya, termasuk nama paket.
Misalnya: <code>com.example.android.storageprovider.MyCloudProvider</code>.</li>
<li>Nama otoritas Anda, yaitu nama paket Anda (dalam contoh ini,
<code>com.example.android.storageprovider</code>) plus tipe penyedia konten
(<code>documents</code>). Misalnya, {@code com.example.android.storageprovider.documents}.</li>
<li>Atribut <code>android:exported</code> yang diatur ke <code>&quot;true&quot;</code>.
Anda harus mengekspor penyedia sehingga aplikasi lain bisa membacanya.</li>
<li>Atribut <code>android:grantUriPermissions</code> yang diatur ke
<code>&quot;true&quot;</code>. Pengaturan ini memungkinkan sistem memberi aplikasi lain akses
ke konten dalam penyedia Anda. Untuk pembahasan cara mempertahankan pemberian bagi
dokumen tertentu, lihat <a href="#permissions">Mempertahankan izin</a>.</li>
<li>Izin {@code MANAGE_DOCUMENTS}. Secara default, penyedia tersedia
bagi siapa saja. Menambahkan izin ini akan membatasi penyedia Anda pada sistem.
Pembatasan ini penting untuk keamanan.</li>
<li>Atribut {@code android:enabled} yang diatur ke nilai boolean didefinisikan dalam file
sumber daya. Tujuan atribut ini adalah menonaktifkan penyedia pada perangkat yang menjalankan Android 4.3 atau yang lebih rendah.
Misalnya, {@code android:enabled="@bool/atLeastKitKat"}. Selain
memasukkan atribut ini dalam manifes, Anda perlu melakukan hal-hal berikut:
<ul>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atLeastKitKat&quot;&gt;false&lt;/bool&gt;</pre></li>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atLeastKitKat&quot;&gt;true&lt;/bool&gt;</pre></li>
</ul></li>
<li>Sebuah filter intent berisi tindakan
{@code android.content.action.DOCUMENTS_PROVIDER}, agar penyedia Anda
muncul dalam picker saat sistem mencari penyedia.</li>
</ul>
<p>Berikut ini adalah kutipan contoh manifes berisi penyedia yang:</p>
<pre>&lt;manifest... &gt;
...
&lt;uses-sdk
android:minSdkVersion=&quot;19&quot;
android:targetSdkVersion=&quot;19&quot; /&gt;
....
&lt;provider
android:name=&quot;com.example.android.storageprovider.MyCloudProvider&quot;
android:authorities=&quot;com.example.android.storageprovider.documents&quot;
android:grantUriPermissions=&quot;true&quot;
android:exported=&quot;true&quot;
android:permission=&quot;android.permission.MANAGE_DOCUMENTS&quot;
android:enabled=&quot;&#64;bool/atLeastKitKat&quot;&gt;
&lt;intent-filter&gt;
&lt;action android:name=&quot;android.content.action.DOCUMENTS_PROVIDER&quot; /&gt;
&lt;/intent-filter&gt;
&lt;/provider&gt;
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<h4 id="43">Mendukung perangkat yang menjalankan Android 4.3 dan yang lebih rendah</h4>
<p>Intent
{@link android.content.Intent#ACTION_OPEN_DOCUMENT} hanya tersedia
pada perangkat yang menjalankan Android 4.4 dan yang lebih tinggi.
Jika ingin aplikasi Anda mendukung {@link android.content.Intent#ACTION_GET_CONTENT}
untuk mengakomodasi perangkat yang menjalankan Android 4.3 dan yang lebih rendah, Anda harus
menonaktifkan filter inten {@link android.content.Intent#ACTION_GET_CONTENT} dalam
manifes untuk perangkat yang menjalankan Android 4.4 atau yang lebih tinggi. Penyedia
dokumen dan {@link android.content.Intent#ACTION_GET_CONTENT} harus dianggap
saling eksklusif. Jika Anda mendukung keduanya sekaligus, aplikasi Anda akan
muncul dua kali dalam UI picker sistem, yang menawarkan dua cara mengakses
data tersimpan Anda. Hal ini akan membingungkan pengguna.</p>
<p>Berikut ini adalah cara yang disarankan untuk menonaktifkan
filter intent {@link android.content.Intent#ACTION_GET_CONTENT} untuk perangkat
yang menjalankan Android versi 4.4 atau yang lebih tinggi:</p>
<ol>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atMostJellyBeanMR2&quot;&gt;true&lt;/bool&gt;</pre></li>
<li>Dalam file sumber daya {@code bool.xml} Anda di bawah {@code res/values-v19/}, tambahkan
baris ini: <pre>&lt;bool name=&quot;atMostJellyBeanMR2&quot;&gt;false&lt;/bool&gt;</pre></li>
<li>Tambahkan
<a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">alias
aktivitas</a> untuk menonaktifkan filter intent {@link android.content.Intent#ACTION_GET_CONTENT}
bagi versi 4.4 (API level 19) dan yang lebih tinggi. Misalnya:
<pre>
&lt;!-- This activity alias is added so that GET_CONTENT intent-filter
can be disabled for builds on API level 19 and higher. --&gt;
&lt;activity-alias android:name=&quot;com.android.example.app.MyPicker&quot;
android:targetActivity=&quot;com.android.example.app.MyActivity&quot;
...
android:enabled=&quot;@bool/atMostJellyBeanMR2&quot;&gt;
&lt;intent-filter&gt;
&lt;action android:name=&quot;android.intent.action.GET_CONTENT&quot; /&gt;
&lt;category android:name=&quot;android.intent.category.OPENABLE&quot; /&gt;
&lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
&lt;data android:mimeType=&quot;image/*&quot; /&gt;
&lt;data android:mimeType=&quot;video/*&quot; /&gt;
&lt;/intent-filter&gt;
&lt;/activity-alias&gt;
</pre>
</li>
</ol>
<h3 id="contract">Kontrak</h3>
<p>Biasanya bila Anda menulis penyedia konten custom, salah satu tugas adalah
mengimplementasikan kelas kontrak, seperti dijelaskan dalam panduan pengembang
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html#ContractClass">
Penyedia Konten</a>. Kelas kontrak adalah kelas {@code public final}
yang berisi definisi konstanta untuk URI, nama kolom, tipe MIME, dan
metadata lain yang berkenaan dengan penyedia. SAF
menyediakan kelas-kelas kontrak ini untuk Anda, jadi Anda tidak perlu menulisnya
sendiri:</p>
<ul>
<li>{@link android.provider.DocumentsContract.Document}</li>
<li>{@link android.provider.DocumentsContract.Root}</li>
</ul>
<p>Misalnya, berikut ini adalah kolom-kolom yang bisa Anda hasilkan di kursor bila
penyedia dokumen Anda membuat query dokumen atau akar:</p>
<pre>private static final String[] DEFAULT_ROOT_PROJECTION =
new String[]{Root.COLUMN_ROOT_ID, Root.COLUMN_MIME_TYPES,
Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
Root.COLUMN_SUMMARY, Root.COLUMN_DOCUMENT_ID,
Root.COLUMN_AVAILABLE_BYTES,};
private static final String[] DEFAULT_DOCUMENT_PROJECTION = new
String[]{Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE,
Document.COLUMN_DISPLAY_NAME, Document.COLUMN_LAST_MODIFIED,
Document.COLUMN_FLAGS, Document.COLUMN_SIZE,};
</pre>
<h3 id="subclass">Subkelas DocumentsProvider</h3>
<p>Langkah berikutnya dalam menulis penyedia dokumen custom adalah menjadikan
kelas abstrak sebagai subkelas {@link android.provider.DocumentsProvider}. Setidaknya, Anda perlu
mengimplementasikan metode berikut:</p>
<ul>
<li>{@link android.provider.DocumentsProvider#queryRoots queryRoots()}</li>
<li>{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}</li>
<li>{@link android.provider.DocumentsProvider#queryDocument queryDocument()}</li>
<li>{@link android.provider.DocumentsProvider#openDocument openDocument()}</li>
</ul>
<p>Hanya inilah metode yang diwajibkan kepada Anda secara ketat untuk diimplementasikan, namun ada
banyak lagi yang mungkin Anda inginkan. Lihat {@link android.provider.DocumentsProvider}
untuk detailnya.</p>
<h4 id="queryRoots">Mengimplementasikan queryRoots</h4>
<p>Implementasi {@link android.provider.DocumentsProvider#queryRoots
queryRoots()} oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua
direktori akar penyedia dokumen, dengan menggunakan kolom-kolom yang didefinisikan dalam
{@link android.provider.DocumentsContract.Root}.</p>
<p>Dalam cuplikan berikut, parameter {@code projection} mewakili bidang-bidang
tertentu yang ingin didapatkan kembali oleh pemanggil. Cuplikan ini membuat kursor baru
dan menambahkan satu baris ke satu akar&mdash; kursor, satu direktori level atas, seperti
Downloads atau Images. Kebanyakan penyedia hanya mempunyai satu akar. Anda bisa mempunyai lebih dari satu,
misalnya, jika ada banyak akun pengguna. Dalam hal itu, cukup tambahkan sebuah
baris kedua ke kursor.</p>
<pre>
&#64;Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
// Create a cursor with either the requested fields, or the default
// projection if "projection" is null.
final MatrixCursor result =
new MatrixCursor(resolveRootProjection(projection));
// If user is not logged in, return an empty root cursor. This removes our
// provider from the list entirely.
if (!isUserLoggedIn()) {
return result;
}
// It's possible to have multiple roots (e.g. for multiple accounts in the
// same app) -- just add multiple cursor rows.
// Construct one row for a root called &quot;MyCloud&quot;.
final MatrixCursor.RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, ROOT);
row.add(Root.COLUMN_SUMMARY, getContext().getString(R.string.root_summary));
// FLAG_SUPPORTS_CREATE means at least one directory under the root supports
// creating documents. FLAG_SUPPORTS_RECENTS means your application's most
// recently used documents will show up in the &quot;Recents&quot; category.
// FLAG_SUPPORTS_SEARCH allows users to search all documents the application
// shares.
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE |
Root.FLAG_SUPPORTS_RECENTS |
Root.FLAG_SUPPORTS_SEARCH);
// COLUMN_TITLE is the root title (e.g. Gallery, Drive).
row.add(Root.COLUMN_TITLE, getContext().getString(R.string.title));
// This document id cannot change once it's shared.
row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(mBaseDir));
// The child MIME types are used to filter the roots and only present to the
// user roots that contain the desired type somewhere in their file hierarchy.
row.add(Root.COLUMN_MIME_TYPES, getChildMimeTypes(mBaseDir));
row.add(Root.COLUMN_AVAILABLE_BYTES, mBaseDir.getFreeSpace());
row.add(Root.COLUMN_ICON, R.drawable.ic_launcher);
return result;
}</pre>
<h4 id="queryChildDocuments">Mengimplementasikan queryChildDocuments</h4>
<p>Implementasi
{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}
oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke semua file dalam
direktori yang ditentukan, dengan menggunakan kolom-kolom yang didefinisikan dalam
{@link android.provider.DocumentsContract.Document}.</p>
<p>Metode ini akan dipanggil bila Anda memilih akar aplikasi dalam picker UI.
Metode mengambil dokumen anak dari direktori di bawah akar. Metode ini bisa dipanggil pada level apa saja dalam
hierarki file, bukan hanya akar. Cuplikan ini
membuat kursor baru dengan kolom-kolom yang diminta, lalu menambahkan informasi tentang
setiap anak langsung dalam direktori induk ke kursor.
Satu anak bisa berupa gambar, direktori lain&mdash;file apa saja:</p>
<pre>&#64;Override
public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
String sortOrder) throws FileNotFoundException {
final MatrixCursor result = new
MatrixCursor(resolveDocumentProjection(projection));
final File parent = getFileForDocId(parentDocumentId);
for (File file : parent.listFiles()) {
// Adds the file's display name, MIME type, size, and so on.
includeFile(result, null, file);
}
return result;
}
</pre>
<h4 id="queryDocument">Mengimplementasikan queryDocument</h4>
<p>Implementasi
{@link android.provider.DocumentsProvider#queryDocument queryDocument()}
oleh Anda harus menghasilkan {@link android.database.Cursor} yang menunjuk ke file yang disebutkan,
dengan menggunakan kolom-kolom yang didefinisikan dalam {@link android.provider.DocumentsContract.Document}.
</p>
<p>Metode {@link android.provider.DocumentsProvider#queryDocument queryDocument()}
menghasilkan informasi yang sama yang diteruskan dalam
{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()},
namun untuk file tertentu:</p>
<pre>&#64;Override
public Cursor queryDocument(String documentId, String[] projection) throws
FileNotFoundException {
// Create a cursor with the requested projection, or the default projection.
final MatrixCursor result = new
MatrixCursor(resolveDocumentProjection(projection));
includeFile(result, documentId, null);
return result;
}
</pre>
<h4 id="openDocument">Mengimplementasikan openDocument</h4>
<p>Anda harus mengimplementasikan {@link android.provider.DocumentsProvider#openDocument
openDocument()} untuk menghasilkan {@link android.os.ParcelFileDescriptor} yang mewakili
file yang disebutkan. Aplikasi lain bisa menggunakan {@link android.os.ParcelFileDescriptor}
yang dihasilkan untuk mengalirkan data. Sistem memanggil metode ini setelah pengguna memilih file
dan aplikasi klien meminta akses ke file itu dengan memanggil
{@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()}.
Misalnya:</p>
<pre>&#64;Override
public ParcelFileDescriptor openDocument(final String documentId,
final String mode,
CancellationSignal signal) throws
FileNotFoundException {
Log.v(TAG, &quot;openDocument, mode: &quot; + mode);
// It's OK to do network operations in this method to download the document,
// as long as you periodically check the CancellationSignal. If you have an
// extremely large file to transfer from the network, a better solution may
// be pipes or sockets (see ParcelFileDescriptor for helper methods).
final File file = getFileForDocId(documentId);
final boolean isWrite = (mode.indexOf('w') != -1);
if(isWrite) {
// Attach a close listener if the document is opened in write mode.
try {
Handler handler = new Handler(getContext().getMainLooper());
return ParcelFileDescriptor.open(file, accessMode, handler,
new ParcelFileDescriptor.OnCloseListener() {
&#64;Override
public void onClose(IOException e) {
// Update the file with the cloud server. The client is done
// writing.
Log.i(TAG, &quot;A file with id &quot; +
documentId + &quot; has been closed!
Time to &quot; +
&quot;update the server.&quot;);
}
});
} catch (IOException e) {
throw new FileNotFoundException(&quot;Failed to open document with id &quot;
+ documentId + &quot; and mode &quot; + mode);
}
} else {
return ParcelFileDescriptor.open(file, accessMode);
}
}
</pre>
<h3 id="security">Keamanan</h3>
<p>Anggaplah penyedia dokumen Anda sebuah layanan penyimpanan cloud yang dilindungi kata sandi
dan Anda ingin memastikan bahwa pengguna sudah login sebelum Anda mulai berbagi file mereka.
Apakah yang harus dilakukan aplikasi Anda jika pengguna tidak login? Solusinya adalah menghasilkan
akar nol dalam implementasi {@link android.provider.DocumentsProvider#queryRoots
queryRoots()} Anda. Yakni, sebuah kursor akar kosong:</p>
<pre>
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
...
// If user is not logged in, return an empty root cursor. This removes our
// provider from the list entirely.
if (!isUserLoggedIn()) {
return result;
}
</pre>
<p>Langkah lainnya adalah memanggil {@code getContentResolver().notifyChange()}.
Ingat {@link android.provider.DocumentsContract}? Kita menggunakannya untuk membuat
URI ini. Cuplikan berikut memberi tahu sistem untuk membuat query akar penyedia dokumen Anda
kapan saja status login pengguna berubah. Jika pengguna tidak
login, panggilan ke {@link android.provider.DocumentsProvider#queryRoots queryRoots()} akan menghasilkan
kursor kosong, seperti yang ditampilkan di atas. Cara ini akan memastikan bahwa dokumen penyedia hanya
tersedia jika pengguna login ke penyedia itu.</p>
<pre>private void onLoginButtonClick() {
loginOrLogout();
getContentResolver().notifyChange(DocumentsContract
.buildRootsUri(AUTHORITY), null);
}
</pre>

View File

@@ -0,0 +1,337 @@
page.title=Mengakses Sumber Daya
parent.title=Sumber Daya Aplikasi
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Tampilan Cepat</h2>
<ul>
<li>Sumber daya bisa diacu dari kode dengan menggunakan integer dari {@code R.java}, seperti
{@code R.drawable.myimage}</li>
<li>Sumber daya bisa diacu dari sumber daya dengan menggunakan sintaks XML khusus, seperti {@code
&#64;drawable/myimage}</li>
<li>Anda juga bisa mengakses sumber daya aplikasi Anda dengan berbagai metode di
{@link android.content.res.Resources}</li>
</ul>
<h2>Kelas-Kelas Utama</h2>
<ol>
<li>{@link android.content.res.Resources}</li>
</ol>
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#ResourcesFromCode">Mengakses Sumber Daya dari Kode</a></li>
<li><a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>
<ol>
<li><a href="#ReferencesToThemeAttributes">Mengacu atribut gaya</a></li>
</ol>
</li>
<li><a href="#PlatformResources">Mengakses Sumber Daya Platform</a></li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
<li><a href="available-resources.html">Tipe Sumber Daya</a></li>
</ol>
</div>
</div>
<p>Setelah Anda menyediakan sumber daya dalam aplikasi Anda (yang dibicarakan di <a href="providing-resources.html">Menyediakan Sumber Daya</a>), Anda bisa menerapkannya dengan
mengacu ID sumber dayanya. Semua ID sumber daya didefinisikan di kelas {@code R} proyek Anda, yang
dihasilkan oleh alat {@code aapt} secara otomatis.</p>
<p>Bila aplikasi Anda dikompilasi, {@code aapt} akan membuat kelas {@code R}, yang berisi
ID sumber daya untuk semua sumber daya dalam direktori {@code
res/} Anda. Untuk masing-masing tipe sumber daya, ada subkelas {@code R} (misalnya,
{@code R.drawable} untuk semua sumber daya yang bisa ditarik), dan untuk masing-masing sumber daya dari tipe itu, ada satu integer statis
(misalnya, {@code R.drawable.icon}). Integer ini adalah ID sumber daya yang bisa Anda gunakan
untuk mengambil sumber daya Anda.</p>
<p>Walaupun kelas {@code R} adalah tempat menyebutkan ID sumber daya, Anda tidak perlu
melihat ke sana untuk menemukan ID sumber daya. ID sumber daya selalu terdiri dari:</p>
<ul>
<li><em>Tipe sumber daya</em>: Masing-masing sumber daya dikelompokkan menjadi "tipe", misalnya {@code
string}, {@code drawable}, dan {@code layout}. Untuk mengetahui selengkapnya tentang berbagai tipe, lihat <a href="available-resources.html">Tipe Sumber Daya</a>.
</li>
<li><em>Nama sumber daya</em>, bisa berupa: nama file,
tidak termasuk ekstensi; atau nilai dalam atribut {@code android:name} XML, jika
sumber daya itu sebuah nilai sederhana (misalnya sebuah string).</li>
</ul>
<p>Ada dua cara untuk mengakses sumber daya:</p>
<ul>
<li><strong>Dalam kode:</strong> Menggunakan integer statis dari subkelas dari kelas {@code R}
, misalnya:
<pre class="classic no-pretty-print">R.string.hello</pre>
<p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Ada banyak
API Android yang bisa mengakses sumber daya Anda bila Anda menyediakan ID sumber daya dengan format ini. Lihat
<a href="#ResourcesFromCode">Mengakses Sumber Daya dalam Kode</a>.</p>
</li>
<li><strong>Dalam XML:</strong> Menggunakan sebuah sintaks XML khusus yang juga berkaitan dengan
ID sumber daya yang didefinisikan dalam kelas {@code R}, misalnya:
<pre class="classic no-pretty-print">&#64;string/hello</pre>
<p>{@code string} adalah tipe sumber daya dan {@code hello} adalah nama sumber daya. Anda bisa menggunakan
sintaks ini dalam sumber daya XML di mana saja Anda ingin menyediakan sebuah nilai dalam sebuah sumber daya. Lihat <a href="#ResourcesFromXml">Mengakses Sumber Daya dari XML</a>.</p>
</li>
</ul>
<h2 id="ResourcesFromCode">Mengakses Sumber Daya dalam Kode </h2>
<p>Anda bisa menggunakan sumber daya dalam kode dengan menyalurkan ID sumber daya sebagai sebuah parameter metode. Misalnya,
Anda bisa mengatur sebuah {@link android.widget.ImageView} agar menggunakan sumber daya{@code res/drawable/myimage.png}
dengan menggunakan {@link android.widget.ImageView#setImageResource(int) setImageResource()}:</p>
<pre>
ImageView imageView = (ImageView) findViewById(R.id.myimageview);
imageView.setImageResource(<strong>R.drawable.myimage</strong>);
</pre>
<p>Anda juga bisa mengambil tiap sumber daya dengan menggunakan berbagai metode di {@link
android.content.res.Resources}, di mana Anda bisa mendapatkan instance
{@link android.content.Context#getResources()}.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Akses ke File Asli</h2>
<p>Walaupun tidak lazim, Anda mungkin perlu mengakses file dan direktori asli Anda. Jika demikian, maka
menyimpan file Anda di {@code res/} tidak akan berhasil, karena satu-satunya cara untuk membaca sebuah sumber daya dari
{@code res/} adalah dengan ID sumber daya. Sebagai gantinya, Anda bisa menyimpan sumber daya dalam direktori
{@code assets/}.</p>
<p>File yang tersimpan di direktori {@code assets/} <em>tidak</em> diberi ID
sumber daya, sehingga Anda tidak bisa mengacunya melalui kelas {@code R} atau dari sumber daya XML. Sebagai gantinya, Anda bisa melakukan
query file di direktori {@code assets/} seperti sebuah sistem file biasa dan membaca data mentah dengan menggunakan
{@link android.content.res.AssetManager}.</p>
<p>Akan tetapi, jika yang Anda butuhkan hanya kemampuan membaca data mentah (misalnya sebuah file video atau audio),
maka simpanlah file itu di direktori {@code res/raw/} dan baca aliran byte dengan menggunakan {@link
android.content.res.Resources#openRawResource(int) openRawResource()}.</p>
</div>
</div>
<h3>Sintaks</h3>
<p>Inilah sintaks untuk mengacu sumber daya dalam kode:</p>
<pre class="classic no-pretty-print">
[<em>&lt;package_name&gt;</em>.]R.<em>&lt;resource_type&gt;</em>.<em>&lt;resource_name&gt;</em>
</pre>
<ul>
<li><em> {@code &lt;package_name&gt;}</em>adalah nama paket yang di dalamnya terdapat sumber daya (tidak
dibutuhkan bila mengacu sumber daya dari paket Anda sendiri).</li>
<li><em>{@code &lt;resource_type&gt;}</em> adalah subkelas {@code R} untuk tipe sumber daya.</li>
<li><em>{@code &lt;resource_name&gt;}</em> bisa berupa nama file sumber daya
tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
sederhana).</li>
</ul>
<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
<h3>Kasus penggunaan</h3>
<p>Ada banyak metode yang menerima parameter ID sumber daya dan Anda bisa mengambil sumber daya dengan menggunakan
metode di {@link android.content.res.Resources}. Anda bisa mengambil instance {@link
android.content.res.Resources} dengan {@link android.content.Context#getResources
Context.getResources()}.</p>
<p>Berikut adalah beberapa contoh cara mengakses sumber daya dalam kode:</p>
<pre>
// Load a background for the current screen from a drawable resource
{@link android.app.Activity#getWindow()}.{@link
android.view.Window#setBackgroundDrawableResource(int)
setBackgroundDrawableResource}(<strong>R.drawable.my_background_image</strong>) ;
// Set the Activity title by getting a string from the Resources object, because
// this method requires a CharSequence rather than a resource ID
{@link android.app.Activity#getWindow()}.{@link android.view.Window#setTitle(CharSequence)
setTitle}(getResources().{@link android.content.res.Resources#getText(int)
getText}(<strong>R.string.main_title</strong>));
// Load a custom layout for the current screen
{@link android.app.Activity#setContentView(int)
setContentView}(<strong>R.layout.main_screen</strong>);
// Set a slide in animation by getting an Animation from the Resources object
mFlipper.{@link android.widget.ViewAnimator#setInAnimation(Animation)
setInAnimation}(AnimationUtils.loadAnimation(this,
<strong>R.anim.hyperspace_in</strong>));
// Set the text on a TextView object using a resource ID
TextView msgTextView = (TextView) findViewById(<strong>R.id.msg</strong>);
msgTextView.{@link android.widget.TextView#setText(int)
setText}(<strong>R.string.hello_message</strong>);
</pre>
<p class="caution"><strong>Perhatian:</strong> Anda tidak boleh memodifikasi file {@code
R.java} secara manual&mdash;, ini dihasilkan oleh alat {@code aapt} bila proyek Anda telah
dikompilasi. Perubahan apa pun akan ditimpa bila nanti Anda mengompilasi.</p>
<h2 id="ResourcesFromXml">Mengakses Sumber Daya dari XML</h2>
<p>Anda bisa mendefinisikan nilai untuk beberapa atribut dan elemen XML dengan menggunakan
acuan ke sumber daya yang ada. Anda akan sering melakukannya saat membuat file layout, untuk
memasok string dan gambar bagi widget Anda.</p>
<p>Misalnya, jika Anda menambahkan sebuah {@link android.widget.Button} ke layout, Anda harus menggunakan
sebuah <a href="string-resource.html">sumber daya string</a> bagi teks tombolnya:</p>
<pre>
&lt;Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="<strong>@string/submit</strong>" /&gt;
</pre>
<h3>Sintaks</h3>
<p>Berikut adalah sintaks untuk mengacu sumber daya di sumber daya XML:</p>
<pre class="classic no-pretty-print">
&#64;[<em>&lt;package_name&gt;</em>:]<em>&lt;resource_type&gt;</em>/<em>&lt;resource_name&gt;</em>
</pre>
<ul>
<li>{@code &lt;package_name&gt;} adalah nama paket yang di dalamnya terdapat sumber daya (tidak
dibutuhkan bila mengacu sumber daya dari paket yang sama)</li>
<li>{@code &lt;resource_type&gt;} adalah subkelas
{@code R} untuk tipe sumber daya</li>
<li>{@code &lt;resource_name&gt;} bisa berupa nama file sumber daya
tanpa ekstensi atau nilai atribut {@code android:name} dalam elemen XML (untuk nilai
sederhana).</li>
</ul>
<p>Lihat <a href="available-resources.html">Tipe Sumber Daya</a> untuk
informasi selengkapnya tentang masing-masing tipe sumber daya dan cara mengacunya.</p>
<h3>Kasus penggunaan</h3>
<p>Dalam beberapa kasus, Anda harus menggunakan sumber daya untuk suatu nilai dalam XML (misalnya, untuk menerapkan gambar yang bisa ditarik
pada widget), namun Anda juga bisa menggunakan sumber daya di XML mana saja yang menerima nilai sederhana. Misalnya, jika
Anda mempunyai file sumber daya berikut yang berisi <a href="more-resources.html#Color">sumber daya warna</a> dan <a href="string-resource.html">sumber daya string</a>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;color name="opaque_red">#f00&lt;/color>
&lt;string name="hello">Hello!&lt;/string>
&lt;/resources>
</pre>
<p>Anda bisa menggunakan sumber daya ini dalam file layout berikut untuk mengatur warna teks dan
string teks:</p>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:textColor=&quot;<strong>&#64;color/opaque_red</strong>&quot;
android:text=&quot;<strong>&#64;string/hello</strong>&quot; /&gt;
</pre>
<p>Dalam hal ini, Anda tidak perlu menyebutkan nama paket dalam sumber daya acuan karena
sumber daya berasal dari paket Anda sendiri. Untuk
mengacu sumber daya sistem, Anda perlu memasukkan nama paketnya. Misalnya:</p>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;EditText xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:textColor=&quot;<strong>&#64;android:color/secondary_text_dark</strong>&quot;
android:text=&quot;&#64;string/hello&quot; /&gt;
</pre>
<p class="note"><strong>Catatan:</strong> Anda harus menggunakan sumber daya string sepanjang
waktu, sehingga aplikasi Anda bisa dilokalkan untuk bahasa lain.
Untuk informasi tentang cara menciptakan
sumber daya alternatif (seperti string lokal), lihat <a href="providing-resources.html#AlternativeResources">Menyediakan Sumber Daya Alternatif
</a>. Untuk panduan lengkap melokalkan aplikasi Anda ke bahasa lain,
lihat <a href="localization.html">Pelokalan</a>.</p>
<p>Anda bahkan bisa menggunakan sumber daya dalam XML untuk membuat alias. Misalnya, Anda bisa membuat
sumber daya yang bisa ditarik yang merupakan alias bagi sumber daya yang bisa ditarik lainnya:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/other_drawable" />
</pre>
<p>Hal ini terdengar berlebihan, namun bisa sangat berguna saat menggunakan sumber daya alternatif. Baca selengkapnya tentang
<a href="providing-resources.html#AliasResources">Membuat sumber daya alias</a>.</p>
<h3 id="ReferencesToThemeAttributes">Mengacu atribut gaya</h3>
<p>Sumber daya atribut gaya memungkinkan Anda mengacu nilai
suatu atribut dalam tema yang diterapkan saat ini. Dengan mengacu sebuah atribut gaya memungkinkan Anda
menyesuaikan tampilan elemen UI dengan mengatur gayanya agar cocok dengan beragam variasi standar yang dipasok oleh
tema saat ini, sebagai ganti memasok nilai yang ditanamkan (hard-coded). Mengacu sebuah atribut gaya
pada dasarnya adalah "gunakan gaya yang didefinisikan oleh atribut ini, dalam tema saat ini".</p>
<p>Untuk mengacu sebuah atribut gaya, sintaks namanya hampir sama dengan format sumber daya normal
, namun sebagai ganti simbol @ ({@code @}), gunakan sebuah tanda tanya ({@code ?}), dan
porsi tipe sumber daya bersifat opsional. Sebagai contoh:</p>
<pre class="classic">
?[<em>&lt;package_name&gt;</em>:][<em>&lt;resource_type&gt;</em>/]<em>&lt;resource_name&gt;</em>
</pre>
<p>Misalnya, begini cara Anda mengacu suatu atribut untuk mengatur warna teks agar cocok dengan
warna teks "utama" tema sistem:</p>
<pre>
&lt;EditText id=&quot;text&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:textColor=&quot;<strong>?android:textColorSecondary</strong>&quot;
android:text=&quot;&#64;string/hello_world&quot; /&gt;
</pre>
<p>Di sini, atribut {@code android:textColor} menyebutkan nama atribut gaya
dalam tema saat ini. Android kini menggunakan nilai yang diterapkan pada atribut gaya {@code android:textColorSecondary}
sebagai nilai untuk {@code android:textColor} dalam widget ini. Karena alat sumber daya
mengetahui bahwa atribut sumber daya diharapkan dalam konteks ini,
maka Anda tidak perlu menyatakan tipenyanya secara eksplisit (yang akan berupa
<code>?android:attr/textColorSecondary</code>)&mdash;Anda bisa mengecualikan tipe {@code attr}.</p>
<h2 id="PlatformResources">Mengakses Sumber Daya Platform</h2>
<p>Android berisi sejumlah sumber daya standar, seperti gaya, tema, dan layout. Untuk
mengakses semua sumber daya ini, tetapkan acuan sumber daya Anda dengan nama paket
<code>android</code>. Misalnya, Android menyediakan sumber daya layout yang bisa Anda gunakan untuk
item daftar dalam{@link android.widget.ListAdapter}:</p>
<pre>
{@link android.app.ListActivity#setListAdapter(ListAdapter)
setListAdapter}(new {@link
android.widget.ArrayAdapter}&lt;String&gt;(this, <strong>android.R.layout.simple_list_item_1</strong>, myarray));
</pre>
<p>Dalam contoh ini, {@link android.R.layout#simple_list_item_1} adalah sumber daya layout yang didefinisikan oleh
platform untuk item di {@link android.widget.ListView}. Anda bisa menggunakannya sebagai ganti menciptakan
layout sendiri untuk item daftar. Untuk informasi selengkapnya, lihat panduan pengembang
<a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a>.</p>

View File

@@ -0,0 +1,103 @@
page.title=Ikhtisar Sumber Daya
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Topik</h2>
<ol>
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
<li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
<li><a href="runtime-changes.html">Menangani Perubahan Runtime</a></li>
<li><a href="localization.html">Pelokalan</a></li>
</ol>
<h2>Acuan</h2>
<ol>
<li><a href="available-resources.html">Tipe Sumber Daya</a></li>
</ol>
</div>
</div>
<p>Anda harus selalu mengeksternalkan sumber daya seperti gambar dan string dari kode
aplikasi, agar Anda bisa memeliharanya secara independen. Mengeksternalkan
sumber daya juga membuat Anda dapat menyediakan sumber daya alternatif yang mendukung konfigurasi
perangkat tertentu seperti bahasa atau ukuran layar yang berbeda, yang semakin penting
seiring semakin banyak tersedianya perangkat berbasis Android dengan konfigurasi berbeda. Untuk
memberikan kompatibilitas dengan konfigurasi berbeda, Anda harus menata sumber daya dalam
direktori {@code res/} proyek Anda, menggunakan berbagai subdirektori yang mengelompokkan sumber daya menurut tipe
dan konfigurasinya.</p>
<div class="figure" style="width:429px">
<img src="{@docRoot}images/resources/resource_devices_diagram1.png" height="167" alt="" />
<p class="img-caption">
<strong>Gambar 1.</strong> Dua perangkat berbeda, masing-masing menggunakan layout default
(aplikasi tidak menyediakan layout alternatif).</p>
</div>
<div class="figure" style="width:429px">
<img src="{@docRoot}images/resources/resource_devices_diagram2.png" height="167" alt="" />
<p class="img-caption">
<strong>Gambar 2.</strong> Dua perangkat berbeda, masing-masing menggunakan layout berbeda yang tersedia untuk
ukuran layar berbeda.</p>
</div>
<p>Bagi setiap tipe sumber daya, Anda bisa menetapkan sumber daya <em>default</em> dan sumber daya
<em>alternatif</em> untuk aplikasi Anda:</p>
<ul>
<li>Sumber daya default adalah sumber daya yang harus digunakan apa pun
konfigurasi perangkatnya atau jika tidak ada sumber daya alternatif yang sesuai
dengan konfigurasi saat ini.</li>
<li>Sumber daya alternatif adalah sumber daya yang Anda desain untuk digunakan dengan
konfigurasi tertentu. Untuk menetapkan bahwa satu kelompok sumber daya ditujukan bagi konfigurasi tertentu,
tambahkan qualifier konfigurasi yang sesuai ke nama direktori.</li>
</ul>
<p>Misalnya, walaupun layout
UI default Anda disimpan dalam direktori {@code res/layout/}, Anda dapat menetapkan layout berbeda
untuk digunakan saat layar dalam orientasi lanskap, dengan menyimpannya dalam direktori {@code res/layout-land/}
. Android secara otomatis memberlakukan sumber daya yang sesuai dengan mencocokkan konfigurasi perangkat
saat ini dengan nama direktori sumber daya.</p>
<p>Gambar 1 mengilustrasikan cara sistem memberlakukan layout yang sama untuk
dua perangkat berbeda saat sumber daya alternatif tidak tersedia. Gambar 2 menunjukkan
aplikasi yang sama saat menambahkan sumber daya layout alternatif untuk layar yang lebih besar.</p>
<p>Dokumen-dokumen berikut berisi panduan lengkap mengenai cara menata sumber daya aplikasi,
menetapkan sumber daya alternatif, mengaksesnya dalam aplikasi, dan banyak lagi:</p>
<dl>
<dt><strong><a href="providing-resources.html">Menyediakan Sumber Daya</a></strong></dt>
<dd>Jenis sumber daya yang dapat Anda sediakan dalam aplikasi, tempat menyimpannya, dan cara membuat sumber daya
alternatif untuk konfigurasi perangkat tertentu.</dd>
<dt><strong><a href="accessing-resources.html">Mengakses Sumber Daya</a></strong></dt>
<dd>Cara menggunakan sumber daya yang telah Anda sediakan, baik dengan mengacunya dari kode
aplikasi Anda atau dari sumber daya XML lainnya.</dd>
<dt><strong><a href="runtime-changes.html">Menangani Perubahan Runtime</a></strong></dt>
<dd>Cara mengelola perubahan konfigurasi yang terjadi saat Aktivitas Anda berjalan.</dd>
<dt><strong><a href="localization.html">Pelokalan</a></strong></dt>
<dd>Panduan dari pengalaman untuk melokalkan aplikasi menggunakan sumber daya alternatif. Walaupun ini
hanya satu penggunaan tertentu dari sumber daya alternatif, hal ini sangat penting dalam meraih pengguna lebih
banyak.</dd>
<dt><strong><a href="available-resources.html">Tipe Sumber Daya</a></strong></dt>
<dd>Acuan dari berbagai tipe sumber daya yang dapat Anda sediakan, menjelaskan elemen-elemen XML,
atribut, dan sintaksnya. Misalnya, acuan ini menunjukkan kepada Anda cara membuat sumber daya untuk
menu aplikasi, drawable, animasi, dan lainnya.</dd>
</dl>
<!--
<h2>Raw Assets</h2>
<p>An alternative to saving files in {@code res/} is to save files in the {@code
assets/} directory. This should only be necessary if you need direct access to original files and
directories by name. Files saved in the {@code assets/} directory will not be given a resource
ID, so you can't reference them through the {@code R} class or from XML resources. Instead, you can
query data in the {@code assets/} directory like an ordinary file system, search through the
directory and
read raw data using {@link android.content.res.AssetManager}. For example, this can be more useful
when dealing with textures for a game. However, if you only need to read raw data from a file
(such as a video or audio file), then you should save files into the {@code res/raw/} directory and
then read a stream of bytes using {@link android.content.res.Resources#openRawResource(int)}. This
is uncommon, but if you need direct access to original files in {@code assets/}, refer to the {@link
android.content.res.AssetManager} documentation.</p>
-->

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,281 @@
page.title=Menangani Perubahan Runtime
page.tags=aktivitas,daur hidup
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</a></li>
<li><a href="#HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</a>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="providing-resources.html">Menyediakan Sumber Daya</a></li>
<li><a href="accessing-resources.html">Mengakses Sumber Daya</a></li>
<li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Perubahan
Orientasi Layar yang Lebih Cepat</a></li>
</ol>
</div>
</div>
<p>Sebagian konfigurasi perangkat bisa berubah selama runtime
(seperti orientasi layar, ketersediaan keyboard, dan bahasa). Saat perubahan demikian terjadi,
Android akan me-restart
{@link android.app.Activity} yang berjalan ({@link android.app.Activity#onDestroy()} dipanggil, diikuti oleh {@link
android.app.Activity#onCreate(Bundle) onCreate()}). Perilaku restart didesain untuk membantu
aplikasi Anda beradaptasi dengan konfigurasi baru melalui pemuatan kembali aplikasi Anda secara otomatis dengan
sumber daya alternatif sumber yang sesuai dengan konfigurasi perangkat baru.</p>
<p>Untuk menangani restart dengan benar, aktivitas Anda harus mengembalikan
statusnya seperti semula melalui <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup
aktivitas</a> normal, dalam hal ini Android akan memanggil
{@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} sebelum menghentikan
aktivitas Anda sehingga Anda dapat menyimpan data mengenai status aplikasi. Selanjutnya Anda bisa mengembalikan status
selama {@link android.app.Activity#onCreate(Bundle) onCreate()} atau {@link
android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}.</p>
<p>Untuk menguji bahwa aplikasi me-restart sendiri dengan status tak berubah, Anda harus
memanggil perubahan konfigurasi (seperti mengubah orientasi layar) saat melakukan berbagai
tugas dalam aplikasi. Aplikasi Anda harus dapat me-restart setiap saat tanpa kehilangan
data pengguna atau status untuk menangani kejadian seperti perubahan konfigurasi atau bila pengguna menerima panggilan telepon
masuk lalu kembali ke aplikasi setelah proses
aplikasi Anda dimusnahkan. Untuk mengetahui cara mengembalikan status aktivitas, bacalah tentang <a href="{@docRoot}guide/components/activities.html#Lifecycle">Daur hidup aktivitas</a>.</p>
<p>Akan tetapi, Anda mungkin menemui situasi ketika me-restart aplikasi dan
mengembalikan data dalam jumlah besar malah menjadi mahal dan menghasilkan pengalaman pengguna yang buruk. Dalam situasi
demikian, Anda memiliki dua opsi lain:</p>
<ol type="a">
<li><a href="#RetainingAnObject">Mempertahankan objek selama perubahan konfigurasi</a>
<p>Izinkan aktivitas Anda me-restart saat konfigurasi berubah, namun bawa objek
berstatus (stateful) ke instance baru aktivitas Anda.</p>
</li>
<li><a href="#HandlingTheChange">Menangani sendiri perubahan konfigurasi</a>
<p>Cegah sistem me-restart aktivitas selama perubahan konfigurasi
tertentu, namun terima callback saat konfigurasi benar-benar berubah, agar Anda bisa memperbarui
aktivitas secara manual bila diperlukan.</p>
</li>
</ol>
<h2 id="RetainingAnObject">Mempertahankan Objek Selama Perubahan Konfigurasi</h2>
<p>Jika me-restart aktivitas mengharuskan pemulihan seperangkat data dalam jumlah besar, menghubungkan kembali koneksi
jaringan, atau melakukan operasi intensif lainnya, maka restart penuh karena perubahan konfigurasi mungkin
menjadi pengalaman pengguna yang lambat. Selain itu, Anda mungkin tidak bisa sepenuhnya mengembalikan status
aktivitas dengan {@link android.os.Bundle} yang disimpan sistem untuk Anda dengan callback {@link
android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()}&mdash;itu tidaklah
didesain untuk membawa objek besar (seperti bitmap) dan data di dalamnya harus diserialkan kemudian
dinon-serialkan, yang bisa menghabiskan banyak memori dan membuat perubahan konfigurasi menjadi lambat. Dalam situasi
demikian, Anda bisa meringankan beban memulai kembali aktivitas Anda dengan mempertahankan {@link
android.app.Fragment} saat aktivitas Anda di-restart karena perubahan konfigurasi. Fragmen ini
bisa berisi acuan ke objek stateful yang ingin Anda pertahankan.</p>
<p>Bila sistem Android menghentikan aktivitas Anda karena perubahan konfigurasi, fragmen
aktivitas yang telah ditandai untuk dipertahankan tidak akan dimusnahkan. Anda dapat menambahkan fragmen tersebut ke
aktivitas untuk mempertahankan objek stateful.</p>
<p>Untuk mempertahankan objek stateful dalam fragmen selama perubahan konfigurasi runtime:</p>
<ol>
<li>Perluas kelas {@link android.app.Fragment} dan deklarasikan referensi ke objek stateful
Anda.</li>
<li>Panggil {@link android.app.Fragment#setRetainInstance(boolean)} saat fragmen dibuat.
</li>
<li>Tambahkan fragmen ke aktivitas.</li>
<li>Gunakan {@link android.app.FragmentManager} untuk mengambil fragmen saat aktivitas
di-restart.</li>
</ol>
<p>Misalnya, definisikan fragmen sebagai berikut:</p>
<pre>
public class RetainedFragment extends Fragment {
// data object we want to retain
private MyDataObject data;
// this method is only called once for this fragment
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
public void setData(MyDataObject data) {
this.data = data;
}
public MyDataObject getData() {
return data;
}
}
</pre>
<p class="caution"><strong>Perhatian:</strong> Meskipun bisa menyimpan objek apa saja, Anda
sama sekali tidak boleh meneruskan objek yang terkait dengan {@link android.app.Activity}, seperti {@link
android.graphics.drawable.Drawable}, {@link android.widget.Adapter}, {@link android.view.View}
atau objek lainnya mana pun yang terkait dengan {@link android.content.Context}. Jika Anda melakukannya, hal tersebut akan
membocorkan semua tampilan dan sumber daya instance aktivitas semula. (Sumber daya yang bocor
berarti bahwa aplikasi Anda tetap menyimpannya dan tidak bisa dijadikan kumpulan sampah, sehingga bisa banyak
memori yang hilang.)</p>
<p>Selanjutnya gunakan {@link android.app.FragmentManager} untuk menambahkan fragmen ke aktivitas.
Anda bisa memperoleh objek data dari fragmen saat aktivitas memulai kembali selama perubahan
konfigurasi runtime. Misalnya, definisikan aktivitas Anda sebagai berikut:</p>
<pre>
public class MyActivity extends Activity {
private RetainedFragment dataFragment;
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
// create the fragment and data the first time
if (dataFragment == null) {
// add the fragment
dataFragment = new DataFragment();
fm.beginTransaction().add(dataFragment, “data”).commit();
// load the data from the web
dataFragment.setData(loadMyData());
}
// the data is available in dataFragment.getData()
...
}
&#64;Override
public void onDestroy() {
super.onDestroy();
// store the data in the fragment
dataFragment.setData(collectMyLoadedData());
}
}
</pre>
<p>Dalam contoh ini, {@link android.app.Activity#onCreate(Bundle) onCreate()} menambahkan fragmen
atau mengembalikan referensinya. {@link android.app.Activity#onCreate(Bundle) onCreate()} juga
menyimpan objek stateful dalam instance fragmen.
{@link android.app.Activity#onDestroy() onDestroy()} akan memperbarui objek stateful dalam
instance fragmen yang dipertahankan.</p>
<h2 id="HandlingTheChange">Menangani Sendiri Perubahan Konfigurasi</h2>
<p>Jika aplikasi Anda tidak memerlukan pembaruan sumber daya selama perubahan konfigurasi
tertentu <em>dan</em> Anda memiliki keterbatasan kinerja yang mengharuskan Anda untuk
menghindari restart aktivitas, maka Anda bisa mendeklarasikan agar aktivitas Anda menangani sendiri perubahan
konfigurasinya, sehingga mencegah sistem me-restart aktivitas.</p>
<p class="note"><strong>Catatan:</strong> Menangani sendiri perubahan konfigurasi bisa jauh lebih
mempersulit penggunaan sumber daya alternatif, karena sistem tidak menerapkannya secara otomatis
untuk Anda. Teknik ini harus dianggap sebagai usaha terakhir bila Anda harus menghindari restart
karena perubahan konfigurasi dan tidak disarankan untuk sebagian besar aplikasi.</p>
<p>Untuk mendeklarasikan agar aktivitas Anda menangani perubahan konfigurasi, edit elemen <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> yang sesuai
dalam file manifes Anda agar menyertakan atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> dengan nilai yang mewakili konfigurasi yang ingin
ditangani. Nilai yang memungkinkan tercantum dalam dokumentasi untuk atribut <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> (nilai paling sering digunakan adalah {@code "orientation"} untuk
mencegah restart saat orientasi layar berubah dan {@code "keyboardHidden"} untuk mencegah
restart saat ketersediaan keyboard berubah). Anda dapat mendeklarasikan beberapa nilai konfigurasi
dalam atribut dengan memisahkannya menggunakan karakter pipa {@code |}.</p>
<p>Misalnya, kode manifes berikut menyatakan aktivitas yang menangani
perubahan orientasi layar maupun perubahan ketersediaan keyboard:</p>
<pre>
&lt;activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
</pre>
<p>Sekarang, bila salah satu konfigurasi ini berubah, {@code MyActivity} tidak akan me-restart.
Sebagai gantinya, {@code MyActivity} akan menerima panggilan ke {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Metode ini
meneruskan objek {@link android.content.res.Configuration} yang menetapkan
konfigurasi perangkat baru. Dengan membaca bidang-bidang dalam {@link android.content.res.Configuration},
Anda dapat menentukan konfigurasi baru dan membuat perubahan yang sesuai dengan memperbarui
sumber daya yang digunakan dalam antarmuka. Pada saat
metode ini dipanggil, objek {@link android.content.res.Resources} aktivitas Anda akan diperbarui untuk
mengembalikan sumber daya berdasarkan konfigurasi baru, jadi Anda bisa dengan mudah
me-reset elemen UI tanpa membuat sistem me-restart aktivitas Anda.</p>
<p class="caution"><strong>Perhatian:</strong> Mulai Android 3.2 (API level 13), <strong>
"ukuran layar" juga berubah</strong> bila perangkat beralih orientasi antara potret
dan lanskap. Jadi jika Anda tidak ingin runtime di-restart karena perubahan orientasi saat mengembangkan
API level 13 atau yang lebih tinggi (sebagaimana dideklarasikan oleh atribut <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> dan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a>
), Anda harus menyertakan nilai {@code "screenSize"} selain nilai {@code
"orientation"}. Yaitu Anda harus mendeklarasikan {@code
android:configChanges="orientation|screenSize"}. Akan tetapi, jika aplikasi Anda menargetkan API level
12 atau yang lebih rendah, maka aktivitas Anda akan selalu menangani sendiri perubahan konfigurasi ini (perubahan
konfigurasi ini tidak me-restart aktivitas Anda, bahkan saat berjalan pada perangkat Android 3.2 atau yang lebih tinggi).</p>
<p>Misalnya, implementasi {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} berikut akan
memeriksa orientasi perangkat saat ini:</p>
<pre>
&#64;Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
</pre>
<p>Objek {@link android.content.res.Configuration} mewakili semua konfigurasi
saat ini, tidak hanya konfigurasi yang telah berubah. Seringkali Anda tidak perlu memperhatikan dengan persis bagaimana
konfigurasi berubah dan cukup menetapkan kembali semua sumber daya yang memberikan alternatif untuk
konfigurasi sedang ditangani. Misalnya, karena objek {@link
android.content.res.Resources} sekarang diperbarui, Anda dapat me-reset
setiap {@link android.widget.ImageView} dengan {@link android.widget.ImageView#setImageResource(int)
setImageResource()}
dan sumber daya yang sesuai untuk konfigurasi baru yang digunakan (seperti dijelaskan dalam <a href="providing-resources.html#AlternateResources">Menyediakan Sumber Daya</a>).</p>
<p>Perhatikan bahwa nilai-nilai dari bidang {@link
android.content.res.Configuration} adalah integer yang sesuai dengan konstanta spesifik
dari kelas {@link android.content.res.Configuration}. Untuk dokumentasi tentang konstanta
yang harus digunakan di setiap bidang, lihat bidang yang sesuai dalam referensi {@link
android.content.res.Configuration}.</p>
<p class="note"><strong>Ingatlah:</strong> Saat mendeklarasikan aktivitas untuk menangani perubahan
konfigurasi, Anda bertanggung jawab untuk me-reset setiap elemen yang alternatifnya Anda berikan. Jika Anda
mendeklarasikan aktivitas untuk menangani perubahan orientasi dan memiliki gambar yang harus berubah
antara lanskap dan potret, Anda harus menetapkan kembali setiap sumber daya elemen selama {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}.</p>
<p>Jika Anda tidak perlu memperbarui aplikasi berdasarkan perubahan
konfigurasi ini, sebagai gantinya Anda bisa saja <em>tidak</em> mengimplementasikan {@link
android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}. Dalam
hal ini, semua sumber daya yang digunakan sebelum perubahan konfigurasi akan tetap digunakan
dan Anda hanya menghindari restart aktivitas. Akan tetapi, aplikasi Anda harus selalu
bisa dimatikan dan di-restart dengan status sebelumnya tetap utuh, sehingga Anda jangan menganggap teknik
ini sebagai jalan keluar untuk mempertahankan status selama daur hidup aktivitas normal. Tidak hanya
karena ada perubahan konfigurasi lainnya yang tidak bisa Anda cegah untuk me-restart aplikasi, namun
juga karena Anda harus menangani kejadian seperti saat pengguna meninggalkan aplikasi dan
dimusnahkan sebelum pengguna kembali ke aplikasi.</p>
<p>Untuk informasi selengkapnya tentang perubahan konfigurasi yang bisa Anda tangani dalam aktivitas, lihat dokumentasi <a href="{@docRoot}guide/topics/manifest/activity-element.html#config">{@code
android:configChanges}</a> dan kelas {@link android.content.res.Configuration}
.</p>

View File

@@ -0,0 +1,90 @@
page.title=Kontrol Input
parent.title=Antarmuka Pengguna
parent.link=index.html
@jd:body
<div class="figure" style="margin:0">
<img src="{@docRoot}images/ui/ui-controls.png" alt="" style="margin:0" />
</div>
<p>Kontrol input adalah komponen interaktif dalam antarmuka pengguna aplikasi Anda. Android menyediakan
aneka ragam kontrol yang bisa Anda gunakan dalam UI, seperti tombol, bidang teks, bilah pencarian,
kotak cek, tombol zoom, tombol toggle, dan masih banyak lagi.</p>
<p>Menambahkan sebuah kontrol input ke UI adalah semudah menambahkan satu elemen XML ke <a href="{@docRoot}guide/topics/ui/declaring-layout.html">layout XML</a>. Misalnya, inilah sebuah
layout dengan satu bidang teks dan satu tombol:</p>
<pre style="clear:right">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
&lt;EditText android:id="@+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
&lt;Button android:id="@+id/button_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send"
android:onClick="sendMessage" />
&lt;/LinearLayout>
</pre>
<p>Tiap kontrol input mendukung satu set kejadian input sehingga Anda bisa menangani berbagai kejadian seperti saat
pengguna memasukkan teks atau menyentuh tombol.</p>
<h2 id="CommonControls">Kontrol Umum</h2>
<p>Berikut adalah daftar beberapa kontrol umum yang bisa Anda gunakan dalam aplikasi. Ikuti tautan ini untuk mengetahui
selengkapnya tentang penggunaannya masing-masing.</p>
<p class="note"><strong>Catatan:</strong> Android menyediakan beberapa kontrol lain yang tidak tercantum
di sini. Telusuri paket {@link android.widget} untuk mengetahui selengkapnya. Jika aplikasi Anda memerlukan
semacam kontrol input tertentu, Anda bisa membangun <a href="{@docRoot}guide/topics/ui/custom-components.html">komponen custom</a> sendiri.</p>
<table>
<tr>
<th scope="col">Tipe Kontrol</th>
<th scope="col">Keterangan</th>
<th scope="col">Kelas Terkait</th>
</tr>
<tr>
<td><a href="controls/button.html">Tombol</a></td>
<td>Tombol tekan yang bisa ditekan, atau diklik, oleh pengguna untuk melakukan suatu tindakan.</td>
<td>{@link android.widget.Button Button} </td>
</tr>
<tr>
<td><a href="controls/text.html">Bidang teks</a></td>
<td>Bidang teks yang bisa diedit. Anda bisa menggunakan widget <code>AutoCompleteTextView</code> untuk membuat widget entri teks yang menyediakan saran pelengkapan otomatis</td>
<td>{@link android.widget.EditText EditText}, {@link android.widget.AutoCompleteTextView}</td>
</tr>
<tr>
<td><a href="controls/checkbox.html">Kotak cek</a></td>
<td>Switch aktif/nonaktif yang bisa diubah oleh pengguna. Anda harus menggunakan kotak cek saat menampilkan sekumpulan opsi yang bisa dipilih pengguna dan bila keduanya mungkin terjadi bersamaan.</td>
<td>{@link android.widget.CheckBox CheckBox} </td>
</tr>
<tr>
<td><a href="controls/radiobutton.html">Tombol radio</a></td>
<td>Mirip dengan kotak cek, hanya saja cuma satu opsi yang bisa dipilih dalam kumpulan tersebut.</td>
<td>{@link android.widget.RadioGroup RadioGroup}
<br>{@link android.widget.RadioButton RadioButton} </td>
</tr>
<tr>
<td><a href="controls/togglebutton.html" style="white-space:nowrap">Tombol toggle</a></td>
<td>Tombol aktif/nonaktif dengan indikator cahaya.</td>
<td>{@link android.widget.ToggleButton ToggleButton} </td>
</tr>
<tr>
<td><a href="controls/spinner.html">Spinner</a></td>
<td>Daftar tarik-turun yang memungkinkan pengguna memilih salah satu dari serangkaian nilai.</td>
<td>{@link android.widget.Spinner Spinner} </td>
</tr>
<tr>
<td><a href="controls/pickers.html">Picker</a></td>
<td>Dialog bagi pengguna untuk memilih satu nilai dari satu kumpulan dengan menggunakan tombol naik/turun atau dengan gerakan mengusap. Gunakan widget <code>DatePicker</code>code&gt; untuk memasukkan nilai tanggal (bulan, hari, tahun) atau widget <code>TimePicker</code> untuk memasukkan nilai waktu (jam, menit, AM/PM), yang akan diformat secara otomatis untuk lokasi pengguna tersebut.</td>
<td>{@link android.widget.DatePicker}, {@link android.widget.TimePicker}</td>
</tr>
</table>

View File

@@ -0,0 +1,492 @@
page.title=Layout
page.tags=view,viewgroup
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#write">Tulis XML</a></li>
<li><a href="#load">Muat Sumber Daya XML</a></li>
<li><a href="#attributes">Atribut</a>
<ol>
<li><a href="#id">ID</a></li>
<li><a href="#layout-params">Parameter Layout</a></li>
</ol>
</li>
<li><a href="#Position">Posisi Layout</a></li>
<li><a href="#SizePaddingMargins">Ukuran, Pengisi, dan Margin</a></li>
<li><a href="#CommonLayouts">Layout Umum</a></li>
<li><a href="#AdapterViews">Membangun Layout dengan Adaptor</a>
<ol>
<li><a href="#FillingTheLayout">Mengisi tampilan adaptor dengan data</a></li>
<li><a href="#HandlingUserSelections">Menangani kejadian klik</a></li>
</ol>
</li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
<li>{@link android.view.ViewGroup.LayoutParams}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}training/basics/firstapp/building-ui.html">Membangun Antarmuka Pengguna
Sederhana</a></li> </div>
</div>
<p>Layout mendefinisikan struktur visual untuk antarmuka pengguna, seperti UI sebuah <a href="{@docRoot}guide/components/activities.html">aktivitas</a> atau <a href="{@docRoot}guide/topics/appwidgets/index.html">widget aplikasi</a>.
Anda dapat mendeklarasikan layout dengan dua cara:</p>
<ul>
<li><strong>Deklarasikan elemen UI dalam XML</strong>. Android menyediakan sebuah kosakata XML
sederhana yang sesuai dengan kelas dan subkelas View, seperti halnya untuk widget dan layout.</li>
<li><strong>Buat instance elemen layout saat runtime</strong>. Aplikasi Anda
bisa membuat objek View dan ViewGroup (dan memanipulasi propertinya) lewat program. </li>
</ul>
<p>Kerangka kerja Android memberi Anda fleksibilitas untuk menggunakan salah satu atau kedua metode ini guna mendeklarasikan dan mengelola UI aplikasi Anda. Misalnya, Anda bisa mendeklarasikan layout default aplikasi Anda dalam XML, termasuk elemen-elemen layar yang akan muncul di dalamnya dan di propertinya. Anda nanti bisa menambahkan kode dalam aplikasi yang akan memodifikasi status objek layar, termasuk yang dideklarasikan dalam XML, saat runtime. </p>
<div class="sidebox-wrapper">
<div class="sidebox">
<ul>
<li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
Plugin for Eclipse</a> menawarkan preview layout XML &mdash;
Anda dengan file XML yang dibuka, pilih tab <strong>Layout</strong>.</li>
<li>Anda juga harus mencoba alat
<a href="{@docRoot}tools/debugging/debugging-ui.html#hierarchyViewer">Hierarchy Viewer</a>,
untuk merunut layout &mdash; alat ini akan menampilkan nilai-nilai properti layout,
menggambar bentuk kerangka dengan indikator pengisi/margin, dan tampilan yang dirender penuh selagi
Anda merunut pada emulator atau perangkat.</li>
<li>Alat <a href="{@docRoot}tools/debugging/debugging-ui.html#layoutopt">layoutopt</a> memungkinkan
Anda menganalisis layout dan hierarki dengan untuk mengetahui ketidakefisienan atau masalah lainnya.</li>
</div>
</div>
<p>Keuntungan mendeklarasikan UI dalam XML adalah karena hal ini memungkinkan Anda memisahkan penampilan aplikasi dari kode yang mengontrol perilakunya dengan lebih baik. Keterangan UI Anda bersifat eksternal bagi kode aplikasi Anda, yang berarti bahwa Anda bisa memodifikasi atau menyesuaikannya tanpa harus memodifikasi dan mengompilasi ulang kode sumber. Misalnya, Anda bisa membuat layout XML untuk berbagai orientasi layar, berbagai ukuran layar perangkat, dan berbagai bahasa. Selain itu, mendeklarasikan layout dalam XML akan mempermudah Anda memvisualisasikan struktur UI, sehingga lebih mudah merunut masalahnya. Karena itu, dokumen ini berfokus pada upaya mengajari Anda cara mendeklarasikan layout dalam XML. Jika Anda
tertarik dalam membuat instance objek View saat runtime, lihat referensi kelas {@link android.view.ViewGroup} dan
{@link android.view.View}.</p>
<p>Secara umum, kosakata XML untuk mendeklarasikan elemen UI mengikuti dengan sangat mirip struktur serta penamaan kelas dan metode, dengan nama elemen dipadankan dengan nama kelas dan nama atribut dipadankan dengan metode. Sebenarnya, pemadanan ini kerap kali begitu jelas sehingga Anda bisa menebak atribut XML yang berpadanan dengan sebuah metode kelas, atau menebak kelas yang berpadanan dengan sebuah elemen XML. Akan tetapi, perhatikan bahwa tidak semua kosakata identik. Dalam beberapa kasus, ada sedikit perbedaan penamaan. Misalnya
, elemen EditText memiliki atribut <code>text</code> yang berpadanan dengan
<code>EditText.setText()</code>. </p>
<p class="note"><strong>Tip:</strong> Ketahui selengkapnya berbagai tipe layout dalam <a href="{@docRoot}guide/topics/ui/layout-objects.html">Objek
Layout Umum</a>. Ada juga sekumpulan tutorial tentang cara membangun berbagai layout dalam panduan tutorial
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a>.</p>
<h2 id="write">Tulis XML</h2>
<p>Dengan menggunakan kosakata XML Android, Anda bisa mendesain secara cepat layout UI dan elemen layar yang dimuatnya, sama dengan cara membuat halaman web dalam HTML &mdash; dengan serangkaian elemen tersarang. </p>
<p>Tiap file layout harus berisi persis satu elemen akar, yang harus berupa sebuah objek View atau ViewGroup. Setelah mendefinisikan elemen akar, Anda bisa menambahkan objek atau widget layout tambahan sebagai elemen anak untuk membangun hierarki View yang mendefinisikan layout Anda secara bertahap. Misalnya, inilah layout XML yang menggunakan {@link android.widget.LinearLayout}
vertikal untuk menyimpan {@link android.widget.TextView} dan {@link android.widget.Button}:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
&lt;/LinearLayout>
</pre>
<p>Setelah Anda mendeklarasikan layout dalam XML, simpanlah file dengan ekstensi <code>.xml</code>,
dalam direktori <code>res/layout/</code> proyek Android, sehingga nanti bisa dikompilasi dengan benar. </p>
<p>Informasi selengkapnya tentang sintaks untuk file XML layout tersedia dalam dokumen <a href="{@docRoot}guide/topics/resources/layout-resource.html">Sumber Daya Layout</a>.</p>
<h2 id="load">Muat Sumber Daya XML</h2>
<p>Saat mengompilasi aplikasi, masing-masing file layout XML akan dikompilasi dalam sebuah sumber daya
{@link android.view.View}. Anda harus memuat sumber daya layout dari kode aplikasi, dalam implementasi
callback {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()}.
Lakukan dengan memanggil <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
dengan meneruskan acuan ke sumber daya layout berupa:
<code>R.layout.<em>layout_file_name</em></code>.
Misalnya, jika XML layout Anda disimpan sebagai <code>main_layout.xml</code>, Anda akan memuatnya
untuk Activity seperti ini:</p>
<pre>
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
</pre>
<p>Metode callback <code>onCreate()</code> dalam Activity dipanggil oleh kerangka kerja Android saat
Activity Anda dijalankan (lihat diskusi tentang daur hidup, dalam dokumen
<a href="{@docRoot}guide/components/activities.html#Lifecycle">Aktivitas</a>
).</p>
<h2 id="attributes">Atribut</h2>
<p>Setiap objek View dan ViewGroup mendukung variasi atribut XML-nya sendiri.
Sebagian atribut bersifat spesifik untuk objek View (misalnya, TextView mendukung atribut <code>textSize</code>
), namun atribut ini juga diwarisi oleh sembarang objek View yang dapat memperluas kelas ini.
Sebagian atribut bersifat umum untuk semua objek View, karena diwarisi dari kelas View akar (seperti
atribut <code>id</code>). Dan, atribut lain dianggap sebagai "parameter layout" yaitu
atribut yang menjelaskan orientasi layout tertentu dari objek View, seperti yang didefinisikan oleh objek ViewGroup induk
dari objek itu.</p>
<h3 id="id">ID</h3>
<p>Objek View apa saja dapat memiliki ID integer yang dikaitkan dengannya, untuk mengidentifikasi secara unik View dalam pohon.
Bila aplikasi dikompilasi, ID ini akan diacu sebagai integer, namun ID biasanya
ditetapkan dalam file XML layout sebagai string, dalam atribut <code>id</code>.
Ini atribut XML yang umum untuk semua objek View
(yang didefinisikan oleh kelas {@link android.view.View}) dan Anda akan sering sekali menggunakannya.
Sintaks untuk ID dalam tag XML adalah:</p>
<pre>android:id="&#64;+id/my_button"</pre>
<p>Simbol "at" (@) pada awal string menunjukkan parser XML harus mengurai dan memperluas
ID string selebihnya dan mengenalinya sebagai ID sumber daya. Simbol tanda tambah (+) berarti ini nama sumber daya baru yang harus
dibuat dan ditambahkan ke sumber daya kita (dalam file <code>R.java</code>). Ada sejumlah sumber daya ID lain yang
ditawarkan oleh kerangka kerja Android. Saat mengacu sebuah ID sumber daya Android, Anda tidak memerlukan simbol tanda tambah,
namun harus menambahkan namespace paket <code>android</code>, sehingga:</p>
<pre>android:id="&#64;android:id/empty"</pre>
<p>Dengan namespace paket <code>android</code> yang tersedia, kita sekarang mengacu ID dari kelas sumber daya <code>android.R</code>
, daripada kelas sumber daya lokal.</p>
<p>Untuk membuat tampilan dan mengacunya dari aplikasi, pola yang umum adalah:</p>
<ol>
<li>Mendefinisikan tampilan/widget dalam file layout dan memberinya ID unik:
<pre>
&lt;Button android:id="&#64;+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/my_button_text"/>
</pre>
</li>
<li>Kemudian buat instance objek tampilan dan tangkap instance itu dari layout
(biasanya dalam metode <code>{@link android.app.Activity#onCreate(Bundle) onCreate()}</code>):
<pre>
Button myButton = (Button) findViewById(R.id.my_button);
</pre>
</li>
</ol>
<p>Mendefinisikan ID untuk objek tampilan adalah penting saat membuat {@link android.widget.RelativeLayout}.
Dalam layout relatif, tampilan saudara bisa mendefinisikan layout secara relatif terhadap tampilan saudara lainnya,
yang diacu melalui ID unik.</p>
<p>ID tidak perlu unik di seluruh pohon, namun harus
unik di bagian pohon yang Anda cari (yang mungkin sering kali seluruh pohon, jadi lebih baik
benar-benar unik bila memungkinkan).</p>
<h3 id="layout-params">Parameter Layout</h3>
<p>Atribut layout XML bernama <code>layout_<em>something</em></code> mendefinisikan
parameter layout View yang cocok untuk ViewGroup tempatnya berada.</p>
<p>Setiap kelas ViewGroup mengimplementasikan kelas tersarang yang memperluas {@link
android.view.ViewGroup.LayoutParams}. Subkelas ini
berisi tipe properti yang mendefinisikan ukuran dan posisi masing-masing tampilan anak, sebagaimana
mestinya untuk grup tampilan. Seperti yang bisa Anda lihat dalam gambar 1,
grup tampilan induk mendefinisikan parameter layout untuk masing-masing tampilan anak (termasuk grup tampilan anak).</p>
<img src="{@docRoot}images/layoutparams.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Visualisasi hierarki tampilan dengan parameter layout
yang dikaitkan dengan tiap tampilan.</p>
<p>Perhatikan bahwa setiap subkelas LayoutParams memiliki sintaksnya sendiri untuk menetapkan
nilai-nilai. Tiap elemen anak harus mendefinisikan LayoutParams yang semestinya bagi induknya,
meskipun elemen itu bisa juga mendefinisikan LayoutParams untuk anak-anaknya sendiri. </p>
<p>Semua grup tampilan berisi lebar dan tinggi (<code>layout_width</code> dan
<code>layout_height</code>), dan masing-masing tampilan harus mendefinisikannya. Banyak
LayoutParams yang juga menyertakan margin dan border opsional. <p>
<p>Anda bisa menetapkan lebar dan tinggi dengan ukuran persis, meskipun Anda mungkin
tidak ingin sering-sering melakukannya. Lebih sering, Anda akan menggunakan salah satu konstanta ini untuk
mengatur lebar atau tinggi: </p>
<ul>
<li><var>wrap_content</var> memberi tahu tampilan Anda agar menyesuaikan sendiri ukurannya dengan dimensi
yang dibutuhkan oleh isinya.</li>
<li><var>match_parent</var> (bernama <var>fill_parent</var> sebelum API Level 8)
memberi tahu tampilan Anda agar menjadi sebesar yang diperbolehkan oleh grup tampilan induknya.</li>
</ul>
<p>Secara umum, menetapkan lebar dan tinggi layout dengan satuan mutlak seperti
piksel tidaklah disarankan. Melainkan dengan menggunakan ukuran relatif seperti
satuan piksel yang tidak bergantung pada kerapatan (<var>dp</var>), <var>wrap_content</var>, atau
<var>match_parent</var>, adalah sebuah pendekatan yang lebih baik, karena membantu memastikan bahwa
aplikasi Anda akan ditampilkan dengan benar pada berbagai ukuran layar perangkat.
Tipe ukuran yang diterima didefinisikan dalam dokumen
<a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">
Sumber Daya yang Tersedia</a>.</p>
<h2 id="Position">Posisi Layout</h2>
<p>
Geometri tampilan adalah persegi panjang. Sebuah tampilan memiliki lokasi,
yang dinyatakan berupa sepasang koordinat <em>kiri</em> dan <em>atas</em>, dan
dua dimensi, yang dinyatakan berupa lebar dan tinggi. Satuan untuk lokasi
dan dimensi adalah piksel.
</p>
<p>
Lokasi tampilan dapat diambil dengan memanggil metode
{@link android.view.View#getLeft()} dan {@link android.view.View#getTop()}. Metode terdahulu menghasilkan koordinat kiri, atau X,
persegi panjang yang mewakili tampilan. Metode selanjutnya menghasilkan koordinat
atas, atau Y, persegi panjang yang mewakili tampilan. Kedua metode ini
menghasilkan lokasi tampilan relatif terhadap induknya. Misalnya,
bila <code>getLeft()</code> menghasilkan 20, berarti tampilan berlokasi 20 piksel ke
kanan dari tepi kiri induk langsungnya.
</p>
<p>
Selain itu, beberapa metode praktis ditawarkan untuk menghindari komputasi yang tidak perlu,
yakni {@link android.view.View#getRight()} dan {@link android.view.View#getBottom()}.
Kedua metode ini menghasilkan koordinat tepi kanan dan bawah
persegi panjang yang mewakili tampilan. Misalnya, memanggil {@link android.view.View#getRight()}
serupa dengan komputasi berikut: <code>getLeft() + getWidth()</code>.
</p>
<h2 id="SizePaddingMargins">Ukuran, Pengisi, dan Margin</h2>
<p>
Ukuran tampilan dinyatakan dengan lebar dan tinggi. Tampilan sebenarnya
memiliki dua pasang nilai lebar dan tinggi.
</p>
<p>
Sepasang pertama disebut <em>lebar terukur</em> dan
<em>tinggi terukur</em>. Dimensi ini mendefinisikan seberapa besar tampilan yang diinginkan
dalam induknya. Dimensi
terukur bisa diperoleh dengan memanggil {@link android.view.View#getMeasuredWidth()}
dan {@link android.view.View#getMeasuredHeight()}.
</p>
<p>
Sepasang kedua cukup disebut dengan <em>lebar</em> dan <em>tinggi</em>, atau
kadang-kadang <em>lebar penggambaran</em> dan <em>tinggi penggambaran</em>. Dimensi-dimensi ini
mendefinisikan ukuran tampilan sebenarnya pada layar, saat digambar dan
setelah layout. Nilai-nilai ini mungkin, namun tidak harus, berbeda dengan
lebar dan tinggi terukur. Lebar dan tinggi bisa diperoleh dengan memanggil
{@link android.view.View#getWidth()} dan {@link android.view.View#getHeight()}.
</p>
<p>
Untuk mengukur dimensinya, tampilan akan memperhitungkan pengisinya (padding). Pengisi
dinyatakan dalam piksel untuk bagian kiri, atas, kanan, dan bawah tampilan.
Pengisi bisa digunakan untuk meng-offset isi tampilan dengan
piksel dalam jumlah tertentu. Misalnya, pengisi kiri sebesar 2 akan mendorong isi tampilan sebanyak
2 piksel ke kanan dari tepi kiri. Pengisi bisa diatur menggunakan
metode {@link android.view.View#setPadding(int, int, int, int)} dan diketahui dengan memanggil
{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()},
{@link android.view.View#getPaddingRight()}, dan {@link android.view.View#getPaddingBottom()}.
</p>
<p>
Meskipun bisa mendefinisikan pengisi, tampilan tidak menyediakan dukungan untuk
margin. Akan tetapi, grup tampilan menyediakan dukungan tersebut. Lihat
{@link android.view.ViewGroup} dan
{@link android.view.ViewGroup.MarginLayoutParams} untuk informasi lebih jauh.
</p>
<p>Untuk informasi selengkapnya tentang dimensi, lihat
<a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">Nilai-Nilai Dimensi</a>.
</p>
<style type="text/css">
div.layout {
float:left;
width:200px;
margin:0 0 20px 20px;
}
div.layout.first {
margin-left:0;
clear:left;
}
</style>
<h2 id="CommonLayouts">Layout Umum</h2>
<p>Tiap subkelas dari kelas {@link android.view.ViewGroup} menyediakan cara unik untuk menampilkan
tampilan yang Anda sarangkan di dalamnya. Di bawah ini adalah beberapa tipe layout lebih umum yang dibuat
ke dalam platform Android.</p>
<p class="note"><strong>Catatan:</strong> Walaupun Anda bisa menyarangkan satu atau beberapa layout dalam
layout lain untuk mendapatkan desain UI, Anda harus berusaha menjaga hierarki layout sedangkal
mungkin. Layout Anda akan digambar lebih cepat jika memiliki layout tersarang yang lebih sedikit (hierarki tampilan yang melebar
lebih baik daripada hierarki tampilan yang dalam).</p>
<!--
<h2 id="framelayout">FrameLayout</h2>
<p>{@link android.widget.FrameLayout FrameLayout} is the simplest type of layout
object. It's basically a blank space on your screen that you can
later fill with a single object &mdash; for example, a picture that you'll swap in and out.
All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot
specify a different location for a child view. Subsequent child views will simply be drawn over
previous ones,
partially or totally obscuring them (unless the newer object is transparent).
</p>
-->
<div class="layout first">
<h4><a href="layout/linear.html">Layout Linier</a></h4>
<a href="layout/linear.html"><img src="{@docRoot}images/ui/linearlayout-small.png" alt="" /></a>
<p>Layout yang mengatur anak-anaknya menjadi satu baris horizontal atau vertikal. Layout ini
akan membuat scrollbar jika panjang jendela melebihi panjang layar.</p>
</div>
<div class="layout">
<h4><a href="layout/relative.html">Layout Relatif</a></h4>
<a href="layout/relative.html"><img src="{@docRoot}images/ui/relativelayout-small.png" alt="" /></a>
<p>Memungkinkan Anda menentukan lokasi objek anak relatif terhadap satu sama lain (anak A di
kiri anak B) atau terhadap induk (disejajarkan dengan atas induknya).</p>
</div>
<div class="layout">
<h4><a href="{@docRoot}guide/webapps/webview.html">Tampilan Web</a></h4>
<a href="{@docRoot}guide/webapps/webview.html"><img src="{@docRoot}images/ui/webview-small.png" alt="" /></a>
<p>Menampilkan halaman web.</p>
</div>
<h2 id="AdapterViews" style="clear:left">Membangun Layout dengan Adaptor</h2>
<p>Bila isi layout bersifat dinamis atau tidak dipastikan sebelumnya, Anda bisa menggunakan layout yang menjadi
subkelas {@link android.widget.AdapterView} untuk mengisi layout dengan tampilan saat runtime.
Subkelas dari kelas {@link android.widget.AdapterView} menggunakan {@link android.widget.Adapter} untuk
mengikat data ke layoutnya. {@link android.widget.Adapter} berfungsi sebagai penghubung antara sumber data
dan layout{@link android.widget.AdapterView}&mdash;{@link android.widget.Adapter}
menarik data (dari suatu sumber seperti larik (array) atau query database) dan mengubah setiap entri
menjadi tampilan yang bisa ditambahkan ke dalam layout {@link android.widget.AdapterView}.</p>
<p>Layout umum yang didukung oleh adaptor meliputi:</p>
<div class="layout first">
<h4><a href="layout/listview.html">Tampilan Daftar</a></h4>
<a href="layout/listview.html"><img src="{@docRoot}images/ui/listview-small.png" alt="" /></a>
<p>Menampilkan daftar kolom tunggal yang bergulir.</p>
</div>
<div class="layout">
<h4><a href="layout/gridview.html">Tampilan Petak</a></h4>
<a href="layout/gridview.html"><img src="{@docRoot}images/ui/gridview-small.png" alt="" /></a>
<p>Menampilkan petak bergulir yang terdiri atas kolom dan baris.</p>
</div>
<h3 id="FillingTheLayout" style="clear:left">Mengisi tampilan adaptor dengan data</h3>
<p>Anda bisa mengisi {@link android.widget.AdapterView} seperti {@link android.widget.ListView} atau
{@link android.widget.GridView} dengan mengikat instance {@link android.widget.AdapterView} ke
{@link android.widget.Adapter}, yang akan mengambil data dari sumber eksternal dan membuat {@link
android.view.View} yang mewakili tiap entri data.</p>
<p>Android menyediakan beberapa subkelas {@link android.widget.Adapter} yang berguna untuk
menarik berbagai jenis data dan membangun tampilan untuk {@link android.widget.AdapterView}. Dua
adaptor yang paling umum adalah:</p>
<dl>
<dt>{@link android.widget.ArrayAdapter}</dt>
<dd>Gunakan adaptor ini bila sumber data Anda berupa larik. Secara default, {@link
android.widget.ArrayAdapter} akan membuat tampilan untuk tiap elemen larik dengan memanggil {@link
java.lang.Object#toString()} pada tiap elemen dan menempatkan isinya dalam {@link
android.widget.TextView}.
<p>Misalnya, jika Anda memiliki satu larik string yang ingin ditampilkan dalam {@link
android.widget.ListView}, buatlah {@link android.widget.ArrayAdapter} baru dengan konstruktor
untuk menentukan layout setiap string dan larik string:</p>
<pre>
ArrayAdapter&lt;String> adapter = new ArrayAdapter&lt;String>(this,
android.R.layout.simple_list_item_1, myStringArray);
</pre>
<p>Argumen-argumen untuk konstruktor ini adalah:</p>
<ul>
<li>{@link android.content.Context} aplikasi Anda</li>
<li>Layout yang berisi {@link android.widget.TextView} untuk tiap string dalam larik</li>
<li>Larik string</li>
</ul>
<p>Kemudian tinggal panggil
{@link android.widget.ListView#setAdapter setAdapter()} pada {@link android.widget.ListView} Anda:</p>
<pre>
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
</pre>
<p>Untuk menyesuaikan penampilan setiap item, Anda bisa mengesampingkan metode {@link
java.lang.Object#toString()} bagi objek dalam larik Anda. Atau, untuk membuat tampilan tiap
elemen selain {@link android.widget.TextView} (misalnya, jika Anda menginginkan
{@link android.widget.ImageView} bagi setiap item larik), perluas kelas {@link
android.widget.ArrayAdapter} dan kesampingkan {@link android.widget.ArrayAdapter#getView
getView()} agar memberikan tipe tampilan yang Anda inginkan bagi tiap item.</p>
</dd>
<dt>{@link android.widget.SimpleCursorAdapter}</dt>
<dd>Gunakan adaptor ini bila data Anda berasal dari {@link android.database.Cursor}. Saat
menggunakan {@link android.widget.SimpleCursorAdapter}, Anda harus menentukan layout yang akan digunakan untuk tiap
baris dalam {@link android.database.Cursor} dan di kolom mana di {@link android.database.Cursor}
harus memasukkan tampilan layout. Misalnya, jika Anda ingin untuk membuat daftar
nama orang dan nomor telepon, Anda bisa melakukan query yang menghasilkan {@link
android.database.Cursor} yang berisi satu baris untuk tiap orang dan kolom-kolom untuk nama dan
nomor. Selanjutnya Anda membuat larik string yang menentukan kolom dari {@link
android.database.Cursor} yang Anda inginkan dalam layout untuk setiap hasil dan larik integer yang menentukan
tampilan yang sesuai untuk menempatkan masing-masing kolom:</p>
<pre>
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
</pre>
<p>Bila Anda membuat instance {@link android.widget.SimpleCursorAdapter}, teruskan layout yang akan digunakan untuk
setiap hasil, {@link android.database.Cursor} yang berisi hasil tersebut, dan dua larik ini:</p>
<pre>
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);
</pre>
<p>{@link android.widget.SimpleCursorAdapter} kemudian membuat tampilan untuk tiap baris dalam
{@link android.database.Cursor} dengan layout yang disediakan dengan memasukkan setiap item {@code
fromColumns} ke dalam tampilan {@code toViews} yang sesuai.</p></dd>
</dl>
<p>Jika, selama aplikasi berjalan, Anda mengubah data sumber yang dibaca oleh
adaptor, maka Anda harus memanggil {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. Hal ini akan
memberi tahu tampilan yang bersangkutan bahwa data telah berubah dan tampilan harus memperbarui dirinya sendiri.</p>
<h3 id="HandlingUserSelections">Menangani kejadian klik</h3>
<p>Anda bisa merespons kejadian klik pada setiap item dalam {@link android.widget.AdapterView} dengan
menerapkan antarmuka {@link android.widget.AdapterView.OnItemClickListener}. Misalnya:</p>
<pre>
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
// Do something in response to the click
}
};
listView.setOnItemClickListener(mMessageClickedHandler);
</pre>

View File

@@ -0,0 +1,798 @@
page.title=Dialog
page.tags=alertdialog,dialogfragment
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#DialogFragment">Membuat Fragmen Dialog</a></li>
<li><a href="#AlertDialog">Membuat Dialog Peringatan</a>
<ol>
<li><a href="#AddingButtons">Menambahkan tombol</a></li>
<li><a href="#AddingAList">Menambahkan daftar</a></li>
<li><a href="#CustomLayout">Membuat Layout Custom</a></li>
</ol>
</li>
<li><a href="#PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</a></li>
<li><a href="#ShowingADialog">Menampilkan Dialog</a></li>
<li><a href="#FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</a>
<ol>
<li><a href="#ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</a></li>
</ol>
</li>
<li><a href="#DismissingADialog">Menutup Dialog</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.DialogFragment}</li>
<li>{@link android.app.AlertDialog}</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li><a href="{@docRoot}design/building-blocks/dialogs.html">Panduan desain dialog</a></li>
<li><a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a> (dialog Tanggal/Waktu)</li>
</ol>
</div>
</div>
<p>Dialog adalah jendela kecil yang meminta pengguna untuk
membuat keputusan atau memasukkan informasi tambahan. Dialog tidak mengisi layar dan
biasanya digunakan untuk kejadian modal yang mengharuskan pengguna untuk melakukan tindakan sebelum bisa melanjutkan.</p>
<div class="note design">
<p><strong>Desain Dialog</strong></p>
<p>Untuk informasi tentang cara mendesain dialog, termasuk saran
untuk bahasa, bacalah panduan Desain <a href="{@docRoot}design/building-blocks/dialogs.html">dialog</a>.</p>
</div>
<img src="{@docRoot}images/ui/dialogs.png" />
<p>Kelas {@link android.app.Dialog} adalah kelas basis untuk dialog, namun Anda
harus menghindari pembuatan instance {@link android.app.Dialog} secara langsung.
Sebagai gantinya, gunakan salah satu subkelas berikut:</p>
<dl>
<dt>{@link android.app.AlertDialog}</dt>
<dd>Dialog yang bisa menampilkan judul, hingga tiga tombol, daftar
item yang dapat dipilih, atau layout custom.</dd>
<dt>{@link android.app.DatePickerDialog} atau {@link android.app.TimePickerDialog}</dt>
<dd>Dialog berisi UI yang sudah didefinisikan dan memungkinkan pengguna memilih tanggal atau waktu.</dd>
</dl>
<div class="sidebox">
<h2>Hindari ProgressDialog</h2>
<p>Android menyertakan kelas dialog lain yang disebut
{@link android.app.ProgressDialog} yang menampilkan dialog berisi progress-bar. Akan tetapi, jika Anda
perlu menunjukkan kemajuan pemuatan ataupun kemajuan yang tidak pasti, maka Anda harus mengikuti
panduan desain untuk <a href="{@docRoot}design/building-blocks/progress.html">Kemajuan &amp;
Aktivitas</a> dan menggunakan {@link android.widget.ProgressBar} dalam layout Anda.</p>
</div>
<p>Kelas-kelas ini mendefinisikan gaya dan struktur dialog Anda, namun Anda harus
menggunakan {@link android.support.v4.app.DialogFragment} sebagai kontainer dialog Anda.
Kelas {@link android.support.v4.app.DialogFragment} menyediakan semua kontrol yang Anda
perlukan untuk membuat dialog dan mengelola penampilannya, sebagai ganti memanggil metode
pada objek {@link android.app.Dialog}.</p>
<p>Menggunakan {@link android.support.v4.app.DialogFragment} untuk mengelola dialog
akan memastikan bahwa kelas itu menangani kejadian daur hidup
dengan benar seperti ketika pengguna menekan tombol <em>Back</em> atau memutar layar. Kelas {@link
android.support.v4.app.DialogFragment} juga memungkinkan Anda menggunakan ulang dialog UI sebagai
komponen yang bisa ditanamkan dalam UI yang lebih besar, persis seperti {@link
android.support.v4.app.Fragment} tradisional (seperti saat Anda ingin dialog UI muncul berbeda
pada layar besar dan kecil).</p>
<p>Bagian-bagian berikutnya dalam panduan ini akan menjelaskan cara menggunakan {@link
android.support.v4.app.DialogFragment} yang dikombinasikan dengan objek {@link android.app.AlertDialog}
. Jika Anda ingin membuat picker tanggal atau waktu, Anda harus membaca panduan
<a href="{@docRoot}guide/topics/ui/controls/pickers.html">Picker</a>.</p>
<p class="note"><strong>Catatan:</strong>
Karena kelas {@link android.app.DialogFragment} mulanya ditambahkan pada
Android 3.0 (API level 11), dokumen ini menjelaskan cara menggunakan kelas {@link
android.support.v4.app.DialogFragment} yang disediakan bersama <a href="{@docRoot}tools/support-library/index.html">Pustaka Dukungan</a>. Dengan menambahkan pustaka ini
ke aplikasi, Anda bisa menggunakan {@link android.support.v4.app.DialogFragment} dan berbagai
API lain pada perangkat yang menjalankan Android 1.6 atau yang lebih tinggi. Jika versi minimum yang didukung aplikasi Anda
adalah API level 11 atau yang lebih tinggi, maka Anda bisa menggunakan versi kerangka kerja {@link
android.app.DialogFragment}, namun ketahuilah bahwa tautan dalam dokumen ini adalah untuk API
pustaka dukungan. Saat menggunakan pustaka dukungan,
pastikan Anda mengimpor kelas <code>android.support.v4.app.DialogFragment</code>
dan <em>bukan</em> <code>android.app.DialogFragment</code>.</p>
<h2 id="DialogFragment">Membuat Fragmen Dialog</h2>
<p>Anda bisa menghasilkan beragam rancangan dialog&mdash;termasuk
layout custom dan desain yang dijelaskan dalam panduan desain <a href="{@docRoot}design/building-blocks/dialogs.html">Dialog</a>
&mdash;dengan memperluas
{@link android.support.v4.app.DialogFragment} dan membuat {@link android.app.AlertDialog}
dalam metode callback {@link android.support.v4.app.DialogFragment#onCreateDialog
onCreateDialog()}.</p>
<p>Misalnya, berikut ini sebuah {@link android.app.AlertDialog} dasar yang dikelola dalam
{@link android.support.v4.app.DialogFragment}:</p>
<pre>
public class FireMissilesDialogFragment extends DialogFragment {
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
</pre>
<div class="figure" style="width:290px;margin:0 0 0 20px">
<img src="{@docRoot}images/ui/dialog_buttons.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong>
Dialog dengan satu pesan dan dua tombol tindakan.</p>
</div>
<p>Sekarang, bila Anda membuat instance kelas ini dan memanggil {@link
android.support.v4.app.DialogFragment#show show()} pada objek itu, dialog akan muncul seperti
yang ditampilkan dalam gambar 1.</p>
<p>Bagian berikutnya menjelaskan lebih jauh tentang penggunaan API {@link android.app.AlertDialog.Builder}
untuk membuat dialog.</p>
<p>Bergantung pada seberapa rumit dialog tersebut, Anda bisa menerapkan berbagai metode callback lain
dalam {@link android.support.v4.app.DialogFragment}, termasuk semua
<a href="{@docRoot}guide/components/fragments.html#Lifecycle">metode daur hidup fragmen</a> dasar.
<h2 id="AlertDialog">Membuat Dialog Peringatan</h2>
<p>Kelas {@link android.app.AlertDialog} memungkinkan Anda membuat berbagai desain dialog dan
seringkali satu-satunya kelas dialog yang akan Anda perlukan.
Seperti yang ditampilkan dalam gambar 2, ada tiga area pada dialog peringatan:</p>
<div class="figure" style="width:311px;margin-top:0">
<img src="{@docRoot}images/ui/dialogs_regions.png" alt="" style="margin-bottom:0" />
<p class="img-caption"><strong>Gambar 2.</strong> Layout dialog.</p>
</div>
<ol>
<li><b>Judul</b>
<p>Area ini opsional dan hanya boleh digunakan bila area konten
ditempati oleh pesan terperinci, daftar, atau layout custom. Jika Anda perlu menyatakan
pesan atau pertanyaan sederhana (seperti dialog dalam gambar 1), Anda tidak memerlukan judul.</li>
<li><b>Area konten</b>
<p>Area ini bisa menampilkan pesan, daftar, atau layout custom lainnya.</p></li>
<li><b>Tombol tindakan</b>
<p>Tidak boleh ada lebih dari tiga tombol tindakan dalam sebuah dialog.</p></li>
</ol>
<p>Kelas {@link android.app.AlertDialog.Builder}
menyediakan API yang memungkinkan Anda membuat {@link android.app.AlertDialog}
dengan jenis konten ini, termasuk layout custom.</p>
<p>Untuk membuat {@link android.app.AlertDialog}:</p>
<pre>
<b>// 1. Instantiate an {@link android.app.AlertDialog.Builder} with its constructor</b>
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
<b>// 2. Chain together various setter methods to set the dialog characteristics</b>
builder.setMessage(R.string.dialog_message)
.setTitle(R.string.dialog_title);
<b>// 3. Get the {@link android.app.AlertDialog} from {@link android.app.AlertDialog.Builder#create()}</b>
AlertDialog dialog = builder.create();
</pre>
<p>Topik-topik selanjutnya menampilkan cara mendefinisikan berbagai atribut dialog dengan menggunakan
kelas {@link android.app.AlertDialog.Builder}.</p>
<h3 id="AddingButtons">Menambahkan tombol</h3>
<p>Untuk menambahkan tombol tindakan seperti dalam gambar 2,
panggil metode {@link android.app.AlertDialog.Builder#setPositiveButton setPositiveButton()} dan
{@link android.app.AlertDialog.Builder#setNegativeButton setNegativeButton()}:</p>
<pre style="clear:right">
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Add the buttons
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked OK button
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Set other dialog properties
...
// Create the AlertDialog
AlertDialog dialog = builder.create();
</pre>
<p>Metode <code>set...Button()</code> mengharuskan adanya judul bagi tombol (disediakan
oleh suatu <a href="{@docRoot}guide/topics/resources/string-resource.html">sumber daya string</a>) dan
{@link android.content.DialogInterface.OnClickListener} yang mendefinisikan tindakan yang diambil
bila pengguna menekan tombol.</p>
<p>Ada tiga macam tombol tindakan yang Anda bisa tambahkan:</p>
<dl>
<dt>Positif</dt>
<dd>Anda harus menggunakan tipe ini untuk menerima dan melanjutkan tindakan (tindakan "OK").</dd>
<dt>Negatif</dt>
<dd>Anda harus menggunakan tipe ini untuk membatalkan tindakan.</dd>
<dt>Netral</dt>
<dd>Anda harus menggunakan tipe ini bila pengguna mungkin tidak ingin melanjutkan tindakan,
namun tidak ingin membatalkan. Tipe ini muncul antara tombol positif dan
tombol negatif. Misalnya, tindakan bisa berupa "Ingatkan saya nanti".</dd>
</dl>
<p>Anda hanya bisa menambahkan salah satu tipe tombol ke {@link
android.app.AlertDialog}. Artinya, Anda tidak bisa memiliki lebih dari satu tombol "positif".</p>
<div class="figure" style="width:290px;margin:0 0 0 40px">
<img src="{@docRoot}images/ui/dialog_list.png" alt="" />
<p class="img-caption"><strong>Gambar 3.</strong>
Dialog dengan satu judul dan daftar.</p>
</div>
<h3 id="AddingAList">Menambahkan daftar</h3>
<p>Ada tiga macam daftar yang tersedia pada API {@link android.app.AlertDialog}:</p>
<ul>
<li>Daftar pilihan tunggal biasa</li>
<li>Daftar pilihan tunggal persisten (tombol radio)</li>
<li>Daftar pilihan ganda persisten (kotak cek)</li>
</ul>
<p>Untuk membuat daftar pilihan tunggal seperti dalam gambar 3,
gunakan metode {@link android.app.AlertDialog.Builder#setItems setItems()}:</p>
<pre style="clear:right">
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_color)
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// The 'which' argument contains the index position
// of the selected item
}
});
return builder.create();
}
</pre>
<p>Karena daftar muncul dalam area konten dialog,
dialog tidak bisa menampilkan pesan dan daftar sekaligus dan Anda harus menetapkan judul untuk
dialog dengan {@link android.app.AlertDialog.Builder#setTitle setTitle()}.
Untuk menentukan item daftar, panggil {@link
android.app.AlertDialog.Builder#setItems setItems()}, dengan meneruskan larik.
Atau, Anda bisa menetapkan daftar menggunakan {@link
android.app.AlertDialog.Builder#setAdapter setAdapter()}. Hal ini memungkinkan Anda mendukung daftar
dengan data dinamis (seperti dari database) dengan menggunakan {@link android.widget.ListAdapter}.</p>
<p>Jika Anda memilih untuk mendukung daftar dengan {@link android.widget.ListAdapter},
selalu gunakan sebuah {@link android.support.v4.content.Loader} agar konten dimuat
secara asinkron. Hal ini dijelaskan lebih jauh dalam panduan
<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Membuat Layout
dengan Adaptor</a> dan <a href="{@docRoot}guide/components/loaders.html">Loader</a>
.</p>
<p class="note"><strong>Catatan:</strong> Secara default, menyentuh sebuah item daftar akan menutup dialog,
kecuali Anda menggunakan salah satu daftar pilihan persisten berikut ini.</p>
<div class="figure" style="width:290px;margin:-30px 0 0 40px">
<img src="{@docRoot}images/ui/dialog_checkboxes.png" />
<p class="img-caption"><strong>Gambar 4.</strong>
Daftar item pilihan ganda.</p>
</div>
<h4 id="Checkboxes">Menambahkan daftar pilihan ganda atau pilihan tunggal persisten</h4>
<p>Untuk menambahkan daftar item pilihan ganda (kotak cek) atau
item pilihan tunggal (tombol radio), gunakan masing-masing metode
{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String,
DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()}, atau
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
setSingleChoiceItems()}.</p>
<p>Misalnya, berikut ini cara membuat daftar pilihan ganda seperti
yang ditampilkan dalam gambar 4 yang menyimpan item
yang dipilih dalam {@link java.util.ArrayList}:</p>
<pre style="clear:right">
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mSelectedItems = new ArrayList(); // Where we track the selected items
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Set the dialog title
builder.setTitle(R.string.pick_toppings)
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(R.array.toppings, null,
new DialogInterface.OnMultiChoiceClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
mSelectedItems.add(which);
} else if (mSelectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int id) {
// User clicked OK, so save the mSelectedItems results somewhere
// or return them to the component that opened the dialog
...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int id) {
...
}
});
return builder.create();
}
</pre>
<p>Walaupun daftar tradisional maupun daftar dengan tombol radio
menyediakan tindakan "pilihan tunggal", Anda harus menggunakan {@link
android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
setSingleChoiceItems()} jika ingin mempertahankan pilihan pengguna.
Yakni, jika nanti membuka dialog lagi untuk menunjukkan pilihan pengguna,
maka Anda perlu membuat daftar dengan tombol radio.</p>
<h3 id="CustomLayout">Membuat Layout Custom</h3>
<div class="figure" style="width:290px;margin:-30px 0 0 40px">
<img src="{@docRoot}images/ui/dialog_custom.png" alt="" />
<p class="img-caption"><strong>Gambar 5.</strong> Layout dialog custom.</p>
</div>
<p>Jika Anda menginginkan layout custom dalam dialog, buatlah layout dan tambahkan ke
{@link android.app.AlertDialog} dengan memanggil {@link
android.app.AlertDialog.Builder#setView setView()} pada objek {@link
android.app.AlertDialog.Builder} Anda.</p>
<p>Secara default, layout custom akan mengisi jendela dialog, namun Anda masih bisa
menggunakan metode {@link android.app.AlertDialog.Builder} untuk menambahkan tombol dan judul.</p>
<p>Misalnya, berikut ini adalah file layout untuk dialog dalam Gambar 5:</p>
<p style="clear:right" class="code-caption">res/layout/dialog_signin.xml</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
&lt;ImageView
android:src="@drawable/header_logo"
android:layout_width="match_parent"
android:layout_height="64dp"
android:scaleType="center"
android:background="#FFFFBB33"
android:contentDescription="@string/app_name" />
&lt;EditText
android:id="@+id/username"
android:inputType="textEmailAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
android:hint="@string/username" />
&lt;EditText
android:id="@+id/password"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="16dp"
android:fontFamily="sans-serif"
android:hint="@string/password"/>
&lt;/LinearLayout>
</pre>
<p class="note"><strong>Tip:</strong> Secara default, bila Anda telah mengatur sebuah elemen {@link android.widget.EditText}
agar menggunakan tipe input {@code "textPassword"}, keluarga font akan diatur ke spasi tunggal, sehingga
Anda harus mengubah keluarga font ke {@code "sans-serif"} sehingga kedua bidang teks menggunakan
gaya font yang cocok.</p>
<p>Untuk memekarkan layout dalam {@link android.support.v4.app.DialogFragment} Anda,
ambillah {@link android.view.LayoutInflater} dengan
{@link android.app.Activity#getLayoutInflater()} dan panggil
{@link android.view.LayoutInflater#inflate inflate()}, dengan parameter pertama
adalah ID sumber daya layout dan parameter kedua adalah tampilan induk untuk layout.
Selanjutnya Anda bisa memanggil {@link android.app.AlertDialog#setView setView()}
untuk menempatkan layout dalam dialog.</p>
<pre>
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.dialog_signin, null))
// Add action buttons
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
&#64;Override
public void onClick(DialogInterface dialog, int id) {
// sign in the user ...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
LoginDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
}
</pre>
<div class="note">
<p><strong>Tip:</strong> Jika Anda menginginkan dialog custom,
Anda bisa menampilkan {@link android.app.Activity} sebagai dialog
daripada menggunakan API {@link android.app.Dialog}. Cukup buat satu aktivitas dan mengatur temanya ke
{@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog}
di elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a>:</p>
<pre>
&lt;activity android:theme="&#64;android:style/Theme.Holo.Dialog" >
</pre>
<p>Demikian saja. Aktivitas sekarang ditampilkan dalam jendela dialog, sebagai ganti layar penuh.</p>
</div>
<h2 id="PassingEvents">Meneruskan Kejadian Kembali ke Host Dialog</h2>
<p>Bila pengguna menyentuh salah satu tombol tindakan dialog atau memilih satu item dari daftarnya,
{@link android.support.v4.app.DialogFragment} Anda bisa melakukan sendiri tindakan yang diperlukan
, namun sering kali Anda perlu mengirim kejadian itu ke aktivitas atau fragmen yang
membuka dialog. Caranya, definisikan antarmuka dengan sebuah metode untuk masing-masing tipe kejadian klik.
Lalu implementasikan antarmuka itu dalam komponen host yang akan
menerima kejadian tindakan dari dialog.</p>
<p>Misalnya, berikut ini adalah {@link android.support.v4.app.DialogFragment} yang mendefinisikan
antarmuka yang akan digunakan untuk mengirim kembali suatu kejadian ke aktivitas host:</p>
<pre>
public class NoticeDialogFragment extends DialogFragment {
/* The activity that creates an instance of this dialog fragment must
* implement this interface in order to receive event callbacks.
* Each method passes the DialogFragment in case the host needs to query it. */
public interface NoticeDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
}
// Use this instance of the interface to deliver action events
NoticeDialogListener mListener;
// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
&#64;Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Verify that the host activity implements the callback interface
try {
// Instantiate the NoticeDialogListener so we can send events to the host
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
}
...
}
</pre>
<p>Aktivitas yang menjadi host dialog tersebut akan membuat instance dialog
dengan konstruktor fragmen dialog dan menerima kejadian dialog
melalui implementasi antarmuka {@code NoticeDialogListener}:</p>
<pre>
public class MainActivity extends FragmentActivity
implements NoticeDialogFragment.NoticeDialogListener{
...
public void showNoticeDialog() {
// Create an instance of the dialog fragment and show it
DialogFragment dialog = new NoticeDialogFragment();
dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
}
// The dialog fragment receives a reference to this Activity through the
// Fragment.onAttach() callback, which it uses to call the following methods
// defined by the NoticeDialogFragment.NoticeDialogListener interface
&#64;Override
public void onDialogPositiveClick(DialogFragment dialog) {
// User touched the dialog's positive button
...
}
&#64;Override
public void onDialogNegativeClick(DialogFragment dialog) {
// User touched the dialog's negative button
...
}
}
</pre>
<p>Karena aktivitas host mengimplementasikan {@code NoticeDialogListener}&mdash;yang
diberlakukan oleh metode callback {@link android.support.v4.app.Fragment#onAttach onAttach()}
di atas,&mdash;fragmen dialog bisa menggunakan
metode callback antarmuka untuk mengirimkan kejadian klik ke aktivitas:</p>
<pre>
public class NoticeDialogFragment extends DialogFragment {
...
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Build the dialog and set up the button click handlers
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the positive button event back to the host activity
mListener.onDialogPositiveClick(NoticeDialogFragment.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Send the negative button event back to the host activity
mListener.onDialogNegativeClick(NoticeDialogFragment.this);
}
});
return builder.create();
}
}
</pre>
<h2 id="ShowingADialog">Menampilkan Dialog</h2>
<p>Bila Anda ingin menampilkan dialog, buatlah instance {@link
android.support.v4.app.DialogFragment} dan panggil {@link android.support.v4.app.DialogFragment#show
show()}, dengan meneruskan {@link android.support.v4.app.FragmentManager} dan nama tag
untuk fragmen dialognya.</p>
<p>Anda bisa mendapatkan {@link android.support.v4.app.FragmentManager} dengan memanggil
{@link android.support.v4.app.FragmentActivity#getSupportFragmentManager()} dari
{@link android.support.v4.app.FragmentActivity} atau {@link
android.support.v4.app.Fragment#getFragmentManager()} dari {@link
android.support.v4.app.Fragment}. Misalnya:</p>
<pre>
public void confirmFireMissiles() {
DialogFragment newFragment = new FireMissilesDialogFragment();
newFragment.show(getSupportFragmentManager(), "missiles");
}
</pre>
<p>Argumen kedua, {@code "missiles"}, adalah nama tag unik yang digunakan sistem untuk menyimpan
dan memulihkan status fragmen bila diperlukan. Tag ini juga memungkinkan Anda mendapatkan handle ke
fragmen dengan memanggil {@link android.support.v4.app.FragmentManager#findFragmentByTag
findFragmentByTag()}.</p>
<h2 id="FullscreenDialog">Menampilkan Dialog sebagai Layar Penuh atau Fragmen Tertanam</h2>
<p>Anda mungkin memiliki desain UI yang di dalamnya Anda ingin UI muncul sebagai dialog dalam beberapa
situasi, namun sebagai layar penuh atau fragmen tertanam dalam situasi lain (mungkin bergantung pada apakah
perangkat memiliki layar besar atau layar kecil). Kelas {@link android.support.v4.app.DialogFragment}
menawarkan fleksibilitas ini karena masih bisa berperilaku sebagai {@link
android.support.v4.app.Fragment} yang bisa ditanamkan.</p>
<p>Akan tetapi, dalam hal ini Anda tidak bisa menggunakan {@link android.app.AlertDialog.Builder AlertDialog.Builder}
atau objek {@link android.app.Dialog} lain untuk membangun dialog. Jika
Anda ingin {@link android.support.v4.app.DialogFragment}
bisa ditanamkan, Anda harus mendefinisikan dialog UI dalam layout, lalu memuat layout itu dalam metode callback
{@link android.support.v4.app.DialogFragment#onCreateView
onCreateView()}.</p>
<p>Berikut ini adalah contoh {@link android.support.v4.app.DialogFragment} yang bisa muncul sebagai
dialog maupun fragmen yang bisa ditanamkan (menggunakan layout bernama <code>purchase_items.xml</code>):</p>
<pre>
public class CustomDialogFragment extends DialogFragment {
/** The system calls this to get the DialogFragment's layout, regardless
of whether it's being displayed as a dialog or an embedded fragment. */
&#64;Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout to use as dialog or embedded fragment
return inflater.inflate(R.layout.purchase_items, container, false);
}
/** The system calls this only when creating the layout in a dialog. */
&#64;Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// The only reason you might override this method when using onCreateView() is
// to modify any dialog characteristics. For example, the dialog includes a
// title by default, but your custom layout might not need it. So here you can
// remove the dialog title, but you must call the superclass to get the Dialog.
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
}
</pre>
<p>Dan berikut ini adalah beberapa kode yang memutuskan apakah akan menampilkan fragmen sebagai dialog
atau UI layar penuh, berdasarkan ukuran layar:</p>
<pre>
public void showDialog() {
FragmentManager fragmentManager = getSupportFragmentManager();
CustomDialogFragment newFragment = new CustomDialogFragment();
if (mIsLargeLayout) {
// The device is using a large layout, so show the fragment as a dialog
newFragment.show(fragmentManager, "dialog");
} else {
// The device is smaller, so show the fragment fullscreen
FragmentTransaction transaction = fragmentManager.beginTransaction();
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction.add(android.R.id.content, newFragment)
.addToBackStack(null).commit();
}
}
</pre>
<p>Untuk informasi selengkapnya tentang melakukan transaksi fragmen, lihat panduan
<a href="{@docRoot}guide/components/fragments.html">Fragmen</a>.</p>
<p>Dalam contoh ini, nilai boolean <code>mIsLargeLayout</code> menentukan apakah perangkat saat ini
harus menggunakan desain layout besar aplikasi (dan dengan demikian menampilkan fragmen ini sebagai dialog, bukan
layar penuh). Cara terbaik untuk mengatur jenis boolean ini adalah mendeklarasikan
<a href="{@docRoot}guide/topics/resources/more-resources.html#Bool">nilai sumber daya boolean</a>
dengan nilai <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">sumber daya alternatif</a> untuk berbagai ukuran layar. Misalnya, berikut ini adalah dua
versi sumber daya boolean untuk berbagai ukuran layar:</p>
<p class="code-caption">res/values/bools.xml</p>
<pre>
&lt;!-- Default boolean values -->
&lt;resources>
&lt;bool name="large_layout">false&lt;/bool>
&lt;/resources>
</pre>
<p class="code-caption">res/values-large/bools.xml</p>
<pre>
&lt;!-- Large screen boolean values -->
&lt;resources>
&lt;bool name="large_layout">true&lt;/bool>
&lt;/resources>
</pre>
<p>Selanjutnya Anda bisa menetapkan nilai {@code mIsLargeLayout} selama
metode {@link android.app.Activity#onCreate onCreate()} aktivitas:</p>
<pre>
boolean mIsLargeLayout;
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
}
</pre>
<h3 id="ActivityAsDialog">Menampilkan aktivitas sebagai dialog pada layar besar</h3>
<p>Sebagai ganti menampilkan dialog berupa UI layar penuh saat di layar kecil, Anda bisa memperoleh
hasil yang sama dengan menampilkan {@link android.app.Activity} sebagai dialog saat di
layar besar. Pendekatan yang Anda pilih bergantung pada desain aplikasi, namun
menampilkan aktivitas sebagai dialog sering kali berguna bila aplikasi Anda sudah didesain untuk
layar kecil dan Anda ingin meningkatkan pengalaman pada tablet dengan menampilkan aktivitas berjangka pendek
sebagai dialog.</p>
<p>Untuk menampilkan aktivitas sebagai dialog hanya saat di layar besar,
terapkan tema {@link android.R.style#Theme_Holo_DialogWhenLarge Theme.Holo.DialogWhenLarge}
pada elemen manifes <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a>:</p>
<pre>
&lt;activity android:theme="&#64;android:style/Theme.Holo.DialogWhenLarge" >
</pre>
<p>Untuk informasi selengkapnya tentang mengatur gaya aktivitas Anda dengan tema, lihat panduan <a href="{@docRoot}guide/topics/ui/themes.html">Gaya dan Tema</a>.</p>
<h2 id="DismissingADialog">Menutup Dialog</h2>
<p>Bila pengguna menyentuh salah satu tombol tindakan yang dibuat dengan
{@link android.app.AlertDialog.Builder}, sistem akan menutup dialog untuk Anda.</p>
<p>Sistem juga menutup dialog bila pengguna menyentuh sebuah item dalam daftar dialog, kecuali
bila daftar itu menggunakan tombol radio atau kotak cek. Jika tidak, Anda bisa menutup dialog secara manual
dengan memanggil {@link android.support.v4.app.DialogFragment#dismiss()} pada {@link
android.support.v4.app.DialogFragment} Anda.</p>
<p>Jika Anda perlu melakukan
tindakan tertentu saat dialog menghilang, Anda bisa menerapkan metode {@link
android.support.v4.app.DialogFragment#onDismiss onDismiss()} dalam {@link
android.support.v4.app.DialogFragment} Anda.</p>
<p>Anda juga bisa <em>membatalkan</em> dialog. Ini merupakan kejadian khusus yang menunjukkan bahwa pengguna
secara eksplisit meninggalkan dialog tanpa menyelesaikan tugas. Hal ini terjadi jika pengguna menekan tombol
<em>Back</em>, menyentuh layar di luar area dialog,
atau jika Anda secara eksplisit memanggil {@link android.app.Dialog#cancel()} pada {@link
android.app.Dialog} (seperti saat merespons tombol "Cancel" dalam dialog).</p>
<p>Seperti yang ditampilkan dalam contoh di atas, Anda bisa merespons kejadian batal dengan menerapkan
{@link android.support.v4.app.DialogFragment#onCancel onCancel()} dalam kelas {@link
android.support.v4.app.DialogFragment} Anda.</p>
<p class="note"><strong>Catatan:</strong> Sistem akan memanggil
{@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} pada tiap kejadian yang
memanggil callback {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Akan tetapi,
jika Anda memanggil {@link android.app.Dialog#dismiss Dialog.dismiss()} atau {@link
android.support.v4.app.DialogFragment#dismiss DialogFragment.dismiss()},
sistem akan memanggil {@link android.support.v4.app.DialogFragment#onDismiss onDismiss()} <em>namun
bukan</em> {@link android.support.v4.app.DialogFragment#onCancel onCancel()}. Jadi biasanya Anda harus
memanggil {@link android.support.v4.app.DialogFragment#dismiss dismiss()} bila pengguna menekan tombol
<em>positif</em> dalam dialog untuk menghilangkan tampilan dialog.</p>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,979 @@
page.title=Pemberitahuan
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#Design">Pertimbangan Desain</a></li>
<li><a href="#CreateNotification">Membuat Pemberitahuan</a>
<ol>
<li><a href="#Required">Isi pemberitahuan yang diperlukan</a></li>
<li><a href="#Optional">Isi dan pengaturan pemberitahuan opsional</a></li>
<li><a href="#Actions">Tindakan pemberitahuan</a></li>
<li><a href="#Priority">Prioritas pemberitahuan</a></li>
<li><a href="#SimpleNotification">Membuat pemberitahuan sederhana</a></li>
<li><a href="#ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</a></li>
<li><a href="#Compatibility">Menangani kompatibilitas</a></li>
</ol>
</li>
<li><a href="#Managing">Mengelola Pemberitahuan</a>
<ol>
<li><a href="#Updating">Memperbarui pemberitahuan</a></li>
<li><a href="#Removing">Menghapus pemberitahuan</a></li>
</ol>
</li>
<li><a href="#NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</a>
<ol>
<li><a href="#DirectEntry">Menyiapkan PendingIntent aktivitas biasa</a></li>
<li><a href="#ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</a></li>
</ol>
</li>
<li><a href="#Progress">Menampilkan Kemajuan dalam Pemberitahuan</a>
<ol>
<li><a href="#FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</a></li>
<li><a href="#ActivityIndicator">Menampilkan indikator aktivitas berlanjut</a></li>
</ol>
</li>
<li><a href="#metadata">Metadata Pemberitahuan</a></li>
<li><a href="#Heads-up">Pemberitahuan Pendahuluan</a></li>
<li><a href="#lockscreenNotification">Pemberitahuan Layar Kunci</a></li>
<ol>
<li><a href="#visibility">Mengatur Visibilitas</a></li>
<li><a href="#controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</a></li>
</ol>
<li><a href="#CustomNotification">Layout Pemberitahuan Custom</a></li>
</ol>
<h2>Kelas-kelas utama</h2>
<ol>
<li>{@link android.app.NotificationManager}</li>
<li>{@link android.support.v4.app.NotificationCompat}</li>
</ol>
<h2>Video</h2>
<ol>
<li>
<a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&amp;feature=player_detailpage#t=1672s">
Pemberitahuan di 4.1</a>
</li>
</ol>
<h2>Lihat juga</h2>
<ol>
<li>
<a href="{@docRoot}design/patterns/notifications.html">Desain Android: Pemberitahuan</a>
</li>
</ol>
</div>
</div>
<p>
Pemberitahuan adalah pesan yang bisa Anda tampilkan kepada pengguna di luar
UI normal aplikasi. Bila Anda memberi tahu sistem untuk mengeluarkan pemberitahuan, pemberitahuan akan muncul lebih dahulu sebagai ikon dalam
<strong>area pemberitahuan</strong>. Untuk melihat detail pemberitahuan, pengguna membuka
<strong>laci pemberitahuan</strong>. Baik area pemberitahuan maupun laci pemberitahuan
adalah area-area yang dikontrol sistem yang bisa dilihat pengguna kapan saja.
</p>
<img id="figure1" src="{@docRoot}images/ui/notifications/notification_area.png" height="" alt="" />
<p class="img-caption">
<strong>Gambar 1.</strong> Pemberitahuan di area pemberitahuan.
</p>
<img id="figure2" src="{@docRoot}images/ui/notifications/notification_drawer.png" width="280px" alt="" />
<p class="img-caption">
<strong>Gambar 2.</strong> Pemberitahuan di laci pemberitahuan.
</p>
<p class="note"><strong>Catatan:</strong> Kecuali disebutkan, panduan ini mengacu pada
kelas {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}
dalam <a href="{@docRoot}tools/support-library/index.html">Support Library</a> versi 4.
Kelas {@link android.app.Notification.Builder Notification.Builder} telah ditambahkan pada Android
3.0 (API level 11).</p>
<h2 id="Design">Pertimbangan Desain</h2>
<p>Pemberitahuan, sebagai bagian penting dari antarmuka pengguna Android, memiliki panduan desainnya sendiri.
Perubahan desain materi yang diperkenalkan dalam Android 5.0 (API level 21) adalah sangat
penting, dan Anda harus meninjau pelatihan <a href="{@docRoot}training/material/index.html">Desain Bahan</a>
untuk informasi selengkapnya. Untuk mengetahui cara mendesain pemberitahuan dan interaksinya, bacalah panduan desain
<a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.</p>
<h2 id="CreateNotification">Membuat Pemberitahuan</h2>
<p>Anda menetapkan informasi dan tindakan UI bagi pemberitahuan dalam
objek {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
Untuk membuat pemberitahuan itu sendiri, panggil
{@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()},
yang akan mengembalikan objek {@link android.app.Notification} berisi spesifikasi Anda. Untuk mengeluarkan
pemberitahuan, Anda meneruskan objek {@link android.app.Notification} ke sistem dengan memanggil
{@link android.app.NotificationManager#notify NotificationManager.notify()}.</p>
<h3 id="Required">Isi pemberitahuan yang diperlukan</h3>
<p>
Objek {@link android.app.Notification} <em>harus</em> berisi yang berikut ini:
</p>
<ul>
<li>
Ikon kecil, yang diatur dengan
{@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
</li>
<li>
Judul, yang diatur dengan
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
</li>
<li>
Teks detail, yang diatur dengan
{@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
</li>
</ul>
<h3 id="Optional">Isi dan pengaturan pemberitahuan opsional</h3>
<p>
Semua isi dan pengaturan pemberitahuan lainnya bersifat opsional. Untuk mengetahui selengkapnya tentang semua itu,
lihat dokumentasi acuan untuk {@link android.support.v4.app.NotificationCompat.Builder}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Actions">Tindakan pemberitahuan</h3>
<p>
Walaupun bersifat opsional, Anda harus menambahkan setidaknya satu tindakan pada pemberitahuan.
Tindakan memungkinkan pengguna beralih langsung dari pemberitahuan ke
{@link android.app.Activity} dalam aplikasi Anda, tempat pengguna bisa melihat satu atau beberapa kejadian
atau melakukan pekerjaan lebih jauh.
</p>
<p>
Pemberitahuan bisa menyediakan beberapa tindakan sekaligus. Anda harus selalu mendefinisikan tindakan yang
akan diaktifkan bila pengguna mengklik pemberitahuan; biasanya tindakan ini akan membuka
{@link android.app.Activity} dalam aplikasi Anda. Anda juga bisa menambahkan tombol pada pemberitahuan
yang melakukan tindakan tambahan seperti mendiamkan alarm atau segera merespons
pesan teks; fitur ini tersedia mulai Android 4.1. Jika menggunakan tombol tindakan tambahan, Anda
juga harus membuat fungsionalitasnya tersedia dalam {@link android.app.Activity} di aplikasi Anda; lihat
bagian <a href="#Compatibility">Menangani kompatibilitas</a> untuk detail selengkapnya.
</p>
<p>
Dalam {@link android.app.Notification}, tindakan itu sendiri didefinisikan oleh
{@link android.app.PendingIntent} berisi
{@link android.content.Intent} yang memulai
{@link android.app.Activity} dalam aplikasi Anda. Untuk mengaitkan
{@link android.app.PendingIntent} dengan gestur, panggil metode
{@link android.support.v4.app.NotificationCompat.Builder} yang sesuai. Misalnya, jika ingin memulai
{@link android.app.Activity} bila pengguna mengklik teks pemberitahuan pada
laci pemberitahuan, tambahkan {@link android.app.PendingIntent} dengan memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
</p>
<p>
Memulai {@link android.app.Activity} bila pengguna mengklik pemberitahuan adalah
skenario tindakan yang paling umum. Anda juga bisa memulai {@link android.app.Activity} bila pengguna
menghilangkan pemberitahuan. Dalam Android 4.1 dan yang lebih baru, Anda bisa memulai
{@link android.app.Activity} dari tombol tindakan. Untuk mengetahui selengkapnya, bacalah panduan acuan untuk
{@link android.support.v4.app.NotificationCompat.Builder}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Priority">Prioritas pemberitahuan</h3>
<p>
Jika diinginkan, Anda bisa mengatur prioritas pemberitahuan. Prioritas berfungsi
sebagai petunjuk bagi UI perangkat tentang cara menampilkan pemberitahuan.
Untuk mengatur prioritas pemberitahuan, panggil {@link
android.support.v4.app.NotificationCompat.Builder#setPriority(int)
NotificationCompat.Builder.setPriority()} dan teruskan salah satu konstanta prioritas {@link
android.support.v4.app.NotificationCompat}. Ada
lima level prioritas, mulai dari {@link
android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) hingga {@link
android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); jika tidak diatur,
prioritas default akan ditetapkan {@link
android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0).
</p>
<p> Untuk informasi tentang mengatur level prioritas, lihat "Mengatur
dan mengelola prioritas pemberitahuan dengan benar" dalam panduan
Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="SimpleNotification">Membuat pemberitahuan sederhana</h3>
<p>
Cuplikan berikut mengilustrasikan pemberitahuan sederhana yang menetapkan aktivitas untuk dibuka bila
pengguna mengklik pemberitahuan. Perhatikan bahwa kode ini membuat
objek {@link android.support.v4.app.TaskStackBuilder} dan menggunakannya untuk membuat
{@link android.app.PendingIntent} untuk tindakan. Pola ini dijelaskan secara lebih detail
di bagian <a href="#NotificationResponse">
Mempertahankan Navigasi saat Memulai Aktivitas</a>:
</p>
<pre>
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
</pre>
<p>Demikian saja. Pengguna Anda kini telah diberi tahu.</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ApplyStyle">Menerapkan layout yang diperluas pada pemberitahuan</h3>
<p>
Agar pemberitahuan muncul dalam tampilan yang diperluas, buat dahulu
objek {@link android.support.v4.app.NotificationCompat.Builder} dengan opsi tampilan normal
yang Anda inginkan. Berikutnya, panggil {@link android.support.v4.app.NotificationCompat.Builder#setStyle
Builder.setStyle()} dengan objek layout yang diperluas sebagai argumennya.
</p>
<p>
Ingatlah bahwa pemberitahuan yang diperluas tidak tersedia pada platform-platform sebelum Android 4.1. Untuk
mengetahui cara menangani pemberitahuan untuk Android 4.1 dan untuk platform-platform sebelumnya, bacalah
bagian <a href="#Compatibility">Menangani kompatibilitas</a>.
</p>
<p>
Misalnya, cuplikan kode berikut memperagakan cara mengubah pemberitahuan yang dibuat
dalam cuplikan sebelumnya untuk menggunakan layout yang diperluas:
</p>
<pre>
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Event tracker")
.setContentText("Events received")
NotificationCompat.InboxStyle inboxStyle =
new NotificationCompat.InboxStyle();
String[] events = new String[6];
// Sets a title for the Inbox in expanded layout
inboxStyle.setBigContentTitle("Event tracker details:");
...
// Moves events into the expanded layout
for (int i=0; i &lt; events.length; i++) {
inboxStyle.addLine(events[i]);
}
// Moves the expanded layout object into the notification object.
mBuilder.setStyle(inBoxStyle);
...
// Issue the notification here.
</pre>
<h3 id="Compatibility">Menangani kompatibilitas</h3>
<p>
Tidak semua fitur pemberitahuan tersedia untuk versi tertentu, walaupun
metode untuk mengaturnya ada dalam kelas pustaka dukungan
{@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}.
Misalnya, tombol tindakan, yang bergantung pada pemberitahuan yang diperluas, hanya muncul pada Android
4.1 dan lebih tinggi, karena pemberitahuan yang diperluas itu sendiri hanya tersedia pada
Android 4.1 dan yang lebih tinggi.
</p>
<p>
Untuk memastikan kompatibilitas terbaik, buatlah pemberitahuan dengan
{@link android.support.v4.app.NotificationCompat NotificationCompat} dan subkelasnya,
khususnya {@link android.support.v4.app.NotificationCompat.Builder
NotificationCompat.Builder}. Selain itu, ikutilah proses ini bila Anda mengimplementasikan pemberitahuan:
</p>
<ol>
<li>
Sediakan semua fungsionalitas pemberitahuan kepada semua pengguna, terlepas dari versi
yang mereka gunakan. Caranya, pastikan semua fungsionalitas tersedia dari
{@link android.app.Activity} dalam aplikasi Anda. Anda mungkin perlu menambahkan sebuah
{@link android.app.Activity} baru untuk melakukannya.
<p>
Misalnya, jika Anda ingin menggunakan
{@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} untuk
menyediakan kontrol yang menghentikan dan memulai pemutaran media, implementasikan dahulu
kontrol ini pada {@link android.app.Activity} dalam aplikasi Anda.
</p>
</li>
<li>
Pastikan semua pengguna bisa memperoleh fungsionalitas dalam {@link android.app.Activity},
dengan memulainya bila pengguna mengklik pemberitahuan. Caranya,
buatlah {@link android.app.PendingIntent}
untuk {@link android.app.Activity}. Panggil
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()} untuk menambahkan {@link android.app.PendingIntent} pada pemberitahuan.
</li>
<li>
Kini tambahkan fitur pemberitahuan diperluas yang ingin Anda gunakan pada pemberitahuan. Ingatlah
bahwa setiap fungsionalitas yang Anda tambahkan juga harus tersedia dalam {@link android.app.Activity}
yang akan dimulai bila pengguna mengklik pemberitahuan.
</li>
</ol>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="Managing">Mengelola Pemberitahuan</h2>
<p>
Bila perlu mengeluarkan pemberitahuan beberapa kali untuk tipe kejadian yang sama,
hindari membuat pemberitahuan yang sama sekali baru. Sebagai gantinya, Anda harus mempertimbangkan untuk memperbarui
pemberitahuan sebelumnya, baik dengan mengubah sebagian nilainya atau dengan menambahkan nilai, atau keduanya.
</p>
<p>
Misalnya, Gmail akan memberi tahu pengguna bila ada email baru dengan menambah hitungan
pesan tidak terbaca dan dengan menambahkan rangkuman tiap email ke pemberitahuan. Ini disebut dengan
"stacking" (menumpuk) pemberitahuan; hal ini dijelaskan lebih detail dalam panduan
Desain <a href="{@docRoot}design/patterns/notifications.html">Pemberitahuan</a>.
</p>
<p class="note">
<strong>Catatan:</strong> Fitur Gmail ini mensyaratkan layout "kotak masuk" diperluas, yang merupakan
bagian dari fitur pemberitahuan diperluas yang tersedia mulai Android 4.1.
</p>
<p>
Bagian berikut menjelaskan cara memperbarui pemberitahuan dan cara menghapusnya.
</p>
<h3 id="Updating">Memperbarui pemberitahuan</h3>
<p>
Untuk menyiapkan pemberitahuan agar bisa diperbarui, keluarkan pemberitahuan bersama ID pemberitahuan dengan
memanggil {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}.
Untuk memperbarui pemberitahuan ini setelah Anda
mengeluarkan, memperbarui, atau membuat objek {@link android.support.v4.app.NotificationCompat.Builder},
buat objek {@link android.app.Notification} darinya, dan keluarkan
{@link android.app.Notification} bersama ID yang sama dengan yang Anda gunakan sebelumnya. Jika
pemberitahuan sebelumnya tetap terlihat, sistem akan memperbaruinya dari konten
objek {@link android.app.Notification}. Jika pemberitahuan sebelumnya telah dihilangkan, sebuah
pemberitahuan baru akan dibuat.
</p>
<p>
Cuplikan berikut memperagakan pemberitahuan yang diperbarui untuk mencerminkan
jumlah kejadian yang telah terjadi. Cuplikan ini menumpuk pemberitahuan, yang menampilkan rangkuman:
</p>
<pre>
mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);
// Because the ID remains unchanged, the existing notification is
// updated.
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
...
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="Removing">Menghapus pemberitahuan</h3>
<p>
Pemberitahuan tetap terlihat hingga salah satu kejadian berikut terjadi:
</p>
<ul>
<li>
Pengguna menghilangkan pemberitahuan satu per satu atau dengan menggunakan "Clear All" (jika
pemberitahuan bisa dihapus).
</li>
<li>
Pengguna mengklik pemberitahuan, dan Anda memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} bila
Anda telah membuat pemberitahuan.
</li>
<li>
Anda memanggil {@link android.app.NotificationManager#cancel(int) cancel()} untuk
ID pemberitahuan tertentu. Metode ini juga menghapus pemberitahuan yang berjalan.
</li>
<li>
Anda memanggil {@link android.app.NotificationManager#cancelAll() cancelAll()}, yang menghapus
semua pemberitahuan yang dikeluarkan sebelumnya.
</li>
</ul>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="NotificationResponse">Mempertahankan Navigasi saat Memulai Aktivitas</h2>
<p>
Bila memulai {@link android.app.Activity} dari pemberitahuan, Anda harus mempertahankan
pengalaman navigasi yang diharapkan pengguna. Mengklik <i>Back</i> harus membawa pengguna kembali melalui
aliran pekerjaan normal aplikasi ke layar Home, dan mengklik <i>Recents</i> harus menampilkan
{@link android.app.Activity} sebagai tugas terpisah. Untuk mempertahankan pengalaman navigasi, Anda
harus memulai {@link android.app.Activity} dalam tugas baru. Cara menyiapkan
{@link android.app.PendingIntent} untuk memberi Anda tugas baru bergantung pada sifat
{@link android.app.Activity} yang Anda mulai. Ada dua situasi umum:
</p>
<dl>
<dt>
Aktivitas rutin
</dt>
<dd>
Anda memulai {@link android.app.Activity} yang merupakan bagian dari aliran pekerjaan normal
aplikasi. Dalam situasi ini, siapkan {@link android.app.PendingIntent} untuk
memulai tugas baru, dan sediakan {@link android.app.PendingIntent} bersama back-stack
yang meniru perilaku <i>Back</i> biasa.
<p>
Pemberitahuan dari aplikasi Gmail memperagakan hal ini. Bila Anda mengklik pemberitahuan untuk
satu pesan email, Anda akan melihat pesan itu sendiri. Menyentuh <b>Back</b> akan membawa Anda
kembali melalui Gmail ke layar Home, persis seperti jika memasuki Gmail dari
layar Home bukannya memasukinya dari pemberitahuan.
</p>
<p>
Hal ini terjadi terlepas dari aplikasi tempat Anda berada saat menyentuh
pemberitahuan. Misalnya, jika Anda dalam Gmail sedang menulis pesan, dan Anda mengklik
pemberitahuan untuk satu email, Anda akan segera dibawa ke email itu. Menyentuh <i>Back</i>
akan membawa Anda ke kotak masuk kemudian layar Home, bukannya membawa Anda ke
pesan yang sedang ditulis.
</p>
</dd>
<dt>
Aktivitas khusus
</dt>
<dd>
Pengguna hanya melihat {@link android.app.Activity} ini jika dimulai dari pemberitahuan.
Dalam beberapa hal, {@link android.app.Activity} akan memperluas pemberitahuan dengan menyediakan
informasi yang akan sulit untuk ditampilkan dalam pemberitahuan itu sendiri. Untuk situasi ini,
siapkan {@link android.app.PendingIntent} untuk dimulai dalam tugas baru. Tidak perlu
membuat back-stack, karena {@link android.app.Activity} yang dimulai bukan bagian dari
aliran aktivitas aplikasi. Mengklik <i>Back</i> tetap akan membawa pengguna ke
layar Home.
</dd>
</dl>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="DirectEntry">Menyiapkan PendingIntent aktivitas biasa</h3>
<p>
Untuk menyiapkan {@link android.app.PendingIntent} yang memulai entri langsung
{@link android.app.Activity}, ikuti langkah-langkah ini:
</p>
<ol>
<li>
Definisikan hierarki {@link android.app.Activity} aplikasi Anda dalam manifes.
<ol style="list-style-type: lower-alpha;">
<li>
Tambahkan dukungan untuk Android 4.0.3 dan yang terdahulu. Caranya, tetapkan induk
{@link android.app.Activity} yang Anda mulai dengan menambahkan elemen
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
sebagai anak
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>.
<p>
Untuk elemen ini, atur
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
Atur
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#val">android:value</a>="&lt;parent_activity_name&gt;"</code>
dengan <code>&lt;parent_activity_name&gt;</code> sebagai nilai
<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
untuk elemen induk
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
. Lihat XML berikut sebagai contoh.
</p>
</li>
<li>
Juga tambahkan dukungan untuk Android 4.1 dan yang lebih baru. Caranya, tambahkan atribut
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
pada elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
dari {@link android.app.Activity} yang Anda mulai.
</li>
</ol>
<p>
XML akhir akan terlihat seperti ini:
</p>
<pre>
&lt;activity
android:name=".MainActivity"
android:label="&#64;string/app_name" &gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
&lt;activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity"&gt;
&lt;meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/&gt;
&lt;/activity&gt;
</pre>
</li>
<li>
Buat back-stack berdasarkan {@link android.content.Intent} yang memulai
{@link android.app.Activity}:
<ol style="list-style-type: lower-alpha;">
<li>
Buat {@link android.content.Intent} untuk memulai {@link android.app.Activity}.
</li>
<li>
Buat stack-builder (pembangun tumpukan) dengan memanggil {@link android.app.TaskStackBuilder#create
TaskStackBuilder.create()}.
</li>
<li>
Tambahkan back-stack ke stack-builder dengan memanggil
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
Untuk setiap {@link android.app.Activity} dalam hierarki yang telah Anda definisikan dalam
manifes, back-stack berisi objek {@link android.content.Intent} yang
memulai {@link android.app.Activity}. Metode ini juga menambahkan flag yang memulai
back-stack dalam tugas baru.
<p class="note">
<strong>Catatan:</strong> Walaupun argumen untuk
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
adalah acuan ke {@link android.app.Activity} yang dimulai, panggilan metode
tidak akan menambahkan {@link android.content.Intent} yang memulai
{@link android.app.Activity}. Sebagai gantinya, hal itu ditangani dalam langkah berikutnya.
</p>
</li>
<li>
Tambahkan {@link android.content.Intent} yang memulai {@link android.app.Activity}
dari pemberitahuan, dengan memanggil
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
Teruskan {@link android.content.Intent} yang Anda buat dalam langkah pertama sebagai
argumen ke
{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
</li>
<li>
Jika perlu, tambahkan argumen ke objek {@link android.content.Intent} pada
back-stack dengan memanggil {@link android.support.v4.app.TaskStackBuilder#editIntentAt
TaskStackBuilder.editIntentAt()}. Kadang-kadang perlu memastikan apakah
{@link android.app.Activity} target menampilkan data bermakna saat pengguna menelusurinya
dengan menggunakan <i>Back</i>.
</li>
<li>
Dapatkan {@link android.app.PendingIntent} untuk back-stack ini dengan memanggil
{@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()}.
</li>
</ol>
</li>
</ol>
<p>
Cuplikan kode berikut memperagakan prosesnya:
</p>
<pre>
...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ExtendedNotification">Menyiapkan PendingIntent aktivitas khusus</h3>
<p>
Bagian berikut menjelaskan cara menyiapkan aktivitas khusus
{@link android.app.PendingIntent}.
</p>
<p>
{@link android.app.Activity} khusus tidak memerlukan back-stack, sehingga Anda tidak perlu
mendefinisikan hierarki {@link android.app.Activity}-nya dalam manifes, dan Anda tidak perlu
memanggil
{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} untuk membuat
back-stack. Sebagai gantinya, gunakan manifes untuk menyiapkan opsi tugas {@link android.app.Activity},
dan buat {@link android.app.PendingIntent} dengan memanggil
{@link android.app.PendingIntent#getActivity getActivity()}:
</p>
<ol>
<li>
Dalam manifes, tambahkan atribut berikut pada elemen
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
untuk {@link android.app.Activity}
<dl>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
</dt>
<dd>
Nama kelas mutlak (fully qualified) aktivitas.
</dd>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
</dt>
<dd>
Dikombinasikan dengan flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
yang Anda atur dalam kode, ini memastikan bahwa {@link android.app.Activity} ini tidak
masuk ke dalam tugas default aplikasi. Setiap tugas yang ada yang memiliki
afinitas default aplikasi tidak terpengaruh.
</dd>
<dt>
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
</dt>
<dd>
Mengecualikan tugas baru dari <i>Recents</i>, sehingga pengguna tidak bisa tanpa sengaja
mengarahkan kembali.
</dd>
</dl>
<p>
Cuplikan ini menampilkan elemen:
</p>
<pre>
&lt;activity
android:name=".ResultActivity"
...
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true"&gt;
&lt;/activity&gt;
...
</pre>
</li>
<li>
Buat dan keluarkan pemberitahuan:
<ol style="list-style-type: lower-alpha;">
<li>
Buat {@link android.content.Intent} yang memulai
{@link android.app.Activity}.
</li>
<li>
Atur {@link android.app.Activity} untuk dimulai dalam tugas kosong yang baru dengan memanggil
{@link android.content.Intent#setFlags setFlags()} dengan flag
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
dan
{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
</li>
<li>
Atur setiap opsi lain yang Anda perlukan untuk {@link android.content.Intent}.
</li>
<li>
Buat {@link android.app.PendingIntent} dari {@link android.content.Intent}
dengan memanggil {@link android.app.PendingIntent#getActivity getActivity()}.
Anda nanti bisa menggunakan {@link android.app.PendingIntent} ini sebagai argumen untuk
{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
setContentIntent()}.
</li>
</ol>
<p>
Cuplikan kode berikut memperagakan prosesnya:
</p>
<pre>
// Instantiate a Builder object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
PendingIntent.getActivity(
this,
0,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Puts the PendingIntent into the notification builder
builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Builds an anonymous Notification object from the builder, and
// passes it to the NotificationManager
mNotificationManager.notify(id, builder.build());
</pre>
</li>
</ol>
<!-- ------------------------------------------------------------------------------------------ -->
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="Progress">Menampilkan Kemajuan dalam Pemberitahuan</h2>
<p>
Pemberitahuan bisa menyertakan indikator kemajuan beranimasi yang menampilkan status
operasi yang berjalan kepada pengguna. Jika Anda bisa memperkirakan lamanya operasi berlangsung dan berapa banyak
yang sudah selesai pada suatu waktu, gunakan bentuk indikator yang "pasti"
(baris kemajuan). Jika Anda tidak bisa memperkirakan lamanya operasi, gunakan
bentuk indikator "tidak pasti" (indikator aktivitas).
</p>
<p>
Indikator kemajuan ditampilkan bersama implementasi platform
kelas {@link android.widget.ProgressBar}.
</p>
<p>
Untuk menggunakan indikator kemajuan pada platform mulai dari Android 4.0, panggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. Untuk
versi sebelumnya, Anda harus membuat layout pemberitahuan custom sendiri yang
menyertakan tampilan {@link android.widget.ProgressBar}.
</p>
<p>
Bagian berikut ini menjelaskan cara menampilkan kemajuan dalam pemberitahuan dengan menggunakan
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="FixedProgress">Menampilkan indikator kemajuan berdurasi tetap</h3>
<p>
Untuk menampilkan baris kemajuan pasti, tambahkan baris itu ke pemberitahuan dengan memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(max, progress, false)}, kemudian keluarkan pemberitahuan. Selagi operasi berlangsung,
tambah <code>progress</code>, dan perbarui pemberitahuan. Di akhir operasi,
<code>progress</code> harus sama dengan <code>max</code>. Satu cara umum memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
adalah mengatur <code>max</code> ke 100, kemudian tambah <code>progress</code> sebagai
nilai "persen selesai"untuk operasi itu.
</p>
<p>
Anda bisa membiarkan baris kemajuan ditampilkan saat operasi selesai, atau menghilangkannya. Dalam
hal apa pun, ingatlah memperbarui teks pemberitahuan untuk menampilkan bahwa operasi telah selesai.
Untuk menghapus baris kemajuan, panggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(0, 0, false)}. Misalnya:
</p>
<pre>
...
mNotifyManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_notification);
// Start a lengthy operation in a background thread
new Thread(
new Runnable() {
&#64;Override
public void run() {
int incr;
// Do the "lengthy" operation 20 times
for (incr = 0; incr &lt;= 100; incr+=5) {
// Sets the progress indicator to a max value, the
// current completion percentage, and "determinate"
// state
mBuilder.setProgress(100, incr, false);
// Displays the progress bar for the first time.
mNotifyManager.notify(0, mBuilder.build());
// Sleeps the thread, simulating an operation
// that takes time
try {
// Sleep for 5 seconds
Thread.sleep(5*1000);
} catch (InterruptedException e) {
Log.d(TAG, "sleep failure");
}
}
// When the loop is finished, updates the notification
mBuilder.setContentText("Download complete")
// Removes the progress bar
.setProgress(0,0,false);
mNotifyManager.notify(ID, mBuilder.build());
}
}
// Starts the thread by calling the run() method in its Runnable
).start();
</pre>
<!-- ------------------------------------------------------------------------------------------ -->
<h3 id="ActivityIndicator">Menampilkan indikator aktivitas berlanjut</h3>
<p>
Untuk menampilkan indikator aktivitas tidak pasti, tambahkan aktivitas ke pemberitahuan dengan
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
(dua argumen pertama akan diabaikan), dan keluarkan pemberitahuan. Hasilnya adalah indikator
yang memiliki gaya yang sama dengan baris kemajuan, hanya saja animasinya terus berjalan.
</p>
<p>
Keluarkan pemberitahuan di awal operasi. Animasi akan berjalan hingga Anda
memodifikasi pemberitahuan. Bila operasi selesai, panggil
{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}
kemudian perbarui pemberitahuan untuk menghapus indikator aktivitas.
Selalu lakukan ini; jika makan animasi akan terus berjalan sekalipun operasi telah selesai. Juga
ingatlah mengubah teks pemberitahuan untuk menunjukkan bahwa operasi telah selesai.
</p>
<p>
Untuk melihat cara kerja indikator aktivitas, lihat cuplikan terdahulu. Cari lokasi baris-baris berikut:
</p>
<pre>
// Sets the progress indicator to a max value, the current completion
// percentage, and "determinate" state
mBuilder.setProgress(100, incr, false);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
</pre>
<p>
Ganti baris yang telah Anda temukan dengan baris berikut:
</p>
<pre>
// Sets an activity indicator for an operation of indeterminate length
mBuilder.setProgress(0, 0, true);
// Issues the notification
mNotifyManager.notify(0, mBuilder.build());
</pre>
<h2 id="metadata">Metadata Pemberitahuan</h2>
<p>Pemberitahuan dapat disortir sesuai metadata yang Anda tetapkan dengan
metode {@link android.support.v4.app.NotificationCompat.Builder} berikut:</p>
<ul>
<li>{@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()}
memberi tahu sistem cara menangani pemberitahuan aplikasi Anda bila perangkat berada dalam mode Priority
(misalnya, jika pemberitahuan menyatakan suatu panggilan masuk, pesan instan, atau alarm).</li>
<li>{@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()} menyebabkan
pemberitahuan dengan bidang prioritas diatur ke {@code PRIORITY_MAX} atau {@code PRIORITY_HIGH}
muncul dalam jendela kecil mengambang jika pemberitahuan juga memiliki suara atau getaran.</li>
<li>{@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()}
memungkinkan Anda menambahkan daftar orang ke pemberitahuan. Aplikasi Anda bisa menggunakannya untuk memberi isyarat pada
sistem bahwa sistem harus mengelompokkan bersama pemberitahuan dari orang-orang yang ditetapkan, atau memberi peringkat lebih penting pada pemberitahuan
untuk orang-orang ini.</li>
</ul>
<div class="figure" style="width:230px">
<img src="{@docRoot}images/ui/notifications/heads-up.png" alt="" width="" height="" id="figure3" />
<p class="img-caption">
<strong>Gambar 3.</strong> Aktivitas layar penuh yang menampilkan pemberitahuan pendahuluan
</p>
</div>
<h2 id="Heads-up">Pemberitahuan Pendahuluan</h2>
<p>Dengan Android 5.0 (API level 21), pemberitahuan bisa muncul dalam jendela kecil mengambang
(yang disebut juga dengan <em>pemberitahuan pendahuluan</em>) saat perangkat aktif
(yakni, perangkat dibuka kuncinya dan layarnya menyala). Pemberitahuan ini
muncul seperti bentuk ringkas pemberitahuan Anda, hanya saja
pemberitahuan pendahuluan juga menampilkan tombol tindakan. Pengguna bisa menindaklanjuti atau mengabaikan,
pemberitahuan pendahuluan tanpa meninggalkan aplikasi saat ini.</p>
<p>Contoh-contoh kondisi yang dapat memicu pemberitahuan pendahuluan antara lain:</p>
<ul>
<li>Aktivitas pengguna berada dalam mode layar penuh (aplikasi menggunakan
{@link android.app.Notification#fullScreenIntent}), atau</li>
<li>Pemberitahuan memiliki prioritas tinggi dan menggunakan nada dering atau
getaran</li>
</ul>
<h2 id="lockscreenNotification">Pemberitahuan Layar Kunci</h2>
<p>Dengan rilis Android 5.0 (API level 21), pemberitahuan kini dapat muncul pada
layar kunci. Aplikasi Anda bisa menggunakan fungsionalitas ini untuk menyediakan kontrol pemutaran media dan
tindakan umum lainnya. Pengguna bisa memilih lewat Settings apakah akan menampilkan pemberitahuan pada layar kunci, dan
Anda bisa mendesain apakah pemberitahuan aplikasi akan terlihat pada layar kunci.</p>
<h3 id="visibility">Mengatur Visibilitas</h3>
<p>Aplikasi Anda bisa mengatur level detail terlihat pada pemberitahuan yang ditampilkan di
layar kunci aman. Anda memanggil {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()}
dan menetapkan salah satu nilai berikut:</p>
<ul>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC} menampilkan isi lengkap
pemberitahuan.</li>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET} tidak menampilkan bagian apa pun dari
pemberitahuan ini pada layar kunci.</li>
<li>{@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} menampilkan informasi dasar,
misalnya ikon dan judul isi pemberitahuan, namun menyembunyikan isi lengkap pemberitahuan.</li>
</ul>
<p>Bila {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE} telah diatur, Anda juga bisa
menyediakan versi alternatif isi pemberitahuan yang menyembunyikan detail tertentu. Misalnya,
aplikasi SMS dapat menampilkan pemberitahuan yang menampilkan <em>Anda memiliki 3 pesan teks baru</em>, namun menyembunyikan
isi dan pengirim pesan. Untuk menyediakan pemberitahuan alternatif ini, buat dahulu pemberitahuan
pengganti menggunakan {@link android.support.v4.app.NotificationCompat.Builder}. Bila Anda membuat
objek pemberitahuan privat, lampirkan pemberitahuan pengganti melalui metode
{@link android.support.v4.app.NotificationCompat.Builder#setPublicVersion(android.app.Notification) setPublicVersion()}
.</p>
<h3 id="controllingMedia">Mengontrol Pemutaran Media pada Layar Kunci</h3>
<p>Dalam Android 5.0 (API level 21) layar kunci tidak lagi menampilkan kontrol media
berdasarkan {@link android.media.RemoteControlClient}, yang sekarang telah dihilangkan. Sebagai gantinya, gunakan
template {@link android.app.Notification.MediaStyle} dengan metode
{@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
, yang mengubah tindakan menjadi ikon yang bisa diklik.</p>
<p class="note"><strong>Catatan:</strong> Template dan metode {@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()}
tidak disertakan dalam pustaka dukungan, sehingga fitur-fitur ini berjalan pada Android 5.0 dan yang lebih tinggi
saja.</p>
<p>Untuk menampilkan kontrol pemutaran media di layar kunci dalam Android 5.0, atur visibilitas
ke {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, seperti dijelaskan di atas. Kemudian tambahkan
tindakan dan atur template {@link android.app.Notification.MediaStyle}, seperti dijelaskan dalam contoh kode
berikut:</p>
<pre>
Notification notification = new Notification.Builder(context)
// Show controls on lock screen even when user hides sensitive content.
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_stat_player)
// Add media control buttons that invoke intents in your media service
.addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
.addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
.addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
// Apply the media style template
.setStyle(new Notification.MediaStyle()
.setShowActionsInCompactView(1 /* #1: pause button */)
.setMediaSession(mMediaSession.getSessionToken())
.setContentTitle("Wonderful music")
.setContentText("My Awesome Band")
.setLargeIcon(albumArtBitmap)
.build();
</pre>
<p class="note"><strong>Catatan:</strong> Dihilangkannya {@link android.media.RemoteControlClient}
memiliki implikasi lebih jauh untuk mengontrol media. Lihat
<a href="{@docRoot}about/versions/android-5.0.html#MediaPlaybackControl">Kontrol Pemutaran Media</a>
untuk informasi selengkapnya tentang API baru untuk mengelola sesi media dan mengontrol pemutaran.</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h2 id="CustomNotification">Layout Pemberitahuan Custom</h2>
<p>
Kerangka kerja pemberitahuan memungkinkan Anda mendefinisikan layout pemberitahuan custom, yang
mendefinisikan penampilan pemberitahuan dalam objek {@link android.widget.RemoteViews}.
Pemberitahuan dengan layout custom serupa pemberitahuan normal, namun dibuat berdasarkan
{@link android.widget.RemoteViews} yang didefinisikan dalam file layout XML.
</p>
<p>
Tinggi yang tersedia untuk layout pemberitahuan custom bergantung pada tampilan pemberitahuan. Layout
tampilan normal dibatasi hingga 64 dp, dan layout tampilan yang diperluas dibatasi hingga 256 dp.
</p>
<p>
Untuk mendefinisikan layout pemberitahuan custom, mulailah dengan membuat instance
objek {@link android.widget.RemoteViews} yang memekarkan file layout XML. Kemudian,
sebagai ganti memanggil metode seperti
{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
panggil {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Untuk mengatur
detail isi pemberitahuan custom, gunakan metode dalam
{@link android.widget.RemoteViews} untuk mengatur nilai anak tampilan:
</p>
<ol>
<li>
Buat layout XML untuk pemberitahuan di file terpisah. Anda bisa menggunakan nama file
apa saja yang diinginkan, namun Anda harus menggunakan ekstensi <code>.xml</code>
</li>
<li>
Dalam aplikasi Anda, gunakan metode {@link android.widget.RemoteViews} untuk mendefinisikan
ikon dan teks pemberitahuan. Masukkan objek {@link android.widget.RemoteViews} ini ke dalam
{@link android.support.v4.app.NotificationCompat.Builder} Anda dengan memanggil
{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Hindari
mengatur {@link android.graphics.drawable.Drawable} latar belakang pada
objek {@link android.widget.RemoteViews} Anda, karena warna teks bisa menjadi tidak terbaca.
</li>
</ol>
<p>
Kelas {@link android.widget.RemoteViews} juga menyertakan metode yang bisa Anda gunakan untuk
menambahkan {@link android.widget.Chronometer} atau {@link android.widget.ProgressBar}
dengan mudah ke layout pemberitahuan Anda. Untuk informasi selengkapnya tentang cara membuat layout custom
pemberitahuan Anda, lihat dokumentasi acuan {@link android.widget.RemoteViews}.
</p>
<p class="caution">
<strong>Perhatian:</strong> Bila Anda menggunakan layout pemberitahuan custom, berhati-hatilah
untuk memastikan bahwa layout custom itu bekerja pada berbagai orientasi dan resolusi perangkat. Walaupun
berlaku bagi semua layout View, nasihat ini khususnya penting untuk pemberitahuan karena
ruang di laci pemberitahuan sangat terbatas. Jangan buat layout custom terlalu
kompleks, dan pastikan mengujinya di berbagai konfigurasi.
</p>
<!-- ------------------------------------------------------------------------------------------ -->
<h4>Menggunakan sumber daya gaya untuk teks pemberitahuan custom</h4>
<p>
Selalu gunakan sumber daya gaya untuk teks pemberitahuan custom. Warna latar belakang
pemberitahuan bisa bervariasi di berbagai perangkat dan versi, dan menggunakan sumber daya gaya
membantu Anda menangani hal ini. Mulai Android 2.3, sistem mendefinisikan sebuah gaya untuk
teks layout pemberitahuan standar. Jika Anda menggunakan gaya yang sama dalam aplikasi yang menargetkan Android
2.3 atau yang lebih tinggi, Anda akan memastikan bahwa teks terlihat pada latar belakang tampilan.
</p>

View File

@@ -0,0 +1,71 @@
page.title=Ikhtisar UI
@jd:body
<p>Semua elemen antarmuka pengguna dalam aplikasi Android dibangun menggunakan objek {@link android.view.View} dan
{@link android.view.ViewGroup}. {@link android.view.View} adalah objek yang menarik
sesuatu di layar dan dapat berinteraksi dengan pengguna. {@link android.view.ViewGroup} merupakan sebuah
objek yang menyimpan objek {@link android.view.View} lainnya (dan {@link android.view.ViewGroup}) untuk
mendefinisikan layout antarmuka.</p>
<p>Android menyediakan sekumpulan subkelas {@link android.view.View} dan {@link
android.view.ViewGroup} yang menawarkan kontrol input umum (seperti tombol dan bidang
teks) serta berbagai model layout (seperti layout linear atau relatif).</p>
<h2 id="Layout">Layout Antarmuka Pengguna</h2>
<p>Antarmuka pengguna untuk setiap komponen aplikasi Anda didefinisikan menggunakan hierarki objek {link
android.view.View} dan {@link android.view.ViewGroup}, seperti yang ditampilkan dalam gambar 1. Setiap kelompok tampilan
merupakan kontainer tak terlihat yang mengelola tampilan anak, sementara tampilan anak ini dapat menjadi kontrol
input atau widget lain yang
menarik sebagian dari UI. Pohon hierarki ini bisa sederhana atau bisa juga kompleks bergantung kebutuhan
(namun yang sederhana paling baik untuk kinerja).</p>
<img src="{@docRoot}images/viewgroup.png" alt="" />
<p class="img-caption"><strong>Gambar 1.</strong> Ilustrasi dari hierarki tampilan, yang mendefinisikan layout
UI.</p>
<p>Untuk mendeklarasikan layout, Anda dapat menyediakan objek {@link android.view.View} dalam kode dan mulai
membangun pohon, namun cara termudah dan terefektif untuk mendefinisikan layout adalah dengan file XML.
XML menawarkan struktur layout yang dapat dibaca manusia, serupa dengan HTML.</p>
<p>Nama elemen XML untuk tampilan sesuai dengan kelas Android yang diwakilinya. Dengan demikian elemen
<code>&lt;TextView&gt;</code> membuat widget {@link android.widget.TextView} dalam UI Anda,
dan elemen <code>&lt;LinearLayout&gt;</code> membuat kelompok tampilan {@link android.widget.LinearLayout}
. </p>
<p>Misalnya, layout vertikal sederhana dengan tampilan teks dan tombol akan tampak seperti ini:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a Button" />
&lt;/LinearLayout>
</pre>
<p>Saat Anda memuat sumber daya layout di aplikasi, Android akan menginisialisasi setiap simpul layout menjadi
objek runtime yang bisa Anda gunakan untuk mendefinisikan perilaku tambahan, query status objek, atau memodifikasi
layout.</p>
<p>Untuk mendapatkan panduan lengkap mengenai pembuatan layout UI, lihat <a href="declaring-layout.html">Layout
XML</a>.
<h2 id="UIComponents">Komponen Antarmuka Pengguna</h2>
<p>Anda tidak harus membuat semua UI menggunakan objek {@link android.view.View} dan {link
android.view.ViewGroup}. Android menyediakan beberapa komponen aplikasi yang menawarkan
layout UI standar yang tinggal Anda definisikan kontennya. Komponen UI ini masing-masing
memiliki set API unik yang dijelaskan dalam masing-masing dokumennya, seperti <a href="{@docRoot}guide/topics/ui/actionbar.html">Action-Bar</a>, <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialog</a>, dan <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Pemberitahuan Status</a>.</p>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,291 @@
page.title=Kejadian Input
parent.title=Antarmuka Pengguna
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Dalam dokumen ini</h2>
<ol>
<li><a href="#EventListeners">Event Listener</a></li>
<li><a href="#EventHandlers">Event Handler</a></li>
<li><a href="#TouchMode">Mode Sentuh</a></li>
<li><a href="#HandlingFocus">Menangani Fokus</a></li>
</ol>
</div>
</div>
<p>Di Android, ada lebih dari satu cara untuk mencegat kejadian dari interaksi pengguna dengan aplikasi Anda.
Saat mempertimbangkan kejadian dalam antarmuka pengguna Anda, pendekatannya adalah menangkap kejadian
dari objek View tertentu yang digunakan pengguna untuk berinteraksi. Kelas View menyediakan sarana untuk melakukannya.</p>
<p>Dalam berbagai kelas View yang akan digunakan untuk menyusun layout, Anda mungkin melihat beberapa metode callback
publik yang tampak berguna untuk kejadian UI. Metode ini dipanggil oleh kerangka kerja Android ketika masing-masing
tindakan terjadi pada objek itu. Misalnya, bila View (seperti Button/Tombol) disentuh,
metode <code>onTouchEvent()</code> akan dipanggil pada objek itu. Akan tetapi, untuk mencegatnya, Anda harus memperluas
kelas dan mengesampingkan metode itu. Akan tetapi, memperluas setiap objek View
untuk menangani kejadian seperti itu tidaklah praktis. Karena itulah kelas View juga berisi
sekumpulan antarmuka tersarang dengan callback yang jauh lebih mudah didefinisikan. Antarmuka ini,
yang disebut <a href="#EventListeners">event listener</a>, merupakan tiket Anda untuk menangkap interaksi pengguna dengan UI.</p>
<p>Walaupun Anda akan lebih sering menggunakan event listener ini untuk interaksi pengguna,
mungkin ada saatnya Anda ingin memperluas kelas View, untuk membuat komponen custom.
Mungkin Anda ingin memperluas kelas {@link android.widget.Button}
untuk membuat sesuatu yang lebih menarik. Dalam hal ini, Anda akan dapat mendefinisikan perilaku kejadian default untuk kelas Anda dengan menggunakan
kelas <a href="#EventHandlers">event handler</a>.</p>
<h2 id="EventListeners">Event Listener</h2>
<p>Event listener merupakan antarmuka di kelas {@link android.view.View} yang berisi metode
callback tunggal. Metode ini akan dipanggil oleh kerangka kerja Android bila View yang
telah didaftarkan dengan listener dipicu oleh interaksi pengguna dengan item dalam UI.</p>
<p>Yang juga disertakan dalam antarmuka event listener adalah metode callback berikut ini:</p>
<dl>
<dt><code>onClick()</code></dt>
<dd>Dari {@link android.view.View.OnClickListener}.
Ini dipanggil baik saat pengguna menyentuh item
(bila dalam mode sentuh), maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
menekan tombol "enter" yang sesuai atau menekan trackball.</dd>
<dt><code>onLongClick()</code></dt>
<dd>Dari {@link android.view.View.OnLongClickListener}.
Ini dipanggil baik saat pengguna menyentuh dan menahan item (bila dalam mode sentuh),
maupun memfokuskan pada item dengan tombol navigasi atau trackball dan
menekan serta menahan tombol "enter" yang sesuai atau menekan dan menahan trackball (selama satu detik).</dd>
<dt><code>onFocusChange()</code></dt>
<dd>Dari {@link android.view.View.OnFocusChangeListener}.
Ini dipanggil saat pengguna menyusuri ke atau dari item, dengan menggunakan tombol navigasi atau trackball.</dd>
<dt><code>onKey()</code></dt>
<dd>Dari {@link android.view.View.OnKeyListener}.
Ini dipanggil saat pengguna memfokuskan pada item dan menekan atau melepas tombol fisik pada perangkat.</dd>
<dt><code>onTouch()</code></dt>
<dd>Dari {@link android.view.View.OnTouchListener}.
Ini dipanggil saat pengguna melakukan tindakan yang digolongkan sebagai kejadian sentuh, termasuk penekanan, pelepasan,
atau gerak perpindahan pada layar (dalam batasan item itu).</dd>
<dt><code>onCreateContextMenu()</code></dt>
<dd>Dari {@link android.view.View.OnCreateContextMenuListener}.
Ini dipanggil saat Menu Konteks sedang dibuat (akibat "klik lama" terus-menerus). Lihat diskusi
tentang menu konteks di panduan pengembang <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Menu</a>.
</dd>
</dl>
<p>Metode ini satu-satunya yang menempati antarmukanya masing-masing. Untuk mendefinisikan salah satu metode ini
dan menangani kejadian Anda, implementasikan antarmuka tersarang dalam Aktivitas Anda atau definisikan sebagai kelas anonim.
Kemudian, teruskan satu
instance implementasi Anda pada masing-masing metode <code>View.set...Listener()</code>. (Misalnya, panggil
<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
dan teruskan implementasi {@link android.view.View.OnClickListener OnClickListener} Anda.)</p>
<p>Contoh di bawah menunjukkan cara mendaftarkan on-click listener untuk Button. </p>
<pre>
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
</pre>
<p>Anda juga akan merasa lebih praktis mengimplementasikan OnClickListener sebagai bagian dari Aktivitas.
Ini akan menghindari beban kelas ekstra dan alokasi objek. Misalnya:</p>
<pre>
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
</pre>
<p>Perhatikan bahwa callback <code>onClick()</code> dalam contoh di atas tidak memiliki
nilai hasil, namun beberapa metode event listener lainnya harus mengembalikan boolean. Sebabnya
bergantung pada kejadian. Untuk sebagian yang mengembalikan boolean, ini sebabnya:</p>
<ul>
<li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> -
Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
on-click listener lainnya.</li>
<li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> -
Ini mengembalikan boolean untuk menunjukkan apakah Anda telah menggunakan kejadian dan tidak boleh dibawa lebih jauh.
Yaitu, mengembalikan <em>benar</em> untuk menunjukkan apakah Anda telah menangani kejadian dan semestinya berhenti di sini;
mengembalikan <em>salah</em> jika Anda tidak menanganinya dan/atau kejadian semestinya berlanjut ke
on-key listener lainnya.</li>
<li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> -
Ini mengembalikan boolean untuk menunjukkan apakah listener Anda telah menggunakan kejadian ini. Yang penting adalah
kejadian ini bisa memiliki beberapa tindakan yang saling mengikuti. Jadi, jika Anda mengembalikan <em>salah</em>saat
kejadian tindakan turun diterima, itu menunjukkan bahwa Anda belum menggunakan kejadian itu dan juga
tidak tertarik dengan tindakan berikutnya dari kejadian ini. Karena itu, Anda tidak akan diminta untuk melakukan tindakan
lainnya dalam kejadian, seperti gerakan jari, atau kejadian tindakan naik yang akan terjadi.</li>
</ul>
<p>Ingatlah bahwa kejadian tombol fisik selalu disampaikan ke View yang sedang difokus. Kejadian ini dikirim mulai dari atas
hierarki View, kemudian turun hingga tujuan yang sesuai. Jika View Anda (atau anak View Anda)
saat ini sedang fokus, maka Anda dapat melihat kejadian berpindah melalui metode.<code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
dispatchKeyEvent()}</code> Sebagai pengganti untuk menangkap kejadian penting melalui View, Anda juga dapat menerima
semua kejadian dalam Aktivitas Anda dengan <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
dan <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
<p>Selain itu, saat memikirkan tentang input teks aplikasi Anda, ingatlah bahwa banyak perangkat yang hanya memiliki
metode input perangkat lunak. Metode seperti itu tidak harus berbasis tombol; sebagian mungkin menggunakan input suara, tulisan tangan, dan seterusnya. Meskipun
metode input menyajikan antarmuka seperti keyboard, itu umumnya <strong>tidak</strong> memicu keluarga kejadian
<code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>. Anda sama sekali tidak boleh
membangun UI yang mengharuskan penekanan tombol tertentu dikontrol kecuali jika Anda ingin membatasi aplikasi Anda pada perangkat yang memiliki
keyboard fisik. Khususnya, jangan mengandalkan metode ini untuk memvalidasi input saat pengguna menekan tombol
enter; melainkan, gunakan tindakan seperti {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE} untuk menandai
metode input mengenai reaksi yang diharapkan aplikasi Anda, sehingga bisa mengubah UI-nya secara signifikan. Hindari anggapan
tentang bagaimana metode input perangkat lunak seharusnya bekerja dan percayalah bahwa metode akan menyediakan teks yang sudah diformat bagi aplikasi Anda.</p>
<p class="note"><strong>Catatan:</strong> Android akan memanggil event handler terlebih dahulu kemudian handler
default yang sesuai dari definisi kelas. Karena itu, mengembalikan <em>benar</em> dari event listener ini akan menghentikan
penyebaran kejadian ke event listener lain dan juga akan memblokir callback ke
event handler default di View. Pastikan bahwa Anda ingin mengakhiri kejadian saat mengembalikan <em>true</em>.</p>
<h2 id="EventHandlers">Event Handler</h2>
<p>Jika Anda membuat komponen custom dari View, maka Anda dapat mendefinisikan penggunaan beberapa
metode callback sebagai event handler default.
Dalam dokumen tentang <a href="{@docRoot}guide/topics/ui/custom-components.html">Komponen
Custom</a>, Anda akan melihat penggunaan beberapa callback umum untuk penanganan kejadian,
termasuk:</p>
<ul>
<li><code>{@link android.view.View#onKeyDown}</code> - Dipanggil bila terjadi kejadian tombol baru.</li>
<li><code>{@link android.view.View#onKeyUp}</code> - Dipanggil bila terjadi kejadian tombol naik.</li>
<li><code>{@link android.view.View#onTrackballEvent}</code> - Dipanggil bila terjadi kejadian gerakan trackball.</li>
<li><code>{@link android.view.View#onTouchEvent}</code> - Dipanggil bila terjadi kejadian gerakan layar sentuh.</li>
<li><code>{@link android.view.View#onFocusChanged}</code> - Dipanggil bila View memperoleh atau kehilangan fokus.</li>
</ul>
<p>Ada beberapa metode lain yang harus Anda ketahui, yang bukan bagian dari kelas View,
namun bisa berdampak langsung pada kemampuan Anda menangani kejadian. Jadi, saat mengelola kejadian yang lebih kompleks dalam
layout, pertimbangkanlah metode-metode lain ini:</p>
<ul>
<li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent)
Activity.dispatchTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
android.app.Activity} Anda mencegat semua kejadian sentuh sebelum dikirim ke jendela.</li>
<li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - Ini memungkinkan {@link
android.view.ViewGroup} memantau kejadian saat dikirim ke View anak.</li>
<li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Panggil ini
pada View induk untuk menunjukan larangan mencegat kejadian sentuh dengan <code>{@link
android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
</ul>
<h2 id="TouchMode">Mode Sentuh</h2>
<p>
Saat pengguna menyusuri antarmuka pengguna dengan tombol pengarah atau trackball, Anda
perlu memberikan fokus pada item tindakan (seperti tombol) agar pengguna bisa mengetahui apa
yang akan menerima input. Akan tetapi jika perangkat memiliki kemampuan sentuh, dan pengguna
mulai berinteraksi dengan antarmuka dengan menyentuhnya, maka Anda tidak perlu lagi
menyorot item, atau memfokuskan pada View tertentu. Karena itu, ada mode
untuk interaksi yang bernama "mode sentuh".
</p>
<p>
Untuk perangkat berkemampuan sentuh, setelah pengguna menyentuh layar, perangkat
akan masuk ke mode sentuh. Dari sini dan selanjutnya, hanya View dengan
{@link android.view.View#isFocusableInTouchMode} benar yang akan dapat difokus, seperti widget pengedit teks.
View lain yang dapat disentuh, seperti tombol, tidak akan difokus bila disentuh; View ini akan
langsung memicu on-click listener bila ditekan.
</p>
<p>
Kapan saja pengguna menekan tombol pengarah atau menggulir dengan trackball, perangkat akan
keluar dari mode sentuh, dan mencari tampilan untuk difokuskan. Kini pengguna bisa melanjutkan interaksi
dengan antarmuka pengguna tanpa menyentuh layar.
</p>
<p>
Status mode sentuh dipertahankan di seluruh sistem (semua jendela dan aktivitas).
Untuk query status saat ini, Anda bisa memanggil
{@link android.view.View#isInTouchMode} untuk mengetahui apakah perangkat saat ini sedang dalam mode sentuh.
</p>
<h2 id="HandlingFocus">Menangani Fokus</h2>
<p>Kerangka kerja ini akan menangani gerakan fokus rutin sebagai respons input pengguna.
Ini termasuk mengubah fokus saat View dihapus atau disembunyikan, atau saat tersedia View
baru. View menunjukkan kesediaannya untuk mengambil fokus
melalui metode <code>{@link android.view.View#isFocusable()}</code>. Untuk mengubah apakah View bisa mengambil
fokus, panggil <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>. Saat dalam mode sentuh,
Anda dapat me-query apakah View memungkinkan fokus dengan <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
Anda bisa mengubahnya dengan <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
</p>
<p>Gerakan fokus berdasarkan pada algoritma yang mencari tetangga terdekat dalam
arah yang diberikan. Dalam kasus yang jarang terjadi, algoritma default mungkin
tidak cocok dengan perilaku yang diinginkan pengembang. Dalam situasi ini, Anda bisa memberikan
pengesampingan eksplisit dengan mengikuti atribut XML berikut dalam file layout:
<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, dan
<var>nextFocusUp</var>. Tambahkan salah satu atribut ini ke View <em>dari</em> mana fokus
meninggalkan. Definisikan nilai atribut untuk menjadi ID View
<em>ke</em> mana fokus harus diberikan. Misalnya:</p>
<pre>
&lt;LinearLayout
android:orientation="vertical"
... >
&lt;Button android:id="@+id/top"
android:nextFocusUp="@+id/bottom"
... />
&lt;Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
&lt;/LinearLayout>
</pre>
<p>Biasanya, dalam layout vertikal ini, navigasi ke atas dari Button pertama tidak akan membawa ke
mana pun, tidak pula akan menyusuri ke bawah dari Button kedua. Karena sekarang Button atas telah
mendefinisikan Button bawah sebagai <var>nextFocusUp</var> (dan sebaliknya), fokus navigasi akan
silih berganti dari atas ke bawah dan bawah ke atas.</p>
<p>Jika Anda ingin mendeklarasikan View sebagai dapat difokus dalam UI (bila biasanya tidak dapat difokus),
tambahkan atribut XML <code>android:focusable</code> ke View, dalam deklarasi layout Anda.
Atur nilai <var>true</var>. Anda juga bisa mendeklarasikan View
sebagai dapat difokus saat dalam Mode Sentuh dengan <code>android:focusableInTouchMode</code>.</p>
<p>Untuk meminta View tertentu difokus, panggil <code>{@link android.view.View#requestFocus()}</code>.</p>
<p>Untuk mendengarkan kejadian fokus (diberi tahu bila View menerima atau kehilangan fokus), gunakan
<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>
, seperti yang dibahas di bagian <a href="#EventListeners">Event Listener</a>, di atas.</p>
<!--
<h2 is="EventCycle">Event Cycle</h2>
<p>The basic cycle of a View is as follows:</p>
<ol>
<li>An event comes in and is dispatched to the appropriate View. The View
handles the event and notifies any listeners.</li>
<li>If, in the course of processing the event, the View's bounds may need
to be changed, the View will call {@link android.view.View#requestLayout()}.</li>
<li>Similarly, if in the course of processing the event the View's appearance
may need to be changed, the View will call {@link android.view.View#invalidate()}.</li>
<li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called,
the framework will take care of measuring, laying out, and drawing the tree
as appropriate.</li>
</ol>
<p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on
the UI thread when calling any method on any View.
If you are doing work on other threads and want to update the state of a View
from that thread, you should use a {@link android.os.Handler}.
</p>
-->

View File

@@ -0,0 +1,432 @@
page.title=Unduh Android Studio dan SDK Tools
page.tags=sdk, android studio
page.image=images/cards/android-studio_2x.png
page.template=sdk
page.image=images/cards/android-studio_2x.png
header.hide=1
page.metaDescription=Unduh Android IDE resmi dan alat pengembang untuk membuat aplikasi bagi ponsel, tablet, perangkat wearable, TV Android dan lainnya.
@jd:body
<style type="text/css">
.offline {display:none;}
h2.feature {
padding-top:30px;
margin-top:0;
clear:both;
}
.feature-blurb {
margin:0px; font-size:16px; font-weight:300;
padding-top:40px;
}
.landing-button .small {
font-size: 12px;
font-weight: normal;
line-height: 12px;
display: block;
}
h1.studio-logo {
width:226px;
height:78px;
display:block;
padding:0;
white-space: nowrap;
text-indent: -10000px;
font-size:0px;
background: url({@docRoot}images/tools/studio-logo.png);
background-image: -webkit-image-set(url({@docRoot}images/tools/studio-logo.png) 1x, url({@docRoot}images/tools/studio-logo_2x.png) 2x);
background-size: 226px 78px;
}
</style>
<div style="position:relative;">
<div class="wrap" id="tos" style="display:none;width:inherit;height:650px">
<div class="col-13" style="margin:0;">&nbsp;</div><!-- provides top margin for content -->
<h1 id="tos-header" style="margin-top:0">Unduh</h1>
<p class="sdk-terms-intro">Sebelum menginstal Android Studio atau alat SDK mandiri,
Anda harus menyetujui ketentuan dan persyaratan berikut.</p>
<div class="sdk-terms" onfocus="this.blur()">
<h2 class="norule">Ketentuan dan Persyaratan</h2>
Ini adalah Perjanjian Lisensi Kit Pengembangan Perangkat Lunak Android
<h3>1. Introduction</h3>
1.1 The Android Software Development Kit (referred to in the License Agreement as the "SDK" and specifically including the Android system files, packaged APIs, and Google APIs add-ons) is licensed to you subject to the terms of the License Agreement. The License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK.
1.2 "Android" means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
1.3 A "compatible implementation" means any Android device that (i) complies with the Android Compatibility Definition document, which can be found at the Android compatibility website (http://source.android.com/compatibility) and which may be updated from time to time; and (ii) successfully passes the Android Compatibility Test Suite (CTS).
1.4 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
<h3>2. Accepting this License Agreement</h3>
2.1 In order to use the SDK, you must first agree to the License Agreement. You may not use the SDK if you do not accept the License Agreement.
2.2 By clicking to accept, you hereby agree to the terms of the License Agreement.
2.3 You may not use the SDK and may not accept the License Agreement if you are a person barred from receiving the SDK under the laws of the United States or other countries, including the country in which you are resident or from which you use the SDK.
2.4 If you are agreeing to be bound by the License Agreement on behalf of your employer or other entity, you represent and warrant that you have full legal authority to bind your employer or such entity to the License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the SDK on behalf of your employer or other entity.
<h3>3. SDK License from Google</h3>
3.1 Subject to the terms of the License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the SDK solely to develop applications for compatible implementations of Android.
3.2 You may not use this SDK to develop applications for other platforms (including non-compatible implementations of Android) or to develop another SDK. You are of course free to develop applications for other platforms, including non-compatible implementations of Android, provided that this SDK is not used for that purpose.
3.3 You agree that Google or third parties own all legal right, title and interest in and to the SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
3.4 You may not use the SDK for any purpose not expressly permitted by the License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the SDK or any part of the SDK; or (b) load any part of the SDK onto a mobile handset or any other hardware device except a personal computer, combine any part of the SDK with other software, or distribute any software or device incorporating a part of the SDK.
3.5 Use, reproduction and distribution of components of the SDK licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement.
3.6 You agree that the form and nature of the SDK that Google provides may change without prior notice to you and that future versions of the SDK may be incompatible with applications developed on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) providing the SDK (or any features within the SDK) to you or to users generally at Google's sole discretion, without prior notice to you.
3.7 Nothing in the License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the SDK.
<h3>4. Use of the SDK by You</h3>
4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the SDK, including any intellectual property rights that subsist in those applications.
4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) the License Agreement and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
4.3 You agree that if you use the SDK to develop applications for general public users, you will protect the privacy and legal rights of those users. If the users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If the user provides your application with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so.
4.4 You agree that you will not engage in any activity with the SDK, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of any third party including, but not limited to, Google or any mobile communications carrier.
4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under the License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
<h3>5. Your Developer Credentials</h3>
5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
<h3>6. Privacy and Information</h3>
6.1 In order to continually innovate and improve the SDK, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the SDK are being used and how they are being used. Before any of this information is collected, the SDK will notify you and seek your consent. If you withhold consent, the information will not be collected.
6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in accordance with Google's Privacy Policy.
<h3>7. Third Party Applications</h3>
7.1 If you use the SDK to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party. In that case, the License Agreement does not affect your legal relationship with these third parties.
<h3>8. Using Android APIs</h3>
8.1 Google Data APIs
8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
<h3>9. Terminating this License Agreement</h3>
9.1 The License Agreement will continue to apply until terminated by either you or Google as set out below.
9.2 If you want to terminate the License Agreement, you may do so by ceasing your use of the SDK and any relevant developer credentials.
9.3 Google may at any time, terminate the License Agreement with you if:
(A) you have breached any provision of the License Agreement; or
(B) Google is required to do so by law; or
(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated its relationship with Google or ceased to offer certain parts of the SDK to you; or
(D) Google decides to no longer provide the SDK or certain parts of the SDK to users in the country in which you are resident or from which you use the service, or the provision of the SDK or certain SDK services to you by Google is, in Google's sole discretion, no longer commercially viable.
9.4 When the License Agreement comes to an end, all of the legal rights, obligations and liabilities that you and Google have benefited from, been subject to (or which have accrued over time whilst the License Agreement has been in force) or which are expressed to continue indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall continue to apply to such rights, obligations and liabilities indefinitely.
<h3>10. DISCLAIMER OF WARRANTIES</h3>
10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.
10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
<h3>11. LIMITATION OF LIABILITY</h3>
11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
<h3>12. Indemnification</h3>
12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you with the License Agreement.
<h3>13. Changes to the License Agreement</h3>
13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. When these changes are made, Google will make a new version of the License Agreement available on the website where the SDK is made available.
<h3>14. General Legal Terms</h3>
14.1 The License Agreement constitutes the whole legal agreement between you and Google and governs your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the SDK.
14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in the License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of the License Agreement is invalid, then that provision will be removed from the License Agreement without affecting the rest of the License Agreement. The remaining provisions of the License Agreement will continue to be valid and enforceable.
14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to the License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of the License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to the License Agreement.
14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
14.6 The rights granted in the License Agreement may not be assigned or transferred by either you or Google without the prior written approval of the other party. Neither you nor Google shall be permitted to delegate their responsibilities or obligations under the License Agreement without the prior written approval of the other party.
14.7 The License Agreement, and your relationship with Google under the License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from the License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
<em>November 20, 2015</em>
</div>
<div id="next-steps" style="display:none;position:absolute;width:inherit">
<p>Beberapa saat lagi Anda akan dapat membuat aplikasi untuk Android!</p>
<p>Sebentar lagi, Anda akan dialihkan ke
<a id="next-link" href="{@docRoot}sdk/installing/index.html">Menginstal Android SDK</a>.</p>
</div><!-- end next-steps -->
<div id="sdk-terms-form">
<p>
<input id="agree" type="checkbox" name="agree" value="1" onclick="onAgreeChecked()" />
<label id="agreeLabel" for="agree">Saya telah membaca dan menyetujui ketentuan dan persyaratan di atas</label>
</p>
<p><a href="" class="button disabled" id="downloadForRealz" onclick="return onDownloadForRealz(this);"></a></p>
</div>
</div><!-- end TOS -->
<div id="landing">
<div class="col-13">&nbsp;</div><!-- provides top margin for content -->
<img src="{@docRoot}images/tools/studio-hero.png"
srcset="{@docRoot}images/tools/studio-hero_2x.png 2x, {@docRoot}images/tools/studio-hero.png 1x"
width="760" alt="" />
<div style="color: #fff; width:226px; height:0; overflow:visible; position:absolute; top:40px; left:25px">
<h1 class="studio-logo" style="margin:0 0 35px !important">Android Studio</h1>
<p style="font-size: 16px; color:#bbb; position: absolute;left: 297px; top: 5px; display: block;
width: 400px;text-align: center;">Android IDE resmi</p>
<ul style="font-size:12px;line-height:19px;">
<li>Android Studio IDE</li>
<li>Android SDK Tools</li>
<li>Platform Android 6.0 (Marshmallow)</li>
<li>Citra sistem emulator Android 6.0 dengan Google API</li>
</ul>
<a class="online landing-button green download-bundle-button"
href="#Other" >Download Android Studio<br/><span class='small'></span></a>
<!-- this appears when viewing the offline docs -->
<p class="offline">
Untuk mendapatkan Android Studio atau alat SDK mandiri, kunjungi <a href="http://developer.android.com/sdk/index.html">developer.android.com/sdk/</a>
</p>
</div>
<ul>
<li><a href="#Requirements">Kebutuhan Sistem</a></li>
<li><a href="#Other">Opsi Unduhan Lain</a></li>
<li><a href="{@docRoot}sdk/installing/migrate.html">Beralih ke Android Studio</a></li>
<li><a href="https://docs.google.com/a/google.com/forms/d/1mjsyfzv3HAnDY-_Kfj-3QJKdpuksyMFs9e73CRwmT6Q/viewform" target="_blank">Ikuti Survei</a></li>
</ul>
<h2 class="feature norule" >Editor kode cerdas</h2>
<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-code.png" srcset="{@docRoot}images/tools/studio-hero-code_2x.png 2x, {@docRoot}images/tools/studio-hero-code.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
<div class="col-4 feature-blurb">
<p>Yang menjadi inti Android Studio adalah editor kode cerdas dengan kemampuan
penyelesaian kode, optimalisasi, dan analisis kode yang canggih.</p>
<p>Editor kode yang andal ini membantu Anda menjadi pengembang aplikasi Android yang lebih produktif.</p>
</div>
<h2 class="feature norule">Template kode dan integrasi GitHub</h2>
<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-import.png" srcset="{@docRoot}images/tools/studio-hero-import_2x.png 2x, {@docRoot}images/tools/studio-hero-import.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
<div class="col-4 feature-blurb">
<p>Pemandu proyek yang baru membuat proses memulai proyek baru menjadi jauh lebih mudah.</p>
<p>Mulai proyek dengan menggunakan kode template untuk pola seperti navigation-drawer dan view-pager,
dan bahkan impor contoh kode Google dari GitHub.</p>
</div>
<h2 class="feature norule">Pengembangan aplikasi multilayar</h2>
<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-screens.png" srcset="{@docRoot}images/tools/studio-hero-screens_2x.png 2x, {@docRoot}images/tools/studio-hero-screens.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
<div class="col-4 feature-blurb">
<p>Buat aplikasi untuk ponsel dan tablet Android, Android Wear,
Android TV, Android Auto dan Google Glass.</p>
<p>Dengan Android Project View yang baru dan dukungan modul di Android Studio, jadi semakin mudah
mengelola proyek dan sumber daya aplikasi.
</div>
<h2 class="feature norule">Perangkat virtual untuk semua ukuran dan bentuk</h2>
<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-avds.png" srcset="{@docRoot}images/tools/studio-hero-avds_2x.png 2x, {@docRoot}images/tools/studio-hero-avds.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
<div class="col-4 feature-blurb">
<p>Android Studio sudah dikonfigurasi dengan citra emulator yang dioptimalkan.</p>
<p>Virtual Device Manager yang telah diperbarui dan dibuat lebih efisien menyediakan
profil perangkat yang sudah didefinisikan untuk perangkat Android umum.</p>
</div>
<h2 class="feature norule">
Pembuatan Android berkembang dengan Gradle</h2>
<div class="col-9">
<img src="{@docRoot}images/tools/studio-hero-gradle.png" srcset="{@docRoot}images/tools/studio-hero-gradle_2x.png 2x, {@docRoot}images/tools/studio-hero-gradle.png 1x" width="520" />
</div><!-- end col-9 (left column) -->
<div class="col-4 feature-blurb">
<p>Buatlah berbagai APK untuk aplikasi Android Anda dengan aneka fitur menggunakan proyek yang sama.</p>
<p>Kelola dependensi aplikasi dengan Maven.</p>
<p>Buat APK dari Android Studio atau baris perintah.</p>
</div>
<h2 class="feature norule">Selengkapnya tentang Android Studio</h2>
<div style="background:#424242;padding:30px; color:#fff;margin:0 0 15px;">
<a class="online landing-button green download-bundle-button" style="margin:0 0 40px 60px;float:right" href="">Download</a>
<ul>
<li>Dibuat dengan IntelliJ IDEA Community Edition, JAVA IDE populer karya JetBrains.</li>
<li>Sistem pembuatan berbasis Gradle yang fleksibel.</li>
<li>Buat berbagai generasi APK dan variannya.</li>
<li>Dukungan template bertambah untuk Google Services dan aneka tipe perangkat.</li>
<li>Editor layout yang lengkap dengan dukungan untuk pengeditan tema.</li>
<li>Alat penambal untuk solusi kinerja, kegunaan, kompatibilitas versi, dan masalah lain.</li>
<li>ProGuard dan kemampuan penandatanganan aplikasi.</li>
<li>Dukungan bawaan untuk Google Cloud Platform, mempermudah integrasi Google Cloud
Messaging dan App Engine.</li>
</ul>
<p style="margin:0">
Untuk detail selengkapnya tentang fitur-fitur yang tersedia di Android Studio,
bacalah panduan <a href="{@docRoot}tools/studio/index.html">Dasar-Dasar Android Studio</a>.</p>
</div>
<p>Jika Anda menggunakan Eclipse dengan ADT, ingatlah bahwa Android Studio sekarang merupakan IDE resmi
untuk Android, jadi Anda harus beralih ke Android Studio untuk menerima semua
pembaruan terakhir IDE. Untuk bantuan dalam memindahkan proyek,
lihat <a href="{@docRoot}sdk/installing/migrate.html">Beralih ke Android
Studio</a>.</p>
<h2 id="Requirements">Kebutuhan Sistem</h2>
<h3>Windows</h3>
<ul>
<li>Microsoft&reg; Windows&reg; 8/7/Vista/2003 (32 atau 64-bit)</li>
<li>RAM minimum 2 GB, RAM yang direkomendasikan 4 GB</li>
<li>Ruang hard-disk 400 MB</li>
<li>Setidaknya 1 GB untuk Android SDK, citra sistem emulator, dan cache</li>
<li>Resolusi layar minimum 1280 x 800</li>
<li>Java Development Kit (JDK) 7 </li>
<li>Opsional untuk emulator akselerasi: Prosesor Intel® dengan dukungan untuk Intel® VT-x, Intel® EM64T
(Intel® 64), dan fungsionalitas Execute Disable (XD) Bit</li>
</ul>
<h3>Mac OS X</h3>
<ul>
<li>Mac&reg; OS X&reg; 10.8.5 atau yang lebih tinggi, hingga 10.9 (Mavericks)</li>
<li>RAM minimum 2 GB, RAM yang direkomendasikan 4 GB</li>
<li>Ruang hard-disk 400 MB</li>
<li>Setidaknya 1 GB untuk Android SDK, citra sistem emulator, dan cache</li>
<li>Resolusi layar minimum 1280 x 800</li>
<li>Java Runtime Environment (JRE) 6</li>
<li>Java Development Kit (JDK) 7</li>
<li>Opsional untuk emulator akselerasi: Prosesor Intel® dengan dukungan untuk Intel® VT-x, Intel® EM64T
(Intel® 64), dan fungsionalitas Execute Disable (XD) Bit</li>
</ul>
<p>Pada Mac OS, jalankan Android Studio dengan Java Runtime Environment (JRE) 6 untuk rendering
font yang dioptimalkan. Kemudian Anda bisa mengonfigurasi proyek untuk menggunakan Java Development Kit (JDK) 6 atau JDK 7.</p>
<h3>Linux</h3>
<ul>
<li>Desktop GNOME atau KDE</li>
<li>GNU C Library (glibc) 2.15 atau yang lebih baru</li>
<li>RAM minimum 2 GB, RAM yang direkomendasikan 4 GB</li>
<li>Ruang hard-disk 400 MB</li>
<li>Setidaknya 1 GB untuk Android SDK, citra sistem emulator, dan cache</li>
<li>Resolusi layar minimum 1280 x 800</li>
<li>Oracle&reg; Java Development Kit (JDK) 7 </li>
</ul>
<p>Telah diuji pada Ubuntu&reg; 14.04, Trusty Tahr (distribusi 64-bit yang mampu menjalankan
aplikasi 32-bit).</p>
<h2 id="Other" style="clear:left">Opsi Unduhan Lain</h2>
<!-- alternative SDK options follows -->

View File

@@ -0,0 +1,226 @@
page.title=Menambahkan Paket SDK
page.tags=sdk manager
@jd:body
<style>
ol.large {
margin-left:0;
}
ol.large > li {
list-style-position: inside;
list-style-type:none;
margin:30px 0 0 0;
padding:30px 20px;
background:#eee;
}
ol.large > li:nth-child(odd) {
}
ol.large > li:before {
display:inline;
left:-40px;
float:left;
width:20px;
font-size:20px;
line-height:20px;
}
ol.large > li > h2 {
font-size:20px;
line-height:20px;
padding:0 0 0 20px;
margin:0 0 20px 0;
display:inline;
font-weight:normal;
}
ol.large > li:nth-child(1):before {
content:"1. ";
}
ol.large > li:nth-child(2):before {
content:"2. ";
}
ol.large > li:nth-child(3):before {
content:"3. ";
}
ol.large > li:nth-child(4):before {
content:"4. ";
}
ol.large > li:nth-child(5):before {
content:"5. ";
}
ol.large > li:nth-child(6):before {
content:"6. ";
}
</style>
<p>
Secara default, Android SDK tidak mencakup segala sesuatu yang Anda perlukan untuk memulai pengembangan.
SDK memisahkan alat, platform, dan komponen lain ke dalam paket yang bisa Anda
unduh bila diperlukan dengan menggunakan
<a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.
Jadi, sebelum Anda bisa memulai, ada beberapa paket yang harus Anda tambahkan ke Android SDK Anda.</p>
<p>Untuk mulai menambahkan paket, jalankan Android SDK Manager dengan salah satu cara berikut:</p>
<ul>
<li>Di Android Studio, klik <strong>SDK Manager</strong>
<img src="{@docRoot}images/tools/sdk-manager-studio.png" style="vertical-align:bottom;margin:0;height:17px" /> di toolbar.</li>
<li>Jika Anda tidak menggunakan Android Studio:
<ul>
<li>Windows: Klik ganda file <code>SDK Manager.exe</code> pada akar direktori Android
SDK.</li>
<li>Mac/Linux: Buka sebuah terminal dan arahkan ke direktori <code>tools/</code> di
lokasi instalasi Android SDK, lalu jalankan <code>android sdk</code>.</li>
</ul>
</li>
</ul>
<p>Bila Anda membuka SDK Manager untuk pertama kali, beberapa paket akan dipilih secara
default. Biarkan dipilih, namun pastikan bahwa Anda mempunyai semua yang Anda perlukan
untuk persiapan dengan mengikuti langkah-langkah ini:</p>
<ol class="large">
<li>
<h2 id="GetTools" class="norule">Dapatkan alat-alat SDK terbaru</h2>
<img src="/images/sdk_manager_packages.png" alt="" width="350" style="float:right;margin-left:20px" />
<p>Setidaknya saat menyiapkan Android SDK,
Anda harus mengunduh platform Android dan alat-alat terbaru:</p>
<ol>
<li>Buka direktori Tools dan pilih:
<ul>
<li><strong>Android SDK Tools</strong></li>
<li><strong>Android SDK Platform-tools</strong></li>
<li><strong>Android SDK Build-tools</strong> (versi tertinggi)</li>
</ul>
</li>
<li>Buka folder Android X.X (versi terbaru) yang pertama dan pilih:
<ul>
<li><strong>SDK Platform</strong></li>
<li>Sebuah citra sistem untuk emulator, seperti <br>
<strong>ARM EABI v7a System Image</strong></li>
</ul>
</li>
</ol>
</li>
<li>
<h2 id="GetSupportLib" class="norule">Dapatkan pustaka dukungan untuk API tambahan</h2>
<div class="sidebox">
<p>Pustaka dukungan diperlukan untuk:</p>
<ul>
<li><a href="{@docRoot}wear/index.html">Android Wear</a></li>
<li><a href="{@docRoot}tv/index.html">Android TV</a></li>
<li><a href="{@docRoot}google/play-services/cast.html">Google Cast</a></li>
</ul>
<p>Pustaka ini juga menyediakan API populer:</p>
<ul>
<li><a href="{@docRoot}reference/android/support/v4/widget/DrawerLayout.html">Drawer
navigasi</a></li>
<li><a href="{@docRoot}reference/android/support/v4/view/ViewPager.html">Tampilan usap</a></li>
<li><a href="{@docRoot}reference/android/support/v7/app/ActionBar.html">Action-bar
yang kompatibel dengan versi lama</a></li>
</ul>
</div>
<p><a href="{@docRoot}tools/support-library/features.html">Android Support Library</a>
menyediakan set API tambahan yang kompatibel dengan sebagian besar versi Android.</p>
<p>Buka direktori <strong>Extras</strong> dan pilih:</p>
<ul>
<li><strong>Android Support Repository</strong></li>
<li><strong>Android Support Library</strong></li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
</li>
<li>
<h2 id="GetGoogle" class="norule">Dapatkan Google Play services untuk API yang lebih banyak lagi</h2>
<div class="sidebox">
<p>API Google Play services menyediakan beragam fitur dan layanan untuk aplikasi Android
Anda, misalnya:</p>
<ul>
<li><a href="{@docRoot}google/play-services/plus.html">Autentikasi pengguna</a></li>
<li><a href="{@docRoot}google/play-services/maps.html">Google Maps</a></li>
<li><a href="{@docRoot}google/play-services/cast.html">Google Cast</a></li>
<li><a href="{@docRoot}google/play-services/games.html">Skor dan
papan peringkat permainan</a></li>
<li><a href="{@docRoot}google/play-services/index.html">Dan masih banyak lagi</a></li>
</ul>
</div>
<p>Untuk mengembangkan aplikasi dengan Google API, Anda memerlukan paket Google Play services:</p>
<p>Buka direktori <strong>Extras</strong> dan pilih:</p>
<ul>
<li><strong>Google Repository</strong></li>
<li><strong>Google Play services</strong></li>
</ul>
<p class="note"><strong>Catatan:</strong> API Google Play services tidak tersedia pada semua
perangkat berbasis Android, namun tersedia pada semua perangkat dengan Google Play Store. Untuk menggunakan API ini
dalam emulator Android, Anda juga harus menginstal citra sistem <strong>Google API</strong>
dari direktori Android X.X terbaru di SDK Manager.</p>
</li>
<li>
<h2 id="Install" class="norule">Instal paket tersebut</h2>
<p>Setelah Anda memilih semua paket yang diinginkan, teruskan untuk menginstal:</p>
<ol>
<li>Klik <strong>Install X packages</strong>.</li>
<li>Di jendela berikutnya, klik ganda masing-masing nama paket di sebelah kiri
untuk menyetujui perjanjian lisensinya masing-masing.</li>
<li>Klik <strong>Install</strong>.</li>
</ol>
<p>Kemajuan pengunduhan diperlihatkan di bagian bawah jendela SDK Manager.
<strong>Jangan keluar dari SDK Manager</strong> karena hal itu akan membatalkan pengunduhan.</p>
</li>
<li>
<h2 id="Build" class="norule">Bangun sesuatu!</h2>
<p>Dengan adanya semua paket di atas di Android SDK, maka Anda siap untuk membangun aplikasi
untuk Android. Dengan tersedianya berbagai alat baru dan API lainnya, maka tinggal jalankan SDK Manager
untuk mengunduh paket baru bagi SDK Anda.</p>
<p>Inilah beberapa opsi cara Anda untuk melanjutkan:</p>
<div class="cols" style="padding:10px 0">
<div class="col-4">
<h3>Persiapkan</h3>
<p>Jika Anda masih baru dengan pengembangan Android, pelajari dasar-dasar aplikasi Android dengan mengikuti
panduan untuk <strong><a href="{@docRoot}training/basics/firstapp/index.html">Membangun Aplikasi Pertama Anda</a></strong>.</p>
</div>
<div class="col-4 box">
<h3>Bangun untuk perangkat wearable</h3>
<p>Jika Anda siap memulai pembangunan aplikasi untuk perangkat wearable Android, lihat panduan untuk
<strong><a href="{@docRoot}wear/preview/start.html">Membangun Aplikasi untuk Android Wear</a></strong>.</p>
</div>
<div class="col-4 box">
<h3>Gunakan Google API</h3>
<p>Untuk mulai menggunakan Google API, seperti Maps atau
layanan Play Game, lihat panduan untuk
<strong><a href="{@docRoot}google/play-services/setup.html">Mempersiapkan Google Play
Services</a></strong>.</p>
</div>
</div><!-- end cols -->
</li>
</ol>

View File

@@ -0,0 +1,550 @@
page.title=Mendefinisikan Animasi Custom
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Pelajaran ini mengajarkan Anda cara</h2>
<ol>
<li><a href="#Touch">Menyesuaikan Umpan Balik Sentuh</a></li>
<li><a href="#Reveal">Menggunakan Reveal Effect</a></li>
<li><a href="#Transitions">Menyesuaikan Transisi Aktivitas</a></li>
<li><a href="#ViewState">Menganimasikan Perubahan Status Tampilan</a></li>
<li><a href="#AnimVector">Menganimasikan Drawable Vektor</a></li>
</ol>
<h2>Anda juga harus membaca</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
</ul>
</div>
</div>
<p>Animasi dalam desain bahan memberi pengguna umpan balik tentang tindakannya dan menyediakan
kesinambungan visual saat pengguna berinteraksi dengan aplikasi Anda. Tema bahan menyediakan beberapa animasi default
untuk tombol dan transisi aktivitas, dan Android 5.0 (API level 21) ke atas memungkinkan Anda menyesuaikan
animasi ini dan membuat yang baru:</p>
<ul>
<li>Umpan balik sentuh</li>
<li>Singkap Melingkar</li>
<li>Transisi aktivitas</li>
<li>Gerakan melengkung</li>
<li>Perubahan status tampilan</li>
</ul>
<h2 id="Touch">Menyesuaikan Umpan Balik Sentuh</h2>
<p>Umpan balik sentuh dalam desain bahan menyediakan konfirmasi visual seketika pada
titik kontak bila pengguna berinteraksi dengan elemen UI. Animasi umpan balik sentuh default
untuk tombol menggunakan kelas {@link android.graphics.drawable.RippleDrawable} baru, yang bertransisi
di antara berbagai status dengan efek riak.</p>
<p>Di sebagian besar kasus, Anda harus menerapkan fungsionalitas ini dalam XML tampilan dengan menetapkan
latar belakang tampilan sebagai:</p>
<ul>
<li><code>?android:attr/selectableItemBackground</code> untuk riak berbatas.</li>
<li><code>?android:attr/selectableItemBackgroundBorderless</code> untuk riak yang meluas ke luar
tampilan. Latar belakang ini akan digambar di atas, dan dibatasi oleh, induk tampilan terdekat dengan
latar belakang non-null.</li>
</ul>
<p class="note"><strong>Catatan:</strong> <code>selectableItemBackgroundBorderless</code> adalah
atribut baru yang diperkenalkan di API level 21.</p>
<p>Atau, Anda bisa mendefinisikan {@link android.graphics.drawable.RippleDrawable}
sebagai sumber daya XML dengan menggunakan elemen <code>ripple</code>.</p>
<p>Anda bisa menetapkan warna ke objek-objek {@link android.graphics.drawable.RippleDrawable}. Untuk mengubah
warna default umpan balik sentuh, gunakan atribut <code>android:colorControlHighlight</code>
tema.</p>
<p>Untuk informasi selengkapnya, lihat referensi API bagi kelas {@link
android.graphics.drawable.RippleDrawable}.</p>
<h2 id="Reveal">Menggunakan Reveal Effect</h2>
<p>Animasi singkap memberi pengguna kesinambungan visual saat menampilkan atau menyembunyikan sekelompok
elemen UI. Metode {@link android.view.ViewAnimationUtils#createCircularReveal
ViewAnimationUtils.createCircularReveal()} memungkinkan Anda menganimasikan lingkaran terpangkas
untuk memperlihatkan atau menyembunyikan tampilan.</p>
<p>Untuk memperlihatkan tampilan yang sebelumnya tidak terlihat dengan menggunakan efek ini:</p>
<pre>
// previously invisible view
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
</pre>
<p>Untuk menyembunyikan sebuah tampilan yang sebelumnya terlihat dengan menggunakan efek ini:</p>
<pre>
// previously visible view
final View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
&#64;Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
</pre>
<h2 id="Transitions">Menyesuaikan Transisi Aktivitas</h2>
<!-- shared transition video -->
<div style="width:290px;margin-left:35px;float:right">
<div class="framed-nexus5-port-span-5">
<video class="play-on-hover" autoplay="">
<source src="{@docRoot}design/material/videos/ContactsAnim.mp4">
<source src="{@docRoot}design/material/videos/ContactsAnim.webm">
<source src="{@docRoot}design/material/videos/ContactsAnim.ogv">
</video>
</div>
<div style="font-size:10pt;margin-left:20px;margin-bottom:30px">
<p class="img-caption" style="margin-top:3px;margin-bottom:10px"><strong>Gambar 1</strong> - Transisi
dengan elemen bersama.</p>
<em>Untuk memutar ulang film, klik layar perangkat</em>
</div>
</div>
<p>Transisi aktivitas dalam aplikasi desain bahan memberikan koneksi visual antar berbagai status
melalui gerakan dan transformasi di antara elemen umum. Anda bisa menetapkan animasi custom untuk
masuk ke dan keluar dari transisi dan untuk transisi elemen bersama di antara aktivitas.</p>
<ul>
<li>Transisi <strong>masuk</strong> menentukan cara tampilan di aktivitas memasuki suatu babak.
misalnya, dalam transisi masuk <em>explode</em>, tampilan memasuki babak dari sisi luar
dan melayang masuk ke arah tengah layar.</li>
<li>Transisi <strong>keluar</strong> menentukan cara tampilan di aktivitas keluar dari suatu babak. Misalnya
, dalam transisi keluar <em>explode</em>, tampilan akan keluar dari babak dari bagian
tengahnya.</li>
<li>Transisi <strong>elemen bersama</strong> menentukan cara menggunakan bersama suatu tampilan
oleh dua transisi aktivitas di antara aktivitas-aktivitas ini. Misalnya, jika dua aktivitas memiliki
gambar yang sama dengan posisi dan ukuran berbeda, transisi elemen bersama <em>changeImageTransform</em>
mentransformasikan dan menskalakan gambar secara mulus di antara aktivitas-aktivitas ini.</li>
</ul>
<p>Android 5.0 (API level 21) mendukung transisi masuk dan transisi keluar ini:</p>
<ul>
<li><em>explode</em> - Memindahkan tampilan masuk ke atau keluar dari tengah babak.</li>
<li><em>slide</em> - Memindahkan tampilan masuk ke atau keluar dari salah satu tepi babak.</li>
<li><em>fade</em> - Menambahkan atau menghapus tampilan dari babak dengan mengubah opasitasnya.</li>
</ul>
<p>Transisi apa pun yang memperluas kelas {@link android.transition.Visibility} didukung
sebagai transisi masuk atau transisi keluar. Untuk informasi selengkapnya, lihat referensi API untuk kelas
{@link android.transition.Transition}.</p>
<p>Android 5.0 (API level 21) juga mendukung transisi elemen bersama ini:</p>
<ul>
<li><em>changeBounds</em> - Menganimasikan perubahan pada batas-batas layout tampilan target.</li>
<li><em>changeClipBounds</em> - Menganimasikan perubahan pada batas-batas pemangkasan tampilan target.</li>
<li><em>changeTransform</em> - Menganimasikan perubahan pada skala dan rotasi tampilan target.</li>
<li><em>changeImageTransform</em> - Menganimasikan perubahan pada ukuran dan skala gambar target.</li>
</ul>
<p>Bila Anda mengaktifkan transisi aktivitas dalam aplikasi, transisi memudar-silang default akan
diaktifkan di antara aktivitas masuk dan aktivitas keluar.</p>
<img src="{@docRoot}training/material/images/SceneTransition.png" alt="" width="600" height="405" style="margin-top:20px" />
<p class="img-caption">
  <strong>Gambar 2</strong> - Transisi babak dengan satu elemen bersama.
</p>
<h3>Menetapkan transisi custom</h3>
<p>Pertama, aktifkan transisi konten jendela dengan atribut <code>android:windowContentTransitions</code>
bila Anda mendefinisikan gaya yang mewarisi tema bahan. Anda juga bisa menetapkan
transisi-transisi masuk, keluar, dan elemen bersama dalam definisi gaya:</p>
<pre>
&lt;style name="BaseAppTheme" parent="android:Theme.Material">
&lt;!-- enable window content transitions -->
&lt;item name="android:windowContentTransitions">true&lt;/item>
&lt;!-- specify enter and exit transitions -->
&lt;item name="android:windowEnterTransition">@transition/explode&lt;/item>
&lt;item name="android:windowExitTransition">@transition/explode&lt;/item>
&lt;!-- specify shared element transitions -->
&lt;item name="android:windowSharedElementEnterTransition">
&#64;transition/change_image_transform&lt;/item>
&lt;item name="android:windowSharedElementExitTransition">
&#64;transition/change_image_transform&lt;/item>
&lt;/style>
</pre>
<p>Transisi <code>change_image_transform</code> dalam contoh ini didefinisikan sebagai berikut:</p>
<pre>
&lt;!-- res/transition/change_image_transform.xml -->
&lt;!-- (see also Shared Transitions below) -->
&lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
&lt;changeImageTransform/>
&lt;/transitionSet>
</pre>
<p>Elemen <code>changeImageTransform</code> menunjukkan
kelas {@link android.transition.ChangeImageTransform}. Untuk informasi selengkapnya, lihat referensi
API untuk {@link android.transition.Transition}.</p>
<p>Sebaliknya, untuk mengaktifkan transisi konten jendela dalam kode Anda, panggil
metode {@link android.view.Window#requestFeature Window.requestFeature()}:</p>
<pre>
// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// set an exit transition
getWindow().setExitTransition(new Explode());
</pre>
<p>Untuk menetapkan transisi dalam kode Anda, panggil metode-metode ini dengan objek {@link
android.transition.Transition}:</p>
<ul>
<li>{@link android.view.Window#setEnterTransition Window.setEnterTransition()}</li>
<li>{@link android.view.Window#setExitTransition Window.setExitTransition()}</li>
<li>{@link android.view.Window#setSharedElementEnterTransition
Window.setSharedElementEnterTransition()}</li>
<li>{@link android.view.Window#setSharedElementExitTransition
Window.setSharedElementExitTransition()}</li>
</ul>
<p>Metode {@link android.view.Window#setExitTransition setExitTransition()} dan {@link
android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} mendefinisikan
transisi keluar untuk aktivitas yang memanggil. Metode {@link android.view.Window#setEnterTransition
setEnterTransition()} dan {@link android.view.Window#setSharedElementEnterTransition
setSharedElementEnterTransition()} mendefinisikan transisi masuk untuk aktivitas yang dipanggil.</p>
<p>Untuk mendapatkan efek penuh sebuah transisi, Anda harus mengaktifkan transisi konten jendela pada
aktivitas yang memanggil maupun aktivitas yang dipanggil. Jika tidak, aktivitas yang memanggil akan memulai transisi keluar,
namun kemudian Anda akan melihat transisi jendela (seperti mengelupas atau memudar).</p>
<p>Untuk memulai transisi masuk sesegera mungkin, gunakan metode
{@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()}
pada aktivitas yang dipanggil. Ini memungkinkan Anda mendapatkan transisi masuk yang lebih dramatis.</p>
<h3>Memulai aktivitas dengan menggunakan transisi</h3>
<p>Jika Anda mengaktifkan transisi dan mengatur transisi keluar untuk aktivitas, transisi itu akan diaktifkan
bila Anda menjalankan aktivitas lain sebagai berikut:</p>
<pre>
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
</pre>
<p>Jika Anda telah mengatur transisi masuk untuk aktivitas kedua, transisi juga akan diaktifkan
bila aktivitas dimulai. Untuk menonaktifkan transisi bila Anda memulai aktivitas lain, sediakan
bundel opsi <code>null</code>.</p>
<h3>Memulai aktivitas dengan satu elemen bersama</h3>
<p>Untuk membuat animasi transisi layar di antara dua aktivitas yang memiliki satu elemen bersama:</p>
<ol>
<li>Aktifkan transisi konten jendela dalam tema Anda.</li>
<li>Tetapkan transisi elemen bersama dalam gaya Anda.</li>
<li>Definisikan transisi Anda sebagai sumber daya XML.</li>
<li>Tetapkan nama umum pada elemen bersama dalam kedua layout dengan
atribut <code>android:transitionName</code>.</li>
<li>Gunakan metode {@link android.app.ActivityOptions#makeSceneTransitionAnimation
ActivityOptions.makeSceneTransitionAnimation()}.</li>
</ol>
<pre>
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);
// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);
// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
&#64;Override
public void onClick(View view) {
Intent intent = new Intent(this, Activity2.class);
// create the transition animation - the images in the layouts
// of both activities are defined with android:transitionName="robot"
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(this, androidRobotView, "robot");
// start the new activity
startActivity(intent, options.toBundle());
}
});
</pre>
<p>Untuk tampilan dinamis bersama yang Anda hasilkan dalam kode, gunakan
metode {@link android.view.View#setTransitionName View.setTransitionName()} untuk menetapkan
nama elemen umum di kedua aktivitas.</p>
<p>Untuk membalik animasi transisi babak bila Anda menyelesaikan aktivitas kedua, panggil metode
{@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()}
sebagai ganti {@link android.app.Activity#finish Activity.finish()}.</p>
<h3>Memulai aktivitas dengan beberapa elemen bersama</h3>
<p>Untuk membuat animasi transisi babak antara dua aktivitas yang memiliki lebih dari satu
elemen bersama, definisikan elemen bersama di kedua layout dengan atribut <code>android:transitionName</code>
(atau gunakan metode {@link android.view.View#setTransitionName View.setTransitionName()}
di kedua aktivitas), dan buat sebuah objek {@link android.app.ActivityOptions} sebagai berikut:</p>
<pre>
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
Pair.create(view1, "agreedName1"),
Pair.create(view2, "agreedName2"));
</pre>
<h2 id="CurvedMotion">Menggunakan Gerakan Melengkung</h2>
<p>Animasi dalam desain bahan mengandalkan kurva untuk pola interpolasi waktu dan
gerakan spasial. Dengan Android 5.0 (API level 21) ke atas, Anda bisa mendefinisikan kurva pewaktuan custom dan
pola gerakan melengkung untuk animasi.</p>
<p>Kelas {@link android.view.animation.PathInterpolator} adalah interpolator baru berdasarkan sebuah
kurva Bézier atau objek {@link android.graphics.Path}. Interpolator ini menetapkan kurva gerakan
dalam bujur sangkar 1x1, dengan titik-titik jangkar di (0,0) dan (1,1) dan titik-titik kontrol sebagaimana ditetapkan menggunakan
argumen konstruktor. Anda juga bisa mendefinisikan interpolator path sebagai sumber daya XML:</p>
<pre>
&lt;pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:controlX1="0.4"
android:controlY1="0"
android:controlX2="1"
android:controlY2="1"/>
</pre>
<p>Sistem menyediakan sumber daya XML untuk tiga kurva dasar dalam
spesifikasi desain bahan:</p>
<ul>
<li><code>&#64;interpolator/fast_out_linear_in.xml</code></li>
<li><code>&#64;interpolator/fast_out_slow_in.xml</code></li>
<li><code>&#64;interpolator/linear_out_slow_in.xml</code></li>
</ul>
<p>Anda bisa meneruskan objek {@link android.view.animation.PathInterpolator} ke metode {@link
android.animation.Animator#setInterpolator Animator.setInterpolator()}.</p>
<p>Kelas {@link android.animation.ObjectAnimator} memiliki konstruktor-konstruktor baru yang memungkinkan Anda menganimasikan
koordinat bersama sebuah path dengan menggunakan dua atau beberapa properti sekaligus. Misalnya, animator berikut
menggunakan objek {@link android.graphics.Path} untuk menganimasikan properti X dan Y sebuah tampilan:</p>
<pre>
ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();
</pre>
<h2 id="ViewState">Menganimasikan Perubahan Status Tampilan</h2>
<p>Kelas {@link android.animation.StateListAnimator} memungkinkan Anda mendefinisikan animator yang berjalan bila
status tampilan berubah. Contoh berikut menampilkan cara mendefinisikan {@link
android.animation.StateListAnimator} sebagai sumber daya XML:</p>
<pre>
&lt;!-- animate the translationZ property of a view when pressed -->
&lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
&lt;item android:state_pressed="true">
&lt;set>
&lt;objectAnimator android:propertyName="translationZ"
android:duration="@android:integer/config_shortAnimTime"
android:valueTo="2dp"
android:valueType="floatType"/>
&lt;!-- you could have other objectAnimator elements
here for "x" and "y", or other properties -->
&lt;/set>
&lt;/item>
&lt;item android:state_enabled="true"
android:state_pressed="false"
android:state_focused="true">
&lt;set>
&lt;objectAnimator android:propertyName="translationZ"
android:duration="100"
android:valueTo="0"
android:valueType="floatType"/>
&lt;/set>
&lt;/item>
&lt;/selector>
</pre>
<p>Untuk menyertakan animasi status tampilan custom ke tampilan, definisikan animator menggunakan
elemen <code>selector</code> dalam sumber daya file XML sebagaimana dalam contoh ini, dan tetapkan ke
tampilan Anda dengan atribut <code>android:stateListAnimator</code>. Untuk menetapkan animator daftar status
ke sebuah tampilan dalam kode Anda, gunakan metode {@link android.animation.AnimatorInflater#loadStateListAnimator
AnimationInflater.loadStateListAnimator()}, dan tetapkan animator ke tampilan dengan
metode {@link android.view.View#setStateListAnimator View.setStateListAnimator()}.</p>
<p>Bila tema Anda memperluas tema bahan, tombol-tombol akan memiliki animasi Z secara default. Untuk menghindari
perilaku ini di tombol Anda, aturlah atribut <code>android:stateListAnimator</code> ke
<code>@null</code>.</p>
<p>Kelas {@link android.graphics.drawable.AnimatedStateListDrawable} memungkinkan Anda membuat drawable
yang menampilkan animasi di antara perubahan status tampilan terkait. Sebagian widget sistem di
Android 5.0 menggunakan animasi ini secara default. Contoh berikut menampilkan cara
mendefinisikan {@link android.graphics.drawable.AnimatedStateListDrawable} sebagai sumber daya XML:</p>
<pre>
&lt;!-- res/drawable/myanimstatedrawable.xml -->
&lt;animated-selector
xmlns:android="http://schemas.android.com/apk/res/android">
&lt;!-- provide a different drawable for each state-->
&lt;item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
android:state_pressed="true"/>
&lt;item android:id="@+id/focused" android:drawable="@drawable/drawableF"
android:state_focused="true"/>
&lt;item android:id="@id/default"
android:drawable="@drawable/drawableD"/>
&lt;!-- specify a transition -->
&lt;transition android:fromId="@+id/default" android:toId="@+id/pressed">
&lt;animation-list>
&lt;item android:duration="15" android:drawable="@drawable/dt1"/>
&lt;item android:duration="15" android:drawable="@drawable/dt2"/>
...
&lt;/animation-list>
&lt;/transition>
...
&lt;/animated-selector>
</pre>
<h2 id="AnimVector">Menganimasikan Drawable Vektor</h2>
<p><a href="{@docRoot}training/material/drawables.html#VectorDrawables">Drawable Vektor </a>
bisa diubah skalanya tanpa kehilangan definisi. Kelas {@link android.graphics.drawable.AnimatedVectorDrawable}
memungkinkan Anda menganimasikan properti drawable vektor.</p>
<p>Anda biasanya mendefinisikan drawable vektor yang dianimasikan dalam tiga file XML:</p>
<ul>
<li>Drawable vektor dengan elemen <code>&lt;vector&gt;</code> dalam
<code>res/drawable/</code></li>
<li>Drawable vektor animasi dengan elemen <code>&lt;animated-vector&gt;</code> dalam
<code>res/drawable/</code></li>
<li>Satu atau beberapa animator objek dengan elemen <code>&lt;objectAnimator&gt;</code> dalam
<code>res/anim/</code></li>
</ul>
<p>Drawable vektor yang dianimasikan bisa menganimasikan atribut elemen <code>&lt;group&gt;</code> dan
<code>&lt;path&gt;</code>. Elemen <code>&lt;group&gt;</code> mendefinisikan satu set
path atau subgrup, dan elemen <code>&lt;path&gt;</code> mendefinisikan path yang harus digambar.</p>
<p>Bila Anda mendefinisikan drawable vektor yang ingin dianimasikan, gunakan atribut <code>android:name</code>
untuk menetapkan nama unik ke grup dan path, sehingga Anda bisa merujuknya dari
definisi animator Anda. Misalnya:</p>
<pre>
&lt;!-- res/drawable/vectordrawable.xml -->
&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="64dp"
android:width="64dp"
android:viewportHeight="600"
android:viewportWidth="600">
&lt;group
<strong>android:name="rotationGroup"</strong>
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="45.0" >
&lt;path
<strong>android:name="v"</strong>
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
&lt;/group>
&lt;/vector>
</pre>
<p>Definisi drawable vektor yang dianimasikan merujuk pada grup dan path dalam drawable vektor
berdasarkan namanya:</p>
<pre>
&lt;!-- res/drawable/animvectordrawable.xml -->
&lt;animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vectordrawable" >
&lt;target
android:name="rotationGroup"
android:animation="@anim/rotation" />
&lt;target
android:name="v"
android:animation="@anim/path_morph" />
&lt;/animated-vector>
</pre>
<p>Definisi animasi menyatakan objek {@link android.animation.ObjectAnimator} atau {@link
android.animation.AnimatorSet}. Animator pertama dalam contoh ini memutar
grup target sebanyak 360 derajat:</p>
<pre>
&lt;!-- res/anim/rotation.xml -->
&lt;objectAnimator
android:duration="6000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360" />
</pre>
<p>Animator kedua dalam contoh ini perlahan-lahan mengubah bentuk path drawable vektor dari satu bentuk ke
bentuk yang lain. Kedua path harus kompatibel untuk morphing: keduanya harus memiliki jumlah perintah yang sama
dan jumlah parameter yang sama untuk setiap perintah.</p>
<pre>
&lt;!-- res/anim/path_morph.xml -->
&lt;set xmlns:android="http://schemas.android.com/apk/res/android">
&lt;objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType" />
&lt;/set>
</pre>
<p>Untuk informasi selengkapnya, lihat referensi API bagi {@link
android.graphics.drawable.AnimatedVectorDrawable}.</p>

View File

@@ -0,0 +1,168 @@
page.title=Mempertahankan Kompatibilitas
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Pelajaran ini mengajarkan Anda cara</h2>
<ol>
<li><a href="#Theme">Mendefinisikan Gaya Alternatif</a></li>
<li><a href="#Layouts">Menyediakan Layout Alternatif</a></li>
<li><a href="#SupportLib">Menggunakan Support Library</a></li>
<li><a href="#CheckVersion">Memeriksa Versi Sistem</a></li>
</ol>
<h2>Anda juga harus membaca</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
</ul>
</div>
</div>
<p>Sebagian fitur desain bahan seperti tema bahan dan transisi aktivitas custom
hanya tersedia pada Android 5.0 (API level 21) ke atas. Akan tetapi, Anda bisa mendesain aplikasi untuk menggunakan
fitur-fitur ini saat dijalankan pada perangkat yang mendukung desain bahan dan tetap kompatibel
dengan perangkat yang menjalankan rilis Android sebelumnya.</p>
<h2 id="Theme">Mendefinisikan Gaya Alternatif</h2>
<p>Anda bisa mengonfigurasi aplikasi untuk menggunakan tema bahan pada perangkat yang mendukungnya dan mengembalikan
ke tema lama pada perangkat yang menjalankan versi Android terdahulu:</p>
<ol>
<li>Definisikan tema yang mewarisi tema lama (seperti Holo) di
<code>res/values/styles.xml</code>.</li>
<li>Definisikan tema bernama sama yang mewarisi tema bahan di
<code>res/values-v21/styles.xml</code>.</li>
<li>Atur tema ini sebagai tema aplikasi Anda dalam file manifes.</li>
</ol>
<p class="note"><strong>Catatan:</strong>
Jika aplikasi Anda menggunakan tema bahan namun tidak menyediakan tema alternatif dengan cara ini,
aplikasi itu tidak akan berjalan pada versi Android sebelum 5.0.
</p>
<h2 id="Layouts">Menyediakan Layout Alternatif</h2>
<p>Jika layout yang Anda desain sesuai dengan panduan desain bahan tidak menggunakan salah satu
atribut XML baru yang diperkenalkan di Android 5.0 (API level 21), layout itu akan berfungsi pada
versi Android sebelumnya. Jika tidak, Anda bisa menyediakan layout alternatif. Anda juga bisa menyediakan
layout alternatif untuk menyesuaikan cara aplikasi ditampilkan pada versi Android terdahulu.</p>
<p>Buatlah file layout untuk Android 5.0 (API level 21) dalam <code>res/layout-v21/</code> dan
file layout alternatif untuk versi Android terdahulu dalam <code>res/layout/</code>.
Misalnya, <code>res/layout/my_activity.xml</code> adalah layout alternatif untuk
<code>res/layout-v21/my_activity.xml</code>.</p>
<p>Untuk menghindari duplikasi kode, definisikan gaya dalam <code>res/values/</code>, modifikasi
gaya di <code>res/values-v21/</code> untuk API baru, dan gunakan pewarisan gaya, dengan mendefinisikan
gaya dasar di <code>res/values/</code> dan mewarisi gaya di <code>res/values-v21/</code>.</p>
<h2 id="SupportLib">Menggunakan Support Library</h2>
<p><a href="{@docRoot}tools/support-library/features.html#v7">v7 Support Library</a>
r21 ke atas menyertakan fitur desain bahan berikut:</p>
<ul>
<li><a href="{@docRoot}training/material/theme.html">Gaya desain bahan</a> untuk beberapa widget sistem
bila Anda menerapkan salah satu tema <code>Theme.AppCompat</code>.</li>
<li><a href="{@docRoot}training/material/theme.html#ColorPalette">Atribut tema palet warna</a>
dalam tema <code>Theme.AppCompat</code>.</li>
<li>Widget {@link android.support.v7.widget.RecyclerView} untuk <a href="{@docRoot}training/material/lists-cards.html#RecyclerView">
menampilkan kumpulan data.</a></li>
<li>Widget {@link android.support.v7.widget.CardView} untuk <a href="{@docRoot}training/material/lists-cards.html#CardView">membuat kartu</a>.</li>
<li>Kelas {@link android.support.v7.graphics.Palette} untuk <a href="{@docRoot}training/material/drawables.html#ColorExtract">mengekstrak warna mencolok dari
gambar</a>.</li>
</ul>
<h3>Widget sistem</h3>
<p>Tema-tema <code>Theme.AppCompat</code> menyediakan gaya desain bahan untuk widget ini:</p>
<ul>
<li>{@link android.widget.EditText}</li>
<li>{@link android.widget.Spinner}</li>
<li>{@link android.widget.CheckBox}</li>
<li>{@link android.widget.RadioButton}</li>
<li>{@link android.support.v7.widget.SwitchCompat}</li>
<li>{@link android.widget.CheckedTextView}</li>
</ul>
<h3>Palet Warna</h3>
<p>Untuk memperoleh gaya desain bahan dan menyesuaikan palet warna dengan Android v7 Support
Library, terapkan salah satu tema <code>Theme.AppCompat</code>:</p>
<pre>
&lt;!-- extend one of the Theme.AppCompat themes -->
&lt;style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
&lt;!-- customize the color palette -->
&lt;item name="colorPrimary">@color/material_blue_500&lt;/item>
&lt;item name="colorPrimaryDark">@color/material_blue_700&lt;/item>
&lt;item name="colorAccent">@color/material_green_A200&lt;/item>
&lt;/style>
</pre>
<h3>Daftar dan Kartu</h3>
<p>Widget {@link android.support.v7.widget.RecyclerView} dan {@link
android.support.v7.widget.CardView} tersedia di versi Android terdahulu melalui
Android v7 Support Library dengan pembatasan ini:</p>
<ul>
<li>{@link android.support.v7.widget.CardView} memundurkan ke implementasi bayangan terprogram
dengan menggunakan pengisi tambahan.</li>
<li>{@link android.support.v7.widget.CardView} tidak memangkas tampilan anaknya yang berpotongan
dengan sudut melengkung.</li>
</ul>
<h3>Dependensi</h3>
<p>Untuk menggunakan fitur-fitur ini di versi Android sebelum 5.0 (API level 21), sertakan
Android v7 Support Library dalam proyek Anda sebagai <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependensi Gradle</a>:</p>
<pre>
dependencies {
compile 'com.android.support:appcompat-v7:21.0.+'
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>
<h2 id="CheckVersion">Memeriksa Versi Sistem</h2>
<p>Fitur berikut hanya tersedia di Android 5.0 (API level 21) ke atas:</p>
<ul>
<li>Transisi aktivitas</li>
<li>Umpan balik sentuh</li>
<li>Animasi membuka</li>
<li>Animasi berbasis path</li>
<li>Drawable vektor</li>
<li>Pewarnaan drawable</li>
</ul>
<p>Untuk menjaga kompatibilitas dengan versi Android terdahulu, periksa {@link
android.os.Build.VERSION#SDK_INT version} sistem saat runtime sebelum Anda memanggil API untuk salah satu
fitur ini:</p>
<pre>
// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Call some material design APIs here
} else {
// Implement this feature without material design
}
</pre>
<p class="note"><strong>Catatan:</strong> Untuk menetapkan versi Android yang didukung aplikasi Anda,
gunakan atribut <code>android:minSdkVersion</code> dan <code>android:targetSdkVersion</code>
dalam file manifes. Untuk menggunakan fitur desain bahan di Android 5.0, atur
atribut <code>android:targetSdkVersion</code> ke <code>21</code>. Untuk informasi selengkapnya, lihat
panduan <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">API
&lt;uses-sdk&gt;</a>.</p>

View File

@@ -0,0 +1,126 @@
page.title=Bekerja dengan Drawable
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Pelajaran ini mengajarkan Anda cara</h2>
<ol>
<li><a href="#DrawableTint">Mewarnai Sumber Daya Drawable</a></li>
<li><a href="#ColorExtract">Mengekstrak Warna Mencolok dari Gambar</a></li>
<li><a href="#VectorDrawables">Membuat Drawable Vektor</a></li>
</ol>
<h2>Anda juga harus membaca</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
</ul>
</div>
</div>
<p>Kemampuan berikut untuk drawable membantu Anda mengimplementasikan desain bahan dalam aplikasi Anda:</p>
<ul>
<li>Pewarnaan drawable</li>
<li>Ekstraksi warna mencolok</li>
<li>Drawable vektor</li>
</ul>
<p>Pelajaran ini menampilkan cara menggunakan fitur-fitur ini dalam aplikasi Anda.</p>
<h2 id="DrawableTint">Mewarnai Sumber Daya Drawable</h2>
<p>Dengan Android 5.0 (API level 21) ke atas, Anda bisa mewarnai bitmap dan sembilan-tambalan yang didefinisikan sebagai
alpha-mask. Anda bisa mewarnainya dengan sumber daya warna atau atribut tema yang mencocokkan ke
sumber daya warna (misalnya, <code>?android:attr/colorPrimary</code>). Biasanya, Anda membuat aset ini
hanya sekali dan mewarnainya secara otomatis agar cocok dengan tema Anda.</p>
<p>Anda bisa menerapkan warna ke objek {@link android.graphics.drawable.BitmapDrawable} atau {@link
android.graphics.drawable.NinePatchDrawable} dengan metode {@code setTint()}. Anda juga bisa
mengatur warna dan mode dalam layout dengan atribut <code>android:tint</code> dan
<code>android:tintMode</code>.</p>
<h2 id="ColorExtract">Mengekstrak Warna Mencolok dari Gambar</h2>
<p>Android Support Library r21 ke atas menyertakan kelas {@link
android.support.v7.graphics.Palette}, yang memungkinkan Anda mengekstrak warna mencolok dari gambar.
Kelas ini mengekstrak warna mencolok berikut:</p>
<ul>
<li>Menyala</li>
<li>Menyala pekat</li>
<li>Menyala pucat</li>
<li>Pudar</li>
<li>Pudar pekat</li>
<li>Pudar pucat</li>
</ul>
<p>Untuk mengekstrak warna-warna ini, teruskan objek {@link android.graphics.Bitmap} ke
metode statis {@link android.support.v7.graphics.Palette#generate Palette.generate()} dalam
thread latar belakang tempat Anda memuat gambar. Jika Anda tidak bisa menggunakan thread itu, panggil metode
{@link android.support.v7.graphics.Palette#generateAsync Palette.generateAsync()} dan
sediakan listener sebagai gantinya.</p>
<p>Anda bisa mengambil warna mencolok dari gambar dengan metode getter di kelas
<code>Palette</code>, misalnya <code>Palette.getVibrantColor</code>.</p>
<p>Untuk menggunakan kelas {@link android.support.v7.graphics.Palette} dalam proyek Anda, tambahkan
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a> berikut ke
modul aplikasi Anda:</p>
<pre>
dependencies {
...
compile 'com.android.support:palette-v7:21.0.0'
}
</pre>
<p>Untuk informasi selengkapnya, lihat referensi API untuk kelas {@link android.support.v7.graphics.Palette}.
</p>
<h2 id="VectorDrawables">Membuat Drawable Vektor</h2>
<!-- video box -->
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=wlFVIIstKmA" style="margin-top:18px">
<div>
<h3>Video</h3>
<p>Grafis Vektor Android</p>
</div>
</a>
<p>Di Android 5.0 (API Level 21) ke atas, Anda bisa mendefinisikan drawable vektor, yang berubah skala tanpa
kehilangan definisi. Anda hanya memerlukan satu file aset per gambar vektor, bukan file aset untuk
setiap densitas layar seperti pada gambar bitmap. Untuk membuat gambar vektor, Anda mendefinisikan detail
bentuknya dalam sebuah elemen XML <code>&lt;vector&gt;</code>.</p>
<p>Contoh berikut mendefinisikan gambar vektor berbentuk hati:</p>
<pre>
&lt;!-- res/drawable/heart.xml -->
&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
&lt;!-- intrinsic size of the drawable -->
android:height="256dp"
android:width="256dp"
&lt;!-- size of the virtual canvas -->
android:viewportWidth="32"
android:viewportHeight="32">
&lt;!-- draw a path -->
&lt;path android:fillColor="#8fff"
android:pathData="M20.5,9.5
c-1.955,0,-3.83,1.268,-4.5,3
c-0.67,-1.732,-2.547,-3,-4.5,-3
C8.957,9.5,7,11.432,7,14
c0,3.53,3.793,6.257,9,11.5
c5.207,-5.242,9,-7.97,9,-11.5
C25,11.432,23.043,9.5,20.5,9.5z" />
&lt;/vector>
</pre>
<p>Gambar vektor direpresentasikan di Android sebagai objek {@link android.graphics.drawable.VectorDrawable}.
Untuk informasi selengkapnya tentang sintaks <code>pathData</code>, lihat <a href="http://www.w3.org/TR/SVG11/paths.html#PathData">Referensi Path SVG</a>. Untuk informasi selengkapnya
tentang menganimasikan properti drawable vektor, lihat
<a href="{@docRoot}training/material/animations.html#AnimVector">Menganimasikan Drawable Vektor</a>.</p>

View File

@@ -0,0 +1,171 @@
page.title=Memulai
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Pelajaran ini mengajarkan Anda cara</h2>
<ol>
<li><a href="#ApplyTheme">Menerapkan Tema Bahan</a></li>
<li><a href="#Layouts">Mendesain Layout Anda</a></li>
<li><a href="#Depth">Menetapkan Ketinggian di Tampilan Anda</a></li>
<li><a href="#ListsCards">Membuat Daftar dan Kartu</a></li>
<li><a href="#Animations">Menyesuaikan Animasi Anda</a></li>
</ol>
<h2>Anda juga harus membaca</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
</ul>
</div>
</div>
<p>Untuk membuat aplikasi dengan desain bahan:</p>
<ol>
<li style="margin-bottom:10px">
Tinjaulah <a href="http://www.google.com/design/spec">spesifikasi desain bahan</a>.</li>
<li style="margin-bottom:10px">
Terapkan <strong>tema</strong> bahan ke aplikasi Anda.</li>
<li style="margin-bottom:10px">
Buat <strong>layout</strong> agar mengikuti panduan desain bahan.</li>
<li style="margin-bottom:10px">
Tetapkan <strong>ketinggian</strong> tampilan Anda untuk menghasilkan bayangan.</li>
<li style="margin-bottom:10px">
Gunakan <strong>widget</strong> sistem untuk daftar dan kartu.</li>
<li style="margin-bottom:10px">
Sesuaikan <strong>animasi</strong> di aplikasi Anda.</li>
</ol>
<h3>Mempertahankan kompatibilitas mundur</h3>
<p>Anda bisa menambahkan banyak fitur desain bahan ke aplikasi sekaligus mempertahankan kompatibilitas dengan
versi Android sebelum 5.0. Untuk informasi selengkapnya, lihat
<a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a>.</p>
<h3>Memperbarui aplikasi dengan desain bahan</h3>
<p>Untuk memperbarui aplikasi yang ada guna memasukkan desain bahan, perbarui layout Anda dengan mengikuti
panduan desain bahan. Juga pastikan memasukkan kedalaman, umpan balik sentuh, dan
animasi.</p>
<h3>Membuat aplikasi baru dengan desain bahan</h3>
<p>Jika Anda sedang membuat aplikasi baru dengan fitur desain bahan, <a href="http://www.google.com/design/spec">panduan desain bahan</a> akan memberi Anda
kerangka kerja desain yang kohesif. Ikuti panduan itu dan gunakan fungsionalitas baru di
kerangka kerja Android untuk mendesain dan mengembangkan aplikasi Anda.</p>
<h2 id="ApplyTheme">Menerapkan Tema Bahan</h2>
<p>Untuk menerapkan tema bahan dalam aplikasi Anda, tetapkan gaya yang mewarisi
<code>android:Theme.Material</code>:</p>
<pre>
&lt;!-- res/values/styles.xml -->
&lt;resources>
&lt;!-- your theme inherits from the material theme -->
&lt;style name="AppTheme" parent="android:Theme.Material">
&lt;!-- theme customizations -->
&lt;/style>
&lt;/resources>
</pre>
<p>Tema bahan menyediakan widget sistem terbaru yang memungkinkan Anda mengatur palet warnanya dan
animasi default untuk umpan balik sentuh dan transisi aktivitas. Untuk detail selengkapnya, lihat
<a href="{@docRoot}training/material/theme.html">Menggunakan Tema Bahan</a>.</p>
<h2 id="Layouts">Mendesain Layout Anda</h2>
<p>Selain menerapkan dan menyesuaikan tema bahan, layout Anda harus mematuhi
<a href="http://www.google.com/design/spec">panduan desain bahan</a>. Bila Anda mendesain
layout, berikan perhatian khusus pada hal-hal berikut:</p>
<ul>
<li>Petak patokan</li>
<li>Garis utama</li>
<li>Pengaturan Jarak</li>
<li>Ukuran target sentuh</li>
<li>Struktur layout</li>
</ul>
<h2 id="Depth">Menetapkan Ketinggian di Tampilan Anda</h2>
<p>Tampilan bisa menghasilkan bayangan, dan nilai ketinggian tampilan
menentukan ukuran bayangan dan urutan penggambarannya. Untuk mengatur ketinggian tampilan, gunakan
atribut <code>android:elevation</code> dalam layout:</p>
<pre>
&lt;TextView
android:id="&#64;+id/my_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/next"
android:background="&#64;color/white"
android:elevation="5dp" />
</pre>
<p>Properti <code>translationZ</code> baru memungkinkan Anda membuat animasi yang mencerminkan
perubahan sementara pada ketinggian tampilan. Perubahan ketinggian bisa berguna saat
<a href="{@docRoot}training/material/animations.html#ViewState">merespons
gerakan sentuh</a>.</p>
<p>Untuk detail selengkapnya, lihat <a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan
Bayangan dan Memangkas Tampilan</a>.</p>
<h2 id="ListsCards">Membuat Daftar dan Kartu</h2>
<p>{@link android.support.v7.widget.RecyclerView} adalah versi {@link
android.widget.ListView} yang lebih mudah dimasukkan dan mendukung beragam tipe layout serta memberikan peningkatan kinerja.
{@link android.support.v7.widget.CardView} memungkinkan Anda menampilkan potongan informasi dalam kartu dengan
tampilan konsisten di seluruh aplikasi. Contoh kode berikut memperagakan cara menyertakan
{@link android.support.v7.widget.CardView} dalam layout Anda:</p>
<pre>
&lt;android.support.v7.widget.CardView
android:id="&#64;+id/card_view"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardCornerRadius="3dp">
...
&lt;/android.support.v7.widget.CardView>
</pre>
<p>Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar
dan Kartu</a>.</p>
<h2 id="Animations">Menyesuaikan Animasi Anda</h2>
<p>Android 5.0 (API level 21) menyertakan API baru untuk membuat animasi custom di aplikasi Anda.
Misalnya, Anda bisa mengaktifkan transisi aktivitas dan mendefinisikan transisi keluar di
aktivitas:</p>
<pre>
public class MyActivity extends Activity {
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// enable transitions
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
setContentView(R.layout.activity_my);
}
public void onSomeButtonClicked(View view) {
getWindow().setExitTransition(new Explode());
Intent intent = new Intent(this, MyOtherActivity.class);
startActivity(intent,
ActivityOptions
.makeSceneTransitionAnimation(this).toBundle());
}
}
</pre>
<p>Bila Anda memulai aktivitas lain dari aktivitas ini, transisi keluar akan diaktifkan.</p>
<p>Untuk mengetahui selengkapnya tentang API animasi yang baru, lihat <a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi Custom</a>.</p>

View File

@@ -0,0 +1,60 @@
page.title=Desain Bahan untuk Pengembang
page.image=images/cards/material_2x.png
page.metaDescription=Pelajari cara menerapkan desain bahan pada aplikasi Anda.
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dependensi dan Prasyarat</h2>
<ul>
<li>Android 5.0 (API Level 21)</li>
</ul>
</div>
</div>
<p>Desain bahan adalah panduan komprehensif untuk desain visual, gerak, dan interaksi di
berbagai platform dan perangkat. Untuk menggunakan desain bahan di aplikasi Android, ikuti panduan
yang dijelaskan dalam
<a href="http://www.google.com/design/spec/material-design/introduction.html">spesifikasi desain bahan
</a> dan gunakan komponen serta fungsionalitas baru yang tersedia di Android 5.0
(API level 21).</p>
<p>Kelas ini menampilkan kepada Anda cara membuat aplikasi desain bahan dengan elemen-elemen berikut:</p>
<ul>
<li>Tema bahan</li>
<li>Widget untuk kartu dan daftar</li>
<li>Bayangan custom dan pemangkasan tampilan</li>
<li>Drawable vektor</li>
<li>Animasi custom</li>
</ul>
<p>Kelas ini juga mengajarkan cara mempertahankan kompatibilitas dengan versi Android sebelum
5.0 (API level 21) bila Anda menggunakan fitur desain bahan dalam aplikasi.</p>
<h2>Pelajaran</h2>
<dl>
<dt><a href="{@docRoot}training/material/get-started.html">Memulai</a></dt>
<dd>Pelajari cara memperbarui aplikasi Anda dengan fitur desain bahan.</dd>
<dt><a href="{@docRoot}training/material/theme.html">Menggunakan Tema Bahan</a></dt>
<dd>Pelajari cara menerapkan gaya desain bahan pada aplikasi Anda.</dd>
<dt><a href="{@docRoot}training/material/lists-cards.html">Membuat Daftar dan Kartu</a></dt>
<dd>Pelajari cara membuat daftar dan kartu dengan tampilan dan cara kerja yang konsisten menggunakan widget sistem.</dd>
<dt><a href="{@docRoot}training/material/shadows-clipping.html">Mendefinisikan Bayangan dan Memangkas Tampilan</a></dt>
<dd>Pelajari cara mengatur elevasi tampilan Anda untuk membuat bayangan custom dan cara memangkas tampilan.</dd>
<dt><a href="{@docRoot}training/material/drawables.html">Bekerja dengan Drawable</a></dt>
<dd>Pelajari cara membuat drawable vektor dan cara mewarnai sumber daya drawable.</dd>
<dt><a href="{@docRoot}training/material/animations.html">Mendefinisikan Animasi Custom</a></dt>
<dd>Pelajari cara membuat animasi custom untuk tampilan dan transisi aktivitas dengan elemen bersama.</dd>
<dt><a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a></dt>
<dd>Pelajari cara mempertahankan kompatibilitas dengan versi platform sebelum Android 5.0.</dd>
</dl>

View File

@@ -0,0 +1,266 @@
page.title=Membuat Daftar dan Kartu
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Pelajaran ini mengajarkan Anda cara</h2>
<ol>
<li><a href="#RecyclerView">Membuat Daftar</a></li>
<li><a href="#CardView">Membuat Kartu</a></li>
<li><a href="#Dependencies">Menambahkan Dependensi</a></li>
</ol>
<h2>Anda juga harus membaca</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
</ul>
</div>
</div>
<p>Untuk membuat daftar dan kartu yang kompleks dengan gaya desain bahan di aplikasi, Anda bisa menggunakan widget
{@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView}.
</p>
<h2 id="RecyclerView">Membuat Daftar</h2>
<p>Widget {@link android.support.v7.widget.RecyclerView} adalah
versi {@link android.widget.ListView} yang lebih maju dan fleksibel. Widget ini adalah kontainer untuk menampilkan set data
besar yang bisa digulir secara sangat efisien dengan mempertahankan tampilan dalam jumlah terbatas. Gunakan
widget {@link android.support.v7.widget.RecyclerView} bila Anda memiliki kumpulan data dengan elemen
yang berubah saat runtime berdasarkan tindakan pengguna atau kejadian jaringan.</p>
<p>Kelas {@link android.support.v7.widget.RecyclerView} menyederhanakan penampilan dan penanganan
set data yang besar dengan menyediakan:</p>
<ul>
<li>Pengelola layout untuk memosisikan item</li>
<li>Animasi default untuk operasi item umum, misalnya penghapusan atau penambahan item</li>
</ul>
<p>Anda juga memiliki keluwesan untuk mendefinisikan pengelola layout custom dan animasi untuk widget {@link
android.support.v7.widget.RecyclerView}.</p>
<img src="{@docRoot}training/material/images/RecyclerView.png" alt="" width="550" height="106" />
<p class="img-caption">
<strong>Gambar 1</strong>. Widget <code>RecyclerView</code>.
</p>
<p>Untuk menggunakan widget {@link android.support.v7.widget.RecyclerView}, Anda harus menetapkan
adaptor dan pengelola layout. Untuk membuat adaptor, perluas kelas {@link
android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}. Detail
implementasi bergantung pada detail set data Anda dan tipe tampilan. Untuk informasi selengkapnya,
lihat <a href="#RVExamples">contoh-contoh</a> di bawah.</p>
<div style="float:right">
<img src="{@docRoot}design/material/images/list_mail.png" alt="" width="250" height="426" />
<p class="img-caption" style="margin-left:8px">
<strong>Gambar 2</strong> - Daftar berisi <code>RecyclerView</code>.
</p>
</div>
<p><strong>Pengelola layout</strong> memosisikan tampilan item dalam {@link
android.support.v7.widget.RecyclerView} dan menentukan waktu untuk menggunakan ulang tampilan item yang tidak
lagi terlihat oleh pengguna. Untuk menggunakan ulang (atau <em>mendaur ulang</em>) tampilan, pengelola layout bisa meminta
adaptor untuk mengganti konten tampilan dengan elemen lain dalam dataset. Mendaur ulang
tampilan dengan cara ini akan meningkatkan kinerja karena menghindari pembuatan tampilan yang tidak diperlukan atau
melakukan pencarian {@link android.app.Activity#findViewById findViewById()} yang mahal.</p>
<p>{@link android.support.v7.widget.RecyclerView} menyediakan semua pengelola layout bawaan ini:</p>
<ul>
<li>{@link android.support.v7.widget.LinearLayoutManager} menampilkan item dalam
daftar gulir vertikal atau horizontal.</li>
<li>{@link android.support.v7.widget.GridLayoutManager} menampilkan item dalam petak.</li>
<li>{@link android.support.v7.widget.StaggeredGridLayoutManager} menampilkan item dalam petak zigzag.</li>
</ul>
<p>Untuk membuat pengelola layout custom, perluas kelas {@link
android.support.v7.widget.RecyclerView.LayoutManager RecyclerView.LayoutManager}.</p>
<h3>Animasi</h3>
<p>Animasi untuk menambahkan dan menghapus item diaktifkan secara default di {@link
android.support.v7.widget.RecyclerView}. Untuk menyesuaikan animasi ini, perluas kelas
{@link android.support.v7.widget.RecyclerView.ItemAnimator RecyclerView.ItemAnimator}dan gunakan
metode {@link android.support.v7.widget.RecyclerView#setItemAnimator RecyclerView.setItemAnimator()}.
</p>
<h3 id="RVExamples">Contoh</h3>
<p>Contoh kode berikut memperagakan cara menambahkan
{@link android.support.v7.widget.RecyclerView} ke layout:</p>
<pre>
&lt;!-- A RecyclerView with some commonly used attributes -->
&lt;android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</pre>
<p>Begitu Anda menambahkan widget {@link android.support.v7.widget.RecyclerView} ke layout,
dapatkan pengatur atau handle objek itu, hubungkan dengan pengelola layout, dan sertakan adaptor untuk data
yang akan ditampilkan:</p>
<pre>
public class MyActivity extends Activity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
}
...
}
</pre>
<p>Adaptor menyediakan akses ke item dataset Anda, membuat tampilan untuk item, dan
mengganti konten sebagian tampilan dengan item data baru bila item semula tidak lagi
terlihat. Contoh kode berikut menampilkan implementasi sederhana untuk sebuah dataset yang terdiri dari
larik string yang ditampilkan dengan menggunakan widget {@link android.widget.TextView}:</p>
<pre>
public class MyAdapter extends RecyclerView.Adapter&lt;MyAdapter.ViewHolder> {
private String[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
&#64;Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters
...
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
&#64;Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset[position]);
}
// Return the size of your dataset (invoked by the layout manager)
&#64;Override
public int getItemCount() {
return mDataset.length;
}
}
</pre>
<div style="float:right;margin-top:15px;margin-left:30px">
<img src="{@docRoot}design/material/images/card_travel.png" alt="" width="225" height="383">
<p class="img-caption" style="margin-left:12px">
<strong>Gambar 3</strong>. Contoh kartu.
</p>
</div>
<h2 id="CardView">Membuat Kartu</h2>
<p>{@link android.support.v7.widget.CardView} memperluas kelas {@link android.widget.FrameLayout}
dan memungkinkan Anda menampilkan informasi dalam kartu yang memiliki tampilan konsisten lintas platform. Widget {@link
android.support.v7.widget.CardView} bisa memiliki bayangan dan sudut membulat.</p>
<p>Untuk membuat kartu dengan bayangan, gunakan atribut <code>card_view:cardElevation</code>.
{@link android.support.v7.widget.CardView} menggunakan elevasi nyata dan bayangan dinamis pada Android 5.0
(API level 21) ke atas dan memundurkan ke implementasi bayangan terprogram pada versi terdahulu.
Untuk informasi selengkapnya, lihat <a href="{@docRoot}training/material/compatibility.html">Mempertahankan
Kompatibilitas</a>.</p>
<p>Gunakan properti-properti ini untuk menyesuaikan penampilan
widget {@link android.support.v7.widget.CardView}:</p>
<ul>
<li>Untuk mengatur radius sudut pada layout Anda, gunakan atribut <code>card_view:cardCornerRadius</code>.
</li>
<li>Untuk mengatur radius sudut dalam kode Anda, gunakan metode <code>CardView.setRadius</code>.</li>
<li>Untuk mengatur warna latar belakang kartu, gunakan atribut <code>card_view:cardBackgroundColor</code>.
</li>
</ul>
<p>Contoh kode berikut menampilkan cara menyertakan widget {@link android.support.v7.widget.CardView}
dalam layout:</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
... >
&lt;!-- A CardView that contains a TextView -->
&lt;android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardCornerRadius="4dp">
&lt;TextView
android:id="@+id/info_text"
android:layout_width="match_parent"
android:layout_height="match_parent" />
&lt;/android.support.v7.widget.CardView>
&lt;/LinearLayout>
</pre>
<p>Untuk informasi selengkapnya, lihat referensi API untuk {@link android.support.v7.widget.CardView}.</p>
<h2 id="Dependencies">Menambahkan Dependensi</h2>
<p>Widget {@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView}
adalah bagian dari <a href="{@docRoot}tools/support-library/features.html#v7">v7 Support
Library</a>. Untuk menggunakan widget dalam proyek Anda, tambahkan
<a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a> ini ke
modul aplikasi Anda:</p>
<pre>
dependencies {
...
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
}
</pre>

View File

@@ -0,0 +1,133 @@
page.title=Mendefinisikan Bayangan dan Memangkas Tampilan
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Pelajaran ini mengajarkan Anda cara</h2>
<ol>
<li><a href="#Elevation">Menetapkan Elevasi pada Tampilan Anda</a></li>
<li><a href="#Shadows">Menyesuaikan Bayangan dan Garis Luar Tampilan</a></li>
<li><a href="#Clip">Memangkas Tampilan</a></li>
</ol>
<h2>Anda juga harus membaca</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
</ul>
</div>
</div>
<p>Desain bahan memperkenalkan elevasi untuk elemen-elemen UI. Elevasi membantu pengguna memahami
arti penting relatif masing-masing elemen dan memfokuskan perhatian pada tugas yang ada.</p>
<p>Elevasi tampilan, yang dinyatakan dengan properti Z, menentukan tampilan visual
bayangannya: tampilan dengan nilai Z lebih tinggi menghasilkan bayangan lebih besar dan lebih halus. Tampilan dengan nilai Z lebih tinggi menutupi
tampilan dengan nilai Z lebih rendah; akan tetapi, nilai Z tampilan tidak memengaruhi ukuran tampilan.</p>
<p>Bayangan digambar oleh induk tampilan yang dinaikkan, sehingga terkena pemangkasan standar tampilan,
yang dipangkas oleh induk secara default.</p>
<p>Elevasi juga berguna untuk membuat animasi tempat memunculkan widget untuk sementara di atas
bidang tampilan saat melakukan beberapa tindakan.</p>
<p>Untuk informasi selengkapnya tentang elevasi dalam desain bahan, lihat
<a href="http://www.google.com/design/spec/what-is-material/objects-in-3d-space.html">Objek
di ruang 3D</a>.</p>
<h2 id="Elevation">Menetapkan Elevasi pada Tampilan Anda</h2>
<p>Nilai Z untuk tampilan memiliki dua komponen:
<ul>
<li>Elevasi: Komponen statis.</li>
<li>Transformasi: Komponen dinamis yang digunakan untuk animasi.</li>
</ul>
<p><code>Z = elevation + translationZ</code></p>
<img src="{@docRoot}training/material/images/shadows-depth.png" width="580" height="261" alt="" />
<p class="img-caption"><strong>Gambar 1</strong> - Bayangan untuk berbagai elevasi tampilan.</p>
<p>Untuk mengatur elevasi tampilan dalam definisi layout, gunakan atribut <code>android:elevation</code>.
Untuk mengatur elevasi tampilan dalam kode aktivitas, gunakan
metode {@link android.view.View#setElevation View.setElevation()}.</p>
<p>Untuk mengatur transformasi tampilan, gunakan metode {@link android.view.View#setTranslationZ
View.setTranslationZ()}.</p>
<p>Metode {@link android.view.ViewPropertyAnimator#z ViewPropertyAnimator.z()} dan {@link
android.view.ViewPropertyAnimator#translationZ ViewPropertyAnimator.translationZ()} yang baru memudahkan
Anda menganimasikan elevasi tampilan. Untuk informasi selengkapnya, lihat referensi API untuk
{@link android.view.ViewPropertyAnimator} dan panduan pengembang <a href="{@docRoot}guide/topics/graphics/prop-animation.html">Animasi Properti</a>.
</p>
<p>Anda juga bisa menggunakan {@link android.animation.StateListAnimator}
untuk menetapkan animasi ini secara deklaratif. Ini khususnya berguna bila
perubahan status memicu animasi, seperti saat seorang pengguna menekan tombol. Untuk informasi selengkapnya, lihat
<a href="{@docRoot}training/material/animations.html#ViewState">Menganimasikan Perubahan Status Tampilan</a>.</p>
<p>Nilai Z diukur dengan satuan dp (density-independent pixel).</p>
<h2 id="Shadows">Menyesuaikan Bayangan dan Garis Luar Tampilan</h2>
<p>Batas-batas drawable latar belakang tampilan menentukan bentuk default bayangannya.
<strong>Garis luar</strong> menyatakan bentuk luar objek grafis dan mendefinisikan
bidang riak untuk umpan balik sentuh.</p>
<p>Perhatikan tampilan ini, yang didefinisikan dengan drawable latar belakang:</p>
<pre>
&lt;TextView
android:id="@+id/myview"
...
android:elevation="2dp"
android:background="@drawable/myrect" />
</pre>
<p>Drawable latar belakang didefinisikan sebagai persegi panjang dengan sudut membulat:</p>
<pre>
&lt;!-- res/drawable/myrect.xml -->
&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
&lt;solid android:color="#42000000" />
&lt;corners android:radius="5dp" />
&lt;/shape>
</pre>
<p>Tampilan ini menghasilkan bayangan dengan sudut membulat, karena drawable latar belakang mendefinisikan
garis luar tampilan. Memberikan garis luar custom akan mengesampingkan bentuk default bayangan tampilan.</p>
<p>Untuk mendefinisikan garis luar custom suatu tampilan dalam kode Anda:<p>
<ol>
<li>Perluas kelas {@link android.view.ViewOutlineProvider}.</li>
<li>Kesampingkan metode {@link android.view.ViewOutlineProvider#getOutline getOutline()}.</li>
<li>Tetapkan penyedia garis luar baru untuk tampilan Anda dengan metode {@link
android.view.View#setOutlineProvider View.setOutlineProvider()}.</li>
</ol>
<p>Anda bisa membuat garis luar lonjong dan persegi panjang yang bersudut membulat dengan menggunakan metode dalam
kelas {@link android.graphics.Outline}. Penyedia garis luar default untuk tampilan memperoleh garis luar
dari latar belakang tampilan. Untuk mencegah tampilan menghasilkan bayangan, atur penyedia garis luarnya
ke <code>null</code>.</p>
<h2 id="Clip">Memangkas Tampilan</h2>
<p>Memangkas tampilan memudahkan Anda mengubah bentuk tampilan. Anda bisa memangkas tampilan agar
konsistensi dengan elemen desain lainnya atau mengubah bentuk tampilan untuk merespons input pengguna.
Anda bisa memangkas tampilan hingga area garis luarnya dengan menggunakan metode {@link android.view.View#setClipToOutline
View.setClipToOutline()} atau atribut <code>android:clipToOutline</code>. Hanya
garis-garis luar persegi panjang, lingkaran, dan persegi panjang bersudut bulat yang mendukung pemangkasan, seperti yang ditentukan oleh
metode {@link android.graphics.Outline#canClip Outline.canClip()}.</p>
<p>Untuk memangkas tampilan ke bentuk drawable, atur drawable sebagai latar belakang tampilan
(seperti yang ditampilkan di atas) dan panggil metode {@link android.view.View#setClipToOutline View.setClipToOutline()}.
</p>
<p>Memangkas tampilan adalah operasi yang mahal; jadi, jangan animasikan bentuk yang Anda gunakan
untuk memangkas tampilan. Untuk memperoleh efek ini, gunakan animasi <a href="{@docRoot}training/material/animations.html#Reveal">Reveal Effect</a>.</p>

View File

@@ -0,0 +1,131 @@
page.title=Menggunakan Tema Bahan
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Pelajaran ini mengajarkan Anda cara</h2>
<ol>
<li><a href="#ColorPalette">Menyesuaikan Palet Warna</a></li>
<li><a href="#StatusBar">Menyesuaikan Baris Status</a></li>
<li><a href="#Inheritance">Tampilan Setiap Tema</a></li>
</ol>
<h2>Anda juga harus membaca</h2>
<ul>
<li><a href="http://www.google.com/design/spec">Spesifikasi desain bahan</a></li>
<li><a href="{@docRoot}design/material/index.html">Desain bahan di Android</a></li>
</ul>
</div>
</div>
<p>Tema bahan yang baru menyediakan:</p>
<ul>
<li>Widget sistem yang memungkinkan Anda mengatur palet warnanya</li>
<li>Animasi umpan balik sentuh untuk widget sistem</li>
<li>Animasi transisi aktivitas</li>
</ul>
<p>Anda bisa menyesuaikan tampilan tema bahan
sesuai dengan identitas merek Anda dengan palet warna yang Anda kontrol. Anda bisa mewarnai action-bar dan
baris status dengan menggunakan atribut tema, seperti yang ditampilkan dalam <a href="#fig3">Gambar 3</a>.</p>
<p>Widget sistem memiliki desain baru dan animasi umpan balik sentuh. Anda bisa menyesuaikan
palet warna, animasi umpan balik sentuh, dan transisi aktivitas untuk aplikasi.</p>
<p>Tema bahan didefinisikan sebagai:</p>
<ul>
<li><code>@android:style/Theme.Material</code> (versi gelap)</li>
<li><code>@android:style/Theme.Material.Light</code> (versi terang)</li>
<li><code>@android:style/Theme.Material.Light.DarkActionBar</code></li>
</ul>
<p>Untuk daftar gaya bahan yang bisa Anda gunakan, lihat referensi API untuk
{@link android.R.style R.style}.</p>
<!-- two columns, dark/light material theme example -->
<div style="width:700px;margin-top:25px;margin-bottom:10px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238">
<div style="width:170px;margin:0 auto">
<p style="margin-top:8px;font-size:12px"><strong>Gambar 1</strong>. Tema bahan gelap</p>
</div>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238">
<div style="width:170px;margin:0 auto">
<p style="margin-top:8px;font-size:12px"><strong>Gambar 2</strong>. Tema bahan terang</p>
</div>
</div>
<br style="clear:left">
</div>
<p class="note">
<strong>Catatan:</strong> Tema bahan hanya tersedia di Android 5.0 (API level 21)
ke atas. <a href="{@docRoot}tools/support-library/features.html#v7">v7 Support Library</a>
menyediakan tema dengan gaya desain bahan untuk beberapa widget dan dukungan untuk menyesuaikan
palet warna. Untuk informasi selengkapnya, lihat
<a href="{@docRoot}training/material/compatibility.html">Mempertahankan Kompatibilitas</a>.
</p>
<h2 id="ColorPalette">Menyesuaikan Palet Warna</h2>
<p style="margin-bottom:30px">Untuk menyesuaikan warna dasar tema agar cocok dengan merek Anda, definisikan
warna custom menggunakan atribut tema saat Anda mewariskan dari tema bahan:</p>
<pre>
&lt;resources>
&lt;!-- inherit from the material theme -->
&lt;style name="AppTheme" parent="android:Theme.Material">
&lt;!-- Main theme colors -->
&lt;!-- your app branding color for the app bar -->
&lt;item name="android:colorPrimary">@color/primary&lt;/item>
&lt;!-- darker variant for the status bar and contextual app bars -->
&lt;item name="android:colorPrimaryDark">@color/primary_dark&lt;/item>
&lt;!-- theme UI controls like checkboxes and text fields -->
&lt;item name="android:colorAccent">@color/accent&lt;/item>
&lt;/style>
&lt;/resources>
</pre>
<div style="float:right;margin-left:25px;margin-top:20px;margin-bottom:10px" id="fig3">
<img src="{@docRoot}training/material/images/ThemeColors.png" width="250" height="445" />
<p class="img-caption" style="margin-bottom:0px">
<strong>Gambar 3.</strong> Menyesuaikan tema bahan.</p>
</div>
<h2 id="StatusBar">Menyesuaikan Baris Status</h2>
<p>Tema bahan memungkinkan Anda menyesuaikan baris status dengan mudah; jadi Anda bisa menetapkan
warna yang cocok dengan merek Anda dan memberikan kontras yang cukup untuk menampilkan ikon status putih. Untuk
mengatur warna custom bagi baris status, gunakan atribut <code>android:statusBarColor</code> bila
Anda memperluas tema bahan. Secara default, <code>android:statusBarColor</code> mewarisi
nilai <code>android:colorPrimaryDark</code>.</p>
<p>Anda juga bisa menggambar sendiri di belakang baris status. Misalnya, jika Anda ingin menampilkan
baris status secara transparan di atas foto, dengan gradasi gelap yang halus untuk memastikan
ikon status putih tetap terlihat. Caranya, atur atribut <code>android:statusBarColor</code> ke
<code>&#64;android:color/transparent</code> dan sesuaikan flag jendela seperti yang diperlukan. Anda juga bisa
menggunakan metode {@link android.view.Window#setStatusBarColor Window.setStatusBarColor()} untuk
animasi atau pemudaran.</p>
<p class="note">
<strong>Catatan:</strong> Baris status harus selalu memiliki delineasi yang jelas dari
toolbar utama, kecuali bila Anda menampilkan gambar detail atau konten media tepi-ke-tepi di belakang
baris ini dan bila Anda menggunakan gradasi untuk memastikan ikon tetap terlihat.
</p>
<p>Bila Anda menyesuaikan baris navigasi dan baris status, jadikan keduanya transparan atau modifikasi
baris status saja. Baris navigasi harus tetap hitam di semua kasus lainnya.</p>
<h2 id="Inheritance">Tampilan Setiap Tema</h3>
<p>Elemen dalam definisi layout XML bisa menetapkan atribut <code>android:theme</code>,
yang merujuk sumber daya tema. Atribut ini memodifikasi tema untuk elemen itu dan setiap
elemen anak, yang berguna untuk mengubah palet warna tema dalam porsi tertentu
pada antarmuka.</p>

View File

@@ -1,29 +1,29 @@
page.title=Android デザイン指針
page.title=Android デザインの原則
@jd:body
<p>このデザイン指針は、ユーザーがもっとも知りたいと思われることを中心に、Android User Experience Team により、またその活動を統一的なものにするために作成されたものです。Android デベロッパーとデザイナーに対しては各種端末向けのより詳細なデザイン ガイドラインがあります。
<p>このデザインの原則は、ユーザーがもっとも知りたいと思われることを中心に、Android User Experience Team により、またその活動を統一的なものにするために作成されたものです。
Android デベロッパーとデザイナーに対しては各種端末向けのより詳細なデザイン ガイドラインがあります。
</p>
<p>
ご自身の創造性やデザインについて考える際、この指針を考慮に入れてください。
ご自身のクリエイティビティやデザインについて考える際、この原則を考慮に入れてください。
何を当てはめるかは目的に応じて調整してください。
</p>
<h2 id="enchant-me">ユーザーを引きつける</h2>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="delight-me">サプライズで楽しませる</h4>
<p>美しい画面、考え抜かれて配置されたアニメーション、タイミングの良いサウンド エフェクトは、使っていて楽しくなります。
<p>美しい画面、思慮深く配置されたアニメーション、タイミングの良いサウンド エフェクトは、使っていて楽しくなります。
わずかな効果でも、ユーザーを楽しませ、力を得たように感じてもらえます。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_delight.png">
@@ -32,15 +32,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="real-objects-more-fun">ボタンやメニューよりもリアルなオブジェクトでさらに楽しく</h4>
<p>ユーザーがアプリでオブジェクトを直接タップしたり操作したりできるようになります。タスクを実行するために必要な認知の労力が軽減され、感覚的な満足度も上がります。
<p>アプリでオブジェクトを直接タップしたり操作したりできます。タスクを試行錯誤しながら実行する必要はなく、アプリの満足度も上がります。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_real_objects.png">
@@ -49,16 +49,16 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="make-it-mine">自分らしさを加える</h4>
<p>ユーザーは自分でカスタマイズすることを好みます。これにより、くつろいだ気分や自分の思いのままできる自由な気分を味わうことができます。デフォルトで実用的で美しいものを取りそろえ、それに加えてメイン タスクの妨げにならない、楽しいカスタマイズも任意で加えられます。
<h4 id="make-it-mine">アプリに自分らしさをプラス</h4>
<p>誰もがアプリで自分らしさを出したいと思っています。好きなようにアプリを操作できるからです。実用的で美しい機能があらかじめ用意されており、それに加えてメイン タスクの邪魔にならない、楽しいカスタマイズもできます。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_it_mine.png">
@@ -67,31 +67,31 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="get-to-know-me">ユーザーについて知る</h4>
<p>徐々にユーザーの好みを学習していきます。同じ選択を繰り返す手間をかけず、前に選択したものをすぐに選べるようになります。
<h4 id="get-to-know-me">ユーザーの好みを学習</h4>
<p>徐々にユーザーの好みを学習していきます。ユーザーに何度も同じ選択をさせるのではなく、前に選択したものをすぐに選べるようにします。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_get_to_know_me.png">
</div>
</div>
<h2 id="simplify-my-life">よりシンプルに</h2>
<h2 id="simplify-my-life">生活をシンプルに</h2>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="keep-it-brief">常に簡潔に</h4>
<p>シンプルな言葉を並べた短いフレーズを用います。長い文章は好まれません。</p>
<h4 id="keep-it-brief">簡潔を心がける</h4>
<p>シンプルで短いフレーズを用います。長い文章は好まれません。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_keep_it_brief.png">
@@ -100,15 +100,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="pictures-faster-than-words">画像は言葉よりもわかりやすい</h4>
<p>画像を使ってアイデアを説明してみましょう。ユーザーの興味を引くことができ、言葉よりも効率的です。
<p>画像を使ってアイデアを説明してみましょう。ユーザーの興味を引くことができ、言葉よりも効果的です。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_pictures.png">
@@ -117,15 +117,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="decide-for-me">選択は最小限に、最終決定はユーザーに</h4>
<p>最初からユーザーにすべて尋ねるのではなく、もっとも適切と思われる項目を提示します。選択肢や決定事項が多すぎると面倒に感じます。
推測が間違っていた場合に備え、「やり直し」も可能にします。</p>
<p>最初からユーザーに選ばせるのではなく、適切と思われる項目を提示します。選択肢や決定事項が多すぎるとユーザーは面倒に感じます。
間違った選択をしても、「やり直し」ができます。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_decide_for_me.png">
@@ -134,15 +134,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="only-show-when-i-need-it">必要なものを必要なときにだけ表示する</h4>
<h4 id="only-show-when-i-need-it">必要なものを必要なときに</h4>
<p>一度に表示される内容が多すぎると疲れてしまいます。タスクや情報はいくつかに小さくまとめてわかりやすくします。
その時点で必要のないオプションは非表示にして、必要なときだけ表示します。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_information_when_need_it.png">
@@ -151,15 +151,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="always-know-where-i-am">全体像から現在の位置を示す</h4>
<p>ユーザーがはっきりと自分の現在の場所を把握できるようにします。アプリのどの場所にいるかを明示し、遷移して画面の関係を認識できるようにします。
実行しているタスクに対して応答し続けます。</p>
<h4 id="always-know-where-i-am">現在位置を把握する</h4>
<p>ユーザーが現在アプリのどこにいるのかがすぐに分かります。アプリ内における現在位置を明示し、遷移を使用して画面間の関係を表示します。
実行中のタスクにフィードバックを返します。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_navigation.png">
@@ -168,16 +168,16 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="never-lose-my-stuff">作成したものは失くさない</h4>
<p>ユーザーが時間をかけて作ったものは保存して、どこからでもアクセスできるようにします。設定、独自のカスタマイズ、電話、タブレット、コンピュータで作成したものを記録します。
アップグレードも簡単になります。
<h4 id="never-lose-my-stuff">作成物を失くさない</h4>
<p>ユーザーが時間をかけて作ったものは保存して、どこからでもアクセスできるようにします。設定、独自のカスタマイズ、および携帯端末、タブレット、コンピュータで作成したものを保存します。
アップグレードも簡単にできます。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_never_lose_stuff.png">
@@ -186,15 +186,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="looks-same-should-act-same">見た目が同じ場合は機能も同じにする</h4>
<p>視覚的な違いを際立たせ、ユーザーが機能の違いをはっきり区別できるようにします。同じような外観、同じ入力で機能が異なるようなモードは避けます。
</p>
<h4 id="looks-same-should-act-same">見た目が同じなら機能も同じ</h4>
<p>機能の違いがはっきり分かるように、特徴的なビジュアルにします。
同じような外観、同じ入力方法なのに機能が異なるということのないようにします。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_looks_same.png">
@@ -203,15 +203,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="interrupt-only-if-important">割り込みは重要なときにだけ行う</h4>
<p>優秀な個人秘書のように、重要ではない些細なことでユーザーをわずらわせることのないよう配慮します。集中したいユーザーにとって、重要で一刻を争うようなものでない限り、割り込まれると面倒で不快に感じる可能性があります。
<h4 id="interrupt-only-if-important">割り込みは必要な場合のみ</h4>
<p>優秀な個人秘書のように、ユーザーを些細なことでわずらわせないようにします。ユーザーは実行中の操作に専念したいと考えており、重要で一刻を争うようなものでない限り、割り込みは面倒で不快と感じます。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_important_interruption.png">
@@ -220,16 +220,16 @@ page.title=Android デザイン指針
<h2 id="make-me-amazing">操作を楽しく</h2>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="give-me-tricks">あらゆる場所に工夫を仕込む</h4>
<p>自分で理解すると嬉しく感じられます。Android アプリで広く使われている視覚や操作のパターンを生かし、アプリの操作をわかりやすいものにします。
たとえばスワイプ操作は便利なナビゲーションのショートカットとして使えます。
<h4 id="give-me-tricks">あらゆる場所に工夫を凝らす</h4>
<p>理解できれば楽しくなります。Android アプリで広く使われている視覚や操作のパターンを生かし、アプリの操作をわかりやすいものにします。
たとえばスワイプ操作は、ナビゲーションのショートカットとして使えるので便利です。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_tricks.png">
@@ -238,16 +238,16 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="its-not-my-fault">解決は簡単に</h4>
<p>ユーザーに修正を促す場合はその方法に注意します。アプリではスマートに問題を解決できるようにします。うまくいかなかったときは解決方法を明確に示し、技術的な詳細を表示する必要はありません。自動的に修正できる問題はユーザーに通知する必要すらありません。
</p>
<h4 id="its-not-my-fault">ユーザーの責任にしない</h4>
<p>ユーザーに修正を促す場合はその方法に注意します。ユーザーはアプリをスマートに使いこなしたいと考えています。
うまくいかなかったときの解決方法は明確でなければなりませんが、技術的に詳細である必要はありません。
自動的に修正できる問題については、通知も不要です。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_error.png">
@@ -256,15 +256,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="sprinkle-encouragement">操作を促すしかけを散りばめる</h4>
<p>複雑なタスクは分割し、それぞれ簡単に達成できるようにします。1 つ 1 つにフィードバックすることで、ユーザーの満足度は高まります。
<p>複雑なタスクは分割し、簡単に達成できるようにします。1 つ 1 つのアクションにフィードバックすることで、ユーザーの満足度は高まります。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
@@ -273,16 +273,16 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="do-heavy-lifting-for-me">作業の手間はかけない</h4>
<p>できると思っていなかったことをできるようにすることで、知識がなくても専門家のような気分を味わってもらえます。たとえば複数の写真効果を組み合わせたショートカットを使うことで、わずかな手順でプロのような写真に仕上げられます。
<h4 id="do-heavy-lifting-for-me">手間のかかる作業は不要</h4>
<p>できないと思っていたことができるようになれば、初心者でもエキスパートの気分が味わえます。たとえば複数の写真効果を組み合わせるショートカットを使うことで、わずかな手順でプロのような写真に仕上げられます。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_heavy_lifting.png">
@@ -291,15 +291,15 @@ page.title=Android デザイン指針
<div class="vspace size-2">&nbsp;</div>
<div class="layout-content-row">
<div class="layout-content-col span-7">
<div class="cols">
<div class="col-7">
<h4 id="make-important-things-fast">重要なことはすみやかに</h4>
<p>すべてのアクションが同じ優先度とは限りません。アプリのアクションには優先度を設定し、重要なものはたとえばカメラのシャッター ボタンや音楽プレイヤーの一時停止ボタンのように、簡単に見つけられすぐに使えるようにします。
<p>すべてのアクションが同じ優先度とは限りません。アプリのアクションに優先度を設定し、カメラのシャッター ボタンや音楽プレイヤーの一時停止ボタンのように重要なものは、簡単に見つけてすぐに使えるようにします。
</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/principles_make_important_fast.png">

View File

@@ -1,15 +1,14 @@
page.title=マテリアル デザイン
page.tags=Material, design
page.type=design
page.image=design/material/images/MaterialLight.png
page.title=Android のマテリアル デザイン
page.tags=Material,design
page.image=images/cards/design-material-for-android_2x.jpg
@jd:body
<!-- developer docs box -->
<a class="notice-developers right" href="{@docRoot}training/material/index.html">
<div>
<h3>デベロッパー文書</h3>
<p>マテリアル デザインを使ったアプリの作成</p>
<h3>デベロッパー ドキュメント</h3>
<p>マテリアル デザインを使用したアプリの作成</p>
</div>
</a>
@@ -25,7 +24,7 @@ page.image=design/material/images/MaterialLight.png
<a class="notice-developers-video" href="https://www.youtube.com/watch?v=YaG_ljfzeUw">
<div>
<h3>ビデオ</h3>
<p>紙とインク:重要なマテリアル</p>
<p>紙とインク: 重要なマテリアル</p>
</div>
</a>
@@ -39,27 +38,27 @@ page.image=design/material/images/MaterialLight.png
<p itemprop="description">マテリアル デザインは、視覚や動作と、複数のプラットフォームや端末間でのインタラクション デザインに関する包括的な指針です。
<p itemprop="description">マテリアル デザインは、複数のプラットフォームや端末の視覚、モーション、インタラクション デザインの包括的な指針です。
Android はマテリアル デザイン アプリに対応するようになりました。
Android アプリでマテリアル デザインを使うには、<a href="http://www.google.com/design/spec">マテリアル デザインの仕様</a>で説明されているガイドラインに従い、Android 5.0(API レベル 21)以降の新しいコンポーネントや機能を使用します。
Android アプリでマテリアル デザインを使うには、<a href="http://www.google.com/design/spec">マテリアル デザインの仕様</a>で定義されているガイドラインに従い、Android 5.0(API レベル 21)以降の新しいコンポーネントや機能を使用します。
</p>
<p>Android にはマテリアル デザインの作成に使うことができる次の要素が用意されています。</p>
<p>Android にはマテリアル デザインのアプリのビルドに使用できる次の要素が用意されています。</p>
<ul>
<li>新しいテーマ</li>
<li>複雑なビュー用の新しいウィジェット</li>
<li>複雑なビューに対応した新しいウィジェット</li>
<li>カスタムのシャドウとアニメーション用の新しい API</li>
</ul>
<p>Android でのマテリアル デザインの実装については、<a href="{@docRoot}training/material/index.html">マテリアル デザインを使ったアプリの作成</a>をご覧ください。
<p>Android でのマテリアル デザインの実装については、<a href="{@docRoot}training/material/index.html">マテリアル デザインを使用したアプリの作成</a>をご覧ください。
</p>
<h3>マテリアル テーマ</h3>
<p>マテリアル テーマはアプリの新しいスタイルである、システム ウィジェットを提供します。システム ウィジェットを使ってカラーパレット、タッチ フィードバックやアクティビティ遷移のためのデフォルトのアニメーションを指定できます。
<p>マテリアル テーマには、アプリの新しいスタイルであるシステム ウィジェットがあります。このシステム ウィジェットを使うと、システム ウィジェットのカラーパレットを設定したり、タッチ フィードバックやアクティビティ遷移のためのデフォルトのアニメーションを設定したりできます。
</p>
<!-- two columns -->
@@ -67,13 +66,13 @@ Android アプリでマテリアル デザインを使うには、<a href="http:
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/MaterialDark.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">暗色マテリアル テーマ</p>
<p style="margin-top:8px">暗い色のマテリアル テーマ</p>
</div>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/MaterialLight.png" width="500" height="238" />
<div style="width:140px;margin:0 auto">
<p style="margin-top:8px">明色マテリアル テーマ</p>
<p style="margin-top:8px">明るい色のマテリアル テーマ</p>
</div>
</div>
<br style="clear:left"/>
@@ -85,19 +84,19 @@ Android アプリでマテリアル デザインを使うには、<a href="http:
<h3>リストとカード</h3>
<p>Android はマテリアル デザインのスタイルとアニメーションを含むカードとリストを表示する新しい 2 つのウィジェットを提供しています。
<p>Android はマテリアル デザインのスタイルとアニメーションを含むカードとリストを表示する、次のような新しい 2 つのウィジェットを提供しています。
</p>
<!-- two columns -->
<div style="width:700px;margin-top:25px;margin-bottom:20px">
<div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
<img src="{@docRoot}design/material/images/list_mail.png" width="500" height="426" />
<p><code>RecyclerView</code> ウィジェットは <code>ListView</code> のさらに柔軟なバージョンで、さまざまなレイアウト タイプをサポートしてパフォーマンスを向上します。
</p>
<p>新しい <code>RecyclerView</code> ウィジェットは <code>ListView</code>
に比べてさらに柔軟に機能を追加できるようになっており、さまざまなレイアウト タイプをサポートしてパフォーマンスを向上させます。</p>
</div>
<div style="float:left;width:250px;margin-right:0px;">
<img src="{@docRoot}design/material/images/card_travel.png" width="500" height="426" />
<p>新しい <code>CardView</code> ウィジェットでは、外観や使用感が一貫しているカード内に重要な情報を表示できます。
<p>新しい <code>CardView</code> ウィジェットではカードの外観や操作性が統一され、カード内の重要な情報を表示できるようになりました。
</p>
</div>
<br style="clear:left"/>
@@ -109,12 +108,12 @@ Android アプリでマテリアル デザインを使うには、<a href="http:
<h3>シャドウの表示</h3>
<p>X と Y プロパティに加え、Android のビューに Z プロパティが追加されました。
この新しいプロパティはビューのエレベーションを表し、次を指定します。</p>
<p>Android のビューに、X と Y のプロパティに加えて Z プロパティが追加されました。
この新しいプロパティはビューのエレベーションを表し、次の要素を指定します。</p>
<ul>
<li>シャドウのサイズ: Z 値が高いビューほどキャストするシャドウのサイズが大きくなります。</li>
<li>表示される順序: Z 値が高いビューほど他のビューより上位に表示されます。</li>
<li>シャドウのサイズ: ビューの Z 値が高いほどシャドウのサイズが大きくなります。</li>
<li>描画順序: ビューの Z 値が高いほど他のビューの前面に表示されます。</li>
</ul>
<div style="width:290px;margin-left:35px;float:right">
@@ -136,33 +135,33 @@ Android アプリでマテリアル デザインを使うには、<a href="http:
<h3>アニメーション</h3>
<p>新しいアニメーション API を使って UI コントロールのタッチ フィードバック、ビューの状態遷移、アクティビティ遷移のカスタム アニメーションを作成できます。
<p>新しいアニメーション API を使って、UI コントロールのタッチ フィードバック、ビューの状態変化、アクティビティ間の遷移時のカスタム アニメーションを作成できます。
</p>
<p>これらの API で次の操作を実行できます。</p>
<p>この API で次のようなことができます。</p>
<ul>
<li style="margin-bottom:15px">
<strong>タッチ フィードバック</strong> アニメーションを使ってビューのタップイベントに応答します。
<strong>タッチ フィードバック</strong> アニメーションでビューのタップ イベントに応答する。
</li>
<li style="margin-bottom:15px">
<strong>円形状の出現</strong>アニメーションを使ってビューを表示 / 非表示にします。
<strong>円形状の出現</strong>アニメーションを使ってビューを表示したり、非表示にしたりする。
</li>
<li style="margin-bottom:15px">
カスタムの<strong>アクティビティ遷移</strong>アニメーションを使ってアクティビティを切り替えます。
カスタムの<strong>アクティビティ遷移</strong>アニメーションを使ってアクティビティを切り替える。
</li>
<li style="margin-bottom:15px">
<strong>曲線モーション</strong>を使ってより自然なアニメーションを作成します。
<strong>曲線モーション</strong>を使ってより自然なアニメーションを作成する。
</li>
<li style="margin-bottom:15px">
<strong>ビューの状態遷移</strong>アニメーションを使って 1 つ以上のビュー プロパティの遷移を表現します。
<strong>ビューの状態変化</strong>アニメーションを使って 1 つ以上のビュー プロパティを変化させるアニメーションを作成する。
</li>
<li style="margin-bottom:15px">
ビューの状態遷移間のアニメーションを<strong>状態リスト ドローアブル</strong>で表示します。
ビューの状態を変化させるアニメーションを<strong>状態リスト ドローアブル</strong>で表示します。
</li>
</ul>
<p>タッチ フィードバック アニメーションはボタンなどの複数の標準ビューに組み込まれます。新しい API を使ってこれらのアニメーションをカスタマイズし、それらをカスタム ビューに追加できます。
<p>タッチ フィードバック アニメーションはボタンなどの複数の標準ビューに組み込まれています。新しい API を使うと、これらのアニメーションをカスタマイズして、カスタム ビューに追加できます。
</p>
<p>詳細については、<a href="{@docRoot}training/material/animations.html">カスタム アニメーションの定義</a>をご覧ください。
@@ -171,12 +170,12 @@ Android アプリでマテリアル デザインを使うには、<a href="http:
<h3>ドローアブル</h3>
<p>次の新しいドローアブル機能を使ってマテリアル デザイン アプリを実装できます。</p>
<p>次の新しいドローアブル機能を使用してマテリアル デザイン アプリを実装できます。</p>
<ul>
<li><strong>ベクター型ドローアブル</strong>は鮮明度を失わずに拡張でき、単色のアプリ内アイコンに最適です。
<li><strong>ベクター型ドローアブル</strong>は定義を失わずにスケールできるので、単色のアプリ アイコンに最適です。
</li>
<li><strong>ドローアブルによる着色</strong>を使ってビットマップをアルファマスクとして定義し、実行時にそれらのビットマップに色付けすることができます。
<li><strong>ドローアブルによる着色</strong>を使ってビットマップをアルファ マスクとして定義し、実行時にそのビットマップに色付けできます。
</li>
<li><strong>色の抽出</strong>を使ってビットマップ画像から代表色を自動的に抽出できます。
</li>

View File

@@ -0,0 +1,70 @@
page.title=下方互換性
page.tags="support"
page.metaDescription=Android 4.x がバージョンの古いハードウェアや OS 向けにデザインされた UI にどのように対応するかについての注意事項。
@jd:body
<a class="notice-developers" href="{@docRoot}training/basics/supporting-devices/index.html">
<div>
<h3>デベロッパー ドキュメント</h3>
<p>異なる端末のサポート</p>
</div>
</a>
<p>Android 3.0 での大きな変更点には、以下のような点があります。</p>
<ul>
<li>仮想コントロール(Back、Home、Recents)のナビゲーション処理の導入によるナビゲーション ハードウェア キー(Back、Menu、Search、Home)の廃止
</li>
<li>アクションバーでメニュー項目を使用する際の表現パターンの強化</li>
</ul>
<p>Android 4.0 では、こういったタブレット向けの変更点が携帯端末プラットフォームにも導入されました。</p>
<h2 id="older-hardware">古いハードウェアやアプリへの Android 4.0 の対応</h2>
<div class="cols">
<div class="col-6">
<h4>仮想ナビゲーション コントロールのある携帯端末</h4>
<p>Android 3.0 以降をターゲットにした Android アプリは、アクションをアクションバーに表示します。アクションバーに収まらないアクションや、トップレベルに表示するほど重要ではないアクションは、アクション オーバーフローに表示されます。
</p>
<p>ユーザーは、アクションバーをタップすることで、アクション オーバーフローにアクセスできます。</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_virtual_nav.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>物理ナビゲーション キーのある携帯端末</h4>
<p>従来型のナビゲーション ハードウェア キーのある Android 携帯端末では、画面下部に仮想ナビゲーション バーは表示されません。
代わりに、メニュー ハードウェア キーからアクション オーバーフローを利用できます。そのため、ポップアップするアクションは先ほどの例と同じように利用できますが、画面の下部に表示される点が異なります。
</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_physical_buttons.png">
</div>
</div>
<div class="cols">
<div class="col-6">
<h4>仮想ナビゲーション コントロールのある携帯端末でのレガシー アプリ</h4>
<p>Android 2.3 以前をターゲットにビルドされたアプリを仮想ナビゲーション コントロールのある携帯端末で実行すると、仮想ナビゲーション バーの右側にアクション オーバーフロー コントロールが表示されます。
コントロールをタップすると、アプリのアクションを従来型の Android メニュー形式で表示できます。
</p>
</div>
<div class="col-7">
<img src="{@docRoot}design/media/compatibility_legacy_apps.png">
</div>
</div>

View File

@@ -2,69 +2,69 @@ page.title=確認と通知
page.tags=dialog,toast,notification
@jd:body
<p>状況に応じて、ユーザーがアプリでアクションを呼び出したときに、テキストを使ってそのアクションを<em>確認</em>したり<em>通知</em>したりするのは良い方法です。</p>
<p>アプリでアクションを呼び出すときに、テキストでそのアクションを<em>確認</em>または<em>通知</em>するとよい場合があります。</p>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<div class="cols">
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_confirming.png">
<p><strong>確認</strong>とは、呼び出したアクションを続けるかどうかをユーザーに確認してもらうことです。場合によって、確認は考慮する必要があるアクションに関連する警告や重要情報とともに表示されることがあります。</p>
<p><strong>確認</strong>とは、呼び出したアクションを本当に続行してもよいかどうかをユーザーにたずねることです。検討を要するアクションがあれば、それに関する警告や重要情報とともに表示されることもあります。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<img src="{@docRoot}design/media/confirm_ack_acknowledge.png">
<p><strong>通知</strong>とは、呼び出したアクションが完了したことをユーザーにお知らせするテキストを表示することです。これによって、システムが実行している暗黙的な処理の不明瞭さをなくすことができます。場合によって、通知はアクションを元に戻すオプションとともに表示されることがあります。</p>
<p><strong>通知</strong>とは、呼び出したアクションが完了したことをユーザーに知らせるテキストを表示することです。システムにより実行中であり、ユーザーには表示されない操作を確認できます。アクションを元に戻すオプションとともに表示されることもあります。</p>
</div>
</div>
<p>このような方法でユーザーに情報を伝えると、実行された処理やこれから実行される処理についての不明瞭さを軽減できます。確認や通知によって、後悔するような間違いをするのを防ぐこともできます。</p>
<p>このような機能を使用すれば、実行済みの処理やこれから実行される処理を明確に把握できます。確認や通知を表示することで、後悔するような間違いを防ぐこともできます。</p>
<h2>ユーザーのアクションを確認または通知する場合</h2>
<p>すべてのアクションに確認または通知が必要なわけではありません。デザインを決定する際の指針として次のチャートを使用してください。</p>
<h2>ユーザーのアクションを確認または通知するタイミング</h2>
<p>すべてのアクションに確認または通知が必要なわけではありません。確認や通知が必要かどうかを判断するには、次のチャートを使用してください。</p>
<img src="{@docRoot}design/media/confirm_ack_flowchart.png">
<h2>確認</h2>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<div class="cols">
<div class="col-6">
<h4>例: Google Play ブックス</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_books.png">
<p>この例では、ユーザーが Google Play ライブラリから書籍を削除することを要求しています。その書籍が今後端末で使えなくなることを知ってもらうことが重要であるため、このアクションを確認する<a href="{@docRoot}design/building-blocks/dialogs.html#alerts">アラート</a>が表示されます。</p>
<p>確認のダイアログを作成するときは、要求されたアクションがすぐわかるようなタイトルにします。</p>
<p>この例では、ユーザーは Google Play ライブラリから書籍を削除するよう要求しています。この書籍が今後いずれの端末でも使用できなくなるということを知らせる必要があるため、このアクションを確認する<a href="{@docRoot}design/building-blocks/dialogs.html#alerts">アラート</a>が表示されます。</p>
<p>確認ダイアログは、要求されたアクションをタイトルに記述するなどして、わかりやすく作成します。</p>
</div>
<div class="layout-content-col span-7">
<h4>例: Android Beam</h4>
<div class="col-7">
<h4>例: Android ビーム</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_beam.png">
<p>確認は、必ずしも 2 つのボタンの付いたアラートで示す必要はありません。Android Beam を開始した後に、ユーザーには共有するコンテンツ(この例では写真)にタップするように求めるメッセージが表示されます。共有を続行しない場合は、電話を離すだけです。</p>
<p>確認は、必ずしも 2 つのボタンが付いたアラートで行う必要はありません。Android ビームを開始した後、共有するコンテンツ(この例では写真)をタップするようメッセージが表示されます。共有を続行しない場合は、携帯端末を離すだけです。</p>
</div>
</div>
<h2>通知</h2>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<h4>例: 放置した Gmail 下書きの保存</h4>
<div class="cols">
<div class="col-6">
<h4>例: 途中まで書いた Gmail の下書きの保存</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_draftsave.png">
<p>この例では、ユーザーが Gmail 作成画面から前の画面に戻ったり、上位画面に移動したりするときに、予測しないことが起こる可能性があるため、現在の下書きが自動的に保存されます。トースト形式の通知によってその状態が明らかになります。この通知は数秒後にフェードします。</p>
<p>この例では、ユーザーが Gmail 作成画面から前の画面に戻ったり、画面の上部に移動したりすると、予測しないことが起こることもあるため、現在の下書きが自動的に保存されています。この動作はトースト形式で通知され、数秒後に消えます。</p>
<p>この場合、保存操作はユーザーではなくアプリによって行われるため、元に戻す操作は適切ではありません。また、下書きのリストに移動するだけでメッセージの作成をすぐに再開できます。</p>
</div>
<div class="layout-content-col span-6">
<div class="col-6">
<h4>例: Gmail スレッドの削除</h4>
<img src="{@docRoot}design/media/confirm_ack_draft_deleted.png">
<p>ユーザーが Gmail のリストからスレッドを削除した後に、元に戻すオプションとともに通知が表示されます。ユーザーがリストのスクロールなど関連しないアクションを実行するまで通知は表示されたままになります。</p>
<p>ユーザーが Gmail のリストから会話を削除した後に、元に戻すオプションとともに認定が表示されます。リストのスクロールなど無関係なアクションをユーザーが実行するまで、通知の表示は消えません。</p>
</div>
</div>
<h2>確認または通知を行わない場合</h2>
<div class="layout-content-row">
<div class="layout-content-col span-6">
<div class="cols">
<div class="col-6">
<h4>例: +1 操作</h4>
<img style="padding: 33px 0 30px;" src="{@docRoot}design/media/confirm_ack_ex_plus1.png">
<p><strong>確認は不要</strong>。ユーザーが誤って +1 ボタンをタップしても、大きな問題にはなりません。ボタンをもう一度タップすればアクションを元に戻すことができます。</p>
<p><strong>通知は不要</strong>。+1 ボタンがバウンスし、赤に変わります。これは非常にわかりやすいシグナルです。</p>
<p><strong>確認は不要です</strong>。ユーザーが誤って [+1] ボタンをタップしても、あまり問題ではありません。ボタンをもう一度タップすれば、アクションを元に戻すことができるからです。</p>
<p><strong>通知は不要です</strong>。[+1] ボタンがバウンドして赤に変わります。これは非常にわかりやすいシグナルです。</p>
</div>
<div class="layout-content-col span-7">
<h4>例: ホームスクリーンからアプリを削除</h4>
<div class="col-7">
<h4>例: ホームスクリーンからアプリを削除する場合</h4>
<img src="{@docRoot}design/media/confirm_ack_ex_removeapp.png">
<p><strong>確認は不要</strong>。これは意図的なアクションです。ユーザーはアイテムを比較的大きな分離されたターゲットにドラッグ アンド ドロップする必要があります。そのため、不測の問題が発生することはほとんどありません。ユーザーがこの決定を元に戻したい場合は、ほんの数秒で元に戻すことができます。</p>
<p><strong>通知は不要</strong>。ユーザーは自分でアプリをドラッグして削除するため、アプリがホームスクリーンから消えることがわかっています。</p>
<p><strong>確認は不要です</strong>。このアクションは賢明に設計されており、ユーザーはアイテムを比較的離れたところにある大きいターゲットにドラッグ アンド ドロップする必要があります。そのため、アクシデントが発生することはほとんどありません。しかもこの操作を取り消したい場合は、ほんの数秒で元に戻すことができるようになっています。</p>
<p><strong>通知は不要です</strong>。ユーザーが自分でアプリをドラッグして削除しているので、アプリがホームスクリーンから消えるのがわかっているからです。</p>
</div>
</div>

View File

@@ -1,213 +1,213 @@
page.title=Back と Up を使用したナビゲーション
page.title=Back ボタンと Up ボタンを使用したナビゲーション
page.tags="navigation","activity","task","up navigation","back navigation"
page.image=/design/media/navigation_between_siblings_gmail.png
@jd:body
<a class="notice-developers" href="{@docRoot}training/implementing-navigation/index.html">
<div>
<h3>デベロッパー文書</h3>
<p>効果的なナビゲーションを実装する</p>
<h3>デベロッパー ドキュメント</h3>
<p>効果的なナビゲーションの実装</p>
</div>
</a>
<p itemprop="description">一貫したナビゲーションは全体的なユーザーの操作性を向上するために欠かせない重要な要素です。一貫性がなく予測できない動作ほどユーザーにとって不快なものはありません。
Android 3.0 では、全体的なナビゲーション動作が大きく変更されました。
注意深く Back と Up のガイドラインに従うことで、アプリのナビゲーションをユーザーにとって予測可能で信頼できるものにすることができます。
<p itemprop="description">使いやすいアプリでは、ナビゲーションに統一性があります。統一性がなく、動作の読めないアプリほど使いにくいものはありません。
Android 3.0 では、全体的なナビゲーション動作が大きく変わりました。
Back ボタンと Up ボタンのガイドラインに従えば、ユーザーにとってわかりやすく、信頼できるナビゲーションを実装できます。
</p>
<p>Android 2.3 以前のアプリ内でのナビゲーションはシステムの <em>Back</em> ボタンを使って行われてきました。Android 3.0 よりアクションバーが導入され、第 2 のナビゲーション メカニズムとして <em>Up</em> ボタンが登場しました。このボタンはアプリアイコンと左向きのキャラットで構成されています。
<p>Android 2.3 以前のアプリのナビゲーションはシステムの <em>Back</em> ボタンで行っていました。
Android 3.0 よりアクションバーが導入され、第 2 のナビゲーション メカニズムとして <em>Up</em> ボタンが登場しました。このボタンはアプリアイコンと左向きのキャレットで表されています。
</p>
<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
<h2 id="up-vs-back">Up と Back</h2>
<h2 id="up-vs-back">Up ボタンと Back ボタンの違い</h2>
<p>Up ボタンは、画面間の階層関係に基づいてアプリ内を移動するために使います。
たとえば、画面 A がアイテムのリストを表示し、アイテムを選択すると(そのアイテムの詳細を表示する)画面 B に移動する場合、画面 B には画面 A に戻るための Up ボタンを用意する必要があります。
たとえば、画面 A でアイテムのリストを表示し、アイテムを選択すると(そのアイテムの詳細を表示する)画面 B に移動する場合、画面 B には画面 A に戻るための Up ボタンが必要です。
</p>
<p>画面がアプリの最上位(つまり、アプリのホーム)であれば、Up ボタンを表示すべきではありません。
<p>画面がアプリのトップ レベル(アプリのホーム)であれば、Up ボタンを表示する必要はありません。
</p>
<p>システムの Back ボタンはユーザーが最近使用した画面を、さかのぼって順番に移動する場合に使用されます。
通常このナビゲーションはアプリの階層ではなく、画面を表示した順番に基づいています。
<p>システムの Back ボタンは、最近使用した画面をさかのぼって順番に移動する場合に使用します。
通常、このナビゲーションはアプリの階層ではなく、画面を表示した順番に基づいています。
</p>
<p>前に表示していた画面が現在の画面の親階層となる場合は、Back ボタンを押すとUp ボタンを押したときと同じ結果になります &mdash; これはよくある動作です。
<p>前に表示していた画面が現在の画面の親階層となる場合は、Back ボタンを押すと Up ボタンを押したときと同じ結果になります &mdash; これは一般的な動作です。
ただし、Up ボタンではユーザーが確実にアプリ内に留まるのに対して、Back ボタンを使えばホームスクリーンに、さらには別のアプリに戻ることさえできます。
ただし、Up ボタンではユーザーの移動がアプリ内に限られるのに対して、Back ボタンではホーム画面や、別のアプリにも戻れます。
</p>
<img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
<p>Back ボタンは、画面間を直接ナビゲーションするだけでなく、次のような動作もサポートします。
<p>Back ボタンは、画面間を直接ナビゲーションするだけでなく、次のような動作にも対応しています。
</p>
<ul>
<li>フローティング ウィンドウ(ダイアログ、ポップアップ)を閉じる</li>
<li>コンテキスト アクションバーを閉じて、選択したアイテムのハイライト表示を解除する</li>
<li>オンスクリーン キーボード(IME)を非表示にする</li>
<li>画面上のキーボード(IME)を非表示にする</li>
</ul>
<h2 id="within-app">アプリ内でのナビゲーション</h2>
<h4>複数のエントリ ポイントのある画面のナビゲーション</h4>
<p>画面にアプリ階層内の正確な位置がなく、アプリ内の他のどの画面からでもアクセスできる設定画面などのように複数のエントリ ポイントからアクセスできる場合があります。この場合、Up ボタンは参照元の画面に戻ることを選択する必要があります。これは Back も同様です。
&mdash;
<h4>エントリ ポイントが複数ある画面へのナビゲート</h4>
<p>設定画面のように、アプリ内の他のどの画面からでもアクセスでき、アプリ階層内に定位置がなく、複数のエントリ ポイントからアクセスできる画面もあります。
この場合、Up ボタンは Back ボタンと同じように元の画面に戻ります。
</p>
<h4>画面内でビューを変更する</h4>
<p>画面のビュー オプションを変更しても Up と Back の動作は変わりません。画面はアプリの階層内の同じ位置に留まり、新しいナビゲーション履歴は作成されません。
<h4>画面内でのビューの変更</h4>
<p>画面のビュー オプションを変更しても Up ボタンと Back ボタンの動作は変わりません。画面はアプリの階層内の同じ位置にあり、新しいナビゲーション履歴は作成されません。
</p>
<p>このようなビューの変更には次のようなものがあります。</p>
<ul>
<li>タブや左右のスワイプを使ってビューを切り替える</li>
<li>ドロップダウン(折りたたみタブ)を使ってビューを切り替える</li>
<li>リストにフィルタをかける</li>
<li>リストをソートする</li>
<li>表示の方法を変える(ズームなど)</li>
<li>タブや左右のスワイプを使ったビューの切り替え</li>
<li>ドロップダウン(折りたたみタブ)を使ったビューの切り替え</li>
<li>リストへのフィルタの適用</li>
<li>リストの並び替え</li>
<li>表示方法の変更(ズームなど)</li>
</ul>
<h4>兄弟画面間のナビゲーション</h4>
<p>アプリでアイテムのリストから 1 つのアイテム詳細画面に移動するとき、そのアイテムからリスト内の前後にある別のアイテムへのナビゲーションをサポートするのが望ましいことがよくあります。
<p>アプリでアイテムのリストから選択して、あるアイテムの詳細画面に移動するとき、そのアイテムからリストの前後にある別のアイテムにナビゲーションできるようにすると使いやすくなる場合があります。
たとえば、Gmail では、スワイプすることで、ある会話から同じ受信トレイの新しいまたは古い会話へ左右に簡単に移動できます。
画面内でビューを変更する場合と同じように、このようなナビゲーションによって Up または Back の動作は変わりません。
たとえば、Gmail で左か右にスワイプすると、同じ受信トレイのある会話から新しい会話や古い会話に簡単に移動できます。
画面内でビューを変更する場合と同様に、このナビゲーションでも Up ボタンまたは Back ボタンの動作は変わりません。
</p>
<img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
<p>しかし、参照リストで結び付けられていない関連詳細ビュー間をブラウジングする場合 &mdash; たとえば Play ストアで同じデベロッパーのアプリや同じアーティストのアルバム間をブラウジング場合、その動作はこれとは明らかに異なります。
<p>ただし、参照リストで結び付けられていない関連詳細ビュー間をブラウジングする場合は例外です。たとえば Play Store で同じデベロッパーのアプリや同じアーティストのアルバム間をブラウジングする場合です。
この場合、各リンクをたどると履歴が作成され、Back ボタンで以前に表示した各画面に戻ることになります。
Up では常にこれらの関連画面をバイパスして、直前に表示したコンテナ画面に移動します。
Up ボタンを使用するとこれらの関連画面をバイパスして、直前に表示したコンテナ画面に移動します。
</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
<p>Up の動作を詳細ビューの知識に基づいてより使いやすくすることができます。
前述の Play ストアの例で、ユーザーが直前に表示した書籍から映画版の詳細に移動したとします。
その場合、Up でユーザーが前に表示していないコンテナ(映画)に戻ることができます。
<p>詳細ビューを応用すれば、Up ボタンを使いやすくできます。
前述の Play Store の例で、直前に表示した書籍から映画版の詳細に移動したとします。
その場合、Up ボタンを使用すると前に表示していないコンテナ(映画)に戻ることができます。
</p>
<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
<h2 id="into-your-app">ホームスクリーンのウィジェットと通知によるアプリへのナビゲーション</h2>
<h2 id="into-your-app">ホーム画面のウィジェットと通知を使用したアプリへのナビゲーション</h2>
<p>ホームスクリーンのウィジェットや通知を使ってユーザーがアプリ階層内の深い階層にある画面に直接移動できるようにします。
たとえば、Gmail の受信ボックスのウィジェットと新しいメッセージ通知はどちらも受信トレイ画面をバイパスし、会話ビューを直接表示できます。
<p>ホーム画面のウィジェットや通知を使用して、アプリの深い階層にある画面に直接移動できるようにします。
たとえば、Gmail の受信トレイのウィジェットと新しいメッセージ通知をタップすると、どちらも受信トレイ画面をバイパスし、会話ビューを直接表示できます。
</p>
<p>この両方の機能で、Up ボタンを次のように処理します。</p>
<ul>
<li><em>通常アプリ内の特定の画面から移動先画面に移動する場合</em>、Up でその画面に移動します。
<li><em>通常どおりにアプリの特定の画面から移動先画面に移動する場合</em>、Up ボタンを使用するとその画面に移動します。
</li>
<li><em>それ以外の場合は</em>、Up でアプリの最上位(「ホーム」)画面に移動します。</li>
<li><em>それ以外の場合は</em>、Up ボタンを使用するとアプリのトップレベル([ホーム])の画面に移動します。</li>
</ul>
<p>Back ボタンの場合は、アプリの最上位画面への完全な上向きナビゲーション パスをタスクのバックスタックに挿入してナビゲーションをより予測可能なものにする必要があります。
この設定によって、アプリにどのように入ったか忘れたユーザーは、終了前のアプリの最上位画面に移動できます。
<p>Back ボタンの場合は、アプリのトップ レベルの画面に直接ナビゲートできるパスをタスクのバック スタックに挿入して、わかりやすいナビゲーションにします。
こうすることで、アプリをどのように起動したか覚えていなくても、トップ レベルの画面に移動してから終了できます。
</p>
<p>たとえば Gmail のホームスクリーンのウィジェットには、その作成画面に直接移動するボタンがあります。
作成画面の Up または Back で受信トレイが表示され、そこから Back ボタンでホームに移動します。
<p>たとえば Gmail のホーム画面のウィジェットには、作成画面に直接移動するボタンがあります。
作成画面の Up ボタンまたは Back ボタンで受信トレイが表示され、そこから Back ボタンでホームに移動します。
</p>
<img src="{@docRoot}design/media/navigation_from_outside_back.png">
<h4>間接通知</h4>
<p>アプリで複数のイベントに関する情報を同時に表示する必要がある場合、1 つの通知を使ってユーザーをインタースティシャル画面に導くことができます。
この画面にはこれらのイベントがまとめてあり、アプリのさらに深い階層に移動するためのパスが示されます。このスタイルの通知を<em>間接通知</em>と呼びます。
<p>アプリで複数のイベントに関する情報を同時に表示する必要がある場合、通知を 1 つにまとめてそこからインタースティシャル画面に遷移させることができます。
この画面にはこれらのイベントの要約が表示されており、アプリのさらに深い階層に移動するパスが示されます。
このスタイルの通知を<em>間接通知</em>と呼びます。
</p>
<p>標準(直接)通知とは異なり、間接通知のインタースティシャル画面で Back ボタンを押すと、通知がトリガーされた画面に戻ります。バックスタックには追加の画面は挿入されません。
ユーザーがインタースティシャル画面からアプリに移動すると、Up ボタンと Back ボタンは前述の標準通知と同様に動作します。つまり、インタースティシャル画面に戻るのではなくアプリ内で遷移します。
</p>
<p>標準(直接)通知とは異なり、間接通知のインタースティシャル画面から Back を押すとユーザーは通知がトリガーされた地点に戻ります &mdash; バックスタックには追加の画面は挿入されません。
<p>たとえば Gmail がカレンダーから間接通知を受け取ったとします。この通知をタップするとインタースティシャル画面が開き、複数の異なるイベントのリマインダーが表示されます。
ユーザーがインタースティシャル画面からアプリに移動すると、Up および Back は前述した標準通知の場合と同様に動作します。つまりインタースティシャル画面に戻るのではなくアプリ内でナビゲーションします。
インタースティシャル画面で Back ボタンをタップすると Gmail に戻ります。特定のイベントをタップすると、インタースティシャル画面からカレンダー アプリに移動し、そのイベントの詳細が表示されます。
</p>
<p>たとえば Gmail のユーザーがカレンダーから間接通知を受け取ったとします。この通知をタップするとインタースティシャル画面が開き、複数の異なるイベントに関するリマインダーが表示されます。
インタースティシャル画面で Back をタップすると Gmail に戻ります。特定のイベントをタップすると、インタースティシャル画面から完全なカレンダー アプリに移動し、そのイベントの詳細が表示されます。
イベントの詳細から、Up および Back を使うとカレンダーの最上位ビューが表示されます。</p>
イベントの詳細画面で Up ボタンや Back ボタンを使うと、カレンダーのトップ ビューに移動します。</p>
<img src="{@docRoot}design/media/navigation_indirect_notification.png">
<h4>ポップアップ通知</h4>
<p><em>ポップアップ通知</em>は通知ドロワーをバイパスしてユーザーの前に直接表示されます。
ポップアップ通知はめったに使われません。<strong>タイムリーな応答が要求され、ユーザーのコンテキストの中断が必要な場合に使われます</strong>。
たとえばトークでは、このスタイルを使って友人からのビデオチャットへの参加に関する招待状についてユーザーに通知します。というのも、この招待状は数秒後に自動的に期限切れになるからです。
<p><em>ポップアップ通知</em>は通知ドロワーをバイパスし、直接表示される通知です。
ポップアップ通知はほとんど使われません。<strong>タイムリーな応答が要求され、ユーザーの操作の中断が必要な場合にのみ使うべきです</strong>。
たとえばトークでは、友人からのビデオチャットへの招待が数秒後に自動的に期限切れとなる場合、このスタイルを使ってユーザーに通知します。
</p>
<p>ナビゲーション動作の点から、ポップアップ通知は間接通知のインタースティシャル画面の動作に厳密に従います。
Back でポップアップ通知は閉じます。ユーザーがポップアップから通知元のアプリに移動すると、Up と Back は標準通知のルールに従い、アプリ内でナビゲーションします。
<p>ナビゲーションでは、間接通知のインタースティシャル画面の動作に慎重に従ってポップアップ通知を行います。
Back ボタンでポップアップ通知を閉じます。ポップアップから通知対象のアプリに移動すると、Up ボタンと Back ボタンは標準通知のルールに従って、そのアプリ内で通常のナビゲーションを実行します。
</p>
<img src="{@docRoot}design/media/navigation_popup_notification.png">
<h2 id="between-apps">アプリ間のナビゲーション</h2>
<p>Android システムの基本的な利点の 1 つにアプリ同士がそれぞれをアクティブにできる機能があります。これによりユーザーは特定のアプリから別のアプリへ直接移動できます。
たとえば写真を撮影する必要があるアプリでは、カメラアプリをアクティブにすることができます。カメラアプリは写真を参照元のアプリに戻します。これはデベロッパーにとっては他のアプリのコードを簡単に利用できるという点で、またユーザーにとっては通常実行するアクションに対して一貫した操作を実行できるという点で大きなメリットです。
<h2 id="between-apps">アプリ間ナビゲーション</h2>
<p>Android システムの基本的な利点の 1 つに、アプリが別のアプリを起動できる機能があります。これを使用すると、あるアプリから別のアプリへ直接移動できます。
たとえば、写真をキャプチャするアプリで、カメラアプリを起動できます。カメラアプリは写真を起動元のアプリに返します。
デベロッパーにとっては他のアプリのコードを簡単に利用できるという点で、ユーザーにとってはよく実行するアクションを常に同じ操作で実行できるという点で大きなメリットです。
</p>
<p>アプリ間のナビゲーションを理解するには、次に説明する Android フレームワークの動作を理解することが重要です。
<p>アプリ間ナビゲーションを理解するには、次に説明する Android フレームワークの動作を理解する必要があります。
</p>
<h4>アクティビティ、タスク、インテント</h4>
<p>Android における<strong>アクティビティ</strong>とは情報の画面と、ユーザーが実行できるすべての関連アクションを定義するアプリケーション コンポーネントです。
アプリはアクティビティのコレクションで、作成したアクティビティと他のアプリから再利用するアクティビティの両方で構成されています。
<p>Android における<strong>アクティビティ</strong>とは、情報を表示する画面と、実行できるすべての関連アクションを定義するアプリケーション コンポーネントのことです。
アプリはアクティビティの集まりで構成され、作成したアクティビティと他のアプリから再利用するアクティビティで構成されています。
</p>
<p><strong>タスク</strong>とは目標を実現するためにユーザーが従う一連のアクティビティです。1 つのタスクで 1 つのアプリだけのアクティビティを利用することも、複数のアプリのアクティビティを利用することもできます。
<p><strong>タスク</strong>とは目的の動作を遂行するために実行する、一連のアクティビティのことです。1 つのタスクで 1 つのアプリだけのアクティビティを利用することも、複数のアプリのアクティビティを利用することもできます。
</p>
<p><strong>インテント</strong>とは、あるアプリがアクションの実行に関して別のアプリのサポートが必要であることを示すメカニズムです。
アプリのアクティビティでそれらのアプリが対応できるインテントを示すことができます。
「共有」などの一般的なインテントの場合、ユーザーはその要求を実現できる多くのアプリをインストールしている場合があります。
<p><strong>インテント</strong>とは、アプリがあるアクションを実行するために、別のアプリにアシストを要求するためのシグナルを出すメカニズムです。
アプリのアクティビティは、どのようなインテントに応答できるか決めることができます。
「共有」などの一般的なインテントの場合、その要求に対応できるアプリが複数インストールされていることもあります。
</p>
<h4>例: 共有をサポートするアプリ間のナビゲーション</h4>
<h4>例: アプリ間をナビゲートして共有をサポートする</h4>
<p>アクティビティ、タスク、インテントの連携を理解するには、1 つのアプリが別のアプリを使ってユーザーによるコンテンツの共有を可能にする仕組みを知る必要があります。たとえばホームから Play ストアのアプリを起動すると、新しいタスク A が開始されるとします(以下の図を参照)。
Play ストア内をナビゲートし、プロンプトで表示された書籍をタップしてその詳細を表示した後もユーザーは同じタスク内に留まり、アクティビティを追加するとタスクは拡張されます。
「共有」アクションをトリガーすると、共有インテントを処理するよう登録されている(さまざまなアプリの)各アクティビティを示すダイアログがユーザー表示されます。
<p>アクティビティ、タスク、インテントの連携を理解するには、あるアプリが別のアプリを使ってコンテンツを共有する仕組みについて理解する必要があります。
たとえば、ホームから Play Store のアプリを起動すると、新しいタスク A が開始されるとします(以下の図を参照)。
Play Store 内をナビゲートし、おすすめの書籍をタップしてその詳細を表示した後もユーザーは同じタスク内に留まり、アクティビティを追加するとタスクが拡張されます。
「共有」アクションをトリガーすると、共有インテントを処理するよう登録されている(さまざまなアプリの)各アクティビティを一覧表示するダイアログが表示されます。
</p>
<img src="{@docRoot}design/media/navigation_between_apps_inward.png">
<p>ユーザーが Gmail 経由で共有することを選択すると、Gmail の作成アクティビティがタスク A の続きとして追加されます &mdash; 新しいタスクは作成されません。
Gmail にバックグラウンドで実行中の独自のタスクがある場合、そのタスクは影響を受けません。
<p>Gmail で共有するよう選択すると、Gmail の作成アクティビティがタスク A の続きとして追加され、新しいタスクは作成されません。
Gmail にバックグラウンドで実行中のタスクがある場合、そのタスクは影響を受けません。
</p>
<p>作成アクティビティからメッセージを送信するか、Back ボタンをタップするとユーザーは書籍の詳細アクティビティに戻ります。
Back を連続してタップすると Play ストアに戻り、最終的にはホームが表示されます。
<p>作成アクティビティからメッセージを送信するか、Back ボタンをタップすると書籍の詳細アクティビティに戻ります。
Back ボタンを連続してタップすると Play Store に戻り、最後にホーム画面が表示されます。
</p>
<img src="{@docRoot}design/media/navigation_between_apps_back.png">
<p>ただし、作成アクティビティから Up をタップすると、ユーザーは Gmail 内に留まる意思を示すことになります。
Gmail の会話リストのアクティビティが表示され、新しいタスク B が作成されます。新しいタスクは常にホームをルートとしているため、会話リストからBack をタップするとホームに戻ります。
<p>ただし、作成アクティビティで Up ボタンをタップすると、Gmail で引き続き作業することになります。
Gmail の会話リストのアクティビティが表示され、新しいタスク B が作成されます。新しいタスクでは常にホーム画面がルートになるため、会話リストから Back ボタンをタップするとホーム画面に戻ります。
</p>
<img src="{@docRoot}design/media/navigation_between_apps_up.png">
<p>タスク A はバックグラウンドで維持され、ユーザー後から(たとえば [最近使ったアプリ] 画面経由で)このタスクに戻ることができます。
Gmail にバックグラウンドで実行中の独自のタスクが既にある場合、そのタスクはタスク B に置き換えられます &mdash; 前のコンテキストはユーザーの新しい目標の導入より破棄されます。
<p>タスク A はバックグラウンドで待機しているので、後から(たとえば [最近使ったアプリ] 画面から)このタスクに戻ることができます。
Gmail にバックグラウンドで実行中のタスクが既にある場合、そのタスクはタスク B に置き換えられます。新しいタスクが選択され、前のコンテキストは破棄されます。
</p>
<p>アプリがアプリ階層内の深い階層にあるアクティビティでインテントを処理するように登録されている場合は、Up ナビゲーションの指定方法について<a href="#into-your-app">ホームスクリーンのウィジェットと通知によるアプリへのナビゲーション</a>をご覧ください。
<p>深い階層にあるアクティビティでインテントを処理するようアプリで登録されている場合は、Up ナビゲーションの指定方法については、<a href="#into-your-app">ホーム画面のウィジェットと通知を使用したアプリへのナビゲーション</a>をご覧ください。
</p>

View File

@@ -0,0 +1,756 @@
page.title=アクティビティ
page.tags=activity,intent
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>本書の内容</h2>
<ol>
<li><a href="#Creating">アクティビティを作成する</a>
<ol>
<li><a href="#UI">ユーザー インターフェースを実装する</a></li>
<li><a href="#Declaring">マニフェストでアクティビティを宣言する</a></li>
</ol>
</li>
<li><a href="#StartingAnActivity">アクティビティを開始する</a>
<ol>
<li><a href="#StartingAnActivityForResult">結果待ちのアクティビティを開始する</a></li>
</ol>
</li>
<li><a href="#ShuttingDown">アクティビティをシャットダウンする</a></li>
<li><a href="#Lifecycle">アクティビティのライフサイクルを管理する</a>
<ol>
<li><a href="#ImplementingLifecycleCallbacks">ライフサイクル コールバックを実装する</a></li>
<li><a href="#SavingActivityState">アクティビティの状態を保存する</a></li>
<li><a href="#ConfigurationChanges">構成の変更を処理する</a></li>
<li><a href="#CoordinatingActivities">アクティビティを連携する</a></li>
</ol>
</li>
</ol>
<h2>キークラス</h2>
<ol>
<li>{@link android.app.Activity}</li>
</ol>
<h2>関連ドキュメント</h2>
<ol>
<li><a href="{@docRoot}guide/components/tasks-and-back-stack.html">タスクとバックスタック
</a></li>
</ol>
</div>
</div>
<p>{@link android.app.Activity} は、電話をかける、写真を撮影する、メールを送る、マップを閲覧するといった操作をユーザーができる画面を提供するアプリケーション コンポーネントです。
各アクティビティには、ユーザー インターフェースを描画できるウィンドウがあります。一般的にはウィンドウは画面と同じ大きさになりますが、画面より小さくしたり、他のウィンドウ上にフローティングさせたりすることもできます。
</p>
<p> 通常、アプリケーションは複数のアクティビティで構成されており、各アプリケーションはそれぞれ緩やかにつながっています。
一般的には、アプリケーションの 1 つのアクティビティが「メイン」アクティビティとして指定され、ユーザーが初めてアプリケーションを起動したときに表示されるのがこのアクティビティになります。
その後、各アクティビティで別のアクティビティを開始して別の操作を実行できます。
新しいアクティビティの開始時には、前のアクティビティは停止しますが、そのアクティビティはシステムによってスタック(「バックスタック」)に維持されます
新しいアクティビティが開始すると、それがバックスタックに入ってユーザーに表示されます。
バックスタックは「後入れ先出し」の基本的なスタック メカニズムを順守するため、ユーザーが現在のアクティビティを完了して [<em>戻る</em>] ボタンを押すと、そのアクティビティはスタックから消え(破棄され)、前のアクティビティが再開します。
(バックスタックの詳細については、<a href="{@docRoot}guide/components/tasks-and-back-stack.html">タスクとバックスタック</a>ドキュメントで説明します)。
</p>
<p>新しいアクティビティが開始したことで、別のアクティビティが停止した場合、その状態の変化がアクティビティのライフサイクル コールバック メソッド経由で通知されます。システムがアクティビティを作成しているのか、停止しているのか、再開しているのか、破棄しているのかという状態の変化によって、アクティビティが受け取るコールバック メソッドにはいくつかの種類があり、各コールバックではユーザーがその状態の変化に応じた特定の操作を実行できます。
&mdash;&mdash;
たとえば、アクティビティが停止した場合は、ネットワーク接続やデータベース接続などの大きなオブジェクトを解放することになります。
アクティビティが再開した場合は、必要なリソースを再度取得し、中断したところから操作を再開できます。
このような状態の推移はすべて、アクティビティのライフサイクルの一部です。
</p>
<p>このドキュメントでは、さまざまなアクティビティの状態間の切り替えを正しく管理できるよう、アクティビティのライフサイクルの仕組みについてさらに詳しく説明する他、アクティビティのビルド方法と使用方法の基本について解説します。
</p>
<h2 id="Creating">アクティビティを作成する</h2>
<p>アクティビティを作成するには、{@link android.app.Activity} のサブクラス(またはその既存のサブクラス)を作成する必要があります。
サブクラスでは、アクティビティのライフサイクルの状態の切り替え時(アクティビティの作成、停止、再開、破棄など)にシステムが呼び出すコールバック メソッドを実装する必要があります。
最も重要なコールバック メソッドは次の 2 つです。
</p>
<dl>
<dt>{@link android.app.Activity#onCreate onCreate()}</dt>
<dd>このメソッドは必ず実装してください。システムはアクティビティ作成の際にこのメソッドを呼び出します。
実装の際には、アクティビティの必須コンポーネントを初期化する必要があります。
さらに重要な点は、ここで {@link android.app.Activity#setContentView
setContentView()} を呼び出してアクティビティのユーザー インターフェースのレイアウトを定義する必要があるということです。</dd>
<dt>{@link android.app.Activity#onPause onPause()}</dt>
<dd>システムは、ユーザーがアクティビティを終了したことを始めて示すときに、このメソッドを呼び出します(アクティビティが破棄されていない場合も含む)。
通常はここで、現在のユーザー セッション後も維持する必要のある変更点を保存しておきます(ユーザーが戻ってこない可能性があるため)。
</dd>
</dl>
<p>アクティビティ間の滑らかな操作感を実現し、アクティビティが停止したり破棄されたりする可能性のある予想外の中断に対応するために使用できるライフサイクル コールバック メソッドは他にもいくつかあります。
すべてのライフサイクル コールバック メソッドについては、<a href="#Lifecycle">アクティビティのライフサイクルを管理する</a>のセクションで説明します。
</p>
<h3 id="UI">ユーザー インターフェースを実装する</h3>
<p> アクティビティのユーザー インターフェースは、ビューの階層、 {@link android.view.View} から派生したオブジェクトから提供されます。&mdash;
各ビューはアクティビティ ウィンドウ内の特定の長方形のエリアを制御し、ユーザーの操作に応答します。
たとえば、1 つのビューが、ユーザーがタップしたときに操作を開始するボタンである場合があります。
</p>
<p>Android には、レイアウトのデザインや整理に使用できる既成のビューが多数用意されています。
「ウィジェット」は、ボタン、テキスト フィールド、チェックボックス、画像といった画像の視覚的(操作可能な)要素を提供するビューです。
「レイアウト」は、{@link
android.view.ViewGroup} から派生したビューで、線形レイアウト、グリッド レイアウト、相対レイアウトなど、子ビューの特有のレイアウト モデルを提供するものです。
また、{@link android.view.View} クラスと {@link android.view.ViewGroup} クラス(または既存のサブクラス)のサブクラスを作成し、独自のウィジェットやレイアウトを作ってアクティビティのレイアウトに適用することもできます。
</p>
<p>ビューを使用したレイアウトの定義で最も一般的なのは、XML レイアウト ファイルをアプリケーション リソースに保存する方法です。
この方法では、ユーザー インターフェースのデザインを、アクティビティの挙動を定義するソース コードとは別に維持できます。
{@link android.app.Activity#setContentView(int) setContentView()} を使用して、レイアウトのリソース ID を渡すと、アクティビティの UI としてレイアウトを設定できます。
ただし、アクティビティ コードに新しい {@link android.view.View} を作成して、{@link android.view.ViewGroup} に新しい {@link
android.view.View} を挿入してビュー階層をビルドし、ルートの {@link android.view.ViewGroup} を {@link android.app.Activity#setContentView(View)
setContentView()} に渡して、そのレイアウトを使うこともできます。
</p>
<p>ユーザー インターフェースの作成の詳細については、「<a href="{@docRoot}guide/topics/ui/index.html">ユーザー インターフェース</a>」のドキュメントをご覧ください。</p>
<h3 id="Declaring">マニフェストでアクティビティを宣言する</h3>
<p>アクティビティがシステムにアクセスできるようにするには、マニフェストでアクティビティを宣言する必要があります。
アクティビティを宣言するには、マニフェスト ファイルを開いて、<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 要素を <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a> の子要素として追加します。
次に例を示します。</p>
<pre>
&lt;manifest ... &gt;
&lt;application ... &gt;
&lt;activity android:name=".ExampleActivity" /&gt;
...
&lt;/application ... &gt;
...
&lt;/manifest &gt;
</pre>
<p>この要素には他にも、アクティビティのラベル、アクティビティのアイコン、アクティビティの UI を決めるテーマなどのプロパティを定義する属性を含めることができます。<a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a> 属性は、アクティビティのクラス名を指定するもので、唯一の必須属性です。
&mdash;アプリケーションを発行したら、この名前は変更できません。変更すると、アプリケーションのショートカットなどの一部の機能が破損する可能性があります(ブログの投稿「<a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things That Cannot Change</a>」をご覧ください)。
</p>
<p>マニフェストでのアクティビティの宣言に関する詳細については、<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 要素のリファレンスをご覧ください。
</p>
<h4>インテント フィルタを使用する</h4>
<p><a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
&lt;activity&gt;}</a> 要素でも &mdash; <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> 要素を使用してさまざまなインテント フィルタを指定して &mdash; 他のアプリケーション コンポーネントでのアクティベート方法を宣言できます。
</p>
<p>Android SDK ツールを使用して新しいアプリケーションを作成する際、自動的に作成されるスタブ アクティビティには、「メイン」アクションに応答するアクティビティで、「ランチャー」カテゴリに置かれるべきものを宣言するインテント フィルタが含まれます。
インテント フィルタは次のように表示されます。
</p>
<pre>
&lt;activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MAIN" /&gt;
&lt;category android:name="android.intent.category.LAUNCHER" /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>
<p><a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a> 要素は、これがアプリケーションへの「メイン」エントリ ポイントであることを指定します。<a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a> 要素は、アクティビティをシステムのアプリケーション ランチャーに入れるべきであると指定します(ユーザーがこのアクティビティを起動できるようにします)。
</p>
<p>アプリケーションを自己完結型にして、他のアプリケーションでアクティビティをアクティベートできないようにする場合は、他のインテント フィルタは必要ありません。
前の例のように、「メイン」アクションを持ち、「ランチャー」カテゴリにできるのは 1 つのアクティビティのみです。
アクティビティを他のアプリケーションで利用できないようにする場合は、そのアクティビティにはインテント フィルタを使用せず、明示的なインテントを使用して自身でアクティビティを開始するようにできます(次のセクションで説明します)。
</p>
<p>ただし、他のアプリケーション(と自身のアプリケーション)から派生した暗黙的なインテントにアクティビティが応答するようにする場合は、アクティビティで追加のインテント フィルタを定義する必要があります。
応答するインテントのタイプごとに、<a href="{@docRoot}guide/topics/manifest/action-element.html">{@code
&lt;action&gt;}</a> 要素を含む <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code
&lt;intent-filter&gt;}</a> と、任意で <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code
&lt;category&gt;}</a> 要素や <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code
&lt;data&gt;}</a> 要素を含める必要があります。
これらの要素は、アクティビティが応答できるインテントのタイプを指定します。
</p>
<p>アクティビティがインテントに応答する方法の詳細については、「<a href="{@docRoot}guide/components/intents-filters.html">インテントとインテント フィルタ</a>」のドキュメントをご覧ください。
</p>
<h2 id="StartingAnActivity">アクティビティを開始する</h2>
<p>@link android.app.Activity#startActivity
startActivity()} を呼び出して、開始するアクティビティを記述する {@link android.content.Intent} を渡すと、新しいアクティビティを開始できます。
インテントは開始するアクティビティを正確に指定するか、実行する操作のタイプを記述します(システムが適切なアクティビティを選択しますが、それが他のアプリケーションのアクティビティである場合もあります)。
また、インテントには開始したアクティビティで使用する少量のデータを含めることもできます。
</p>
<p>自身のアプリケーションを操作するとき、既知のアクティビティを起動することが頻繁にあります。
そのような場合、クラス名を使用して開始するアクティビティを明示的に定義するインテントを作成できます。
例として、1 つのアクティビティで {@code
SignInActivity} という名前の他のアクティビティを開始する方法を次に示します。</p>
<pre>
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
</pre>
<p>ただし、アクティビティからのデータを使用して、アプリケーションでメールやテキスト メッセージの送信、ステータスのアップデートといった操作を実行する場合もあります。
アプリケーションにそのような操作を実行できるアクティビティがない場合、代わりに、端末上の他のアプリケーションによるアクティビティを活用できます。
ここが、インテントがその存在意義を発揮する場面です。実行する操作を記述するインテントを作成し、システムが適切なアクティビティを他のアプリケーションから起動します。
&mdash;
インテントを処理できるアクティビティが複数ある場合は、使用するアクティビティを 1 つユーザーが選択できます。
たとえば、メールを送信できるようにする場合は、次のようなインテントを作成します。
</p>
<pre>
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
</pre>
<p>インテントに追加された {@link android.content.Intent#EXTRA_EMAIL} のエクストラは、メールの送信先となるメールアドレスの文字列配列です。
メール アプリケーションがこのインテントに応答するとき、エクストラにある文字列配列を読み取り、それをメール作成フォームの「宛先」フィールドに置きます。
この場合、メール アプリケーションのアクティビティが開始してユーザーが操作を完了したときにアクティビティが再開します。
</p>
<h3 id="StartingAnActivityForResult">結果待ちのアクティビティを開始する</h3>
<p>開始するアクティビティから結果を受け取りたい場合は、{@link android.app.Activity#startActivityForResult
startActivityForResult()}({@link android.app.Activity#startActivity
startActivity()} の代わりに)を呼び出してアクティビティを開始します。
その後のアクティビティから結果を受け取るには、
{@link android.app.Activity#onActivityResult onActivityResult()} コールバック メソッドを実装します。
後続のアクティビティが完了すると、{@link
android.content.Intent} の結果を {@link android.app.Activity#onActivityResult onActivityResult()} メソッドに返します。
</p>
<p>たとえば、連絡先を 1 つ受け取って、アクティビティでその連絡先情報を使用する場合は、
次のようにインテントを作成して結果を処理できます。
</p>
<pre>
private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content provider URI
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}
&#64;Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the request went well (OK) and the request was PICK_CONTACT_REQUEST
if (resultCode == Activity.RESULT_OK &amp;&amp; requestCode == PICK_CONTACT_REQUEST) {
// Perform a query to the contact's content provider for the contact's name
Cursor cursor = getContentResolver().query(data.getData(),
new String[] {Contacts.DISPLAY_NAME}, null, null, null);
if (cursor.moveToFirst()) { // True if the cursor is not empty
int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// Do something with the selected contact's name...
}
}
}
</pre>
<p>この例では、アクティビティの結果を処理するために {@link
android.app.Activity#onActivityResult onActivityResult()} メソッドで使用すべき基本ロジックを示しています。
1 つ目の条件では、要求が成功したかどうかを確認し、成功した場合は {@code resultCode} が{@link android.app.Activity#RESULT_OK} になり、この結果への要求が応答しているかどうかが判明します。この場合、{@code requestCode} が {@link android.app.Activity#startActivityForResult
startActivityForResult()} で送信された 2 つ目のパラメータに一致しています。&mdash;
&mdash;&mdash;
そこから、コードが {@link android.content.Intent}({@code data} パラメータ)に返されたデータを照会することでアクティビティの結果を処理します。
</p>
<p>ここで、{@link
android.content.ContentResolver} がコンテンツ プロバイダに対してクエリを実行し、照会されたデータを読み取れるようにする {@link android.database.Cursor} が返されます。
詳細については、「<a href="{@docRoot}guide/topics/providers/content-providers.html">コンテンツ プロバイダ</a>」のドキュメントをご覧ください。
</p>
<p>インテントの使用に関する詳細については、「<a href="{@docRoot}guide/components/intents-filters.html">インテントとインテント フィルタ</a>」のドキュメントをご覧ください。
</p>
<h2 id="ShuttingDown">アクティビティをシャットダウンする</h2>
<p>アクティビティは、{@link android.app.Activity#finish
finish()} メソッドを呼び出すことでシャットダウンできます。また、{@link android.app.Activity#finishActivity finishActivity()} を呼び出すと以前に開始した別のアクティビティをシャットダウンすることもできます。
</p>
<p class="note"><strong>注:</strong> ほとんどの場合、これらのメソッドを用いてアクティビティを明示的に終了しないでください。
後述のアクティビティのライフサイクルでも説明していますが、Android システム自体がアクティビティのライフサイクルを管理するため、アクティビティを自身で終了させる必要はありません。
これらのメソッドを呼び出すと、期待された操作性に影響を与えることがあるため、ユーザーが絶対にアクティビティのこのインスタンスに戻らないようにする場合にのみ使用するようにしてください。
</p>
<h2 id="Lifecycle">アクティビティのライフサイクルを管理する</h2>
<p>コールバック メソッドを実装したアクティビティのライフサイクルの管理は、強固で柔軟なアプリケーションの開発にとって重要です。
アクティビティのライフサイクルは、他のアクティビティ、タスク、バックスタックとの関連による影響を直接受けます。
</p>
<p>基本的に、アクティビティには次の 3 つの状態があります。</p>
<dl>
<dt><i>再開状態</i></dt>
<dd>アクティビティが画面のフォアグラウンドにあり、ユーザー フォーカスのある状態。(この状態は「実行中」とも呼ばれます)。
</dd>
<dt><i>一時停止状態</i></dt>
<dd>他のアクティビティがフォアグラウンドにあり、メインに表示されているが、このアクティビティも表示されている。つまり、このアクティビティの上に他のアクティビティが表示されており、他方のアクティビティは一部が透明であるか、画面全体を覆ってはいない状態です。
一時停止状態のアクティビティは完全に生きている状態ですが({@link android.app.Activity} オブジェクトがメモリに保持されており、すべての状態やメンバー情報が維持され、ウィンドウ マネージャーにもアタッチされたまま)、メモリ量が極端に低下した場合にはシステムによって強制停止される場合もあります。
</dd>
<dt><i>停止状態</i></dt>
<dd>アクティビティは、他のアクティビティによって完全に見えない状態です(アクティビティが「バックグラウンド」にある)。
停止状態のアクティビティもまだ生きていますが({@link android.app.Activity} オブジェクトがメモリに保持されており、すべての状態やメンバー情報が維持されているが、ウィンドウ マネージャーにはアタッチ<em>されていない</em>状態です)。
ただし、ユーザーには表示されておらず、別の場所でメモリが必要になればシステムによって強制終了される場合もあります。
</dd>
</dl>
<p>アクティビティが一時停止か停止状態の場合、システムはアクティビティに終了するかどうかを尋ねる({@link android.app.Activity#finish finish()} メソッドを呼び出す)か、単純にプロセスを強制終了してメモリから解放できます。
アクティビティを再度開くとき(終了や強制終了後)は、もう一度最初から作成する必要があります。
</p>
<h3 id="ImplementingLifecycleCallbacks">ライフサイクル コールバックを実装する</h3>
<p>アクティビティが上記の異なる状態の間を遷移するとき、さまざまなコールバック メソッドを介して通知されます。
すべてのコールバック メソッドは、アクティビティの状態が変化したときに必要な操作を実行するようオーバーライドできるフックになります。
次のスケルトン アクティビティには、基本的なライフサイクル メソッドがそれぞれ含まれています。
</p>
<pre>
public class ExampleActivity extends Activity {
&#64;Override
public void {@link android.app.Activity#onCreate onCreate}(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
&#64;Override
protected void {@link android.app.Activity#onStart onStart()} {
super.onStart();
// The activity is about to become visible.
}
&#64;Override
protected void {@link android.app.Activity#onResume onResume()} {
super.onResume();
// The activity has become visible (it is now "resumed").
}
&#64;Override
protected void {@link android.app.Activity#onPause onPause()} {
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
&#64;Override
protected void {@link android.app.Activity#onStop onStop()} {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
&#64;Override
protected void {@link android.app.Activity#onDestroy onDestroy()} {
super.onDestroy();
// The activity is about to be destroyed.
}
}
</pre>
<p class="note"><strong>注:</strong> これらのライフサイクル メソッドを実装する際は、上記の例のように、すべての操作の前にスーパークラスの実装を呼び出す必要があります。
</p>
<p>これらのメソッドすべてで、アクティビティのライフサイクル全体を定義します。これらのメソッドを実装すると、アクティビティのライフサイクル内の次の 3 つのネストされたループを監視できます。
</p>
<ul>
<li>アクティビティの<b> entire lifetime</b> は、{@link
android.app.Activity#onCreate onCreate()} の呼び出しから、{@link
android.app.Activity#onDestroy} の呼び出しまでの間です。アクティビティは、{@link android.app.Activity#onCreate onCreate()} で「グローバル」状態のセットアップ(レイアウトの定義など)を実行し、{@link android.app.Activity#onDestroy} に残っているすべてのリソースを解放する必要があります。
たとえば、アクティビティにネットワークからデータをダウンロードするためバックグラウンドで実行しているスレッドがある場合、そのスレッドが {@link android.app.Activity#onCreate onCreate()} に作成され、{@link
android.app.Activity#onDestroy} のスレッドが停止される場合があります。
</li>
<li><p>アクティビティの<b>visible lifetime</b> は、{@link
android.app.Activity#onStart onStart()} の呼び出しから、{@link
android.app.Activity#onStop onStop()} の呼び出しまでの間です。この間、アクティビティは画面上に表示され、ユーザーが操作できる状態です。
たとえば {@link android.app.Activity#onStop onStop()} は、新たなアクティビティが開始してこのアクティビティが表示されなくなったときに呼び出されます。
これらの 2 つのメソッド間で、アクティビティをユーザーに表示するのに必要なリソースは保持できます
たとえば、{@link android.content.BroadcastReceiver} を {@link
android.app.Activity#onStart onStart()} に登録して UI に影響のある変更を監視し、ユーザーが表示内容の閲覧をやめたときに {@link android.app.Activity#onStop onStop()} で登録解除できます
アクティビティがユーザーに表示されたり、非表示になったりとアクティビティの状態が変化する場合、アクティビティの entire lifetime 中にシステムが {@link android.app.Activity#onStart onStart()} と {@link
android.app.Activity#onStop onStop()} を複数回呼び出すこともあります。
</p></li>
<li><p>アクティビティの <b>foreground lifetime</b> は {@link
android.app.Activity#onResume onResume()} の呼び出しから、{@link android.app.Activity#onPause
onPause()} の呼び出しまでの間です。この間、アクティビティは画面上の他のすべてのアクティビティの前面にあり、ユーザーの入力フォーカスがある状態です。
アクティビティは フォアグラウンドにある状態からそうでない状態に頻繁に遷移する可能性があります。たとえば、端末がスリープ状態になったり、ダイアログが表示されたりしたときには{@link android.app.Activity#onPause onPause()} が呼び出されます。
&mdash;
この状態遷移は頻繁に起こるため、この 2 つのメソッドのコードはユーザーを待たせてしまうような遅い遷移にならないよう、適正な軽い処理にしておく必要があります。
</p></li>
</ul>
<p>図 1 では、状態間でアクティビティがたどる可能性のあるループと経路を表しています。長方形はアクティビティが状態間で遷移したときの処理用に実装できるコールバック メソッドを表しています。
<p>
<img src="{@docRoot}images/activity_lifecycle.png" alt="" />
<p class="img-caption"><strong>図 1.</strong> アクティビティのライフサイクル</p>
<p>表 1 には同じライフサイクル コールバック メソッドがリストされており、各コールバック メソッドの詳細と、アクティビティのライフサイクル全体でのそれぞれの位置関係、コールバック メソッドの完了後にシステムによってアクティビティが強制終了されるかどうかを示しています。
</p>
<p class="table-caption"><strong>表 1.</strong> ライフサイクル コールバック メソッドの概要
</p>
<table border="2" width="85%" frame="hsides" rules="rows">
<colgroup align="left" span="3"></colgroup>
<colgroup align="left"></colgroup>
<colgroup align="center"></colgroup>
<colgroup align="center"></colgroup>
<thead>
<tr><th colspan="3">メソッド</th> <th>説明</th> <th>完了後の強制終了</th> <th>次のメソッド</th></tr>
</thead>
<tbody>
<tr>
<td colspan="3" align="left"><code>{@link android.app.Activity#onCreate onCreate()}</code></td>
<td>アクティビティが最初に作成されるときに呼び出されます。
ここで、ビューの作成、リストとのデータバインドといった、通常の静的なセットアップを行います。&mdash;
アクティビティの前の状態を含む Bundle オブジェクトを取り出せた場合、それをメソッドに渡します(後半の<a href="#actstate">アクティビティの状態を保存する</a>をご覧ください)。
<p>常に {@code onStart()} が後に続きます。</p></td>
<td align="center">いいえ</td>
<td align="center">{@code onStart()}</td>
</tr>
<tr>
<td rowspan="5" style="border-left: none; border-right: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td colspan="2" align="left"><code>{@link android.app.Activity#onRestart
onRestart()}</code></td>
<td>アクティビティが停止した後、再開する直前に呼び出されます。
<p>常に {@code onStart()} が後に続きます。</p></td>
<td align="center">いいえ</td>
<td align="center">{@code onStart()}</td>
</tr>
<tr>
<td colspan="2" align="left"><code>{@link android.app.Activity#onStart onStart()}</code></td>
<td>アクティビティがユーザーに見える状態になる直前に呼び出されます。
<p>アクティビティがフォアグラウンドになったときは {@code onResume()} が後に続き、アクティビティが非表示になったときは {@code onStop()} が後に続きます。
</p></td>
<td align="center">いいえ</td>
<td align="center">{@code onResume()} <br/>または<br/> {@code onStop()}</td>
</tr>
<tr>
<td rowspan="2" style="border-left: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td align="left"><code>{@link android.app.Activity#onResume onResume()}</code></td>
<td>アクティビティとユーザーとの操作が開始する直前に呼び出されます。
この時点で、アクティビティはアクティビティ スタックの先頭にあり、ユーザー入力の準備ができています。
<p>常に {@code onPause()} が後に続きます。</p></td>
<td align="center">いいえ</td>
<td align="center">{@code onPause()}</td>
</tr>
<tr>
<td align="left"><code>{@link android.app.Activity#onPause onPause()}</code></td>
<td>システムが別のアクティビティを再開する直前に呼び出されます。
通常、このメソッドは永続化データへの未保存の変更をコミットしたり、アニメーションや CPU を消費する可能性のあるその他の動作を停止したりする際に使用されます。
それが完了するまで次のアクティビティが再開できないため、それらの操作は迅速に行う必要があります。
<p>アクティビティが前面に戻るときは {@code onResume()} が後に続き、アクティビティが非表示になるときは {@code onStop()} が後に続きます。
</td>
<td align="center"><strong style="color:#800000">はい</strong></td>
<td align="center">{@code onResume()} <br/>または<br/> {@code onStop()}</td>
</tr>
<tr>
<td colspan="2" align="left"><code>{@link android.app.Activity#onStop onStop()}</code></td>
<td>アクティビティがユーザーに見えなくなると呼び出されます。これは、アクティビティが破棄されたか、別のアクティビティ(既存のアクティビティや新しいアクティビティ)が再開されてこのアクティビティを覆っている場合に起こります。
<p>アクティビティのユーザー操作が可能に戻るときは {@code onRestart()} が後に続き、アクティビティがなくなるときは {@code onDestroy()} が後に続きます。
</p></td>
<td align="center"><strong style="color:#800000">はい</strong></td>
<td align="center">{@code onRestart()} <br/>または<br/> {@code onDestroy()}</td>
</tr>
<tr>
<td colspan="3" align="left"><code>{@link android.app.Activity#onDestroy
onDestroy()}</code></td>
<td>アクティビティが破棄される前に呼び出されます。これはアクティビティが受け取る最後の呼び出しです。
アクティビティが終了した(<code>{@link android.app.Activity#finish
finish()}</code> が呼び出された)か、アクティビティ領域を節約するためにシステムが一時的にこのアクティビティを破棄した場合に呼び出されます。
この 2 つのシナリオは、<code>{@link
android.app.Activity#isFinishing isFinishing()}</code> メソッドで区別できます。
</td>
<td align="center"><strong style="color:#800000">はい</strong></td>
<td align="center"><em>なし</em></td>
</tr>
</tbody>
</table>
<p>「完了後の強制終了」の列は、<em>メソッドが戻った後</em>に、アクティビティのコードの後続行を実行することなく、アクティビティをホストするプロセスをシステムが強制終了できるかどうかを示しています。
3 つのメソッド({@link
android.app.Activity#onPause
onPause()}、{@link android.app.Activity#onStop onStop()}、{@link android.app.Activity#onDestroy
onDestroy()})が「はい」になっています。{@link android.app.Activity#onPause onPause()} は 3 つのなかで最初であるため、アクティビティが作成された後は{@link android.app.Activity#onPause onPause()} がプロセスが強制終了される<em>可能性がある</em>前に呼び出されることが保証される最後のメソッドです。システムが緊急でメモリを空ける必要がある場合は、{@link
android.app.Activity#onStop onStop()} と {@link android.app.Activity#onDestroy onDestroy()} は呼び出されない場合があります。
&mdash;
そのため、重要な永続的データ(ユーザーの編集内容など)をストレージに書き込む際は、{@link android.app.Activity#onPause onPause()} を使用する必要があります。
ただし、このメソッドで後続のアクティビティへの遷移をブロックしてしまい、ユーザー操作の速度を送らせてしまうことから、{@link android.app.Activity#onPause onPause()} 中にどんな情報を保持するかについては吟味する必要があります。
</p>
<p> <b>「強制終了」</b>列で「いいえ」となっているメソッドでは、アクティビティが呼び出された時点から、アクティビティをホストするプロセスが強制終了されないよう保護します。
つまり、アクティビティが強制終了される可能性があるのは、{@link android.app.Activity#onPause onPause()} が戻ってから、{@link android.app.Activity#onResume onResume()} が呼び出されるまでの間です。
{@link android.app.Activity#onPause onPause()} が再度呼び出されて戻るまでは、再度強制終了されることはありません。
</p>
<p class="note"><strong>注:</strong> 表 1 の定義では技術的に「強制終了」できないアクティビティでも、システムによって強制終了されることがありますが、そうなるのはリソース不足などの緊急時のみです。
&mdash;
アクティビティが強制終了されるケースについては、<a href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threading</a> のドキュメントで説明しています。
</p>
<h3 id="SavingActivityState">アクティビティの状態を保存する</h3>
<p><a href="#Lifecycle">アクティビティのライフサイクルを管理する</a>でも簡単に説明したように、アクティビティが一時停止や停止したとき、アクティビティの状態は保持されます。
これは、一時停止や停止されたときも {@link android.app.Activity} オブジェクトがメモリに保持されるためです &mdash; メンバーや現在の状態といったすべての情報は残っています。
つまり、アクティビティ内でユーザーが加えた変更点は保持されるため、アクティビティがフォアグラウンドに戻ったとき(「再開」したとき)、それらの変更点はそのまま表示されます。
</p>
<p>ただし、メモリを確保するためにシステムがアクティビティを破棄すると、 {@link
android.app.Activity} オブジェクトが破棄されるため、システムはそれをそのままの状態で再開できなくなります。
代わりに、ユーザーがそれに戻る操作を行った場合、システムは {@link android.app.Activity} オブジェクトを再作成します。
ユーザーにはシステムがアクティビティを破棄して再作成したことはわからないため、アクティビティが以前の状態のままであることを期待します。
この場合、アクティビティの状態情報を保存できる追加のコールバック メソッド({@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()})を実装することで、アクティビティの状態に関する重要な情報を維持できます。
</p>
<p>アクティビティが破棄されるような状態になる前に、システムが {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} を呼び出します。
システムはこのメソッドを {@link android.os.Bundle} に渡し、そこでアクティビティの状態情報を名前と値のペアとして {@link
android.os.Bundle#putString putString()} や {@link
android.os.Bundle#putInt putInt()} などのメソッドを使用して保存できます。
その後、システムがアプリケーション プロセスを強制終了して、ユーザーがアクティビティに戻った場合、システムはアクティビティを再作成して {@link android.os.Bundle} を {@link android.app.Activity#onCreate onCreate()} と {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} の両方に渡します。
いずれのメソッドを使った場合でも、保存した状態を {@link android.os.Bundle} から抽出してアクティビティの状態を復元できます。
復元する状態情報がない場合は、{@link
android.os.Bundle} は null で渡されます(アクティビティを最初に作成した場合がこれにあたります)。
</p>
<img src="{@docRoot}images/fundamentals/restore_instance.png" alt="" />
<p class="img-caption"><strong>図 2.</strong> アクティビティが前の状態のままでユーザー フォーカスに戻るには、アクティビティが破棄され、再作成された後にアクティビティが保存された以前の状態を復元する必要があるか、アクティビティが停止し、再開した後にアクティビティの状態が以前のままになるか、の 2 つの方法があります。
</p>
<p class="note"><strong>注:</strong> アクティビティが破棄される前に {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} が呼び出される保証はありません。これは、状態を保存する必要がないケースがあるためです(ユーザーが [<em>戻る</em>] ボタンを使用してアクティビティを離れることで明示的にアクティビティを閉じた場合など)。
システムが {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()} を呼び出す場合、呼び出しは常に {@link
android.app.Activity#onStop onStop()} の前、場合によっては {@link android.app.Activity#onPause
onPause()} の前に行われます。</p>
<p>ただし、何もせず {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} も実装しない場合でも、{@link android.app.Activity} クラスの {@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} のデフォルトの実装によって、アクティビティの状態が復元されるものもあります。
具体的には、デフォルトの実装がレイアウト内のすべての {@link
android.view.View} の {@link
android.view.View#onSaveInstanceState onSaveInstanceState()} を呼び出すことで、各ビューが保存すべき情報を提供できるようになります。
Android フレームワークの大半のウィジェットが必要に応じてこのメソッドを実装しており、UI への視覚的な変更は自動的に保存され、アクティビティが再作成されると復元されるようになっています。
たとえば、{@link android.widget.EditText} ウィジェットではユーザーが入力したすべてのテキストを保存し、{@link android.widget.CheckBox} ウィジェットはオンにされたかどうかを保存するようになっています。
ここで必要な作業は、状態を保存する各ウィジェット用の一意の ID(<a href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">{@code android:id}</a>)を提供するだけです。
ウィジェットに ID がないと、システムは状態を保存できません。
</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>また、レイアウトのビューでの状態の保存を明示的に停止するには、{@link android.R.attr#saveEnabled android:saveEnabled} 属性を {@code "false"} に設定するか、{@link android.view.View#setSaveEnabled setSaveEnabled()} メソッドを呼び出します。
通常はこの機能を無効にしませんが、アクティビティ UI の状態を別の方法で復元する場合には無効にできます。
</p>
</div>
</div>
<p>{@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} のデフォルトの実装によってアクティビティの UI に関する有用な情報は保存されますが、追加の情報を保存するようそれをオーバーライドすることもできます。例としては、アクティビティの期間に変更されたメンバー値を保存する必要があるケースなどがあります。(UI で復元された値に関連している場合でも、それらの UI 値を持つメンバーはデフォルトでは復元されません)。
</p>
<p>{@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} のデフォルトの実装で UI の状態を保存できるため、状態の追加情報を保存するようメソッドをオーバーライドする場合は、常に作業前に {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} のスーパークラス実装を呼び出す必要があります。
同様に、オーバーライドする場合はデフォルトの実装でビューの状態を復元できるよう、{@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()} のスーパークラスの実装も呼び出す必要があります。
</p>
<p class="note"><strong>注:</strong> {@link android.app.Activity#onSaveInstanceState
onSaveInstanceState()} は呼び出される保証がないため、これはアクティビティの一時的な状態の記録用にのみ使用し、永続的データの保存には使用しないようにします。
&mdash;代わりに {@link
android.app.Activity#onPause onPause()} を使用して、ユーザーがアクティビティを離れたときの永続的データ(データベースに保存するインストール必要のあるデータなど)を保存します。
</p>
<p>アプリケーションが状態を復元できるかどうかテストするには、端末を回転してみて、方向が変化するかを確認します
画面の方向が変わるとき、システムがアクティビティを破棄して再作成し、新しい画面構成に利用可能な別のリソースを適用します。
アプリケーションの使用中にユーザーが端末を回転させるという場面は日常的にあるため、アクティビティが再作成されたときに状態を完全に復元することは非常に重要です。
</p>
<h3 id="ConfigurationChanges">構成の変更を処理する</h3>
<p>端末の構成の中には、実行の際に変化するものがあります(画面の向き、キーボードの可用性、言語など)。
そのような変化が生じたとき、Android は実行中のアクティビティを再作成します(システムが {@link android.app.Activity#onDestroy} を呼び出し、その後すぐに {@link
android.app.Activity#onCreate onCreate()})を呼び出します。
この動作は、提供した別のリソース(異なる画面の向きやサイズに応じたレイアウトなど)を使用してアプリケーションを自動的にリロードすることで、アプリケーションを新しい構成に適応させることを目的としています。
</p>
<p>前述のように画面の向きの変化による再起動を処理して、アクティビティの状態を復元するようアプリケーションを適切にデザインしていれば、アプリケーションはアクティビティのライフサイクルでの予期しない他のイベントに対しても回復力を持つことができます。
</p>
<p>このような再起動を処理するのに最適な方法は、前のセクションで説明したように、{@link
android.app.Activity#onSaveInstanceState onSaveInstanceState()} と {@link
android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}(または {@link
android.app.Activity#onCreate onCreate()})を使用してアクティビティの状態を保存、復元する方法です。
</p>
<p>実行の際に起こる構成の変更と、その処理方法の詳細については、「<a href="{@docRoot}guide/topics/resources/runtime-changes.html">実行時の変更の処理</a>」のガイドをご覧ください。
</p>
<h3 id="CoordinatingActivities">アクティビティを連携する</h3>
<p>1 つのアクティビティで別のアクティビティを開始すると、双方でライフサイクルの遷移が生じます。1 つ目のアクティビティが一時停止したり停止したりすると(バックグラウンドにある場合は停止しません)、もう一方のアクティビティが作成されます。
これらのアクティビティでディスクなどに保存されているデータを共有している場合は、2 つ目のアクティビティが作成される前に 1 つ目のアクティビティが完全に停止することはないということを理解しておくことが重要です。むしろ、2 つ目の開始プロセスは、1 つ目の停止プロセスにオーバーラップします。
</p>
<p>特に 2 つのアクティビティが同じプロセスにあって 1 つが別のアクティビティを開始する場合、ライフサイクル コールバックの順序は厳密に定義されています。
アクティビティ A がアクティビティ B を開始する場合の動作の順序を次に示します。
</p>
<ol>
<li>アクティビティ A の {@link android.app.Activity#onPause onPause()} メソッドが実行されます。</li>
<li>アクティビティ B の {@link android.app.Activity#onCreate onCreate()}、{@link
android.app.Activity#onStart onStart()}、{@link android.app.Activity#onResume onResume()} メソッドが順次実行されます
(このとき、ユーザー フォーカスはアクティビティ B にあります)。</li>
<li>次に、アクティビティ A が画面から消えた場合、{@link
android.app.Activity#onStop onStop()} メソッドが実行されます。</li>
</ol>
<p>このライフサイクル コールバックの順序を予測しておくことで、1 つのアクティビティから他のアクティビティへの情報の遷移を管理できるようになります。
たとえば、1 つ目のアクティビティが停止したときに、後続のアクティビティが読み取れるようにデータベースに書き込む必要がある場合、データベースに書き込むタイミングは {@link
android.app.Activity#onStop onStop()} ではなく {@link android.app.Activity#onPause onPause()} の間になります。
</p>
<!--
<h2>Beginner's Path</h2>
<p>For more information about how Android maintains a history of activities and
enables user multitasking, continue with the <b><a
href="{@docRoot}guide/components/tasks-and-back-stack.html">Tasks and Back
Stack</a></b> document.</p>
-->

Some files were not shown because too many files have changed in this diff Show More