diff --git a/Android.mk b/Android.mk index 7230cbff33d915b9f67b7f69922bd858ae058519..c0bb7240c796b2dff88d480e91c90199824247ee 100644 --- a/Android.mk +++ b/Android.mk @@ -75,6 +75,7 @@ LOCAL_SRC_FILES += \ core/java/android/app/IAppTask.aidl \ core/java/android/app/ITaskStackListener.aidl \ core/java/android/app/IBackupAgent.aidl \ + core/java/android/app/IEphemeralResolver.aidl \ core/java/android/app/IInstrumentationWatcher.aidl \ core/java/android/app/INotificationManager.aidl \ core/java/android/app/IProcessObserver.aidl \ @@ -201,6 +202,7 @@ LOCAL_SRC_FILES += \ core/java/android/net/ICaptivePortal.aidl \ core/java/android/net/IConnectivityManager.aidl \ core/java/android/net/IConnectivityMetricsLogger.aidl \ + core/java/android/net/IIpConnectivityMetrics.aidl \ core/java/android/net/IEthernetManager.aidl \ core/java/android/net/IEthernetServiceListener.aidl \ core/java/android/net/INetworkManagementEventObserver.aidl \ @@ -309,9 +311,9 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/app/IAppOpsService.aidl \ core/java/com/android/internal/app/IAssistScreenshotReceiver.aidl \ core/java/com/android/internal/app/IBatteryStats.aidl \ - core/java/com/android/internal/app/IEphemeralResolver.aidl \ core/java/com/android/internal/app/ISoundTriggerService.aidl \ core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \ + core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl \ core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl \ core/java/com/android/internal/app/IVoiceInteractor.aidl \ core/java/com/android/internal/app/IVoiceInteractorCallback.aidl \ @@ -322,6 +324,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \ core/java/com/android/internal/backup/IBackupTransport.aidl \ core/java/com/android/internal/backup/IObbBackupService.aidl \ + core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \ core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \ core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \ core/java/com/android/internal/policy/IKeyguardService.aidl \ @@ -345,6 +348,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/view/IInputMethodManager.aidl \ core/java/com/android/internal/view/IInputMethodSession.aidl \ core/java/com/android/internal/view/IInputSessionCallback.aidl \ + core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl \ core/java/com/android/internal/widget/ILockSettings.aidl \ core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \ core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \ @@ -471,6 +475,9 @@ LOCAL_SRC_FILES += \ ../../system/update_engine/binder_bindings/android/os/IUpdateEngine.aidl \ ../../system/update_engine/binder_bindings/android/os/IUpdateEngineCallback.aidl \ +LOCAL_SRC_FILES += \ + ../../system/netd/server/binder/android/net/INetd.aidl \ + LOCAL_AIDL_INCLUDES += system/update_engine/binder_bindings # FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk @@ -504,6 +511,10 @@ LOCAL_JACK_FLAGS := --multi-dex native LOCAL_RMTYPEDEFS := true +ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true) +LOCAL_EMMA_INSTRUMENT := true +endif + include $(BUILD_JAVA_LIBRARY) framework_module := $(LOCAL_INSTALLED_MODULE) @@ -695,6 +706,7 @@ aidl_files := \ frameworks/base/core/java/android/service/quicksettings/Tile.aidl \ frameworks/native/aidl/binder/android/os/PersistableBundle.aidl \ system/netd/server/binder/android/net/UidRange.aidl \ + frameworks/base/telephony/java/android/telephony/PcoData.aidl \ gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl $(gen): PRIVATE_SRC_FILES := $(aidl_files) @@ -886,16 +898,16 @@ sample_groups := -samplegroup Admin \ ## SDK version identifiers used in the published docs # major[.minor] version for current SDK. (full releases only) -framework_docs_SDK_VERSION:=6.0 +framework_docs_SDK_VERSION:=7.0 # release version (ie "Release x") (full releases only) framework_docs_SDK_REL_ID:=1 framework_docs_LOCAL_DROIDDOC_OPTIONS += \ -hdf sdk.codename N \ - -hdf sdk.preview.version 2 \ + -hdf sdk.preview.version 5 \ -hdf sdk.version $(framework_docs_SDK_VERSION) \ -hdf sdk.rel.id $(framework_docs_SDK_REL_ID) \ - -hdf sdk.preview 1 + -hdf sdk.preview 0 # ==== the api stubs and current.xml =========================== include $(CLEAR_VARS) @@ -915,6 +927,7 @@ LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES LOCAL_DROIDDOC_OPTIONS:=\ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -referenceonly \ -api $(INTERNAL_PLATFORM_API_FILE) \ -removedApi $(INTERNAL_PLATFORM_REMOVED_API_FILE) \ -nodocs @@ -948,6 +961,7 @@ LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES LOCAL_DROIDDOC_OPTIONS:=\ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -referenceonly \ -showAnnotation android.annotation.SystemApi \ -api $(INTERNAL_PLATFORM_SYSTEM_API_FILE) \ -removedApi $(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE) \ @@ -982,6 +996,7 @@ LOCAL_DROIDDOC_STUB_OUT_DIR := $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES LOCAL_DROIDDOC_OPTIONS:=\ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -referenceonly \ -stubs $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/android_test_stubs_current_intermediates/src \ -showAnnotation android.annotation.TestApi \ -api $(INTERNAL_PLATFORM_TEST_API_FILE) \ @@ -1015,6 +1030,7 @@ LOCAL_MODULE := doc-comment-check LOCAL_DROIDDOC_OPTIONS:=\ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -referenceonly \ -parsecomments LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk @@ -1045,6 +1061,42 @@ LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) LOCAL_MODULE := offline-sdk +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 + +LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk + +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) + + +# ==== static html in the sdk ================================== +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-sdk-referenceonly + LOCAL_DROIDDOC_OPTIONS:=\ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ -offlinemode \ @@ -1059,10 +1111,17 @@ LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk include $(BUILD_DROIDDOC) static_doc_index_redirect := $(out_dir)/index.html -$(static_doc_index_redirect): $(LOCAL_PATH)/docs/docs-preview-index.html +$(static_doc_index_redirect): $(LOCAL_PATH)/docs/docs-documentation-redirect.html $(copy-file-to-target) +static_doc_properties := $(out_dir)/source.properties +$(static_doc_properties): \ + $(LOCAL_PATH)/docs/source.properties | $(ACP) + $(hide) mkdir -p $(dir $@) + $(hide) $(ACP) $< $@ + $(full_target): $(static_doc_index_redirect) +$(full_target): $(static_doc_properties) $(full_target): $(framework_built) @@ -1114,6 +1173,7 @@ LOCAL_MODULE := online-system-api-sdk LOCAL_DROIDDOC_OPTIONS:= \ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -referenceonly \ -showAnnotation android.annotation.SystemApi \ -title "Android SDK - Including system APIs." \ -toroot / \ @@ -1150,17 +1210,67 @@ LOCAL_MODULE := ds LOCAL_DROIDDOC_OPTIONS:= \ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ - -devsite \ - -hdf devsite true \ -toroot / \ -hdf android.whichdoc online \ + -devsite \ $(sample_groups) \ - -useUpdatedTemplates \ -hdf android.hasSamples true \ - -yaml _book.yaml \ -samplesdir $(samples_dir) -LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-dev +LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk + +include $(BUILD_DROIDDOC) + +# ==== docs for the web (on the devsite 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:=$(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 / + +LOCAL_MODULE := ds-static + +LOCAL_DROIDDOC_OPTIONS:= \ + $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -hdf android.whichdoc online \ + -staticonly \ + -toroot / \ + -devsite \ + -ignoreJdLinks + +LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk + +include $(BUILD_DROIDDOC) + +# ==== generates full navtree for resolving @links in ds postprocessing ==== +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_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR) +LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) + +LOCAL_MODULE := ds-ref-navtree + +LOCAL_DROIDDOC_OPTIONS:= \ + $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -hdf android.whichdoc online \ + -toroot / \ + -atLinksNavtree \ + -navtreeonly + +LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk include $(BUILD_DROIDDOC) @@ -1185,11 +1295,10 @@ 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-dev +LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk include $(BUILD_DROIDDOC) @@ -1208,6 +1317,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) LOCAL_MODULE := hidden LOCAL_DROIDDOC_OPTIONS:=\ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \ + -referenceonly \ -title "Android SDK - Including hidden APIs." # -hidden diff --git a/api/current.txt b/api/current.txt index c1314ad050914f624d40030f14f9705b52e5b35a..2788f3648eb661137f9a07cb6232ee79858872b7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -397,6 +397,7 @@ package android { field public static final int colorPressedHighlight = 16843661; // 0x101038d field public static final int colorPrimary = 16843827; // 0x1010433 field public static final int colorPrimaryDark = 16843828; // 0x1010434 + field public static final int colorSecondary = 16844080; // 0x1010530 field public static final int columnCount = 16843639; // 0x1010377 field public static final int columnDelay = 16843215; // 0x10101cf field public static final int columnOrderPreserved = 16843640; // 0x1010378 @@ -420,7 +421,9 @@ package android { field public static final int contentInsetStart = 16843859; // 0x1010453 field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522 field public static final int contextClickable = 16844007; // 0x10104e7 + field public static final int contextDescription = 16844078; // 0x101052e field public static final int contextPopupMenuStyle = 16844033; // 0x1010501 + field public static final int contextUri = 16844077; // 0x101052d field public static final int controlX1 = 16843772; // 0x10103fc field public static final int controlX2 = 16843774; // 0x10103fe field public static final int controlY1 = 16843773; // 0x10103fd @@ -1039,6 +1042,7 @@ package android { field public static final int rotation = 16843558; // 0x1010326 field public static final int rotationX = 16843559; // 0x1010327 field public static final int rotationY = 16843560; // 0x1010328 + field public static final int roundIcon = 16844076; // 0x101052c field public static final int rowCount = 16843637; // 0x1010375 field public static final int rowDelay = 16843216; // 0x10101d0 field public static final int rowEdgeFlags = 16843329; // 0x1010241 @@ -1106,11 +1110,16 @@ package android { field public static final int shareInterpolator = 16843195; // 0x10101bb field public static final int sharedUserId = 16842763; // 0x101000b field public static final int sharedUserLabel = 16843361; // 0x1010261 + field public static final int shortcutDisabledMessage = 16844075; // 0x101052b + field public static final int shortcutId = 16844072; // 0x1010528 + field public static final int shortcutLongLabel = 16844074; // 0x101052a + field public static final int shortcutShortLabel = 16844073; // 0x1010529 field public static final int shouldDisableView = 16843246; // 0x10101ee field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 field public static final int showForAllUsers = 16844015; // 0x10104ef + field public static final int showMetadataInPreview = 16844079; // 0x101052f field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb field public static final int showText = 16843949; // 0x10104ad @@ -3696,6 +3705,7 @@ package android.app { method public void moveTaskToFront(int, int); method public void moveTaskToFront(int, int, android.os.Bundle); method public deprecated void restartPackage(java.lang.String); + method public static void setVrThread(int); method public void setWatchHeapLimit(long); field public static final java.lang.String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT"; field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1 @@ -5037,12 +5047,14 @@ package android.app { method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder); method public java.lang.CharSequence getCancelLabel(); method public java.lang.CharSequence getConfirmLabel(); + method public boolean getHintDisplayActionInline(); method public boolean getHintLaunchesActivity(); method public java.lang.CharSequence getInProgressLabel(); method public boolean isAvailableOffline(); method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean); method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence); method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence); + method public android.app.Notification.Action.WearableExtender setHintDisplayActionInline(boolean); method public android.app.Notification.Action.WearableExtender setHintLaunchesActivity(boolean); method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence); } @@ -5756,7 +5768,10 @@ package android.app { method public android.content.pm.ServiceInfo getServiceInfo(); method public java.lang.String getServiceName(); method public java.lang.String getSettingsActivity(); + method public boolean getShowMetadataInPreview(); method public java.lang.CharSequence loadAuthor(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; + method public java.lang.CharSequence loadContextDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; + method public android.net.Uri loadContextUri(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager); method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager); @@ -6484,11 +6499,13 @@ package android.app.usage { method public android.content.res.Configuration getConfiguration(); method public int getEventType(); method public java.lang.String getPackageName(); + method public java.lang.String getShortcutId(); method public long getTimeStamp(); field public static final int CONFIGURATION_CHANGE = 5; // 0x5 field public static final int MOVE_TO_BACKGROUND = 2; // 0x2 field public static final int MOVE_TO_FOREGROUND = 1; // 0x1 field public static final int NONE = 0; // 0x0 + field public static final int SHORTCUT_INVOCATION = 8; // 0x8 field public static final int USER_INTERACTION = 7; // 0x7 } @@ -8191,6 +8208,7 @@ package android.content { field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions"; field public static final java.lang.String SEARCH_SERVICE = "search"; field public static final java.lang.String SENSOR_SERVICE = "sensor"; + field public static final java.lang.String SHORTCUT_SERVICE = "shortcut"; field public static final java.lang.String STORAGE_SERVICE = "storage"; field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth"; field public static final java.lang.String TELECOM_SERVICE = "telecom"; @@ -9500,13 +9518,20 @@ package android.content.pm { public class LauncherApps { method public java.util.List getActivityList(java.lang.String, android.os.UserHandle); + method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int); + method public android.graphics.drawable.Drawable getShortcutIconDrawable(android.content.pm.ShortcutInfo, int); + method public java.util.List getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle); + method public boolean hasShortcutHostPermission(); method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle); method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle); + method public void pinShortcuts(java.lang.String, java.util.List, android.os.UserHandle); method public void registerCallback(android.content.pm.LauncherApps.Callback); method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler); method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle); method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); + method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle); + method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle); method public void unregisterCallback(android.content.pm.LauncherApps.Callback); } @@ -9519,6 +9544,20 @@ package android.content.pm { method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle); method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean); method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle); + method public void onShortcutsChanged(java.lang.String, java.util.List, android.os.UserHandle); + } + + public static class LauncherApps.ShortcutQuery { + ctor public LauncherApps.ShortcutQuery(); + method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName); + method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long); + method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String); + method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int); + method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List); + field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4 + field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1 + field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8 + field public static final int FLAG_MATCH_PINNED = 2; // 0x2 } public class PackageInfo implements android.os.Parcelable { @@ -10019,6 +10058,66 @@ package android.content.pm { field public java.lang.String permission; } + public final class ShortcutInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.content.ComponentName getActivity(); + method public java.util.Set getCategories(); + method public java.lang.CharSequence getDisabledMessage(); + method public android.os.PersistableBundle getExtras(); + method public java.lang.String getId(); + method public android.content.Intent getIntent(); + method public android.content.Intent[] getIntents(); + method public long getLastChangedTimestamp(); + method public java.lang.CharSequence getLongLabel(); + method public java.lang.String getPackage(); + method public int getRank(); + method public java.lang.CharSequence getShortLabel(); + method public android.os.UserHandle getUserHandle(); + method public boolean hasKeyFieldsOnly(); + method public boolean isDeclaredInManifest(); + method public boolean isDynamic(); + method public boolean isEnabled(); + method public boolean isImmutable(); + method public boolean isPinned(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation"; + } + + public static class ShortcutInfo.Builder { + ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String); + method public android.content.pm.ShortcutInfo build(); + method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName); + method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set); + method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence); + method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle); + method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); + method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent); + method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]); + method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence); + method public android.content.pm.ShortcutInfo.Builder setRank(int); + method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence); + } + + public class ShortcutManager { + method public boolean addDynamicShortcuts(java.util.List); + method public void disableShortcuts(java.util.List); + method public void disableShortcuts(java.util.List, java.lang.CharSequence); + method public void enableShortcuts(java.util.List); + method public java.util.List getDynamicShortcuts(); + method public int getIconMaxHeight(); + method public int getIconMaxWidth(); + method public java.util.List getManifestShortcuts(); + method public int getMaxShortcutCountPerActivity(); + method public java.util.List getPinnedShortcuts(); + method public boolean isRateLimitingActive(); + method public void removeAllDynamicShortcuts(); + method public void removeDynamicShortcuts(java.util.List); + method public void reportShortcutUsed(java.lang.String); + method public boolean setDynamicShortcuts(java.util.List); + method public boolean updateShortcuts(java.util.List); + } + public class Signature implements android.os.Parcelable { ctor public Signature(byte[]); ctor public Signature(java.lang.String); @@ -10225,7 +10324,7 @@ package android.content.res { } public class Resources { - ctor public Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); + ctor public deprecated Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); method public final void finishPreloading(); method public final void flushLayoutCache(); method public android.content.res.XmlResourceParser getAnimation(int) throws android.content.res.Resources.NotFoundException; @@ -10276,7 +10375,7 @@ package android.content.res { method public android.content.res.AssetFileDescriptor openRawResourceFd(int) throws android.content.res.Resources.NotFoundException; method public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException; method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; - method public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); + method public deprecated void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); } public static class Resources.NotFoundException extends java.lang.RuntimeException { @@ -19556,6 +19655,7 @@ package android.media { field public static final android.os.Parcelable.Creator CREATOR; field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_DEFAULT = 1; // 0x1 + field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe field public static final int ENCODING_DTS = 7; // 0x7 field public static final int ENCODING_DTS_HD = 8; // 0x8 field public static final int ENCODING_E_AC3 = 6; // 0x6 @@ -28268,6 +28368,7 @@ package android.os { field public static final int LOLLIPOP_MR1 = 22; // 0x16 field public static final int M = 23; // 0x17 field public static final int N = 24; // 0x18 + field public static final int N_MR1 = 25; // 0x19 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -29261,6 +29362,7 @@ package android.os { method public android.os.Bundle getUserRestrictions(); method public android.os.Bundle getUserRestrictions(android.os.UserHandle); method public boolean hasUserRestriction(java.lang.String); + method public boolean isDemoUser(); method public boolean isQuietModeEnabled(android.os.UserHandle); method public boolean isSystemUser(); method public boolean isUserAGoat(); @@ -29501,6 +29603,7 @@ package android.os.storage { method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); + field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; } public final class StorageVolume implements android.os.Parcelable { @@ -30643,6 +30746,7 @@ package android.provider { public static class CallLog.Calls implements android.provider.BaseColumns { ctor public CallLog.Calls(); method public static java.lang.String getLastOutgoingCall(android.content.Context); + field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7 field public static final int BLOCKED_TYPE = 6; // 0x6 field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number"; field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri"; @@ -30665,6 +30769,7 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final java.lang.String FEATURES = "features"; + field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_VIDEO = 1; // 0x1 field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 @@ -32370,6 +32475,7 @@ package android.provider { field public static final java.lang.String DATA_ROAMING = "data_roaming"; field public static final java.lang.String DEBUG_APP = "debug_app"; field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled"; + field public static final java.lang.String DEVICE_NAME = "device_name"; field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned"; field public static final java.lang.String HTTP_PROXY = "http_proxy"; field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; @@ -32379,7 +32485,7 @@ package android.provider { field public static final java.lang.String RADIO_CELL = "cell"; field public static final java.lang.String RADIO_NFC = "nfc"; field public static final java.lang.String RADIO_WIFI = "wifi"; - field public static final java.lang.String SHOW_PROCESSES = "show_processes"; + field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes"; field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in"; field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale"; field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled"; @@ -32955,6 +33061,7 @@ package android.provider { field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL"; field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL"; field public static final java.lang.String AUTHORITY = "com.android.voicemail"; + field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.provider.extra.PHONE_ACCOUNT_HANDLE"; field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE"; field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package"; } @@ -32963,6 +33070,9 @@ package android.provider { method public static android.net.Uri buildSourceUri(java.lang.String); field public static final java.lang.String CONFIGURATION_STATE = "configuration_state"; field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2 + field public static final int CONFIGURATION_STATE_CONFIGURING = 3; // 0x3 + field public static final int CONFIGURATION_STATE_DISABLED = 5; // 0x5 + field public static final int CONFIGURATION_STATE_FAILED = 4; // 0x4 field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1 field public static final int CONFIGURATION_STATE_OK = 0; // 0x0 field public static final android.net.Uri CONTENT_URI; @@ -32987,6 +33097,7 @@ package android.provider { field public static final int QUOTA_UNAVAILABLE = -1; // 0xffffffff field public static final java.lang.String SETTINGS_URI = "settings_uri"; field public static final java.lang.String SOURCE_PACKAGE = "source_package"; + field public static final java.lang.String SOURCE_TYPE = "source_type"; field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri"; } @@ -35946,9 +36057,14 @@ package android.telecom { method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); + method public final void putExtras(android.os.Bundle); method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, java.lang.String); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); + method public void sendCallEvent(java.lang.String, android.os.Bundle); method public void splitFromConference(); method public void stopDtmfTone(); method public void swapConference(); @@ -35962,6 +36078,7 @@ package android.telecom { field public static final int STATE_DISCONNECTING = 10; // 0xa field public static final int STATE_HOLDING = 3; // 0x3 field public static final int STATE_NEW = 0; // 0x0 + field public static final int STATE_PULLING_CALL = 11; // 0xb field public static final int STATE_RINGING = 2; // 0x2 field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8 } @@ -35972,6 +36089,7 @@ package android.telecom { method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List); method public void onChildrenChanged(android.telecom.Call, java.util.List); method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details); method public void onParentChanged(android.telecom.Call, android.telecom.Call); method public void onPostDialWait(android.telecom.Call, java.lang.String); @@ -36002,6 +36120,7 @@ package android.telecom { method public static java.lang.String propertiesToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 @@ -36021,7 +36140,9 @@ package android.telecom { field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_ENTERPRISE_CALL = 32; // 0x20 field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 + field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_WIFI = 8; // 0x8 } @@ -36072,6 +36193,7 @@ package android.telecom { method public final android.telecom.CallAudioState getCallAudioState(); method public final java.util.List getConferenceableConnections(); method public final int getConnectionCapabilities(); + method public final int getConnectionProperties(); method public final long getConnectionTime(); method public final java.util.List getConnections(); method public final android.telecom.DisconnectCause getDisconnectCause(); @@ -36084,6 +36206,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onConnectionAdded(android.telecom.Connection); method public void onDisconnect(); + method public void onExtrasChanged(android.os.Bundle); method public void onHold(); method public void onMerge(android.telecom.Connection); method public void onMerge(); @@ -36092,10 +36215,14 @@ package android.telecom { method public void onStopDtmfTone(); method public void onSwap(); method public void onUnhold(); + method public final void putExtras(android.os.Bundle); method public final void removeConnection(android.telecom.Connection); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); method public final void setActive(); method public final void setConferenceableConnections(java.util.List); method public final void setConnectionCapabilities(int); + method public final void setConnectionProperties(int); method public final void setConnectionTime(long); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); @@ -36125,6 +36252,7 @@ package android.telecom { method public final android.telecom.Conference getConference(); method public final java.util.List getConferenceables(); method public final int getConnectionCapabilities(); + method public final int getConnectionProperties(); method public final android.telecom.DisconnectCause getDisconnectCause(); method public final android.os.Bundle getExtras(); method public final int getState(); @@ -36135,16 +36263,24 @@ package android.telecom { method public void onAnswer(int); method public void onAnswer(); method public void onCallAudioStateChanged(android.telecom.CallAudioState); + method public void onCallEvent(java.lang.String, android.os.Bundle); method public void onDisconnect(); + method public void onExtrasChanged(android.os.Bundle); method public void onHold(); method public void onPlayDtmfTone(char); method public void onPostDialContinue(boolean); + method public void onPullExternalCall(); method public void onReject(); method public void onReject(java.lang.String); method public void onSeparate(); method public void onStateChanged(int); method public void onStopDtmfTone(); method public void onUnhold(); + method public static java.lang.String propertiesToString(int); + method public final void putExtras(android.os.Bundle); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); + method public void sendConnectionEvent(java.lang.String, android.os.Bundle); method public final void setActive(); method public final void setAddress(android.net.Uri, int); method public final void setAudioModeIsVoip(boolean); @@ -36152,6 +36288,7 @@ package android.telecom { method public final void setConferenceableConnections(java.util.List); method public final void setConferenceables(java.util.List); method public final void setConnectionCapabilities(int); + method public final void setConnectionProperties(int); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); method public final void setExtras(android.os.Bundle); @@ -36160,6 +36297,7 @@ package android.telecom { method public final void setNextPostDialChar(char); method public final void setOnHold(); method public final void setPostDialWait(java.lang.String); + method public final void setPulling(); method public final void setRingbackRequested(boolean); method public final void setRinging(); method public final void setStatusHints(android.telecom.StatusHints); @@ -36168,6 +36306,7 @@ package android.telecom { method public static java.lang.String stateToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000 field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 @@ -36185,15 +36324,21 @@ package android.telecom { field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800 field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2 field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8 + field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED"; + field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; + field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL"; field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; + field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10 field public static final int STATE_ACTIVE = 4; // 0x4 field public static final int STATE_DIALING = 3; // 0x3 field public static final int STATE_DISCONNECTED = 6; // 0x6 field public static final int STATE_HOLDING = 5; // 0x5 field public static final int STATE_INITIALIZING = 0; // 0x0 field public static final int STATE_NEW = 1; // 0x1 + field public static final int STATE_PULLING_CALL = 7; // 0x7 field public static final int STATE_RINGING = 2; // 0x2 } @@ -36271,7 +36416,9 @@ package android.telecom { method public java.lang.String getReason(); method public int getTone(); method public void writeToParcel(android.os.Parcel, int); + field public static final int ANSWERED_ELSEWHERE = 11; // 0xb field public static final int BUSY = 7; // 0x7 + field public static final int CALL_PULLED = 12; // 0xc field public static final int CANCELED = 4; // 0x4 field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa field public static final android.os.Parcelable.Creator CREATOR; @@ -36307,6 +36454,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onCallRemoved(android.telecom.Call); method public void onCanAddCallChanged(boolean); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onSilenceRinger(); method public final void setAudioRoute(int); method public final void setMuted(boolean); @@ -36430,6 +36578,7 @@ package android.telecom { method public void onConferenceableConnectionsChanged(android.telecom.RemoteConference, java.util.List); method public void onConnectionAdded(android.telecom.RemoteConference, android.telecom.RemoteConnection); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConference, int); + method public void onConnectionPropertiesChanged(android.telecom.RemoteConference, int); method public void onConnectionRemoved(android.telecom.RemoteConference, android.telecom.RemoteConnection); method public void onDestroyed(android.telecom.RemoteConference); method public void onDisconnected(android.telecom.RemoteConference, android.telecom.DisconnectCause); @@ -36448,6 +36597,7 @@ package android.telecom { method public android.telecom.RemoteConference getConference(); method public java.util.List getConferenceableConnections(); method public int getConnectionCapabilities(); + method public int getConnectionProperties(); method public android.telecom.DisconnectCause getDisconnectCause(); method public final android.os.Bundle getExtras(); method public int getState(); @@ -36459,6 +36609,7 @@ package android.telecom { method public boolean isVoipAudioMode(); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.RemoteConnection.Callback); method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler); method public void reject(); @@ -36475,6 +36626,8 @@ package android.telecom { method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference); method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int); + method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle); + method public void onConnectionPropertiesChanged(android.telecom.RemoteConnection, int); method public void onDestroyed(android.telecom.RemoteConnection); method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause); method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle); @@ -36571,6 +36724,7 @@ package android.telecom { field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; + field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 @@ -36625,9 +36779,11 @@ package android.telephony { field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool"; field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool"; + field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call"; field public static final java.lang.String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool"; field public static final java.lang.String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool"; field public static final java.lang.String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool"; + field public static final java.lang.String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool"; field public static final java.lang.String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool"; field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool"; field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool"; @@ -36659,6 +36815,7 @@ package android.telephony { field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool"; field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string"; field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool"; + field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool"; field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool"; field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int"; field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool"; @@ -36717,6 +36874,7 @@ package android.telephony { field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; field public static final java.lang.String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool"; field public static final java.lang.String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool"; + field public static final java.lang.String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool"; field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool"; field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool"; field public static final java.lang.String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool"; @@ -37315,12 +37473,15 @@ package android.telephony { field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6 field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc field public static final int NETWORK_TYPE_GPRS = 1; // 0x1 + field public static final int NETWORK_TYPE_GSM = 16; // 0x10 field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8 field public static final int NETWORK_TYPE_HSPA = 10; // 0xa field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9 field public static final int NETWORK_TYPE_IDEN = 11; // 0xb + field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12 field public static final int NETWORK_TYPE_LTE = 13; // 0xd + field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11 field public static final int NETWORK_TYPE_UMTS = 3; // 0x3 field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0 field public static final int PHONE_TYPE_CDMA = 2; // 0x2 @@ -40121,7 +40282,10 @@ package android.util { method public boolean equals(android.util.DisplayMetrics); method public void setTo(android.util.DisplayMetrics); method public void setToDefaults(); + field public static final int DENSITY_260 = 260; // 0x104 field public static final int DENSITY_280 = 280; // 0x118 + field public static final int DENSITY_300 = 300; // 0x12c + field public static final int DENSITY_340 = 340; // 0x154 field public static final int DENSITY_360 = 360; // 0x168 field public static final int DENSITY_400 = 400; // 0x190 field public static final int DENSITY_420 = 420; // 0x1a4 @@ -41451,6 +41615,10 @@ package android.view { field public static final int KEYCODE_SWITCH_CHARSET = 95; // 0x5f field public static final int KEYCODE_SYM = 63; // 0x3f field public static final int KEYCODE_SYSRQ = 120; // 0x78 + field public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281; // 0x119 + field public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; // 0x11a + field public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; // 0x11b + field public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; // 0x118 field public static final int KEYCODE_T = 48; // 0x30 field public static final int KEYCODE_TAB = 61; // 0x3d field public static final int KEYCODE_TV = 170; // 0xaa @@ -42333,6 +42501,7 @@ package android.view { method public float getPivotY(); method public android.view.PointerIcon getPointerIcon(); method public android.content.res.Resources getResources(); + method public final boolean getRevealOnFocusHint(); method public final int getRight(); method protected float getRightFadingEdgeStrength(); method protected int getRightPaddingOffset(); @@ -42620,6 +42789,7 @@ package android.view { method public void setPivotY(float); method public void setPointerIcon(android.view.PointerIcon); method public void setPressed(boolean); + method public final void setRevealOnFocusHint(boolean); method public final void setRight(int); method public void setRotation(float); method public void setRotationX(float); @@ -43769,6 +43939,7 @@ package android.view { field public static final int TYPE_APPLICATION_SUB_PANEL = 1002; // 0x3ea field public static final int TYPE_BASE_APPLICATION = 1; // 0x1 field public static final int TYPE_CHANGED = 2; // 0x2 + field public static final int TYPE_DRAWN_APPLICATION = 4; // 0x4 field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9 @@ -44541,6 +44712,7 @@ package android.view.inputmethod { method public boolean clearMetaKeyStates(int); method public void closeConnection(); method public boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public boolean commitText(java.lang.CharSequence, int); method public boolean deleteSurroundingText(int, int); @@ -44650,6 +44822,7 @@ package android.view.inputmethod { field public static final int IME_NULL = 0; // 0x0 field public int actionId; field public java.lang.CharSequence actionLabel; + field public java.lang.String[] contentMimeTypes; field public android.os.Bundle extras; field public int fieldId; field public java.lang.String fieldName; @@ -44709,6 +44882,7 @@ package android.view.inputmethod { method public abstract boolean clearMetaKeyStates(int); method public abstract void closeConnection(); method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public abstract boolean commitText(java.lang.CharSequence, int); method public abstract boolean deleteSurroundingText(int, int); @@ -44734,6 +44908,7 @@ package android.view.inputmethod { field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2 field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1 field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1 + field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1 } public class InputConnectionWrapper implements android.view.inputmethod.InputConnection { @@ -44742,6 +44917,7 @@ package android.view.inputmethod { method public boolean clearMetaKeyStates(int); method public void closeConnection(); method public boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public boolean commitText(java.lang.CharSequence, int); method public boolean deleteSurroundingText(int, int); @@ -44766,6 +44942,19 @@ package android.view.inputmethod { method public void setTarget(android.view.inputmethod.InputConnection); } + public final class InputContentInfo implements android.os.Parcelable { + ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription); + ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri); + method public int describeContents(); + method public android.net.Uri getContentUri(); + method public android.content.ClipDescription getDescription(); + method public android.net.Uri getLinkUri(); + method public void releasePermission(); + method public void requestPermission(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public abstract interface InputMethod { method public abstract void attachToken(android.os.IBinder); method public abstract void bindInput(android.view.inputmethod.InputBinding); diff --git a/api/system-current.txt b/api/system-current.txt index cfc05dd7d850d1f043a4f43ddedb9ddb023dd4c4..74b1af306657f09d87e715ad7a4292c6c93bdc5d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -504,6 +504,7 @@ package android { field public static final int colorPressedHighlight = 16843661; // 0x101038d field public static final int colorPrimary = 16843827; // 0x1010433 field public static final int colorPrimaryDark = 16843828; // 0x1010434 + field public static final int colorSecondary = 16844080; // 0x1010530 field public static final int columnCount = 16843639; // 0x1010377 field public static final int columnDelay = 16843215; // 0x10101cf field public static final int columnOrderPreserved = 16843640; // 0x1010378 @@ -527,7 +528,9 @@ package android { field public static final int contentInsetStart = 16843859; // 0x1010453 field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522 field public static final int contextClickable = 16844007; // 0x10104e7 + field public static final int contextDescription = 16844078; // 0x101052e field public static final int contextPopupMenuStyle = 16844033; // 0x1010501 + field public static final int contextUri = 16844077; // 0x101052d field public static final int controlX1 = 16843772; // 0x10103fc field public static final int controlX2 = 16843774; // 0x10103fe field public static final int controlY1 = 16843773; // 0x10103fd @@ -1146,6 +1149,7 @@ package android { field public static final int rotation = 16843558; // 0x1010326 field public static final int rotationX = 16843559; // 0x1010327 field public static final int rotationY = 16843560; // 0x1010328 + field public static final int roundIcon = 16844076; // 0x101052c field public static final int rowCount = 16843637; // 0x1010375 field public static final int rowDelay = 16843216; // 0x10101d0 field public static final int rowEdgeFlags = 16843329; // 0x1010241 @@ -1217,11 +1221,16 @@ package android { field public static final int shareInterpolator = 16843195; // 0x10101bb field public static final int sharedUserId = 16842763; // 0x101000b field public static final int sharedUserLabel = 16843361; // 0x1010261 + field public static final int shortcutDisabledMessage = 16844075; // 0x101052b + field public static final int shortcutId = 16844072; // 0x1010528 + field public static final int shortcutLongLabel = 16844074; // 0x101052a + field public static final int shortcutShortLabel = 16844073; // 0x1010529 field public static final int shouldDisableView = 16843246; // 0x10101ee field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 field public static final int showForAllUsers = 16844015; // 0x10104ef + field public static final int showMetadataInPreview = 16844079; // 0x101052f field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb field public static final int showText = 16843949; // 0x10104ad @@ -3832,6 +3841,7 @@ package android.app { method public void moveTaskToFront(int, int); method public void moveTaskToFront(int, int, android.os.Bundle); method public deprecated void restartPackage(java.lang.String); + method public static void setVrThread(int); method public void setWatchHeapLimit(long); field public static final java.lang.String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT"; field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1 @@ -4515,6 +4525,15 @@ package android.app { field public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3; // 0x3 } + public abstract class EphemeralResolverService extends android.app.Service { + ctor public EphemeralResolverService(); + method public final void attachBaseContext(android.content.Context); + method public final android.os.IBinder onBind(android.content.Intent); + method public abstract java.util.List onEphemeralResolveInfoList(int[], int); + field public static final java.lang.String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO"; + field public static final java.lang.String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE"; + } + public class ExpandableListActivity extends android.app.Activity implements android.widget.ExpandableListView.OnChildClickListener android.widget.ExpandableListView.OnGroupCollapseListener android.widget.ExpandableListView.OnGroupExpandListener android.view.View.OnCreateContextMenuListener { ctor public ExpandableListActivity(); method public android.widget.ExpandableListAdapter getExpandableListAdapter(); @@ -5185,12 +5204,14 @@ package android.app { method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder); method public java.lang.CharSequence getCancelLabel(); method public java.lang.CharSequence getConfirmLabel(); + method public boolean getHintDisplayActionInline(); method public boolean getHintLaunchesActivity(); method public java.lang.CharSequence getInProgressLabel(); method public boolean isAvailableOffline(); method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean); method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence); method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence); + method public android.app.Notification.Action.WearableExtender setHintDisplayActionInline(boolean); method public android.app.Notification.Action.WearableExtender setHintLaunchesActivity(boolean); method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence); } @@ -5904,7 +5925,10 @@ package android.app { method public android.content.pm.ServiceInfo getServiceInfo(); method public java.lang.String getServiceName(); method public java.lang.String getSettingsActivity(); + method public boolean getShowMetadataInPreview(); method public java.lang.CharSequence loadAuthor(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; + method public java.lang.CharSequence loadContextDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; + method public android.net.Uri loadContextUri(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager); method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager); @@ -6767,11 +6791,13 @@ package android.app.usage { method public android.content.res.Configuration getConfiguration(); method public int getEventType(); method public java.lang.String getPackageName(); + method public java.lang.String getShortcutId(); method public long getTimeStamp(); field public static final int CONFIGURATION_CHANGE = 5; // 0x5 field public static final int MOVE_TO_BACKGROUND = 2; // 0x2 field public static final int MOVE_TO_FOREGROUND = 1; // 0x1 field public static final int NONE = 0; // 0x0 + field public static final int SHORTCUT_INVOCATION = 8; // 0x8 field public static final int USER_INTERACTION = 7; // 0x7 } @@ -8515,6 +8541,7 @@ package android.content { field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions"; field public static final java.lang.String SEARCH_SERVICE = "search"; field public static final java.lang.String SENSOR_SERVICE = "sensor"; + field public static final java.lang.String SHORTCUT_SERVICE = "shortcut"; field public static final java.lang.String STORAGE_SERVICE = "storage"; field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth"; field public static final java.lang.String TELECOM_SERVICE = "telecom"; @@ -9855,13 +9882,20 @@ package android.content.pm { public class LauncherApps { method public java.util.List getActivityList(java.lang.String, android.os.UserHandle); + method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int); + method public android.graphics.drawable.Drawable getShortcutIconDrawable(android.content.pm.ShortcutInfo, int); + method public java.util.List getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle); + method public boolean hasShortcutHostPermission(); method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle); method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle); + method public void pinShortcuts(java.lang.String, java.util.List, android.os.UserHandle); method public void registerCallback(android.content.pm.LauncherApps.Callback); method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler); method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle); method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); + method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle); + method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle); method public void unregisterCallback(android.content.pm.LauncherApps.Callback); } @@ -9874,6 +9908,20 @@ package android.content.pm { method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle); method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean); method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle); + method public void onShortcutsChanged(java.lang.String, java.util.List, android.os.UserHandle); + } + + public static class LauncherApps.ShortcutQuery { + ctor public LauncherApps.ShortcutQuery(); + method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName); + method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long); + method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String); + method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int); + method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List); + field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4 + field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1 + field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8 + field public static final int FLAG_MATCH_PINNED = 2; // 0x2 } public class PackageInfo implements android.os.Parcelable { @@ -10444,6 +10492,66 @@ package android.content.pm { field public java.lang.String permission; } + public final class ShortcutInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.content.ComponentName getActivity(); + method public java.util.Set getCategories(); + method public java.lang.CharSequence getDisabledMessage(); + method public android.os.PersistableBundle getExtras(); + method public java.lang.String getId(); + method public android.content.Intent getIntent(); + method public android.content.Intent[] getIntents(); + method public long getLastChangedTimestamp(); + method public java.lang.CharSequence getLongLabel(); + method public java.lang.String getPackage(); + method public int getRank(); + method public java.lang.CharSequence getShortLabel(); + method public android.os.UserHandle getUserHandle(); + method public boolean hasKeyFieldsOnly(); + method public boolean isDeclaredInManifest(); + method public boolean isDynamic(); + method public boolean isEnabled(); + method public boolean isImmutable(); + method public boolean isPinned(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation"; + } + + public static class ShortcutInfo.Builder { + ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String); + method public android.content.pm.ShortcutInfo build(); + method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName); + method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set); + method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence); + method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle); + method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); + method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent); + method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]); + method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence); + method public android.content.pm.ShortcutInfo.Builder setRank(int); + method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence); + } + + public class ShortcutManager { + method public boolean addDynamicShortcuts(java.util.List); + method public void disableShortcuts(java.util.List); + method public void disableShortcuts(java.util.List, java.lang.CharSequence); + method public void enableShortcuts(java.util.List); + method public java.util.List getDynamicShortcuts(); + method public int getIconMaxHeight(); + method public int getIconMaxWidth(); + method public java.util.List getManifestShortcuts(); + method public int getMaxShortcutCountPerActivity(); + method public java.util.List getPinnedShortcuts(); + method public boolean isRateLimitingActive(); + method public void removeAllDynamicShortcuts(); + method public void removeDynamicShortcuts(java.util.List); + method public void reportShortcutUsed(java.lang.String); + method public boolean setDynamicShortcuts(java.util.List); + method public boolean updateShortcuts(java.util.List); + } + public class Signature implements android.os.Parcelable { ctor public Signature(byte[]); ctor public Signature(java.lang.String); @@ -10664,7 +10772,7 @@ package android.content.res { } public class Resources { - ctor public Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); + ctor public deprecated Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); method public final void finishPreloading(); method public final void flushLayoutCache(); method public android.content.res.XmlResourceParser getAnimation(int) throws android.content.res.Resources.NotFoundException; @@ -10715,7 +10823,7 @@ package android.content.res { method public android.content.res.AssetFileDescriptor openRawResourceFd(int) throws android.content.res.Resources.NotFoundException; method public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException; method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; - method public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); + method public deprecated void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); } public static class Resources.NotFoundException extends java.lang.RuntimeException { @@ -21064,6 +21172,7 @@ package android.media { field public static final android.os.Parcelable.Creator CREATOR; field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_DEFAULT = 1; // 0x1 + field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe field public static final int ENCODING_DTS = 7; // 0x7 field public static final int ENCODING_DTS_HD = 8; // 0x8 field public static final int ENCODING_E_AC3 = 6; // 0x6 @@ -25947,6 +26056,33 @@ package android.net.http { package android.net.metrics { + public final class ApfProgramEvent implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int FLAG_HAS_IPV4_ADDRESS = 1; // 0x1 + field public static final int FLAG_MULTICAST_FILTER_ON = 0; // 0x0 + field public final int currentRas; + field public final int filteredRas; + field public final int flags; + field public final long lifetime; + field public final int programLength; + } + + public final class ApfStats implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public final int droppedRas; + field public final long durationMs; + field public final int matchingRas; + field public final int maxProgramSize; + field public final int parseErrors; + field public final int programUpdates; + field public final int receivedRas; + field public final int zeroLifetimeRas; + } + public final class DefaultNetworkEvent implements android.os.Parcelable { method public int describeContents(); method public static void logEvent(int, int[], int, boolean, boolean); @@ -25964,6 +26100,7 @@ package android.net.metrics { method public static void logStateEvent(java.lang.String, java.lang.String); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; + field public final int durationMs; field public final java.lang.String ifName; field public final java.lang.String msg; } @@ -26055,6 +26192,18 @@ package android.net.metrics { field public final int netId; } + public final class RaEvent implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public final long dnsslLifetime; + field public final long prefixPreferredLifetime; + field public final long prefixValidLifetime; + field public final long rdnssLifetime; + field public final long routeInfoLifetime; + field public final long routerLifetime; + } + public final class ValidationProbeEvent implements android.os.Parcelable { method public int describeContents(); method public static void logEvent(int, long, int, int); @@ -30740,6 +30889,7 @@ package android.os { field public static final int LOLLIPOP_MR1 = 22; // 0x16 field public static final int M = 23; // 0x17 field public static final int N = 24; // 0x18 + field public static final int N_MR1 = 25; // 0x19 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -31575,6 +31725,7 @@ package android.os { method public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException; method public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException; method public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException; + method public static void rebootWipeAb(android.content.Context, java.io.File, java.lang.String) throws java.io.IOException; method public static void rebootWipeCache(android.content.Context) throws java.io.IOException; method public static void rebootWipeUserData(android.content.Context) throws java.io.IOException; method public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException; @@ -31817,6 +31968,7 @@ package android.os { method public android.os.Bundle getUserRestrictions(); method public android.os.Bundle getUserRestrictions(android.os.UserHandle); method public boolean hasUserRestriction(java.lang.String); + method public boolean isDemoUser(); method public boolean isManagedProfile(); method public boolean isManagedProfile(int); method public boolean isQuietModeEnabled(android.os.UserHandle); @@ -32066,6 +32218,7 @@ package android.os.storage { method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); + field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; } public final class StorageVolume implements android.os.Parcelable { @@ -33247,6 +33400,7 @@ package android.provider { public static class CallLog.Calls implements android.provider.BaseColumns { ctor public CallLog.Calls(); method public static java.lang.String getLastOutgoingCall(android.content.Context); + field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7 field public static final int BLOCKED_TYPE = 6; // 0x6 field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number"; field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri"; @@ -33269,6 +33423,7 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final java.lang.String FEATURES = "features"; + field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_VIDEO = 1; // 0x1 field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 @@ -35107,6 +35262,7 @@ package android.provider { field public static final java.lang.String DATA_ROAMING = "data_roaming"; field public static final java.lang.String DEBUG_APP = "debug_app"; field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled"; + field public static final java.lang.String DEVICE_NAME = "device_name"; field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned"; field public static final java.lang.String HTTP_PROXY = "http_proxy"; field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; @@ -35118,7 +35274,7 @@ package android.provider { field public static final java.lang.String RADIO_CELL = "cell"; field public static final java.lang.String RADIO_NFC = "nfc"; field public static final java.lang.String RADIO_WIFI = "wifi"; - field public static final java.lang.String SHOW_PROCESSES = "show_processes"; + field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes"; field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in"; field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on"; field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale"; @@ -35697,6 +35853,7 @@ package android.provider { field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL"; field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL"; field public static final java.lang.String AUTHORITY = "com.android.voicemail"; + field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.provider.extra.PHONE_ACCOUNT_HANDLE"; field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE"; field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package"; } @@ -35705,6 +35862,9 @@ package android.provider { method public static android.net.Uri buildSourceUri(java.lang.String); field public static final java.lang.String CONFIGURATION_STATE = "configuration_state"; field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2 + field public static final int CONFIGURATION_STATE_CONFIGURING = 3; // 0x3 + field public static final int CONFIGURATION_STATE_DISABLED = 5; // 0x5 + field public static final int CONFIGURATION_STATE_FAILED = 4; // 0x4 field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1 field public static final int CONFIGURATION_STATE_OK = 0; // 0x0 field public static final android.net.Uri CONTENT_URI; @@ -35729,6 +35889,7 @@ package android.provider { field public static final int QUOTA_UNAVAILABLE = -1; // 0xffffffff field public static final java.lang.String SETTINGS_URI = "settings_uri"; field public static final java.lang.String SOURCE_PACKAGE = "source_package"; + field public static final java.lang.String SOURCE_TYPE = "source_type"; field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri"; } @@ -38816,10 +38977,15 @@ package android.telecom { method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); + method public final void putExtras(android.os.Bundle); method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, java.lang.String); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); method public deprecated void removeListener(android.telecom.Call.Listener); + method public void sendCallEvent(java.lang.String, android.os.Bundle); method public void splitFromConference(); method public void stopDtmfTone(); method public void swapConference(); @@ -38834,6 +39000,7 @@ package android.telecom { field public static final int STATE_HOLDING = 3; // 0x3 field public static final int STATE_NEW = 0; // 0x0 field public static final deprecated int STATE_PRE_DIAL_WAIT = 8; // 0x8 + field public static final int STATE_PULLING_CALL = 11; // 0xb field public static final int STATE_RINGING = 2; // 0x2 field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8 } @@ -38844,6 +39011,7 @@ package android.telecom { method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List); method public void onChildrenChanged(android.telecom.Call, java.util.List); method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details); method public void onParentChanged(android.telecom.Call, android.telecom.Call); method public void onPostDialWait(android.telecom.Call, java.lang.String); @@ -38874,6 +39042,7 @@ package android.telecom { method public static java.lang.String propertiesToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 @@ -38893,7 +39062,9 @@ package android.telecom { field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_ENTERPRISE_CALL = 32; // 0x20 field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 + field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_WIFI = 8; // 0x8 } @@ -38950,6 +39121,7 @@ package android.telecom { method public final java.util.List getConferenceableConnections(); method public final deprecated long getConnectTimeMillis(); method public final int getConnectionCapabilities(); + method public final int getConnectionProperties(); method public final long getConnectionTime(); method public final java.util.List getConnections(); method public final android.telecom.DisconnectCause getDisconnectCause(); @@ -38964,6 +39136,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onConnectionAdded(android.telecom.Connection); method public void onDisconnect(); + method public void onExtrasChanged(android.os.Bundle); method public void onHold(); method public void onMerge(android.telecom.Connection); method public void onMerge(); @@ -38972,11 +39145,15 @@ package android.telecom { method public void onStopDtmfTone(); method public void onSwap(); method public void onUnhold(); + method public final void putExtras(android.os.Bundle); method public final void removeConnection(android.telecom.Connection); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); method public final void setActive(); method public final void setConferenceableConnections(java.util.List); method public final deprecated void setConnectTimeMillis(long); method public final void setConnectionCapabilities(int); + method public final void setConnectionProperties(int); method public final void setConnectionTime(long); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); @@ -39007,6 +39184,7 @@ package android.telecom { method public final android.telecom.Conference getConference(); method public final java.util.List getConferenceables(); method public final int getConnectionCapabilities(); + method public final int getConnectionProperties(); method public final android.telecom.DisconnectCause getDisconnectCause(); method public final android.os.Bundle getExtras(); method public final int getState(); @@ -39018,16 +39196,24 @@ package android.telecom { method public void onAnswer(); method public deprecated void onAudioStateChanged(android.telecom.AudioState); method public void onCallAudioStateChanged(android.telecom.CallAudioState); + method public void onCallEvent(java.lang.String, android.os.Bundle); method public void onDisconnect(); + method public void onExtrasChanged(android.os.Bundle); method public void onHold(); method public void onPlayDtmfTone(char); method public void onPostDialContinue(boolean); + method public void onPullExternalCall(); method public void onReject(); method public void onReject(java.lang.String); method public void onSeparate(); method public void onStateChanged(int); method public void onStopDtmfTone(); method public void onUnhold(); + method public static java.lang.String propertiesToString(int); + method public final void putExtras(android.os.Bundle); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); + method public void sendConnectionEvent(java.lang.String, android.os.Bundle); method public final void setActive(); method public final void setAddress(android.net.Uri, int); method public final void setAudioModeIsVoip(boolean); @@ -39035,6 +39221,7 @@ package android.telecom { method public final void setConferenceableConnections(java.util.List); method public final void setConferenceables(java.util.List); method public final void setConnectionCapabilities(int); + method public final void setConnectionProperties(int); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); method public final void setExtras(android.os.Bundle); @@ -39043,6 +39230,7 @@ package android.telecom { method public final void setNextPostDialChar(char); method public final void setOnHold(); method public final void setPostDialWait(java.lang.String); + method public final void setPulling(); method public final void setRingbackRequested(boolean); method public final void setRinging(); method public final void setStatusHints(android.telecom.StatusHints); @@ -39051,6 +39239,7 @@ package android.telecom { method public static java.lang.String stateToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000 field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 @@ -39068,15 +39257,21 @@ package android.telecom { field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800 field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2 field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8 + field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED"; + field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; + field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL"; field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; + field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10 field public static final int STATE_ACTIVE = 4; // 0x4 field public static final int STATE_DIALING = 3; // 0x3 field public static final int STATE_DISCONNECTED = 6; // 0x6 field public static final int STATE_HOLDING = 5; // 0x5 field public static final int STATE_INITIALIZING = 0; // 0x0 field public static final int STATE_NEW = 1; // 0x1 + field public static final int STATE_PULLING_CALL = 7; // 0x7 field public static final int STATE_RINGING = 2; // 0x2 } @@ -39154,7 +39349,9 @@ package android.telecom { method public java.lang.String getReason(); method public int getTone(); method public void writeToParcel(android.os.Parcel, int); + field public static final int ANSWERED_ELSEWHERE = 11; // 0xb field public static final int BUSY = 7; // 0x7 + field public static final int CALL_PULLED = 12; // 0xc field public static final int CANCELED = 4; // 0x4 field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa field public static final android.os.Parcelable.Creator CREATOR; @@ -39191,6 +39388,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onCallRemoved(android.telecom.Call); method public void onCanAddCallChanged(boolean); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public deprecated void onPhoneCreated(android.telecom.Phone); method public deprecated void onPhoneDestroyed(android.telecom.Phone); method public void onSilenceRinger(); @@ -39228,14 +39426,16 @@ package android.telecom { } public class ParcelableCallAnalytics implements android.os.Parcelable { - ctor public ParcelableCallAnalytics(long, long, int, boolean, boolean, int, int, boolean, java.lang.String, boolean); + ctor public ParcelableCallAnalytics(long, long, int, boolean, boolean, int, int, boolean, java.lang.String, boolean, java.util.List, java.util.List); ctor public ParcelableCallAnalytics(android.os.Parcel); + method public java.util.List analyticsEvents(); method public int describeContents(); method public long getCallDurationMillis(); method public int getCallTechnologies(); method public int getCallTerminationCode(); method public int getCallType(); method public java.lang.String getConnectionService(); + method public java.util.List getEventTimings(); method public long getStartTimeMillis(); method public boolean isAdditionalCall(); method public boolean isCreatedFromExistingConnection(); @@ -39256,6 +39456,73 @@ package android.telecom { field public static final int THIRD_PARTY_PHONE = 16; // 0x10 } + public static final class ParcelableCallAnalytics.AnalyticsEvent implements android.os.Parcelable { + ctor public ParcelableCallAnalytics.AnalyticsEvent(int, long); + method public int describeContents(); + method public int getEventName(); + method public long getTimeSinceLastEvent(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int AUDIO_ROUTE_BT = 204; // 0xcc + field public static final int AUDIO_ROUTE_EARPIECE = 205; // 0xcd + field public static final int AUDIO_ROUTE_HEADSET = 206; // 0xce + field public static final int AUDIO_ROUTE_SPEAKER = 207; // 0xcf + field public static final int BIND_CS = 5; // 0x5 + field public static final int BLOCK_CHECK_FINISHED = 105; // 0x69 + field public static final int BLOCK_CHECK_INITIATED = 104; // 0x68 + field public static final int CONFERENCE_WITH = 300; // 0x12c + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int CS_BOUND = 6; // 0x6 + field public static final int DIRECT_TO_VM_FINISHED = 103; // 0x67 + field public static final int DIRECT_TO_VM_INITIATED = 102; // 0x66 + field public static final int FILTERING_COMPLETED = 107; // 0x6b + field public static final int FILTERING_INITIATED = 106; // 0x6a + field public static final int FILTERING_TIMED_OUT = 108; // 0x6c + field public static final int MUTE = 202; // 0xca + field public static final int REMOTELY_HELD = 402; // 0x192 + field public static final int REMOTELY_UNHELD = 403; // 0x193 + field public static final int REQUEST_ACCEPT = 7; // 0x7 + field public static final int REQUEST_HOLD = 400; // 0x190 + field public static final int REQUEST_PULL = 500; // 0x1f4 + field public static final int REQUEST_REJECT = 8; // 0x8 + field public static final int REQUEST_UNHOLD = 401; // 0x191 + field public static final int SCREENING_COMPLETED = 101; // 0x65 + field public static final int SCREENING_SENT = 100; // 0x64 + field public static final int SET_ACTIVE = 1; // 0x1 + field public static final int SET_DIALING = 4; // 0x4 + field public static final int SET_DISCONNECTED = 2; // 0x2 + field public static final int SET_HOLD = 404; // 0x194 + field public static final int SET_PARENT = 302; // 0x12e + field public static final int SET_SELECT_PHONE_ACCOUNT = 0; // 0x0 + field public static final int SILENCE = 201; // 0xc9 + field public static final int SKIP_RINGING = 200; // 0xc8 + field public static final int SPLIT_CONFERENCE = 301; // 0x12d + field public static final int START_CONNECTION = 3; // 0x3 + field public static final int SWAP = 405; // 0x195 + field public static final int UNMUTE = 203; // 0xcb + } + + public static final class ParcelableCallAnalytics.EventTiming implements android.os.Parcelable { + ctor public ParcelableCallAnalytics.EventTiming(int, long); + method public int describeContents(); + method public int getName(); + method public long getTime(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int ACCEPT_TIMING = 0; // 0x0 + field public static final int BIND_CS_TIMING = 6; // 0x6 + field public static final int BLOCK_CHECK_FINISHED_TIMING = 9; // 0x9 + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int DIRECT_TO_VM_FINISHED_TIMING = 8; // 0x8 + field public static final int DISCONNECT_TIMING = 2; // 0x2 + field public static final int FILTERING_COMPLETED_TIMING = 10; // 0xa + field public static final int FILTERING_TIMED_OUT_TIMING = 11; // 0xb + field public static final int HOLD_TIMING = 3; // 0x3 + field public static final int INVALID = 999999; // 0xf423f + field public static final int OUTGOING_TIME_TO_DIALING_TIMING = 5; // 0x5 + field public static final int REJECT_TIMING = 1; // 0x1 + field public static final int SCREENING_COMPLETED_TIMING = 7; // 0x7 + field public static final int UNHOLD_TIMING = 4; // 0x4 + } + public final deprecated class Phone { method public final void addListener(android.telecom.Phone.Listener); method public final boolean canAddCall(); @@ -39369,6 +39636,7 @@ package android.telecom { method public void onConferenceableConnectionsChanged(android.telecom.RemoteConference, java.util.List); method public void onConnectionAdded(android.telecom.RemoteConference, android.telecom.RemoteConnection); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConference, int); + method public void onConnectionPropertiesChanged(android.telecom.RemoteConference, int); method public void onConnectionRemoved(android.telecom.RemoteConference, android.telecom.RemoteConnection); method public void onDestroyed(android.telecom.RemoteConference); method public void onDisconnected(android.telecom.RemoteConference, android.telecom.DisconnectCause); @@ -39387,6 +39655,7 @@ package android.telecom { method public android.telecom.RemoteConference getConference(); method public java.util.List getConferenceableConnections(); method public int getConnectionCapabilities(); + method public int getConnectionProperties(); method public android.telecom.DisconnectCause getDisconnectCause(); method public final android.os.Bundle getExtras(); method public int getState(); @@ -39398,6 +39667,7 @@ package android.telecom { method public boolean isVoipAudioMode(); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.RemoteConnection.Callback); method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler); method public void reject(); @@ -39415,6 +39685,8 @@ package android.telecom { method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference); method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int); + method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle); + method public void onConnectionPropertiesChanged(android.telecom.RemoteConnection, int); method public void onDestroyed(android.telecom.RemoteConnection); method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause); method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle); @@ -39468,6 +39740,41 @@ package android.telecom { field public static final android.os.Parcelable.Creator CREATOR; } + public final class TelecomAnalytics implements android.os.Parcelable { + ctor public TelecomAnalytics(java.util.List, java.util.List); + method public int describeContents(); + method public java.util.List getCallAnalytics(); + method public java.util.List getSessionTimings(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class TelecomAnalytics.SessionTiming implements android.os.Parcelable { + ctor public TelecomAnalytics.SessionTiming(int, long); + method public int describeContents(); + method public java.lang.Integer getKey(); + method public long getTime(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int CSW_ADD_CONFERENCE_CALL = 108; // 0x6c + field public static final int CSW_HANDLE_CREATE_CONNECTION_COMPLETE = 100; // 0x64 + field public static final int CSW_REMOVE_CALL = 106; // 0x6a + field public static final int CSW_SET_ACTIVE = 101; // 0x65 + field public static final int CSW_SET_DIALING = 103; // 0x67 + field public static final int CSW_SET_DISCONNECTED = 104; // 0x68 + field public static final int CSW_SET_IS_CONFERENCED = 107; // 0x6b + field public static final int CSW_SET_ON_HOLD = 105; // 0x69 + field public static final int CSW_SET_RINGING = 102; // 0x66 + field public static final int ICA_ANSWER_CALL = 1; // 0x1 + field public static final int ICA_CONFERENCE = 8; // 0x8 + field public static final int ICA_DISCONNECT_CALL = 3; // 0x3 + field public static final int ICA_HOLD_CALL = 4; // 0x4 + field public static final int ICA_MUTE = 6; // 0x6 + field public static final int ICA_REJECT_CALL = 2; // 0x2 + field public static final int ICA_SET_AUDIO_ROUTE = 7; // 0x7 + field public static final int ICA_UNHOLD_CALL = 5; // 0x5 + } + public class TelecomManager { method public void acceptRingingCall(); method public void acceptRingingCall(int); @@ -39477,7 +39784,7 @@ package android.telecom { method public deprecated void clearAccounts(); method public void clearPhoneAccounts(); method public android.content.Intent createManageBlockedNumbersIntent(); - method public java.util.List dumpAnalytics(); + method public android.telecom.TelecomAnalytics dumpAnalytics(); method public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean); method public boolean endCall(); method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle); @@ -39538,6 +39845,7 @@ package android.telecom { field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; + field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 @@ -39594,9 +39902,11 @@ package android.telephony { field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool"; field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool"; + field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call"; field public static final java.lang.String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool"; field public static final java.lang.String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool"; field public static final java.lang.String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool"; + field public static final java.lang.String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool"; field public static final java.lang.String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool"; field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool"; field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool"; @@ -39628,6 +39938,7 @@ package android.telephony { field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool"; field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string"; field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool"; + field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool"; field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool"; field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int"; field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool"; @@ -39686,6 +39997,7 @@ package android.telephony { field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; field public static final java.lang.String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool"; field public static final java.lang.String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool"; + field public static final java.lang.String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool"; field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool"; field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool"; field public static final java.lang.String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool"; @@ -40186,6 +40498,26 @@ package android.telephony { method public void onSubscriptionsChanged(); } + public final class TelephonyHistogram implements android.os.Parcelable { + ctor public TelephonyHistogram(int, int, int); + ctor public TelephonyHistogram(android.telephony.TelephonyHistogram); + ctor public TelephonyHistogram(android.os.Parcel); + method public void addTimeTaken(int); + method public int describeContents(); + method public int getAverageTime(); + method public int getBucketCount(); + method public int[] getBucketCounters(); + method public int[] getBucketEndPoints(); + method public int getCategory(); + method public int getId(); + method public int getMaxTime(); + method public int getMinTime(); + method public int getSampleCount(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int TELEPHONY_CATEGORY_RIL = 1; // 0x1 + } + public class TelephonyManager { method public void answerRingingCall(); method public void call(java.lang.String, java.lang.String); @@ -40237,6 +40569,7 @@ package android.telephony { method public java.lang.String getSimSerialNumber(); method public int getSimState(); method public java.lang.String getSubscriberId(); + method public java.util.List getTelephonyHistograms(); method public java.lang.String getVoiceMailAlphaTag(); method public java.lang.String getVoiceMailNumber(); method public int getVoiceNetworkType(); @@ -40260,6 +40593,7 @@ package android.telephony { method public boolean isSmsCapable(); method public boolean isTtyModeSupported(); method public boolean isVideoCallingEnabled(); + method public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle); method public boolean isVoiceCapable(); method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle); method public boolean isWorldPhone(); @@ -40273,6 +40607,7 @@ package android.telephony { method public boolean setPreferredNetworkTypeToGlobal(); method public boolean setRadio(boolean); method public boolean setRadioPower(boolean); + method public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean); method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); method public void silenceRinger(); method public boolean supplyPin(java.lang.String); @@ -40325,12 +40660,15 @@ package android.telephony { field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6 field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc field public static final int NETWORK_TYPE_GPRS = 1; // 0x1 + field public static final int NETWORK_TYPE_GSM = 16; // 0x10 field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8 field public static final int NETWORK_TYPE_HSPA = 10; // 0xa field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9 field public static final int NETWORK_TYPE_IDEN = 11; // 0xb + field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12 field public static final int NETWORK_TYPE_LTE = 13; // 0xd + field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11 field public static final int NETWORK_TYPE_UMTS = 3; // 0x3 field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0 field public static final int PHONE_TYPE_CDMA = 2; // 0x2 @@ -43148,7 +43486,10 @@ package android.util { method public boolean equals(android.util.DisplayMetrics); method public void setTo(android.util.DisplayMetrics); method public void setToDefaults(); + field public static final int DENSITY_260 = 260; // 0x104 field public static final int DENSITY_280 = 280; // 0x118 + field public static final int DENSITY_300 = 300; // 0x12c + field public static final int DENSITY_340 = 340; // 0x154 field public static final int DENSITY_360 = 360; // 0x168 field public static final int DENSITY_400 = 400; // 0x190 field public static final int DENSITY_420 = 420; // 0x1a4 @@ -44478,6 +44819,10 @@ package android.view { field public static final int KEYCODE_SWITCH_CHARSET = 95; // 0x5f field public static final int KEYCODE_SYM = 63; // 0x3f field public static final int KEYCODE_SYSRQ = 120; // 0x78 + field public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281; // 0x119 + field public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; // 0x11a + field public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; // 0x11b + field public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; // 0x118 field public static final int KEYCODE_T = 48; // 0x30 field public static final int KEYCODE_TAB = 61; // 0x3d field public static final int KEYCODE_TV = 170; // 0xaa @@ -45360,6 +45705,7 @@ package android.view { method public float getPivotY(); method public android.view.PointerIcon getPointerIcon(); method public android.content.res.Resources getResources(); + method public final boolean getRevealOnFocusHint(); method public final int getRight(); method protected float getRightFadingEdgeStrength(); method protected int getRightPaddingOffset(); @@ -45647,6 +45993,7 @@ package android.view { method public void setPivotY(float); method public void setPointerIcon(android.view.PointerIcon); method public void setPressed(boolean); + method public final void setRevealOnFocusHint(boolean); method public final void setRight(int); method public void setRotation(float); method public void setRotationX(float); @@ -46799,6 +47146,7 @@ package android.view { field public static final int TYPE_APPLICATION_SUB_PANEL = 1002; // 0x3ea field public static final int TYPE_BASE_APPLICATION = 1; // 0x1 field public static final int TYPE_CHANGED = 2; // 0x2 + field public static final int TYPE_DRAWN_APPLICATION = 4; // 0x4 field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9 @@ -47571,6 +47919,7 @@ package android.view.inputmethod { method public boolean clearMetaKeyStates(int); method public void closeConnection(); method public boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public boolean commitText(java.lang.CharSequence, int); method public boolean deleteSurroundingText(int, int); @@ -47680,6 +48029,7 @@ package android.view.inputmethod { field public static final int IME_NULL = 0; // 0x0 field public int actionId; field public java.lang.CharSequence actionLabel; + field public java.lang.String[] contentMimeTypes; field public android.os.Bundle extras; field public int fieldId; field public java.lang.String fieldName; @@ -47739,6 +48089,7 @@ package android.view.inputmethod { method public abstract boolean clearMetaKeyStates(int); method public abstract void closeConnection(); method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public abstract boolean commitText(java.lang.CharSequence, int); method public abstract boolean deleteSurroundingText(int, int); @@ -47764,6 +48115,7 @@ package android.view.inputmethod { field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2 field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1 field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1 + field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1 } public class InputConnectionWrapper implements android.view.inputmethod.InputConnection { @@ -47772,6 +48124,7 @@ package android.view.inputmethod { method public boolean clearMetaKeyStates(int); method public void closeConnection(); method public boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public boolean commitText(java.lang.CharSequence, int); method public boolean deleteSurroundingText(int, int); @@ -47796,6 +48149,19 @@ package android.view.inputmethod { method public void setTarget(android.view.inputmethod.InputConnection); } + public final class InputContentInfo implements android.os.Parcelable { + ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription); + ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri); + method public int describeContents(); + method public android.net.Uri getContentUri(); + method public android.content.ClipDescription getDescription(); + method public android.net.Uri getLinkUri(); + method public void releasePermission(); + method public void requestPermission(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public abstract interface InputMethod { method public abstract void attachToken(android.os.IBinder); method public abstract void bindInput(android.view.inputmethod.InputBinding); diff --git a/api/test-current.txt b/api/test-current.txt index 2d7b29fe2d591c0f7442ff6948238dc771446a11..8e3d4ef6cbadcc52c0d2e62098eb1de3fad438f5 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -397,6 +397,7 @@ package android { field public static final int colorPressedHighlight = 16843661; // 0x101038d field public static final int colorPrimary = 16843827; // 0x1010433 field public static final int colorPrimaryDark = 16843828; // 0x1010434 + field public static final int colorSecondary = 16844080; // 0x1010530 field public static final int columnCount = 16843639; // 0x1010377 field public static final int columnDelay = 16843215; // 0x10101cf field public static final int columnOrderPreserved = 16843640; // 0x1010378 @@ -420,7 +421,9 @@ package android { field public static final int contentInsetStart = 16843859; // 0x1010453 field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522 field public static final int contextClickable = 16844007; // 0x10104e7 + field public static final int contextDescription = 16844078; // 0x101052e field public static final int contextPopupMenuStyle = 16844033; // 0x1010501 + field public static final int contextUri = 16844077; // 0x101052d field public static final int controlX1 = 16843772; // 0x10103fc field public static final int controlX2 = 16843774; // 0x10103fe field public static final int controlY1 = 16843773; // 0x10103fd @@ -1039,6 +1042,7 @@ package android { field public static final int rotation = 16843558; // 0x1010326 field public static final int rotationX = 16843559; // 0x1010327 field public static final int rotationY = 16843560; // 0x1010328 + field public static final int roundIcon = 16844076; // 0x101052c field public static final int rowCount = 16843637; // 0x1010375 field public static final int rowDelay = 16843216; // 0x10101d0 field public static final int rowEdgeFlags = 16843329; // 0x1010241 @@ -1106,11 +1110,16 @@ package android { field public static final int shareInterpolator = 16843195; // 0x10101bb field public static final int sharedUserId = 16842763; // 0x101000b field public static final int sharedUserLabel = 16843361; // 0x1010261 + field public static final int shortcutDisabledMessage = 16844075; // 0x101052b + field public static final int shortcutId = 16844072; // 0x1010528 + field public static final int shortcutLongLabel = 16844074; // 0x101052a + field public static final int shortcutShortLabel = 16844073; // 0x1010529 field public static final int shouldDisableView = 16843246; // 0x10101ee field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 field public static final int showForAllUsers = 16844015; // 0x10104ef + field public static final int showMetadataInPreview = 16844079; // 0x101052f field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb field public static final int showText = 16843949; // 0x10104ad @@ -3246,6 +3255,7 @@ package android.animation { method public java.lang.Object getAnimatedValue(java.lang.String); method public long getCurrentPlayTime(); method public long getDuration(); + method public static float getDurationScale(); method public static long getFrameDelay(); method public int getRepeatCount(); method public int getRepeatMode(); @@ -3263,6 +3273,7 @@ package android.animation { method public void setCurrentFraction(float); method public void setCurrentPlayTime(long); method public android.animation.ValueAnimator setDuration(long); + method public static void setDurationScale(float); method public void setEvaluator(android.animation.TypeEvaluator); method public void setFloatValues(float...); method public static void setFrameDelay(long); @@ -3696,6 +3707,7 @@ package android.app { method public void moveTaskToFront(int, int); method public void moveTaskToFront(int, int, android.os.Bundle); method public deprecated void restartPackage(java.lang.String); + method public static void setVrThread(int); method public void setWatchHeapLimit(long); field public static final java.lang.String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT"; field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1 @@ -5038,12 +5050,14 @@ package android.app { method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder); method public java.lang.CharSequence getCancelLabel(); method public java.lang.CharSequence getConfirmLabel(); + method public boolean getHintDisplayActionInline(); method public boolean getHintLaunchesActivity(); method public java.lang.CharSequence getInProgressLabel(); method public boolean isAvailableOffline(); method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean); method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence); method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence); + method public android.app.Notification.Action.WearableExtender setHintDisplayActionInline(boolean); method public android.app.Notification.Action.WearableExtender setHintLaunchesActivity(boolean); method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence); } @@ -5617,6 +5631,7 @@ package android.app { public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener { ctor public TimePickerDialog(android.content.Context, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean); ctor public TimePickerDialog(android.content.Context, int, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean); + method public android.widget.TimePicker getTimePicker(); method public void onClick(android.content.DialogInterface, int); method public void onTimeChanged(android.widget.TimePicker, int, int); method public void updateTime(int, int); @@ -5762,7 +5777,10 @@ package android.app { method public android.content.pm.ServiceInfo getServiceInfo(); method public java.lang.String getServiceName(); method public java.lang.String getSettingsActivity(); + method public boolean getShowMetadataInPreview(); method public java.lang.CharSequence loadAuthor(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; + method public java.lang.CharSequence loadContextDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; + method public android.net.Uri loadContextUri(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; method public java.lang.CharSequence loadDescription(android.content.pm.PackageManager) throws android.content.res.Resources.NotFoundException; method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager); method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager); @@ -6490,11 +6508,13 @@ package android.app.usage { method public android.content.res.Configuration getConfiguration(); method public int getEventType(); method public java.lang.String getPackageName(); + method public java.lang.String getShortcutId(); method public long getTimeStamp(); field public static final int CONFIGURATION_CHANGE = 5; // 0x5 field public static final int MOVE_TO_BACKGROUND = 2; // 0x2 field public static final int MOVE_TO_FOREGROUND = 1; // 0x1 field public static final int NONE = 0; // 0x0 + field public static final int SHORTCUT_INVOCATION = 8; // 0x8 field public static final int USER_INTERACTION = 7; // 0x7 } @@ -8199,6 +8219,7 @@ package android.content { field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions"; field public static final java.lang.String SEARCH_SERVICE = "search"; field public static final java.lang.String SENSOR_SERVICE = "sensor"; + field public static final java.lang.String SHORTCUT_SERVICE = "shortcut"; field public static final java.lang.String STORAGE_SERVICE = "storage"; field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth"; field public static final java.lang.String TELECOM_SERVICE = "telecom"; @@ -9512,13 +9533,20 @@ package android.content.pm { public class LauncherApps { ctor public LauncherApps(android.content.Context); method public java.util.List getActivityList(java.lang.String, android.os.UserHandle); + method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int); + method public android.graphics.drawable.Drawable getShortcutIconDrawable(android.content.pm.ShortcutInfo, int); + method public java.util.List getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle); + method public boolean hasShortcutHostPermission(); method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle); method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle); + method public void pinShortcuts(java.lang.String, java.util.List, android.os.UserHandle); method public void registerCallback(android.content.pm.LauncherApps.Callback); method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler); method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle); method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); + method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle); + method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle); method public void unregisterCallback(android.content.pm.LauncherApps.Callback); } @@ -9531,6 +9559,20 @@ package android.content.pm { method public void onPackagesSuspended(java.lang.String[], android.os.UserHandle); method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean); method public void onPackagesUnsuspended(java.lang.String[], android.os.UserHandle); + method public void onShortcutsChanged(java.lang.String, java.util.List, android.os.UserHandle); + } + + public static class LauncherApps.ShortcutQuery { + ctor public LauncherApps.ShortcutQuery(); + method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName); + method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long); + method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String); + method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int); + method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List); + field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4 + field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1 + field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8 + field public static final int FLAG_MATCH_PINNED = 2; // 0x2 } public class PackageInfo implements android.os.Parcelable { @@ -10032,6 +10074,67 @@ package android.content.pm { field public java.lang.String permission; } + public final class ShortcutInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.content.ComponentName getActivity(); + method public java.util.Set getCategories(); + method public java.lang.CharSequence getDisabledMessage(); + method public android.os.PersistableBundle getExtras(); + method public java.lang.String getId(); + method public android.content.Intent getIntent(); + method public android.content.Intent[] getIntents(); + method public long getLastChangedTimestamp(); + method public java.lang.CharSequence getLongLabel(); + method public java.lang.String getPackage(); + method public int getRank(); + method public java.lang.CharSequence getShortLabel(); + method public android.os.UserHandle getUserHandle(); + method public boolean hasKeyFieldsOnly(); + method public boolean isDeclaredInManifest(); + method public boolean isDynamic(); + method public boolean isEnabled(); + method public boolean isImmutable(); + method public boolean isPinned(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation"; + } + + public static class ShortcutInfo.Builder { + ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String); + method public android.content.pm.ShortcutInfo build(); + method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName); + method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set); + method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence); + method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle); + method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); + method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent); + method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]); + method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence); + method public android.content.pm.ShortcutInfo.Builder setRank(int); + method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence); + } + + public class ShortcutManager { + ctor public ShortcutManager(android.content.Context); + method public boolean addDynamicShortcuts(java.util.List); + method public void disableShortcuts(java.util.List); + method public void disableShortcuts(java.util.List, java.lang.CharSequence); + method public void enableShortcuts(java.util.List); + method public java.util.List getDynamicShortcuts(); + method public int getIconMaxHeight(); + method public int getIconMaxWidth(); + method public java.util.List getManifestShortcuts(); + method public int getMaxShortcutCountPerActivity(); + method public java.util.List getPinnedShortcuts(); + method public boolean isRateLimitingActive(); + method public void removeAllDynamicShortcuts(); + method public void removeDynamicShortcuts(java.util.List); + method public void reportShortcutUsed(java.lang.String); + method public boolean setDynamicShortcuts(java.util.List); + method public boolean updateShortcuts(java.util.List); + } + public class Signature implements android.os.Parcelable { ctor public Signature(byte[]); ctor public Signature(java.lang.String); @@ -10238,7 +10341,7 @@ package android.content.res { } public class Resources { - ctor public Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); + ctor public deprecated Resources(android.content.res.AssetManager, android.util.DisplayMetrics, android.content.res.Configuration); method public final void finishPreloading(); method public final void flushLayoutCache(); method public android.content.res.XmlResourceParser getAnimation(int) throws android.content.res.Resources.NotFoundException; @@ -10289,7 +10392,7 @@ package android.content.res { method public android.content.res.AssetFileDescriptor openRawResourceFd(int) throws android.content.res.Resources.NotFoundException; method public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException; method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; - method public void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); + method public deprecated void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); } public static class Resources.NotFoundException extends java.lang.RuntimeException { @@ -19625,6 +19728,7 @@ package android.media { field public static final android.os.Parcelable.Creator CREATOR; field public static final int ENCODING_AC3 = 5; // 0x5 field public static final int ENCODING_DEFAULT = 1; // 0x1 + field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe field public static final int ENCODING_DTS = 7; // 0x7 field public static final int ENCODING_DTS_HD = 8; // 0x8 field public static final int ENCODING_E_AC3 = 6; // 0x6 @@ -28337,6 +28441,7 @@ package android.os { field public static final int LOLLIPOP_MR1 = 22; // 0x16 field public static final int M = 23; // 0x17 field public static final int N = 24; // 0x18 + field public static final int N_MR1 = 25; // 0x19 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -29126,6 +29231,7 @@ package android.os { method public static final long getStartElapsedRealtime(); method public static final long getStartUptimeMillis(); method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException; + method public static final int getThreadScheduler(int) throws java.lang.IllegalArgumentException; method public static final int getUidForName(java.lang.String); method public static final boolean is64Bit(); method public static boolean isApplicationUid(int); @@ -29331,6 +29437,7 @@ package android.os { method public android.os.Bundle getUserRestrictions(); method public android.os.Bundle getUserRestrictions(android.os.UserHandle); method public boolean hasUserRestriction(java.lang.String); + method public boolean isDemoUser(); method public boolean isQuietModeEnabled(android.os.UserHandle); method public boolean isSystemUser(); method public boolean isUserAGoat(); @@ -29571,6 +29678,7 @@ package android.os.storage { method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); + field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; } public final class StorageVolume implements android.os.Parcelable { @@ -30716,6 +30824,7 @@ package android.provider { public static class CallLog.Calls implements android.provider.BaseColumns { ctor public CallLog.Calls(); method public static java.lang.String getLastOutgoingCall(android.content.Context); + field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7 field public static final int BLOCKED_TYPE = 6; // 0x6 field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number"; field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri"; @@ -30738,6 +30847,7 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final java.lang.String FEATURES = "features"; + field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_VIDEO = 1; // 0x1 field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 @@ -32443,6 +32553,7 @@ package android.provider { field public static final java.lang.String DATA_ROAMING = "data_roaming"; field public static final java.lang.String DEBUG_APP = "debug_app"; field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled"; + field public static final java.lang.String DEVICE_NAME = "device_name"; field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned"; field public static final java.lang.String HTTP_PROXY = "http_proxy"; field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps"; @@ -32452,7 +32563,7 @@ package android.provider { field public static final java.lang.String RADIO_CELL = "cell"; field public static final java.lang.String RADIO_NFC = "nfc"; field public static final java.lang.String RADIO_WIFI = "wifi"; - field public static final java.lang.String SHOW_PROCESSES = "show_processes"; + field public static final deprecated java.lang.String SHOW_PROCESSES = "show_processes"; field public static final java.lang.String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in"; field public static final java.lang.String TRANSITION_ANIMATION_SCALE = "transition_animation_scale"; field public static final java.lang.String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled"; @@ -33031,6 +33142,7 @@ package android.provider { field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL"; field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL"; field public static final java.lang.String AUTHORITY = "com.android.voicemail"; + field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.provider.extra.PHONE_ACCOUNT_HANDLE"; field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE"; field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package"; } @@ -33039,6 +33151,9 @@ package android.provider { method public static android.net.Uri buildSourceUri(java.lang.String); field public static final java.lang.String CONFIGURATION_STATE = "configuration_state"; field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2 + field public static final int CONFIGURATION_STATE_CONFIGURING = 3; // 0x3 + field public static final int CONFIGURATION_STATE_DISABLED = 5; // 0x5 + field public static final int CONFIGURATION_STATE_FAILED = 4; // 0x4 field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1 field public static final int CONFIGURATION_STATE_OK = 0; // 0x0 field public static final android.net.Uri CONTENT_URI; @@ -33063,6 +33178,7 @@ package android.provider { field public static final int QUOTA_UNAVAILABLE = -1; // 0xffffffff field public static final java.lang.String SETTINGS_URI = "settings_uri"; field public static final java.lang.String SOURCE_PACKAGE = "source_package"; + field public static final java.lang.String SOURCE_TYPE = "source_type"; field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri"; } @@ -36023,9 +36139,14 @@ package android.telecom { method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); + method public final void putExtras(android.os.Bundle); method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, java.lang.String); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); + method public void sendCallEvent(java.lang.String, android.os.Bundle); method public void splitFromConference(); method public void stopDtmfTone(); method public void swapConference(); @@ -36039,6 +36160,7 @@ package android.telecom { field public static final int STATE_DISCONNECTING = 10; // 0xa field public static final int STATE_HOLDING = 3; // 0x3 field public static final int STATE_NEW = 0; // 0x0 + field public static final int STATE_PULLING_CALL = 11; // 0xb field public static final int STATE_RINGING = 2; // 0x2 field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8 } @@ -36049,6 +36171,7 @@ package android.telecom { method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List); method public void onChildrenChanged(android.telecom.Call, java.util.List); method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details); method public void onParentChanged(android.telecom.Call, android.telecom.Call); method public void onPostDialWait(android.telecom.Call, java.lang.String); @@ -36079,6 +36202,7 @@ package android.telecom { method public static java.lang.String propertiesToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 @@ -36098,7 +36222,9 @@ package android.telecom { field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_ENTERPRISE_CALL = 32; // 0x20 field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 + field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_WIFI = 8; // 0x8 } @@ -36149,6 +36275,7 @@ package android.telecom { method public final android.telecom.CallAudioState getCallAudioState(); method public final java.util.List getConferenceableConnections(); method public final int getConnectionCapabilities(); + method public final int getConnectionProperties(); method public final long getConnectionTime(); method public final java.util.List getConnections(); method public final android.telecom.DisconnectCause getDisconnectCause(); @@ -36161,6 +36288,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onConnectionAdded(android.telecom.Connection); method public void onDisconnect(); + method public void onExtrasChanged(android.os.Bundle); method public void onHold(); method public void onMerge(android.telecom.Connection); method public void onMerge(); @@ -36169,10 +36297,14 @@ package android.telecom { method public void onStopDtmfTone(); method public void onSwap(); method public void onUnhold(); + method public final void putExtras(android.os.Bundle); method public final void removeConnection(android.telecom.Connection); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); method public final void setActive(); method public final void setConferenceableConnections(java.util.List); method public final void setConnectionCapabilities(int); + method public final void setConnectionProperties(int); method public final void setConnectionTime(long); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); @@ -36202,6 +36334,7 @@ package android.telecom { method public final android.telecom.Conference getConference(); method public final java.util.List getConferenceables(); method public final int getConnectionCapabilities(); + method public final int getConnectionProperties(); method public final android.telecom.DisconnectCause getDisconnectCause(); method public final android.os.Bundle getExtras(); method public final int getState(); @@ -36212,16 +36345,24 @@ package android.telecom { method public void onAnswer(int); method public void onAnswer(); method public void onCallAudioStateChanged(android.telecom.CallAudioState); + method public void onCallEvent(java.lang.String, android.os.Bundle); method public void onDisconnect(); + method public void onExtrasChanged(android.os.Bundle); method public void onHold(); method public void onPlayDtmfTone(char); method public void onPostDialContinue(boolean); + method public void onPullExternalCall(); method public void onReject(); method public void onReject(java.lang.String); method public void onSeparate(); method public void onStateChanged(int); method public void onStopDtmfTone(); method public void onUnhold(); + method public static java.lang.String propertiesToString(int); + method public final void putExtras(android.os.Bundle); + method public final void removeExtras(java.util.List); + method public final void removeExtras(java.lang.String...); + method public void sendConnectionEvent(java.lang.String, android.os.Bundle); method public final void setActive(); method public final void setAddress(android.net.Uri, int); method public final void setAudioModeIsVoip(boolean); @@ -36229,6 +36370,7 @@ package android.telecom { method public final void setConferenceableConnections(java.util.List); method public final void setConferenceables(java.util.List); method public final void setConnectionCapabilities(int); + method public final void setConnectionProperties(int); method public final void setDialing(); method public final void setDisconnected(android.telecom.DisconnectCause); method public final void setExtras(android.os.Bundle); @@ -36237,6 +36379,7 @@ package android.telecom { method public final void setNextPostDialChar(char); method public final void setOnHold(); method public final void setPostDialWait(java.lang.String); + method public final void setPulling(); method public final void setRingbackRequested(boolean); method public final void setRinging(); method public final void setStatusHints(android.telecom.StatusHints); @@ -36245,6 +36388,7 @@ package android.telecom { method public static java.lang.String stateToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000 field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 @@ -36262,15 +36406,21 @@ package android.telecom { field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800 field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2 field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8 + field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED"; + field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; + field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL"; field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; + field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10 field public static final int STATE_ACTIVE = 4; // 0x4 field public static final int STATE_DIALING = 3; // 0x3 field public static final int STATE_DISCONNECTED = 6; // 0x6 field public static final int STATE_HOLDING = 5; // 0x5 field public static final int STATE_INITIALIZING = 0; // 0x0 field public static final int STATE_NEW = 1; // 0x1 + field public static final int STATE_PULLING_CALL = 7; // 0x7 field public static final int STATE_RINGING = 2; // 0x2 } @@ -36348,7 +36498,9 @@ package android.telecom { method public java.lang.String getReason(); method public int getTone(); method public void writeToParcel(android.os.Parcel, int); + field public static final int ANSWERED_ELSEWHERE = 11; // 0xb field public static final int BUSY = 7; // 0x7 + field public static final int CALL_PULLED = 12; // 0xc field public static final int CANCELED = 4; // 0x4 field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa field public static final android.os.Parcelable.Creator CREATOR; @@ -36384,6 +36536,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onCallRemoved(android.telecom.Call); method public void onCanAddCallChanged(boolean); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onSilenceRinger(); method public final void setAudioRoute(int); method public final void setMuted(boolean); @@ -36507,6 +36660,7 @@ package android.telecom { method public void onConferenceableConnectionsChanged(android.telecom.RemoteConference, java.util.List); method public void onConnectionAdded(android.telecom.RemoteConference, android.telecom.RemoteConnection); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConference, int); + method public void onConnectionPropertiesChanged(android.telecom.RemoteConference, int); method public void onConnectionRemoved(android.telecom.RemoteConference, android.telecom.RemoteConnection); method public void onDestroyed(android.telecom.RemoteConference); method public void onDisconnected(android.telecom.RemoteConference, android.telecom.DisconnectCause); @@ -36525,6 +36679,7 @@ package android.telecom { method public android.telecom.RemoteConference getConference(); method public java.util.List getConferenceableConnections(); method public int getConnectionCapabilities(); + method public int getConnectionProperties(); method public android.telecom.DisconnectCause getDisconnectCause(); method public final android.os.Bundle getExtras(); method public int getState(); @@ -36536,6 +36691,7 @@ package android.telecom { method public boolean isVoipAudioMode(); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.RemoteConnection.Callback); method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler); method public void reject(); @@ -36552,6 +36708,8 @@ package android.telecom { method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference); method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int); + method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle); + method public void onConnectionPropertiesChanged(android.telecom.RemoteConnection, int); method public void onDestroyed(android.telecom.RemoteConnection); method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause); method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle); @@ -36648,6 +36806,7 @@ package android.telecom { field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; + field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 @@ -36702,9 +36861,11 @@ package android.telephony { field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED"; field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool"; field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool"; + field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call"; field public static final java.lang.String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool"; field public static final java.lang.String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool"; field public static final java.lang.String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool"; + field public static final java.lang.String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool"; field public static final java.lang.String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool"; field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool"; field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool"; @@ -36736,6 +36897,7 @@ package android.telephony { field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool"; field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string"; field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool"; + field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool"; field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool"; field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int"; field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool"; @@ -36794,6 +36956,7 @@ package android.telephony { field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; field public static final java.lang.String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool"; field public static final java.lang.String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool"; + field public static final java.lang.String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool"; field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool"; field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool"; field public static final java.lang.String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool"; @@ -37392,12 +37555,15 @@ package android.telephony { field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6 field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc field public static final int NETWORK_TYPE_GPRS = 1; // 0x1 + field public static final int NETWORK_TYPE_GSM = 16; // 0x10 field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8 field public static final int NETWORK_TYPE_HSPA = 10; // 0xa field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9 field public static final int NETWORK_TYPE_IDEN = 11; // 0xb + field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12 field public static final int NETWORK_TYPE_LTE = 13; // 0xd + field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11 field public static final int NETWORK_TYPE_UMTS = 3; // 0x3 field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0 field public static final int PHONE_TYPE_CDMA = 2; // 0x2 @@ -40200,7 +40366,10 @@ package android.util { method public boolean equals(android.util.DisplayMetrics); method public void setTo(android.util.DisplayMetrics); method public void setToDefaults(); + field public static final int DENSITY_260 = 260; // 0x104 field public static final int DENSITY_280 = 280; // 0x118 + field public static final int DENSITY_300 = 300; // 0x12c + field public static final int DENSITY_340 = 340; // 0x154 field public static final int DENSITY_360 = 360; // 0x168 field public static final int DENSITY_400 = 400; // 0x190 field public static final int DENSITY_420 = 420; // 0x1a4 @@ -41530,6 +41699,10 @@ package android.view { field public static final int KEYCODE_SWITCH_CHARSET = 95; // 0x5f field public static final int KEYCODE_SYM = 63; // 0x3f field public static final int KEYCODE_SYSRQ = 120; // 0x78 + field public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281; // 0x119 + field public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; // 0x11a + field public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; // 0x11b + field public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; // 0x118 field public static final int KEYCODE_T = 48; // 0x30 field public static final int KEYCODE_TAB = 61; // 0x3d field public static final int KEYCODE_TV = 170; // 0xaa @@ -42412,6 +42585,7 @@ package android.view { method public float getPivotY(); method public android.view.PointerIcon getPointerIcon(); method public android.content.res.Resources getResources(); + method public final boolean getRevealOnFocusHint(); method public final int getRight(); method protected float getRightFadingEdgeStrength(); method protected int getRightPaddingOffset(); @@ -42699,6 +42873,7 @@ package android.view { method public void setPivotY(float); method public void setPointerIcon(android.view.PointerIcon); method public void setPressed(boolean); + method public final void setRevealOnFocusHint(boolean); method public final void setRight(int); method public void setRotation(float); method public void setRotationX(float); @@ -43848,6 +44023,7 @@ package android.view { field public static final int TYPE_APPLICATION_SUB_PANEL = 1002; // 0x3ea field public static final int TYPE_BASE_APPLICATION = 1; // 0x1 field public static final int TYPE_CHANGED = 2; // 0x2 + field public static final int TYPE_DRAWN_APPLICATION = 4; // 0x4 field public static final int TYPE_INPUT_METHOD = 2011; // 0x7db field public static final int TYPE_INPUT_METHOD_DIALOG = 2012; // 0x7dc field public static final int TYPE_KEYGUARD_DIALOG = 2009; // 0x7d9 @@ -44620,6 +44796,7 @@ package android.view.inputmethod { method public boolean clearMetaKeyStates(int); method public void closeConnection(); method public boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public boolean commitText(java.lang.CharSequence, int); method public boolean deleteSurroundingText(int, int); @@ -44729,6 +44906,7 @@ package android.view.inputmethod { field public static final int IME_NULL = 0; // 0x0 field public int actionId; field public java.lang.CharSequence actionLabel; + field public java.lang.String[] contentMimeTypes; field public android.os.Bundle extras; field public int fieldId; field public java.lang.String fieldName; @@ -44788,6 +44966,7 @@ package android.view.inputmethod { method public abstract boolean clearMetaKeyStates(int); method public abstract void closeConnection(); method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public abstract boolean commitText(java.lang.CharSequence, int); method public abstract boolean deleteSurroundingText(int, int); @@ -44813,6 +44992,7 @@ package android.view.inputmethod { field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2 field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1 field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1 + field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1 } public class InputConnectionWrapper implements android.view.inputmethod.InputConnection { @@ -44821,6 +45001,7 @@ package android.view.inputmethod { method public boolean clearMetaKeyStates(int); method public void closeConnection(); method public boolean commitCompletion(android.view.inputmethod.CompletionInfo); + method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle); method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo); method public boolean commitText(java.lang.CharSequence, int); method public boolean deleteSurroundingText(int, int); @@ -44845,6 +45026,19 @@ package android.view.inputmethod { method public void setTarget(android.view.inputmethod.InputConnection); } + public final class InputContentInfo implements android.os.Parcelable { + ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription); + ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri); + method public int describeContents(); + method public android.net.Uri getContentUri(); + method public android.content.ClipDescription getDescription(); + method public android.net.Uri getLinkUri(); + method public void releasePermission(); + method public void requestPermission(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + public abstract interface InputMethod { method public abstract void attachToken(android.os.IBinder); method public abstract void bindInput(android.view.inputmethod.InputBinding); @@ -46438,6 +46632,7 @@ package android.widget { method public int getFirstDayOfWeek(); method public long getMaxDate(); method public long getMinDate(); + method public int getMode(); method public int getMonth(); method public deprecated boolean getSpinnersShown(); method public int getYear(); @@ -46448,6 +46643,8 @@ package android.widget { method public void setMinDate(long); method public deprecated void setSpinnersShown(boolean); method public void updateDate(int, int, int); + field public static final int MODE_CALENDAR = 2; // 0x2 + field public static final int MODE_SPINNER = 1; // 0x1 } public static abstract interface DatePicker.OnDateChangedListener { @@ -48212,6 +48409,7 @@ package android.widget { method public deprecated java.lang.Integer getCurrentMinute(); method public int getHour(); method public int getMinute(); + method public int getMode(); method public boolean is24HourView(); method public deprecated void setCurrentHour(java.lang.Integer); method public deprecated void setCurrentMinute(java.lang.Integer); @@ -48219,6 +48417,8 @@ package android.widget { method public void setIs24HourView(java.lang.Boolean); method public void setMinute(int); method public void setOnTimeChangedListener(android.widget.TimePicker.OnTimeChangedListener); + field public static final int MODE_CLOCK = 2; // 0x2 + field public static final int MODE_SPINNER = 1; // 0x1 } public static abstract interface TimePicker.OnTimeChangedListener { diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 8ccd5d2ebcbadf28589b4f57f10bac98a4703f7e..d6c00589e7c2ab414b58d587d909cd36f001236d 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -723,10 +723,10 @@ public class Am extends BaseCommand { System.out.println("Complete"); } mRepeat--; - if (mRepeat > 1) { + if (mRepeat > 0) { mAm.unhandledBack(); } - } while (mRepeat > 1); + } while (mRepeat > 0); } private void runForceStop() throws Exception { diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index 7c8842ca02316ba9b6e3aefd2cd9e3f157745c0c..3a92b9e74144c7b4fcd583826ac796747447f483 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk @@ -3,14 +3,16 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ bootanimation_main.cpp \ - AudioPlayer.cpp \ + audioplay.cpp \ BootAnimation.cpp LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -LOCAL_C_INCLUDES += external/tinyalsa/include +LOCAL_C_INCLUDES += \ + external/tinyalsa/include \ + frameworks/wilhelm/include LOCAL_SHARED_LIBRARIES := \ libcutils \ @@ -23,6 +25,7 @@ LOCAL_SHARED_LIBRARIES := \ libEGL \ libGLESv1_CM \ libgui \ + libOpenSLES \ libtinyalsa LOCAL_MODULE:= bootanimation diff --git a/cmds/bootanimation/AudioPlayer.cpp b/cmds/bootanimation/AudioPlayer.cpp deleted file mode 100644 index 293213008d582ca6d5048a1a585da9fb4f570d62..0000000000000000000000000000000000000000 --- a/cmds/bootanimation/AudioPlayer.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_NDEBUG 0 -#define LOG_TAG "BootAnim_AudioPlayer" - -#include "AudioPlayer.h" - -#include -#include -#include -#include - -#define ID_RIFF 0x46464952 -#define ID_WAVE 0x45564157 -#define ID_FMT 0x20746d66 -#define ID_DATA 0x61746164 - -// Maximum line length for audio_conf.txt -// We only accept lines less than this length to avoid overflows using sscanf() -#define MAX_LINE_LENGTH 1024 - -struct riff_wave_header { - uint32_t riff_id; - uint32_t riff_sz; - uint32_t wave_id; -}; - -struct chunk_header { - uint32_t id; - uint32_t sz; -}; - -struct chunk_fmt { - uint16_t audio_format; - uint16_t num_channels; - uint32_t sample_rate; - uint32_t byte_rate; - uint16_t block_align; - uint16_t bits_per_sample; -}; - - -namespace android { - -AudioPlayer::AudioPlayer() - : mCard(-1), - mDevice(-1), - mPeriodSize(0), - mPeriodCount(0), - mCurrentFile(NULL) -{ -} - -AudioPlayer::~AudioPlayer() { -} - -static bool setMixerValue(struct mixer* mixer, const char* name, const char* values) -{ - if (!mixer) { - ALOGE("no mixer in setMixerValue"); - return false; - } - struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, name); - if (!ctl) { - ALOGE("mixer_get_ctl_by_name failed for %s", name); - return false; - } - - enum mixer_ctl_type type = mixer_ctl_get_type(ctl); - int numValues = mixer_ctl_get_num_values(ctl); - int intValue; - char stringValue[MAX_LINE_LENGTH]; - - for (int i = 0; i < numValues && values; i++) { - // strip leading space - while (*values == ' ') values++; - if (*values == 0) break; - - switch (type) { - case MIXER_CTL_TYPE_BOOL: - case MIXER_CTL_TYPE_INT: - if (sscanf(values, "%d", &intValue) == 1) { - if (mixer_ctl_set_value(ctl, i, intValue) != 0) { - ALOGE("mixer_ctl_set_value failed for %s %d", name, intValue); - } - } else { - ALOGE("Could not parse %s as int for %s", values, name); - } - break; - case MIXER_CTL_TYPE_ENUM: - if (sscanf(values, "%s", stringValue) == 1) { - if (mixer_ctl_set_enum_by_string(ctl, stringValue) != 0) { - ALOGE("mixer_ctl_set_enum_by_string failed for %s %s", name, stringValue); - } - } else { - ALOGE("Could not parse %s as enum for %s", values, name); - } - break; - default: - ALOGE("unsupported mixer type %d for %s", type, name); - break; - } - - values = strchr(values, ' '); - } - - return true; -} - - -/* - * Parse the audio configuration file. - * The file is named audio_conf.txt and must begin with the following header: - * - * card= - * device= - * period_size= - * period_count= - * - * This header is followed by zero or more mixer settings, each with the format: - * mixer "" = - * Since mixer names can contain spaces, the name must be enclosed in double quotes. - * The values in the value list can be integers, booleans (represented by 0 or 1) - * or strings for enum values. - */ -bool AudioPlayer::init(const char* config) -{ - int tempInt; - struct mixer* mixer = NULL; - char name[MAX_LINE_LENGTH]; - - for (;;) { - const char* endl = strstr(config, "\n"); - if (!endl) break; - String8 line(config, endl - config); - if (line.length() >= MAX_LINE_LENGTH) { - ALOGE("Line too long in audio_conf.txt"); - return false; - } - const char* l = line.string(); - - if (sscanf(l, "card=%d", &tempInt) == 1) { - ALOGD("card=%d", tempInt); - mCard = tempInt; - - mixer = mixer_open(mCard); - if (!mixer) { - ALOGE("could not open mixer for card %d", mCard); - return false; - } - } else if (sscanf(l, "device=%d", &tempInt) == 1) { - ALOGD("device=%d", tempInt); - mDevice = tempInt; - } else if (sscanf(l, "period_size=%d", &tempInt) == 1) { - ALOGD("period_size=%d", tempInt); - mPeriodSize = tempInt; - } else if (sscanf(l, "period_count=%d", &tempInt) == 1) { - ALOGD("period_count=%d", tempInt); - mPeriodCount = tempInt; - } else if (sscanf(l, "mixer \"%[0-9a-zA-Z _]s\"", name) == 1) { - const char* values = strchr(l, '='); - if (values) { - values++; // skip '=' - ALOGD("name: \"%s\" = %s", name, values); - setMixerValue(mixer, name, values); - } else { - ALOGE("values missing for name: \"%s\"", name); - } - } - config = ++endl; - } - - mixer_close(mixer); - - if (mCard >= 0 && mDevice >= 0) { - return true; - } - - return false; -} - -void AudioPlayer::playFile(FileMap* fileMap) { - // stop any currently playing sound - requestExitAndWait(); - - mCurrentFile = fileMap; - run("bootanim audio", PRIORITY_URGENT_AUDIO); -} - -bool AudioPlayer::threadLoop() -{ - struct pcm_config config; - struct pcm *pcm = NULL; - bool moreChunks = true; - const struct chunk_fmt* chunkFmt = NULL; - int bufferSize; - const uint8_t* wavData; - size_t wavLength; - const struct riff_wave_header* wavHeader; - - if (mCurrentFile == NULL) { - ALOGE("mCurrentFile is NULL"); - return false; - } - - wavData = (const uint8_t *)mCurrentFile->getDataPtr(); - if (!wavData) { - ALOGE("Could not access WAV file data"); - goto exit; - } - wavLength = mCurrentFile->getDataLength(); - - wavHeader = (const struct riff_wave_header *)wavData; - if (wavLength < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || - (wavHeader->wave_id != ID_WAVE)) { - ALOGE("Error: audio file is not a riff/wave file\n"); - goto exit; - } - wavData += sizeof(*wavHeader); - wavLength -= sizeof(*wavHeader); - - do { - const struct chunk_header* chunkHeader = (const struct chunk_header*)wavData; - if (wavLength < sizeof(*chunkHeader)) { - ALOGE("EOF reading chunk headers"); - goto exit; - } - - wavData += sizeof(*chunkHeader); - wavLength -= sizeof(*chunkHeader); - - switch (chunkHeader->id) { - case ID_FMT: - chunkFmt = (const struct chunk_fmt *)wavData; - wavData += chunkHeader->sz; - wavLength -= chunkHeader->sz; - break; - case ID_DATA: - /* Stop looking for chunks */ - moreChunks = 0; - break; - default: - /* Unknown chunk, skip bytes */ - wavData += chunkHeader->sz; - wavLength -= chunkHeader->sz; - } - } while (moreChunks); - - if (!chunkFmt) { - ALOGE("format not found in WAV file"); - goto exit; - } - - - memset(&config, 0, sizeof(config)); - config.channels = chunkFmt->num_channels; - config.rate = chunkFmt->sample_rate; - config.period_size = mPeriodSize; - config.period_count = mPeriodCount; - config.start_threshold = mPeriodSize / 4; - config.stop_threshold = INT_MAX; - config.avail_min = config.start_threshold; - if (chunkFmt->bits_per_sample != 16) { - ALOGE("only 16 bit WAV files are supported"); - goto exit; - } - config.format = PCM_FORMAT_S16_LE; - - pcm = pcm_open(mCard, mDevice, PCM_OUT, &config); - if (!pcm || !pcm_is_ready(pcm)) { - ALOGE("Unable to open PCM device (%s)\n", pcm_get_error(pcm)); - goto exit; - } - - bufferSize = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); - - while (wavLength > 0) { - if (exitPending()) goto exit; - size_t count = bufferSize; - if (count > wavLength) - count = wavLength; - - if (pcm_write(pcm, wavData, count)) { - ALOGE("pcm_write failed (%s)", pcm_get_error(pcm)); - goto exit; - } - wavData += count; - wavLength -= count; - } - -exit: - if (pcm) - pcm_close(pcm); - delete mCurrentFile; - mCurrentFile = NULL; - return false; -} - -} // namespace android diff --git a/cmds/bootanimation/AudioPlayer.h b/cmds/bootanimation/AudioPlayer.h deleted file mode 100644 index 1def0aeac8d12d28bee7aadfc10c296ca6bd971e..0000000000000000000000000000000000000000 --- a/cmds/bootanimation/AudioPlayer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _BOOTANIMATION_AUDIOPLAYER_H -#define _BOOTANIMATION_AUDIOPLAYER_H - -#include -#include - -namespace android { - -class AudioPlayer : public Thread -{ -public: - AudioPlayer(); - virtual ~AudioPlayer(); - bool init(const char* config); - - void playFile(FileMap* fileMap); - -private: - virtual bool threadLoop(); - -private: - int mCard; // ALSA card to use - int mDevice; // ALSA device to use - int mPeriodSize; - int mPeriodCount; - - FileMap* mCurrentFile; -}; - -} // namespace android - -#endif // _BOOTANIMATION_AUDIOPLAYER_H diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 25b264ecff103853c84ab7e096c57735a3538318..c9211939ec6c150dfe2e105dddc7dd24bd5c31dd 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -18,6 +18,9 @@ #define LOG_TAG "BootAnimation" #include +#include +#include +#include #include #include #include @@ -55,26 +58,56 @@ #include #include "BootAnimation.h" -#include "AudioPlayer.h" - -#define OEM_BOOTANIMATION_FILE "/oem/media/bootanimation.zip" -#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip" -#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip" -#define EXIT_PROP_NAME "service.bootanim.exit" +#include "audioplay.h" namespace android { +static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; +static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; +static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip"; +static const char SYSTEM_DATA_DIR_PATH[] = "/data/system"; +static const char SYSTEM_TIME_DIR_NAME[] = "time"; +static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time"; +static const char CLOCK_FONT_ASSET[] = "images/clock_font.png"; +static const char CLOCK_FONT_ZIP_NAME[] = "clock_font.png"; +static const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change"; +static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change"; +static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate"; +static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate"; +// Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00. +static const long long ACCURATE_TIME_EPOCH = 946684800000; +static constexpr char FONT_BEGIN_CHAR = ' '; +static constexpr char FONT_END_CHAR = '~' + 1; +static constexpr size_t FONT_NUM_CHARS = FONT_END_CHAR - FONT_BEGIN_CHAR + 1; +static constexpr size_t FONT_NUM_COLS = 16; +static constexpr size_t FONT_NUM_ROWS = FONT_NUM_CHARS / FONT_NUM_COLS; +static const int TEXT_CENTER_VALUE = INT_MAX; +static const int TEXT_MISSING_VALUE = INT_MIN; +static const char EXIT_PROP_NAME[] = "service.bootanim.exit"; +static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound"; static const int ANIM_ENTRY_NAME_MAX = 256; +static constexpr size_t TEXT_POS_LEN_MAX = 16; +static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed"; +static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason"; +// bootreasons list in "system/core/bootstat/bootstat.cpp". +static const std::vector PLAY_SOUND_BOOTREASON_BLACKLIST { + "kernel_panic", + "Panic", + "Watchdog", +}; // --------------------------------------------------------------------------- -BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true) { +BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), + mTimeCheckThread(NULL) { mSession = new SurfaceComposerClient(); -} -BootAnimation::~BootAnimation() { + // If the system has already booted, the animation is not being used for a boot. + mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0); } +BootAnimation::~BootAnimation() {} + void BootAnimation::onFirstRef() { status_t err = mSession->linkToComposerDeath(this); ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err)); @@ -97,9 +130,7 @@ void BootAnimation::binderDied(const wp&) // might be blocked on a condition variable that will never be updated. kill( getpid(), SIGKILL ); requestExit(); - if (mAudioPlayer != NULL) { - mAudioPlayer->requestExit(); - } + audioplay::destroy(); } status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, @@ -154,15 +185,14 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + return NO_ERROR; } -status_t BootAnimation::initTexture(const Animation::Frame& frame) +status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { - //StopWatch watch("blah"); - SkBitmap bitmap; - SkMemoryStream stream(frame.map->getDataPtr(), frame.map->getDataLength()); + SkMemoryStream stream(map->getDataPtr(), map->getDataLength()); SkImageDecoder* codec = SkImageDecoder::Factory(&stream); if (codec != NULL) { codec->setDitherImage(false); @@ -175,7 +205,7 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame) // FileMap memory is never released until application exit. // Release it now as the texture is already loaded and the memory used for // the packed resource can be released. - delete frame.map; + delete map; // ensure we can call getPixels(). No need to call unlock, since the // bitmap will go out of scope when we return from this method. @@ -193,25 +223,25 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame) switch (bitmap.colorType()) { case kN32_SkColorType: - if (tw != w || th != h) { + if (!mUseNpotTextures && (tw != w || th != h)) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p); } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, p); } break; case kRGB_565_SkColorType: - if (tw != w || th != h) { + if (!mUseNpotTextures && (tw != w || th != h)) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); } break; @@ -221,6 +251,9 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame) glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + *width = w; + *height = h; + return NO_ERROR; } @@ -384,7 +417,6 @@ bool BootAnimation::android() return false; } - void BootAnimation::checkExit() { // Allow surface flinger to gracefully request shutdown char value[PROPERTY_VALUE_MAX]; @@ -392,10 +424,48 @@ void BootAnimation::checkExit() { int exitnow = atoi(value); if (exitnow) { requestExit(); - if (mAudioPlayer != NULL) { - mAudioPlayer->requestExit(); + } +} + +bool BootAnimation::validClock(const Animation::Part& part) { + return part.clockPosX != TEXT_MISSING_VALUE && part.clockPosY != TEXT_MISSING_VALUE; +} + +bool parseTextCoord(const char* str, int* dest) { + if (strcmp("c", str) == 0) { + *dest = TEXT_CENTER_VALUE; + return true; + } + + char* end; + int val = (int) strtol(str, &end, 0); + if (end == str || *end != '\0' || val == INT_MAX || val == INT_MIN) { + return false; + } + *dest = val; + return true; +} + +// Parse two position coordinates. If only string is non-empty, treat it as the y value. +void parsePosition(const char* str1, const char* str2, int* x, int* y) { + bool success = false; + if (strlen(str1) == 0) { // No values were specified + // success = false + } else if (strlen(str2) == 0) { // we have only one value + if (parseTextCoord(str1, y)) { + *x = TEXT_CENTER_VALUE; + success = true; + } + } else { + if (parseTextCoord(str1, x) && parseTextCoord(str2, y)) { + success = true; } } + + if (!success) { + *x = TEXT_MISSING_VALUE; + *y = TEXT_MISSING_VALUE; + } } // Parse a color represented as an HTML-style 'RRGGBB' string: each pair of @@ -444,69 +514,105 @@ static bool readFile(ZipFileRO* zip, const char* name, String8& outString) return true; } -// The time glyphs are stored in a single image of height 64 pixels. Each digit is 40 pixels wide, -// and the colon character is half that at 20 pixels. The glyph order is '0123456789:'. -// We render 24 hour time. -void BootAnimation::drawTime(const Texture& clockTex, const int yPos) { - static constexpr char TIME_FORMAT[] = "%H:%M"; - static constexpr int TIME_LENGTH = sizeof(TIME_FORMAT); +// The font image should be a 96x2 array of character images. The +// columns are the printable ASCII characters 0x20 - 0x7f. The +// top row is regular text; the bottom row is bold. +status_t BootAnimation::initFont(Font* font, const char* fallback) { + status_t status = NO_ERROR; - static constexpr int DIGIT_HEIGHT = 64; - static constexpr int DIGIT_WIDTH = 40; - static constexpr int COLON_WIDTH = DIGIT_WIDTH / 2; - static constexpr int TIME_WIDTH = (DIGIT_WIDTH * 4) + COLON_WIDTH; + if (font->map != nullptr) { + glGenTextures(1, &font->texture.name); + glBindTexture(GL_TEXTURE_2D, font->texture.name); - if (clockTex.h < DIGIT_HEIGHT || clockTex.w < (10 * DIGIT_WIDTH + COLON_WIDTH)) { - ALOGE("Clock texture is too small; abandoning boot animation clock"); - mClockEnabled = false; - return; + status = initTexture(font->map, &font->texture.w, &font->texture.h); + + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } else if (fallback != nullptr) { + status = initTexture(&font->texture, mAssets, fallback); + } else { + return NO_INIT; } - time_t rawtime; - time(&rawtime); - struct tm* timeInfo = localtime(&rawtime); + if (status == NO_ERROR) { + font->char_width = font->texture.w / FONT_NUM_COLS; + font->char_height = font->texture.h / FONT_NUM_ROWS / 2; // There are bold and regular rows + } - char timeBuff[TIME_LENGTH]; - size_t length = strftime(timeBuff, TIME_LENGTH, TIME_FORMAT, timeInfo); + return status; +} - if (length != TIME_LENGTH - 1) { - ALOGE("Couldn't format time; abandoning boot animation clock"); - mClockEnabled = false; - return; +void BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) { + glEnable(GL_BLEND); // Allow us to draw on top of the animation + glBindTexture(GL_TEXTURE_2D, font.texture.name); + + const int len = strlen(str); + const int strWidth = font.char_width * len; + + if (*x == TEXT_CENTER_VALUE) { + *x = (mWidth - strWidth) / 2; + } else if (*x < 0) { + *x = mWidth + *x - strWidth; + } + if (*y == TEXT_CENTER_VALUE) { + *y = (mHeight - font.char_height) / 2; + } else if (*y < 0) { + *y = mHeight + *y - font.char_height; } - glEnable(GL_BLEND); // Allow us to draw on top of the animation - glBindTexture(GL_TEXTURE_2D, clockTex.name); + int cropRect[4] = { 0, 0, font.char_width, -font.char_height }; - int xPos = (mWidth - TIME_WIDTH) / 2; - int cropRect[4] = { 0, DIGIT_HEIGHT, DIGIT_WIDTH, -DIGIT_HEIGHT }; + for (int i = 0; i < len; i++) { + char c = str[i]; - for (int i = 0; i < TIME_LENGTH - 1; i++) { - char c = timeBuff[i]; - int width = DIGIT_WIDTH; - int pos = c - '0'; // Position in the character list - if (pos < 0 || pos > 10) { - continue; - } - if (c == ':') { - width = COLON_WIDTH; + if (c < FONT_BEGIN_CHAR || c > FONT_END_CHAR) { + c = '?'; } // Crop the texture to only the pixels in the current glyph - int left = pos * DIGIT_WIDTH; - cropRect[0] = left; - cropRect[2] = width; + const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters + const int row = charPos / FONT_NUM_COLS; + const int col = charPos % FONT_NUM_COLS; + cropRect[0] = col * font.char_width; // Left of column + cropRect[1] = row * font.char_height * 2; // Top of row + // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line + cropRect[1] += bold ? 2 * font.char_height : font.char_height; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); - glDrawTexiOES(xPos, yPos, 0, width, DIGIT_HEIGHT); + glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height); - xPos += width; + *x += font.char_width; } glDisable(GL_BLEND); // Return to the animation's default behaviour glBindTexture(GL_TEXTURE_2D, 0); } +// We render 24 hour time. +void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) { + static constexpr char TIME_FORMAT[] = "%H:%M"; + static constexpr int TIME_LENGTH = 6; + + time_t rawtime; + time(&rawtime); + struct tm* timeInfo = localtime(&rawtime); + + char timeBuff[TIME_LENGTH]; + size_t length = strftime(timeBuff, TIME_LENGTH, TIME_FORMAT, timeInfo); + + if (length != TIME_LENGTH - 1) { + ALOGE("Couldn't format time; abandoning boot animation clock"); + mClockEnabled = false; + return; + } + + int x = xPos; + int y = yPos; + drawText(timeBuff, font, false, &x, &y); +} + bool BootAnimation::parseAnimationDesc(Animation& animation) { String8 desString; @@ -516,16 +622,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) } char const* s = desString.string(); - // Create and initialize an AudioPlayer if we have an audio_conf.txt file - String8 audioConf; - if (readFile(animation.zip, "audio_conf.txt", audioConf)) { - mAudioPlayer = new AudioPlayer; - if (!mAudioPlayer->init(audioConf.string())) { - ALOGE("mAudioPlayer.init failed"); - mAudioPlayer = NULL; - } - } - // Parse the description file for (;;) { const char* endl = strstr(s, "\n"); @@ -537,9 +633,10 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) int height = 0; int count = 0; int pause = 0; - int clockPosY = -1; char path[ANIM_ENTRY_NAME_MAX]; char color[7] = "000000"; // default to black if unspecified + char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; + char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { @@ -547,16 +644,16 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) animation.width = width; animation.height = height; animation.fps = fps; - } else if (sscanf(l, " %c %d %d %s #%6s %d", - &pathType, &count, &pause, path, color, &clockPosY) >= 4) { - // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPosY=%d", pathType, count, pause, path, color, clockPosY); + } else if (sscanf(l, " %c %d %d %s #%6s %16s %16s", + &pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) { + //ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s", + // pathType, count, pause, path, color, clockPos1, clockPos2); Animation::Part part; part.playUntilComplete = pathType == 'c'; part.count = count; part.pause = pause; part.path = path; - part.clockPosY = clockPosY; - part.audioFile = NULL; + part.audioData = NULL; part.animation = NULL; if (!parseColor(color, part.backgroundColor)) { ALOGE("> invalid color '#%s'", color); @@ -564,6 +661,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) part.backgroundColor[1] = 0.0f; part.backgroundColor[2] = 0.0f; } + parsePosition(clockPos1, clockPos2, &part.clockPosX, &part.clockPosY); animation.parts.add(part); } else if (strcmp(l, "$SYSTEM") == 0) { @@ -572,7 +670,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) part.playUntilComplete = false; part.count = 1; part.pause = 0; - part.audioFile = NULL; + part.audioData = NULL; part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE)); if (part.animation != NULL) animation.parts.add(part); @@ -588,15 +686,16 @@ bool BootAnimation::preloadZip(Animation& animation) // read all the data structures const size_t pcount = animation.parts.size(); void *cookie = NULL; - ZipFileRO* mZip = animation.zip; - if (!mZip->startIteration(&cookie)) { + ZipFileRO* zip = animation.zip; + if (!zip->startIteration(&cookie)) { return false; } + Animation::Part* partWithAudio = NULL; ZipEntryRO entry; char name[ANIM_ENTRY_NAME_MAX]; - while ((entry = mZip->nextEntry(cookie)) != NULL) { - const int foundEntryName = mZip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX); + while ((entry = zip->nextEntry(cookie)) != NULL) { + const int foundEntryName = zip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX); if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) { ALOGE("Error fetching entry file name"); continue; @@ -606,25 +705,44 @@ bool BootAnimation::preloadZip(Animation& animation) const String8 path(entryName.getPathDir()); const String8 leaf(entryName.getPathLeaf()); if (leaf.size() > 0) { - for (size_t j=0 ; jcreateEntryFileMap(entry); + if (map) { + animation.clockFont.map = map; + } + continue; + } + + for (size_t j = 0; j < pcount; j++) { if (path == animation.parts[j].path) { uint16_t method; // supports only stored png files - if (mZip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) { + if (zip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) { if (method == ZipFileRO::kCompressStored) { - FileMap* map = mZip->createEntryFileMap(entry); + FileMap* map = zip->createEntryFileMap(entry); if (map) { Animation::Part& part(animation.parts.editItemAt(j)); if (leaf == "audio.wav") { // a part may have at most one audio file - part.audioFile = map; + part.audioData = (uint8_t *)map->getDataPtr(); + part.audioLength = map->getDataLength(); + partWithAudio = ∂ + } else if (leaf == "trim.txt") { + part.trimData.setTo((char const*)map->getDataPtr(), + map->getDataLength()); } else { Animation::Frame frame; frame.name = leaf; frame.map = map; + frame.trimWidth = animation.width; + frame.trimHeight = animation.height; + frame.trimX = 0; + frame.trimY = 0; part.frames.add(frame); } } + } else { + ALOGE("bootanimation.zip is compressed; must be only stored"); } } } @@ -632,18 +750,76 @@ bool BootAnimation::preloadZip(Animation& animation) } } - mZip->endIteration(cookie); + // If there is trimData present, override the positioning defaults. + for (Animation::Part& part : animation.parts) { + const char* trimDataStr = part.trimData.string(); + for (size_t frameIdx = 0; frameIdx < part.frames.size(); frameIdx++) { + const char* endl = strstr(trimDataStr, "\n"); + // No more trimData for this part. + if (endl == NULL) { + break; + } + String8 line(trimDataStr, endl - trimDataStr); + const char* lineStr = line.string(); + trimDataStr = ++endl; + int width = 0, height = 0, x = 0, y = 0; + if (sscanf(lineStr, "%dx%d+%d+%d", &width, &height, &x, &y) == 4) { + Animation::Frame& frame(part.frames.editItemAt(frameIdx)); + frame.trimWidth = width; + frame.trimHeight = height; + frame.trimX = x; + frame.trimY = y; + } else { + ALOGE("Error parsing trim.txt, line: %s", lineStr); + break; + } + } + } + + // Create and initialize audioplay if there is a wav file in any of the animations. + if (partWithAudio != NULL) { + ALOGD("found audio.wav, creating playback engine"); + if (!audioplay::create(partWithAudio->audioData, partWithAudio->audioLength)) { + return false; + } + } + + zip->endIteration(cookie); return true; } bool BootAnimation::movie() { - Animation* animation = loadAnimation(mZipFileName); if (animation == NULL) return false; + bool anyPartHasClock = false; + for (size_t i=0; i < animation->parts.size(); i++) { + if(validClock(animation->parts[i])) { + anyPartHasClock = true; + break; + } + } + if (!anyPartHasClock) { + mClockEnabled = false; + } + + // Check if npot textures are supported + mUseNpotTextures = false; + String8 gl_extensions; + const char* exts = reinterpret_cast(glGetString(GL_EXTENSIONS)); + if (!exts) { + glGetError(); + } else { + gl_extensions.setTo(exts); + if ((gl_extensions.find("GL_ARB_texture_non_power_of_two") != -1) || + (gl_extensions.find("GL_OES_texture_npot") != -1)) { + mUseNpotTextures = true; + } + } + // Blend required to draw time on top of animation frames. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_FLAT); @@ -659,17 +835,29 @@ bool BootAnimation::movie() glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - bool clockTextureInitialized = false; + bool clockFontInitialized = false; if (mClockEnabled) { - clockTextureInitialized = (initTexture(&mClock, mAssets, "images/clock64.png") == NO_ERROR); - mClockEnabled = clockTextureInitialized; + clockFontInitialized = + (initFont(&animation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR); + mClockEnabled = clockFontInitialized; + } + + if (mClockEnabled && !updateIsTimeAccurate()) { + mTimeCheckThread = new TimeCheckThread(this); + mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); } playAnimation(*animation); + + if (mTimeCheckThread != NULL) { + mTimeCheckThread->requestExit(); + mTimeCheckThread = NULL; + } + releaseAnimation(animation); - if (clockTextureInitialized) { - glDeleteTextures(1, &mClock.name); + if (clockFontInitialized) { + glDeleteTextures(1, &animation->clockFont.texture.name); } return false; @@ -678,12 +866,9 @@ bool BootAnimation::movie() bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); - const int xc = (mWidth - animation.width) / 2; - const int yc = ((mHeight - animation.height) / 2); nsecs_t frameDuration = s2ns(1) / animation.fps; - - Region clearReg(Rect(mWidth, mHeight)); - clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); + const int animationX = (mWidth - animation.width) / 2; + const int animationY = (mHeight - animation.height) / 2; for (size_t i=0 ; iplayFile(part.audioFile); + if (r == 0 && part.audioData && playSoundsAllowed()) { + ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength); + audioplay::playClip(part.audioData, part.audioLength); } glClearColor( @@ -727,27 +913,31 @@ bool BootAnimation::playAnimation(const Animation& animation) glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - initTexture(frame); + int w, h; + initTexture(frame.map, &w, &h); } + const int xc = animationX + frame.trimX; + const int yc = animationY + frame.trimY; + Region clearReg(Rect(mWidth, mHeight)); + clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight)); if (!clearReg.isEmpty()) { Region::const_iterator head(clearReg.begin()); Region::const_iterator tail(clearReg.end()); glEnable(GL_SCISSOR_TEST); while (head != tail) { const Rect& r2(*head++); - glScissor(r2.left, mHeight - r2.bottom, - r2.width(), r2.height()); + glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height()); glClear(GL_COLOR_BUFFER_BIT); } glDisable(GL_SCISSOR_TEST); } - // specify the y center as ceiling((mHeight - animation.height) / 2) - // which is equivalent to mHeight - (yc + animation.height) - glDrawTexiOES(xc, mHeight - (yc + animation.height), - 0, animation.width, animation.height); - if (mClockEnabled && part.clockPosY >= 0) { - drawTime(mClock, part.clockPosY); + // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) + // which is equivalent to mHeight - (yc + frame.trimHeight) + glDrawTexiOES(xc, mHeight - (yc + frame.trimHeight), + 0, frame.trimWidth, frame.trimHeight); + if (mClockEnabled && mTimeIsAccurate && validClock(part)) { + drawClock(animation.clockFont, part.clockPosX, part.clockPosY); } eglSwapBuffers(mDisplay, mSurface); @@ -777,14 +967,23 @@ bool BootAnimation::playAnimation(const Animation& animation) break; } - // free the textures for this part + } + + // Free textures created for looping parts now that the animation is done. + for (const Animation::Part& part : animation.parts) { if (part.count != 1) { - for (size_t j=0 ; jfileName = fn; animation->zip = zip; + animation->clockFont.map = nullptr; mLoadedFiles.add(animation->fileName); parseAnimationDesc(*animation); - preloadZip(*animation); + if (!preloadZip(*animation)) { + return NULL; + } + mLoadedFiles.remove(fn); return animation; } + +bool BootAnimation::playSoundsAllowed() const { + // Only play sounds for system boots, not runtime restarts. + if (!mSystemBoot) { + return false; + } + + // Read the system property to see if we should play the sound. + // If it's not present, default to allowed. + if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) { + return false; + } + + // Don't play sounds if this is a reboot due to an error. + char bootreason[PROPERTY_VALUE_MAX]; + if (property_get(BOOTREASON_PROP_NAME, bootreason, nullptr) > 0) { + for (const auto& str : PLAY_SOUND_BOOTREASON_BLACKLIST) { + if (strcasecmp(str.c_str(), bootreason) == 0) { + return false; + } + } + } + return true; +} + +bool BootAnimation::updateIsTimeAccurate() { + static constexpr long long MAX_TIME_IN_PAST = 60000LL * 60LL * 24LL * 30LL; // 30 days + static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL; // 90 minutes + + if (mTimeIsAccurate) { + return true; + } + + struct stat statResult; + if(stat(ACCURATE_TIME_FLAG_FILE_PATH, &statResult) == 0) { + mTimeIsAccurate = true; + return true; + } + + FILE* file = fopen(LAST_TIME_CHANGED_FILE_PATH, "r"); + if (file != NULL) { + long long lastChangedTime = 0; + fscanf(file, "%lld", &lastChangedTime); + fclose(file); + if (lastChangedTime > 0) { + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + // Match the Java timestamp format + long long rtcNow = (now.tv_sec * 1000LL) + (now.tv_nsec / 1000000LL); + if (ACCURATE_TIME_EPOCH < rtcNow + && lastChangedTime > (rtcNow - MAX_TIME_IN_PAST) + && lastChangedTime < (rtcNow + MAX_TIME_IN_FUTURE)) { + mTimeIsAccurate = true; + } + } + } + + return mTimeIsAccurate; +} + +BootAnimation::TimeCheckThread::TimeCheckThread(BootAnimation* bootAnimation) : Thread(false), + mInotifyFd(-1), mSystemWd(-1), mTimeWd(-1), mBootAnimation(bootAnimation) {} + +BootAnimation::TimeCheckThread::~TimeCheckThread() { + // mInotifyFd may be -1 but that's ok since we're not at risk of attempting to close a valid FD. + close(mInotifyFd); +} + +bool BootAnimation::TimeCheckThread::threadLoop() { + bool shouldLoop = doThreadLoop() && !mBootAnimation->mTimeIsAccurate + && mBootAnimation->mClockEnabled; + if (!shouldLoop) { + close(mInotifyFd); + mInotifyFd = -1; + } + return shouldLoop; +} + +bool BootAnimation::TimeCheckThread::doThreadLoop() { + static constexpr int BUFF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1)); + + // Poll instead of doing a blocking read so the Thread can exit if requested. + struct pollfd pfd = { mInotifyFd, POLLIN, 0 }; + ssize_t pollResult = poll(&pfd, 1, 1000); + + if (pollResult == 0) { + return true; + } else if (pollResult < 0) { + ALOGE("Could not poll inotify events"); + return false; + } + + char buff[BUFF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));; + ssize_t length = read(mInotifyFd, buff, BUFF_LEN); + if (length == 0) { + return true; + } else if (length < 0) { + ALOGE("Could not read inotify events"); + return false; + } + + const struct inotify_event *event; + for (char* ptr = buff; ptr < buff + length; ptr += sizeof(struct inotify_event) + event->len) { + event = (const struct inotify_event *) ptr; + if (event->wd == mSystemWd && strcmp(SYSTEM_TIME_DIR_NAME, event->name) == 0) { + addTimeDirWatch(); + } else if (event->wd == mTimeWd && (strcmp(LAST_TIME_CHANGED_FILE_NAME, event->name) == 0 + || strcmp(ACCURATE_TIME_FLAG_FILE_NAME, event->name) == 0)) { + return !mBootAnimation->updateIsTimeAccurate(); + } + } + + return true; +} + +void BootAnimation::TimeCheckThread::addTimeDirWatch() { + mTimeWd = inotify_add_watch(mInotifyFd, SYSTEM_TIME_DIR_PATH, + IN_CLOSE_WRITE | IN_MOVED_TO | IN_ATTRIB); + if (mTimeWd > 0) { + // No need to watch for the time directory to be created if it already exists + inotify_rm_watch(mInotifyFd, mSystemWd); + mSystemWd = -1; + } +} + +status_t BootAnimation::TimeCheckThread::readyToRun() { + mInotifyFd = inotify_init(); + if (mInotifyFd < 0) { + ALOGE("Could not initialize inotify fd"); + return NO_INIT; + } + + mSystemWd = inotify_add_watch(mInotifyFd, SYSTEM_DATA_DIR_PATH, IN_CREATE | IN_ATTRIB); + if (mSystemWd < 0) { + close(mInotifyFd); + mInotifyFd = -1; + ALOGE("Could not add watch for %s", SYSTEM_DATA_DIR_PATH); + return NO_INIT; + } + + addTimeDirWatch(); + + if (mBootAnimation->updateIsTimeAccurate()) { + close(mInotifyFd); + mInotifyFd = -1; + return ALREADY_EXISTS; + } + + return NO_ERROR; +} + // --------------------------------------------------------------------------- } diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index d49e1ec837b95299e6207b72aca22e54250f8404..42759f1acf0dc5fac12078d22e461e1558503220 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -30,7 +30,6 @@ class SkBitmap; namespace android { -class AudioPlayer; class Surface; class SurfaceComposerClient; class SurfaceControl; @@ -51,16 +50,45 @@ private: virtual void onFirstRef(); virtual void binderDied(const wp& who); + bool updateIsTimeAccurate(); + + class TimeCheckThread : public Thread { + public: + TimeCheckThread(BootAnimation* bootAnimation); + virtual ~TimeCheckThread(); + private: + virtual status_t readyToRun(); + virtual bool threadLoop(); + bool doThreadLoop(); + void addTimeDirWatch(); + + int mInotifyFd; + int mSystemWd; + int mTimeWd; + BootAnimation* mBootAnimation; + }; + struct Texture { GLint w; GLint h; GLuint name; }; + struct Font { + FileMap* map; + Texture texture; + int char_width; + int char_height; + }; + struct Animation { struct Frame { String8 name; FileMap* map; + int trimX; + int trimY; + int trimWidth; + int trimHeight; mutable GLuint tid; bool operator < (const Frame& rhs) const { return name < rhs.name; @@ -69,13 +97,19 @@ private: struct Part { int count; // The number of times this part should repeat, 0 for infinite int pause; // The number of frames to pause for at the end of this part - int clockPosY; // The y position of the clock, in pixels, from the bottom of the - // display (the clock is centred horizontally). -1 to disable the clock + int clockPosX; // The x position of the clock, in pixels. Positive values offset from + // the left of the screen, negative values offset from the right. + int clockPosY; // The y position of the clock, in pixels. Positive values offset from + // the bottom of the screen, negative values offset from the top. + // If either of the above are INT_MIN the clock is disabled, if INT_MAX + // the clock is centred on that axis. String8 path; + String8 trimData; SortedVector frames; bool playUntilComplete; float backgroundColor[3]; - FileMap* audioFile; + uint8_t* audioData; + int audioLength; Animation* animation; }; int fps; @@ -85,36 +119,43 @@ private: String8 audioConf; String8 fileName; ZipFileRO* zip; + Font clockFont; }; status_t initTexture(Texture* texture, AssetManager& asset, const char* name); - status_t initTexture(const Animation::Frame& frame); + status_t initTexture(FileMap* map, int* width, int* height); + status_t initFont(Font* font, const char* fallback); bool android(); bool movie(); - void drawTime(const Texture& clockTex, const int yPos); + void drawText(const char* str, const Font& font, bool bold, int* x, int* y); + void drawClock(const Font& font, const int xPos, const int yPos); + bool validClock(const Animation::Part& part); Animation* loadAnimation(const String8&); bool playAnimation(const Animation&); void releaseAnimation(Animation*) const; bool parseAnimationDesc(Animation&); bool preloadZip(Animation &animation); + bool playSoundsAllowed() const; void checkExit(); sp mSession; - sp mAudioPlayer; AssetManager mAssets; Texture mAndroid[2]; - Texture mClock; int mWidth; int mHeight; + bool mUseNpotTextures = false; EGLDisplay mDisplay; EGLDisplay mContext; EGLDisplay mSurface; sp mFlingerSurfaceControl; sp mFlingerSurface; bool mClockEnabled; + bool mTimeIsAccurate; + bool mSystemBoot; String8 mZipFileName; SortedVector mLoadedFiles; + sp mTimeCheckThread; }; // --------------------------------------------------------------------------- diff --git a/cmds/bootanimation/FORMAT.md b/cmds/bootanimation/FORMAT.md new file mode 100644 index 0000000000000000000000000000000000000000..9ea6fea966f2521489c4abade4c1d1b3e3192fc4 --- /dev/null +++ b/cmds/bootanimation/FORMAT.md @@ -0,0 +1,101 @@ +# bootanimation format + +## zipfile paths + +The system selects a boot animation zipfile from the following locations, in order: + + /system/media/bootanimation-encrypted.zip (if getprop("vold.decrypt") = '1') + /system/media/bootanimation.zip + /oem/media/bootanimation.zip + +## zipfile layout + +The `bootanimation.zip` archive file includes: + + desc.txt - a text file + part0 \ + part1 \ directories full of PNG frames + ... / + partN / + +## desc.txt format + +The first line defines the general parameters of the animation: + + WIDTH HEIGHT FPS + + * **WIDTH:** animation width (pixels) + * **HEIGHT:** animation height (pixels) + * **FPS:** frames per second, e.g. 60 + +It is followed by a number of rows of the form: + + TYPE COUNT PAUSE PATH [#RGBHEX CLOCK] + + * **TYPE:** a single char indicating what type of animation segment this is: + + `p` -- this part will play unless interrupted by the end of the boot + + `c` -- this part will play to completion, no matter what + * **COUNT:** how many times to play the animation, or 0 to loop forever until boot is complete + * **PAUSE:** number of FRAMES to delay after this part ends + * **PATH:** directory in which to find the frames for this part (e.g. `part0`) + * **RGBHEX:** _(OPTIONAL)_ a background color, specified as `#RRGGBB` + * **CLOCK:** _(OPTIONAL)_ the y-coordinate at which to draw the current time (for watches) + +There is also a special TYPE, `$SYSTEM`, that loads `/system/media/bootanimation.zip` +and plays that. + +## loading and playing frames + +Each part is scanned and loaded directly from the zip archive. Within a part directory, every file +(except `trim.txt` and `audio.wav`; see next sections) is expected to be a PNG file that represents +one frame in that part (at the specified resolution). For this reason it is important that frames be +named sequentially (e.g. `part000.png`, `part001.png`, ...) and added to the zip archive in that +order. + +## trim.txt + +To save on memory, textures may be trimmed by their background color. trim.txt sequentially lists +the trim output for each frame in its directory, so the frames may be properly positioned. +Output should be of the form: `WxH+X+Y`. Example: + + 713x165+388+914 + 708x152+388+912 + 707x139+388+911 + 649x92+388+910 + +If the file is not present, each frame is assumed to be the same size as the animation. + +## audio.wav + +Each part may optionally play a `wav` sample when it starts. To enable this, add a file +with the name `audio.wav` in the part directory. + +## exiting + +The system will end the boot animation (first completing any incomplete or even entirely unplayed +parts that are of type `c`) when the system is finished booting. (This is accomplished by setting +the system property `service.bootanim.exit` to a nonzero string.) + +## protips + +### PNG compression + +Use `zopflipng` if you have it, otherwise `pngcrush` will do. e.g.: + + for fn in *.png ; do + zopflipng -m ${fn}s ${fn}s.new && mv -f ${fn}s.new ${fn} + # or: pngcrush -q .... + done + +Some animations benefit from being reduced to 256 colors: + + pngquant --force --ext .png *.png + # alternatively: mogrify -colors 256 anim-tmp/*/*.png + +### creating the ZIP archive + + cd + zip -0qry -i \*.txt \*.png \*.wav @ ../bootanimation.zip *.txt part* + +Note that the ZIP archive is not actually compressed! The PNG files are already as compressed +as they can reasonably get, and there is unlikely to be any redundancy between files. diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c546072e733a17618ecaed19e6e5bca563ae65bc --- /dev/null +++ b/cmds/bootanimation/audioplay.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// cribbed from samples/native-audio + +#include "audioplay.h" + +#define CHATTY ALOGD +#define LOG_TAG "audioplay" + +#include + +#include + +// for native audio +#include +#include + +namespace audioplay { +namespace { + +// engine interfaces +static SLObjectItf engineObject = NULL; +static SLEngineItf engineEngine; + +// output mix interfaces +static SLObjectItf outputMixObject = NULL; + +// buffer queue player interfaces +static SLObjectItf bqPlayerObject = NULL; +static SLPlayItf bqPlayerPlay; +static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; +static SLMuteSoloItf bqPlayerMuteSolo; +static SLVolumeItf bqPlayerVolume; + +// pointer and size of the next player buffer to enqueue, and number of remaining buffers +static const uint8_t* nextBuffer; +static unsigned nextSize; + +static const uint32_t ID_RIFF = 0x46464952; +static const uint32_t ID_WAVE = 0x45564157; +static const uint32_t ID_FMT = 0x20746d66; +static const uint32_t ID_DATA = 0x61746164; + +struct RiffWaveHeader { + uint32_t riff_id; + uint32_t riff_sz; + uint32_t wave_id; +}; + +struct ChunkHeader { + uint32_t id; + uint32_t sz; +}; + +struct ChunkFormat { + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint32_t byte_rate; + uint16_t block_align; + uint16_t bits_per_sample; +}; + +// this callback handler is called every time a buffer finishes playing +void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { + (void)bq; + (void)context; + audioplay::setPlaying(false); +} + +bool hasPlayer() { + return (engineObject != NULL && bqPlayerObject != NULL); +} + +// create the engine and output mix objects +bool createEngine() { + SLresult result; + + // create engine + result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); + if (result != SL_RESULT_SUCCESS) { + ALOGE("slCreateEngine failed with result %d", result); + return false; + } + (void)result; + + // realize the engine + result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine Realize failed with result %d", result); + return false; + } + (void)result; + + // get the engine interface, which is needed in order to create other objects + result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine GetInterface failed with result %d", result); + return false; + } + (void)result; + + // create output mix + result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl engine CreateOutputMix failed with result %d", result); + return false; + } + (void)result; + + // realize the output mix + result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl outputMix Realize failed with result %d", result); + return false; + } + (void)result; + + return true; +} + +// create buffer queue audio player +bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) { + SLresult result; + + // configure audio source + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1}; + + // Determine channelMask from num_channels + SLuint32 channelMask; + switch (chunkFormat->num_channels) { + case 1: + channelMask = SL_SPEAKER_FRONT_CENTER; + break; + case 2: + channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; + break; + default: + // Default of 0 will derive mask from num_channels and log a warning. + channelMask = 0; + } + + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, + chunkFormat->num_channels, + chunkFormat->sample_rate * 1000, // convert to milliHz + chunkFormat->bits_per_sample, + 16, + channelMask, + SL_BYTEORDER_LITTLEENDIAN + }; + SLDataSource audioSrc = {&loc_bufq, &format_pcm}; + + // configure audio sink + SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject}; + SLDataSink audioSnk = {&loc_outmix, NULL}; + + // create audio player + const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME, SL_IID_ANDROIDCONFIGURATION}; + const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; + result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, + 3, ids, req); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl CreateAudioPlayer failed with result %d", result); + return false; + } + (void)result; + + // Use the System stream for boot sound playback. + SLAndroidConfigurationItf playerConfig; + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, + SL_IID_ANDROIDCONFIGURATION, &playerConfig); + if (result != SL_RESULT_SUCCESS) { + ALOGE("config GetInterface failed with result %d", result); + return false; + } + SLint32 streamType = SL_ANDROID_STREAM_SYSTEM; + result = (*playerConfig)->SetConfiguration(playerConfig, + SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32)); + if (result != SL_RESULT_SUCCESS) { + ALOGE("SetConfiguration failed with result %d", result); + return false; + } + // use normal performance mode as low latency is not needed. This is not mandatory so + // do not bail if we fail + SLuint32 performanceMode = SL_ANDROID_PERFORMANCE_NONE; + result = (*playerConfig)->SetConfiguration( + playerConfig, SL_ANDROID_KEY_PERFORMANCE_MODE, &performanceMode, sizeof(SLuint32)); + ALOGW_IF(result != SL_RESULT_SUCCESS, + "could not set performance mode on player, error %d", result); + (void)result; + + // realize the player + result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl player Realize failed with result %d", result); + return false; + } + (void)result; + + // get the play interface + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl player GetInterface failed with result %d", result); + return false; + } + (void)result; + + // get the buffer queue interface + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, + &bqPlayerBufferQueue); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl playberBufferQueue GetInterface failed with result %d", result); + return false; + } + (void)result; + + // register callback on the buffer queue + result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result); + return false; + } + (void)result; + + // get the volume interface + result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); + if (result != SL_RESULT_SUCCESS) { + ALOGE("sl volume GetInterface failed with result %d", result); + return false; + } + (void)result; + + // set the player's state to playing + audioplay::setPlaying(true); + CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue); + return true; +} + +bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat, + const uint8_t** oSoundBuf, unsigned* oSoundBufSize) { + *oSoundBuf = clipBuf; + *oSoundBufSize = clipBufSize; + *oChunkFormat = NULL; + const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf; + if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || + (wavHeader->wave_id != ID_WAVE)) { + ALOGE("Error: audio file is not a riff/wave file\n"); + return false; + } + *oSoundBuf += sizeof(*wavHeader); + *oSoundBufSize -= sizeof(*wavHeader); + + while (true) { + const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf; + if (*oSoundBufSize < sizeof(*chunkHeader)) { + ALOGE("EOF reading chunk headers"); + return false; + } + + *oSoundBuf += sizeof(*chunkHeader); + *oSoundBufSize -= sizeof(*chunkHeader); + + bool endLoop = false; + switch (chunkHeader->id) { + case ID_FMT: + *oChunkFormat = (const ChunkFormat*)*oSoundBuf; + *oSoundBuf += chunkHeader->sz; + *oSoundBufSize -= chunkHeader->sz; + break; + case ID_DATA: + /* Stop looking for chunks */ + *oSoundBufSize = chunkHeader->sz; + endLoop = true; + break; + default: + /* Unknown chunk, skip bytes */ + *oSoundBuf += chunkHeader->sz; + *oSoundBufSize -= chunkHeader->sz; + } + if (endLoop) { + break; + } + } + + if (*oChunkFormat == NULL) { + ALOGE("format not found in WAV file"); + return false; + } + return true; +} + +} // namespace + +bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) { + if (!createEngine()) { + return false; + } + + // Parse the example clip. + const ChunkFormat* chunkFormat; + const uint8_t* soundBuf; + unsigned soundBufSize; + if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) { + return false; + } + + // Initialize the BufferQueue based on this clip's format. + if (!createBufferQueueAudioPlayer(chunkFormat)) { + return false; + } + return true; +} + +bool playClip(const uint8_t* buf, int size) { + // Parse the WAV header + const ChunkFormat* chunkFormat; + if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) { + return false; + } + + if (!hasPlayer()) { + ALOGD("cannot play clip %p without a player", buf); + return false; + } + + CHATTY("playClip on player %p: buf=%p size=%d nextSize %d", + bqPlayerBufferQueue, buf, size, nextSize); + + if (nextSize > 0) { + // here we only enqueue one buffer because it is a long clip, + // but for streaming playback we would typically enqueue at least 2 buffers to start + SLresult result; + result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize); + if (SL_RESULT_SUCCESS != result) { + return false; + } + audioplay::setPlaying(true); + } + + return true; +} + +// set the playing state for the buffer queue audio player +void setPlaying(bool isPlaying) { + if (!hasPlayer()) return; + + SLresult result; + + if (NULL != bqPlayerPlay) { + // set the player's state + result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, + isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED); + } + +} + +void destroy() { + // destroy buffer queue audio player object, and invalidate all associated interfaces + if (bqPlayerObject != NULL) { + CHATTY("destroying audio player"); + (*bqPlayerObject)->Destroy(bqPlayerObject); + bqPlayerObject = NULL; + bqPlayerPlay = NULL; + bqPlayerBufferQueue = NULL; + bqPlayerMuteSolo = NULL; + bqPlayerVolume = NULL; + } + + // destroy output mix object, and invalidate all associated interfaces + if (outputMixObject != NULL) { + (*outputMixObject)->Destroy(outputMixObject); + outputMixObject = NULL; + } + + // destroy engine object, and invalidate all associated interfaces + if (engineObject != NULL) { + CHATTY("destroying audio engine"); + (*engineObject)->Destroy(engineObject); + engineObject = NULL; + engineEngine = NULL; + } +} + +} // namespace audioplay diff --git a/cmds/bootanimation/audioplay.h b/cmds/bootanimation/audioplay.h new file mode 100644 index 0000000000000000000000000000000000000000..0e5705af0ad03513d0dc800790c5b2764e1828a7 --- /dev/null +++ b/cmds/bootanimation/audioplay.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef AUDIOPLAY_H_ +#define AUDIOPLAY_H_ + +#include + +namespace audioplay { + +// Initializes the engine with an example of the type of WAV clip to play. +// All buffers passed to playClip are assumed to be in the same format. +bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize); + +// Plays a WAV contained in buf. +// Should not be called while a clip is still playing. +bool playClip(const uint8_t* buf, int size); +void setPlaying(bool isPlaying); +void destroy(); + +} + +#endif // AUDIOPLAY_H_ diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc index ee0d0b8c042f199082d285611b11812456a986f4..7344ba74f70b643fa0fefab4551fa3ce87f825dd 100644 --- a/cmds/bootanimation/bootanim.rc +++ b/cmds/bootanimation/bootanim.rc @@ -4,3 +4,4 @@ service bootanim /system/bin/bootanimation group graphics audio disabled oneshot + writepid /dev/stune/top-app/tasks \ No newline at end of file diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index c6834f940554797962ef6c5b6159f8b53c2f9fc7..5f83d191a731571fcbd1c5d43b16de09d4fb3322 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -41,6 +41,10 @@ import android.content.pm.PackageInstaller; import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.PackageParser.ApkLite; +import android.content.pm.PackageParser.PackageLite; +import android.content.pm.PackageParser.PackageParserException; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Binder; @@ -362,11 +366,27 @@ public final class Pm { */ private int runInstall() throws RemoteException { final InstallParams params = makeInstallParams(); + final String inPath = nextArg(); + if (params.sessionParams.sizeBytes < 0 && inPath != null) { + File file = new File(inPath); + if (file.isFile()) { + try { + ApkLite baseApk = PackageParser.parseApkLite(file, 0); + PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null); + params.sessionParams.setSize( + PackageHelper.calculateInstalledSize(pkgLite, false, + params.sessionParams.abiOverride)); + } catch (PackageParserException | IOException e) { + System.err.println("Error: Failed to parse APK file : " + e); + return 1; + } + } + } + final int sessionId = doCreateSession(params.sessionParams, params.installerPackageName, params.userId); try { - final String inPath = nextArg(); if (inPath == null && params.sessionParams.sizeBytes == 0) { System.err.println("Error: must either specify a package size or an APK file"); return 1; @@ -922,6 +942,8 @@ public final class Pm { flags |= UserInfo.FLAG_EPHEMERAL; } else if ("--guest".equals(opt)) { flags |= UserInfo.FLAG_GUEST; + } else if ("--demo".equals(opt)) { + flags |= UserInfo.FLAG_DEMO; } else { System.err.println("Error: unknown option " + opt); return showUsage(); diff --git a/cmds/wm/src/com/android/commands/wm/Wm.java b/cmds/wm/src/com/android/commands/wm/Wm.java index f7f7c887aeb06d1d89aa401390667f9d8af5f1e8..383cd01ddcd6cca8e2007fb5463cb96166ddf8bb 100644 --- a/cmds/wm/src/com/android/commands/wm/Wm.java +++ b/cmds/wm/src/com/android/commands/wm/Wm.java @@ -23,6 +23,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.util.AndroidException; import android.util.DisplayMetrics; import android.view.Display; @@ -201,9 +202,11 @@ public class Wm extends BaseCommand { try { if (density > 0) { // TODO(multidisplay): For now Configuration only applies to main screen. - mWm.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, density); + mWm.setForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, density, + UserHandle.USER_CURRENT); } else { - mWm.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY); + mWm.clearForcedDisplayDensityForUser(Display.DEFAULT_DISPLAY, + UserHandle.USER_CURRENT); } } catch (RemoteException e) { } diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index ae78e21807e84c66cc2c85f210e68a1e8a8e1638..163e7d2661b91bca0185eef7ea81d75acc228158 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -53,7 +53,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.List; /** - * Accessibility services are intended to assist users with disabilities in using + * Accessibility services should only be used to assist users with disabilities in using * Android devices and apps. They run in the background and receive callbacks by the system * when {@link AccessibilityEvent}s are fired. Such events denote some state transition * in the user interface, for example, the focus has changed, a button has been clicked, @@ -628,8 +628,8 @@ public abstract class AccessibilityService extends Service { if (connection == null) { return false; } - List events = MotionEventGenerator.getMotionEventsFromGestureDescription( - gesture, 100); + List steps = + MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 100); try { synchronized (mLock) { mGestureStatusCallbackSequence++; @@ -641,8 +641,8 @@ public abstract class AccessibilityService extends Service { callback, handler); mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo); } - connection.sendMotionEvents(mGestureStatusCallbackSequence, - new ParceledListSlice<>(events)); + connection.sendGesture(mGestureStatusCallbackSequence, + new ParceledListSlice<>(steps)); } } catch (RemoteException re) { throw new RuntimeException(re); diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java index fc9581e7367c589be5536c04617ffbd6541b18db..d9b03faa42faab73716fb32f6b48aff699633258 100644 --- a/core/java/android/accessibilityservice/GestureDescription.java +++ b/core/java/android/accessibilityservice/GestureDescription.java @@ -21,6 +21,8 @@ import android.annotation.NonNull; import android.graphics.Path; import android.graphics.PathMeasure; import android.graphics.RectF; +import android.os.Parcel; +import android.os.Parcelable; import android.view.InputDevice; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; @@ -303,13 +305,37 @@ public final class GestureDescription { } } - private static class TouchPoint { + /** + * The location of a finger for gesture dispatch + * + * @hide + */ + public static class TouchPoint implements Parcelable { + private static final int FLAG_IS_START_OF_PATH = 0x01; + private static final int FLAG_IS_END_OF_PATH = 0x02; + int mPathIndex; boolean mIsStartOfPath; boolean mIsEndOfPath; float mX; float mY; + public TouchPoint() { + } + + public TouchPoint(TouchPoint pointToCopy) { + copyFrom(pointToCopy); + } + + public TouchPoint(Parcel parcel) { + mPathIndex = parcel.readInt(); + int startEnd = parcel.readInt(); + mIsStartOfPath = (startEnd & FLAG_IS_START_OF_PATH) != 0; + mIsEndOfPath = (startEnd & FLAG_IS_END_OF_PATH) != 0; + mX = parcel.readFloat(); + mY = parcel.readFloat(); + } + void copyFrom(TouchPoint other) { mPathIndex = other.mPathIndex; mIsStartOfPath = other.mIsStartOfPath; @@ -317,12 +343,94 @@ public final class GestureDescription { mX = other.mX; mY = other.mY; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mPathIndex); + int startEnd = mIsStartOfPath ? FLAG_IS_START_OF_PATH : 0; + startEnd |= mIsEndOfPath ? FLAG_IS_END_OF_PATH : 0; + dest.writeInt(startEnd); + dest.writeFloat(mX); + dest.writeFloat(mY); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public TouchPoint createFromParcel(Parcel in) { + return new TouchPoint(in); + } + + public TouchPoint[] newArray(int size) { + return new TouchPoint[size]; + } + }; + } + + /** + * A step along a gesture. Contains all of the touch points at a particular time + * + * @hide + */ + public static class GestureStep implements Parcelable { + public long timeSinceGestureStart; + public int numTouchPoints; + public TouchPoint[] touchPoints; + + public GestureStep(long timeSinceGestureStart, int numTouchPoints, + TouchPoint[] touchPointsToCopy) { + this.timeSinceGestureStart = timeSinceGestureStart; + this.numTouchPoints = numTouchPoints; + this.touchPoints = new TouchPoint[numTouchPoints]; + for (int i = 0; i < numTouchPoints; i++) { + this.touchPoints[i] = new TouchPoint(touchPointsToCopy[i]); + } + } + + public GestureStep(Parcel parcel) { + timeSinceGestureStart = parcel.readLong(); + Parcelable[] parcelables = + parcel.readParcelableArray(TouchPoint.class.getClassLoader()); + numTouchPoints = (parcelables == null) ? 0 : parcelables.length; + touchPoints = new TouchPoint[numTouchPoints]; + for (int i = 0; i < numTouchPoints; i++) { + touchPoints[i] = (TouchPoint) parcelables[i]; + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(timeSinceGestureStart); + dest.writeParcelableArray(touchPoints, flags); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public GestureStep createFromParcel(Parcel in) { + return new GestureStep(in); + } + + public GestureStep[] newArray(int size) { + return new GestureStep[size]; + } + }; } /** * Class to convert a GestureDescription to a series of MotionEvents. + * + * @hide */ - static class MotionEventGenerator { + public static class MotionEventGenerator { /** * Constants used to initialize all MotionEvents */ @@ -341,38 +449,52 @@ public final class GestureDescription { private static PointerCoords[] sPointerCoords; private static PointerProperties[] sPointerProps; - static List getMotionEventsFromGestureDescription( + static List getGestureStepsFromGestureDescription( GestureDescription description, int sampleTimeMs) { - final List motionEvents = new ArrayList<>(); + final List gestureSteps = new ArrayList<>(); // Point data at each time we generate an event for final TouchPoint[] currentTouchPoints = getCurrentTouchPoints(description.getStrokeCount()); - // Point data sent in last touch event - int lastTouchPointSize = 0; - final TouchPoint[] lastTouchPoints = - getLastTouchPoints(description.getStrokeCount()); - + int currentTouchPointSize = 0; /* Loop through each time slice where there are touch points */ long timeSinceGestureStart = 0; long nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart); while (nextKeyPointTime >= 0) { - timeSinceGestureStart = (lastTouchPointSize == 0) ? nextKeyPointTime + timeSinceGestureStart = (currentTouchPointSize == 0) ? nextKeyPointTime : Math.min(nextKeyPointTime, timeSinceGestureStart + sampleTimeMs); - int currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart, + currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart, currentTouchPoints); + gestureSteps.add(new GestureStep(timeSinceGestureStart, currentTouchPointSize, + currentTouchPoints)); + + /* Move to next time slice */ + nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1); + } + return gestureSteps; + } + + public static List getMotionEventsFromGestureSteps(List steps) { + final List motionEvents = new ArrayList<>(); + + // Number of points in last touch event + int lastTouchPointSize = 0; + TouchPoint[] lastTouchPoints; + + for (int i = 0; i < steps.size(); i++) { + GestureStep step = steps.get(i); + int currentTouchPointSize = step.numTouchPoints; + lastTouchPoints = getLastTouchPoints( + Math.max(lastTouchPointSize, currentTouchPointSize)); appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize, - currentTouchPoints, currentTouchPointSize, timeSinceGestureStart); + step.touchPoints, currentTouchPointSize, step.timeSinceGestureStart); lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints, - lastTouchPointSize, currentTouchPoints, currentTouchPointSize, - timeSinceGestureStart); + lastTouchPointSize, step.touchPoints, currentTouchPointSize, + step.timeSinceGestureStart); lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints, - lastTouchPointSize, currentTouchPoints, currentTouchPointSize, - timeSinceGestureStart); - - /* Move to next time slice */ - nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1); + lastTouchPointSize, step.touchPoints, currentTouchPointSize, + step.timeSinceGestureStart); } return motionEvents; } diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl index 7a55079d3ecf2eb50b9db5d947c040074e27ef06..81cddbac3f53b2f69280584f9357344882db1ded 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl @@ -88,5 +88,5 @@ interface IAccessibilityServiceConnection { void setSoftKeyboardCallbackEnabled(boolean enabled); - void sendMotionEvents(int sequence, in ParceledListSlice events); + void sendGesture(int sequence, in ParceledListSlice gestureSteps); } diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java index 7b83a3076db336d53bb8d3eef65eb799ed96ff39..b6e85f18a69525e6d35ee20d70d0ae6ae11c9015 100644 --- a/core/java/android/accounts/Account.java +++ b/core/java/android/accounts/Account.java @@ -16,9 +16,19 @@ package android.accounts; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; import android.os.Parcelable; import android.os.Parcel; +import android.os.RemoteException; +import android.os.ServiceManager; import android.text.TextUtils; +import android.util.ArraySet; +import android.util.Log; +import com.android.internal.annotations.GuardedBy; + +import java.util.Set; /** * Value type that represents an Account in the {@link AccountManager}. This object is @@ -26,8 +36,14 @@ import android.text.TextUtils; * suitable for use as the key of a {@link java.util.Map} */ public class Account implements Parcelable { + private static final String TAG = "Account"; + + @GuardedBy("sAccessedAccounts") + private static final Set sAccessedAccounts = new ArraySet<>(); + public final String name; public final String type; + private final @Nullable String accessId; public boolean equals(Object o) { if (o == this) return true; @@ -44,6 +60,20 @@ public class Account implements Parcelable { } public Account(String name, String type) { + this(name, type, null); + } + + /** + * @hide + */ + public Account(@NonNull Account other, @NonNull String accessId) { + this(other.name, other.type, accessId); + } + + /** + * @hide + */ + public Account(String name, String type, String accessId) { if (TextUtils.isEmpty(name)) { throw new IllegalArgumentException("the name must not be empty: " + name); } @@ -52,11 +82,31 @@ public class Account implements Parcelable { } this.name = name; this.type = type; + this.accessId = accessId; } public Account(Parcel in) { this.name = in.readString(); this.type = in.readString(); + this.accessId = in.readString(); + if (accessId != null) { + synchronized (sAccessedAccounts) { + if (sAccessedAccounts.add(this)) { + try { + IAccountManager accountManager = IAccountManager.Stub.asInterface( + ServiceManager.getService(Context.ACCOUNT_SERVICE)); + accountManager.onAccountAccessed(accessId); + } catch (RemoteException e) { + Log.e(TAG, "Error noting account access", e); + } + } + } + } + } + + /** @hide */ + public String getAccessId() { + return accessId; } public int describeContents() { @@ -66,6 +116,7 @@ public class Account implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeString(type); + dest.writeString(accessId); } public static final Creator CREATOR = new Creator() { diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 5cf59bc4760db8987131657ec8aa6f9987521477..cabaf85b37c35750e1120df52a349cb81ff7db14 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -28,6 +28,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.IntentSender; import android.content.res.Resources; import android.database.SQLException; import android.os.Build; @@ -177,6 +178,14 @@ public class AccountManager { */ public static final String KEY_ACCOUNT_TYPE = "accountType"; + /** + * Bundle key used for the account access id used for noting the + * account was accessed when unmarshalled from a parcel. + * + * @hide + */ + public static final String KEY_ACCOUNT_ACCESS_ID = "accountAccessId"; + /** * Bundle key used for the auth token value in results * from {@link #getAuthToken} and friends. @@ -265,6 +274,15 @@ public class AccountManager { "android.accounts.AccountAuthenticator"; public static final String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator"; + /** + * Token type for the special case where a UID has access only to an account + * but no authenticator specific auth token types. + * + * @hide + */ + public static final String ACCOUNT_ACCESS_TOKEN_TYPE = + "com.android.AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE"; + private final Context mContext; private final IAccountManager mService; private final Handler mMainHandler; @@ -803,7 +821,8 @@ public class AccountManager { public Account bundleToResult(Bundle bundle) throws AuthenticatorException { String name = bundle.getString(KEY_ACCOUNT_NAME); String type = bundle.getString(KEY_ACCOUNT_TYPE); - return new Account(name, type); + String accessId = bundle.getString(KEY_ACCOUNT_ACCESS_ID); + return new Account(name, type, accessId); } }.start(); } @@ -2263,6 +2282,7 @@ public class AccountManager { result.putString(KEY_ACCOUNT_NAME, null); result.putString(KEY_ACCOUNT_TYPE, null); result.putString(KEY_AUTHTOKEN, null); + result.putBinder(KEY_ACCOUNT_ACCESS_ID, null); try { mResponse.onResult(result); } catch (RemoteException e) { @@ -2288,9 +2308,11 @@ public class AccountManager { public void onResult(Bundle value) throws RemoteException { Account account = new Account( value.getString(KEY_ACCOUNT_NAME), - value.getString(KEY_ACCOUNT_TYPE)); - mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions, - mActivity, mMyCallback, mHandler); + value.getString(KEY_ACCOUNT_TYPE), + value.getString(KEY_ACCOUNT_ACCESS_ID)); + mFuture = getAuthToken(account, mAuthTokenType, + mLoginOptions, mActivity, mMyCallback, + mHandler); } @Override @@ -2337,7 +2359,8 @@ public class AccountManager { setException(new AuthenticatorException("account not in result")); return; } - final Account account = new Account(accountName, accountType); + final String accessId = result.getString(KEY_ACCOUNT_ACCESS_ID); + final Account account = new Account(accountName, accountType, accessId); mNumAccounts = 1; getAuthToken(account, mAuthTokenType, null /* options */, mActivity, mMyCallback, mHandler); @@ -2680,8 +2703,6 @@ public class AccountManager { *
    *
  • {@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for * adding the the to the device later. - *
  • {@link #KEY_PASSWORD} - optional, the password or password - * hash of the account. *
  • {@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check * status of the account *
@@ -2769,8 +2790,6 @@ public class AccountManager { *
    *
  • {@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for * updating the local credentials on device later. - *
  • {@link #KEY_PASSWORD} - optional, the password or password - * hash of the account *
  • {@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check * status of the account *
@@ -2964,4 +2983,49 @@ public class AccountManager { } }.start(); } + + /** + * Gets whether a given package under a user has access to an account. + * Can be called only from the system UID. + * + * @param account The account for which to check. + * @param packageName The package for which to check. + * @param userHandle The user for which to check. + * @return True if the package can access the account. + * + * @hide + */ + public boolean hasAccountAccess(@NonNull Account account, @NonNull String packageName, + @NonNull UserHandle userHandle) { + try { + return mService.hasAccountAccess(account, packageName, userHandle); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Creates an intent to request access to a given account for a UID. + * The returned intent should be stated for a result where {@link + * Activity#RESULT_OK} result means access was granted whereas {@link + * Activity#RESULT_CANCELED} result means access wasn't granted. Can + * be called only from the system UID. + * + * @param account The account for which to request. + * @param packageName The package name which to request. + * @param userHandle The user for which to request. + * @return The intent to request account access or null if the package + * doesn't exist. + * + * @hide + */ + public IntentSender createRequestAccountAccessIntentSenderAsUser(@NonNull Account account, + @NonNull String packageName, @NonNull UserHandle userHandle) { + try { + return mService.createRequestAccountAccessIntentSenderAsUser(account, packageName, + userHandle); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/accounts/AccountManagerInternal.java b/core/java/android/accounts/AccountManagerInternal.java new file mode 100644 index 0000000000000000000000000000000000000000..68c17c32fdc3e9c9e9db64976236218d17a35a79 --- /dev/null +++ b/core/java/android/accounts/AccountManagerInternal.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.accounts; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.os.RemoteCallback; + +/** + * Account manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class AccountManagerInternal { + + /** + * Listener for explicit UID account access grant changes. + */ + public interface OnAppPermissionChangeListener { + + /** + * Called when the explicit grant state for a given UID to + * access an account changes. + * + * @param account The account + * @param uid The UID for which the grant changed + */ + public void onAppPermissionChanged(Account account, int uid); + } + + /** + * Requests that a given package is given access to an account. + * The provided callback will be invoked with a {@link android.os.Bundle} + * containing the result which will be a boolean value mapped to the + * {@link AccountManager#KEY_BOOLEAN_RESULT} key. + * + * @param account The account for which to request. + * @param packageName The package name for which to request. + * @param userId Concrete user id for which to request. + * @param callback A callback for receiving the result. + */ + public abstract void requestAccountAccess(@NonNull Account account, + @NonNull String packageName, @IntRange(from = 0) int userId, + @NonNull RemoteCallback callback); + + /** + * Check whether the given UID has access to the account. + * + * @param account The account + * @param uid The UID + * @return Whether the UID can access the account + */ + public abstract boolean hasAccountAccess(@NonNull Account account, @IntRange(from = 0) int uid); + + /** + * Adds a listener for explicit UID account access grant changes. + * + * @param listener The listener + */ + public abstract void addOnAppPermissionChangeListener( + @NonNull OnAppPermissionChangeListener listener); + + /** + * Backups the account access permissions. + * @param userId The user for which to backup. + * @return The backup data. + */ + public abstract byte[] backupAccountAccessPermissions(int userId); + + /** + * Restores the account access permissions. + * @param data The restore data. + * @param userId The user for which to restore. + */ + public abstract void restoreAccountAccessPermissions(byte[] data, int userId); +} diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 133df2bfa16aadafaf5d9baa69cf0151d6edb4e7..aed7a36937177c6c01f57536625c7455372b9901 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -399,7 +399,7 @@ public class ChooseTypeAndAccountActivity extends Activity * useless. */ private void setNonLabelThemeAndCallSuperCreate(Bundle savedInstanceState) { - setTheme(R.style.Theme_Material_Light_Dialog_NoActionBar); + setTheme(R.style.Theme_DeviceDefault_Light_Dialog_NoActionBar); super.onCreate(savedInstanceState); } diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java index 12b2b9ccf1480c8d8e6c93c6ebda1ad5bb259aec..38eab290502259c1085b130c93998baa8699b648 100644 --- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java +++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java @@ -35,12 +35,10 @@ import java.io.IOException; */ public class GrantCredentialsPermissionActivity extends Activity implements View.OnClickListener { public static final String EXTRAS_ACCOUNT = "account"; - public static final String EXTRAS_AUTH_TOKEN_LABEL = "authTokenLabel"; public static final String EXTRAS_AUTH_TOKEN_TYPE = "authTokenType"; public static final String EXTRAS_RESPONSE = "response"; - public static final String EXTRAS_ACCOUNT_TYPE_LABEL = "accountTypeLabel"; - public static final String EXTRAS_PACKAGES = "application"; public static final String EXTRAS_REQUESTING_UID = "uid"; + private Account mAccount; private String mAuthTokenType; private int mUid; @@ -109,7 +107,11 @@ public class GrantCredentialsPermissionActivity extends Activity implements View } } }; - AccountManager.get(this).getAuthTokenLabel(mAccount.type, mAuthTokenType, callback, null); + + if (!AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE.equals(mAuthTokenType)) { + AccountManager.get(this).getAuthTokenLabel(mAccount.type, + mAuthTokenType, callback, null); + } findViewById(R.id.allow_button).setOnClickListener(this); findViewById(R.id.deny_button).setOnClickListener(this); diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 7199288426f2a2fbc638da1d7f846ea38bec267c..c271e7ebc52c8cd051404d8ed67b6304e0c47536 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -19,8 +19,10 @@ package android.accounts; import android.accounts.IAccountManagerResponse; import android.accounts.Account; import android.accounts.AuthenticatorDescription; +import android.content.IntentSender; import android.os.Bundle; - +import android.os.RemoteCallback; +import android.os.UserHandle; /** * Central application service that provides account management. @@ -102,4 +104,12 @@ interface IAccountManager { /* Check if credentials update is suggested */ void isCredentialsUpdateSuggested(in IAccountManagerResponse response, in Account account, String statusToken); + + /* Check if the package in a user can access an account */ + boolean hasAccountAccess(in Account account, String packageName, in UserHandle userHandle); + /* Crate an intent to request account access for package and a given user id */ + IntentSender createRequestAccountAccessIntentSenderAsUser(in Account account, + String packageName, in UserHandle userHandle); + + void onAccountAccessed(String token); } diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 7841d29b5700dc9f59897121394040826e5290dd..053ba7d5fa0ad276c10c5641d2a716eaebab7e23 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -1064,15 +1064,15 @@ public final class AnimatorSet extends Animator { /** * @hide * TODO: For animatorSet defined in XML, we can use a flag to indicate what the play order - * if defined (i.e. sequential or together), then we can use the flag instead of calculate - * dynamically. + * if defined (i.e. sequential or together), then we can use the flag instead of calculating + * dynamically. Note that when AnimatorSet is empty this method returns true. * @return whether all the animators in the set are supposed to play together */ public boolean shouldPlayTogether() { updateAnimatorsDuration(); createDependencyGraph(); // All the child nodes are set out to play right after the delay animation - return mRootNode.mChildNodes.size() == mNodes.size() - 1; + return mRootNode.mChildNodes == null || mRootNode.mChildNodes.size() == mNodes.size() - 1; } @Override diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java index cdd72be76805a2c57845a1e771a409ae3e53dd8b..5a23fddf1d5128bb2497663f5fa73d40826cca26 100644 --- a/core/java/android/animation/LayoutTransition.java +++ b/core/java/android/animation/LayoutTransition.java @@ -62,7 +62,11 @@ import java.util.Map; * layout will run (closing the gap created in the layout when the item was removed). If this * default choreography behavior is not desired, the {@link #setDuration(int, long)} and * {@link #setStartDelay(int, long)} of any or all of the animations can be changed as - * appropriate.

+ * appropriate. Keep in mind, however, that if you start an APPEARING animation before a + * DISAPPEARING animation is completed, the DISAPPEARING animation stops, and any effects from + * the DISAPPEARING animation are reverted. If you instead start a DISAPPEARING animation + * before an APPEARING animation is completed, a similar set of effects occurs for the + * APPEARING animation.

* *

The animations specified for the transition, both the defaults and any custom animations * set on the transition object, are templates only. That is, these animations exist to hold the diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index 5c4b979ccb3cb1159634758feb2b1778fe3a82c5..0c21c4ff55e7a7c0907af540d4c968db4febf645 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -978,7 +978,8 @@ public final class ObjectAnimator extends ValueAnimator { void animateValue(float fraction) { final Object target = getTarget(); if (mTarget != null && target == null) { - // We lost the target reference, cancel and clean up. + // We lost the target reference, cancel and clean up. Note: we allow null target if the + /// target has never been set. cancel(); return; } diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 224823ee2ff11afc9aef9d9876a25716c22667de..ba16e673ea6991f0f5b6a6a73163cf5655a01f9e 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -1095,8 +1095,12 @@ public class PropertyValuesHolder implements Cloneable { } // TODO: We need a better way to get data out of keyframes. if (mKeyframes instanceof PathKeyframes.FloatKeyframesBase - || mKeyframes instanceof PathKeyframes.IntKeyframesBase) { - // property values will animate based on external data source (e.g. Path) + || mKeyframes instanceof PathKeyframes.IntKeyframesBase + || (mKeyframes.getKeyframes() != null && mKeyframes.getKeyframes().size() > 2)) { + // When a pvh has more than 2 keyframes, that means there are intermediate values in + // addition to start/end values defined for animators. Another case where such + // intermediate values are defined is when animator has a path to animate along. In + // these cases, a data source is needed to capture these intermediate values. values.dataSource = new PropertyValues.DataSource() { @Override public Object getValueAtFraction(float fraction) { @@ -1108,6 +1112,13 @@ public class PropertyValuesHolder implements Cloneable { } } + /** + * @hide + */ + public Class getValueType() { + return mValueType; + } + @Override public String toString() { return mPropertyName + ": " + mKeyframes.toString(); @@ -1177,6 +1188,15 @@ public class PropertyValuesHolder implements Cloneable { } } + @Override + public void setProperty(Property property) { + if (property instanceof IntProperty) { + mIntProperty = (IntProperty) property; + } else { + super.setProperty(property); + } + } + @Override public void setIntValues(int... values) { super.setIntValues(values); @@ -1315,6 +1335,15 @@ public class PropertyValuesHolder implements Cloneable { } } + @Override + public void setProperty(Property property) { + if (property instanceof FloatProperty) { + mFloatProperty = (FloatProperty) property; + } else { + super.setProperty(property); + } + } + @Override public void setFloatValues(float... values) { super.setFloatValues(values); @@ -1516,7 +1545,7 @@ public class PropertyValuesHolder implements Cloneable { } propertyMap.put(mPropertyName, mJniSetter); } - } + } } } diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index 0c7ee2c8c2fec4453a325748e499121a0d0ab3bf..7e16e3ece5495583d979b18ba2fbd5c2f9b44bd2 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -18,6 +18,7 @@ package android.animation; import android.annotation.CallSuper; import android.annotation.IntDef; +import android.annotation.TestApi; import android.os.Looper; import android.os.Trace; import android.util.AndroidRuntimeException; @@ -261,6 +262,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio /** * @hide */ + @TestApi public static void setDurationScale(float durationScale) { sDurationScale = durationScale; } @@ -268,6 +270,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio /** * @hide */ + @TestApi public static float getDurationScale() { return sDurationScale; } @@ -982,6 +985,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio mStarted = true; mPaused = false; mRunning = false; + mAnimationEndRequested = false; // Resets mLastFrameTime when start() is called, so that if the animation was running, // calling start() would put the animation in the // started-but-not-yet-reached-the-first-frame phase. diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index ae3e0ce201a4856904827f7a104dd85d3898e54d..e4880b0f6a43b817c18585a1492c23b9249b8058 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -175,11 +175,11 @@ import java.util.List; * part of the platform's application model. For a detailed perspective on the structure of an * Android application and how activities behave, please read the * Application Fundamentals and - * Tasks and Back Stack + * Tasks and Back Stack * developer guides.

* *

You can also find a detailed discussion about how to create activities in the - * Activities + * Activities * developer guide.

* * @@ -3366,7 +3366,7 @@ public class Activity extends ContextThemeWrapper * should override the method {@link #onPrepareNavigateUpTaskStack(TaskStackBuilder)} * to supply those arguments.

* - *

See Tasks and Back Stack + *

See Tasks and Back Stack * from the developer guide and Navigation * from the design guide for more information about navigating within your app.

* @@ -4220,6 +4220,7 @@ public class Activity extends ContextThemeWrapper public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { + options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, @@ -4268,6 +4269,17 @@ public class Activity extends ContextThemeWrapper } } + private Bundle transferSpringboardActivityOptions(Bundle options) { + if (options == null && (mWindow != null && !mWindow.isActive())) { + final ActivityOptions activityOptions = getActivityOptions(); + if (activityOptions != null && + activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { + return activityOptions.toBundle(); + } + } + return options; + } + /** * @hide Implement to provide correct calling token. */ @@ -4283,6 +4295,7 @@ public class Activity extends ContextThemeWrapper if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } + options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options, user); @@ -4318,6 +4331,7 @@ public class Activity extends ContextThemeWrapper if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } + options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, @@ -4350,6 +4364,7 @@ public class Activity extends ContextThemeWrapper if (mParent != null) { throw new RuntimeException("Can't be called from a child"); } + options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivityAsCaller( this, mMainThread.getApplicationThread(), mToken, this, @@ -4467,7 +4482,7 @@ public class Activity extends ContextThemeWrapper * * @throws android.content.ActivityNotFoundException * - * @see {@link #startActivity(Intent, Bundle)} + * @see #startActivity(Intent, Bundle) * @see #startActivityForResult */ @Override @@ -4494,7 +4509,7 @@ public class Activity extends ContextThemeWrapper * * @throws android.content.ActivityNotFoundException * - * @see {@link #startActivity(Intent)} + * @see #startActivity(Intent) * @see #startActivityForResult */ @Override @@ -4516,7 +4531,7 @@ public class Activity extends ContextThemeWrapper * * @throws android.content.ActivityNotFoundException * - * @see {@link #startActivities(Intent[], Bundle)} + * @see #startActivities(Intent[], Bundle) * @see #startActivityForResult */ @Override @@ -4543,7 +4558,7 @@ public class Activity extends ContextThemeWrapper * * @throws android.content.ActivityNotFoundException * - * @see {@link #startActivities(Intent[])} + * @see #startActivities(Intent[]) * @see #startActivityForResult */ @Override @@ -4789,6 +4804,7 @@ public class Activity extends ContextThemeWrapper */ public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { + options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, child, @@ -4854,6 +4870,7 @@ public class Activity extends ContextThemeWrapper if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } + options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, who, @@ -4923,7 +4940,7 @@ public class Activity extends ContextThemeWrapper *

As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN} an alternative * to using this with starting activities is to supply the desired animation * information through a {@link ActivityOptions} bundle to - * {@link #startActivity(Intent, Bundle) or a related function. This allows + * {@link #startActivity(Intent, Bundle)} or a related function. This allows * you to specify a custom animation even when starting an activity from * outside the context of the current top activity. * @@ -6105,7 +6122,6 @@ public class Activity extends ContextThemeWrapper * the return value must be checked. * * @see #onVisibleBehindCanceled() - * @see #onBackgroundVisibleBehindChanged(boolean) */ public boolean requestVisibleBehind(boolean visible) { if (!mResumed) { @@ -6133,7 +6149,6 @@ public class Activity extends ContextThemeWrapper * process. Otherwise {@link #onStop()} will be called following return. * * @see #requestVisibleBehind(boolean) - * @see #onBackgroundVisibleBehindChanged(boolean) */ @CallSuper public void onVisibleBehindCanceled() { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 31fe39027fb0db743d221aa5c0675f2d77836e6b..af981f69d3b6a775d068e827f5423b6779ae4164 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -93,7 +93,8 @@ public class ActivityManager { @IntDef({ BUGREPORT_OPTION_FULL, BUGREPORT_OPTION_INTERACTIVE, - BUGREPORT_OPTION_REMOTE + BUGREPORT_OPTION_REMOTE, + BUGREPORT_OPTION_WEAR }) public @interface BugreportMode {} /** @@ -114,6 +115,11 @@ public class ActivityManager { * @hide */ public static final int BUGREPORT_OPTION_REMOTE = 2; + /** + * Takes a bugreport on a wearable device. + * @hide + */ + public static final int BUGREPORT_OPTION_WEAR = 3; /** * {@code @@ -1507,7 +1513,7 @@ public class ActivityManager { throws SecurityException { try { return ActivityManagerNative.getDefault().getRecentTasks(maxNum, - flags, UserHandle.myUserId()); + flags, UserHandle.myUserId()).getList(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1532,7 +1538,7 @@ public class ActivityManager { throws SecurityException { try { return ActivityManagerNative.getDefault().getRecentTasks(maxNum, - flags, userId); + flags, userId).getList(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3624,6 +3630,24 @@ public class ActivityManager { } } + /** + * Enable more aggressive scheduling for latency-sensitive low-runtime VR threads. Only one + * thread can be a VR thread in a process at a time, and that thread may be subject to + * restrictions on the amount of time it can run. + * + * To reset the VR thread for an application, a tid of 0 can be passed. + * + * @see android.os.Process#myTid() + * @param tid tid of the VR thread + */ + public static void setVrThread(int tid) { + try { + ActivityManagerNative.getDefault().setVrThread(tid); + } catch (RemoteException e) { + // pass + } + } + /** * The AppTask allows you to manage your own application's tasks. * See {@link android.app.ActivityManager#getAppTasks()} diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 3a70a4cd4b99d8bc53844850db2b0cf6a13a3a11..0ba937a3f16b2028cc38ec59b6ed4c027fb32f50 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -19,6 +19,9 @@ package android.app; import android.annotation.NonNull; import android.content.ComponentName; import android.content.IIntentSender; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; import android.os.IBinder; import android.service.voice.IVoiceInteractionSession; @@ -151,4 +154,29 @@ public abstract class ActivityManagerInternal { * such as Power Save mode. */ public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration); + + /** + * Updates and persists the {@link Configuration} for a given user. + * + * @param values the configuration to update + * @param userId the user to update the configuration for + */ + public abstract void updatePersistentConfigurationForUser(@NonNull Configuration values, + int userId); + + /** + * Start activity {@code intents} as if {@code packageName} on user {@code userId} did it. + * + * @return error codes used by {@link IActivityManager#startActivity} and its siblings. + */ + public abstract int startActivitiesAsPackage(String packageName, + int userId, Intent[] intents, Bundle bOptions); + + /** + * Get the procstate for the UID. The return value will be between + * {@link ActivityManager#MIN_PROCESS_STATE} and {@link ActivityManager#MAX_PROCESS_STATE}. + * Note if the UID doesn't exist, it'll return {@link ActivityManager#PROCESS_STATE_NONEXISTENT} + * (-1). + */ + public abstract int getUidProcessState(int uid); } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index cf5240b581ae760033120eabf89507f43a430efb..50479c8e951bf21ee406a8450663b417635ec83c 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -683,10 +683,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM int maxNum = data.readInt(); int fl = data.readInt(); int userId = data.readInt(); - List list = getRecentTasks(maxNum, + ParceledListSlice list = getRecentTasks(maxNum, fl, userId); reply.writeNoException(); - reply.writeTypedList(list); + list.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); return true; } @@ -2371,7 +2371,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface( data.readStrongBinder()); - registerUserSwitchObserver(observer); + String name = data.readString(); + registerUserSwitchObserver(observer, name); reply.writeNoException(); return true; } @@ -2995,6 +2996,35 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeInt(result); return true; } + case SET_VR_THREAD_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + final int tid = data.readInt(); + setVrThread(tid); + reply.writeNoException(); + return true; + } + case SET_RENDER_THREAD_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + final int tid = data.readInt(); + setRenderThread(tid); + reply.writeNoException(); + return true; + } + case SET_HAS_TOP_UI: { + data.enforceInterface(IActivityManager.descriptor); + final boolean hasTopUi = data.readInt() != 0; + setHasTopUi(hasTopUi); + reply.writeNoException(); + return true; + } + case CAN_BYPASS_WORK_CHALLENGE: { + data.enforceInterface(IActivityManager.descriptor); + final PendingIntent intent = PendingIntent.CREATOR.createFromParcel(data); + final boolean result = canBypassWorkChallenge(intent); + reply.writeNoException(); + reply.writeInt(result ? 1 : 0); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -3740,7 +3770,7 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); return list; } - public List getRecentTasks(int maxNum, + public ParceledListSlice getRecentTasks(int maxNum, int flags, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -3750,8 +3780,8 @@ class ActivityManagerProxy implements IActivityManager data.writeInt(userId); mRemote.transact(GET_RECENT_TASKS_TRANSACTION, data, reply, 0); reply.readException(); - ArrayList list - = reply.createTypedArrayList(ActivityManager.RecentTaskInfo.CREATOR); + final ParceledListSlice list = ParceledListSlice.CREATOR + .createFromParcel(reply); data.recycle(); reply.recycle(); return list; @@ -6060,11 +6090,13 @@ class ActivityManagerProxy implements IActivityManager return result; } - public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException { + public void registerUserSwitchObserver(IUserSwitchObserver observer, + String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(observer != null ? observer.asBinder() : null); + data.writeString(name); mRemote.transact(REGISTER_USER_SWITCH_OBSERVER_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); @@ -7028,5 +7060,59 @@ class ActivityManagerProxy implements IActivityManager return res; } + @Override + public void setVrThread(int tid) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(tid); + mRemote.transact(SET_VR_THREAD_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + return; + } + + public void setRenderThread(int tid) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(tid); + mRemote.transact(SET_RENDER_THREAD_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + return; + } + + public void setHasTopUi(boolean hasTopUi) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(hasTopUi ? 1 : 0); + mRemote.transact(SET_HAS_TOP_UI, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + return; + } + @Override + public boolean canBypassWorkChallenge(PendingIntent intent) + throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + intent.writeToParcel(data, 0); + mRemote.transact(CAN_BYPASS_WORK_CHALLENGE, data, reply, 0); + reply.readException(); + final int result = reply.readInt(); + data.recycle(); + reply.recycle(); + return result != 0; + } + private IBinder mRemote; } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 4c8ddc7eb6b139bdfec6d15ce4661660dad9c9c6..d9a46903ee38e514e18a8a08cd6e65689ef03958 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -31,10 +31,13 @@ import android.os.IRemoteCallback; import android.os.Parcelable; import android.os.RemoteException; import android.os.ResultReceiver; +import android.transition.Transition; +import android.transition.TransitionManager; import android.util.Pair; import android.util.Slog; import android.view.AppTransitionAnimationSpec; import android.view.View; +import android.view.ViewGroup; import android.view.Window; import java.util.ArrayList; @@ -190,6 +193,7 @@ public class ActivityOptions { = "android:activity.exitCoordinatorIndex"; private static final String KEY_USAGE_TIME_REPORT = "android:activity.usageTimeReport"; + private static final String KEY_ROTATION_ANIMATION_HINT = "android:activity.rotationAnimationHint"; /** @hide */ public static final int ANIM_NONE = 0; @@ -241,6 +245,7 @@ public class ActivityOptions { private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; private boolean mTaskOverlay; private AppTransitionAnimationSpec mAnimSpecs[]; + private int mRotationAnimationHint = -1; /** * Create an ActivityOptions specifying a custom animation to run when @@ -640,10 +645,71 @@ public class ActivityOptions { public static ActivityOptions makeSceneTransitionAnimation(Activity activity, Pair... sharedElements) { ActivityOptions opts = new ActivityOptions(); - if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { - opts.mAnimationType = ANIM_DEFAULT; + makeSceneTransitionAnimation(activity, activity.getWindow(), opts, + activity.mExitTransitionListener, sharedElements); + return opts; + } + + /** + * Call this immediately prior to startActivity to begin a shared element transition + * from a non-Activity. The window must support Window.FEATURE_ACTIVITY_TRANSITIONS. + * The exit transition will start immediately and the shared element transition will + * start once the launched Activity's shared element is ready. + *

+ * When all transitions have completed and the shared element has been transfered, + * the window's decor View will have its visibility set to View.GONE. + * + * @hide + */ + @SafeVarargs + public static ActivityOptions startSharedElementAnimation(Window window, + Pair... sharedElements) { + ActivityOptions opts = new ActivityOptions(); + final View decorView = window.getDecorView(); + if (decorView == null) { return opts; } + final ExitTransitionCoordinator exit = + makeSceneTransitionAnimation(null, window, opts, null, sharedElements); + if (exit != null) { + HideWindowListener listener = new HideWindowListener(window, exit); + exit.setHideSharedElementsCallback(listener); + exit.startExit(); + } + return opts; + } + + /** + * This method should be called when the {@link #startSharedElementAnimation(Window, Pair[])} + * animation must be stopped and the Views reset. This can happen if there was an error + * from startActivity or a springboard activity and the animation should stop and reset. + * + * @hide + */ + public static void stopSharedElementAnimation(Window window) { + final View decorView = window.getDecorView(); + if (decorView == null) { + return; + } + final ExitTransitionCoordinator exit = (ExitTransitionCoordinator) + decorView.getTag(com.android.internal.R.id.cross_task_transition); + if (exit != null) { + exit.cancelPendingTransitions(); + decorView.setTagInternal(com.android.internal.R.id.cross_task_transition, null); + TransitionManager.endTransitions((ViewGroup) decorView); + exit.resetViews(); + exit.clearState(); + decorView.setVisibility(View.VISIBLE); + } + } + + static ExitTransitionCoordinator makeSceneTransitionAnimation(Activity activity, Window window, + ActivityOptions opts, SharedElementCallback callback, + Pair[] sharedElements) { + if (!window.hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { + opts.mAnimationType = ANIM_DEFAULT; + return null; + } opts.mAnimationType = ANIM_SCENE_TRANSITION; ArrayList names = new ArrayList(); @@ -665,18 +731,22 @@ public class ActivityOptions { } } - ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, names, names, - views, false); + ExitTransitionCoordinator exit = new ExitTransitionCoordinator(activity, window, + callback, names, names, views, false); opts.mTransitionReceiver = exit; opts.mSharedElementNames = names; - opts.mIsReturning = false; - opts.mExitCoordinatorIndex = - activity.mActivityTransitionState.addExitTransitionCoordinator(exit); - return opts; + opts.mIsReturning = (activity == null); + if (activity == null) { + opts.mExitCoordinatorIndex = -1; + } else { + opts.mExitCoordinatorIndex = + activity.mActivityTransitionState.addExitTransitionCoordinator(exit); + } + return exit; } /** @hide */ - public static ActivityOptions makeSceneTransitionAnimation(Activity activity, + static ActivityOptions makeSceneTransitionAnimation(Activity activity, ExitTransitionCoordinator exitCoordinator, ArrayList sharedElementNames, int resultCode, Intent resultData) { ActivityOptions opts = new ActivityOptions(); @@ -795,6 +865,7 @@ public class ActivityOptions { mAnimationFinishedListener = IRemoteCallback.Stub.asInterface( opts.getBinder(KEY_ANIMATION_FINISHED_LISTENER)); } + mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT); } /** @@ -900,6 +971,16 @@ public class ActivityOptions { return mIsReturning; } + /** + * Returns whether or not the ActivityOptions was created with + * {@link #startSharedElementAnimation(Window, Pair[])}. + * + * @hide + */ + boolean isCrossTask() { + return mExitCoordinatorIndex < 0; + } + /** @hide */ public ArrayList getSharedElementNames() { return mSharedElementNames; @@ -1138,6 +1219,7 @@ public class ActivityOptions { if (mAnimationFinishedListener != null) { b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder()); } + b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint); return b; } @@ -1184,6 +1266,27 @@ public class ActivityOptions { return null; } + /** + * Returns the rotation animation set by {@link setRotationAnimationHint} or -1 + * if unspecified. + * @hide + */ + public int getRotationAnimationHint() { + return mRotationAnimationHint; + } + + + /** + * Set a rotation animation to be used if launching the activity + * triggers an orientation change, or -1 to clear. See + * {@link android.view.WindowManager.LayoutParams} for rotation + * animation values. + * @hide + */ + public void setRotationAnimationHint(int hint) { + mRotationAnimationHint = hint; + } + /** @hide */ @Override public String toString() { @@ -1191,4 +1294,65 @@ public class ActivityOptions { + ", mAnimationType=" + mAnimationType + ", mStartX=" + mStartX + ", mStartY=" + mStartY + ", mWidth=" + mWidth + ", mHeight=" + mHeight; } + + private static class HideWindowListener extends Transition.TransitionListenerAdapter + implements ExitTransitionCoordinator.HideSharedElementsCallback { + private final Window mWindow; + private final ExitTransitionCoordinator mExit; + private final boolean mWaitingForTransition; + private boolean mTransitionEnded; + private boolean mSharedElementHidden; + private ArrayList mSharedElements; + + public HideWindowListener(Window window, ExitTransitionCoordinator exit) { + mWindow = window; + mExit = exit; + mSharedElements = new ArrayList<>(exit.mSharedElements); + Transition transition = mWindow.getExitTransition(); + if (transition != null) { + transition.addListener(this); + mWaitingForTransition = true; + } else { + mWaitingForTransition = false; + } + View decorView = mWindow.getDecorView(); + if (decorView != null) { + if (decorView.getTag(com.android.internal.R.id.cross_task_transition) != null) { + throw new IllegalStateException( + "Cannot start a transition while one is running"); + } + decorView.setTagInternal(com.android.internal.R.id.cross_task_transition, exit); + } + } + + @Override + public void onTransitionEnd(Transition transition) { + mTransitionEnded = true; + hideWhenDone(); + transition.removeListener(this); + } + + @Override + public void hideSharedElements() { + mSharedElementHidden = true; + hideWhenDone(); + } + + private void hideWhenDone() { + if (mSharedElementHidden && (!mWaitingForTransition || mTransitionEnded)) { + mExit.resetViews(); + int numSharedElements = mSharedElements.size(); + for (int i = 0; i < numSharedElements; i++) { + View view = mSharedElements.get(i); + view.requestLayout(); + } + View decorView = mWindow.getDecorView(); + if (decorView != null) { + decorView.setTagInternal( + com.android.internal.R.id.cross_task_transition, null); + decorView.setVisibility(View.GONE); + } + } + } + } } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index d242ba194c6ab855239e2e0ff2b9ddff37ecfaf0..2d22f26069f331a07f4b7ab837b1bf473f4236f5 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -108,6 +108,7 @@ import android.renderscript.RenderScriptCacheDir; import android.system.Os; import android.system.OsConstants; import android.system.ErrnoException; +import android.webkit.WebView; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IVoiceInteractor; @@ -236,6 +237,7 @@ public final class ActivityThread { boolean mSystemThread = false; boolean mJitEnabled = false; boolean mSomeActivitiesChanged = false; + boolean mUpdatingSystemConfig = false; // These can be accessed by multiple threads; mPackages is the lock. // XXX For now we keep around information about all packages we have @@ -432,8 +434,10 @@ public final class ActivityThread { static final class NewIntentData { List intents; IBinder token; + boolean andPause; public String toString() { - return "NewIntentData{intents=" + intents + " token=" + token + "}"; + return "NewIntentData{intents=" + intents + " token=" + token + + " andPause=" + andPause +"}"; } } @@ -750,10 +754,12 @@ public final class ActivityThread { configChanges, notResumed, config, overrideConfig, true, preserveWindow); } - public final void scheduleNewIntent(List intents, IBinder token) { + public final void scheduleNewIntent( + List intents, IBinder token, boolean andPause) { NewIntentData data = new NewIntentData(); data.intents = intents; data.token = token; + data.andPause = andPause; sendMessage(H.NEW_INTENT, data); } @@ -965,10 +971,6 @@ public final class ActivityThread { sendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0, 0, true /*async*/); } - public void attachAgent(String agent) { - sendMessage(H.ATTACH_AGENT, agent); - } - public void setSchedulingGroup(int group) { // Note: do this immediately, since going into the foreground // should happen regardless of what pending work we have to do @@ -1040,10 +1042,21 @@ public final class ActivityThread { long dalvikMax = runtime.totalMemory() / 1024; long dalvikFree = runtime.freeMemory() / 1024; long dalvikAllocated = dalvikMax - dalvikFree; + + Class[] classesToCount = new Class[] { + ContextImpl.class, + Activity.class, + WebView.class, + OpenSSLSocketImpl.class + }; + long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true); + long appContextInstanceCount = instanceCounts[0]; + long activityInstanceCount = instanceCounts[1]; + long webviewInstanceCount = instanceCounts[2]; + long openSslSocketCount = instanceCounts[3]; + long viewInstanceCount = ViewDebug.getViewInstanceCount(); long viewRootInstanceCount = ViewDebug.getViewRootImplCount(); - long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class); - long activityInstanceCount = Debug.countInstancesOfClass(Activity.class); int globalAssetCount = AssetManager.getGlobalAssetCount(); int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount(); int binderLocalObjectCount = Debug.getBinderLocalObjectCount(); @@ -1051,7 +1064,6 @@ public final class ActivityThread { int binderDeathObjectCount = Debug.getBinderDeathObjectCount(); long parcelSize = Parcel.getGlobalAllocSize(); long parcelCount = Parcel.getGlobalAllocCount(); - long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class); SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo(); dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, @@ -1114,6 +1126,7 @@ public final class ActivityThread { "Parcel count:", parcelCount); printRow(pw, TWO_COUNT_COLUMNS, "Death Recipients:", binderDeathObjectCount, "OpenSSL Sockets:", openSslSocketCount); + printRow(pw, ONE_COUNT_COLUMN, "WebViews:", webviewInstanceCount); // SQLite mem info pw.println(" "); @@ -1392,7 +1405,6 @@ public final class ActivityThread { public static final int MULTI_WINDOW_MODE_CHANGED = 152; public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153; public static final int LOCAL_VOICE_INTERACTION_STARTED = 154; - public static final int ATTACH_AGENT = 155; String codeToString(int code) { if (DEBUG_MESSAGES) { @@ -1449,7 +1461,6 @@ public final class ActivityThread { case MULTI_WINDOW_MODE_CHANGED: return "MULTI_WINDOW_MODE_CHANGED"; case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED"; case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED"; - case ATTACH_AGENT: return "ATTACH_AGENT"; } } return Integer.toString(code); @@ -1580,7 +1591,9 @@ public final class ActivityThread { case CONFIGURATION_CHANGED: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged"); mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi; + mUpdatingSystemConfig = true; handleConfigurationChanged((Configuration)msg.obj, null); + mUpdatingSystemConfig = false; Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; case CLEAN_UP_CONTEXT: @@ -1702,8 +1715,6 @@ public final class ActivityThread { case LOCAL_VOICE_INTERACTION_STARTED: handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1, (IVoiceInteractor) ((SomeArgs) msg.obj).arg2); - case ATTACH_AGENT: - handleAttachAgent((String) msg.obj); break; } Object obj = msg.obj; @@ -2792,24 +2803,34 @@ public final class ActivityThread { } } - public final void performNewIntents(IBinder token, List intents) { - ActivityClientRecord r = mActivities.get(token); - if (r != null) { - final boolean resumed = !r.paused; - if (resumed) { - r.activity.mTemporaryPause = true; - mInstrumentation.callActivityOnPause(r.activity); - } - deliverNewIntents(r, intents); - if (resumed) { - r.activity.performResume(); - r.activity.mTemporaryPause = false; - } + void performNewIntents(IBinder token, List intents, boolean andPause) { + final ActivityClientRecord r = mActivities.get(token); + if (r == null) { + return; + } + + final boolean resumed = !r.paused; + if (resumed) { + r.activity.mTemporaryPause = true; + mInstrumentation.callActivityOnPause(r.activity); + } + deliverNewIntents(r, intents); + if (resumed) { + r.activity.performResume(); + r.activity.mTemporaryPause = false; + } + + if (r.paused && andPause) { + // In this case the activity was in the paused state when we delivered the intent, + // to guarantee onResume gets called after onNewIntent we temporarily resume the + // activity and pause again as the caller wanted. + performResumeActivity(token, false, "performNewIntents"); + performPauseActivityIfNeeded(r, "performNewIntents"); } } private void handleNewIntent(NewIntentData data) { - performNewIntents(data.token, data.intents); + performNewIntents(data.token, data.intents, data.andPause); } public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) { @@ -2963,14 +2984,6 @@ public final class ActivityThread { } } - static final void handleAttachAgent(String agent) { - try { - VMDebug.attachAgent(agent); - } catch (IOException e) { - Slog.e(TAG, "Attaching agent failed: " + agent); - } - } - private static final ThreadLocal sCurrentBroadcastIntent = new ThreadLocal(); /** @@ -3798,7 +3811,7 @@ public final class ActivityThread { * than our client -- for the server, stop means to save state and give * it the result when it is done, but the window may still be visible. * For the client, we want to call onStop()/onStart() to indicate when - * the activity's UI visibillity changes. + * the activity's UI visibility changes. */ private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown, boolean saveState, String reason) { @@ -3972,6 +3985,9 @@ public final class ActivityThread { mSomeActivitiesChanged = true; } + // TODO: This method should be changed to use {@link #performStopActivityInner} to perform to + // stop operation on the activity to reduce code duplication and the chance of fixing a bug in + // one place and missing the other. private void handleSleeping(IBinder token, boolean sleeping) { ActivityClientRecord r = mActivities.get(token); @@ -3982,6 +3998,10 @@ public final class ActivityThread { if (sleeping) { if (!r.stopped && !r.isPreHoneycomb()) { + if (!r.activity.mFinished && r.state == null) { + callCallActivityOnSaveInstanceState(r); + } + try { // Now we are idle. r.activity.performStop(false /*preserveWindow*/); @@ -4640,12 +4660,20 @@ public final class ActivityThread { if ((activity == null) || (activity.mCurrentConfig == null)) { shouldChangeConfig = true; } else { - // If the new config is the same as the config this Activity - // is already running with then don't bother calling - // onConfigurationChanged + // If the new config is the same as the config this Activity is already + // running with and the override config also didn't change, then don't + // bother calling onConfigurationChanged. int diff = activity.mCurrentConfig.diff(newConfig); - if (diff != 0) { - shouldChangeConfig = true; + if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken, + amOverrideConfig)) { + // Always send the task-level config changes. For system-level configuration, if + // this activity doesn't handle any of the config changes, then don't bother + // calling onConfigurationChanged as we're going to destroy it. + if (!mUpdatingSystemConfig + || (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0 + || !reportToActivity) { + shouldChangeConfig = true; + } } } diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java index 02eb4d3ded1c17872ca52ac6ad6fb5f0dd1aa9a2..aef1d0c31f9df0facc1b0b4b72c3edf128bbd559 100644 --- a/core/java/android/app/ActivityTransitionState.java +++ b/core/java/android/app/ActivityTransitionState.java @@ -185,7 +185,12 @@ class ActivityTransitionState { activity.getWindow().getDecorView().setVisibility(View.VISIBLE); } mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity, - resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning()); + resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning(), + mEnterActivityOptions.isCrossTask()); + if (mEnterActivityOptions.isCrossTask()) { + mExitingFrom = new ArrayList<>(mEnterActivityOptions.getSharedElementNames()); + mExitingTo = new ArrayList<>(mEnterActivityOptions.getSharedElementNames()); + } if (!mIsEnterPostponed) { startEnter(); @@ -275,7 +280,8 @@ class ActivityTransitionState { } private void restoreReenteringViews() { - if (mEnterTransitionCoordinator != null && mEnterTransitionCoordinator.isReturning()) { + if (mEnterTransitionCoordinator != null && mEnterTransitionCoordinator.isReturning() && + !mEnterTransitionCoordinator.isCrossTask()) { mEnterTransitionCoordinator.forceViewsToAppear(); mExitingFrom = null; mExitingTo = null; @@ -302,8 +308,9 @@ class ActivityTransitionState { } } - mReturnExitCoordinator = - new ExitTransitionCoordinator(activity, mEnteringNames, null, null, true); + mReturnExitCoordinator = new ExitTransitionCoordinator(activity, + activity.getWindow(), activity.mEnterTransitionListener, mEnteringNames, + null, null, true); if (enterViewsTransition != null && decor != null) { enterViewsTransition.resume(decor); } @@ -330,11 +337,12 @@ class ActivityTransitionState { } public void startExitOutTransition(Activity activity, Bundle options) { - if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)) { + mEnterTransitionCoordinator = null; + if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) || + mExitTransitionCoordinators == null) { return; } ActivityOptions activityOptions = new ActivityOptions(options); - mEnterTransitionCoordinator = null; if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) { int key = activityOptions.getExitCoordinatorKey(); int index = mExitTransitionCoordinators.indexOfKey(key); diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java index 782407262c1986f33cd98822424fe20f7475a556..9928512de09f09438897d6bdc5cebac52119f2a5 100644 --- a/core/java/android/app/AlertDialog.java +++ b/core/java/android/app/AlertDialog.java @@ -201,7 +201,7 @@ public class AlertDialog extends Dialog implements DialogInterface { createContextThemeWrapper); mWindow.alwaysReadCloseOnTouchAttr(); - mAlert = new AlertController(getContext(), this, getWindow()); + mAlert = AlertController.create(getContext(), this, getWindow()); } static int resolveDialogTheme(Context context, int themeResId) { diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java index 8692336439f91dda4f000393e6e56ed123c36307..9fa8a5d2faee06e9c597a4626afab450954c0ea4 100644 --- a/core/java/android/app/ApplicationErrorReport.java +++ b/core/java/android/app/ApplicationErrorReport.java @@ -345,7 +345,7 @@ public class ApplicationErrorReport implements Parcelable { PrintWriter pw = new FastPrintWriter(sw, false, 256); tr.printStackTrace(pw); pw.flush(); - stackTrace = sw.toString(); + stackTrace = sanitizeString(sw.toString()); exceptionMessage = tr.getMessage(); // Populate fields with the "root cause" exception @@ -374,6 +374,29 @@ public class ApplicationErrorReport implements Parcelable { throwMethodName = "unknown"; throwLineNumber = 0; } + + exceptionMessage = sanitizeString(exceptionMessage); + } + + /** + * Ensure that the string is of reasonable size, truncating from the middle if needed. + */ + private String sanitizeString(String s) { + int prefixLength = 10 * 1024; + int suffixLength = 10 * 1024; + int acceptableLength = prefixLength + suffixLength; + + if (s != null && s.length() > acceptableLength) { + String replacement = + "\n[TRUNCATED " + (s.length() - acceptableLength) + " CHARS]\n"; + + StringBuilder sb = new StringBuilder(acceptableLength + replacement.length()); + sb.append(s.substring(0, prefixLength)); + sb.append(replacement); + sb.append(s.substring(s.length() - suffixLength)); + return sb.toString(); + } + return s; } /** diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 8cc1bc49f2191bad1b918f63ea14fbb48b393b25..37faa2e23dbf7dfd29bd2f0bce396a93b05c3aee 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1245,18 +1245,16 @@ public class ApplicationPackageManager extends PackageManager { return mContext.mMainThread.getSystemContext().getResources(); } final boolean sameUid = (app.uid == Process.myUid()); - try { - return mContext.mMainThread.getTopLevelResources( + final Resources r = mContext.mMainThread.getTopLevelResources( sameUid ? app.sourceDir : app.publicSourceDir, sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs, app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY, mContext.mPackageInfo); - } catch (Resources.NotFoundException cause) { - final NameNotFoundException ex = - new NameNotFoundException("Unable to open " + app.publicSourceDir); - ex.initCause(cause); - throw ex; + if (r != null) { + return r; } + throw new NameNotFoundException("Unable to open " + app.publicSourceDir); + } @Override diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index a8313d1524225498521210875d64260ef5806cc1..05d9d7e412f09987fd4f40a4b344b2b5296d9510 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -190,7 +190,8 @@ public abstract class ApplicationThreadNative extends Binder data.enforceInterface(IApplicationThread.descriptor); List pi = data.createTypedArrayList(ReferrerIntent.CREATOR); IBinder b = data.readStrongBinder(); - scheduleNewIntent(pi, b); + final boolean andPause = data.readInt() == 1; + scheduleNewIntent(pi, b, andPause); return true; } @@ -501,14 +502,6 @@ public abstract class ApplicationThreadNative extends Binder return true; } - case ATTACH_AGENT_TRANSACTION: - { - data.enforceInterface(IApplicationThread.descriptor); - String agent = data.readString(); - attachAgent(agent); - return true; - } - case DUMP_ACTIVITY_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); ParcelFileDescriptor fd = data.readFileDescriptor(); @@ -917,12 +910,13 @@ class ApplicationThreadProxy implements IApplicationThread { data.recycle(); } - public void scheduleNewIntent(List intents, IBinder token) + public void scheduleNewIntent(List intents, IBinder token, boolean andPause) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeTypedList(intents); data.writeStrongBinder(token); + data.writeInt(andPause ? 1 : 0); mRemote.transact(SCHEDULE_NEW_INTENT_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); @@ -1311,14 +1305,6 @@ class ApplicationThreadProxy implements IApplicationThread { data.recycle(); } - public void attachAgent(String agent) throws RemoteException { - Parcel data = Parcel.obtain(); - data.writeInterfaceToken(IApplicationThread.descriptor); - data.writeString(agent); - mRemote.transact(ATTACH_AGENT_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); - data.recycle(); - } - public void setCoreSettings(Bundle coreSettings) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 1e2cc266201821795e67702d94ab2b10b3f73358..a8d332b8378cfc313a235504a109124d85b321b2 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -17,6 +17,7 @@ package android.app; import android.graphics.Rect; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -852,7 +853,9 @@ final class BackStackRecord extends FragmentTransaction implements * Ensure that fragments that are entering are at least at the CREATED state * so that they may load Transitions using TransitionInflater. */ - if (fragment.mState < Fragment.CREATED && mManager.mCurState >= Fragment.CREATED) { + if (fragment.mState < Fragment.CREATED && mManager.mCurState >= Fragment.CREATED && + mManager.mHost.getContext().getApplicationInfo().targetSdkVersion >= + Build.VERSION_CODES.N) { mManager.makeActive(fragment); mManager.moveToState(fragment, Fragment.CREATED, 0, 0, false); } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index e6ca52072079955fa22908921fcd9fe797257e2c..8f424676dbe505e0dd4765fbf20bc999a8c3926e 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -185,15 +185,6 @@ class ContextImpl extends Context { @GuardedBy("mSync") private File mCodeCacheDir; - @GuardedBy("mSync") - private File[] mExternalObbDirs; - @GuardedBy("mSync") - private File[] mExternalFilesDirs; - @GuardedBy("mSync") - private File[] mExternalCacheDirs; - @GuardedBy("mSync") - private File[] mExternalMediaDirs; - // The system service cache for the system services that are cached per-ContextImpl. final Object[] mServiceCache = SystemServiceRegistry.createServiceCache(); @@ -562,17 +553,10 @@ class ContextImpl extends Context { @Override public File[] getExternalFilesDirs(String type) { synchronized (mSync) { - if (mExternalFilesDirs == null) { - mExternalFilesDirs = Environment.buildExternalStorageAppFilesDirs(getPackageName()); - } - - // Splice in requested type, if any - File[] dirs = mExternalFilesDirs; + File[] dirs = Environment.buildExternalStorageAppFilesDirs(getPackageName()); if (type != null) { dirs = Environment.buildPaths(dirs, type); } - - // Create dirs if needed return ensureExternalDirsExistOrFilter(dirs); } } @@ -586,12 +570,8 @@ class ContextImpl extends Context { @Override public File[] getObbDirs() { synchronized (mSync) { - if (mExternalObbDirs == null) { - mExternalObbDirs = Environment.buildExternalStorageAppObbDirs(getPackageName()); - } - - // Create dirs if needed - return ensureExternalDirsExistOrFilter(mExternalObbDirs); + File[] dirs = Environment.buildExternalStorageAppObbDirs(getPackageName()); + return ensureExternalDirsExistOrFilter(dirs); } } @@ -624,24 +604,16 @@ class ContextImpl extends Context { @Override public File[] getExternalCacheDirs() { synchronized (mSync) { - if (mExternalCacheDirs == null) { - mExternalCacheDirs = Environment.buildExternalStorageAppCacheDirs(getPackageName()); - } - - // Create dirs if needed - return ensureExternalDirsExistOrFilter(mExternalCacheDirs); + File[] dirs = Environment.buildExternalStorageAppCacheDirs(getPackageName()); + return ensureExternalDirsExistOrFilter(dirs); } } @Override public File[] getExternalMediaDirs() { synchronized (mSync) { - if (mExternalMediaDirs == null) { - mExternalMediaDirs = Environment.buildExternalStorageAppMediaDirs(getPackageName()); - } - - // Create dirs if needed - return ensureExternalDirsExistOrFilter(mExternalMediaDirs); + File[] dirs = Environment.buildExternalStorageAppMediaDirs(getPackageName()); + return ensureExternalDirsExistOrFilter(dirs); } } diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 85a0403fe57e68da6ee315c6fd64db51d8149540..6e2c464e9a371bfc50eb6e85d5c0b9380ab43bb9 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.DialogInterface; +import android.content.res.Configuration; import android.content.pm.ApplicationInfo; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -288,9 +289,14 @@ public class Dialog implements DialogInterface, Window.Callback, } mCanceled = false; - + if (!mCreated) { dispatchOnCreate(null); + } else { + // Fill the DecorView in on any configuration changes that + // may have occured while it was removed from the WindowManager. + final Configuration config = mContext.getResources().getConfiguration(); + mWindow.getDecorView().dispatchConfigurationChanged(config); } onStart(); diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index eb07fbc5271a1fe393169ea149486c10f25565a9..6e38347f7c9937fd18e9dd948caecd98f96248bd 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -1089,7 +1089,7 @@ public class DownloadManager { if (cursor.moveToFirst()) { int status = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_STATUS)); if (DownloadManager.STATUS_SUCCESSFUL == status) { - return ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, id); + return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id); } } } finally { @@ -1425,7 +1425,7 @@ public class DownloadManager { * @hide */ public Uri getDownloadUri(long id) { - return ContentUris.withAppendedId(mBaseUri, id); + return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id); } /** @@ -1519,7 +1519,7 @@ public class DownloadManager { // return content URI for cache download long downloadId = getLong(getColumnIndex(Downloads.Impl._ID)); - return ContentUris.withAppendedId(mBaseUri, downloadId).toString(); + return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, downloadId).toString(); } private long getReason(int status) { diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 8bf1e9a97e4847001a9edd1c47f318bf8cd1e7ab..5d12b0da6ab81b6ac3fe9b61fe45e4b76dce3cf5 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -59,12 +59,14 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { private boolean mIsViewsTransitionStarted; private Transition mEnterViewsTransition; private OnPreDrawListener mViewsReadyListener; + private final boolean mIsCrossTask; public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver, - ArrayList sharedElementNames, boolean isReturning) { + ArrayList sharedElementNames, boolean isReturning, boolean isCrossTask) { super(activity.getWindow(), sharedElementNames, - getListener(activity, isReturning), isReturning); + getListener(activity, isReturning && !isCrossTask), isReturning); mActivity = activity; + mIsCrossTask = isCrossTask; setResultReceiver(resultReceiver); prepareEnter(); Bundle resultReceiverBundle = new Bundle(); @@ -85,6 +87,10 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { } } + boolean isCrossTask() { + return mIsCrossTask; + } + public void viewInstancesReady(ArrayList accepted, ArrayList localNames, ArrayList localViews) { boolean remap = false; @@ -325,7 +331,9 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { if (mActivity == null || decorView == null) { return; } - mActivity.overridePendingTransition(0, 0); + if (!isCrossTask()) { + mActivity.overridePendingTransition(0, 0); + } if (!mIsReturning) { mWasOpaque = mActivity.convertToTranslucent(null, null); Drawable background = decorView.getBackground(); diff --git a/core/java/com/android/internal/app/EphemeralResolveInfo.aidl b/core/java/android/app/EphemeralResolveInfo.aidl similarity index 95% rename from core/java/com/android/internal/app/EphemeralResolveInfo.aidl rename to core/java/android/app/EphemeralResolveInfo.aidl index 529527bd394b99e95956a5c7769f2f0290fabd6c..db71d250ade23cd73c7f82e67abcc5caf047979f 100644 --- a/core/java/com/android/internal/app/EphemeralResolveInfo.aidl +++ b/core/java/android/app/EphemeralResolveInfo.aidl @@ -14,6 +14,6 @@ ** limitations under the License. */ -package com.android.internal.app; +package android.app; parcelable EphemeralResolveInfo; diff --git a/core/java/com/android/internal/app/EphemeralResolverService.java b/core/java/android/app/EphemeralResolverService.java similarity index 69% rename from core/java/com/android/internal/app/EphemeralResolverService.java rename to core/java/android/app/EphemeralResolverService.java index 6ba04a98aa2a5441a79d410025ba2539969923de..ba791085d617a81f903897306b1bf987b9ce27bd 100644 --- a/core/java/com/android/internal/app/EphemeralResolverService.java +++ b/core/java/android/app/EphemeralResolverService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.app; +package android.app; import android.annotation.SystemApi; import android.app.Service; @@ -37,19 +37,24 @@ import java.util.List; */ @SystemApi public abstract class EphemeralResolverService extends Service { - public static final String EXTRA_RESOLVE_INFO = "com.android.internal.app.RESOLVE_INFO"; - public static final String EXTRA_SEQUENCE = "com.android.internal.app.SEQUENCE"; + public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO"; + public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE"; + private static final String EXTRA_PREFIX = "android.app.PREFIX"; private Handler mHandler; /** * Called to retrieve resolve info for ephemeral applications. * * @param digestPrefix The hash prefix of the ephemeral's domain. + * @param prefixMask A mask that was applied to each digest prefix. This should + * be used when comparing against the digest prefixes as all bits might + * not be set. */ - protected abstract List getEphemeralResolveInfoList(int digestPrefix); + public abstract List onEphemeralResolveInfoList( + int digestPrefix[], int prefixMask); @Override - protected final void attachBaseContext(Context base) { + public final void attachBaseContext(Context base) { super.attachBaseContext(base); mHandler = new ServiceHandler(base.getMainLooper()); } @@ -59,10 +64,13 @@ public abstract class EphemeralResolverService extends Service { return new IEphemeralResolver.Stub() { @Override public void getEphemeralResolveInfoList( - IRemoteCallback callback, int digestPrefix, int sequence) { - mHandler.obtainMessage(ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, - digestPrefix, sequence, callback) - .sendToTarget(); + IRemoteCallback callback, int digestPrefix[], int prefixMask, int sequence) { + final Message msg = mHandler.obtainMessage( + ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, prefixMask, sequence, callback); + final Bundle data = new Bundle(); + data.putIntArray(EXTRA_PREFIX, digestPrefix); + msg.setData(data); + msg.sendToTarget(); } }; } @@ -81,8 +89,9 @@ public abstract class EphemeralResolverService extends Service { switch (action) { case MSG_GET_EPHEMERAL_RESOLVE_INFO: { final IRemoteCallback callback = (IRemoteCallback) message.obj; + final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX); final List resolveInfo = - getEphemeralResolveInfoList(message.arg1); + onEphemeralResolveInfoList(digestPrefix, message.arg1); final Bundle data = new Bundle(); data.putInt(EXTRA_SEQUENCE, message.arg2); data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo); diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 0404288773714f766a6d4c29307d8b8a8b71def4..160c28592582aef69a1330df138e010236722644 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -35,6 +35,7 @@ import android.transition.TransitionManager; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.Window; import java.util.ArrayList; @@ -59,18 +60,20 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { private Bundle mExitSharedElementBundle; private boolean mIsExitStarted; private boolean mSharedElementsHidden; + private HideSharedElementsCallback mHideSharedElementsCallback; - public ExitTransitionCoordinator(Activity activity, ArrayList names, + public ExitTransitionCoordinator(Activity activity, Window window, + SharedElementCallback listener, ArrayList names, ArrayList accepted, ArrayList mapped, boolean isReturning) { - super(activity.getWindow(), names, getListener(activity, isReturning), isReturning); + super(window, names, listener, isReturning); viewsReady(mapSharedElements(accepted, mapped)); stripOffscreenViews(); mIsBackgroundReady = !isReturning; mActivity = activity; } - private static SharedElementCallback getListener(Activity activity, boolean isReturning) { - return isReturning ? activity.mEnterTransitionListener : activity.mExitTransitionListener; + void setHideSharedElementsCallback(HideSharedElementsCallback callback) { + mHideSharedElementsCallback = callback; } @Override @@ -188,6 +191,9 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { private void hideSharedElements() { moveSharedElementsFromOverlay(); + if (mHideSharedElementsCallback != null) { + mHideSharedElementsCallback.hideSharedElements(); + } if (!mIsHidden) { hideViews(mSharedElements); } @@ -207,7 +213,11 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { startTransition(new Runnable() { @Override public void run() { - beginTransitions(); + if (mActivity != null) { + beginTransitions(); + } else { + startExitTransition(); + } } }); } @@ -508,4 +518,8 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { return getWindow().getSharedElementExitTransition(); } } + + interface HideSharedElementsCallback { + void hideSharedElements(); + } } diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index a637ef4f9c5499f4a72b605a8eced8aacbd3348e..5dead2850942dc21118fe86c6b6565a38b5996ba 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -194,7 +194,7 @@ final class FragmentState implements Parcelable { *

* * @@ -1483,9 +1483,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * at this point. If you want to do work once the activity itself is * created, see {@link #onActivityCreated(Bundle)}. * - *

If your app's targetSdkVersion is 23 or lower, child fragments - * being restored from the savedInstanceState are restored after onCreate - * returns. When targeting N or above and running on an N or newer platform version + *

If your app's targetSdkVersion is {@link android.os.Build.VERSION_CODES#M} + * or lower, child fragments being restored from the savedInstanceState are restored after + * onCreate returns. When targeting {@link android.os.Build.VERSION_CODES#N} or + * above and running on an N or newer platform version * they are restored by Fragment.onCreate.

* * @param savedInstanceState If the fragment is being re-created from diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java index e1d713626e2e1911c8d99da56dd90b137d6ae418..d869168e2b6a55a266093c22a6ab1f44d37483fd 100644 --- a/core/java/android/app/FragmentHostCallback.java +++ b/core/java/android/app/FragmentHostCallback.java @@ -340,6 +340,11 @@ public abstract class FragmentHostCallback extends FragmentContainer { } void restoreLoaderNonConfig(ArrayMap loaderManagers) { + if (loaderManagers != null) { + for (int i = 0, N = loaderManagers.size(); i < N; i++) { + ((LoaderManagerImpl) loaderManagers.valueAt(i)).updateHostController(this); + } + } mAllLoaderManagers = loaderManagers; } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index cd7665cf1163eaff434a0667dd92d2e42c45ec82..bfaf3328f6116bff6c426d8a802f2efe2190f9d4 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -59,7 +59,7 @@ import java.util.List; *
*

Developer Guides

*

For more information about using fragments, read the - * Fragments developer guide.

+ * Fragments developer guide.

*
* * While the FragmentManager API was introduced in diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index e435580d55fef9626ff9195af921550cbb834d3c..633e85b781184bd78fd39c29f6db090b2b62381a 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -17,7 +17,8 @@ import java.lang.annotation.RetentionPolicy; *
*

Developer Guides

*

For more information about using fragments, read the - * Fragments developer guide.

+ * Fragments developer + * guide.

*
*/ public abstract class FragmentTransaction { @@ -25,17 +26,17 @@ public abstract class FragmentTransaction { * Calls {@link #add(int, Fragment, String)} with a 0 containerViewId. */ public abstract FragmentTransaction add(Fragment fragment, String tag); - + /** * Calls {@link #add(int, Fragment, String)} with a null tag. */ public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment); - + /** * Add a fragment to the activity state. This fragment may optionally * also have its view (if {@link Fragment#onCreateView Fragment.onCreateView} * returns non-null) inserted into a container view of the activity. - * + * * @param containerViewId Optional identifier of the container this fragment is * to be placed in. If 0, it will not be placed in a container. * @param fragment The fragment to be added. This fragment must not already @@ -43,64 +44,64 @@ public abstract class FragmentTransaction { * @param tag Optional tag name for the fragment, to later retrieve the * fragment with {@link FragmentManager#findFragmentByTag(String) * FragmentManager.findFragmentByTag(String)}. - * + * * @return Returns the same FragmentTransaction instance. */ public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment, String tag); - + /** * Calls {@link #replace(int, Fragment, String)} with a null tag. */ public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment); - + /** * Replace an existing fragment that was added to a container. This is * essentially the same as calling {@link #remove(Fragment)} for all * currently added fragments that were added with the same containerViewId * and then {@link #add(int, Fragment, String)} with the same arguments * given here. - * + * * @param containerViewId Identifier of the container whose fragment(s) are * to be replaced. * @param fragment The new fragment to place in the container. * @param tag Optional tag name for the fragment, to later retrieve the * fragment with {@link FragmentManager#findFragmentByTag(String) * FragmentManager.findFragmentByTag(String)}. - * + * * @return Returns the same FragmentTransaction instance. */ public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment, String tag); - + /** * Remove an existing fragment. If it was added to a container, its view * is also removed from that container. - * + * * @param fragment The fragment to be removed. - * + * * @return Returns the same FragmentTransaction instance. */ public abstract FragmentTransaction remove(Fragment fragment); - + /** * Hides an existing fragment. This is only relevant for fragments whose * views have been added to a container, as this will cause the view to * be hidden. - * + * * @param fragment The fragment to be hidden. - * + * * @return Returns the same FragmentTransaction instance. */ public abstract FragmentTransaction hide(Fragment fragment); - + /** * Shows a previously hidden fragment. This is only relevant for fragments whose * views have been added to a container, as this will cause the view to * be shown. - * + * * @param fragment The fragment to be shown. - * + * * @return Returns the same FragmentTransaction instance. */ public abstract FragmentTransaction show(Fragment fragment); @@ -135,17 +136,17 @@ public abstract class FragmentTransaction { * false otherwise. */ public abstract boolean isEmpty(); - + /** * Bit mask that is set for all enter transitions. */ public static final int TRANSIT_ENTER_MASK = 0x1000; - + /** * Bit mask that is set for all exit transitions. */ public static final int TRANSIT_EXIT_MASK = 0x2000; - + /** Not set up for a transition. */ public static final int TRANSIT_UNSET = -1; /** No animation for transition. */ @@ -202,7 +203,7 @@ public abstract class FragmentTransaction { * animations. */ public abstract FragmentTransaction setTransitionStyle(@StyleRes int styleRes); - + /** * Add this transaction to the back stack. This means that the transaction * will be remembered after it is committed, and will reverse its operation @@ -269,7 +270,7 @@ public abstract class FragmentTransaction { * because the state after the commit can be lost if the activity needs to * be restored from its state. See {@link #commitAllowingStateLoss()} for * situations where it may be okay to lose the commit.

- * + * * @return Returns the identifier of this transaction's back stack entry, * if {@link #addToBackStack(String)} had been called. Otherwise, returns * a negative number. diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 5037e3eb9dc54772a136f35f2a535b0c7da5dfe2..5a4470b2ecdb5ba25aef19af2f73c22b9fa6764f 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -136,7 +136,7 @@ public interface IActivityManager extends IInterface { ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException; public Point getAppTaskThumbnailSize() throws RemoteException; public List getTasks(int maxNum, int flags) throws RemoteException; - public List getRecentTasks(int maxNum, + public ParceledListSlice getRecentTasks(int maxNum, int flags, int userId) throws RemoteException; public ActivityManager.TaskThumbnail getTaskThumbnail(int taskId) throws RemoteException; public List getServices(int maxNum, int flags) throws RemoteException; @@ -512,7 +512,8 @@ public interface IActivityManager extends IInterface { public int getLaunchedFromUid(IBinder activityToken) throws RemoteException; public String getLaunchedFromPackage(IBinder activityToken) throws RemoteException; - public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException; + public void registerUserSwitchObserver(IUserSwitchObserver observer, + String name) throws RemoteException; public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException; public void requestBugReport(int bugreportType) throws RemoteException; @@ -657,6 +658,31 @@ public interface IActivityManager extends IInterface { IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) throws RemoteException; + public void setVrThread(int tid) throws RemoteException; + public void setRenderThread(int tid) throws RemoteException; + + /** + * Lets activity manager know whether the calling process is currently showing "top-level" UI + * that is not an activity, i.e. windows on the screen the user is currently interacting with. + * + *

This flag can only be set for persistent processes. + * + * @param hasTopUi Whether the calling process has "top-level" UI. + */ + public void setHasTopUi(boolean hasTopUi) throws RemoteException; + + /** + * Returns if the target of the PendingIntent can be fired directly, without triggering + * a work profile challenge. This can happen if the PendingIntent is to start direct-boot + * aware activities, and the target user is in RUNNING_LOCKED state, i.e. we should allow + * direct-boot aware activity to bypass work challenge when the user hasn't unlocked yet. + * @param intent the {@link PendingIntent} to be tested. + * @return {@code true} if the intent should not trigger a work challenge, {@code false} + * otherwise. + * @throws RemoteException + */ + public boolean canBypassWorkChallenge(PendingIntent intent) throws RemoteException; + /* * Private non-Binder interfaces */ @@ -1043,4 +1069,10 @@ public interface IActivityManager extends IInterface { int START_CONFIRM_DEVICE_CREDENTIAL_INTENT = IBinder.FIRST_CALL_TRANSACTION + 374; int SEND_IDLE_JOB_TRIGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 375; int SEND_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 376; + + // Start of N MR1 transactions + int SET_VR_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 377; + int SET_RENDER_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 378; + int SET_HAS_TOP_UI = IBinder.FIRST_CALL_TRANSACTION + 379; + int CAN_BYPASS_WORK_CHALLENGE = IBinder.FIRST_CALL_TRANSACTION + 380; } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 5b13164ddb4a236f6e1cd8c0f0013d13df08380f..3fa88ae674a44fc9a0e5a12f063d1fb8b31ffa6e 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -67,7 +67,8 @@ public interface IApplicationThread extends IInterface { List pendingNewIntents, int configChanges, boolean notResumed, Configuration config, Configuration overrideConfig, boolean preserveWindow) throws RemoteException; - void scheduleNewIntent(List intent, IBinder token) throws RemoteException; + void scheduleNewIntent( + List intent, IBinder token, boolean andPause) throws RemoteException; void scheduleDestroyActivity(IBinder token, boolean finished, int configChanges) throws RemoteException; void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, @@ -122,7 +123,6 @@ public interface IApplicationThread extends IInterface { throws RemoteException; void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) throws RemoteException; - void attachAgent(String path) throws RemoteException; void setSchedulingGroup(int group) throws RemoteException; // the package has been removed, clean up internal references static final int PACKAGE_REMOVED = 0; @@ -225,5 +225,4 @@ public interface IApplicationThread extends IInterface { int SCHEDULE_MULTI_WINDOW_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58; int SCHEDULE_PICTURE_IN_PICTURE_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59; int SCHEDULE_LOCAL_VOICE_INTERACTION_STARTED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+60; - int ATTACH_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+61; } diff --git a/core/java/com/android/internal/app/IEphemeralResolver.aidl b/core/java/android/app/IEphemeralResolver.aidl similarity index 88% rename from core/java/com/android/internal/app/IEphemeralResolver.aidl rename to core/java/android/app/IEphemeralResolver.aidl index 40429ee2cccbf725bf46921180f669c61249205d..ee869eaa79365190e61be012a34f4d25438b2b1f 100644 --- a/core/java/com/android/internal/app/IEphemeralResolver.aidl +++ b/core/java/android/app/IEphemeralResolver.aidl @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.android.internal.app; +package android.app; -import android.content.Intent; import android.os.IRemoteCallback; +/** @hide */ oneway interface IEphemeralResolver { - void getEphemeralResolveInfoList(IRemoteCallback callback, int digestPrefix, int sequence); + void getEphemeralResolveInfoList(IRemoteCallback callback, in int[] digestPrefix, + int prefixMask, int sequence); } diff --git a/core/java/android/app/ITransientNotification.aidl b/core/java/android/app/ITransientNotification.aidl index 35b53a48e6e18385fd0b42b19c8232cc8f8cc6d5..d5b3ed0a44d80274de5003e873a414398a57c516 100644 --- a/core/java/android/app/ITransientNotification.aidl +++ b/core/java/android/app/ITransientNotification.aidl @@ -19,7 +19,7 @@ package android.app; /** @hide */ oneway interface ITransientNotification { - void show(); + void show(IBinder windowToken); void hide(); } diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index a0762b94a040144d89e0226837c9ef10c1dd71a7..75a5bf7f77a2201df48b6999de45e0be22109173 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -44,12 +44,12 @@ interface IWallpaperManager { */ ParcelFileDescriptor setWallpaper(String name, in String callingPackage, in Rect cropHint, boolean allowBackup, out Bundle extras, int which, - IWallpaperManagerCallback completion); + IWallpaperManagerCallback completion, int userId); /** * Set the live wallpaper. This only affects the system wallpaper. */ - void setWallpaperComponentChecked(in ComponentName name, in String callingPackage); + void setWallpaperComponentChecked(in ComponentName name, in String callingPackage, int userId); /** * Set the live wallpaper. This only affects the system wallpaper. @@ -72,7 +72,7 @@ interface IWallpaperManager { * information about that wallpaper. Otherwise, if it is a static image, * simply return null. */ - WallpaperInfo getWallpaperInfo(); + WallpaperInfo getWallpaperInfo(int userId); /** * Clear the system wallpaper. @@ -128,7 +128,7 @@ interface IWallpaperManager { /* * Backup: is the current system wallpaper image eligible for off-device backup? */ - boolean isWallpaperBackupEligible(int userId); + boolean isWallpaperBackupEligible(int which, int userId); /* * Keyguard: register a callback for being notified that lock-state relevant diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java index f33af396070e9dde19302ef366a73e4a7f815a94..e4a22c42d9bcbeadeb63d1ea6a57adca35cdf024 100644 --- a/core/java/android/app/IntentService.java +++ b/core/java/android/app/IntentService.java @@ -46,7 +46,8 @@ import android.os.Message; *

*

Developer Guides

*

For a detailed discussion about how to create services, read the - * Services developer guide.

+ * Services developer + * guide.

*
* * @see android.os.AsyncTask diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 8824c981dc45e12b97a6b8aeb62e334f90bb1474..9ea16a719ceb7ddadb66a9b3ac469df88cc041c1 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -1400,18 +1400,6 @@ public final class LoadedApk { } public void death(ComponentName name, IBinder service) { - ServiceDispatcher.ConnectionInfo old; - - synchronized (this) { - old = mActiveConnections.remove(name); - if (old == null || old.binder != service) { - // Death for someone different than who we last - // reported... just ignore it. - return; - } - old.binder.unlinkToDeath(old.deathMonitor, 0); - } - if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 1)); } else { @@ -1460,7 +1448,7 @@ public final class LoadedApk { } } - // If there was an old service, it is not disconnected. + // If there was an old service, it is now disconnected. if (old != null) { mConnection.onServiceDisconnected(name); } @@ -1471,6 +1459,17 @@ public final class LoadedApk { } public void doDeath(ComponentName name, IBinder service) { + synchronized (this) { + ConnectionInfo old = mActiveConnections.get(name); + if (old == null || old.binder != service) { + // Death for someone different than who we last + // reported... just ignore it. + return; + } + mActiveConnections.remove(name); + old.binder.unlinkToDeath(old.deathMonitor, 0); + } + mConnection.onServiceDisconnected(name); } diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java index c14dec93c348ee1b05112f88fb3a0358566a5970..bedf31a22f26410806c220c20e36ec46ba99a031 100644 --- a/core/java/android/app/LoaderManager.java +++ b/core/java/android/app/LoaderManager.java @@ -195,6 +195,9 @@ public abstract class LoaderManager { public static void enableDebugLogging(boolean enabled) { LoaderManagerImpl.DEBUG = enabled; } + + /** @hide for internal testing only */ + public FragmentHostCallback getFragmentHostCallback() { return null; } } class LoaderManagerImpl extends LoaderManager { @@ -542,6 +545,10 @@ class LoaderManagerImpl extends LoaderManager { void updateHostController(FragmentHostCallback host) { mHost = host; } + + public FragmentHostCallback getFragmentHostCallback() { + return mHost; + } private LoaderInfo createLoader(int id, Bundle args, LoaderManager.LoaderCallbacks callback) { diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java index 2a1e3c250a00a24f9e230e464469245553d5743f..3b273bc1c4b6bdc0cb0223158422d98cfc6dad8c 100644 --- a/core/java/android/app/LocalActivityManager.java +++ b/core/java/android/app/LocalActivityManager.java @@ -314,7 +314,7 @@ public class LocalActivityManager { ArrayList intents = new ArrayList<>(1); intents.add(new ReferrerIntent(intent, mParent.getPackageName())); if (localLOGV) Log.v(TAG, r.id + ": new intent"); - mActivityThread.performNewIntents(r, intents); + mActivityThread.performNewIntents(r, intents, false /* andPause */); r.intent = intent; moveToState(r, mCurState); if (mSingleMode) { diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 3c3da7804a11f9d1464942ada28129225a47ad8b..0dd9c63c40c53bbfc1436138f9f0e8893a99e8da 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -19,6 +19,7 @@ package android.app; import android.annotation.ColorInt; import android.annotation.DrawableRes; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; @@ -39,7 +40,6 @@ import android.media.AudioManager; import android.media.session.MediaSession; import android.net.Uri; import android.os.BadParcelableException; -import android.os.BaseBundle; import android.os.Build; import android.os.Bundle; import android.os.Parcel; @@ -51,7 +51,9 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.style.AbsoluteSizeSpan; +import android.text.style.BackgroundColorSpan; import android.text.style.CharacterStyle; +import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; import android.text.style.TextAppearanceSpan; import android.util.ArraySet; @@ -73,7 +75,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; @@ -762,14 +763,13 @@ public class Notification implements Parcelable public Bundle extras = new Bundle(); /** - * All pending intents in the notification extras (notification extras, actions extras, - * and remote input extras) as the system needs to be able to access them but touching - * the extras bundle in the system process is not safe because the bundle may contain + * All pending intents in the notification as the system needs to be able to access them but + * touching the extras bundle in the system process is not safe because the bundle may contain * custom parcelable objects. * * @hide */ - public ArraySet extrasPendingIntents; + public ArraySet allPendingIntents; /** * {@link #extras} key: this is the title of the notification, @@ -1049,6 +1049,7 @@ public class Notification implements Parcelable this(Icon.createWithResource("", icon), title, intent, new Bundle(), null, false); } + /** Keep in sync with {@link Notification.Action.Builder#Builder(Action)}! */ private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras, RemoteInput[] remoteInputs, boolean allowGeneratedReplies) { this.mIcon = icon; @@ -1115,7 +1116,7 @@ public class Notification implements Parcelable */ @Deprecated public Builder(int icon, CharSequence title, PendingIntent intent) { - this(Icon.createWithResource("", icon), title, intent, new Bundle(), null); + this(Icon.createWithResource("", icon), title, intent); } /** @@ -1125,7 +1126,7 @@ public class Notification implements Parcelable * @param intent the {@link PendingIntent} to fire when users trigger this action */ public Builder(Icon icon, CharSequence title, PendingIntent intent) { - this(icon, title, intent, new Bundle(), null); + this(icon, title, intent, new Bundle(), null, false); } /** @@ -1134,12 +1135,13 @@ public class Notification implements Parcelable * @param action the action to read fields from. */ public Builder(Action action) { - this(action.getIcon(), action.title, action.actionIntent, new Bundle(action.mExtras), - action.getRemoteInputs()); + this(action.getIcon(), action.title, action.actionIntent, + new Bundle(action.mExtras), action.getRemoteInputs(), + action.getAllowGeneratedReplies()); } private Builder(Icon icon, CharSequence title, PendingIntent intent, Bundle extras, - RemoteInput[] remoteInputs) { + RemoteInput[] remoteInputs, boolean allowGeneratedReplies) { mIcon = icon; mTitle = title; mIntent = intent; @@ -1148,6 +1150,7 @@ public class Notification implements Parcelable mRemoteInputs = new ArrayList(remoteInputs.length); Collections.addAll(mRemoteInputs, remoteInputs); } + mAllowGeneratedReplies = allowGeneratedReplies; } /** @@ -1230,7 +1233,7 @@ public class Notification implements Parcelable getIcon(), title, actionIntent, // safe to alias - new Bundle(mExtras), + mExtras == null ? new Bundle() : new Bundle(mExtras), getRemoteInputs(), getAllowGeneratedReplies()); } @@ -1308,6 +1311,7 @@ public class Notification implements Parcelable // Flags bitwise-ored to mFlags private static final int FLAG_AVAILABLE_OFFLINE = 0x1; private static final int FLAG_HINT_LAUNCHES_ACTIVITY = 1 << 1; + private static final int FLAG_HINT_DISPLAY_INLINE = 1 << 2; // Default value for flags integer private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE; @@ -1494,6 +1498,29 @@ public class Notification implements Parcelable public boolean getHintLaunchesActivity() { return (mFlags & FLAG_HINT_LAUNCHES_ACTIVITY) != 0; } + + /** + * Set a hint that this Action should be displayed inline. + * + * @param hintDisplayInline {@code true} if action should be displayed inline, false + * otherwise + * @return this object for method chaining + */ + public WearableExtender setHintDisplayActionInline( + boolean hintDisplayInline) { + setFlag(FLAG_HINT_DISPLAY_INLINE, hintDisplayInline); + return this; + } + + /** + * Get a hint that this Action should be displayed inline. + * + * @return {@code true} if the Action should be displayed inline, {@code false} + * otherwise. The default value is {@code false} if this was never set. + */ + public boolean getHintDisplayActionInline() { + return (mFlags & FLAG_HINT_DISPLAY_INLINE) != 0; + } } } @@ -1569,7 +1596,7 @@ public class Notification implements Parcelable // intents in extras are always written as the last entry. readFromParcelImpl(parcel); // Must be read last! - extrasPendingIntents = (ArraySet) parcel.readArraySet(null); + allPendingIntents = (ArraySet) parcel.readArraySet(null); } private void readFromParcelImpl(Parcel parcel) @@ -1727,8 +1754,8 @@ public class Notification implements Parcelable } } - if (!ArrayUtils.isEmpty(extrasPendingIntents)) { - that.extrasPendingIntents = new ArraySet<>(extrasPendingIntents); + if (!ArrayUtils.isEmpty(allPendingIntents)) { + that.allPendingIntents = new ArraySet<>(allPendingIntents); } if (this.actions != null) { @@ -1854,15 +1881,15 @@ public class Notification implements Parcelable // cannot look into the extras as there may be parcelables there that // the platform does not know how to handle. To go around that we have // an explicit list of the pending intents in the extras bundle. - final boolean collectPendingIntents = (extrasPendingIntents == null); + final boolean collectPendingIntents = (allPendingIntents == null); if (collectPendingIntents) { PendingIntent.setOnMarshaledListener( (PendingIntent intent, Parcel out, int outFlags) -> { if (parcel == out) { - if (extrasPendingIntents == null) { - extrasPendingIntents = new ArraySet<>(); + if (allPendingIntents == null) { + allPendingIntents = new ArraySet<>(); } - extrasPendingIntents.add(intent); + allPendingIntents.add(intent); } }); } @@ -1871,7 +1898,7 @@ public class Notification implements Parcelable // want to intercept all pending events written to the pacel. writeToParcelImpl(parcel, flags); // Must be written last! - parcel.writeArraySet(extrasPendingIntents); + parcel.writeArraySet(allPendingIntents); } finally { if (collectPendingIntents) { PendingIntent.setOnMarshaledListener(null); @@ -3233,11 +3260,13 @@ public class Notification implements Parcelable * Resets the notification header to its original state */ private void resetNotificationHeader(RemoteViews contentView) { - contentView.setImageViewResource(R.id.icon, 0); + // Small icon doesn't need to be reset, as it's always set. Resetting would prevent + // re-using the drawable when the notification is updated. contentView.setBoolean(R.id.notification_header, "setExpanded", false); contentView.setTextViewText(R.id.app_name_text, null); contentView.setViewVisibility(R.id.chronometer, View.GONE); contentView.setViewVisibility(R.id.header_text, View.GONE); + contentView.setTextViewText(R.id.header_text, null); contentView.setViewVisibility(R.id.header_text_divider, View.GONE); contentView.setViewVisibility(R.id.time_divider, View.GONE); contentView.setViewVisibility(R.id.time, View.GONE); @@ -3450,6 +3479,8 @@ public class Notification implements Parcelable mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon); } contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon); + contentView.setDrawableParameters(R.id.icon, false /* targetBackground */, + -1 /* alpha */, -1 /* colorFilter */, null /* mode */, mN.iconLevel); processSmallIconColor(mN.mSmallIcon, contentView); } @@ -3495,6 +3526,8 @@ public class Notification implements Parcelable boolean validRemoteInput = false; int N = mActions.size(); + boolean emphazisedMode = mN.fullScreenIntent != null; + big.setBoolean(R.id.actions, "setEmphasizedMode", emphazisedMode); if (N > 0) { big.setViewVisibility(R.id.actions_container, View.VISIBLE); big.setViewVisibility(R.id.actions, View.VISIBLE); @@ -3505,7 +3538,8 @@ public class Notification implements Parcelable Action action = mActions.get(i); validRemoteInput |= hasValidRemoteInput(action); - final RemoteViews button = generateActionButton(action); + final RemoteViews button = generateActionButton(action, emphazisedMode, + i % 2 != 0); big.addView(R.id.actions, button); } } else { @@ -3670,13 +3704,13 @@ public class Notification implements Parcelable - private RemoteViews generateActionButton(Action action) { + private RemoteViews generateActionButton(Action action, boolean emphazisedMode, + boolean oddAction) { final boolean tombstone = (action.actionIntent == null); RemoteViews button = new BuilderRemoteViews(mContext.getApplicationInfo(), - tombstone ? getActionTombstoneLayoutResource() - : getActionLayoutResource()); - final Icon ai = action.getIcon(); - button.setTextViewText(R.id.action0, processLegacyText(action.title)); + emphazisedMode ? getEmphasizedActionLayoutResource() + : tombstone ? getActionTombstoneLayoutResource() + : getActionLayoutResource()); if (!tombstone) { button.setOnClickPendingIntent(R.id.action0, action.actionIntent); } @@ -3684,12 +3718,143 @@ public class Notification implements Parcelable if (action.mRemoteInputs != null) { button.setRemoteInputs(R.id.action0, action.mRemoteInputs); } - if (mN.color != COLOR_DEFAULT) { - button.setTextColor(R.id.action0, resolveContrastColor()); + if (emphazisedMode) { + // change the background bgColor + int bgColor = mContext.getColor(oddAction ? R.color.notification_action_list + : R.color.notification_action_list_dark); + button.setDrawableParameters(R.id.button_holder, true, -1, bgColor, + PorterDuff.Mode.SRC_ATOP, -1); + CharSequence title = action.title; + ColorStateList[] outResultColor = null; + if (isLegacy()) { + title = clearColorSpans(title); + } else { + outResultColor = new ColorStateList[1]; + title = ensureColorSpanContrast(title, bgColor, outResultColor); + } + button.setTextViewText(R.id.action0, title); + if (outResultColor != null && outResultColor[0] != null) { + // We need to set the text color as well since changing a text to uppercase + // clears its spans. + button.setTextColor(R.id.action0, outResultColor[0]); + } else if (mN.color != COLOR_DEFAULT) { + button.setTextColor(R.id.action0,resolveContrastColor()); + } + } else { + button.setTextViewText(R.id.action0, processLegacyText(action.title)); + if (mN.color != COLOR_DEFAULT) { + button.setTextColor(R.id.action0, resolveContrastColor()); + } } return button; } + /** + * Clears all color spans of a text + * @param charSequence the input text + * @return the same text but without color spans + */ + private CharSequence clearColorSpans(CharSequence charSequence) { + if (charSequence instanceof Spanned) { + Spanned ss = (Spanned) charSequence; + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); + for (Object span : spans) { + Object resultSpan = span; + if (resultSpan instanceof CharacterStyle) { + resultSpan = ((CharacterStyle) span).getUnderlying(); + } + if (resultSpan instanceof TextAppearanceSpan) { + TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan; + if (originalSpan.getTextColor() != null) { + resultSpan = new TextAppearanceSpan( + originalSpan.getFamily(), + originalSpan.getTextStyle(), + originalSpan.getTextSize(), + null, + originalSpan.getLinkTextColor()); + } + } else if (resultSpan instanceof ForegroundColorSpan + || (resultSpan instanceof BackgroundColorSpan)) { + continue; + } else { + resultSpan = span; + } + builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span), + ss.getSpanFlags(span)); + } + return builder; + } + return charSequence; + } + + /** + * Ensures contrast on color spans against a background color. also returns the color of the + * text if a span was found that spans over the whole text. + * + * @param charSequence the charSequence on which the spans are + * @param background the background color to ensure the contrast against + * @param outResultColor an array in which a color will be returned as the first element if + * there exists a full length color span. + * @return the contrasted charSequence + */ + private CharSequence ensureColorSpanContrast(CharSequence charSequence, int background, + ColorStateList[] outResultColor) { + if (charSequence instanceof Spanned) { + Spanned ss = (Spanned) charSequence; + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); + for (Object span : spans) { + Object resultSpan = span; + int spanStart = ss.getSpanStart(span); + int spanEnd = ss.getSpanEnd(span); + boolean fullLength = (spanEnd - spanStart) == charSequence.length(); + if (resultSpan instanceof CharacterStyle) { + resultSpan = ((CharacterStyle) span).getUnderlying(); + } + if (resultSpan instanceof TextAppearanceSpan) { + TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan; + ColorStateList textColor = originalSpan.getTextColor(); + if (textColor != null) { + int[] colors = textColor.getColors(); + int[] newColors = new int[colors.length]; + for (int i = 0; i < newColors.length; i++) { + newColors[i] = NotificationColorUtil.ensureLargeTextContrast( + colors[i], background); + } + textColor = new ColorStateList(textColor.getStates().clone(), + newColors); + resultSpan = new TextAppearanceSpan( + originalSpan.getFamily(), + originalSpan.getTextStyle(), + originalSpan.getTextSize(), + textColor, + originalSpan.getLinkTextColor()); + if (fullLength) { + outResultColor[0] = new ColorStateList( + textColor.getStates().clone(), newColors); + } + } + } else if (resultSpan instanceof ForegroundColorSpan) { + ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan; + int foregroundColor = originalSpan.getForegroundColor(); + foregroundColor = NotificationColorUtil.ensureLargeTextContrast( + foregroundColor, background); + resultSpan = new ForegroundColorSpan(foregroundColor); + if (fullLength) { + outResultColor[0] = ColorStateList.valueOf(foregroundColor); + } + } else { + resultSpan = span; + } + + builder.setSpan(resultSpan, spanStart, spanEnd, ss.getSpanFlags(span)); + } + return builder; + } + return charSequence; + } + /** * @return Whether we are currently building a notification from a legacy (an app that * doesn't create material notifications by itself) app. @@ -3955,6 +4120,10 @@ public class Notification implements Parcelable return R.layout.notification_material_action; } + private int getEmphasizedActionLayoutResource() { + return R.layout.notification_material_action_emphasized; + } + private int getActionTombstoneLayoutResource() { return R.layout.notification_material_action_tombstone; } @@ -4260,9 +4429,15 @@ public class Notification implements Parcelable // mN.mLargeIcon // 2. !mBigLargeIconSet -> mN.mLargeIcon applies Icon oldLargeIcon = null; + Bitmap largeIconLegacy = null; if (mBigLargeIconSet) { oldLargeIcon = mBuilder.mN.mLargeIcon; mBuilder.mN.mLargeIcon = mBigLargeIcon; + // The legacy largeIcon might not allow us to clear the image, as it's taken in + // replacement if the other one is null. Because we're restoring these legacy icons + // for old listeners, this is in general non-null. + largeIconLegacy = mBuilder.mN.largeIcon; + mBuilder.mN.largeIcon = null; } RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource()); @@ -4274,6 +4449,7 @@ public class Notification implements Parcelable if (mBigLargeIconSet) { mBuilder.mN.mLargeIcon = oldLargeIcon; + mBuilder.mN.largeIcon = largeIconLegacy; } contentView.setImageViewBitmap(R.id.big_picture, mPicture); @@ -4477,12 +4653,12 @@ public class Notification implements Parcelable } /** - * @param userDisplayName the name to be displayed for any replies sent by the user before the - * posting app reposts the notification with those messages after they've been actually - * sent and in previous messages sent by the user added in + * @param userDisplayName Required - the name to be displayed for any replies sent by the + * user before the posting app reposts the notification with those messages after they've + * been actually sent and in previous messages sent by the user added in * {@link #addMessage(Notification.MessagingStyle.Message)} */ - public MessagingStyle(CharSequence userDisplayName) { + public MessagingStyle(@NonNull CharSequence userDisplayName) { mUserDisplayName = userDisplayName; } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 18b72e29e0e610253a00c6a73269674f5e222bcf..ff514bd7c81b7792a8b0e5aade2c8376f1a20666 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -312,8 +312,8 @@ public class NotificationManager try { service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id, copy, idOut, user.getIdentifier()); - if (id != idOut[0]) { - Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]); + if (localLOGV && id != idOut[0]) { + Log.v(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 744bd305a9cc5286dd33fbd52e566cfc0645931d..55bb878a99410ba490eff4b5037d4fdcd21bc11f 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -242,7 +242,7 @@ public class ResourcesManager { * @return a new AssetManager. */ @VisibleForTesting - protected @NonNull AssetManager createAssetManager(@NonNull final ResourcesKey key) { + protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) { AssetManager assets = new AssetManager(); // resDir can be null if the 'android' package is creating a new Resources object. @@ -250,15 +250,16 @@ public class ResourcesManager { // already. if (key.mResDir != null) { if (assets.addAssetPath(key.mResDir) == 0) { - throw new Resources.NotFoundException("failed to add asset path " + key.mResDir); + Log.e(TAG, "failed to add asset path " + key.mResDir); + return null; } } if (key.mSplitResDirs != null) { for (final String splitResDir : key.mSplitResDirs) { if (assets.addAssetPath(splitResDir) == 0) { - throw new Resources.NotFoundException( - "failed to add split asset path " + splitResDir); + Log.e(TAG, "failed to add split asset path " + splitResDir); + return null; } } } @@ -303,11 +304,15 @@ public class ResourcesManager { return config; } - private @NonNull ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) { + private @Nullable ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) { final DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration); daj.setCompatibilityInfo(key.mCompatInfo); final AssetManager assets = createAssetManager(key); + if (assets == null) { + return null; + } + final DisplayMetrics dm = getDisplayMetrics(key.mDisplayId, daj); final Configuration config = generateConfig(key, dm); final ResourcesImpl impl = new ResourcesImpl(assets, dm, config, daj); @@ -323,7 +328,7 @@ public class ResourcesManager { * @param key The key to match. * @return a ResourcesImpl if the key matches a cache entry, null otherwise. */ - private ResourcesImpl findResourcesImplForKeyLocked(@NonNull ResourcesKey key) { + private @Nullable ResourcesImpl findResourcesImplForKeyLocked(@NonNull ResourcesKey key) { WeakReference weakImplRef = mResourceImpls.get(key); ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null; if (impl != null && impl.getAssets().isUpToDate()) { @@ -338,12 +343,14 @@ public class ResourcesManager { * @param key The key to match. * @return a ResourcesImpl object matching the key. */ - private @NonNull ResourcesImpl findOrCreateResourcesImplForKeyLocked( + private @Nullable ResourcesImpl findOrCreateResourcesImplForKeyLocked( @NonNull ResourcesKey key) { ResourcesImpl impl = findResourcesImplForKeyLocked(key); if (impl == null) { impl = createResourcesImpl(key); - mResourceImpls.put(key, new WeakReference<>(impl)); + if (impl != null) { + mResourceImpls.put(key, new WeakReference<>(impl)); + } } return impl; } @@ -352,7 +359,8 @@ public class ResourcesManager { * Find the ResourcesKey that this ResourcesImpl object is associated with. * @return the ResourcesKey or null if none was found. */ - private ResourcesKey findKeyForResourceImplLocked(@NonNull ResourcesImpl resourceImpl) { + private @Nullable ResourcesKey findKeyForResourceImplLocked( + @NonNull ResourcesImpl resourceImpl) { final int refCount = mResourceImpls.size(); for (int i = 0; i < refCount; i++) { WeakReference weakImplRef = mResourceImpls.valueAt(i); @@ -364,6 +372,26 @@ public class ResourcesManager { return null; } + /** + * Check if activity resources have same override config as the provided on. + * @param activityToken The Activity that resources should be associated with. + * @param overrideConfig The override configuration to be checked for equality with. + * @return true if activity resources override config matches the provided one or they are both + * null, false otherwise. + */ + boolean isSameResourcesOverrideConfig(@Nullable IBinder activityToken, + @Nullable Configuration overrideConfig) { + synchronized (this) { + final ActivityResources activityResources + = activityToken != null ? mActivityResourceReferences.get(activityToken) : null; + if (activityResources == null) { + return overrideConfig == null; + } else { + return Objects.equals(activityResources.overrideConfig, overrideConfig); + } + } + } + private ActivityResources getOrCreateActivityResourcesStructLocked( @NonNull IBinder activityToken) { ActivityResources activityResources = mActivityResourceReferences.get(activityToken); @@ -460,7 +488,7 @@ public class ResourcesManager { * {@link ClassLoader#getSystemClassLoader()} is used. * @return a Resources object from which to access resources. */ - public @NonNull Resources createBaseActivityResources(@NonNull IBinder activityToken, + public @Nullable Resources createBaseActivityResources(@NonNull IBinder activityToken, @Nullable String resDir, @Nullable String[] splitResDirs, @Nullable String[] overlayDirs, @@ -514,7 +542,7 @@ public class ResourcesManager { * {@link #applyConfigurationToResourcesLocked(Configuration, CompatibilityInfo)} * is called. */ - private @NonNull Resources getOrCreateResources(@Nullable IBinder activityToken, + private @Nullable Resources getOrCreateResources(@Nullable IBinder activityToken, @NonNull ResourcesKey key, @NonNull ClassLoader classLoader) { synchronized (this) { if (DEBUG) { @@ -569,6 +597,9 @@ public class ResourcesManager { // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now. ResourcesImpl resourcesImpl = createResourcesImpl(key); + if (resourcesImpl == null) { + return null; + } synchronized (this) { ResourcesImpl existingResourcesImpl = findResourcesImplForKeyLocked(key); @@ -622,7 +653,7 @@ public class ResourcesManager { * {@link ClassLoader#getSystemClassLoader()} is used. * @return a Resources object from which to access resources. */ - public @NonNull Resources getResources(@Nullable IBinder activityToken, + public @Nullable Resources getResources(@Nullable IBinder activityToken, @Nullable String resDir, @Nullable String[] splitResDirs, @Nullable String[] overlayDirs, @@ -745,10 +776,12 @@ public class ResourcesManager { ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(newKey); if (resourcesImpl == null) { resourcesImpl = createResourcesImpl(newKey); - mResourceImpls.put(newKey, new WeakReference<>(resourcesImpl)); + if (resourcesImpl != null) { + mResourceImpls.put(newKey, new WeakReference<>(resourcesImpl)); + } } - if (resourcesImpl != resources.getImpl()) { + if (resourcesImpl != null && resourcesImpl != resources.getImpl()) { // Set the ResourcesImpl, updating it for all users of this Resources // object. resources.setImpl(resourcesImpl); @@ -892,7 +925,11 @@ public class ResourcesManager { if (r != null) { final ResourcesKey key = updatedResourceKeys.get(r.getImpl()); if (key != null) { - r.setImpl(findOrCreateResourcesImplForKeyLocked(key)); + final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key); + if (impl == null) { + throw new Resources.NotFoundException("failed to load " + libAsset); + } + r.setImpl(impl); } } } @@ -905,7 +942,11 @@ public class ResourcesManager { if (r != null) { final ResourcesKey key = updatedResourceKeys.get(r.getImpl()); if (key != null) { - r.setImpl(findOrCreateResourcesImplForKeyLocked(key)); + final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key); + if (impl == null) { + throw new Resources.NotFoundException("failed to load " + libAsset); + } + r.setImpl(impl); } } } diff --git a/core/java/android/app/RetailDemoModeServiceInternal.java b/core/java/android/app/RetailDemoModeServiceInternal.java new file mode 100644 index 0000000000000000000000000000000000000000..7ca214aae60265712129a7f5b17a84109f5bf603 --- /dev/null +++ b/core/java/android/app/RetailDemoModeServiceInternal.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.app; + +/** + * Retail Demo Mode Service interface to be used locally inside system server + * + * @hide Only for use inside system server + */ +public interface RetailDemoModeServiceInternal { + /** + * Used to notify RetailDemoModeService of any user activity. + */ + public void onUserActivity(); +} \ No newline at end of file diff --git a/core/java/android/app/TabActivity.java b/core/java/android/app/TabActivity.java index 882e55a89a74b1e4fe029d5bc17301b63ecf4d93..637c8c19aef5eeb6ff5fb2586e6882709fe94777 100644 --- a/core/java/android/app/TabActivity.java +++ b/core/java/android/app/TabActivity.java @@ -28,23 +28,6 @@ import android.widget.TextView; * {@link ActionBar#newTab() ActionBar.newTab()} and * related APIs for placing tabs within their action bar area.

* - *

A replacement for TabActivity can also be implemented by directly using - * TabHost. You will need to define a layout that correctly uses a TabHost - * with a TabWidget as well as an area in which to display your tab content. - * A typical example would be:

- * - * {@sample development/samples/Support4Demos/res/layout/fragment_tabs.xml complete} - * - *

The implementation needs to take over responsibility for switching - * the shown content when the user switches between tabs. - * - * {@sample development/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentTabs.java - * complete} - * - *

Also see the - * Fragment Tabs Pager sample for an example of using the support library's ViewPager to - * allow the user to swipe the content to switch between tabs.

- * * @deprecated New applications should use Fragments instead of this class; * to continue to run on older devices, you can use the v4 support library * which provides a version of the Fragment API that is compatible down to diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java index aca07636e26ea4f52136a68f0af3cc459e904483..3f467a01bee2a6cca3462575d973b4e159c42994 100644 --- a/core/java/android/app/TimePickerDialog.java +++ b/core/java/android/app/TimePickerDialog.java @@ -16,6 +16,7 @@ package android.app; +import android.annotation.TestApi; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; @@ -91,6 +92,12 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener, /** * Creates a new time picker dialog with the specified theme. + *

+ * The theme is overlaid on top of the theme of the parent {@code context}. + * If {@code themeResId} is 0, the dialog will be inflated using the theme + * specified by the + * {@link android.R.attr#timePickerDialogTheme android:timePickerDialogTheme} + * attribute on the parent {@code context}'s theme. * * @param context the parent context * @param themeResId the resource ID of the theme to apply to this dialog @@ -109,11 +116,6 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener, mIs24HourView = is24HourView; final Context themeContext = getContext(); - - - final TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.timePickerDialogTheme, outValue, true); - final LayoutInflater inflater = LayoutInflater.from(themeContext); final View view = inflater.inflate(R.layout.time_picker_dialog, null); setView(view); @@ -128,6 +130,15 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener, mTimePicker.setOnTimeChangedListener(this); } + /** + * @return the time picker displayed in the dialog + * @hide For testing only. + */ + @TestApi + public TimePicker getTimePicker() { + return mTimePicker; + } + @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { /* do nothing */ diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java index 7db9fa8fed65993d2ea3cbf2d88f91db8b9ba430..9d40381fcefd2527c1db3c327dda1d2607380329 100644 --- a/core/java/android/app/WallpaperInfo.java +++ b/core/java/android/app/WallpaperInfo.java @@ -31,6 +31,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.service.wallpaper.WallpaperService; @@ -72,6 +73,10 @@ public final class WallpaperInfo implements Parcelable { */ final int mDescriptionResource; + final int mContextUriResource; + final int mContextDescriptionResource; + final boolean mShowMetadataInPreview; + /** * Constructor. * @@ -89,7 +94,10 @@ public final class WallpaperInfo implements Parcelable { int thumbnailRes = -1; int authorRes = -1; int descriptionRes = -1; - + int contextUriRes = -1; + int contextDescriptionRes = -1; + boolean showMetadataInPreview = false; + XmlResourceParser parser = null; try { parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA); @@ -127,6 +135,15 @@ public final class WallpaperInfo implements Parcelable { descriptionRes = sa.getResourceId( com.android.internal.R.styleable.Wallpaper_description, -1); + contextUriRes = sa.getResourceId( + com.android.internal.R.styleable.Wallpaper_contextUri, + -1); + contextDescriptionRes = sa.getResourceId( + com.android.internal.R.styleable.Wallpaper_contextDescription, + -1); + showMetadataInPreview = sa.getBoolean( + com.android.internal.R.styleable.Wallpaper_showMetadataInPreview, + false); sa.recycle(); } catch (NameNotFoundException e) { @@ -140,6 +157,9 @@ public final class WallpaperInfo implements Parcelable { mThumbnailResource = thumbnailRes; mAuthorResource = authorRes; mDescriptionResource = descriptionRes; + mContextUriResource = contextUriRes; + mContextDescriptionResource = contextDescriptionRes; + mShowMetadataInPreview = showMetadataInPreview; } WallpaperInfo(Parcel source) { @@ -147,6 +167,9 @@ public final class WallpaperInfo implements Parcelable { mThumbnailResource = source.readInt(); mAuthorResource = source.readInt(); mDescriptionResource = source.readInt(); + mContextUriResource = source.readInt(); + mContextDescriptionResource = source.readInt(); + mShowMetadataInPreview = source.readInt() != 0; mService = ResolveInfo.CREATOR.createFromParcel(source); } @@ -248,7 +271,60 @@ public final class WallpaperInfo implements Parcelable { return pm.getText(packageName, mDescriptionResource, mService.serviceInfo.applicationInfo); } - + + /** + * Returns an URI that specifies a link for further context about this wallpaper. + * + * @param pm An instance of {@link PackageManager} to retrieve the URI. + * @return The URI. + */ + public Uri loadContextUri(PackageManager pm) throws NotFoundException { + if (mContextUriResource <= 0) throw new NotFoundException(); + String packageName = mService.resolvePackageName; + ApplicationInfo applicationInfo = null; + if (packageName == null) { + packageName = mService.serviceInfo.packageName; + applicationInfo = mService.serviceInfo.applicationInfo; + } + String contextUriString = pm.getText( + packageName, mContextUriResource, applicationInfo).toString(); + if (contextUriString == null) { + return null; + } + return Uri.parse(contextUriString); + } + + /** + * Retrieves a title of the URI that specifies a link for further context about this wallpaper. + * + * @param pm An instance of {@link PackageManager} to retrieve the title. + * @return The title. + */ + public CharSequence loadContextDescription(PackageManager pm) throws NotFoundException { + if (mContextDescriptionResource <= 0) throw new NotFoundException(); + String packageName = mService.resolvePackageName; + ApplicationInfo applicationInfo = null; + if (packageName == null) { + packageName = mService.serviceInfo.packageName; + applicationInfo = mService.serviceInfo.applicationInfo; + } + return pm.getText(packageName, mContextDescriptionResource, applicationInfo).toString(); + } + + /** + * Queries whether any metadata should be shown when previewing the wallpaper. If this value is + * set to true, any component that shows a preview of this live wallpaper should also show + * accompanying information like {@link #loadLabel}, + * {@link #loadDescription}, {@link #loadAuthor} and + * {@link #loadContextDescription(PackageManager)}, so the user gets to know further information + * about this wallpaper. + * + * @return Whether any metadata should be shown when previewing the wallpaper. + */ + public boolean getShowMetadataInPreview() { + return mShowMetadataInPreview; + } + /** * Return the class name of an activity that provides a settings UI for * the wallpaper. You can launch this activity be starting it with @@ -287,6 +363,9 @@ public final class WallpaperInfo implements Parcelable { dest.writeInt(mThumbnailResource); dest.writeInt(mAuthorResource); dest.writeInt(mDescriptionResource); + dest.writeInt(mContextUriResource); + dest.writeInt(mContextDescriptionResource); + dest.writeInt(mShowMetadataInPreview ? 1 : 0); mService.writeToParcel(dest, flags); } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 84457b44103048e4a586cd5a51cbb9963cbea79b..aa0eaaebf9758d3cb0c555eaa50659c430a5448a 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -48,9 +48,11 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.ParcelFileDescriptor; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.view.WindowManagerGlobal; @@ -265,7 +267,7 @@ public class WallpaperManager { } static class Globals extends IWallpaperManagerCallback.Stub { - private IWallpaperManager mService; + private final IWallpaperManager mService; private Bitmap mCachedWallpaper; private int mCachedWallpaperUserId; private Bitmap mDefaultWallpaper; @@ -292,16 +294,16 @@ public class WallpaperManager { public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault, @SetWallpaperFlags int which, int userId) { - synchronized (this) { - if (mService != null) { - try { - if (!mService.isWallpaperSupported(context.getOpPackageName())) { - return null; - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + if (mService != null) { + try { + if (!mService.isWallpaperSupported(context.getOpPackageName())) { + return null; } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } + } + synchronized (this) { if (mCachedWallpaper != null && mCachedWallpaperUserId == userId) { return mCachedWallpaper; } @@ -316,17 +318,21 @@ public class WallpaperManager { if (mCachedWallpaper != null) { return mCachedWallpaper; } - if (returnDefault) { - if (mDefaultWallpaper == null) { - mDefaultWallpaper = getDefaultWallpaperLocked(context, which); + } + if (returnDefault) { + Bitmap defaultWallpaper = mDefaultWallpaper; + if (defaultWallpaper == null) { + defaultWallpaper = getDefaultWallpaper(context, which); + synchronized (this) { + mDefaultWallpaper = defaultWallpaper; } - return mDefaultWallpaper; } - return null; + return defaultWallpaper; } + return null; } - public void forgetLoadedWallpaper() { + void forgetLoadedWallpaper() { synchronized (this) { mCachedWallpaper = null; mCachedWallpaperUserId = 0; @@ -361,7 +367,7 @@ public class WallpaperManager { return null; } - private Bitmap getDefaultWallpaperLocked(Context context, @SetWallpaperFlags int which) { + private Bitmap getDefaultWallpaper(Context context, @SetWallpaperFlags int which) { InputStream is = openDefaultWallpaper(context, which); if (is != null) { try { @@ -412,8 +418,14 @@ public class WallpaperManager { * This is returned as an * abstract Drawable that you can install in a View to display whatever * wallpaper the user has currently set. - * - * @return Returns a Drawable object that will draw the wallpaper. + *

+ * This method can return null if there is no system wallpaper available, if + * wallpapers are not supported in the current user, or if the calling app is not + * permitted to access the system wallpaper. + * + * @return Returns a Drawable object that will draw the system wallpaper, + * or {@code null} if no system wallpaper exists or if the calling application + * is not able to access the wallpaper. */ public Drawable getDrawable() { Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM); @@ -783,7 +795,7 @@ public class WallpaperManager { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); } else { - return sGlobals.mService.getWallpaperInfo(); + return sGlobals.mService.getWallpaperInfo(UserHandle.myUserId()); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -928,7 +940,8 @@ public class WallpaperManager { /* Set the wallpaper to the default values */ ParcelFileDescriptor fd = sGlobals.mService.setWallpaper( "res:" + resources.getResourceName(resid), - mContext.getOpPackageName(), null, false, result, which, completion); + mContext.getOpPackageName(), null, false, result, which, completion, + UserHandle.myUserId()); if (fd != null) { FileOutputStream fos = null; boolean ok = false; @@ -1029,6 +1042,19 @@ public class WallpaperManager { public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup, @SetWallpaperFlags int which) throws IOException { + return setBitmap(fullImage, visibleCropHint, allowBackup, which, + UserHandle.myUserId()); + } + + /** + * Like {@link #setBitmap(Bitmap, Rect, boolean, int)}, but allows to pass in an explicit user + * id. If the user id doesn't match the user id the process is running under, calling this + * requires permission {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}. + * @hide + */ + public int setBitmap(Bitmap fullImage, Rect visibleCropHint, + boolean allowBackup, @SetWallpaperFlags int which, int userId) + throws IOException { validateRect(visibleCropHint); if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); @@ -1039,7 +1065,7 @@ public class WallpaperManager { try { ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null, mContext.getOpPackageName(), visibleCropHint, allowBackup, - result, which, completion); + result, which, completion, userId); if (fd != null) { FileOutputStream fos = null; try { @@ -1165,7 +1191,7 @@ public class WallpaperManager { try { ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null, mContext.getOpPackageName(), visibleCropHint, allowBackup, - result, which, completion); + result, which, completion, UserHandle.myUserId()); if (fd != null) { FileOutputStream fos = null; try { @@ -1367,7 +1393,8 @@ public class WallpaperManager { */ @SystemApi public void clearWallpaper() { - clearWallpaper(FLAG_SYSTEM | FLAG_LOCK, mContext.getUserId()); + clearWallpaper(FLAG_LOCK, mContext.getUserId()); + clearWallpaper(FLAG_SYSTEM, mContext.getUserId()); } /** @@ -1399,12 +1426,26 @@ public class WallpaperManager { */ @SystemApi public boolean setWallpaperComponent(ComponentName name) { + return setWallpaperComponent(name, UserHandle.myUserId()); + } + + /** + * Set the live wallpaper. + * + * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT + * permission. The caller must hold the INTERACT_ACROSS_USERS_FULL permission to change + * another user's wallpaper. + * + * @hide + */ + public boolean setWallpaperComponent(ComponentName name, int userId) { if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); } try { - sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName()); + sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName(), + userId); return true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1655,13 +1696,13 @@ public class WallpaperManager { * Only the OS itself may use this method. * @hide */ - public boolean isWallpaperBackupEligible() { + public boolean isWallpaperBackupEligible(int which) { if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); } try { - return sGlobals.mService.isWallpaperBackupEligible(mContext.getUserId()); + return sGlobals.mService.isWallpaperBackupEligible(which, mContext.getUserId()); } catch (RemoteException e) { Log.e(TAG, "Exception querying wallpaper backup eligibility: " + e.getMessage()); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 325a15f1cb30f9d042bc1d56d667806455349724..a2f9bdd2370dcf883d6c8f450a1e26f3dc2a772c 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -416,6 +416,14 @@ public class DevicePolicyManager { */ public static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3; + /** + * Default and maximum timeout in milliseconds after which unlocking with weak auth times out, + * i.e. the user has to use a strong authentication method like password, PIN or pattern. + * + * @hide + */ + public static final long DEFAULT_STRONG_AUTH_TIMEOUT_MS = 72 * 60 * 60 * 1000; // 72h + /** * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that * allows a mobile device management application or NFC programmer application which starts @@ -1275,6 +1283,33 @@ public class DevicePolicyManager { */ public static final int PASSWORD_QUALITY_MANAGED = 0x80000; + /** + * @hide + * + * adb shell dpm set-{device,profile}-owner will normally not allow installing an owner to + * a user with accounts. {@link #ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED} + * and {@link #ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED} are the account features + * used by authenticator to exempt their accounts from this: + * + *

    + *
  • Non-test-only DO/PO still can't be installed when there are accounts. + *

    In order to make an apk test-only, add android:testOnly="true" to the + * <application> tag in the manifest. + * + *

  • Test-only DO/PO can be installed even when there are accounts, as long as all the + * accounts have the {@link #ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED} feature. + * Some authenticators claim to have any features, so to detect it, we also check + * {@link #ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED} and disallow installing + * if any of the accounts have it. + *
+ */ + public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = + "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED"; + + /** @hide See {@link #ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED} */ + public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = + "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED"; + /** * Called by an application that is administering the device to set the password restrictions it * is imposing. After setting this, the user will not be able to enter a new password that is @@ -1315,7 +1350,7 @@ public class DevicePolicyManager { /** * Retrieve the current minimum password quality for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * *

This method can be called on the {@link DevicePolicyManager} instance @@ -1379,7 +1414,7 @@ public class DevicePolicyManager { /** * Retrieve the current minimum password length for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * *

This method can be called on the {@link DevicePolicyManager} instance @@ -1442,7 +1477,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of upper case letters required in the password - * for a particular admin or all admins that set retrictions on this user and + * for a particular admin or all admins that set restrictions on this user and * its participating profiles. Restrictions on profiles that have a separate challenge * are not taken into account. * This is the same value as set by @@ -1511,7 +1546,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of lower case letters required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1580,7 +1615,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of letters required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1648,7 +1683,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of numerical digits required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1716,7 +1751,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of symbols required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. This is the same value as * set by {@link #setPasswordMinimumSymbols(ComponentName, int)} @@ -1783,7 +1818,7 @@ public class DevicePolicyManager { /** * Retrieve the current number of non-letter characters required in the password - * for a particular admin or all admins that set retrictions on this user + * for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * This is the same value as set by @@ -1915,7 +1950,7 @@ public class DevicePolicyManager { /** * Get the current password expiration time for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. If admin is {@code null}, then a composite * of all expiration times is returned - which will be the minimum of all of them. * @@ -1939,7 +1974,7 @@ public class DevicePolicyManager { /** * Retrieve the current password history length for a particular admin or all admins that - * set retrictions on this user and its participating profiles. Restrictions on profiles that + * set restrictions on this user and its participating profiles. Restrictions on profiles that * have a separate challenge are not taken into account. * *

This method can be called on the {@link DevicePolicyManager} instance @@ -2121,7 +2156,7 @@ public class DevicePolicyManager { /** * Retrieve the current maximum number of login attempts that are allowed before the device - * or profile is wiped, for a particular admin or all admins that set retrictions on this user + * or profile is wiped, for a particular admin or all admins that set restrictions on this user * and its participating profiles. Restrictions on profiles that have a separate challenge are * not taken into account. * @@ -2219,6 +2254,7 @@ public class DevicePolicyManager { * @throws SecurityException if the calling application does not own an active administrator * that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} * @throws IllegalStateException if the calling user is locked or has a managed profile. + * @throws IllegalArgumentException if the password does not meet system requirements. */ public boolean resetPassword(String password, int flags) { throwIfParentInstance("resetPassword"); @@ -2262,7 +2298,7 @@ public class DevicePolicyManager { /** * Retrieve the current maximum time to unlock for a particular admin or all admins that set - * retrictions on this user and its participating profiles. Restrictions on profiles that have + * restrictions on this user and its participating profiles. Restrictions on profiles that have * a separate challenge are not taken into account. * *

This method can be called on the {@link DevicePolicyManager} instance @@ -2307,6 +2343,83 @@ public class DevicePolicyManager { return 0; } + /** + * Called by a device/profile owner to set the timeout after which unlocking with secondary, non + * strong auth (e.g. fingerprint, trust agents) times out, i.e. the user has to use a strong + * authentication method like password, pin or pattern. + * + *

This timeout is used internally to reset the timer to require strong auth again after + * specified timeout each time it has been successfully used. + * + *

Fingerprint can also be disabled altogether using {@link #KEYGUARD_DISABLE_FINGERPRINT}. + * + *

Trust agents can also be disabled altogether using {@link #KEYGUARD_DISABLE_TRUST_AGENTS}. + * + *

The calling device admin must be a device or profile owner. If it is not, + * a {@link SecurityException} will be thrown. + * + *

The calling device admin can verify the value it has set by calling + * {@link #getRequiredStrongAuthTimeout(ComponentName)} and passing in its instance. + * + *

This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param timeoutMs The new timeout, after which the user will have to unlock with strong + * authentication method. A value of 0 means the admin is not participating in + * controlling the timeout. + * The minimum and maximum timeouts are platform-defined and are typically 1 hour and + * 72 hours, respectively. Though discouraged, the admin may choose to require strong + * auth at all times using {@link #KEYGUARD_DISABLE_FINGERPRINT} and/or + * {@link #KEYGUARD_DISABLE_TRUST_AGENTS}. + * + * @throws SecurityException if {@code admin} is not a device or profile owner. + * + * @hide + */ + public void setRequiredStrongAuthTimeout(@NonNull ComponentName admin, + long timeoutMs) { + if (mService != null) { + try { + mService.setRequiredStrongAuthTimeout(admin, timeoutMs, mParentInstance); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Determine for how long the user will be able to use secondary, non strong auth for + * authentication, since last strong method authentication (password, pin or pattern) was used. + * After the returned timeout the user is required to use strong authentication method. + * + *

This method can be called on the {@link DevicePolicyManager} instance + * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve + * restrictions on the parent profile. + * + * @param admin The name of the admin component to check, or {@code null} to aggregate + * accross all participating admins. + * @return The timeout or 0 if not configured for the provided admin. + * + * @hide + */ + public long getRequiredStrongAuthTimeout(@Nullable ComponentName admin) { + return getRequiredStrongAuthTimeout(admin, myUserId()); + } + + /** @hide per-user version */ + public long getRequiredStrongAuthTimeout(@Nullable ComponentName admin, @UserIdInt int userId) { + if (mService != null) { + try { + return mService.getRequiredStrongAuthTimeout(admin, userId, mParentInstance); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return DEFAULT_STRONG_AUTH_TIMEOUT_MS; + } + /** * Make the device lock immediately, as if the lock screen timeout has expired at the point of * this call. @@ -2510,6 +2623,8 @@ public class DevicePolicyManager { /** * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryptionStatus}: * indicating that encryption is active. + *

+ * Also see {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}. */ public static final int ENCRYPTION_STATUS_ACTIVE = 3; @@ -2522,7 +2637,11 @@ public class DevicePolicyManager { /** * Result code for {@link #getStorageEncryptionStatus}: - * indicating that encryption is active and the encryption key is tied to the user. + * indicating that encryption is active and the encryption key is tied to the user or profile. + *

+ * This value is only returned to apps targeting API level 24 and above. For apps targeting + * earlier API levels, {@link #ENCRYPTION_STATUS_ACTIVE} is returned, even if the + * encryption key is specific to the user or profile. */ public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; @@ -2649,7 +2768,7 @@ public class DevicePolicyManager { /** * Called by an application that is administering the device to * determine the current encryption status of the device. - * + *

* Depending on the returned status code, the caller may proceed in different * ways. If the result is {@link #ENCRYPTION_STATUS_UNSUPPORTED}, the * storage system does not support encryption. If the @@ -2657,13 +2776,14 @@ public class DevicePolicyManager { * #ACTION_START_ENCRYPTION} to begin the process of encrypting or decrypting the * storage. If the result is {@link #ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY}, the * storage system has enabled encryption but no password is set so further action - * may be required. If the result is {@link #ENCRYPTION_STATUS_ACTIVATING} or - * {@link #ENCRYPTION_STATUS_ACTIVE}, no further action is required. + * may be required. If the result is {@link #ENCRYPTION_STATUS_ACTIVATING}, + * {@link #ENCRYPTION_STATUS_ACTIVE} or {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}, + * no further action is required. * * @return current status of encryption. The value will be one of * {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE}, * {@link #ENCRYPTION_STATUS_ACTIVATING}, {@link #ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY}, - * or {@link #ENCRYPTION_STATUS_ACTIVE}. + * {@link #ENCRYPTION_STATUS_ACTIVE}, or {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}. */ public int getStorageEncryptionStatus() { throwIfParentInstance("getStorageEncryptionStatus"); @@ -3341,7 +3461,7 @@ public class DevicePolicyManager { /** * Determine whether or not features have been disabled in keyguard either by the calling - * admin, if specified, or all admins that set retrictions on this user and its participating + * admin, if specified, or all admins that set restrictions on this user and its participating * profiles. Restrictions on profiles that have a separate challenge are not taken into account. * *

This method can be called on the {@link DevicePolicyManager} instance @@ -6416,9 +6536,77 @@ public class DevicePolicyManager { } } + /** + * @hide + * @return whether {@link android.provider.Settings.Global#DEVICE_PROVISIONED} has ever been set + * to 1. + */ + public boolean isDeviceProvisioned() { + try { + return mService.isDeviceProvisioned(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * @hide + * Writes that the provisioning configuration has been applied. + */ + public void setDeviceProvisioningConfigApplied() { + try { + mService.setDeviceProvisioningConfigApplied(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * @hide + * @return whether the provisioning configuration has been applied. + */ + public boolean isDeviceProvisioningConfigApplied() { + try { + return mService.isDeviceProvisioningConfigApplied(); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + private void throwIfParentInstance(String functionName) { if (mParentInstance) { throw new SecurityException(functionName + " cannot be called on the parent instance"); } } + + /** + * @hide + * Enable backup service. + *

This includes all backup and restore mechanisms. + * Setting this to {@code false} will make backup service no-op or return empty results. + * + *

There must be only one user on the device, managed by the device owner. + * Otherwise a {@link SecurityException} will be thrown. + * + *

Backup service is off by default when device owner is present. + */ + public void setBackupServiceEnabled(@NonNull ComponentName admin, boolean enabled) { + try { + mService.setBackupServiceEnabled(admin, enabled); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** + * @hide + * @return {@code true} if backup service is enabled, {@code false} otherwise. + */ + public boolean isBackupServiceEnabled(@NonNull ComponentName admin) { + try { + return mService.isBackupServiceEnabled(admin); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index ddec412e53c14dd935395f4b3f8d5a9a432279ab..f39cb5ae9fbd95e9198d1d626213857134b4309e 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -82,6 +82,9 @@ interface IDevicePolicyManager { long getMaximumTimeToLock(in ComponentName who, int userHandle, boolean parent); long getMaximumTimeToLockForUserAndProfiles(int userHandle); + void setRequiredStrongAuthTimeout(in ComponentName who, long timeMs, boolean parent); + long getRequiredStrongAuthTimeout(in ComponentName who, int userId, boolean parent); + void lockNow(boolean parent); void wipeData(int flags); @@ -301,4 +304,11 @@ interface IDevicePolicyManager { boolean isUninstallInQueue(String packageName); void uninstallPackageWithActiveAdmins(String packageName); + + boolean isDeviceProvisioned(); + boolean isDeviceProvisioningConfigApplied(); + void setDeviceProvisioningConfigApplied(); + + void setBackupServiceEnabled(in ComponentName admin, boolean enabled); + boolean isBackupServiceEnabled(in ComponentName admin); } diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index bc8280681e4a1ccd1db2d3cbb75dbd1991dec5ba..bad632555c4212ac7cbbe1735ef08458c33ed4da 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -35,6 +35,8 @@ import android.system.StructStat; import android.util.ArraySet; import android.util.Log; +import libcore.io.IoUtils; + import org.xmlpull.v1.XmlPullParserException; import java.io.File; @@ -647,10 +649,11 @@ public abstract class BackupAgent extends ContextWrapper { File file = scanQueue.remove(0); String filePath; try { - // Ignore symlinks outright + // Ignore things that aren't "real" files or dirs StructStat stat = Os.lstat(file.getPath()); - if (OsConstants.S_ISLNK(stat.st_mode)) { - if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file); + if (!OsConstants.S_ISREG(stat.st_mode) + && !OsConstants.S_ISDIR(stat.st_mode)) { + if (DEBUG) Log.i(TAG, "Not a file/dir (skipping)!: " + file); continue; } @@ -921,6 +924,13 @@ public abstract class BackupAgent extends ContextWrapper { } catch (RemoteException e) { // we'll time out anyway, so we're safe } + + // Don't close the fd out from under the system service if this was local + if (Binder.getCallingPid() != Process.myPid()) { + IoUtils.closeQuietly(oldState); + IoUtils.closeQuietly(data); + IoUtils.closeQuietly(newState); + } } } @@ -951,6 +961,11 @@ public abstract class BackupAgent extends ContextWrapper { } catch (RemoteException e) { // we'll time out anyway, so we're safe } + + if (Binder.getCallingPid() != Process.myPid()) { + IoUtils.closeQuietly(data); + IoUtils.closeQuietly(newState); + } } } @@ -994,6 +1009,10 @@ public abstract class BackupAgent extends ContextWrapper { } catch (RemoteException e) { // we'll time out anyway, so we're safe } + + if (Binder.getCallingPid() != Process.myPid()) { + IoUtils.closeQuietly(data); + } } } @@ -1041,6 +1060,10 @@ public abstract class BackupAgent extends ContextWrapper { } catch (RemoteException e) { // we'll time out anyway, so we're safe } + + if (Binder.getCallingPid() != Process.myPid()) { + IoUtils.closeQuietly(data); + } } } diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 7fcca0969f75966d7c69bc1b180f51cd5989e876..80bc1364fa58755331d0f9681bb445b3d2d345eb 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -128,6 +128,14 @@ public class BackupManager { @SystemApi public static final int ERROR_AGENT_FAILURE = BackupTransport.AGENT_ERROR; + /** + * Intent extra when any subsidiary backup-related UI is launched from Settings: does + * device policy or configuration permit backup operations to run at all? + * + * @hide + */ + public static final String EXTRA_BACKUP_SERVICES_AVAILABLE = "backup_services_available"; + private Context mContext; private static IBackupManager sService; diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index 478024d7d27cd5c5dab1e717e81f04dc01ca31cb..76828eeba78567bbb0c8aa9018a7b31e7aee964f 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -21,6 +21,8 @@ import android.content.pm.PackageManager; import android.content.res.XmlResourceParser; import android.os.ParcelFileDescriptor; import android.os.Process; +import android.os.storage.StorageManager; +import android.os.storage.StorageVolume; import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; @@ -223,8 +225,12 @@ public class FullBackup { final int mFullBackupContent; final PackageManager mPackageManager; + final StorageManager mStorageManager; final String mPackageName; + // lazy initialized, only when needed + private StorageVolume[] mVolumes = null; + /** * Parse out the semantic domains into the correct physical location. */ @@ -260,16 +266,41 @@ public class FullBackup { } else { return null; } + } else if (domainToken.startsWith(FullBackup.SHARED_PREFIX)) { + return sharedDomainToPath(domainToken); } // Not a supported location Log.i(TAG, "Unrecognized domain " + domainToken); return null; - } catch (IOException e) { + } catch (Exception e) { Log.i(TAG, "Error reading directory for domain: " + domainToken); return null; } } + + private String sharedDomainToPath(String domain) throws IOException { + // already known to start with SHARED_PREFIX, so we just look after that + final String volume = domain.substring(FullBackup.SHARED_PREFIX.length()); + final StorageVolume[] volumes = getVolumeList(); + final int volNum = Integer.parseInt(volume); + if (volNum < mVolumes.length) { + return volumes[volNum].getPathFile().getCanonicalPath(); + } + return null; + } + + private StorageVolume[] getVolumeList() { + if (mStorageManager != null) { + if (mVolumes == null) { + mVolumes = mStorageManager.getVolumeList(); + } + } else { + Log.e(TAG, "Unable to access Storage Manager"); + } + return mVolumes; + } + /** * A map of domain -> list of canonical file names in that domain that are to be included. * We keep track of the domain so that we can go through the file system in order later on. @@ -283,6 +314,7 @@ public class FullBackup { BackupScheme(Context context) { mFullBackupContent = context.getApplicationInfo().fullBackupContent; + mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); mPackageManager = context.getPackageManager(); mPackageName = context.getPackageName(); diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java index f256a9536061b1e3426dcdd1bcb87e3f19d3f06c..f9874685167860be38fb0e5aa117dff18e0179b4 100644 --- a/core/java/android/app/backup/WallpaperBackupHelper.java +++ b/core/java/android/app/backup/WallpaperBackupHelper.java @@ -42,7 +42,7 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu // If 'true', then apply an acceptable-size heuristic at restore time, dropping back // to the factory default wallpaper if the restored one differs "too much" from the // device's preferred wallpaper image dimensions. - private static final boolean REJECT_OUTSIZED_RESTORE = true; + private static final boolean REJECT_OUTSIZED_RESTORE = false; // When outsized restore rejection is enabled, this is the maximum ratio between the // source and target image heights that will be permitted. The ratio is checked both @@ -60,6 +60,9 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu public static final String WALLPAPER_IMAGE = new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM), "wallpaper").getAbsolutePath(); + public static final String WALLPAPER_ORIG_IMAGE = + new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM), + "wallpaper_orig").getAbsolutePath(); public static final String WALLPAPER_INFO = new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM), "wallpaper_info.xml").getAbsolutePath(); @@ -199,7 +202,7 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu // since it does not exist anywhere other than the private wallpaper // file. Slog.d(TAG, "Applying restored wallpaper image."); - f.renameTo(new File(WALLPAPER_IMAGE)); + f.renameTo(new File(WALLPAPER_ORIG_IMAGE)); } } } diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index 5823abf9d78fd8495538dde277b401641a205d95..734bf6917eca4d92b27086fa048c8c6194966395 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -165,6 +165,9 @@ public class JobInfo implements Parcelable { * network restrictions for the requesting app. Note that this flag alone * doesn't actually place your {@link JobService} in the foreground; you * still need to post the notification yourself. + *

+ * To use this flag, the caller must hold the + * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} permission. * * @hide */ diff --git a/core/java/android/app/package.html b/core/java/android/app/package.html index f37f1dcc8401df0acba9c925f3d7c54520e68f1c..b259cadc2bceb689e9317f14dd3057a2a902ebc4 100644 --- a/core/java/android/app/package.html +++ b/core/java/android/app/package.html @@ -34,7 +34,7 @@ action bar.

For information about using some the classes in this package, see the following documents: Activities, Services, Fragments, Fragments, Using the Action Bar, Creating Dialogs, and Notifying the User.

diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 24647f388fc128a3fd1a867a10654cc1d3fa772a..a0da258bdf1cd7f8aa5ffeb72f432e0936f67977 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -78,6 +78,13 @@ public final class UsageEvents implements Parcelable { */ public static final int USER_INTERACTION = 7; + /** + * An event type denoting that an action equivalent to a ShortcutInfo is taken by the user. + * + * @see android.content.pm.ShortcutManager#reportShortcutUsed(String) + */ + public static final int SHORTCUT_INVOCATION = 8; + /** * {@hide} */ @@ -104,6 +111,13 @@ public final class UsageEvents implements Parcelable { */ public Configuration mConfiguration; + /** + * ID of the shortcut. + * Only present for {@link #SHORTCUT_INVOCATION} event types. + * {@hide} + */ + public String mShortcutId; + /** * The package name of the source of this event. */ @@ -145,6 +159,16 @@ public final class UsageEvents implements Parcelable { public Configuration getConfiguration() { return mConfiguration; } + + /** + * Returns the ID of a {@link android.content.pm.ShortcutInfo} for this event + * if the event is of type {@link #SHORTCUT_INVOCATION}, otherwise it returns null. + * + * @see android.content.pm.ShortcutManager#reportShortcutUsed(String) + */ + public String getShortcutId() { + return mShortcutId; + } } // Only used when creating the resulting events. Not used for reading/unparceling. @@ -276,8 +300,13 @@ public final class UsageEvents implements Parcelable { p.writeInt(event.mEventType); p.writeLong(event.mTimeStamp); - if (event.mEventType == Event.CONFIGURATION_CHANGE) { - event.mConfiguration.writeToParcel(p, flags); + switch (event.mEventType) { + case Event.CONFIGURATION_CHANGE: + event.mConfiguration.writeToParcel(p, flags); + break; + case Event.SHORTCUT_INVOCATION: + p.writeString(event.mShortcutId); + break; } } @@ -301,11 +330,18 @@ public final class UsageEvents implements Parcelable { eventOut.mEventType = p.readInt(); eventOut.mTimeStamp = p.readLong(); - // Extract the configuration for configuration change events. - if (eventOut.mEventType == Event.CONFIGURATION_CHANGE) { - eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p); - } else { - eventOut.mConfiguration = null; + // Fill out the event-dependant fields. + eventOut.mConfiguration = null; + eventOut.mShortcutId = null; + + switch (eventOut.mEventType) { + case Event.CONFIGURATION_CHANGE: + // Extract the configuration for configuration change events. + eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p); + break; + case Event.SHORTCUT_INVOCATION: + eventOut.mShortcutId = p.readString(); + break; } } diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java index b6f1567568c29048ad6417cd4bedceb6d758fc67..a6f91fe1722758d7b620d42bd68a03ab91254265 100644 --- a/core/java/android/app/usage/UsageStatsManagerInternal.java +++ b/core/java/android/app/usage/UsageStatsManagerInternal.java @@ -55,6 +55,17 @@ public abstract class UsageStatsManagerInternal { */ public abstract void reportConfigurationChange(Configuration config, int userId); + /** + * Reports that an action equivalent to a ShortcutInfo is taken by the user. + * + * @param packageName The package name of the shortcut publisher + * @param shortcutId The ID of the shortcut in question + * @param userId The user in which the content provider was accessed. + * + * @see android.content.pm.ShortcutManager#reportShortcutUsed(String) + */ + public abstract void reportShortcutUsage(String packageName, String shortcutId, int userId); + /** * Reports that a content provider has been accessed by a foreground app. * @param name The authority of the content provider diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index 2d9f4a71b0054845ad07b7aa38f933a80a47bae2..cd144695a989dd744faf1fc99f9db073aa5c886a 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -34,7 +34,6 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.SparseArray; import android.util.TypedValue; @@ -187,19 +186,28 @@ public class AppWidgetHost { idsToUpdate[i] = mViews.keyAt(i); } } - List updatedViews; - int[] updatedIds = new int[idsToUpdate.length]; + List updates; try { - updatedViews = sService.startListening( - mCallbacks, mContextOpPackageName, mHostId, idsToUpdate, updatedIds).getList(); + updates = sService.startListening( + mCallbacks, mContextOpPackageName, mHostId, idsToUpdate).getList(); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } - int N = updatedViews.size(); + int N = updates.size(); for (int i = 0; i < N; i++) { - updateAppWidgetView(updatedIds[i], updatedViews.get(i)); + PendingHostUpdate update = updates.get(i); + switch (update.type) { + case PendingHostUpdate.TYPE_VIEWS_UPDATE: + updateAppWidgetView(update.appWidgetId, update.views); + break; + case PendingHostUpdate.TYPE_PROVIDER_CHANGED: + onProviderChanged(update.appWidgetId, update.widgetInfo); + break; + case PendingHostUpdate.TYPE_VIEW_DATA_CHANGED: + viewDataChanged(update.appWidgetId, update.viewId); + } } } diff --git a/core/java/android/appwidget/PendingHostUpdate.java b/core/java/android/appwidget/PendingHostUpdate.java new file mode 100644 index 0000000000000000000000000000000000000000..578031908f52e3ff935870b469d4da1619457f94 --- /dev/null +++ b/core/java/android/appwidget/PendingHostUpdate.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.appwidget; + +import android.os.Parcel; +import android.os.Parcelable; +import android.widget.RemoteViews; + +/** + * @hide + */ +public class PendingHostUpdate implements Parcelable { + + static final int TYPE_VIEWS_UPDATE = 0; + static final int TYPE_PROVIDER_CHANGED = 1; + static final int TYPE_VIEW_DATA_CHANGED = 2; + + final int appWidgetId; + final int type; + RemoteViews views; + AppWidgetProviderInfo widgetInfo; + int viewId; + + public static PendingHostUpdate updateAppWidget(int appWidgetId, RemoteViews views) { + PendingHostUpdate update = new PendingHostUpdate(appWidgetId, TYPE_VIEWS_UPDATE); + update.views = views; + return update; + } + + public static PendingHostUpdate providerChanged(int appWidgetId, AppWidgetProviderInfo info) { + PendingHostUpdate update = new PendingHostUpdate(appWidgetId, TYPE_PROVIDER_CHANGED); + update.widgetInfo = info; + return update; + } + + public static PendingHostUpdate viewDataChanged(int appWidgetId, int viewId) { + PendingHostUpdate update = new PendingHostUpdate(appWidgetId, TYPE_VIEW_DATA_CHANGED); + update.viewId = viewId; + return update; + } + + private PendingHostUpdate(int appWidgetId, int type) { + this.appWidgetId = appWidgetId; + this.type = type; + } + + private PendingHostUpdate(Parcel in) { + appWidgetId = in.readInt(); + type = in.readInt(); + + switch (type) { + case TYPE_VIEWS_UPDATE: + if (0 != in.readInt()) { + views = new RemoteViews(in); + } + break; + case TYPE_PROVIDER_CHANGED: + if (0 != in.readInt()) { + widgetInfo = new AppWidgetProviderInfo(in); + } + break; + case TYPE_VIEW_DATA_CHANGED: + viewId = in.readInt(); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(appWidgetId); + dest.writeInt(type); + switch (type) { + case TYPE_VIEWS_UPDATE: + writeNullParcelable(views, dest, flags); + break; + case TYPE_PROVIDER_CHANGED: + writeNullParcelable(widgetInfo, dest, flags); + break; + case TYPE_VIEW_DATA_CHANGED: + dest.writeInt(viewId); + break; + } + } + + private void writeNullParcelable(Parcelable p, Parcel dest, int flags) { + if (p != null) { + dest.writeInt(1); + p.writeToParcel(dest, flags); + } else { + dest.writeInt(0); + } + } + + /** + * Parcelable.Creator that instantiates PendingHostUpdate objects + */ + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public PendingHostUpdate createFromParcel(Parcel parcel) { + return new PendingHostUpdate(parcel); + } + + public PendingHostUpdate[] newArray(int size) { + return new PendingHostUpdate[size]; + } + }; +} diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index f66b5ff466c3f790d84aabe3b330edc4b60ae8ad..353c6400ffd74d8ee1446df58660b7eb7979b290 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -30,8 +30,11 @@ import android.os.ParcelUuid; import android.os.RemoteException; import android.util.Log; +import com.android.internal.annotations.GuardedBy; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** @@ -114,7 +117,8 @@ public final class BluetoothA2dp implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private IBluetoothA2dp mService; + private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); + @GuardedBy("mServiceLock") private IBluetoothA2dp mService; private BluetoothAdapter mAdapter; final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -122,25 +126,27 @@ public final class BluetoothA2dp implements BluetoothProfile { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); - synchronized (mConnection) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); - } + if (VDBG) Log.d(TAG, "Unbinding service..."); + try { + mServiceLock.writeLock().lock(); + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG, "", re); + } finally { + mServiceLock.writeLock().unlock(); } } else { - synchronized (mConnection) { - try { - if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); - doBind(); - } - } catch (Exception re) { - Log.e(TAG,"",re); + try { + mServiceLock.readLock().lock(); + if (mService == null) { + if (VDBG) Log.d(TAG,"Binding service..."); + doBind(); } + } catch (Exception re) { + Log.e(TAG,"",re); + } finally { + mServiceLock.readLock().unlock(); } } } @@ -189,15 +195,16 @@ public final class BluetoothA2dp implements BluetoothProfile { } } - synchronized (mConnection) { + try { + mServiceLock.writeLock().lock(); if (mService != null) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); - } + mService = null; + mContext.unbindService(mConnection); } + } catch (Exception re) { + Log.e(TAG, "", re); + } finally { + mServiceLock.writeLock().unlock(); } } @@ -229,17 +236,20 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() && + isValidDevice(device)) { return mService.connect(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; } /** @@ -270,17 +280,20 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() && + isValidDevice(device)) { return mService.disconnect(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; } /** @@ -288,16 +301,19 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public List getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { return mService.getConnectedDevices(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList(); + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); } /** @@ -305,16 +321,19 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public List getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { return mService.getDevicesMatchingConnectionStates(states); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList(); + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return new ArrayList(); + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); } /** @@ -322,17 +341,20 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { return mService.getConnectionState(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; } /** @@ -352,21 +374,24 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON){ - return false; - } - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF && + priority != BluetoothProfile.PRIORITY_ON) { + return false; + } return mService.setPriority(device, priority); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; } /** @@ -385,17 +410,20 @@ public final class BluetoothA2dp implements BluetoothProfile { @RequiresPermission(Manifest.permission.BLUETOOTH) public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { return mService.getPriority(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.PRIORITY_OFF; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.PRIORITY_OFF; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return BluetoothProfile.PRIORITY_OFF; + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.PRIORITY_OFF; } /** @@ -406,16 +434,19 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public boolean isAvrcpAbsoluteVolumeSupported() { if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported"); - if (mService != null && isEnabled()) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { return mService.isAvrcpAbsoluteVolumeSupported(); - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e); - return false; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e); + return false; + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; } /** @@ -433,16 +464,17 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public void adjustAvrcpAbsoluteVolume(int direction) { if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume"); - if (mService != null && isEnabled()) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { mService.adjustAvrcpAbsoluteVolume(direction); - return; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e); - return; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + } catch (RemoteException e) { + Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e); + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); } /** @@ -453,16 +485,17 @@ public final class BluetoothA2dp implements BluetoothProfile { */ public void setAvrcpAbsoluteVolume(int volume) { if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume"); - if (mService != null && isEnabled()) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled()) { mService.setAvrcpAbsoluteVolume(volume); - return; - } catch (RemoteException e) { - Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e); - return; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + } catch (RemoteException e) { + Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e); + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); } /** @@ -473,17 +506,20 @@ public final class BluetoothA2dp implements BluetoothProfile { * @param device BluetoothDevice device */ public boolean isA2dpPlaying(BluetoothDevice device) { - if (mService != null && isEnabled() - && isValidDevice(device)) { - try { + try { + mServiceLock.readLock().lock(); + if (mService != null && isEnabled() + && isValidDevice(device)) { return mService.isA2dpPlaying(device); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } catch (RemoteException e) { + Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); + return false; + } finally { + mServiceLock.readLock().unlock(); } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); - return false; } /** @@ -534,7 +570,12 @@ public final class BluetoothA2dp implements BluetoothProfile { private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); - mService = IBluetoothA2dp.Stub.asInterface(service); + try { + mServiceLock.writeLock().lock(); + mService = IBluetoothA2dp.Stub.asInterface(service); + } finally { + mServiceLock.writeLock().unlock(); + } if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this); @@ -542,7 +583,12 @@ public final class BluetoothA2dp implements BluetoothProfile { } public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); - mService = null; + try { + mServiceLock.writeLock().lock(); + mService = null; + } finally { + mServiceLock.writeLock().unlock(); + } if (mServiceListener != null) { mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP); } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 4271e3f99dff2d327e873da36d465fc280a0b785..d419d0384f5cd489d7c3069f974457a8711315ed 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -23,7 +23,6 @@ import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; -import android.app.ActivityThread; import android.bluetooth.le.BluetoothLeAdvertiser; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; @@ -90,8 +89,11 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * *
*

Developer Guides

- *

For more information about using Bluetooth, read the - * Bluetooth developer guide. + *

+ * For more information about using Bluetooth, read the Bluetooth developer + * guide. + *

*
* * {@see BluetoothDevice} @@ -252,29 +254,6 @@ public final class BluetoothAdapter { public static final String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE"; - /** - * Activity Action: Show a system activity that allows the user to turn off - * Bluetooth. This is used only if permission review is enabled which is for - * apps targeting API less than 23 require a permission review before any of - * the app's components can run. - *

This system activity will return once Bluetooth has completed turning - * off, or the user has decided not to turn Bluetooth off. - *

Notification of the result of this activity is posted using the - * {@link android.app.Activity#onActivityResult} callback. The - * resultCode - * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been - * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user - * has rejected the request or an error has occurred. - *

Applications can also listen for {@link #ACTION_STATE_CHANGED} - * for global notification whenever Bluetooth is turned on or off. - *

Requires {@link android.Manifest.permission#BLUETOOTH} - * - * @hide - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_REQUEST_DISABLE = - "android.bluetooth.adapter.action.REQUEST_DISABLE"; - /** * Activity Action: Show a system activity that allows user to enable BLE scans even when * Bluetooth is turned off.

@@ -789,7 +768,7 @@ public final class BluetoothAdapter { return true; } if (DBG) Log.d(TAG, "enableBLE(): Calling enable"); - return mManagerService.enable(ActivityThread.currentPackageName()); + return mManagerService.enable(); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -916,7 +895,7 @@ public final class BluetoothAdapter { return true; } try { - return mManagerService.enable(ActivityThread.currentPackageName()); + return mManagerService.enable(); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -948,7 +927,7 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean disable() { try { - return mManagerService.disable(ActivityThread.currentPackageName(), true); + return mManagerService.disable(true); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -966,7 +945,7 @@ public final class BluetoothAdapter { public boolean disable(boolean persist) { try { - return mManagerService.disable(ActivityThread.currentPackageName(), persist); + return mManagerService.disable(persist); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index ce54637d883364ed85815562ddb32af5995b2c2a..5c9e2ee4fc423cfded846e10d39646e5de7bbfca 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -59,8 +59,11 @@ import java.util.UUID; * *

*

Developer Guides

- *

For more information about using Bluetooth, read the - * Bluetooth developer guide.

+ *

+ * For more information about using Bluetooth, read the Bluetooth developer + * guide. + *

*
* * {@see BluetoothAdapter} @@ -1172,12 +1175,12 @@ public final class BluetoothDevice implements Parcelable { /** * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing. - *

Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. + *

Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. * * @return true confirmation has been sent out * false for error */ - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPairingConfirmation(boolean confirm) { if (sService == null) { Log.e(TAG, "BT not enabled. Cannot set pairing confirmation"); @@ -1601,7 +1604,7 @@ public final class BluetoothDevice implements Parcelable { // BLE is not supported return null; } - BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this, transport); + BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport); gatt.connect(autoConnect, callback); return gatt; } catch (RemoteException e) {Log.e(TAG, "", e);} diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index f76d62d3c41945da0b337af87ca1717b60ba096b..97a32974d2ab4756b30b480bcb6ef8c89e47f8fe 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -41,7 +41,6 @@ public final class BluetoothGatt implements BluetoothProfile { private static final boolean DBG = true; private static final boolean VDBG = false; - private final Context mContext; private IBluetoothGatt mService; private BluetoothGattCallback mCallback; private int mClientIf; @@ -503,9 +502,8 @@ public final class BluetoothGatt implements BluetoothProfile { } }; - /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device, + /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device, int transport) { - mContext = context; mService = iGatt; mDevice = device; mTransport = transport; diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java index c2bcbb2df6366a71a1468f12b87859407fe0fc7a..5ffceba5e11d7d746be35af42c609bd6e47a049b 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java @@ -44,7 +44,6 @@ public final class BluetoothGattServer implements BluetoothProfile { private static final boolean DBG = true; private static final boolean VDBG = false; - private final Context mContext; private BluetoothAdapter mAdapter; private IBluetoothGatt mService; private BluetoothGattServerCallback mCallback; @@ -298,8 +297,7 @@ public final class BluetoothGattServer implements BluetoothProfile { /** * Create a BluetoothGattServer proxy object. */ - /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt, int transport) { - mContext = context; + /*package*/ BluetoothGattServer(IBluetoothGatt iGatt, int transport) { mService = iGatt; mAdapter = BluetoothAdapter.getDefaultAdapter(); mCallback = null; diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java index 15a9101452edd7bfc9f818b416a9552927da6573..1717a1e36e1f69dff73ebeb130a76cafee3ea107 100644 --- a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java +++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java @@ -68,7 +68,9 @@ public final class BluetoothHealthAppConfiguration implements Parcelable { public boolean equals(Object o) { if (o instanceof BluetoothHealthAppConfiguration) { BluetoothHealthAppConfiguration config = (BluetoothHealthAppConfiguration) o; - // config.getName() can never be NULL + + if (mName == null) return false; + return mName.equals(config.getName()) && mDataType == config.getDataType() && mRole == config.getRole() && diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java index 35437a1fd7078a99ed39f6eb65fb1e123ec86939..29283e793ce931c15ccde9567a257d915e9f2341 100644 --- a/core/java/android/bluetooth/BluetoothManager.java +++ b/core/java/android/bluetooth/BluetoothManager.java @@ -38,8 +38,11 @@ import java.util.List; * *

*

Developer Guides

- *

For more information about using BLUETOOTH, read the - * Bluetooth developer guide.

+ *

+ * For more information about using BLUETOOTH, read the Bluetooth developer + * guide. + *

*
* * @see Context#getSystemService @@ -233,7 +236,7 @@ public final class BluetoothManager { Log.e(TAG, "Fail to get GATT Server connection"); return null; } - BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt,transport); + BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt,transport); Boolean regStatus = mGattServer.registerCallback(callback); return regStatus? mGattServer : null; } catch (RemoteException e) { diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java index 014cb22c57b389698ef670b1a04407c790cef177..e70c936e253e1b8bcf2ea91ab751290bd335e39b 100644 --- a/core/java/android/bluetooth/BluetoothSap.java +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -138,7 +138,7 @@ public final class BluetoothSap implements BluetoothProfile { } boolean doBind() { - Intent intent = new Intent(IBluetoothMap.class.getName()); + Intent intent = new Intent(IBluetoothSap.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 1e99eceeecec22f9aae9ff0983176d8f62faa449..b68693880acfa6dc5c6423de981e6a3ac025276e 100644 --- a/core/java/android/bluetooth/BluetoothSocket.java +++ b/core/java/android/bluetooth/BluetoothSocket.java @@ -532,22 +532,19 @@ public final class BluetoothSocket implements Closeable { if(length <= mMaxTxPacketSize) { mSocketOS.write(b, offset, length); } else { - int tmpOffset = offset; - int tmpLength = mMaxTxPacketSize; - int endIndex = offset + length; - boolean done = false; if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n" + "Packet will be divided into SDU packets of size " + mMaxTxPacketSize); - do{ + int tmpOffset = offset; + int bytesToWrite = length; + while (bytesToWrite > 0) { + int tmpLength = (bytesToWrite > mMaxTxPacketSize) + ? mMaxTxPacketSize + : bytesToWrite; mSocketOS.write(b, tmpOffset, tmpLength); - tmpOffset += mMaxTxPacketSize; - if((tmpOffset + mMaxTxPacketSize) > endIndex) { - tmpLength = endIndex - tmpOffset; - done = true; - } - } while(!done); - + tmpOffset += tmpLength; + bytesToWrite -= tmpLength; + } } } else { mSocketOS.write(b, offset, length); diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl index f39ca8e0e9c865c581f99cb317cc3d82d50c4fa1..2b853a373b522ab47f0cffe750b369a5b1b39707 100644 --- a/core/java/android/bluetooth/IBluetoothManager.aidl +++ b/core/java/android/bluetooth/IBluetoothManager.aidl @@ -34,9 +34,10 @@ interface IBluetoothManager void registerStateChangeCallback(in IBluetoothStateChangeCallback callback); void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback); boolean isEnabled(); - boolean enable(String packageName); + boolean enable(); boolean enableNoAutoConnect(); - boolean disable(String packageName, boolean persist); + boolean disable(boolean persist); + int getState(); IBluetoothGatt getBluetoothGatt(); boolean bindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy); @@ -49,4 +50,3 @@ interface IBluetoothManager int updateBleAppCount(IBinder b, boolean enable); boolean isBleAppPresent(); } - diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index c365e9ee9549417a27e5d53a85a32137fed67c55..d9816a64db3a7a5f0719ded6aea5fe8369d1bf22 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -191,6 +191,14 @@ public class ClipData implements Parcelable { final Intent mIntent; Uri mUri; + /** @hide */ + public Item(Item other) { + mText = other.mText; + mHtmlText = other.mHtmlText; + mIntent = other.mIntent; + mUri = other.mUri; + } + /** * Create an Item consisting of a single block of (possibly styled) text. */ @@ -816,6 +824,11 @@ public class ClipData implements Parcelable { return mItems.get(index); } + /** @hide */ + public void setItemAt(int index, Item item) { + mItems.set(index, item); + } + /** * Prepare this {@link ClipData} to leave an app process. * diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index c8d89204d8d4889b873b943597b9eb89e1e0cc3f..daa1b93889cccc0c7d2b7d6c8b070a2218e1177b 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -34,6 +34,7 @@ import android.database.CrossProcessCursorWrapper; import android.database.Cursor; import android.database.IContentObserver; import android.graphics.Point; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; @@ -51,6 +52,7 @@ import android.util.EventLog; import android.util.Log; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.MimeIconUtils; import com.android.internal.util.Preconditions; import dalvik.system.CloseGuard; @@ -1875,6 +1877,7 @@ public abstract class ContentResolver { if (extras != null) { String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT); if (!TextUtils.isEmpty(accountName)) { + // TODO: No references to Google in AOSP account = new Account(accountName, "com.google"); } extras.remove(SYNC_EXTRAS_ACCOUNT); @@ -2693,4 +2696,9 @@ public abstract class ContentResolver { public int resolveUserId(Uri uri) { return ContentProvider.getUserIdFromUri(uri, mContext.getUserId()); } + + /** @hide */ + public Drawable getTypeDrawable(String mimeType) { + return MimeIconUtils.loadMimeIcon(mContext, mimeType); + } } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index b79c72e03141af2e74b2be94c4535a3b52486ad2..fd11031d5d7b5d1c17f6857f62f5472868e72a0d 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1130,7 +1130,9 @@ public abstract class Context { * Note: you should not rely on the system deleting these * files for you; you should always have a reasonable maximum, such as 1 MB, * for the amount of space you consume with cache files, and prune those - * files when exceeding that space. + * files when exceeding that space. If your app requires a larger + * cache (larger than 1 MB), you should use {@link #getExternalCacheDir()} + * instead. *

* The returned path may change over time if the calling app is moved to an * adopted storage device, so only relative paths should be persisted. @@ -1142,6 +1144,7 @@ public abstract class Context { * @see #openFileOutput * @see #getFileStreamPath * @see #getDir + * @see #getExternalCacheDir */ public abstract File getCacheDir(); @@ -1190,7 +1193,7 @@ public abstract class Context { * *

* If a shared storage device is emulated (as determined by - * {@link Environment#isExternalStorageEmulated(File)}), it's contents are + * {@link Environment#isExternalStorageEmulated(File)}), its contents are * backed by a private user data partition, which means there is little * benefit to storing data here instead of the private directory returned by * {@link #getCacheDir()}. @@ -2761,8 +2764,10 @@ public abstract class Context { *

A {@link android.net.ConnectivityManager ConnectivityManager} for * handling management of network connections. *
{@link #WIFI_SERVICE} ("wifi") - *
A {@link android.net.wifi.WifiManager WifiManager} for management of - * Wi-Fi connectivity. + *
A {@link android.net.wifi.WifiManager WifiManager} for management of Wi-Fi + * connectivity. On releases before NYC, it should only be obtained from an application + * context, and not from any other derived context to avoid memory leaks within the calling + * process. *
{@link #WIFI_P2P_SERVICE} ("wifip2p") *
A {@link android.net.wifi.p2p.WifiP2pManager WifiP2pManager} for management of * Wi-Fi Direct connectivity. @@ -3615,12 +3620,11 @@ public abstract class Context { public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; /** - * TODO Javadoc + * Use with {@link #getSystemService} to retrieve a + * {@link android.content.pm.ShortcutManager} for accessing the launcher shortcut service. * * @see #getSystemService * @see android.content.pm.ShortcutManager - * - * @hide */ public static final String SHORTCUT_SERVICE = "shortcut"; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index ace54ba9ef43037c0b8e6c51ac0ee50fa31eb41d..c6aaa48ddad09b0fe0f1ff3759445bc94b9462a4 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -128,7 +128,7 @@ import static android.content.ContentProvider.maybeAddUserId; * a list of people, which the user can browse through. This example is a * typical top-level entry into the Contacts application, showing you the * list of people. Selecting a particular person to view would result in a - * new intent { {@link #ACTION_VIEW} content://contacts/N } + * new intent { {@link #ACTION_VIEW} content://contacts/people/N } * being used to start an activity to display that person.

* * @@ -2218,6 +2218,22 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE = "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE"; + /** + * Broadcast Action: preferred activities have changed *explicitly*. + * + *

Note there are cases where a preferred activity is invalidated *implicitly*, e.g. + * when an app is installed or uninstalled, but in such cases this broadcast will *not* + * be sent. + * + * {@link #EXTRA_USER_HANDLE} contains the user ID in question. + * + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_PREFERRED_ACTIVITY_CHANGED = + "android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED"; + + /** * Broadcast Action: The current system wallpaper has changed. See * {@link android.app.WallpaperManager} for retrieving the new wallpaper. @@ -3173,6 +3189,14 @@ public class Intent implements Parcelable, Cloneable { /** {@hide} */ public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR"; + /** + * Boolean intent extra to be used with {@link ACTION_MASTER_CLEAR} in order to force a factory + * reset even if {@link android.os.UserManager.DISALLOW_FACTORY_RESET} is set. + * @hide + */ + public static final String EXTRA_FORCE_MASTER_CLEAR = + "android.intent.extra.FORCE_MASTER_CLEAR"; + /** * Broadcast action: report that a settings element is being restored from backup. The intent * contains three extras: EXTRA_SETTING_NAME is a string naming the restored setting, @@ -4289,6 +4313,14 @@ public class Intent implements Parcelable, Cloneable { */ public static final int FLAG_DEBUG_TRIAGED_MISSING = 0x00000100; + /** + * Internal flag used to indicate ephemeral applications should not be + * considered when resolving the intent. + * + * @hide + */ + public static final int FLAG_IGNORE_EPHEMERAL = 0x00000200; + /** * If set, the new activity is not kept in the history stack. As soon as * the user navigates away from it, the activity is finished. This may also @@ -6541,7 +6573,7 @@ public class Intent implements Parcelable, Cloneable { */ public void removeUnsafeExtras() { if (mExtras != null) { - mExtras.filterValues(); + mExtras = mExtras.filterValues(); } } diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 22ab43bbb42921315f63d713e8ca92ead790a886..f5a79c8c13eb33dc3d1ee4e8efbbf69fa37463a4 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -124,7 +124,7 @@ import java.util.Set; * Note that authority matching here is case sensitive, unlike * formal RFC host names! You should thus always use lower case letters * for your authority. - * + * *

Data Path matches if any of the given values match the * Intent's data path and both a scheme and authority in the filter * has matched against the Intent, or no paths were supplied in the @@ -265,6 +265,7 @@ public class IntentFilter implements Parcelable { public static final String SCHEME_HTTPS = "https"; private int mPriority; + private int mOrder; private final ArrayList mActions; private ArrayList mCategories = null; private ArrayList mDataSchemes = null; @@ -358,8 +359,8 @@ public class IntentFilter implements Parcelable { * the {@link MalformedMimeTypeException} exception that the constructor * can call and turns it into a runtime exception. * - * @param action The action to match, i.e. Intent.ACTION_VIEW. - * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person". + * @param action The action to match, such as Intent.ACTION_VIEW. + * @param dataType The type to match, such as "vnd.android.cursor.dir/person". * * @return A new IntentFilter for the given action and type. * @@ -386,7 +387,7 @@ public class IntentFilter implements Parcelable { * no data characteristics are subsequently specified, then the * filter will only match intents that contain no data. * - * @param action The action to match, i.e. Intent.ACTION_MAIN. + * @param action The action to match, such as Intent.ACTION_MAIN. */ public IntentFilter(String action) { mPriority = 0; @@ -406,8 +407,8 @@ public class IntentFilter implements Parcelable { *

Throws {@link MalformedMimeTypeException} if the given MIME type is * not syntactically correct. * - * @param action The action to match, i.e. Intent.ACTION_VIEW. - * @param dataType The type to match, i.e. "vnd.android.cursor.dir/person". + * @param action The action to match, such as Intent.ACTION_VIEW. + * @param dataType The type to match, such as "vnd.android.cursor.dir/person". * */ public IntentFilter(String action, String dataType) @@ -425,6 +426,7 @@ public class IntentFilter implements Parcelable { */ public IntentFilter(IntentFilter o) { mPriority = o.mPriority; + mOrder = o.mOrder; mActions = new ArrayList(o.mActions); if (o.mCategories != null) { mCategories = new ArrayList(o.mCategories); @@ -477,6 +479,16 @@ public class IntentFilter implements Parcelable { return mPriority; } + /** @hide */ + public final void setOrder(int order) { + mOrder = order; + } + + /** @hide */ + public final int getOrder() { + return mOrder; + } + /** * Set whether this filter will needs to be automatically verified against its data URIs or not. * The default is false. @@ -640,7 +652,7 @@ public class IntentFilter implements Parcelable { * in the filter, then an Intent's action must be one of those values for * it to match. If no actions are included, the Intent action is ignored. * - * @param action Name of the action to match, i.e. Intent.ACTION_VIEW. + * @param action Name of the action to match, such as Intent.ACTION_VIEW. */ public final void addAction(String action) { if (!mActions.contains(action)) { @@ -709,7 +721,7 @@ public class IntentFilter implements Parcelable { *

Throws {@link MalformedMimeTypeException} if the given MIME type is * not syntactically correct. * - * @param type Name of the data type to match, i.e. "vnd.android.cursor.dir/person". + * @param type Name of the data type to match, such as "vnd.android.cursor.dir/person". * * @see #matchData */ @@ -786,7 +798,7 @@ public class IntentFilter implements Parcelable { * and any schemes you receive from outside of Android should be * converted to lower case before supplying them here.

* - * @param scheme Name of the scheme to match, i.e. "http". + * @param scheme Name of the scheme to match, such as "http". * * @see #matchData */ @@ -897,7 +909,7 @@ public class IntentFilter implements Parcelable { * Determine whether this AuthorityEntry matches the given data Uri. * Note that this comparison is case-sensitive, unlike formal * RFC host names. You thus should always normalize to lower-case. - * + * * @param data The Uri to match. * @return Returns either {@link IntentFilter#NO_MATCH_DATA}, * {@link IntentFilter#MATCH_CATEGORY_PORT}, or @@ -1352,7 +1364,7 @@ public class IntentFilter implements Parcelable { * filter has no impact on matching unless that category is specified in * the intent. * - * @param category Name of category to match, i.e. Intent.CATEGORY_EMBED. + * @param category Name of category to match, such as Intent.CATEGORY_EMBED. */ public final void addCategory(String category) { if (mCategories == null) mCategories = new ArrayList(); diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java index c5e0ea727869217d971e7ff641c596762e526577..3faf13b601ad3b3be2d15f4944aad1c973e53370 100644 --- a/core/java/android/content/Loader.java +++ b/core/java/android/content/Loader.java @@ -44,7 +44,7 @@ import java.io.PrintWriter; *
*

Developer Guides

*

For more information about using loaders, read the - * Loaders developer guide.

+ * Loaders developer guide.

*
* * @param The result returned when the load is complete diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java index 7f9e17641a19fbd4dc64613924e8a6c7cc8a3863..4b09feda21736bb090bebdc0f07e85b9f5200137 100644 --- a/core/java/android/content/SharedPreferences.java +++ b/core/java/android/content/SharedPreferences.java @@ -72,7 +72,9 @@ public interface SharedPreferences { * {@link #commit} or {@link #apply} are called. * * @param key The name of the preference to modify. - * @param value The new value for the preference. + * @param value The new value for the preference. Passing {@code null} + * for this argument is equivalent to calling {@link #remove(String)} with + * this key. * * @return Returns a reference to the same Editor object, so you can * chain put calls together. diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java index 8a16ac94522ebdd3b2bc0a58a1af58f48ed6a670..6ef7fd214069bf7d9858bb2203593839549a20b7 100644 --- a/core/java/android/content/SyncAdapterType.java +++ b/core/java/android/content/SyncAdapterType.java @@ -16,6 +16,7 @@ package android.content; +import android.annotation.Nullable; import android.text.TextUtils; import android.os.Parcelable; import android.os.Parcel; @@ -33,6 +34,7 @@ public class SyncAdapterType implements Parcelable { private final boolean isAlwaysSyncable; private final boolean allowParallelSyncs; private final String settingsActivity; + private final String packageName; public SyncAdapterType(String authority, String accountType, boolean userVisible, boolean supportsUploading) { @@ -50,6 +52,7 @@ public class SyncAdapterType implements Parcelable { this.allowParallelSyncs = false; this.settingsActivity = null; this.isKey = false; + this.packageName = null; } /** @hide */ @@ -57,7 +60,8 @@ public class SyncAdapterType implements Parcelable { boolean supportsUploading, boolean isAlwaysSyncable, boolean allowParallelSyncs, - String settingsActivity) { + String settingsActivity, + String packageName) { if (TextUtils.isEmpty(authority)) { throw new IllegalArgumentException("the authority must not be empty: " + authority); } @@ -72,6 +76,7 @@ public class SyncAdapterType implements Parcelable { this.allowParallelSyncs = allowParallelSyncs; this.settingsActivity = settingsActivity; this.isKey = false; + this.packageName = packageName; } private SyncAdapterType(String authority, String accountType) { @@ -89,6 +94,7 @@ public class SyncAdapterType implements Parcelable { this.allowParallelSyncs = false; this.settingsActivity = null; this.isKey = true; + this.packageName = null; } public boolean supportsUploading() { @@ -148,6 +154,16 @@ public class SyncAdapterType implements Parcelable { return settingsActivity; } + /** + * The package hosting the sync adapter. + * @return The package name. + * + * @hide + */ + public @Nullable String getPackageName() { + return packageName; + } + public static SyncAdapterType newKey(String authority, String accountType) { return new SyncAdapterType(authority, accountType); } @@ -181,6 +197,7 @@ public class SyncAdapterType implements Parcelable { + ", isAlwaysSyncable=" + isAlwaysSyncable + ", allowParallelSyncs=" + allowParallelSyncs + ", settingsActivity=" + settingsActivity + + ", packageName=" + packageName + "}"; } } @@ -201,6 +218,7 @@ public class SyncAdapterType implements Parcelable { dest.writeInt(isAlwaysSyncable ? 1 : 0); dest.writeInt(allowParallelSyncs ? 1 : 0); dest.writeString(settingsActivity); + dest.writeString(packageName); } public SyncAdapterType(Parcel source) { @@ -211,6 +229,7 @@ public class SyncAdapterType implements Parcelable { source.readInt() != 0, source.readInt() != 0, source.readInt() != 0, + source.readString(), source.readString()); } diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java index 6704b75dff7f306634d0e8a2c515a7cc6bb6c1d5..ddbdb8a7a559b965dd63894065bd2dd51156a6c7 100644 --- a/core/java/android/content/SyncAdaptersCache.java +++ b/core/java/android/content/SyncAdaptersCache.java @@ -81,7 +81,7 @@ public class SyncAdaptersCache extends RegisteredServicesCache sa.getString(com.android.internal.R.styleable .SyncAdapter_settingsActivity); return new SyncAdapterType(authority, accountType, userVisible, supportsUploading, - isAlwaysSyncable, allowParallelSyncs, settingsActivity); + isAlwaysSyncable, allowParallelSyncs, settingsActivity, packageName); } finally { sa.recycle(); } diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java index afb4c30d6a996369c9e695cf2f17e8b1990a47d1..fc3b95850d21e055e4d11508cad309c98c5202d3 100644 --- a/core/java/android/content/pm/EphemeralResolveInfo.java +++ b/core/java/android/content/pm/EphemeralResolveInfo.java @@ -27,6 +27,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; +import java.util.Locale; /** * Information about an ephemeral application. @@ -37,10 +38,7 @@ public final class EphemeralResolveInfo implements Parcelable { /** Algorithm that will be used to generate the domain digest */ public static final String SHA_ALGORITHM = "SHA-256"; - /** Full digest of the domain hash */ - private final byte[] mDigestBytes; - /** The first 4 bytes of the domain hash */ - private final int mDigestPrefix; + private final EphemeralDigest mDigest; private final String mPackageName; /** The filters used to match domain */ private final List mFilters = new ArrayList(); @@ -55,29 +53,23 @@ public final class EphemeralResolveInfo implements Parcelable { throw new IllegalArgumentException(); } - mDigestBytes = generateDigest(uri); - mDigestPrefix = - mDigestBytes[0] << 24 - | mDigestBytes[1] << 16 - | mDigestBytes[2] << 8 - | mDigestBytes[3] << 0; + mDigest = new EphemeralDigest(uri, 0xFFFFFFFF, -1); mFilters.addAll(filters); mPackageName = packageName; } EphemeralResolveInfo(Parcel in) { - mDigestBytes = in.createByteArray(); - mDigestPrefix = in.readInt(); + mDigest = in.readParcelable(null /*loader*/); mPackageName = in.readString(); in.readList(mFilters, null /*loader*/); } public byte[] getDigestBytes() { - return mDigestBytes; + return mDigest.getDigestBytes()[0]; } public int getDigestPrefix() { - return mDigestPrefix; + return mDigest.getDigestPrefix()[0]; } public String getPackageName() { @@ -88,16 +80,6 @@ public final class EphemeralResolveInfo implements Parcelable { return mFilters; } - private static byte[] generateDigest(Uri uri) { - try { - final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM); - final byte[] hostBytes = uri.getHost().getBytes(); - return digest.digest(hostBytes); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("could not find digest algorithm"); - } - } - @Override public int describeContents() { return 0; @@ -105,8 +87,7 @@ public final class EphemeralResolveInfo implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - out.writeByteArray(mDigestBytes); - out.writeInt(mDigestPrefix); + out.writeParcelable(mDigest, flags); out.writeString(mPackageName); out.writeList(mFilters); } @@ -136,4 +117,121 @@ public final class EphemeralResolveInfo implements Parcelable { return mResolveInfo; } } + + /** + * Helper class to generate and store each of the digests and prefixes + * sent to the Ephemeral Resolver. + *

+ * Since intent filters may want to handle multiple hosts within a + * domain [eg “*.google.com”], the resolver is presented with multiple + * hash prefixes. For example, "a.b.c.d.e" generates digests for + * "d.e", "c.d.e", "b.c.d.e" and "a.b.c.d.e". + * + * @hide + */ + public static final class EphemeralDigest implements Parcelable { + /** Full digest of the domain hashes */ + private final byte[][] mDigestBytes; + /** The first 4 bytes of the domain hashes */ + private final int[] mDigestPrefix; + + public EphemeralDigest(@NonNull Uri uri, int digestMask, int maxDigests) { + if (uri == null) { + throw new IllegalArgumentException(); + } + mDigestBytes = generateDigest(uri, maxDigests); + mDigestPrefix = new int[mDigestBytes.length]; + for (int i = 0; i < mDigestBytes.length; i++) { + mDigestPrefix[i] = + ((mDigestBytes[i][0] & 0xFF) << 24 + | (mDigestBytes[i][1] & 0xFF) << 16 + | (mDigestBytes[i][2] & 0xFF) << 8 + | (mDigestBytes[i][3] & 0xFF) << 0) + & digestMask; + } + } + + private static byte[][] generateDigest(Uri uri, int maxDigests) { + ArrayList digests = new ArrayList<>(); + try { + final String host = uri.getHost().toLowerCase(Locale.ENGLISH); + final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM); + if (maxDigests <= 0) { + final byte[] hostBytes = host.getBytes(); + digests.add(digest.digest(hostBytes)); + } else { + int prevDot = host.lastIndexOf('.'); + prevDot = host.lastIndexOf('.', prevDot - 1); + // shortcut for short URLs + if (prevDot < 0) { + digests.add(digest.digest(host.getBytes())); + } else { + byte[] hostBytes = host.substring(prevDot + 1, host.length()).getBytes(); + digests.add(digest.digest(hostBytes)); + int digestCount = 1; + while (prevDot >= 0 && digestCount < maxDigests) { + prevDot = host.lastIndexOf('.', prevDot - 1); + hostBytes = host.substring(prevDot + 1, host.length()).getBytes(); + digests.add(digest.digest(hostBytes)); + digestCount++; + } + } + } + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("could not find digest algorithm"); + } + return digests.toArray(new byte[digests.size()][]); + } + + EphemeralDigest(Parcel in) { + final int digestCount = in.readInt(); + if (digestCount == -1) { + mDigestBytes = null; + } else { + mDigestBytes = new byte[digestCount][]; + for (int i = 0; i < digestCount; i++) { + mDigestBytes[i] = in.createByteArray(); + } + } + mDigestPrefix = in.createIntArray(); + } + + public byte[][] getDigestBytes() { + return mDigestBytes; + } + + public int[] getDigestPrefix() { + return mDigestPrefix; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + if (mDigestBytes == null) { + out.writeInt(-1); + } else { + out.writeInt(mDigestBytes.length); + for (int i = 0; i < mDigestBytes.length; i++) { + out.writeByteArray(mDigestBytes[i]); + } + } + out.writeIntArray(mDigestPrefix); + } + + @SuppressWarnings("hiding") + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public EphemeralDigest createFromParcel(Parcel in) { + return new EphemeralDigest(in); + } + + public EphemeralDigest[] newArray(int size) { + return new EphemeralDigest[size]; + } + }; + } } diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl index 2ba24f6eecdbaa4e2e2633bbcf12b89ea3340e70..1bf2ab0abbadafe0aad65f7232201ea413305642 100644 --- a/core/java/android/content/pm/IShortcutService.aidl +++ b/core/java/android/content/pm/IShortcutService.aidl @@ -28,6 +28,8 @@ interface IShortcutService { ParceledListSlice getDynamicShortcuts(String packageName, int userId); + ParceledListSlice getManifestShortcuts(String packageName, int userId); + boolean addDynamicShortcuts(String packageName, in ParceledListSlice shortcutInfoList, int userId); @@ -39,7 +41,12 @@ interface IShortcutService { boolean updateShortcuts(String packageName, in ParceledListSlice shortcuts, int userId); - int getMaxDynamicShortcutCount(String packageName, int userId); + void disableShortcuts(String packageName, in List shortcutIds, CharSequence disabledMessage, + int disabledMessageResId, int userId); + + void enableShortcuts(String packageName, in List shortcutIds, int userId); + + int getMaxShortcutCountPerActivity(String packageName, int userId); int getRemainingCallCount(String packageName, int userId); @@ -47,6 +54,8 @@ interface IShortcutService { int getIconMaxDimensions(String packageName, int userId); + void reportShortcutUsed(String packageName, String shortcutId, int userId); + void resetThrottling(); // system only API for developer opsions void onApplicationActive(String packageName, int userId); // system only API for sysUI diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 8ca27c5e0087905763530df33f53acad750c3b7f..6b23da93bb8623a3e866a702557f97e7433900b3 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -20,11 +20,18 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; +import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager.ApplicationInfoFlags; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -34,8 +41,10 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.util.DisplayMetrics; import android.util.Log; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -156,18 +165,19 @@ public class LauncherApps { } /** - * Indicates that one or more shortcuts (which may be dynamic and/or pinned) + * Indicates that one or more shortcuts of any kind (dynamic, pinned, or manifest) * have been added, updated or removed. * *

Only the applications that are allowed to access the shortcut information, * as defined in {@link #hasShortcutHostPermission()}, will receive it. * * @param packageName The name of the package that has the shortcuts. - * @param shortcuts all shortcuts from the package (dynamic and/or pinned). Only "key" - * information will be provided, as defined in {@link ShortcutInfo#hasKeyFieldsOnly()}. + * @param shortcuts All shortcuts from the package (dynamic, manifest and/or pinned). + * Only "key" information will be provided, as defined in + * {@link ShortcutInfo#hasKeyFieldsOnly()}. * @param user The UserHandle of the profile that generated the change. * - * @hide + * @see ShortcutManager */ public void onShortcutsChanged(@NonNull String packageName, @NonNull List shortcuts, @NonNull UserHandle user) { @@ -176,31 +186,68 @@ public class LauncherApps { /** * Represents a query passed to {@link #getShortcuts(ShortcutQuery, UserHandle)}. - * - * @hide */ public static class ShortcutQuery { /** * Include dynamic shortcuts in the result. */ - public static final int FLAG_GET_DYNAMIC = 1 << 0; + public static final int FLAG_MATCH_DYNAMIC = 1 << 0; + + /** @hide kept for unit tests */ + @Deprecated + public static final int FLAG_GET_DYNAMIC = FLAG_MATCH_DYNAMIC; /** * Include pinned shortcuts in the result. */ - public static final int FLAG_GET_PINNED = 1 << 1; + public static final int FLAG_MATCH_PINNED = 1 << 1; + + /** @hide kept for unit tests */ + @Deprecated + public static final int FLAG_GET_PINNED = FLAG_MATCH_PINNED; /** - * Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()} for which - * fields are available. + * Include manifest shortcuts in the result. + */ + public static final int FLAG_MATCH_MANIFEST = 1 << 3; + + /** @hide kept for unit tests */ + @Deprecated + public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST; + + /** @hide */ + public static final int FLAG_MATCH_ALL_KINDS = + FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST; + + /** @hide kept for unit tests */ + @Deprecated + public static final int FLAG_GET_ALL_KINDS = FLAG_MATCH_ALL_KINDS; + + /** + * Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()}'s javadoc to + * see which fields fields "key". + * This allows quicker access to shortcut information in order to + * determine whether the caller's in-memory cache needs to be updated. + * + *

Typically, launcher applications cache all or most shortcut information + * in memory in order to show shortcuts without a delay. + * + * When a given launcher application wants to update its cache, such as when its process + * restarts, it can fetch shortcut information with this flag. + * The application can then check {@link ShortcutInfo#getLastChangedTimestamp()} for each + * shortcut, fetching a shortcut's non-key information only if that shortcut has been + * updated. + * + * @see ShortcutManager */ public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2; /** @hide */ @IntDef(flag = true, value = { - FLAG_GET_DYNAMIC, - FLAG_GET_PINNED, + FLAG_MATCH_DYNAMIC, + FLAG_MATCH_PINNED, + FLAG_MATCH_MANIFEST, FLAG_GET_KEY_FIELDS_ONLY, }) @Retention(RetentionPolicy.SOURCE) @@ -224,40 +271,56 @@ public class LauncherApps { } /** - * If non-zero, returns only shortcuts that have been added or updated since the timestamp, - * which is a milliseconds since the Epoch. + * If non-zero, returns only shortcuts that have been added or updated + * since the given timestamp, expressed in milliseconds since the Epoch—see + * {@link System#currentTimeMillis()}. */ - public void setChangedSince(long changedSince) { + public ShortcutQuery setChangedSince(long changedSince) { mChangedSince = changedSince; + return this; } /** * If non-null, returns only shortcuts from the package. */ - public void setPackage(@Nullable String packageName) { + public ShortcutQuery setPackage(@Nullable String packageName) { mPackage = packageName; + return this; } /** * If non-null, return only the specified shortcuts by ID. When setting this field, - * a packange name must also be set with {@link #setPackage}. + * a package name must also be set with {@link #setPackage}. */ - public void setShortcutIds(@Nullable List shortcutIds) { + public ShortcutQuery setShortcutIds(@Nullable List shortcutIds) { mShortcutIds = shortcutIds; + return this; } /** - * If non-null, returns only shortcuts associated with the activity. + * If non-null, returns only shortcuts associated with the activity; i.e. + * {@link ShortcutInfo}s whose {@link ShortcutInfo#getActivity()} are equal + * to {@code activity}. */ - public void setActivity(@Nullable ComponentName activity) { + public ShortcutQuery setActivity(@Nullable ComponentName activity) { mActivity = activity; + return this; } /** - * Set query options. + * Set query options. At least one of the {@code MATCH} flags should be set. Otherwise, + * no shortcuts will be returned. + * + *

    + *
  • {@link #FLAG_MATCH_DYNAMIC} + *
  • {@link #FLAG_MATCH_PINNED} + *
  • {@link #FLAG_MATCH_MANIFEST} + *
  • {@link #FLAG_GET_KEY_FIELDS_ONLY} + *
*/ - public void setQueryFlags(@QueryFlags int queryFlags) { + public ShortcutQuery setQueryFlags(@QueryFlags int queryFlags) { mQueryFlags = queryFlags; + return this; } } @@ -422,12 +485,16 @@ public class LauncherApps { * *

Only the default launcher can access the shortcut information. * - *

Note when this method returns {@code false}, that may be a temporary situation because + *

Note when this method returns {@code false}, it may be a temporary situation because * the user is trying a new launcher application. The user may decide to change the default - * launcher to the calling application again, so even if a launcher application loses + * launcher back to the calling application again, so even if a launcher application loses * this permission, it does not have to purge pinned shortcut information. + * If the calling launcher application contains pinned shortcuts, they will still work, + * even though the caller no longer has the shortcut host permission. * - * @hide + * @throws IllegalStateException when the user is locked. + * + * @see ShortcutManager */ public boolean hasShortcutHostPermission() { try { @@ -438,7 +505,7 @@ public class LauncherApps { } /** - * Returns the IDs of {@link ShortcutInfo}s that match {@code query}. + * Returns {@link ShortcutInfo}s that match {@code query}. * *

Callers must be allowed to access the shortcut information, as defined in {@link * #hasShortcutHostPermission()}. @@ -447,8 +514,10 @@ public class LauncherApps { * @param user The UserHandle of the profile. * * @return the IDs of {@link ShortcutInfo}s that match the query. + * @throws IllegalStateException when the user is locked, or when the {@code user} user + * is locked or not running. * - * @hide + * @see ShortcutManager */ @Nullable public List getShortcuts(@NonNull ShortcutQuery query, @@ -467,12 +536,13 @@ public class LauncherApps { * @hide // No longer used. Use getShortcuts() instead. Kept for unit tests. */ @Nullable + @Deprecated public List getShortcutInfo(@NonNull String packageName, @NonNull List ids, @NonNull UserHandle user) { final ShortcutQuery q = new ShortcutQuery(); q.setPackage(packageName); q.setShortcutIds(ids); - q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED); + q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS); return getShortcuts(q, user); } @@ -482,14 +552,16 @@ public class LauncherApps { *

This API is NOT cumulative; this will replace all pinned shortcuts for the package. * However, different launchers may have different set of pinned shortcuts. * - *

Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + *

The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param packageName The target package name. * @param shortcutIds The IDs of the shortcut to be pinned. * @param user The UserHandle of the profile. + * @throws IllegalStateException when the user is locked, or when the {@code user} user + * is locked or not running. * - * @hide + * @see ShortcutManager */ public void pinShortcuts(@NonNull String packageName, @NonNull List shortcutIds, @NonNull UserHandle user) { @@ -503,6 +575,7 @@ public class LauncherApps { /** * @hide kept for testing. */ + @Deprecated public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) { return shortcut.getIconResourceId(); } @@ -510,46 +583,29 @@ public class LauncherApps { /** * @hide kept for testing. */ + @Deprecated public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) { final ShortcutQuery q = new ShortcutQuery(); q.setPackage(packageName); q.setShortcutIds(Arrays.asList(shortcutId)); - q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED); + q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS); final List shortcuts = getShortcuts(q, user); return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0; } /** - * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file - * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}). - * - *

Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. - * - * @param shortcut The target shortcut. - * - * @hide + * @hide internal/unit tests only */ public ParcelFileDescriptor getShortcutIconFd( @NonNull ShortcutInfo shortcut) { - return getShortcutIconFd(shortcut.getPackageName(), shortcut.getId(), + return getShortcutIconFd(shortcut.getPackage(), shortcut.getId(), shortcut.getUserId()); } /** - * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file - * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}). - * - *

Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. - * - * @param packageName The target package name. - * @param shortcutId The ID of the shortcut to lad rom. - * @param user The UserHandle of the profile. - * - * @hide + * @hide internal/unit tests only */ public ParcelFileDescriptor getShortcutIconFd( @NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) { @@ -567,55 +623,133 @@ public class LauncherApps { } /** - * Launches a shortcut. + * Returns the icon for this shortcut, without any badging for the profile. * - *

Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + *

The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. + * + * @param density The preferred density of the icon, zero for default density. Use + * density DPI values from {@link DisplayMetrics}. + * + * @return The drawable associated with the shortcut. + * @throws IllegalStateException when the user is locked, or when the {@code user} user + * is locked or not running. + * + * @see ShortcutManager + * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int) + * @see DisplayMetrics + */ + public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) { + if (shortcut.hasIconFile()) { + final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut); + if (pfd == null) { + return null; + } + try { + final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor()); + return (bmp == null) ? null : new BitmapDrawable(mContext.getResources(), bmp); + } finally { + try { + pfd.close(); + } catch (IOException ignore) { + } + } + } else if (shortcut.hasIconResource()) { + try { + final int resId = shortcut.getIconResourceId(); + if (resId == 0) { + return null; // Shouldn't happen but just in case. + } + final ApplicationInfo ai = getApplicationInfo(shortcut.getPackage(), + /* flags =*/ 0, shortcut.getUserHandle()); + final Resources res = mContext.getPackageManager().getResourcesForApplication(ai); + return res.getDrawableForDensity(resId, density); + } catch (NameNotFoundException | Resources.NotFoundException e) { + return null; + } + } else { + return null; // Has no icon. + } + } + + /** + * Returns the shortcut icon with badging appropriate for the profile. + * + *

The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. + * + * @param density Optional density for the icon, or 0 to use the default density. Use + * @return A badged icon for the shortcut. + * @throws IllegalStateException when the user is locked, or when the {@code user} user + * is locked or not running. + * + * @see ShortcutManager + * @see #getShortcutIconDrawable(ShortcutInfo, int) + * @see DisplayMetrics + */ + public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) { + final Drawable originalIcon = getShortcutIconDrawable(shortcut, density); + + return (originalIcon == null) ? null : mContext.getPackageManager().getUserBadgedIcon( + originalIcon, shortcut.getUserHandle()); + } + + /** + * Starts a shortcut. + * + *

The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param packageName The target shortcut package name. * @param shortcutId The target shortcut ID. * @param sourceBounds The Rect containing the source bounds of the clicked icon. * @param startActivityOptions Options to pass to startActivity. * @param user The UserHandle of the profile. - * @return {@code false} when the shortcut is no longer valid (e.g. the creator application - * has been uninstalled). {@code true} when the shortcut is still valid. + * @throws IllegalStateException when the user is locked, or when the {@code user} user + * is locked or not running. * - * @hide + * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g. + * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc) */ - public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId, + public void startShortcut(@NonNull String packageName, @NonNull String shortcutId, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions, @NonNull UserHandle user) { - return startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions, + startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions, user.getIdentifier()); } /** * Launches a shortcut. * - *

Callers must be allowed to access the shortcut information, as defined in {@link - * #hasShortcutHostPermission()}. + *

The calling launcher application must be allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}. * * @param shortcut The target shortcut. * @param sourceBounds The Rect containing the source bounds of the clicked icon. * @param startActivityOptions Options to pass to startActivity. - * @return {@code false} when the shortcut is no longer valid (e.g. the creator application - * has been uninstalled). {@code true} when the shortcut is still valid. + * @throws IllegalStateException when the user is locked, or when the {@code user} user + * is locked or not running. * - * @hide + * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g. + * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc) */ - public boolean startShortcut(@NonNull ShortcutInfo shortcut, + public void startShortcut(@NonNull ShortcutInfo shortcut, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) { - return startShortcut(shortcut.getPackageName(), shortcut.getId(), + startShortcut(shortcut.getPackage(), shortcut.getId(), sourceBounds, startActivityOptions, shortcut.getUserId()); } - private boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId, + private void startShortcut(@NonNull String packageName, @NonNull String shortcutId, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions, int userId) { try { - return mService.startShortcut(mContext.getPackageName(), packageName, shortcutId, + final boolean success = + mService.startShortcut(mContext.getPackageName(), packageName, shortcutId, sourceBounds, startActivityOptions, userId); + if (!success) { + throw new ActivityNotFoundException("Shortcut could not be started"); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 81229402e895be21a1514ed6aa2b174e9b4ce3c2..b0efd892558699dc5f19e5ee2f34af314d48381e 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -132,6 +132,9 @@ public abstract class PackageManager { MATCH_SYSTEM_ONLY, MATCH_FACTORY_ONLY, MATCH_DEBUG_TRIAGED_MISSING, + GET_DISABLED_COMPONENTS, + GET_DISABLED_UNTIL_USED_COMPONENTS, + GET_UNINSTALLED_PACKAGES, }) @Retention(RetentionPolicy.SOURCE) public @interface PackageInfoFlags {} @@ -143,6 +146,9 @@ public abstract class PackageManager { MATCH_UNINSTALLED_PACKAGES, MATCH_SYSTEM_ONLY, MATCH_DEBUG_TRIAGED_MISSING, + MATCH_DISABLED_UNTIL_USED_COMPONENTS, + GET_DISABLED_UNTIL_USED_COMPONENTS, + GET_UNINSTALLED_PACKAGES, }) @Retention(RetentionPolicy.SOURCE) public @interface ApplicationInfoFlags {} @@ -160,6 +166,9 @@ public abstract class PackageManager { MATCH_DIRECT_BOOT_UNAWARE, MATCH_SYSTEM_ONLY, MATCH_UNINSTALLED_PACKAGES, + GET_DISABLED_COMPONENTS, + GET_DISABLED_UNTIL_USED_COMPONENTS, + GET_UNINSTALLED_PACKAGES, }) @Retention(RetentionPolicy.SOURCE) public @interface ComponentInfoFlags {} @@ -178,6 +187,9 @@ public abstract class PackageManager { MATCH_DIRECT_BOOT_UNAWARE, MATCH_SYSTEM_ONLY, MATCH_UNINSTALLED_PACKAGES, + GET_DISABLED_COMPONENTS, + GET_DISABLED_UNTIL_USED_COMPONENTS, + GET_UNINSTALLED_PACKAGES, }) @Retention(RetentionPolicy.SOURCE) public @interface ResolveInfoFlags {} @@ -2868,6 +2880,7 @@ public abstract class PackageManager { * * @see #GET_META_DATA * @see #GET_SHARED_LIBRARY_FILES + * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS * @see #MATCH_SYSTEM_ONLY * @see #MATCH_UNINSTALLED_PACKAGES */ @@ -3496,6 +3509,7 @@ public abstract class PackageManager { * * @see #GET_META_DATA * @see #GET_SHARED_LIBRARY_FILES + * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS * @see #MATCH_SYSTEM_ONLY * @see #MATCH_UNINSTALLED_PACKAGES */ @@ -5416,7 +5430,7 @@ public abstract class PackageManager { * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the * application's enabled state is based on the original information in - * the manifest as found in {@link ComponentInfo}. + * the manifest as found in {@link ApplicationInfo}. * @throws IllegalArgumentException if the named package does not exist. */ public abstract int getApplicationEnabledSetting(String packageName); diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 14f7727e61a02daaeb5ac9bbfd08789b35098812..f5bcf64417a666a9d7e2ec949ab486dbdd0c73d7 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -157,7 +157,15 @@ public abstract class PackageManagerInternal { int deviceOwnerUserId, String deviceOwner, SparseArray profileOwners); /** - * Whether a package's data be cleared. + * Returns {@code true} if a given package can't be wiped. Otherwise, returns {@code false}. */ - public abstract boolean canPackageBeWiped(int userId, String packageName); + public abstract boolean isPackageDataProtected(int userId, String packageName); + + /** + * Gets whether the package was ever launched. + * @param packageName The package name. + * @param userId The user for which to check. + * @return Whether was launched. + */ + public abstract boolean wasPackageEverLaunched(String packageName, int userId); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index adf9fe62c37e529c78c342387e6b240d94133e05..2093124d5b8a644a98e91771c61db01517b4eb2b 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -270,6 +270,7 @@ public class PackageParser { final int nameRes; final int labelRes; final int iconRes; + final int roundIconRes; final int logoRes; final int bannerRes; @@ -277,7 +278,8 @@ public class PackageParser { TypedArray sa; ParsePackageItemArgs(Package _owner, String[] _outError, - int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes) { + int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, + int _bannerRes) { owner = _owner; outError = _outError; nameRes = _nameRes; @@ -285,6 +287,7 @@ public class PackageParser { iconRes = _iconRes; logoRes = _logoRes; bannerRes = _bannerRes; + roundIconRes = _roundIconRes; } } @@ -296,10 +299,12 @@ public class PackageParser { int flags; ParseComponentArgs(Package _owner, String[] _outError, - int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes, + int _nameRes, int _labelRes, int _iconRes, int _roundIconRes, int _logoRes, + int _bannerRes, String[] _sepProcesses, int _processRes, int _descriptionRes, int _enabledRes) { - super(_owner, _outError, _nameRes, _labelRes, _iconRes, _logoRes, _bannerRes); + super(_owner, _outError, _nameRes, _labelRes, _iconRes, _roundIconRes, _logoRes, + _bannerRes); sepProcesses = _sepProcesses; processRes = _processRes; descriptionRes = _descriptionRes; @@ -1871,7 +1876,7 @@ public class PackageParser { sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestUsesSdk); - int minVers = 0; + int minVers = 1; String minCode = null; int targetVers = 0; String targetCode = null; @@ -1898,9 +1903,6 @@ public class PackageParser { } else { // If it's not a string, it's an integer. targetVers = val.data; - if (minVers == 0) { - minVers = targetVers; - } } } @@ -2288,11 +2290,7 @@ public class PackageParser { b.append(cls); return b.toString().intern(); } - if (c >= 'a' && c <= 'z') { - return cls.intern(); - } - outError[0] = "Bad class name " + cls + " in package " + pkg; - return null; + return cls.intern(); } private static String buildCompoundName(String pkg, @@ -2506,12 +2504,12 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestPermissionGroup); - if (!parsePackageItemInfo(owner, perm.info, outError, - "", sa, + "", sa, true /*nameRequired*/, com.android.internal.R.styleable.AndroidManifestPermissionGroup_name, com.android.internal.R.styleable.AndroidManifestPermissionGroup_label, com.android.internal.R.styleable.AndroidManifestPermissionGroup_icon, + com.android.internal.R.styleable.AndroidManifestPermissionGroup_roundIcon, com.android.internal.R.styleable.AndroidManifestPermissionGroup_logo, com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) { sa.recycle(); @@ -2552,10 +2550,11 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestPermission); if (!parsePackageItemInfo(owner, perm.info, outError, - "", sa, + "", sa, true /*nameRequired*/, com.android.internal.R.styleable.AndroidManifestPermission_name, com.android.internal.R.styleable.AndroidManifestPermission_label, com.android.internal.R.styleable.AndroidManifestPermission_icon, + com.android.internal.R.styleable.AndroidManifestPermission_roundIcon, com.android.internal.R.styleable.AndroidManifestPermission_logo, com.android.internal.R.styleable.AndroidManifestPermission_banner)) { sa.recycle(); @@ -2621,10 +2620,11 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestPermissionTree); if (!parsePackageItemInfo(owner, perm.info, outError, - "", sa, + "", sa, true /*nameRequired*/, com.android.internal.R.styleable.AndroidManifestPermissionTree_name, com.android.internal.R.styleable.AndroidManifestPermissionTree_label, com.android.internal.R.styleable.AndroidManifestPermissionTree_icon, + com.android.internal.R.styleable.AndroidManifestPermissionTree_roundIcon, com.android.internal.R.styleable.AndroidManifestPermissionTree_logo, com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) { sa.recycle(); @@ -2671,6 +2671,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestInstrumentation_name, com.android.internal.R.styleable.AndroidManifestInstrumentation_label, com.android.internal.R.styleable.AndroidManifestInstrumentation_icon, + com.android.internal.R.styleable.AndroidManifestInstrumentation_roundIcon, com.android.internal.R.styleable.AndroidManifestInstrumentation_logo, com.android.internal.R.styleable.AndroidManifestInstrumentation_banner); mParseInstrumentationArgs.tag = ""; @@ -2736,15 +2737,21 @@ public class PackageParser { TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestApplication); - String name = sa.getNonConfigurationString( - com.android.internal.R.styleable.AndroidManifestApplication_name, 0); - if (name != null) { - ai.className = buildClassName(pkgName, name, outError); - if (ai.className == null) { - sa.recycle(); - mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return false; - } + if (!parsePackageItemInfo(owner, ai, outError, + "", sa, false /*nameRequired*/, + com.android.internal.R.styleable.AndroidManifestApplication_name, + com.android.internal.R.styleable.AndroidManifestApplication_label, + com.android.internal.R.styleable.AndroidManifestApplication_icon, + com.android.internal.R.styleable.AndroidManifestApplication_roundIcon, + com.android.internal.R.styleable.AndroidManifestApplication_logo, + com.android.internal.R.styleable.AndroidManifestApplication_banner)) { + sa.recycle(); + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return false; + } + + if (ai.name != null) { + ai.className = ai.name; } String manageSpaceActivity = sa.getNonConfigurationString( @@ -2810,18 +2817,6 @@ public class PackageParser { } } - TypedValue v = sa.peekValue( - com.android.internal.R.styleable.AndroidManifestApplication_label); - if (v != null && (ai.labelRes=v.resourceId) == 0) { - ai.nonLocalizedLabel = v.coerceToString(); - } - - ai.icon = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestApplication_icon, 0); - ai.logo = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestApplication_logo, 0); - ai.banner = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestApplication_banner, 0); ai.theme = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); ai.descriptionRes = sa.getResourceId( @@ -3335,25 +3330,35 @@ public class PackageParser { return true; } - private boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, - String[] outError, String tag, TypedArray sa, - int nameRes, int labelRes, int iconRes, int logoRes, int bannerRes) { + private static boolean parsePackageItemInfo(Package owner, PackageItemInfo outInfo, + String[] outError, String tag, TypedArray sa, boolean nameRequired, + int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) { String name = sa.getNonConfigurationString(nameRes, 0); if (name == null) { - outError[0] = tag + " does not specify android:name"; - return false; - } - - outInfo.name - = buildClassName(owner.applicationInfo.packageName, name, outError); - if (outInfo.name == null) { - return false; + if (nameRequired) { + outError[0] = tag + " does not specify android:name"; + return false; + } + } else { + outInfo.name + = buildClassName(owner.applicationInfo.packageName, name, outError); + if (outInfo.name == null) { + return false; + } } - int iconVal = sa.getResourceId(iconRes, 0); - if (iconVal != 0) { - outInfo.icon = iconVal; + final boolean useRoundIcon = + Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon); + int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0; + if (roundIconVal != 0) { + outInfo.icon = roundIconVal; outInfo.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(iconRes, 0); + if (iconVal != 0) { + outInfo.icon = iconVal; + outInfo.nonLocalizedLabel = null; + } } int logoVal = sa.getResourceId(logoRes, 0); @@ -3387,6 +3392,7 @@ public class PackageParser { R.styleable.AndroidManifestActivity_name, R.styleable.AndroidManifestActivity_label, R.styleable.AndroidManifestActivity_icon, + R.styleable.AndroidManifestActivity_roundIcon, R.styleable.AndroidManifestActivity_logo, R.styleable.AndroidManifestActivity_banner, mSeparateProcesses, @@ -3761,6 +3767,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestActivityAlias_name, com.android.internal.R.styleable.AndroidManifestActivityAlias_label, com.android.internal.R.styleable.AndroidManifestActivityAlias_icon, + com.android.internal.R.styleable.AndroidManifestActivityAlias_roundIcon, com.android.internal.R.styleable.AndroidManifestActivityAlias_logo, com.android.internal.R.styleable.AndroidManifestActivityAlias_banner, mSeparateProcesses, @@ -3915,6 +3922,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestProvider_name, com.android.internal.R.styleable.AndroidManifestProvider_label, com.android.internal.R.styleable.AndroidManifestProvider_icon, + com.android.internal.R.styleable.AndroidManifestProvider_roundIcon, com.android.internal.R.styleable.AndroidManifestProvider_logo, com.android.internal.R.styleable.AndroidManifestProvider_banner, mSeparateProcesses, @@ -4234,6 +4242,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestService_name, com.android.internal.R.styleable.AndroidManifestService_label, com.android.internal.R.styleable.AndroidManifestService_icon, + com.android.internal.R.styleable.AndroidManifestService_roundIcon, com.android.internal.R.styleable.AndroidManifestService_logo, com.android.internal.R.styleable.AndroidManifestService_banner, mSeparateProcesses, @@ -4550,8 +4559,16 @@ public class PackageParser { outInfo.nonLocalizedLabel = v.coerceToString(); } - outInfo.icon = sa.getResourceId( - com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0); + final boolean useRoundIcon = + Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon); + int roundIconVal = useRoundIcon ? sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0; + if (roundIconVal != 0) { + outInfo.icon = roundIconVal; + } else { + outInfo.icon = sa.getResourceId( + com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0); + } outInfo.logo = sa.getResourceId( com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0); @@ -5180,45 +5197,13 @@ public class PackageParser { public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) { owner = args.owner; intents = new ArrayList(0); - String name = args.sa.getNonConfigurationString(args.nameRes, 0); - if (name == null) { - className = null; - args.outError[0] = args.tag + " does not specify android:name"; - return; - } - - outInfo.name - = buildClassName(owner.applicationInfo.packageName, name, args.outError); - if (outInfo.name == null) { + if (parsePackageItemInfo(args.owner, outInfo, args.outError, args.tag, args.sa, + true /*nameRequired*/, args.nameRes, args.labelRes, args.iconRes, + args.roundIconRes, args.logoRes, args.bannerRes)) { + className = outInfo.name; + } else { className = null; - args.outError[0] = args.tag + " does not have valid android:name"; - return; - } - - className = outInfo.name; - - int iconVal = args.sa.getResourceId(args.iconRes, 0); - if (iconVal != 0) { - outInfo.icon = iconVal; - outInfo.nonLocalizedLabel = null; } - - int logoVal = args.sa.getResourceId(args.logoRes, 0); - if (logoVal != 0) { - outInfo.logo = logoVal; - } - - int bannerVal = args.sa.getResourceId(args.bannerRes, 0); - if (bannerVal != 0) { - outInfo.banner = bannerVal; - } - - TypedValue v = args.sa.peekValue(args.labelRes); - if (v != null && (outInfo.labelRes=v.resourceId) == 0) { - outInfo.nonLocalizedLabel = v.coerceToString(); - } - - outInfo.packageName = owner.packageName; } public Component(final ParseComponentArgs args, final ComponentInfo outInfo) { diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java index 693228f4cd13193322d99ea96f69398f78dfcb03..aea843adbd4814cf8618b97972685402152bf087 100644 --- a/core/java/android/content/pm/RegisteredServicesCache.java +++ b/core/java/android/content/pm/RegisteredServicesCache.java @@ -30,6 +30,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.AtomicFile; import android.util.AttributeSet; +import android.util.IntArray; import android.util.Log; import android.util.Slog; import android.util.SparseArray; @@ -54,6 +55,7 @@ import java.io.InputStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -344,6 +346,47 @@ public abstract class RegisteredServicesCache { } } + public void updateServices(int userId) { + if (DEBUG) { + Slog.d(TAG, "updateServices u" + userId); + } + List> allServices; + synchronized (mServicesLock) { + final UserServices user = findOrCreateUserLocked(userId); + // If services haven't been initialized yet - no updates required + if (user.services == null) { + return; + } + allServices = new ArrayList<>(user.services.values()); + } + IntArray updatedUids = null; + for (ServiceInfo service : allServices) { + int versionCode = service.componentInfo.applicationInfo.versionCode; + String pkg = service.componentInfo.packageName; + ApplicationInfo newAppInfo = null; + try { + newAppInfo = mContext.getPackageManager().getApplicationInfoAsUser(pkg, 0, userId); + } catch (NameNotFoundException e) { + // Package uninstalled - treat as null app info + } + // If package updated or removed + if ((newAppInfo == null) || (newAppInfo.versionCode != versionCode)) { + if (DEBUG) { + Slog.d(TAG, "Package " + pkg + " uid=" + service.uid + + " updated. New appInfo: " + newAppInfo); + } + if (updatedUids == null) { + updatedUids = new IntArray(); + } + updatedUids.add(service.uid); + } + } + if (updatedUids != null && updatedUids.size() > 0) { + int[] updatedUidsArray = updatedUids.toArray(); + generateServicesMap(updatedUidsArray, userId); + } + } + @VisibleForTesting protected boolean inSystemImage(int callerUid) { String[] packages = mContext.getPackageManager().getPackagesForUid(callerUid); @@ -381,10 +424,11 @@ public abstract class RegisteredServicesCache { */ private void generateServicesMap(int[] changedUids, int userId) { if (DEBUG) { - Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = " + changedUids); + Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = " + + Arrays.toString(changedUids)); } - final ArrayList> serviceInfos = new ArrayList>(); + final ArrayList> serviceInfos = new ArrayList<>(); final List resolveInfos = queryIntentServices(userId); for (ResolveInfo resolveInfo : resolveInfos) { try { diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index c9be6edab424c0e381cc6f7a4735f0da20abbfca..b5df4d75a2384a39aec1aefcda047fc6ebd654fa 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -67,12 +67,6 @@ public class ResolveInfo implements Parcelable { */ public EphemeralResolveInfo ephemeralResolveInfo; - /** - * A ResolveInfo that points at the ephemeral installer. - * @hide - */ - public ResolveInfo ephemeralInstaller; - /** * The IntentFilter that was matched for this ResolveInfo. */ diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index 4340d04cee69fab8ae3e34ec397a32aced99eb48..ed0ac53861764dc4f2d6b0814a8f60f19f34bf9b 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -19,56 +19,78 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.app.TaskStackBuilder; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.LauncherApps.ShortcutQuery; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; +import android.graphics.Bitmap; import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.UserHandle; +import android.text.TextUtils; import android.util.ArraySet; +import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.List; import java.util.Set; -// TODO Enhance javadoc /** + * Represents a "launcher shortcut" that can be published via {@link ShortcutManager}. * - * Represents a shortcut from an application. - * - *

Notes about icons: - *

    - *
  • If an {@link Icon} is a resource, the system keeps the package name and the resource ID. - * Otherwise, the bitmap is fetched when it's registered to ShortcutManager, - * then shrunk if necessary, and persisted. - *
  • The system disallows byte[] icons, because they can easily go over the binder size limit. - *
- * - * @see {@link ShortcutManager}. - * - * @hide + * @see ShortcutManager */ public final class ShortcutInfo implements Parcelable { - /* @hide */ + static final String TAG = "Shortcut"; + + private static final String RES_TYPE_STRING = "string"; + + private static final String ANDROID_PACKAGE_NAME = "android"; + + private static final int IMPLICIT_RANK_MASK = 0x7fffffff; + + private static final int RANK_CHANGED_BIT = ~IMPLICIT_RANK_MASK; + + /** @hide */ + public static final int RANK_NOT_SET = Integer.MAX_VALUE; + + /** @hide */ public static final int FLAG_DYNAMIC = 1 << 0; - /* @hide */ + /** @hide */ public static final int FLAG_PINNED = 1 << 1; - /* @hide */ + /** @hide */ public static final int FLAG_HAS_ICON_RES = 1 << 2; - /* @hide */ + /** @hide */ public static final int FLAG_HAS_ICON_FILE = 1 << 3; - /* @hide */ + /** @hide */ public static final int FLAG_KEY_FIELDS_ONLY = 1 << 4; + /** @hide */ + public static final int FLAG_MANIFEST = 1 << 5; + + /** @hide */ + public static final int FLAG_DISABLED = 1 << 6; + + /** @hide */ + public static final int FLAG_STRINGS_RESOLVED = 1 << 7; + + /** @hide */ + public static final int FLAG_IMMUTABLE = 1 << 8; + /** @hide */ @IntDef(flag = true, value = { @@ -77,26 +99,34 @@ public final class ShortcutInfo implements Parcelable { FLAG_HAS_ICON_RES, FLAG_HAS_ICON_FILE, FLAG_KEY_FIELDS_ONLY, + FLAG_MANIFEST, + FLAG_DISABLED, + FLAG_STRINGS_RESOLVED, + FLAG_IMMUTABLE, }) @Retention(RetentionPolicy.SOURCE) public @interface ShortcutFlags {} // Cloning options. - /* @hide */ + /** @hide */ private static final int CLONE_REMOVE_ICON = 1 << 0; - /* @hide */ + /** @hide */ private static final int CLONE_REMOVE_INTENT = 1 << 1; - /* @hide */ + /** @hide */ public static final int CLONE_REMOVE_NON_KEY_INFO = 1 << 2; - /* @hide */ - public static final int CLONE_REMOVE_FOR_CREATOR = CLONE_REMOVE_ICON; + /** @hide */ + public static final int CLONE_REMOVE_RES_NAMES = 1 << 3; + + /** @hide */ + public static final int CLONE_REMOVE_FOR_CREATOR = CLONE_REMOVE_ICON | CLONE_REMOVE_RES_NAMES; - /* @hide */ - public static final int CLONE_REMOVE_FOR_LAUNCHER = CLONE_REMOVE_ICON | CLONE_REMOVE_INTENT; + /** @hide */ + public static final int CLONE_REMOVE_FOR_LAUNCHER = CLONE_REMOVE_ICON | CLONE_REMOVE_INTENT + | CLONE_REMOVE_RES_NAMES; /** @hide */ @IntDef(flag = true, @@ -104,6 +134,7 @@ public final class ShortcutInfo implements Parcelable { CLONE_REMOVE_ICON, CLONE_REMOVE_INTENT, CLONE_REMOVE_NON_KEY_INFO, + CLONE_REMOVE_RES_NAMES, CLONE_REMOVE_FOR_CREATOR, CLONE_REMOVE_FOR_LAUNCHER }) @@ -111,7 +142,7 @@ public final class ShortcutInfo implements Parcelable { public @interface CloneFlags {} /** - * Shortcut category for + * Shortcut category for messaging related actions, such as chat. */ public static final String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation"; @@ -121,33 +152,57 @@ public final class ShortcutInfo implements Parcelable { private final String mPackageName; @Nullable - private ComponentName mActivityComponent; + private ComponentName mActivity; @Nullable private Icon mIcon; - @NonNull - private String mTitle; + private int mTitleResId; + + private String mTitleResName; @Nullable - private String mText; + private CharSequence mTitle; - @NonNull + private int mTextResId; + + private String mTextResName; + + @Nullable + private CharSequence mText; + + private int mDisabledMessageResId; + + private String mDisabledMessageResName; + + @Nullable + private CharSequence mDisabledMessage; + + @Nullable private ArraySet mCategories; /** - * Intent *with extras removed*. + * Intents *with extras removed*. */ - @NonNull - private Intent mIntent; + @Nullable + private Intent[] mIntents; /** - * Extras for the intent. + * Extras for the intents. */ - @NonNull - private PersistableBundle mIntentPersistableExtras; + @Nullable + private PersistableBundle[] mIntentPersistableExtrases; - private int mWeight; + private int mRank; + + /** + * Internally used for auto-rank-adjustment. + * + * RANK_CHANGED_BIT is used to denote that the rank of a shortcut is changing. + * The rest of the bits are used to denote the order in which shortcuts are passed to + * APIs, which is used to preserve the argument order when ranks are tie. + */ + private int mImplicitRank; @Nullable private PersistableBundle mExtras; @@ -159,7 +214,9 @@ public final class ShortcutInfo implements Parcelable { private int mFlags; // Internal use only. - private int mIconResourceId; + private int mIconResId; + + private String mIconResName; // Internal use only. @Nullable @@ -175,26 +232,81 @@ public final class ShortcutInfo implements Parcelable { // Note we can't do other null checks here because SM.updateShortcuts() takes partial // information. mPackageName = b.mContext.getPackageName(); - mActivityComponent = b.mActivityComponent; + mActivity = b.mActivity; mIcon = b.mIcon; mTitle = b.mTitle; + mTitleResId = b.mTitleResId; mText = b.mText; - mCategories = clone(b.mCategories); - mIntent = b.mIntent; - if (mIntent != null) { - final Bundle intentExtras = mIntent.getExtras(); - if (intentExtras != null) { - mIntent.replaceExtras((Bundle) null); - mIntentPersistableExtras = new PersistableBundle(intentExtras); - } - } - mWeight = b.mWeight; + mTextResId = b.mTextResId; + mDisabledMessage = b.mDisabledMessage; + mDisabledMessageResId = b.mDisabledMessageResId; + mCategories = cloneCategories(b.mCategories); + mIntents = cloneIntents(b.mIntents); + fixUpIntentExtras(); + mRank = b.mRank; mExtras = b.mExtras; updateTimestamp(); } - private ArraySet clone(Set source) { - return (source == null) ? null : new ArraySet<>(source); + /** + * Extract extras from {@link #mIntents} and set them to {@link #mIntentPersistableExtrases} + * as {@link PersistableBundle}, and remove extras from the original intents. + */ + private void fixUpIntentExtras() { + if (mIntents == null) { + mIntentPersistableExtrases = null; + return; + } + mIntentPersistableExtrases = new PersistableBundle[mIntents.length]; + for (int i = 0; i < mIntents.length; i++) { + final Intent intent = mIntents[i]; + final Bundle extras = intent.getExtras(); + if (extras == null) { + mIntentPersistableExtrases[i] = null; + } else { + mIntentPersistableExtrases[i] = new PersistableBundle(extras); + intent.replaceExtras((Bundle) null); + } + } + } + + private static ArraySet cloneCategories(Set source) { + if (source == null) { + return null; + } + final ArraySet ret = new ArraySet<>(source.size()); + for (CharSequence s : source) { + if (!TextUtils.isEmpty(s)) { + ret.add(s.toString().intern()); + } + } + return ret; + } + + private static Intent[] cloneIntents(Intent[] intents) { + if (intents == null) { + return null; + } + final Intent[] ret = new Intent[intents.length]; + for (int i = 0; i < ret.length; i++) { + if (intents[i] != null) { + ret[i] = new Intent(intents[i]); + } + } + return ret; + } + + private static PersistableBundle[] clonePersistableBundle(PersistableBundle[] bundle) { + if (bundle == null) { + return null; + } + final PersistableBundle[] ret = new PersistableBundle[bundle.length]; + for (int i = 0; i < ret.length; i++) { + if (bundle[i] != null) { + ret[i] = new PersistableBundle(bundle[i]); + } + } + return ret; } /** @@ -204,8 +316,12 @@ public final class ShortcutInfo implements Parcelable { */ public void enforceMandatoryFields() { Preconditions.checkStringNotEmpty(mId, "Shortcut ID must be provided"); - Preconditions.checkStringNotEmpty(mTitle, "Shortcut title must be provided"); - Preconditions.checkNotNull(mIntent, "Shortcut Intent must be provided"); + Preconditions.checkNotNull(mActivity, "Activity must be provided"); + if (mTitle == null && mTitleResId == 0) { + throw new IllegalArgumentException("Short label must be provided"); + } + Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided"); + Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided"); } /** @@ -215,14 +331,14 @@ public final class ShortcutInfo implements Parcelable { mUserId = source.mUserId; mId = source.mId; mPackageName = source.mPackageName; + mActivity = source.mActivity; mFlags = source.mFlags; mLastChangedTimestamp = source.mLastChangedTimestamp; // Just always keep it since it's cheep. - mIconResourceId = source.mIconResourceId; + mIconResId = source.mIconResId; if ((cloneFlags & CLONE_REMOVE_NON_KEY_INFO) == 0) { - mActivityComponent = source.mActivityComponent; if ((cloneFlags & CLONE_REMOVE_ICON) == 0) { mIcon = source.mIcon; @@ -230,20 +346,247 @@ public final class ShortcutInfo implements Parcelable { } mTitle = source.mTitle; + mTitleResId = source.mTitleResId; mText = source.mText; - mCategories = clone(source.mCategories); + mTextResId = source.mTextResId; + mDisabledMessage = source.mDisabledMessage; + mDisabledMessageResId = source.mDisabledMessageResId; + mCategories = cloneCategories(source.mCategories); if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) { - mIntent = source.mIntent; - mIntentPersistableExtras = source.mIntentPersistableExtras; + mIntents = cloneIntents(source.mIntents); + mIntentPersistableExtrases = + clonePersistableBundle(source.mIntentPersistableExtrases); } - mWeight = source.mWeight; + mRank = source.mRank; mExtras = source.mExtras; + + if ((cloneFlags & CLONE_REMOVE_RES_NAMES) == 0) { + mTitleResName = source.mTitleResName; + mTextResName = source.mTextResName; + mDisabledMessageResName = source.mDisabledMessageResName; + mIconResName = source.mIconResName; + } } else { // Set this bit. mFlags |= FLAG_KEY_FIELDS_ONLY; } } + /** + * Load a string resource from the publisher app. + * + * @param resId resource ID + * @param defValue default value to be returned when the specified resource isn't found. + */ + private CharSequence getResourceString(Resources res, int resId, CharSequence defValue) { + try { + return res.getString(resId); + } catch (NotFoundException e) { + Log.e(TAG, "Resource for ID=" + resId + " not found in package " + mPackageName); + return defValue; + } + } + + /** + * Load the string resources for the text fields and set them to the actual value fields. + * This will set {@link #FLAG_STRINGS_RESOLVED}. + * + * @param res {@link Resources} for the publisher. Must have been loaded with + * {@link PackageManager#getResourcesForApplicationAsUser}. + * + * @hide + */ + public void resolveResourceStrings(@NonNull Resources res) { + mFlags |= FLAG_STRINGS_RESOLVED; + + if ((mTitleResId == 0) && (mTextResId == 0) && (mDisabledMessageResId == 0)) { + return; // Bail early. + } + + if (mTitleResId != 0) { + mTitle = getResourceString(res, mTitleResId, mTitle); + } + if (mTextResId != 0) { + mText = getResourceString(res, mTextResId, mText); + } + if (mDisabledMessageResId != 0) { + mDisabledMessage = getResourceString(res, mDisabledMessageResId, mDisabledMessage); + } + } + + /** + * Look up resource name for a given resource ID. + * + * @return a simple resource name (e.g. "text_1") when {@code withType} is false, or with the + * type (e.g. "string/text_1"). + * + * @hide + */ + @VisibleForTesting + public static String lookUpResourceName(@NonNull Resources res, int resId, boolean withType, + @NonNull String packageName) { + if (resId == 0) { + return null; + } + try { + final String fullName = res.getResourceName(resId); + + if (ANDROID_PACKAGE_NAME.equals(getResourcePackageName(fullName))) { + // If it's a framework resource, the value won't change, so just return the ID + // value as a string. + return String.valueOf(resId); + } + return withType ? getResourceTypeAndEntryName(fullName) + : getResourceEntryName(fullName); + } catch (NotFoundException e) { + Log.e(TAG, "Resource name for ID=" + resId + " not found in package " + packageName + + ". Resource IDs may change when the application is upgraded, and the system" + + " may not be able to find the correct resource."); + return null; + } + } + + /** + * Extract the package name from a fully-donated resource name. + * e.g. "com.android.app1:drawable/icon1" -> "com.android.app1" + * @hide + */ + @VisibleForTesting + public static String getResourcePackageName(@NonNull String fullResourceName) { + final int p1 = fullResourceName.indexOf(':'); + if (p1 < 0) { + return null; + } + return fullResourceName.substring(0, p1); + } + + /** + * Extract the type name from a fully-donated resource name. + * e.g. "com.android.app1:drawable/icon1" -> "drawable" + * @hide + */ + @VisibleForTesting + public static String getResourceTypeName(@NonNull String fullResourceName) { + final int p1 = fullResourceName.indexOf(':'); + if (p1 < 0) { + return null; + } + final int p2 = fullResourceName.indexOf('/', p1 + 1); + if (p2 < 0) { + return null; + } + return fullResourceName.substring(p1 + 1, p2); + } + + /** + * Extract the type name + the entry name from a fully-donated resource name. + * e.g. "com.android.app1:drawable/icon1" -> "drawable/icon1" + * @hide + */ + @VisibleForTesting + public static String getResourceTypeAndEntryName(@NonNull String fullResourceName) { + final int p1 = fullResourceName.indexOf(':'); + if (p1 < 0) { + return null; + } + return fullResourceName.substring(p1 + 1); + } + + /** + * Extract the entry name from a fully-donated resource name. + * e.g. "com.android.app1:drawable/icon1" -> "icon1" + * @hide + */ + @VisibleForTesting + public static String getResourceEntryName(@NonNull String fullResourceName) { + final int p1 = fullResourceName.indexOf('/'); + if (p1 < 0) { + return null; + } + return fullResourceName.substring(p1 + 1); + } + + /** + * Return the resource ID for a given resource ID. + * + * Basically its' a wrapper over {@link Resources#getIdentifier(String, String, String)}, except + * if {@code resourceName} is an integer then it'll just return its value. (Which also the + * aforementioned method would do internally, but not documented, so doing here explicitly.) + * + * @param res {@link Resources} for the publisher. Must have been loaded with + * {@link PackageManager#getResourcesForApplicationAsUser}. + * + * @hide + */ + @VisibleForTesting + public static int lookUpResourceId(@NonNull Resources res, @Nullable String resourceName, + @Nullable String resourceType, String packageName) { + if (resourceName == null) { + return 0; + } + try { + try { + // It the name can be parsed as an integer, just use it. + return Integer.parseInt(resourceName); + } catch (NumberFormatException ignore) { + } + + return res.getIdentifier(resourceName, resourceType, packageName); + } catch (NotFoundException e) { + Log.e(TAG, "Resource ID for name=" + resourceName + " not found in package " + + packageName); + return 0; + } + } + + /** + * Look up resource names from the resource IDs for the icon res and the text fields, and fill + * in the resource name fields. + * + * @param res {@link Resources} for the publisher. Must have been loaded with + * {@link PackageManager#getResourcesForApplicationAsUser}. + * + * @hide + */ + public void lookupAndFillInResourceNames(@NonNull Resources res) { + if ((mTitleResId == 0) && (mTextResId == 0) && (mDisabledMessageResId == 0) + && (mIconResId == 0)) { + return; // Bail early. + } + + // We don't need types for strings because their types are always "string". + mTitleResName = lookUpResourceName(res, mTitleResId, /*withType=*/ false, mPackageName); + mTextResName = lookUpResourceName(res, mTextResId, /*withType=*/ false, mPackageName); + mDisabledMessageResName = lookUpResourceName(res, mDisabledMessageResId, + /*withType=*/ false, mPackageName); + + // But icons have multiple possible types, so include the type. + mIconResName = lookUpResourceName(res, mIconResId, /*withType=*/ true, mPackageName); + } + + /** + * Look up resource IDs from the resource names for the icon res and the text fields, and fill + * in the resource ID fields. + * + * This is called when an app is updated. + * + * @hide + */ + public void lookupAndFillInResourceIds(@NonNull Resources res) { + if ((mTitleResName == null) && (mTextResName == null) && (mDisabledMessageResName == null) + && (mIconResName == null)) { + return; // Bail early. + } + + mTitleResId = lookUpResourceId(res, mTitleResName, RES_TYPE_STRING, mPackageName); + mTextResId = lookUpResourceId(res, mTextResName, RES_TYPE_STRING, mPackageName); + mDisabledMessageResId = lookUpResourceId(res, mDisabledMessageResName, RES_TYPE_STRING, + mPackageName); + + // mIconResName already contains the type, so the third argument is not needed. + mIconResId = lookUpResourceId(res, mIconResName, null, mPackageName); + } + /** * Copy a {@link ShortcutInfo}, optionally removing fields. * @hide @@ -252,50 +595,86 @@ public final class ShortcutInfo implements Parcelable { return new ShortcutInfo(this, cloneFlags); } + /** + * @hide + */ + public void ensureUpdatableWith(ShortcutInfo source) { + Preconditions.checkState(mUserId == source.mUserId, "Owner User ID must match"); + Preconditions.checkState(mId.equals(source.mId), "ID must match"); + Preconditions.checkState(mPackageName.equals(source.mPackageName), + "Package name must match"); + Preconditions.checkState(!isImmutable(), "Target ShortcutInfo is immutable"); + } + /** * Copy non-null/zero fields from another {@link ShortcutInfo}. Only "public" information - * will be overwritten. The timestamp will be updated. + * will be overwritten. The timestamp will *not* be updated to be consistent with other + * setters (and also the clock is not injectable in this file). * * - Flags will not change * - mBitmapPath will not change * - Current time will be set to timestamp * + * @throws IllegalStateException if source is not compatible. + * * @hide */ public void copyNonNullFieldsFrom(ShortcutInfo source) { - Preconditions.checkState(mUserId == source.mUserId, "Owner User ID must match"); - Preconditions.checkState(mId.equals(source.mId), "ID must match"); - Preconditions.checkState(mPackageName.equals(source.mPackageName), - "Package name must match"); + ensureUpdatableWith(source); - if (source.mActivityComponent != null) { - mActivityComponent = source.mActivityComponent; + if (source.mActivity != null) { + mActivity = source.mActivity; } if (source.mIcon != null) { mIcon = source.mIcon; + + mIconResId = 0; + mIconResName = null; + mBitmapPath = null; } if (source.mTitle != null) { mTitle = source.mTitle; + mTitleResId = 0; + mTitleResName = null; + } else if (source.mTitleResId != 0) { + mTitle = null; + mTitleResId = source.mTitleResId; + mTitleResName = null; } + if (source.mText != null) { mText = source.mText; + mTextResId = 0; + mTextResName = null; + } else if (source.mTextResId != 0) { + mText = null; + mTextResId = source.mTextResId; + mTextResName = null; + } + if (source.mDisabledMessage != null) { + mDisabledMessage = source.mDisabledMessage; + mDisabledMessageResId = 0; + mDisabledMessageResName = null; + } else if (source.mDisabledMessageResId != 0) { + mDisabledMessage = null; + mDisabledMessageResId = source.mDisabledMessageResId; + mDisabledMessageResName = null; } if (source.mCategories != null) { - mCategories = clone(source.mCategories); + mCategories = cloneCategories(source.mCategories); } - if (source.mIntent != null) { - mIntent = source.mIntent; - mIntentPersistableExtras = source.mIntentPersistableExtras; + if (source.mIntents != null) { + mIntents = cloneIntents(source.mIntents); + mIntentPersistableExtrases = + clonePersistableBundle(source.mIntentPersistableExtrases); } - if (source.mWeight != 0) { - mWeight = source.mWeight; + if (source.mRank != RANK_NOT_SET) { + mRank = source.mRank; } if (source.mExtras != null) { mExtras = source.mExtras; } - - updateTimestamp(); } /** @@ -310,7 +689,6 @@ public final class ShortcutInfo implements Parcelable { throw getInvalidIconException(); } if (icon.hasTint()) { - // TODO support it throw new IllegalArgumentException("Icons with tints are not supported"); } @@ -320,77 +698,123 @@ public final class ShortcutInfo implements Parcelable { /** @hide */ public static IllegalArgumentException getInvalidIconException() { return new IllegalArgumentException("Unsupported icon type:" - +" only bitmap, resource and content URI are supported"); + +" only the bitmap and resource types are supported"); } /** * Builder class for {@link ShortcutInfo} objects. + * + * @see ShortcutManager */ public static class Builder { private final Context mContext; private String mId; - private ComponentName mActivityComponent; + private ComponentName mActivity; private Icon mIcon; - private String mTitle; + private int mTitleResId; + + private CharSequence mTitle; + + private int mTextResId; + + private CharSequence mText; - private String mText; + private int mDisabledMessageResId; + + private CharSequence mDisabledMessage; private Set mCategories; - private Intent mIntent; + private Intent[] mIntents; - private int mWeight; + private int mRank = RANK_NOT_SET; private PersistableBundle mExtras; - /** Constructor. */ + /** + * Old style constructor. + * @hide + */ + @Deprecated public Builder(Context context) { mContext = context; } /** - * Sets the ID of the shortcut. This is a mandatory field. + * Used with the old style constructor, kept for unit tests. + * @hide */ @NonNull + @Deprecated public Builder setId(@NonNull String id) { - mId = Preconditions.checkStringNotEmpty(id, "id"); + mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty"); return this; } /** - * Optionally sets the target activity. If it's not set, and if the caller application - * has multiple launcher icons, this shortcut will be shown on all those icons. - * If it's set, this shortcut will be only shown on this activity. + * Constructor. + * + * @param context Client context. + * @param id ID of the shortcut. + */ + public Builder(Context context, String id) { + mContext = context; + mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty"); + } + + /** + * Sets the target activity. A shortcut will be shown along with this activity's icon + * on the launcher. + * + * When selecting a target activity, keep the following in mind: + *
    + *
  • All dynamic shortcuts must have a target activity. When a shortcut with no target + * activity is published using + * {@link ShortcutManager#addDynamicShortcuts(List)} or + * {@link ShortcutManager#setDynamicShortcuts(List)}, + * the first main activity defined in the application's AndroidManifest.xml + * file is used. * - *

    The package name of the target activity must match the package name of the shortcut - * publisher. + *

  • Only "main" activities—ones that define the {@link Intent#ACTION_MAIN} + * and {@link Intent#CATEGORY_LAUNCHER} intent filters—can be target + * activities. * - *

    This has nothing to do with the activity that this shortcut will launch. This is - * a hint to the launcher app about which launcher icon to associate this shortcut with. + *

  • By default, the first main activity defined in the application manifest is + * the target activity. + * + *
  • A target activity must belong to the publisher application. + *
+ * + * @see ShortcutInfo#getActivity() */ @NonNull - public Builder setActivityComponent(@NonNull ComponentName activityComponent) { - mActivityComponent = Preconditions.checkNotNull(activityComponent, "activityComponent"); + public Builder setActivity(@NonNull ComponentName activity) { + mActivity = Preconditions.checkNotNull(activity, "activity cannot be null"); return this; } /** - * Optionally sets an icon. + * Sets an icon of a shortcut. * - *
    - *
  • Tints set by {@link Icon#setTint} or {@link Icon#setTintList} are not supported. - *
  • Bitmaps and resources are supported, but "content:" URIs are not supported. - *
+ *

Icons are not available on {@link ShortcutInfo} instances + * returned by {@link ShortcutManager} or {@link LauncherApps}. The default launcher + * application can use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)} + * or {@link LauncherApps#getShortcutBadgedIconDrawable(ShortcutInfo, int)} to fetch + * shortcut icons. + * + *

Tints set with {@link Icon#setTint} or {@link Icon#setTintList} are not supported + * and will be ignored. * - *

For performance reasons, icons will NOT be available on instances - * returned by {@link ShortcutManager} or {@link LauncherApps}. Launcher applications - * can use {@link ShortcutInfo#getIconResourceId()} if {@link #hasIconResource()} is true. - * Otherwise, if {@link #hasIconFile()} is true, use - * {@link LauncherApps#getShortcutIconFd} to load the image. + *

Only icons created with {@link Icon#createWithBitmap(Bitmap)} and + * {@link Icon#createWithResource} are supported. + * Other types, such as URI-based icons, are not supported. + * + * @see LauncherApps#getShortcutIconDrawable(ShortcutInfo, int) + * @see LauncherApps#getShortcutBadgedIconDrawable(ShortcutInfo, int) */ @NonNull public Builder setIcon(Icon icon) { @@ -399,26 +823,112 @@ public final class ShortcutInfo implements Parcelable { } /** - * Sets the title of a shortcut. This is a mandatory field. + * @hide We don't support resource strings for dynamic shortcuts for now. (But unit tests + * use it.) + */ + @Deprecated + public Builder setShortLabelResId(int shortLabelResId) { + Preconditions.checkState(mTitle == null, "shortLabel already set"); + mTitleResId = shortLabelResId; + return this; + } + + /** + * Sets the short title of a shortcut. + * + *

This is a mandatory field when publishing a new shortcut with + * {@link ShortcutManager#addDynamicShortcuts(List)} or + * {@link ShortcutManager#setDynamicShortcuts(List)}. + * + *

This field is intended to be a concise description of a shortcut. + * + *

The recommended maximum length is 10 characters. * - *

This field is intended for a concise description of a shortcut displayed under - * an icon. The recommend max length is 10 characters. + * @see ShortcutInfo#getShortLabel() */ @NonNull - public Builder setTitle(@NonNull String title) { - mTitle = Preconditions.checkStringNotEmpty(title, "title"); + public Builder setShortLabel(@NonNull CharSequence shortLabel) { + Preconditions.checkState(mTitleResId == 0, "shortLabelResId already set"); + mTitle = Preconditions.checkStringNotEmpty(shortLabel, "shortLabel cannot be empty"); + return this; + } + + /** + * @hide We don't support resource strings for dynamic shortcuts for now. (But unit tests + * use it.) + */ + @Deprecated + public Builder setLongLabelResId(int longLabelResId) { + Preconditions.checkState(mText == null, "longLabel already set"); + mTextResId = longLabelResId; return this; } /** - * Sets the text of a shortcut. This is an optional field. + * Sets the text of a shortcut. + * + *

This field is intended to be more descriptive than the shortcut title. The launcher + * shows this instead of the short title when it has enough space. + * + *

The recommend maximum length is 25 characters. * - *

This field is intended to be more descriptive than the shortcut title. - * The recommend max length is 25 characters. + * @see ShortcutInfo#getLongLabel() */ @NonNull - public Builder setText(@NonNull String text) { - mText = Preconditions.checkStringNotEmpty(text, "text"); + public Builder setLongLabel(@NonNull CharSequence longLabel) { + Preconditions.checkState(mTextResId == 0, "longLabelResId already set"); + mText = Preconditions.checkStringNotEmpty(longLabel, "longLabel cannot be empty"); + return this; + } + + /** @hide -- old signature, the internal code still uses it. */ + @Deprecated + public Builder setTitle(@NonNull CharSequence value) { + return setShortLabel(value); + } + + /** @hide -- old signature, the internal code still uses it. */ + @Deprecated + public Builder setTitleResId(int value) { + return setShortLabelResId(value); + } + + /** @hide -- old signature, the internal code still uses it. */ + @Deprecated + public Builder setText(@NonNull CharSequence value) { + return setLongLabel(value); + } + + /** @hide -- old signature, the internal code still uses it. */ + @Deprecated + public Builder setTextResId(int value) { + return setLongLabelResId(value); + } + + /** + * @hide We don't support resource strings for dynamic shortcuts for now. (But unit tests + * use it.) + */ + @Deprecated + public Builder setDisabledMessageResId(int disabledMessageResId) { + Preconditions.checkState(mDisabledMessage == null, "disabledMessage already set"); + mDisabledMessageResId = disabledMessageResId; + return this; + } + + /** + * Sets the message that should be shown when the user attempts to start a shortcut that + * is disabled. + * + * @see ShortcutInfo#getDisabledMessage() + */ + @NonNull + public Builder setDisabledMessage(@NonNull CharSequence disabledMessage) { + Preconditions.checkState( + mDisabledMessageResId == 0, "disabledMessageResId already set"); + mDisabledMessage = + Preconditions.checkStringNotEmpty(disabledMessage, + "disabledMessage cannot be empty"); return this; } @@ -427,6 +937,7 @@ public final class ShortcutInfo implements Parcelable { * categorise shortcuts. * * @see #SHORTCUT_CATEGORY_CONVERSATION + * @see ShortcutInfo#getCategories() */ @NonNull public Builder setCategories(Set categories) { @@ -435,28 +946,70 @@ public final class ShortcutInfo implements Parcelable { } /** - * Sets the intent of a shortcut. This is a mandatory field. The extras must only contain - * persistable information. (See {@link PersistableBundle}). + * Sets the intent of a shortcut. Alternatively, {@link #setIntents(Intent[])} can be used + * to launch an activity with other activities in the back stack. + * + *

This is a mandatory field when publishing a new shortcut with + * {@link ShortcutManager#addDynamicShortcuts(List)} or + * {@link ShortcutManager#setDynamicShortcuts(List)}. + * + *

A shortcut can launch any intent that the publisher application has permission to + * launch. For example, a shortcut can launch an unexported activity within the publisher + * application. A shortcut intent doesn't have to point at the target activity. + * + *

The given {@code intent} can contain extras, but these extras must contain values + * of primitive types in order for the system to persist these values. + * + * @see ShortcutInfo#getIntent() + * @see #setIntents(Intent[]) */ @NonNull public Builder setIntent(@NonNull Intent intent) { - mIntent = Preconditions.checkNotNull(intent, "intent"); + return setIntents(new Intent[]{intent}); + } + + /** + * Sets multiple intents instead of a single intent, in order to launch an activity with + * other activities in back stack. Use {@link TaskStackBuilder} to build intents. + * See the {@link ShortcutManager} javadoc for details. + * + * @see Builder#setIntent(Intent) + * @see ShortcutInfo#getIntents() + * @see Context#startActivities(Intent[]) + * @see TaskStackBuilder + */ + @NonNull + public Builder setIntents(@NonNull Intent[] intents) { + Preconditions.checkNotNull(intents, "intents cannot be null"); + Preconditions.checkNotNull(intents.length, "intents cannot be empty"); + for (Intent intent : intents) { + Preconditions.checkNotNull(intent, "intents cannot contain null"); + Preconditions.checkNotNull(intent.getAction(), "intent's action must be set"); + } + // Make sure always clone incoming intents. + mIntents = cloneIntents(intents); return this; } /** - * Optionally sets the weight of a shortcut, which will be used by the launcher for sorting. - * The larger the weight, the more "important" a shortcut is. + * "Rank" of a shortcut, which is a non-negative value that's used by the launcher app + * to sort shortcuts. + * + * See {@link ShortcutInfo#getRank()} for details. */ @NonNull - public Builder setWeight(int weight) { - mWeight = weight; + public Builder setRank(int rank) { + Preconditions.checkArgument((0 <= rank), + "Rank cannot be negative or bigger than MAX_RANK"); + mRank = rank; return this; } /** - * Optional values that applications can set. Applications can store any meta-data of - * shortcuts in this, and retrieve later from {@link ShortcutInfo#getExtras()}. + * Extras that application can set for any purpose. + * + *

Applications can store arbitrary shortcut metadata in extras and retrieve the + * metadata later using {@link ShortcutInfo#getExtras()}. */ @NonNull public Builder setExtras(@NonNull PersistableBundle extras) { @@ -474,7 +1027,11 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return the ID of the shortcut. + * Returns the ID of a shortcut. + * + *

Shortcut IDs are unique within each publisher application and must be stable across + * devices so that shortcuts will still be valid when restored on a different device. + * See {@link ShortcutManager} for details. */ @NonNull public String getId() { @@ -482,33 +1039,34 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return the package name of the creator application. + * Return the package name of the publisher application. */ @NonNull - public String getPackageName() { + public String getPackage() { return mPackageName; } /** - * Return the target activity, which may be null, in which case the shortcut is not associated - * with a specific activity. + * Return the target activity. * - *

This has nothing to do with the activity that this shortcut will launch. This is - * a hint to the launcher app that on which launcher icon this shortcut should be shown. + *

This has nothing to do with the activity that this shortcut will launch. + * Launcher applications should show the launcher icon for the returned activity alongside + * this shortcut. * - * @see Builder#setActivityComponent + * @see Builder#setActivity */ @Nullable - public ComponentName getActivityComponent() { - return mActivityComponent; + public ComponentName getActivity() { + return mActivity; + } + + /** @hide */ + public void setActivity(ComponentName activity) { + mActivity = activity; } /** - * Icon. - * - * For performance reasons, this will NOT be available when an instance is returned - * by {@link ShortcutManager} or {@link LauncherApps}. A launcher application needs to use - * other APIs in LauncherApps to fetch the bitmap. + * Returns the shortcut icon. * * @hide */ @@ -517,27 +1075,82 @@ public final class ShortcutInfo implements Parcelable { return mIcon; } + /** @hide -- old signature, the internal code still uses it. */ + @Nullable + @Deprecated + public CharSequence getTitle() { + return mTitle; + } + + /** @hide -- old signature, the internal code still uses it. */ + @Deprecated + public int getTitleResId() { + return mTitleResId; + } + + /** @hide -- old signature, the internal code still uses it. */ + @Nullable + @Deprecated + public CharSequence getText() { + return mText; + } + + /** @hide -- old signature, the internal code still uses it. */ + @Deprecated + public int getTextResId() { + return mTextResId; + } + /** - * Return the shortcut title. + * Return the shorter description of a shortcut. * - *

All shortcuts must have a non-empty title, but this method will return null when - * {@link #hasKeyFieldsOnly()} is true. + * @see Builder#setShortLabel(CharSequence) */ @Nullable - public String getTitle() { + public CharSequence getShortLabel() { return mTitle; } + /** @hide */ + public int getShortLabelResourceId() { + return mTitleResId; + } + /** - * Return the shortcut text. + * Return the longer description of a shortcut. + * + * @see Builder#setLongLabel(CharSequence) */ @Nullable - public String getText() { + public CharSequence getLongLabel() { return mText; } + /** @hide */ + public int getLongLabelResourceId() { + return mTextResId; + } + + /** + * Return the message that should be shown when the user attempts to start a shortcut + * that is disabled. + * + * @see Builder#setDisabledMessage(CharSequence) + */ + @Nullable + public CharSequence getDisabledMessage() { + return mDisabledMessage; + } + + /** @hide */ + public int getDisabledMessageResourceId() { + return mDisabledMessageResId; + } + /** - * Return the categories. + * Return the shortcut's categories. + * + * @see Builder#setCategories(Set) */ @Nullable public Set getCategories() { @@ -545,55 +1158,125 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return the intent. + * Returns the intent that is executed when the user selects this shortcut. + * If setIntents() was used, then return the last intent in the array. * - *

All shortcuts must have an intent, but this method will return null when - * {@link #hasKeyFieldsOnly()} is true. + *

Launcher applications cannot see the intent. If a {@link ShortcutInfo} is + * obtained via {@link LauncherApps}, then this method will always return null. + * Launchers can only start a shortcut intent with {@link LauncherApps#startShortcut}. * - *

Launcher apps cannot see the intent. If a {@link ShortcutInfo} is obtained via - * {@link LauncherApps}, then this method will always return null. Launcher apps can only - * start a shortcut intent with {@link LauncherApps#startShortcut}. + * @see Builder#setIntent(Intent) */ @Nullable public Intent getIntent() { - if (mIntent == null) { + if (mIntents == null || mIntents.length == 0) { return null; } - final Intent intent = new Intent(mIntent); - intent.replaceExtras( - mIntentPersistableExtras != null ? new Bundle(mIntentPersistableExtras) : null); - return intent; + final int last = mIntents.length - 1; + final Intent intent = new Intent(mIntents[last]); + return setIntentExtras(intent, mIntentPersistableExtrases[last]); } /** - * Return "raw" intent, which is the original intent without the extras. + * Return the intent set with {@link Builder#setIntents(Intent[])}. + * + *

Launcher applications cannot see the intents. If a {@link ShortcutInfo} is + * obtained via {@link LauncherApps}, then this method will always return null. + * Launchers can only start a shortcut intent with {@link LauncherApps#startShortcut}. + * + * @see Builder#setIntents(Intent[]) + */ + @Nullable + public Intent[] getIntents() { + final Intent[] ret = new Intent[mIntents.length]; + + for (int i = 0; i < ret.length; i++) { + ret[i] = new Intent(mIntents[i]); + setIntentExtras(ret[i], mIntentPersistableExtrases[i]); + } + + return ret; + } + + /** + * Return "raw" intents, which is the original intents without the extras. * @hide */ @Nullable - public Intent getIntentNoExtras() { - return mIntent; + public Intent[] getIntentsNoExtras() { + return mIntents; } /** - * The extras in the intent. We convert extras into {@link PersistableBundle} so we can + * The extras in the intents. We convert extras into {@link PersistableBundle} so we can * persist them. * @hide */ @Nullable - public PersistableBundle getIntentPersistableExtras() { - return mIntentPersistableExtras; + public PersistableBundle[] getIntentPersistableExtrases() { + return mIntentPersistableExtrases; } /** - * Return the weight of a shortcut, which will be used by Launcher for sorting. - * The larger the weight, the more "important" a shortcut is. + * "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each + * {@link #getActivity} for each of the two kinds, dynamic shortcuts and manifest shortcuts. + * + *

Because manifest shortcuts and dynamic shortcuts have overlapping ranks, + * when a launcher application shows shortcuts for an activity, it should first show + * the manifest shortcuts followed by the dynamic shortcuts. Within each of those categories, + * shortcuts should be sorted by rank in ascending order. + * + *

"Floating" shortcuts (i.e. shortcuts that are neither dynamic nor manifest) will all + * have rank 0, because there's no sorting for them. + * + * See the {@link ShortcutManager}'s class javadoc for details. + * + * @see Builder#setRank(int) */ - public int getWeight() { - return mWeight; + public int getRank() { + return mRank; + } + + /** @hide */ + public boolean hasRank() { + return mRank != RANK_NOT_SET; + } + + /** @hide */ + public void setRank(int rank) { + mRank = rank; + } + + /** @hide */ + public void clearImplicitRankAndRankChangedFlag() { + mImplicitRank = 0; + } + + /** @hide */ + public void setImplicitRank(int rank) { + // Make sure to keep RANK_CHANGED_BIT. + mImplicitRank = (mImplicitRank & RANK_CHANGED_BIT) | (rank & IMPLICIT_RANK_MASK); + } + + /** @hide */ + public int getImplicitRank() { + return mImplicitRank & IMPLICIT_RANK_MASK; + } + + /** @hide */ + public void setRankChanged() { + mImplicitRank |= RANK_CHANGED_BIT; + } + + /** @hide */ + public boolean isRankChanged() { + return (mImplicitRank & RANK_CHANGED_BIT) != 0; } /** - * Optional values that application can set. + * Extras that application can set to any purposes. + * + * @see Builder#setExtras(PersistableBundle) */ @Nullable public PersistableBundle getExtras() { @@ -606,7 +1289,7 @@ public final class ShortcutInfo implements Parcelable { } /** - * {@link UserHandle} on which the publisher created shortcuts. + * {@link UserHandle} on which the publisher created this shortcut. */ public UserHandle getUserHandle() { return UserHandle.of(mUserId); @@ -655,19 +1338,94 @@ public final class ShortcutInfo implements Parcelable { return hasFlags(FLAG_PINNED); } + /** + * Return whether a shortcut is published from AndroidManifest.xml or not. If {@code true}, + * it's also {@link #isImmutable()}. + * + *

When an app is upgraded and a shortcut is no longer published from AndroidManifest.xml, + * this will be set to {@code false}. If the shortcut is not pinned, then it'll just disappear. + * However, if it's pinned, it will still be alive, and {@link #isEnabled()} will be + * {@code false} and {@link #isImmutable()} will be {@code true}. + */ + public boolean isDeclaredInManifest() { + return hasFlags(FLAG_MANIFEST); + } + + /** @hide kept for unit tests */ + @Deprecated + public boolean isManifestShortcut() { + return isDeclaredInManifest(); + } + + /** + * @return true if pinned but neither dynamic nor manifest. + * @hide + */ + public boolean isFloating() { + return isPinned() && !(isDynamic() || isManifestShortcut()); + } + + /** @hide */ + public boolean isOriginallyFromManifest() { + return hasFlags(FLAG_IMMUTABLE); + } + + /** + * Return if a shortcut is immutable, in which case it cannot be modified with any of + * {@link ShortcutManager} APIs. + * + *

All manifest shortcuts are immutable. When a manifest shortcut is pinned and then + * disabled because the app is upgraded and its AndroidManifest.xml no longer publishes it, + * {@link #isDeclaredInManifest()} returns {@code false}, but it is still immutable. + * + *

All shortcuts originally published via the {@link ShortcutManager} APIs + * are all mutable. + */ + public boolean isImmutable() { + return hasFlags(FLAG_IMMUTABLE); + } + + /** + * Returns {@code false} if a shortcut is disabled with + * {@link ShortcutManager#disableShortcuts}. + */ + public boolean isEnabled() { + return !hasFlags(FLAG_DISABLED); + } + + /** @hide */ + public boolean isAlive() { + return hasFlags(FLAG_PINNED) || hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_MANIFEST); + } + + /** @hide */ + public boolean usesQuota() { + return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_MANIFEST); + } + /** * Return whether a shortcut's icon is a resource in the owning package. * - * @see LauncherApps#getShortcutIconResId(ShortcutInfo) + * @hide internal/unit tests only */ public boolean hasIconResource() { return hasFlags(FLAG_HAS_ICON_RES); } + /** @hide */ + public boolean hasStringResources() { + return (mTitleResId != 0) || (mTextResId != 0) || (mDisabledMessageResId != 0); + } + + /** @hide */ + public boolean hasAnyResources() { + return hasIconResource() || hasStringResources(); + } + /** * Return whether a shortcut's icon is stored as a file. * - * @see LauncherApps#getShortcutIconFd(ShortcutInfo) + * @hide internal/unit tests only */ public boolean hasIconFile() { return hasFlags(FLAG_HAS_ICON_FILE); @@ -678,18 +1436,32 @@ public final class ShortcutInfo implements Parcelable { * following fields are available. *

    *
  • {@link #getId()} - *
  • {@link #getPackageName()} + *
  • {@link #getPackage()} + *
  • {@link #getActivity()} *
  • {@link #getLastChangedTimestamp()} *
  • {@link #isDynamic()} *
  • {@link #isPinned()} - *
  • {@link #hasIconResource()} - *
  • {@link #hasIconFile()} + *
  • {@link #isDeclaredInManifest()} + *
  • {@link #isImmutable()} + *
  • {@link #isEnabled()} + *
  • {@link #getUserHandle()} *
+ * + *

For performance reasons, shortcuts passed to + * {@link LauncherApps.Callback#onShortcutsChanged(String, List, UserHandle)} as well as those + * returned from {@link LauncherApps#getShortcuts(ShortcutQuery, UserHandle)} + * while using the {@link ShortcutQuery#FLAG_GET_KEY_FIELDS_ONLY} option contain only key + * information. */ public boolean hasKeyFieldsOnly() { return hasFlags(FLAG_KEY_FIELDS_ONLY); } + /** @hide */ + public boolean hasStringResourcesResolved() { + return hasFlags(FLAG_STRINGS_RESOLVED); + } + /** @hide */ public void updateTimestamp() { mLastChangedTimestamp = System.currentTimeMillis(); @@ -708,14 +1480,18 @@ public final class ShortcutInfo implements Parcelable { /** @hide */ public void setIconResourceId(int iconResourceId) { - mIconResourceId = iconResourceId; + if (mIconResId != iconResourceId) { + mIconResName = null; + } + mIconResId = iconResourceId; } /** * Get the resource ID for the icon, valid only when {@link #hasIconResource()} } is true. + * @hide internal / tests only. */ public int getIconResourceId() { - return mIconResourceId; + return mIconResId; } /** @hide */ @@ -728,25 +1504,129 @@ public final class ShortcutInfo implements Parcelable { mBitmapPath = bitmapPath; } + /** @hide */ + public void setDisabledMessageResId(int disabledMessageResId) { + if (mDisabledMessageResId != disabledMessageResId) { + mDisabledMessageResName = null; + } + mDisabledMessageResId = disabledMessageResId; + mDisabledMessage = null; + } + + /** @hide */ + public void setDisabledMessage(String disabledMessage) { + mDisabledMessage = disabledMessage; + mDisabledMessageResId = 0; + mDisabledMessageResName = null; + } + + /** @hide */ + public String getTitleResName() { + return mTitleResName; + } + + /** @hide */ + public void setTitleResName(String titleResName) { + mTitleResName = titleResName; + } + + /** @hide */ + public String getTextResName() { + return mTextResName; + } + + /** @hide */ + public void setTextResName(String textResName) { + mTextResName = textResName; + } + + /** @hide */ + public String getDisabledMessageResName() { + return mDisabledMessageResName; + } + + /** @hide */ + public void setDisabledMessageResName(String disabledMessageResName) { + mDisabledMessageResName = disabledMessageResName; + } + + /** @hide */ + public String getIconResName() { + return mIconResName; + } + + /** @hide */ + public void setIconResName(String iconResName) { + mIconResName = iconResName; + } + + /** + * Replaces the intent + * + * @throws IllegalArgumentException when extra is not compatible with {@link PersistableBundle}. + * + * @hide + */ + public void setIntents(Intent[] intents) throws IllegalArgumentException { + Preconditions.checkNotNull(intents); + Preconditions.checkArgument(intents.length > 0); + + mIntents = cloneIntents(intents); + fixUpIntentExtras(); + } + + /** @hide */ + public static Intent setIntentExtras(Intent intent, PersistableBundle extras) { + if (extras == null) { + intent.replaceExtras((Bundle) null); + } else { + intent.replaceExtras(new Bundle(extras)); + } + return intent; + } + + /** + * Replaces the categories. + * + * @hide + */ + public void setCategories(Set categories) { + mCategories = cloneCategories(categories); + } + private ShortcutInfo(Parcel source) { final ClassLoader cl = getClass().getClassLoader(); mUserId = source.readInt(); mId = source.readString(); mPackageName = source.readString(); - mActivityComponent = source.readParcelable(cl); + mActivity = source.readParcelable(cl); + mFlags = source.readInt(); + mIconResId = source.readInt(); + mLastChangedTimestamp = source.readLong(); + + if (source.readInt() == 0) { + return; // key information only. + } + mIcon = source.readParcelable(cl); - mTitle = source.readString(); - mText = source.readString(); - mIntent = source.readParcelable(cl); - mIntentPersistableExtras = source.readParcelable(cl); - mWeight = source.readInt(); + mTitle = source.readCharSequence(); + mTitleResId = source.readInt(); + mText = source.readCharSequence(); + mTextResId = source.readInt(); + mDisabledMessage = source.readCharSequence(); + mDisabledMessageResId = source.readInt(); + mIntents = source.readParcelableArray(cl, Intent.class); + mIntentPersistableExtrases = source.readParcelableArray(cl, PersistableBundle.class); + mRank = source.readInt(); mExtras = source.readParcelable(cl); - mLastChangedTimestamp = source.readLong(); - mFlags = source.readInt(); - mIconResourceId = source.readInt(); mBitmapPath = source.readString(); + mIconResName = source.readString(); + mTitleResName = source.readString(); + mTextResName = source.readString(); + mDisabledMessageResName = source.readString(); + int N = source.readInt(); if (N == 0) { mCategories = null; @@ -763,20 +1643,36 @@ public final class ShortcutInfo implements Parcelable { dest.writeInt(mUserId); dest.writeString(mId); dest.writeString(mPackageName); - dest.writeParcelable(mActivityComponent, flags); - dest.writeParcelable(mIcon, flags); - dest.writeString(mTitle); - dest.writeString(mText); + dest.writeParcelable(mActivity, flags); + dest.writeInt(mFlags); + dest.writeInt(mIconResId); + dest.writeLong(mLastChangedTimestamp); - dest.writeParcelable(mIntent, flags); - dest.writeParcelable(mIntentPersistableExtras, flags); - dest.writeInt(mWeight); + if (hasKeyFieldsOnly()) { + dest.writeInt(0); + return; + } + dest.writeInt(1); + + dest.writeParcelable(mIcon, flags); + dest.writeCharSequence(mTitle); + dest.writeInt(mTitleResId); + dest.writeCharSequence(mText); + dest.writeInt(mTextResId); + dest.writeCharSequence(mDisabledMessage); + dest.writeInt(mDisabledMessageResId); + + dest.writeParcelableArray(mIntents, flags); + dest.writeParcelableArray(mIntentPersistableExtrases, flags); + dest.writeInt(mRank); dest.writeParcelable(mExtras, flags); - dest.writeLong(mLastChangedTimestamp); - dest.writeInt(mFlags); - dest.writeInt(mIconResourceId); dest.writeString(mBitmapPath); + dest.writeString(mIconResName); + dest.writeString(mTitleResName); + dest.writeString(mTextResName); + dest.writeString(mDisabledMessageResName); + if (mCategories != null) { final int N = mCategories.size(); dest.writeInt(N); @@ -823,24 +1719,67 @@ public final class ShortcutInfo implements Parcelable { sb.append("id="); sb.append(secure ? "***" : mId); - sb.append(", packageName="); - sb.append(mPackageName); - + sb.append(", flags=0x"); + sb.append(Integer.toHexString(mFlags)); + sb.append(" ["); + if (!isEnabled()) { + sb.append("X"); + } + if (isImmutable()) { + sb.append("Im"); + } + if (isManifestShortcut()) { + sb.append("M"); + } if (isDynamic()) { - sb.append(", dynamic"); + sb.append("D"); } if (isPinned()) { - sb.append(", pinned"); + sb.append("P"); + } + if (hasIconFile()) { + sb.append("If"); + } + if (hasIconResource()) { + sb.append("Ir"); + } + if (hasKeyFieldsOnly()) { + sb.append("K"); } + if (hasStringResourcesResolved()) { + sb.append("Sr"); + } + sb.append("]"); + + sb.append(", packageName="); + sb.append(mPackageName); sb.append(", activity="); - sb.append(mActivityComponent); + sb.append(mActivity); - sb.append(", title="); + sb.append(", shortLabel="); sb.append(secure ? "***" : mTitle); + sb.append(", resId="); + sb.append(mTitleResId); + sb.append("["); + sb.append(mTitleResName); + sb.append("]"); - sb.append(", text="); + sb.append(", longLabel="); sb.append(secure ? "***" : mText); + sb.append(", resId="); + sb.append(mTextResId); + sb.append("["); + sb.append(mTextResName); + sb.append("]"); + + sb.append(", disabledMessage="); + sb.append(secure ? "***" : mDisabledMessage); + sb.append(", resId="); + sb.append(mDisabledMessageResId); + sb.append("["); + sb.append(mDisabledMessageResName); + sb.append("]"); sb.append(", categories="); sb.append(mCategories); @@ -848,28 +1787,44 @@ public final class ShortcutInfo implements Parcelable { sb.append(", icon="); sb.append(mIcon); - sb.append(", weight="); - sb.append(mWeight); + sb.append(", rank="); + sb.append(mRank); sb.append(", timestamp="); sb.append(mLastChangedTimestamp); - sb.append(", intent="); - sb.append(mIntent); - - sb.append(", intentExtras="); - sb.append(secure ? "***" : mIntentPersistableExtras); + sb.append(", intents="); + if (mIntents == null) { + sb.append("null"); + } else { + if (secure) { + sb.append("size:"); + sb.append(mIntents.length); + } else { + final int size = mIntents.length; + sb.append("["); + String sep = ""; + for (int i = 0; i < size; i++) { + sb.append(sep); + sep = ", "; + sb.append(mIntents[i]); + sb.append("/"); + sb.append(mIntentPersistableExtrases[i]); + } + sb.append("]"); + } + } sb.append(", extras="); sb.append(mExtras); - sb.append(", flags="); - sb.append(mFlags); - if (includeInternalData) { sb.append(", iconRes="); - sb.append(mIconResourceId); + sb.append(mIconResId); + sb.append("["); + sb.append(mIconResName); + sb.append("]"); sb.append(", bitmapPath="); sb.append(mBitmapPath); @@ -881,26 +1836,36 @@ public final class ShortcutInfo implements Parcelable { /** @hide */ public ShortcutInfo( - @UserIdInt int userId, String id, String packageName, ComponentName activityComponent, - Icon icon, String title, String text, Set categories, Intent intent, - PersistableBundle intentPersistableExtras, - int weight, PersistableBundle extras, long lastChangedTimestamp, - int flags, int iconResId, String bitmapPath) { + @UserIdInt int userId, String id, String packageName, ComponentName activity, + Icon icon, CharSequence title, int titleResId, String titleResName, + CharSequence text, int textResId, String textResName, + CharSequence disabledMessage, int disabledMessageResId, String disabledMessageResName, + Set categories, Intent[] intentsWithExtras, int rank, PersistableBundle extras, + long lastChangedTimestamp, + int flags, int iconResId, String iconResName, String bitmapPath) { mUserId = userId; mId = id; mPackageName = packageName; - mActivityComponent = activityComponent; + mActivity = activity; mIcon = icon; mTitle = title; + mTitleResId = titleResId; + mTitleResName = titleResName; mText = text; - mCategories = clone(categories); - mIntent = intent; - mIntentPersistableExtras = intentPersistableExtras; - mWeight = weight; + mTextResId = textResId; + mTextResName = textResName; + mDisabledMessage = disabledMessage; + mDisabledMessageResId = disabledMessageResId; + mDisabledMessageResName = disabledMessageResName; + mCategories = cloneCategories(categories); + mIntents = cloneIntents(intentsWithExtras); + fixUpIntentExtras(); + mRank = rank; mExtras = extras; mLastChangedTimestamp = lastChangedTimestamp; mFlags = flags; - mIconResourceId = iconResId; + mIconResId = iconResId; + mIconResName = iconResName; mBitmapPath = bitmapPath; } } diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index 16486e13e5279450819f8f9c02744fecaa80b1cc..96ad67c6f3abae859d26ee549307474fb87edacb 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -17,8 +17,11 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.TestApi; +import android.annotation.UserIdInt; +import android.app.Activity; +import android.app.usage.UsageStatsManager; import android.content.Context; -import android.os.IBinder; +import android.content.Intent; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -27,69 +30,416 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.List; -// TODO Enhance javadoc /** - * {@link ShortcutManager} manages shortcuts created by applications. + * The ShortcutManager manages "launcher shortcuts" (or simply "shortcuts"). Shortcuts provide + * users + * with quick access to activities other than an application's main activity in the currently-active + * launcher. For example, + * an email application may publish the "compose new email" action, which will directly open the + * compose activity. The {@link ShortcutInfo} class contains information about each of the + * shortcuts themselves. * - *

Dynamic shortcuts and pinned shortcuts

+ *

Dynamic Shortcuts and Manifest Shortcuts

* - * An application can publish shortcuts with {@link #setDynamicShortcuts(List)} and - * {@link #addDynamicShortcuts(List)}. There can be at most - * {@link #getMaxDynamicShortcutCount()} number of dynamic shortcuts at a time from the same + * There are two ways to publish shortcuts: manifest shortcuts and dynamic shortcuts. + * + *
    + *
  • Manifest shortcuts are declared in a resource + * XML, which is referenced in the publisher application's AndroidManifest.xml file. + * Manifest shortcuts are published when an application is installed, + * and the details of these shortcuts change when an application is upgraded with an updated XML + * file. + * Manifest shortcuts are immutable, and their + * definitions, such as icons and labels, cannot be changed dynamically without upgrading the + * publisher application. + * + *
  • Dynamic shortcuts are published at runtime using the {@link ShortcutManager} APIs. + * Applications can publish, update, and remove dynamic shortcuts at runtime. + *
+ * + *

Only "main" activities—activities that handle the {@code MAIN} action and the + * {@code LAUNCHER} category—can have shortcuts. + * If an application has multiple main activities, these activities will have different sets + * of shortcuts. + * + *

Dynamic shortcuts and manifest shortcuts are shown in the currently active launcher when + * the user long-presses on an application launcher icon. The actual gesture may be different + * depending on the launcher application. + * + *

Each launcher icon can have at most {@link #getMaxShortcutCountPerActivity()} number of + * dynamic and manifest shortcuts combined. + * + * + *

Pinning Shortcuts

+ * + * Launcher applications allow users to "pin" shortcuts so they're easier to access. Both manifest + * and dynamic shortcuts can be pinned. + * Pinned shortcuts cannot be removed by publisher + * applications; they're removed only when the user removes them, + * when the publisher application is uninstalled, or when the + * user performs the "clear data" action on the publisher application from the device's Settings * application. - * A dynamic shortcut can be deleted with {@link #removeDynamicShortcuts(List)}, and apps - * can also use {@link #removeAllDynamicShortcuts()} to delete all dynamic shortcuts. * - *

The shortcuts that are currently published by the above APIs are called "dynamic", because - * they can be removed by the creator application at any time. The user may "pin" dynamic shortcuts - * on Launcher to make "pinned" shortcuts. Pinned shortcuts cannot be removed by the creator - * app. An application can obtain all pinned shortcuts from itself with - * {@link #getPinnedShortcuts()}. Applications should keep the pinned shortcut information - * up-to-date using {@link #updateShortcuts(List)}. + *

However, the publisher application can disable pinned shortcuts so they cannot be + * started. See the following sections for details. + * + * + *

Updating and Disabling Shortcuts

+ * + *

When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut, + * the pinned shortcut will still be visible and launchable. This allows an application to have + * more than {@link #getMaxShortcutCountPerActivity()} number of shortcuts. + * + *

For example, suppose {@link #getMaxShortcutCountPerActivity()} is 5: + *

    + *
  • A chat application publishes 5 dynamic shortcuts for the 5 most recent + * conversations, "c1" - "c5". + * + *
  • The user pins all 5 of the shortcuts. + * + *
  • Later, the user has started 3 additional conversations ("c6", "c7", and "c8"), + * so the publisher application + * re-publishes its dynamic shortcuts. The new dynamic shortcut list is: + * "c4", "c5", "c6", "c7", and "c8". + * The publisher application has to remove "c1", "c2", and "c3" because it can't have more than + * 5 dynamic shortcuts. + * + *
  • However, even though "c1", "c2" and "c3" are no longer dynamic shortcuts, the pinned + * shortcuts for these conversations are still available and launchable. + * + *
  • At this point, the user can access a total of 8 shortcuts that link to activities in + * the publisher application, including the 3 pinned + * shortcuts, even though it's allowed to have at most 5 dynamic shortcuts. + * + *
  • The application can use {@link #updateShortcuts(List)} to update any of the existing + * 8 shortcuts, when, for example, the chat peers' icons have changed. + *
+ * The {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} methods + * can also be used + * to update existing shortcuts with the same IDs, but they cannot be used + * for updating non-dynamic, pinned shortcuts because these two methods try to convert the given + * lists of shortcuts to dynamic shortcuts. + * + * + *

Disabling Manifest Shortcuts

+ * When an application is upgraded and the new version + * no longer uses a manifest shortcut that appeared in the previous version, this deprecated + * shortcut will no longer be published as a manifest shortcut. + * + *

If the deprecated shortcut is pinned, then the pinned shortcut will remain on the launcher, + * but it will be disabled automatically. + * Note that, in this case, the pinned shortcut is no longer a manifest shortcut, but it's + * still immutable and cannot be updated using the {@link ShortcutManager} APIs. + * + * + *

Disabling Dynamic Shortcuts

+ * Sometimes pinned shortcuts become obsolete and may not be usable. For example, a pinned shortcut + * to a group chat will be unusable when the associated group chat is deleted. In cases like this, + * applications should use {@link #disableShortcuts(List)}, which will remove the specified dynamic + * shortcuts and also make any specified pinned shortcuts un-launchable. + * The {@link #disableShortcuts(List, CharSequence)} method can also be used to disabled shortcuts + * and show users a custom error message when they attempt to launch the disabled shortcuts. + * + * + *

Publishing Manifest Shortcuts

+ * + * In order to add manifest shortcuts to your application, first add + * {@code } to your main activity in + * AndroidManifest.xml: + *
+ * <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ *   package="com.example.myapplication">
+ *   <application . . .>
+ *     <activity android:name="Main">
+ *       <intent-filter>
+ *         <action android:name="android.intent.action.MAIN" />
+ *         <category android:name="android.intent.category.LAUNCHER" />
+ *       </intent-filter>
+ *       <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts"/>
+ *     </activity>
+ *   </application>
+ * </manifest>
+ * 
+ * + * Then, define your application's manifest shortcuts in the res/xml/shortcuts.xml + * file: + *
+ * <shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ *   <shortcut
+ *     android:shortcutId="compose"
+ *     android:enabled="true"
+ *     android:icon="@drawable/compose_icon"
+ *     android:shortcutShortLabel="@string/compose_shortcut_short_label1"
+ *     android:shortcutLongLabel="@string/compose_shortcut_long_label1"
+ *     android:shortcutDisabledMessage="@string/compose_disabled_message1"
+ *     >
+ *     <intent
+ *       android:action="android.intent.action.VIEW"
+ *       android:targetPackage="com.example.myapplication"
+ *       android:targetClass="com.example.myapplication.ComposeActivity" />
+ *     <!-- more intents can go here; see below -->
+ *     <categories android:name="android.shortcut.conversation" />
+ *   </shortcut>
+ *   <!-- more shortcuts can go here -->
+ * </shortcuts>
+ * 
+ * + * The following list includes descriptions for the different attributes within a manifest shortcut: + *
+ *
android:shortcutId
+ *
Mandatory shortcut ID
+ * + *
android:enabled
+ *
Default is {@code true}. Can be set to {@code false} in order + * to disable a manifest shortcut that was published in a previous version and and set a custom + * disabled message. If a custom disabled message is not needed, then a manifest shortcut can + * be simply removed from the XML file rather than keeping it with {@code enabled="false"}.
+ * + *
android:icon
+ *
Shortcut icon.
+ * + *
android:shortcutShortLabel
+ *
Mandatory shortcut short label. + * See {@link ShortcutInfo.Builder#setShortLabel(CharSequence)}.
+ * + *
android:shortcutLongLabel
+ *
Shortcut long label. + * See {@link ShortcutInfo.Builder#setLongLabel(CharSequence)}.
+ * + *
android:shortcutDisabledMessage
+ *
When {@code android:enabled} is set to + * {@code false}, this attribute is used to display a custom disabled message.
+ * + *
intent
+ *
Intent to launch when the user selects the shortcut. + * {@code android:action} is mandatory. + * See Using intents for the + * other supported tags. + * You can provide multiple intents for a single shortcut so that an activity is launched + * with other activities in the back stack. See {@link android.app.TaskStackBuilder} for details. + *
+ *
categories
+ *
Specify shortcut categories. Currently only + * {@link ShortcutInfo#SHORTCUT_CATEGORY_CONVERSATION} is defined in the framework. + *
+ *
+ * + *

Publishing Dynamic Shortcuts

+ * + * Applications can publish dynamic shortcuts with {@link #setDynamicShortcuts(List)} + * or {@link #addDynamicShortcuts(List)}. The {@link #updateShortcuts(List)} method can also be + * used to update existing, mutable shortcuts. + * Use {@link #removeDynamicShortcuts(List)} or {@link #removeAllDynamicShortcuts()} to remove + * dynamic shortcuts. + * + *

Example: + *

+ * ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
+ *
+ * ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1")
+ *     .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.mysite.com/")))
+ *     .setShortLabel("Web site")
+ *     .setLongLabel("Open the web site")
+ *     .setIcon(Icon.createWithResource(context, R.drawable.icon_website))
+ *     .build();
+ *
+ * shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut));
+ * 
+ * + * + *

Shortcut Intents

+ * Dynamic shortcuts can be published with any set of {@link Intent#addFlags Intent} flags. + * Typically, {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} is specified, possibly along with other + * flags; otherwise, if the application is already running, the application is simply brought to + * the foreground, and the target activity may not appear. + * + *

The {@link ShortcutInfo.Builder#setIntents(Intent[])} method can be used instead of + * {@link ShortcutInfo.Builder#setIntent(Intent)} with {@link android.app.TaskStackBuilder} + * in order to launch an activity with other activities in the back stack. + * When the user selects a shortcut to load an activity with a back stack, + * then presses the back key, a "parent" activity will be shown instead of the user being + * navigated back to the launcher. + * + *

Manifest shortcuts can also have multiple intents to achieve the same effect. + * In order to associate multiple {@link Intent} objects with a shortcut, simply list multiple + * <intent> elements within a single <shortcut> element. + * The last intent specifies what the user will see when they launch a shortcut. + * + *

Manifest shortcuts cannot have custom intent flags. + * The first intent of a manifest shortcut will always have {@link Intent#FLAG_ACTIVITY_NEW_TASK} + * and {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} set. + * This means, when the application is already running, all the existing activities will be + * destroyed when a manifest shortcut is launched. + * If this behavior is not desirable, you can use a trampoline activity, + * or an invisible activity that starts another activity in {@link Activity#onCreate}, + * then calls {@link Activity#finish()}. + * The first activity should include an attribute setting + * of {@code android:taskAffinity=""} in the application's AndroidManifest.xml + * file, and the intent within the manifest shortcut should point at this first activity. + * + * + *

Showing New Information in a Shortcut

+ * In order to avoid confusion, you should not use {@link #updateShortcuts(List)} to update + * a shortcut so that it contains conceptually different information. + * + *

For example, a phone application may publish the most frequently called contact as a dynamic + * shortcut. Over time, this contact may change; when it does, the application should + * represent the changed contact with a new shortcut that contains a different ID, using either + * {@link #setDynamicShortcuts(List)} or {@link #addDynamicShortcuts(List)}, rather than updating + * the existing shortcut with {@link #updateShortcuts(List)}. + * This is because when the shortcut is pinned, changing + * it to reference a different contact will likely confuse the user. + * + *

On the other hand, when the + * contact's information has changed, such as the name or picture, the application should + * use {@link #updateShortcuts(List)} so that the pinned shortcut is updated too. * - *

The number of pinned shortcuts does not affect the number of dynamic shortcuts that can be - * published by an application at a time. - * No matter how many pinned shortcuts that Launcher has for an application, the - * application can still always publish {@link #getMaxDynamicShortcutCount()} number of dynamic - * shortcuts. * - *

Shortcut IDs

+ *

Shortcut Display Order

+ * When the launcher displays the shortcuts that are associated with a particular launcher icon, + * the shortcuts should appear in the following order: + *
    + *
  • First show manifest shortcuts + * (if {@link ShortcutInfo#isDeclaredInManifest()} is {@code true}), + * and then show dynamic shortcuts (if {@link ShortcutInfo#isDynamic()} is {@code true}). + *
  • Within each category of shortcuts (manifest and dynamic), sort the shortcuts in order + * of increasing rank according to {@link ShortcutInfo#getRank()}. + *
+ *

Shortcut ranks are non-negative sequential integers + * that determine the order in which shortcuts appear, assuming that the shortcuts are all in + * the same category. + * Ranks of existing shortcuts can be updated with + * {@link #updateShortcuts(List)}; you can use {@link #addDynamicShortcuts(List)} and + * {@link #setDynamicShortcuts(List)}, too. * - * Each shortcut must have an ID, which must be unique within each application. When a shortcut is - * published, existing shortcuts with the same ID will be updated. Note this may include a - * pinned shortcut. + *

Ranks are auto-adjusted so that they're unique for each target activity in each category + * (dynamic or manifest). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and 2, + * adding another dynamic shortcut with a rank of 1 represents a request to place this shortcut at + * the second position. + * In response, the third and fourth shortcuts move closer to the bottom of the shortcut list, + * with their ranks changing to 2 and 3, respectively. * - *

Rate limiting

+ *

Rate Limiting

* - * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcuts(List)}, - * and {@link #updateShortcuts(List)} from background applications will be - * rate-limited. An application can call these methods at most - * {@link #getRemainingCallCount()} times until the rate-limiting counter is reset, - * which happens at a certain time every day. + * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcuts(List)}, and + * {@link #updateShortcuts(List)} may be rate-limited when called by background applications, or + * applications with no foreground activity or service. When you attempt to call these methods + * from a background application after exceeding the rate limit, these APIs return {@code false}. * - *

An application can use {@link #getRateLimitResetTime()} to get the next reset time. + *

Applications with a foreground activity or service are not rate-limited. * - *

Foreground applications (i.e. ones with a foreground activity or a foreground services) - * will not be throttled. Also, when an application comes to foreground, - * {@link #getRemainingCallCount()} will be reset to the initial value. + *

Rate-limiting will be reset upon certain events, so that even background applications + * can call these APIs again until the rate limit is reached again. + * These events include the following: + *

    + *
  • When an application comes to the foreground. + *
  • When the system locale changes. + *
  • When the user performs an "inline reply" action on a notification. + *
+ * + *

When rate-limiting is active, {@link #isRateLimitingActive()} returns {@code true}. + * + *

Resetting rate-limiting for testing

+ * + * If your application is rate-limited during development or testing, you can use the + * "Reset ShortcutManager rate-limiting" development option or the following adb command to reset + * it: + *
+ * adb shell cmd shortcut reset-throttling [ --user USER-ID ]
+ * 
+ * + *

Handling System Locale Changes

+ * + * Applications should update dynamic and pinned shortcuts when the system locale changes + * using the {@link Intent#ACTION_LOCALE_CHANGED} broadcast. + * + *

When the system locale changes, rate-limiting is reset, so even background applications + * can set dynamic shortcuts, add dynamic shortcuts, and update shortcuts until the rate limit + * is reached again. * - *

For testing purposes, use "Developer Options" (found in the Settings menu) to reset the - * internal rate-limiting counter. Automated tests can use the following ADB shell command to - * achieve the same effect:

- *
adb shell cmd shortcut reset-throttling
* *

Backup and Restore

* - * Shortcuts will be backed up and restored across devices. This means all information, including - * IDs, must be meaningful on a different device. + * When an application has the {@code android:allowBackup="true"} attribute assignment included + * in its AndroidManifest.xml file, pinned shortcuts are + * backed up automatically and are restored when the user sets up a new device. + * + *

Categories of Shortcuts that are Backed Up

+ * + *
    + *
  • Pinned shortcuts are backed up. Bitmap icons are not backed up by the system, + * but launcher applications should back them up and restore them so that the user still sees icons + * for pinned shortcuts on the launcher. Applications can always use + * {@link #updateShortcuts(List)} to re-publish icons. + * + *
  • Manifest shortcuts are not backed up, but when an application is re-installed on a new + * device, they are re-published from the AndroidManifest.xml file, anyway. + * + *
  • Dynamic shortcuts are not backed up. + *
+ * + *

Because dynamic shortcuts are not restored, it is recommended that applications check + * currently-published dynamic shortcuts using {@link #getDynamicShortcuts()} + * each time they are launched, and they should re-publish + * dynamic shortcuts when necessary. + * + *

+ * public class MainActivity extends Activity {
+ *     public void onCreate(Bundle savedInstanceState) {
+ *         super.onCreate(savedInstanceState);
+ *
+ *         ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
+ *
+ *         if (shortcutManager.getDynamicShortcuts().size() == 0) {
+ *             // Application restored; re-publish dynamic shortcuts.
+ *
+ *             if (shortcutManager.getPinnedShortcuts().size() > 0) {
+ *                 // Pinned shortcuts have been restored.  Use updateShortcuts() to make sure
+ *                 // they have up-to-date information.
+ *             }
+ *         }
+ *     }
+ *     :
+ *
+ * }
+ * 
+ * + * + *

Backup/restore and shortcut IDs

+ * + * Because pinned shortcuts are backed up and restored on new devices, shortcut IDs should be + * meaningful across devices; that is, IDs should contain either stable, constant strings + * or server-side identifiers, + * rather than identifiers generated locally that might not make sense on other devices. + * + * + *

Report Shortcut Usage and Prediction

+ * + * Launcher applications may be capable of predicting which shortcuts will most likely be + * used at a given time by examining the shortcut usage history data. + * + *

In order to provide launchers with such data, publisher applications should + * report the shortcuts that are used with {@link #reportShortcutUsed(String)} + * when a shortcut is selected, + * or when an action equivalent to a shortcut is taken by the user even if it wasn't started + * with the shortcut. * - *

APIs for launcher

+ *

For example, suppose a GPS navigation application supports "navigate to work" as a shortcut. + * It should then report when the user selects this shortcut and when the user chooses + * to navigate to work within the application itself. + * This helps the launcher application + * learn that the user wants to navigate to work at a certain time every + * weekday, and it can then show this shortcut in a suggestion list at the right time. * - * Launcher applications should use {@link LauncherApps} to get shortcuts that are published from - * applications. Launcher applications can also pin shortcuts with - * {@link LauncherApps#pinShortcuts(String, List, UserHandle)}. + *

Launcher API

* - * @hide + * The {@link LauncherApps} class provides APIs for launcher applications to access shortcuts. + * + * + *

Direct Boot and Shortcuts

+ * + * All shortcut information is stored in credential encrypted storage, so no shortcuts can be + * accessed when the user is locked. */ public class ShortcutManager { private static final String TAG = "ShortcutManager"; @@ -115,15 +465,18 @@ public class ShortcutManager { } /** - * Publish a list of shortcuts. All existing dynamic shortcuts from the caller application - * will be replaced. + * Publish the list of shortcuts. All existing dynamic shortcuts from the caller application + * will be replaced. If there are already pinned shortcuts with the same IDs, + * the mutable pinned shortcuts are updated. * *

This API will be rate-limited. * * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. * - * @throws IllegalArgumentException if {@code shortcutInfoList} contains more than - * {@link #getMaxDynamicShortcutCount()} shortcuts. + * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded, + * or when trying to update immutable shortcuts. + * + * @throws IllegalStateException when the user is locked. */ public boolean setDynamicShortcuts(@NonNull List shortcutInfoList) { try { @@ -135,8 +488,9 @@ public class ShortcutManager { } /** - * Return all dynamic shortcuts from the caller application. The number of result items - * will not exceed the value returned by {@link #getMaxDynamicShortcutCount()}. + * Return all dynamic shortcuts from the caller application. + * + * @throws IllegalStateException when the user is locked. */ @NonNull public List getDynamicShortcuts() { @@ -149,15 +503,32 @@ public class ShortcutManager { } /** - * Publish a single dynamic shortcut. If there's already dynamic or pinned shortcuts with - * the same ID, they will all be updated. + * Return all manifest shortcuts from the caller application. + * + * @throws IllegalStateException when the user is locked. + */ + @NonNull + public List getManifestShortcuts() { + try { + return mService.getManifestShortcuts(mContext.getPackageName(), injectMyUserId()) + .getList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with + * the same IDs, each mutable shortcut is updated. * *

This API will be rate-limited. * * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. * - * @throws IllegalArgumentException if the caller application has already published the - * max number of dynamic shortcuts. + * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded, + * or when trying to update immutable shortcuts. + * + * @throws IllegalStateException when the user is locked. */ public boolean addDynamicShortcuts(@NonNull List shortcutInfoList) { try { @@ -169,7 +540,9 @@ public class ShortcutManager { } /** - * Delete a single dynamic shortcut by ID. + * Delete dynamic shortcuts by ID. + * + * @throws IllegalStateException when the user is locked. */ public void removeDynamicShortcuts(@NonNull List shortcutIds) { try { @@ -182,6 +555,8 @@ public class ShortcutManager { /** * Delete all dynamic shortcuts from the caller application. + * + * @throws IllegalStateException when the user is locked. */ public void removeAllDynamicShortcuts() { try { @@ -193,6 +568,8 @@ public class ShortcutManager { /** * Return all pinned shortcuts from the caller application. + * + * @throws IllegalStateException when the user is locked. */ @NonNull public List getPinnedShortcuts() { @@ -205,11 +582,16 @@ public class ShortcutManager { } /** - * Update all existing shortcuts with the same IDs. Shortcuts may be pinned and/or dynamic. + * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or + * dynamic, but they must not be immutable. * *

This API will be rate-limited. * * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited. + * + * @throws IllegalArgumentException If trying to update immutable shortcuts. + * + * @throws IllegalStateException when the user is locked. */ public boolean updateShortcuts(List shortcutInfoList) { try { @@ -221,11 +603,94 @@ public class ShortcutManager { } /** - * Return the max number of dynamic shortcuts that each application can have at a time. + * Disable pinned shortcuts. For more details, see the Javadoc for the {@link ShortcutManager} + * class. + * + * @throws IllegalArgumentException If trying to disable immutable shortcuts. + * + * @throws IllegalStateException when the user is locked. + */ + public void disableShortcuts(@NonNull List shortcutIds) { + try { + mService.disableShortcuts(mContext.getPackageName(), shortcutIds, + /* disabledMessage =*/ null, /* disabledMessageResId =*/ 0, + injectMyUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @hide old signature, kept for unit testing. */ - public int getMaxDynamicShortcutCount() { + public void disableShortcuts(@NonNull List shortcutIds, int disabledMessageResId) { try { - return mService.getMaxDynamicShortcutCount(mContext.getPackageName(), injectMyUserId()); + mService.disableShortcuts(mContext.getPackageName(), shortcutIds, + /* disabledMessage =*/ null, disabledMessageResId, + injectMyUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @hide old signature, kept for unit testing. + */ + public void disableShortcuts(@NonNull List shortcutIds, String disabledMessage) { + disableShortcuts(shortcutIds, (CharSequence) disabledMessage); + } + + /** + * Disable pinned shortcuts, showing the user a custom error message when they try to select + * the disabled shortcuts. + * For more details, see the Javadoc for the {@link ShortcutManager} class. + * + * @throws IllegalArgumentException If trying to disable immutable shortcuts. + * + * @throws IllegalStateException when the user is locked. + */ + public void disableShortcuts(@NonNull List shortcutIds, CharSequence disabledMessage) { + try { + mService.disableShortcuts(mContext.getPackageName(), shortcutIds, + disabledMessage, /* disabledMessageResId =*/ 0, + injectMyUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Re-enable pinned shortcuts that were previously disabled. If the target shortcuts + * already enabled, this method does nothing. + * + * @throws IllegalArgumentException If trying to enable immutable shortcuts. + * + * @throws IllegalStateException when the user is locked. + */ + public void enableShortcuts(@NonNull List shortcutIds) { + try { + mService.enableShortcuts(mContext.getPackageName(), shortcutIds, injectMyUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + + /** + * @hide old signature, kept for unit testing. + */ + public int getMaxShortcutCountForActivity() { + return getMaxShortcutCountPerActivity(); + } + + /** + * Return the maximum number of dynamic and manifest shortcuts that each launcher icon + * can have at a time. + */ + public int getMaxShortcutCountPerActivity() { + try { + return mService.getMaxShortcutCountPerActivity( + mContext.getPackageName(), injectMyUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -236,6 +701,8 @@ public class ShortcutManager { * before the rate limit counter is reset. * * @see #getRateLimitResetTime() + * + * @hide */ public int getRemainingCallCount() { try { @@ -250,6 +717,8 @@ public class ShortcutManager { * * @see #getRemainingCallCount() * @see System#currentTimeMillis() + * + * @hide */ public long getRateLimitResetTime() { try { @@ -260,16 +729,82 @@ public class ShortcutManager { } /** - * Return the max width and height for icons, in pixels. + * Return {@code true} when rate-limiting is active for the caller application. + * + *

See the class level javadoc for details. + * + * @throws IllegalStateException when the user is locked. + */ + public boolean isRateLimitingActive() { + try { + return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId()) + == 0; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Return the max width for icons, in pixels. + */ + public int getIconMaxWidth() { + try { + // TODO Implement it properly using xdpi. + return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Return the max height for icons, in pixels. */ - public int getIconMaxDimensions() { + public int getIconMaxHeight() { try { + // TODO Implement it properly using ydpi. return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } + /** + * Applications that publish shortcuts should call this method + * whenever the user selects the shortcut containing the given ID or when the user completes + * an action in the application that is equivalent to selecting the shortcut. + * For more details, see the Javadoc for the {@link ShortcutManager} class + * + *

The information is accessible via {@link UsageStatsManager#queryEvents} + * Typically, launcher applications use this information to build a prediction model + * so that they can promote the shortcuts that are likely to be used at the moment. + * + * @throws IllegalStateException when the user is locked. + */ + public void reportShortcutUsed(String shortcutId) { + try { + mService.reportShortcutUsed(mContext.getPackageName(), shortcutId, + injectMyUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Called internally when an application is considered to have come to foreground + * even when technically it's not. This method resets the throttling for this package. + * For example, when the user sends an "inline reply" on an notification, the system UI will + * call it. + * + * @hide + */ + public void onApplicationActive(@NonNull String packageName, @UserIdInt int userId) { + try { + mService.onApplicationActive(packageName, userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide injection point */ @VisibleForTesting protected int injectMyUserId() { diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java index 3f8bad15035bfe08834c675f18a2ee704db96d23..af5610570f70ed260bfed84e4a7f35f73cdf55ee 100644 --- a/core/java/android/content/pm/ShortcutServiceInternal.java +++ b/core/java/android/content/pm/ShortcutServiceInternal.java @@ -53,7 +53,8 @@ public abstract class ShortcutServiceInternal { @NonNull String callingPackage, @NonNull String packageName, @NonNull List shortcutIds, int userId); - public abstract Intent createShortcutIntent(int launcherUserId, @NonNull String callingPackage, + public abstract Intent[] createShortcutIntents( + int launcherUserId, @NonNull String callingPackage, @NonNull String packageName, @NonNull String shortcutId, int userId); public abstract void addListener(@NonNull ShortcutChangeListener listener); @@ -67,10 +68,4 @@ public abstract class ShortcutServiceInternal { public abstract boolean hasShortcutHostPermission(int launcherUserId, @NonNull String callingPackage); - - /** - * Called by AM when the system locale changes *within the AM lock*. ABSOLUTELY do not take - * any locks in this method. - */ - public abstract void onSystemLocaleChangedNoLock(); } diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index dd3a36c7996c5e08670b452e1c743e158ca58025..6cd84033da8c137955e138e3c8b323ce3d24882f 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -28,8 +28,8 @@ import android.os.UserManager; */ public class UserInfo implements Parcelable { - /** 8 bits for user type */ - public static final int FLAG_MASK_USER_TYPE = 0x000000FF; + /** 16 bits for user type */ + public static final int FLAG_MASK_USER_TYPE = 0x0000FFFF; /** * *************************** NOTE *************************** @@ -87,6 +87,11 @@ public class UserInfo implements Parcelable { */ public static final int FLAG_EPHEMERAL = 0x00000100; + /** + * User is for demo purposes only and can be removed at any time. + */ + public static final int FLAG_DEMO = 0x00000200; + public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL; public int id; @@ -153,6 +158,10 @@ public class UserInfo implements Parcelable { return (flags & FLAG_INITIALIZED) == FLAG_INITIALIZED; } + public boolean isDemo() { + return (flags & FLAG_DEMO) == FLAG_DEMO; + } + /** * Returns true if the user is a split system user. *

If {@link UserManager#isSplitSystemUser split system user mode} is not enabled, diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 6f43d99ecb9583e4f1f192624d44d27ef3b027ad..b2d518c56ca0a4fc68746673f82effd305666d79 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -1543,27 +1543,41 @@ public final class Configuration implements Parcelable, Comparable= fullLen) { return attrs; @@ -66,7 +70,7 @@ public class TypedArray { private final Resources mResources; private final DisplayMetrics mMetrics; - private final AssetManager mAssets; + private AssetManager mAssets; private boolean mRecycled; @@ -1086,6 +1090,7 @@ public class TypedArray { // These may have been set by the client. mXml = null; mTheme = null; + mAssets = null; mResources.mTypedArrayPool.release(this); } diff --git a/core/java/android/database/CursorJoiner.java b/core/java/android/database/CursorJoiner.java index e3c298893e806975fb253b90946515e0cf737cc5..a95263b67b433dde64d9eca98c4d09ec83c7b8ad 100644 --- a/core/java/android/database/CursorJoiner.java +++ b/core/java/android/database/CursorJoiner.java @@ -27,7 +27,7 @@ import java.util.Iterator; * *

  * CursorJoiner joiner = new CursorJoiner(cursorA, keyColumnsofA, cursorB, keyColumnsofB);
- * for (CursorJointer.Result joinerResult : joiner) {
+ * for (CursorJoiner.Result joinerResult : joiner) {
  *     switch (joinerResult) {
  *         case LEFT:
  *             // handle case where a row in cursorA is unique
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0f64b921a07993779b6e278938204e56d51218eb..8e178320d66d5126f4a6f60126be417aeb6675d0 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1371,6 +1371,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
 
     /**
      * Convenience method for replacing a row in the database.
+     * Inserts a new row if a row does not already exist.
      *
      * @param table the table in which to replace the row
      * @param nullColumnHack optional; may be null.
@@ -1381,7 +1382,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
      *            provides the name of nullable column name to explicitly insert a NULL into
      *            in the case where your initialValues is empty.
      * @param initialValues this map contains the initial column values for
-     *   the row.
+     *   the row. The keys should be the column names and the values the column values.
      * @return the row ID of the newly inserted row, or -1 if an error occurred
      */
     public long replace(String table, String nullColumnHack, ContentValues initialValues) {
@@ -1396,6 +1397,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
 
     /**
      * Convenience method for replacing a row in the database.
+     * Inserts a new row if a row does not already exist.
      *
      * @param table the table in which to replace the row
      * @param nullColumnHack optional; may be null.
@@ -1406,7 +1408,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
      *            provides the name of nullable column name to explicitly insert a NULL into
      *            in the case where your initialValues is empty.
      * @param initialValues this map contains the initial column values for
-     *   the row. The key
+     *   the row. The keys should be the column names and the values the column values.
      * @throws SQLException
      * @return the row ID of the newly inserted row, or -1 if an error occurred
      */
@@ -1740,7 +1742,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
      * Returns true if the new version code is greater than the current database version.
      *
      * @param newVersion The new version code.
-     * @return True if the new version code is greater than the current database version. 
+     * @return True if the new version code is greater than the current database version.
      */
     public boolean needUpgrade(int newVersion) {
         return newVersion > getVersion();
diff --git a/core/java/android/database/sqlite/package.html b/core/java/android/database/sqlite/package.html
index ceed171ce48c269f5bcf9fd284be0a2e49df4461..864a9bb32702ea2e438f05d3727fa53bcffc49ac 100644
--- a/core/java/android/database/sqlite/package.html
+++ b/core/java/android/database/sqlite/package.html
@@ -6,15 +6,44 @@ classes that an application would use to manage its own private database.
 Applications use these classes to manage private databases. If creating a
 content provider, you will probably have to use these classes to create and
 manage your own database to store content. See Content Providers to learn
-the conventions for implementing a content provider. See the
-NotePadProvider class in the NotePad sample application in the SDK for an
-example of a content provider. Android ships with SQLite version 3.4.0
-

If you are working with data sent to you by a provider, you will not use -these SQLite classes, but instead use the generic {@link android.database} -classes. -

Android ships with the sqlite3 database tool in the tools/ -folder. You can use this tool to browse or run SQL commands on the device. Run by -typing sqlite3 in a shell window. +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers +to learn the conventions for implementing a content provider. If you are working +with data sent to you by a provider, you do not use these SQLite classes, but +instead use the generic {@link android.database} classes. + +

The Android SDK and Android emulators both include the +sqlite3 command-line +database tool. On your development machine, run the tool from the +platform-tools/ folder of your SDK. On the emulator, run the tool +with adb shell, for example, adb -e shell sqlite3. + +

The version of SQLite depends on the version of Android. See the following table: + + + + + + + + +
Android APISQLite Version
API 243.9
API 213.8
API 113.7
API 83.6
API 33.5
API 13.4
+ +

Some device manufacturers include different versions of SQLite on their devices. + There are two ways to programmatically determine the version number. + +

    +
  • If available, use the sqlite3 tool, for example: + adb -e shell sqlite3 --version.
  • +
  • Create and query an in-memory database as shown in the following code sample: +
    +    String query = "select sqlite_version() AS sqlite_version";
    +    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(":memory:", null);
    +    Cursor cursor = db.rawQuery(query, null);
    +    String sqliteVersion = "";
    +    if (cursor.moveToNext()) {
    +        sqliteVersion = cursor.getString(0);
    +    }
    +
  • +
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index a20307a868c7fd52a46f1faacb02d054457bf2dd..04ee1e6d57d03a7cbb7a48fb80339e2f11c23b23 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -1356,20 +1356,35 @@ public abstract class SensorManager { /** * Computes the device's orientation based on the rotation matrix. *

- * When it returns, the array values is filled with the result: + * When it returns, the array values are as follows: *

    - *
  • values[0]: azimuth, rotation around the -Z axis, - * i.e. the opposite direction of Z axis.
  • - *
  • values[1]: pitch, rotation around the -X axis, - * i.e the opposite direction of X axis.
  • - *
  • values[2]: roll, rotation around the Y axis.
  • + *
  • values[0]: Azimuth, angle of rotation about the -z axis. + * This value represents the angle between the device's y + * axis and the magnetic north pole. When facing north, this + * angle is 0, when facing south, this angle is π. + * Likewise, when facing east, this angle is π/2, and + * when facing west, this angle is -π/2. The range of + * values is -π to π.
  • + *
  • values[1]: Pitch, angle of rotation about the x axis. + * This value represents the angle between a plane parallel + * to the device's screen and a plane parallel to the ground. + * Assuming that the bottom edge of the device faces the + * user and that the screen is face-up, tilting the top edge + * of the device toward the ground creates a positive pitch + * angle. The range of values is -π to π.
  • + *
  • values[2]: Roll, angle of rotation about the y axis. This + * value represents the angle between a plane perpendicular + * to the device's screen and a plane perpendicular to the + * ground. Assuming that the bottom edge of the device faces + * the user and that the screen is face-up, tilting the left + * edge of the device toward the ground creates a positive + * roll angle. The range of values is -π/2 to π/2.
  • *
*

- * Applying these three intrinsic rotations in azimuth, pitch and roll order transforms - * identity matrix to the rotation matrix given in input R. - * All three angles above are in radians and positive in the - * counter-clockwise direction. Range of output is: azimuth from -π to π, - * pitch from -π/2 to π/2 and roll from -π to π. + * Applying these three rotations in the azimuth, pitch, roll order + * transforms an identity matrix to the rotation matrix passed into this + * method. Also, note that all three orientation angles are expressed in + * radians. * * @param R * rotation matrix see {@link #getRotationMatrix}. diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index 38279a47f2a9b7040b702c38c5f74311be0e3c5c..4b211873598365768517aff397ac055a3130cf87 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -18,6 +18,7 @@ package android.hardware.camera2; import android.annotation.NonNull; import android.annotation.Nullable; +import android.hardware.camera2.params.OutputConfiguration; import android.os.Handler; import android.view.Surface; @@ -219,6 +220,53 @@ public abstract class CameraCaptureSession implements AutoCloseable { */ public abstract void tearDown(@NonNull Surface surface) throws CameraAccessException; + /** + *

+ * Finish the deferred output configurations where the output Surface was not configured before. + *

+ *

+ * For camera use cases where a preview and other output configurations need to be configured, + * it can take some time for the preview Surface to be ready (e.g., if the preview Surface is + * obtained from {@link android.view.SurfaceView}, the SurfaceView is ready after the UI layout + * is done, then it takes some time to get the preview Surface). + *

+ *

+ * To speed up camera startup time, the application can configure the + * {@link CameraCaptureSession} with the desired preview size, and defer the preview output + * configuration until the Surface is ready. After the {@link CameraCaptureSession} is created + * successfully with this deferred configuration and other normal configurations, the + * application can submit requests that don't include deferred output Surfaces. Once the + * deferred Surface is ready, the application can set the Surface to the same deferred output + * configuration with the {@link OutputConfiguration#setDeferredSurface} method, and then finish + * the deferred output configuration via this method, before it can submit requests with this + * output target. + *

+ *

+ * The output Surfaces included by this list of deferred {@link OutputConfiguration + * OutputConfigurations} can be used as {@link CaptureRequest} targets as soon as this call + * returns; + *

+ *

+ * This method is not supported by Legacy devices. + *

+ * + * @param deferredOutputConfigs a list of {@link OutputConfiguration OutputConfigurations} that + * have had {@link OutputConfiguration#setDeferredSurface setDeferredSurface} invoked + * with a valid output Surface. + * @throws CameraAccessException if the camera device is no longer connected or has encountered + * a fatal error. + * @throws IllegalStateException if this session is no longer active, either because the session + * was explicitly closed, a new session has been created or the camera device has + * been closed. Or if this output configuration was already finished with the + * included surface before. + * @throws IllegalArgumentException for invalid output configurations, including ones where the + * source of the Surface is no longer valid or the Surface is from a unsupported + * source. + * @hide + */ + public abstract void finishDeferredConfiguration( + List deferredOutputConfigs) throws CameraAccessException; + /** *

Submit a request for an image to be captured by the camera device.

* diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 3917bfa6beea58657b2faa204b01761970008900..145b1d076e80789309f8fbae58ee953518cad181 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -267,6 +267,10 @@ public final class CameraManager { * @param cameraId The unique identifier of the camera device to open * @param callback The callback for the camera. Must not be null. * @param handler The handler to invoke the callback on. Must not be null. + * @param uid The UID of the application actually opening the camera. + * Must be USE_CALLING_UID unless the caller is a service + * that is trusted to open the device on behalf of an + * application and to forward the real UID. * * @throws CameraAccessException if the camera is disabled by device policy, * too many camera devices are already open, or the cameraId does not match @@ -281,7 +285,7 @@ public final class CameraManager { * @see android.app.admin.DevicePolicyManager#setCameraDisabled */ private CameraDevice openCameraDeviceUserAsync(String cameraId, - CameraDevice.StateCallback callback, Handler handler) + CameraDevice.StateCallback callback, Handler handler, final int uid) throws CameraAccessException { CameraCharacteristics characteristics = getCameraCharacteristics(cameraId); CameraDevice device = null; @@ -317,7 +321,7 @@ public final class CameraManager { "Camera service is currently unavailable"); } cameraUser = cameraService.connectDevice(callbacks, id, - mContext.getOpPackageName(), USE_CALLING_UID); + mContext.getOpPackageName(), uid); } else { // Use legacy camera implementation for HAL1 devices Log.i(TAG, "Using legacy camera HAL."); @@ -434,6 +438,29 @@ public final class CameraManager { @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler) throws CameraAccessException { + openCameraForUid(cameraId, callback, handler, USE_CALLING_UID); + } + + /** + * Open a connection to a camera with the given ID, on behalf of another application + * specified by clientUid. + * + *

The behavior of this method matches that of {@link #openCamera}, except that it allows + * the caller to specify the UID to use for permission/etc verification. This can only be + * done by services trusted by the camera subsystem to act on behalf of applications and + * to forward the real UID.

+ * + * @param clientUid + * The UID of the application on whose behalf the camera is being opened. + * Must be USE_CALLING_UID unless the caller is a trusted service. + * + * @hide + */ + public void openCameraForUid(@NonNull String cameraId, + @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler, + int clientUid) + throws CameraAccessException { + if (cameraId == null) { throw new IllegalArgumentException("cameraId was null"); } else if (callback == null) { @@ -447,7 +474,7 @@ public final class CameraManager { } } - openCameraDeviceUserAsync(cameraId, callback, handler); + openCameraDeviceUserAsync(cameraId, callback, handler, clientUid); } /** diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java index 9478dc002d6c84f2e51bc387caa7a9d721c4936d..1a51acd6c5ecd9603fca75001d05046be6beca3b 100644 --- a/core/java/android/hardware/camera2/DngCreator.java +++ b/core/java/android/hardware/camera2/DngCreator.java @@ -27,6 +27,7 @@ import android.location.Location; import android.media.ExifInterface; import android.media.Image; import android.os.SystemClock; +import android.util.Log; import android.util.Size; import java.io.IOException; @@ -89,21 +90,43 @@ public final class DngCreator implements AutoCloseable { throw new IllegalArgumentException("Null argument to DngCreator constructor"); } - // Find current time + // Find current time in milliseconds since 1970 long currentTime = System.currentTimeMillis(); - - // Find boot time - long bootTimeMillis = currentTime - SystemClock.elapsedRealtime(); + // Assume that sensor timestamp has that timebase to start + long timeOffset = 0; + + int timestampSource = characteristics.get( + CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE); + + if (timestampSource == CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) { + // This means the same timebase as SystemClock.elapsedRealtime(), + // which is CLOCK_BOOTTIME + timeOffset = currentTime - SystemClock.elapsedRealtime(); + } else if (timestampSource == CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN) { + // This means the same timebase as System.currentTimeMillis(), + // which is CLOCK_MONOTONIC + timeOffset = currentTime - SystemClock.uptimeMillis(); + } else { + // Unexpected time source - treat as CLOCK_MONOTONIC + Log.w(TAG, "Sensor timestamp source is unexpected: " + timestampSource); + timeOffset = currentTime - SystemClock.uptimeMillis(); + } // Find capture time (nanos since boot) Long timestamp = metadata.get(CaptureResult.SENSOR_TIMESTAMP); long captureTime = currentTime; if (timestamp != null) { - captureTime = timestamp / 1000000 + bootTimeMillis; + captureTime = timestamp / 1000000 + timeOffset; } + // Create this fresh each time since the time zone may change while a long-running application + // is active. + final DateFormat dateTimeStampFormat = + new SimpleDateFormat(TIFF_DATETIME_FORMAT); + dateTimeStampFormat.setTimeZone(TimeZone.getDefault()); + // Format for metadata - String formattedCaptureTime = sDateTimeStampFormat.format(captureTime); + String formattedCaptureTime = dateTimeStampFormat.format(captureTime); nativeInit(characteristics.getNativeCopy(), metadata.getNativeCopy(), formattedCaptureTime); @@ -450,13 +473,10 @@ public final class DngCreator implements AutoCloseable { private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd"; private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd HH:mm:ss"; private static final DateFormat sExifGPSDateStamp = new SimpleDateFormat(GPS_DATE_FORMAT_STR); - private static final DateFormat sDateTimeStampFormat = - new SimpleDateFormat(TIFF_DATETIME_FORMAT); private final Calendar mGPSTimeStampCalendar = Calendar .getInstance(TimeZone.getTimeZone("UTC")); static { - sDateTimeStampFormat.setTimeZone(TimeZone.getDefault()); sExifGPSDateStamp.setTimeZone(TimeZone.getTimeZone("UTC")); } diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index 6736d3466e2cd80e13e174f5a9a8972a99e79f52..b10c341eb5ec7e4117f09bd1dbc8951380d0b283 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -24,6 +24,7 @@ import android.hardware.camera2.dispatch.BroadcastDispatcher; import android.hardware.camera2.dispatch.DuckTypingDispatcher; import android.hardware.camera2.dispatch.HandlerDispatcher; import android.hardware.camera2.dispatch.InvokeDispatcher; +import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.utils.TaskDrainer; import android.hardware.camera2.utils.TaskSingleDrainer; import android.os.Handler; @@ -155,6 +156,12 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession mDeviceImpl.tearDown(surface); } + @Override + public void finishDeferredConfiguration( + List deferredOutputConfigs) throws CameraAccessException { + mDeviceImpl.finishDeferredConfig(deferredOutputConfigs); + } + @Override public synchronized int capture(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { @@ -279,23 +286,29 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } @Override - public synchronized void abortCaptures() throws CameraAccessException { - checkNotClosed(); + public void abortCaptures() throws CameraAccessException { + synchronized (this) { + checkNotClosed(); - if (DEBUG) { - Log.v(TAG, mIdString + "abortCaptures"); - } + if (DEBUG) { + Log.v(TAG, mIdString + "abortCaptures"); + } - if (mAborting) { - Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing"); - return; - } + if (mAborting) { + Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing"); + return; + } - mAborting = true; - mAbortDrainer.taskStarted(); + mAborting = true; + mAbortDrainer.taskStarted(); + } - mDeviceImpl.flush(); - // The next BUSY -> IDLE set of transitions will mark the end of the abort. + synchronized (mDeviceImpl.mInterfaceLock) { + synchronized (this) { + mDeviceImpl.flush(); + // The next BUSY -> IDLE set of transitions will mark the end of the abort. + } + } } @Override @@ -323,78 +336,86 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession * @see CameraCaptureSession#close */ @Override - public synchronized void replaceSessionClose() { - /* - * In order for creating new sessions to be fast, the new session should be created - * before the old session is closed. - * - * Otherwise the old session will always unconfigure if there is no new session to - * replace it. - * - * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt - * to skip unconfigure if a new session is created before the captures are all drained, - * but this would introduce nondeterministic behavior. - */ - - if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose"); - - // Set up fast shutdown. Possible alternative paths: - // - This session is active, so close() below starts the shutdown drain - // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener. - // - This session is already closed and has executed the idle drain listener, and - // configureOutputsChecked(null) has already been called. - // - // Do not call configureOutputsChecked(null) going forward, since it would race with the - // configuration for the new session. If it was already called, then we don't care, since it - // won't get called again. - mSkipUnconfigure = true; + public void replaceSessionClose() { + synchronized (this) { + /* + * In order for creating new sessions to be fast, the new session should be created + * before the old session is closed. + * + * Otherwise the old session will always unconfigure if there is no new session to + * replace it. + * + * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt + * to skip unconfigure if a new session is created before the captures are all drained, + * but this would introduce nondeterministic behavior. + */ + if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose"); + + // Set up fast shutdown. Possible alternative paths: + // - This session is active, so close() below starts the shutdown drain + // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener. + // - This session is already closed and has executed the idle drain listener, and + // configureOutputsChecked(null) has already been called. + // + // Do not call configureOutputsChecked(null) going forward, since it would race with the + // configuration for the new session. If it was already called, then we don't care, + // since it won't get called again. + mSkipUnconfigure = true; + } close(); } @Override - public synchronized void close() { - - if (mClosed) { - if (DEBUG) Log.v(TAG, mIdString + "close - reentering"); - return; - } + public void close() { + synchronized (this) { + if (mClosed) { + if (DEBUG) Log.v(TAG, mIdString + "close - reentering"); + return; + } - if (DEBUG) Log.v(TAG, mIdString + "close - first time"); + if (DEBUG) Log.v(TAG, mIdString + "close - first time"); - mClosed = true; + mClosed = true; + } - /* - * Flush out any repeating request. Since camera is closed, no new requests - * can be queued, and eventually the entire request queue will be drained. - * - * If the camera device was already closed, short circuit and do nothing; since - * no more internal device callbacks will fire anyway. - * - * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure the - * camera. Once that's done, fire #onClosed. - */ - try { - mDeviceImpl.stopRepeating(); - } catch (IllegalStateException e) { - // OK: Camera device may already be closed, nothing else to do + synchronized (mDeviceImpl.mInterfaceLock) { + synchronized (this) { + /* + * Flush out any repeating request. Since camera is closed, no new requests + * can be queued, and eventually the entire request queue will be drained. + * + * If the camera device was already closed, short circuit and do nothing; since + * no more internal device callbacks will fire anyway. + * + * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure + * the camera. Once that's done, fire #onClosed. + */ + try { + mDeviceImpl.stopRepeating(); + } catch (IllegalStateException e) { + // OK: Camera device may already be closed, nothing else to do - // TODO: Fire onClosed anytime we get the device onClosed or the ISE? - // or just suppress the ISE only and rely onClosed. - // Also skip any of the draining work if this is already closed. + // TODO: Fire onClosed anytime we get the device onClosed or the ISE? + // or just suppress the ISE only and rely onClosed. + // Also skip any of the draining work if this is already closed. - // Short-circuit; queue callback immediately and return - mStateCallback.onClosed(this); - return; - } catch (CameraAccessException e) { - // OK: close does not throw checked exceptions. - Log.e(TAG, mIdString + "Exception while stopping repeating: ", e); + // Short-circuit; queue callback immediately and return + mStateCallback.onClosed(this); + return; + } catch (CameraAccessException e) { + // OK: close does not throw checked exceptions. + Log.e(TAG, mIdString + "Exception while stopping repeating: ", e); - // TODO: call onError instead of onClosed if this happens + // TODO: call onError instead of onClosed if this happens + } + } } - // If no sequences are pending, fire #onClosed immediately - mSequenceDrainer.beginDrain(); + synchronized (this) { + // If no sequences are pending, fire #onClosed immediately + mSequenceDrainer.beginDrain(); + } } /** diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java index 8cd1da50c58a3da848f518730b0121c3c3dcdf78..1c8e124331124d13429b1f2bf823167012ce7579 100644 --- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java @@ -21,6 +21,7 @@ import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.params.OutputConfiguration; import android.hardware.camera2.params.StreamConfigurationMap; import android.hardware.camera2.utils.SurfaceUtils; import android.os.Handler; @@ -256,6 +257,12 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl return mSessionImpl.isAborting(); } + @Override + public void finishDeferredConfiguration(List deferredOutputConfigs) + throws CameraAccessException { + mSessionImpl.finishDeferredConfiguration(deferredOutputConfigs); + } + private class WrapperCallback extends StateCallback { private final StateCallback mCallback; @@ -263,26 +270,32 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl mCallback = callback; } + @Override public void onConfigured(CameraCaptureSession session) { mCallback.onConfigured(CameraConstrainedHighSpeedCaptureSessionImpl.this); } + @Override public void onConfigureFailed(CameraCaptureSession session) { mCallback.onConfigureFailed(CameraConstrainedHighSpeedCaptureSessionImpl.this); } + @Override public void onReady(CameraCaptureSession session) { mCallback.onReady(CameraConstrainedHighSpeedCaptureSessionImpl.this); } + @Override public void onActive(CameraCaptureSession session) { mCallback.onActive(CameraConstrainedHighSpeedCaptureSessionImpl.this); } + @Override public void onClosed(CameraCaptureSession session) { mCallback.onClosed(CameraConstrainedHighSpeedCaptureSessionImpl.this); } + @Override public void onSurfacePrepared(CameraCaptureSession session, Surface surface) { mCallback.onSurfacePrepared(CameraConstrainedHighSpeedCaptureSessionImpl.this, surface); diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 0cee11445246c84606d5b520749a9ca935eab419..ee8a6d7720372b6ef1bf6038095416ed531c77f9 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -407,7 +407,10 @@ public class CameraDeviceImpl extends CameraDevice int streamId = mConfiguredOutputs.keyAt(i); OutputConfiguration outConfig = mConfiguredOutputs.valueAt(i); - if (!outputs.contains(outConfig)) { + if (!outputs.contains(outConfig) || outConfig.isDeferredConfiguration()) { + // Always delete the deferred output configuration when the session + // is created, as the deferred output configuration doesn't have unique surface + // related identifies. deleteList.add(streamId); } else { addSet.remove(outConfig); // Don't create a stream previously created @@ -744,6 +747,37 @@ public class CameraDeviceImpl extends CameraDevice } } + public void finishDeferredConfig(List deferredConfigs) + throws CameraAccessException { + if (deferredConfigs == null || deferredConfigs.size() == 0) { + throw new IllegalArgumentException("deferred config is null or empty"); + } + + synchronized(mInterfaceLock) { + for (OutputConfiguration config : deferredConfigs) { + int streamId = -1; + for (int i = 0; i < mConfiguredOutputs.size(); i++) { + // Have to use equal here, as createCaptureSessionByOutputConfigurations() and + // createReprocessableCaptureSessionByConfigurations() do a copy of the configs. + if (config.equals(mConfiguredOutputs.valueAt(i))) { + streamId = mConfiguredOutputs.keyAt(i); + break; + } + } + if (streamId == -1) { + throw new IllegalArgumentException("Deferred config is not part of this " + + "session"); + } + + if (config.getSurface() == null) { + throw new IllegalArgumentException("The deferred config for stream " + streamId + + " must have a non-null surface"); + } + mRemoteDevice.setDeferredConfiguration(streamId, config); + } + } + } + public int capture(CaptureRequest request, CaptureCallback callback, Handler handler) throws CameraAccessException { if (DEBUG) { @@ -2005,6 +2039,7 @@ public class CameraDeviceImpl extends CameraDevice * *

Handle binder death for ICameraDeviceUser. Trigger onError.

*/ + @Override public void binderDied() { Log.w(TAG, "CameraDevice " + mCameraId + " died unexpectedly"); diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java index ef5f6d71b8b6e0f6da5a4122298c81808e2e0687..d77f60bf0953d31b9c837660ee98ad8dbc9c5c7c 100644 --- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java +++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java @@ -215,5 +215,14 @@ public class ICameraDeviceUserWrapper { } } + public void setDeferredConfiguration(int streamId, OutputConfiguration deferredConfig) + throws CameraAccessException { + try { + mRemoteDevice.setDeferredConfiguration(streamId, deferredConfig); + } catch (Throwable t) { + CameraManager.throwAsPublicException(t); + throw new UnsupportedOperationException("Unexpected exception", t); + } + } } diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index acbf214942c52458ced2b12a40fc8217fe3d8a45..b9e75eec1a34c77ca5f39c8bb06ca152aa7532ac 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -566,6 +566,13 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { } } + @Override + public void setDeferredConfiguration(int steamId, OutputConfiguration config) { + String err = "Set deferred configuration is not supported on legacy devices"; + Log.e(TAG, err); + throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err); + } + @Override public int createInputStream(int width, int height, int format) { String err = "Creating input stream is not supported on legacy devices"; diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index 61b534bf22deb6c28367eeb9426bb408a5e9ded3..69c00e9873021a54313cacdca55a5c7f9f82872a 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -20,6 +20,8 @@ package android.hardware.camera2.params; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.graphics.ImageFormat; +import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.utils.HashCodeHelpers; import android.hardware.camera2.utils.SurfaceUtils; @@ -94,6 +96,21 @@ public final class OutputConfiguration implements Parcelable { this(SURFACE_GROUP_ID_NONE, surface, ROTATION_0); } + /** + * Unknown surface source type. + */ + private final int SURFACE_TYPE_UNKNOWN = -1; + + /** + * The surface is obtained from {@link android.view.SurfaceView}. + */ + private final int SURFACE_TYPE_SURFACE_VIEW = 0; + + /** + * The surface is obtained from {@link android.graphics.SurfaceTexture}. + */ + private final int SURFACE_TYPE_SURFACE_TEXTURE = 1; + /** * Create a new {@link OutputConfiguration} instance with a {@link Surface}, * with a surface group ID. @@ -179,12 +196,110 @@ public final class OutputConfiguration implements Parcelable { checkNotNull(surface, "Surface must not be null"); checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant"); mSurfaceGroupId = surfaceGroupId; + mSurfaceType = SURFACE_TYPE_UNKNOWN; mSurface = surface; mRotation = rotation; mConfiguredSize = SurfaceUtils.getSurfaceSize(surface); mConfiguredFormat = SurfaceUtils.getSurfaceFormat(surface); mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(surface); mConfiguredGenerationId = surface.getGenerationId(); + mIsDeferredConfig = false; + } + + /** + * Create a new {@link OutputConfiguration} instance, with desired Surface size and Surface + * source class. + *

+ * This constructor takes an argument for desired Surface size and the Surface source class + * without providing the actual output Surface. This is used to setup a output configuration + * with a deferred Surface. The application can use this output configuration to create a + * session. + *

+ *

+ * However, the actual output Surface must be set via {@link #setDeferredSurface} and finish the + * deferred Surface configuration via {@link CameraCaptureSession#finishDeferredConfiguration} + * before submitting a request with this Surface target. The deferred Surface can only be + * obtained from either from {@link android.view.SurfaceView} by calling + * {@link android.view.SurfaceHolder#getSurface}, or from + * {@link android.graphics.SurfaceTexture} via + * {@link android.view.Surface#Surface(android.graphics.SurfaceTexture)}). + *

+ * + * @param surfaceSize Size for the deferred surface. + * @param klass a non-{@code null} {@link Class} object reference that indicates the source of + * this surface. Only {@link android.view.SurfaceHolder SurfaceHolder.class} and + * {@link android.graphics.SurfaceTexture SurfaceTexture.class} are supported. + * @hide + */ + public OutputConfiguration(@NonNull Size surfaceSize, @NonNull Class klass) { + checkNotNull(klass, "surfaceSize must not be null"); + checkNotNull(klass, "klass must not be null"); + if (klass == android.view.SurfaceHolder.class) { + mSurfaceType = SURFACE_TYPE_SURFACE_VIEW; + } else if (klass == android.graphics.SurfaceTexture.class) { + mSurfaceType = SURFACE_TYPE_SURFACE_TEXTURE; + } else { + mSurfaceType = SURFACE_TYPE_UNKNOWN; + throw new IllegalArgumentException("Unknow surface source class type"); + } + + mSurfaceGroupId = SURFACE_GROUP_ID_NONE; + mSurface = null; + mRotation = ROTATION_0; + mConfiguredSize = surfaceSize; + mConfiguredFormat = StreamConfigurationMap.imageFormatToInternal(ImageFormat.PRIVATE); + mConfiguredDataspace = StreamConfigurationMap.imageFormatToDataspace(ImageFormat.PRIVATE); + mConfiguredGenerationId = 0; + mIsDeferredConfig = true; + } + + /** + * Check if this configuration has deferred configuration. + * + *

This will return true if the output configuration was constructed with surface deferred. + * It will return true even after the deferred surface is set later.

+ * + * @return true if this configuration has deferred surface. + * @hide + */ + public boolean isDeferredConfiguration() { + return mIsDeferredConfig; + } + + /** + * Set the deferred surface to this OutputConfiguration. + * + *

+ * The deferred surface must be obtained from either from {@link android.view.SurfaceView} by + * calling {@link android.view.SurfaceHolder#getSurface}, or from + * {@link android.graphics.SurfaceTexture} via + * {@link android.view.Surface#Surface(android.graphics.SurfaceTexture)}). After the deferred + * surface is set, the application must finish the deferred surface configuration via + * {@link CameraCaptureSession#finishDeferredConfiguration} before submitting a request with + * this surface target. + *

+ * + * @param surface The deferred surface to be set. + * @throws IllegalArgumentException if the Surface is invalid. + * @throws IllegalStateException if a Surface was already set to this deferred + * OutputConfiguration. + * @hide + */ + public void setDeferredSurface(@NonNull Surface surface) { + checkNotNull(surface, "Surface must not be null"); + if (mSurface != null) { + throw new IllegalStateException("Deferred surface is already set!"); + } + + // This will throw IAE is the surface was abandoned. + Size surfaceSize = SurfaceUtils.getSurfaceSize(surface); + if (!surfaceSize.equals(mConfiguredSize)) { + Log.w(TAG, "Deferred surface size " + surfaceSize + + " is different with pre-configured size " + mConfiguredSize + + ", the pre-configured size will be used."); + } + + mSurface = surface; } /** @@ -203,10 +318,12 @@ public final class OutputConfiguration implements Parcelable { this.mSurface = other.mSurface; this.mRotation = other.mRotation; this.mSurfaceGroupId = other.mSurfaceGroupId; + this.mSurfaceType = other.mSurfaceType; this.mConfiguredDataspace = other.mConfiguredDataspace; this.mConfiguredFormat = other.mConfiguredFormat; this.mConfiguredSize = other.mConfiguredSize; this.mConfiguredGenerationId = other.mConfiguredGenerationId; + this.mIsDeferredConfig = other.mIsDeferredConfig; } /** @@ -215,16 +332,30 @@ public final class OutputConfiguration implements Parcelable { private OutputConfiguration(@NonNull Parcel source) { int rotation = source.readInt(); int surfaceSetId = source.readInt(); + int surfaceType = source.readInt(); + int width = source.readInt(); + int height = source.readInt(); Surface surface = Surface.CREATOR.createFromParcel(source); - checkNotNull(surface, "Surface must not be null"); checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant"); mSurfaceGroupId = surfaceSetId; mSurface = surface; mRotation = rotation; - mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface); - mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface); - mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface); - mConfiguredGenerationId = mSurface.getGenerationId(); + if (surface != null) { + mSurfaceType = SURFACE_TYPE_UNKNOWN; + mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface); + mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface); + mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface); + mConfiguredGenerationId = mSurface.getGenerationId(); + mIsDeferredConfig = true; + } else { + mSurfaceType = surfaceType; + mConfiguredSize = new Size(width, height); + mConfiguredFormat = StreamConfigurationMap.imageFormatToInternal(ImageFormat.PRIVATE); + mConfiguredGenerationId = 0; + mConfiguredDataspace = + StreamConfigurationMap.imageFormatToDataspace(ImageFormat.PRIVATE); + mIsDeferredConfig = false; + } } /** @@ -291,7 +422,12 @@ public final class OutputConfiguration implements Parcelable { } dest.writeInt(mRotation); dest.writeInt(mSurfaceGroupId); - mSurface.writeToParcel(dest, flags); + dest.writeInt(mSurfaceType); + dest.writeInt(mConfiguredSize.getWidth()); + dest.writeInt(mConfiguredSize.getHeight()); + if (mSurface != null) { + mSurface.writeToParcel(dest, flags); + } } /** @@ -311,13 +447,20 @@ public final class OutputConfiguration implements Parcelable { return true; } else if (obj instanceof OutputConfiguration) { final OutputConfiguration other = (OutputConfiguration) obj; + boolean iSSurfaceEqual = mSurface == other.mSurface && + mConfiguredGenerationId == other.mConfiguredGenerationId ; + if (mIsDeferredConfig) { + Log.i(TAG, "deferred config has the same surface"); + iSSurfaceEqual = true; + } return mRotation == other.mRotation && - mSurface == other.mSurface && - mConfiguredGenerationId == other.mConfiguredGenerationId && + iSSurfaceEqual&& mConfiguredSize.equals(other.mConfiguredSize) && mConfiguredFormat == other.mConfiguredFormat && mConfiguredDataspace == other.mConfiguredDataspace && - mSurfaceGroupId == other.mSurfaceGroupId; + mSurfaceGroupId == other.mSurfaceGroupId && + mSurfaceType == other.mSurfaceType && + mIsDeferredConfig == other.mIsDeferredConfig; } return false; } @@ -327,15 +470,26 @@ public final class OutputConfiguration implements Parcelable { */ @Override public int hashCode() { + // Need ensure that the hashcode remains unchanged after set a deferred surface. Otherwise + // The deferred output configuration will be lost in the camera streammap after the deferred + // surface is set. + if (mIsDeferredConfig) { + return HashCodeHelpers.hashCode( + mRotation, mConfiguredSize.hashCode(), mConfiguredFormat, mConfiguredDataspace, + mSurfaceGroupId, mSurfaceType); + } + return HashCodeHelpers.hashCode( mRotation, mSurface.hashCode(), mConfiguredGenerationId, mConfiguredSize.hashCode(), mConfiguredFormat, mConfiguredDataspace, mSurfaceGroupId); } private static final String TAG = "OutputConfiguration"; - private final Surface mSurface; + private Surface mSurface; private final int mRotation; - private int mSurfaceGroupId; + private final int mSurfaceGroupId; + // Surface source type, this is only used by the deferred surface configuration objects. + private final int mSurfaceType; // The size, format, and dataspace of the surface when OutputConfiguration is created. private final Size mConfiguredSize; @@ -343,4 +497,6 @@ public final class OutputConfiguration implements Parcelable { private final int mConfiguredDataspace; // Surface generation ID to distinguish changes to Surface native internals private final int mConfiguredGenerationId; + // Flag indicating if this config has deferred surface. + private final boolean mIsDeferredConfig; } diff --git a/core/java/android/hardware/camera2/utils/TaskDrainer.java b/core/java/android/hardware/camera2/utils/TaskDrainer.java index 7c46e502501b59fe8b7c29ddf7784a937a9c7165..ed30ff34afc890f71065e7869dde9c16ddd5cc19 100644 --- a/core/java/android/hardware/camera2/utils/TaskDrainer.java +++ b/core/java/android/hardware/camera2/utils/TaskDrainer.java @@ -29,8 +29,9 @@ import static com.android.internal.util.Preconditions.*; * (and new ones won't begin). * *

The initial state is to allow all tasks to be started and finished. A task may only be started - * once, after which it must be finished before starting again. Likewise, finishing a task - * that hasn't been started is also not allowed.

+ * once, after which it must be finished before starting again. Likewise, a task may only be + * finished once, after which it must be started before finishing again. It is okay to finish a + * task before starting it due to different threads handling starting and finishing.

* *

When draining begins, no more new tasks can be started. This guarantees that at some * point when all the tasks are finished there will be no more collective new tasks, @@ -60,6 +61,11 @@ public class TaskDrainer { /** Set of tasks which have been started but not yet finished with #taskFinished */ private final Set mTaskSet = new HashSet(); + /** + * Set of tasks which have been finished but not yet started with #taskStarted. This may happen + * if taskStarted and taskFinished are called from two different threads. + */ + private final Set mEarlyFinishedTaskSet = new HashSet(); private final Object mLock = new Object(); private boolean mDraining = false; @@ -118,8 +124,12 @@ public class TaskDrainer { throw new IllegalStateException("Can't start more tasks after draining has begun"); } - if (!mTaskSet.add(task)) { - throw new IllegalStateException("Task " + task + " was already started"); + // Try to remove the task from the early finished set. + if (!mEarlyFinishedTaskSet.remove(task)) { + // The task is not finished early. Add it to the started set. + if (!mTaskSet.add(task)) { + throw new IllegalStateException("Task " + task + " was already started"); + } } } } @@ -128,8 +138,7 @@ public class TaskDrainer { /** * Mark an asynchronous task as having finished. * - *

A task cannot be finished if it hasn't started. Once finished, a task - * cannot be finished again (unless it's started again).

+ *

A task cannot be finished more than once without first having started.

* * @param task a key to identify a task * @@ -137,7 +146,7 @@ public class TaskDrainer { * @see #beginDrain * * @throws IllegalStateException - * If attempting to start a task which is already finished (and not re-started), + * If attempting to finish a task which is already finished (and not started), */ public void taskFinished(T task) { synchronized (mLock) { @@ -145,8 +154,12 @@ public class TaskDrainer { Log.v(TAG + "[" + mName + "]", "taskFinished " + task); } + // Try to remove the task from started set. if (!mTaskSet.remove(task)) { - throw new IllegalStateException("Task " + task + " was already finished"); + // Task is not started yet. Add it to the early finished set. + if (!mEarlyFinishedTaskSet.add(task)) { + throw new IllegalStateException("Task " + task + " was already finished"); + } } // If this is the last finished task and draining has already begun, fire #onDrained diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 93da3e5af4e941f1595c3b1e44c2dfde8d6f16a5..826eb74aef65f54e2bb452b8f3688b2fb627ec65 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -354,9 +354,9 @@ public final class DisplayManagerGlobal { } } - public void requestColorTransform(int displayId, int colorTransformId) { + public void requestColorMode(int displayId, int colorMode) { try { - mDm.requestColorTransform(displayId, colorTransformId); + mDm.requestColorMode(displayId, colorMode); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 8a1abf18602ada2de4e21fadd5afdc1cf66d3962..f696c8d154463f00e65ba3e9e39221885974798a 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -59,8 +59,8 @@ interface IDisplayManager { // No permissions required. WifiDisplayStatus getWifiDisplayStatus(); - // Requires CONFIGURE_DISPLAY_COLOR_TRANSFORM - void requestColorTransform(int displayId, int colorTransformId); + // Requires CONFIGURE_DISPLAY_COLOR_MODE + void requestColorMode(int displayId, int colorMode); // Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate // MediaProjection token for certain combinations of flags. diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 1ff2e8a11a878b21e6077a7a2f6b12a7da9475ae..f17fd55bd22aaca62c6081f60af4f2d070b64420 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -259,6 +259,7 @@ public class FingerprintManager { public static class AuthenticationResult { private Fingerprint mFingerprint; private CryptoObject mCryptoObject; + private int mUserId; /** * Authentication result @@ -267,9 +268,10 @@ public class FingerprintManager { * @param fingerprint the recognized fingerprint data, if allowed. * @hide */ - public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) { + public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId) { mCryptoObject = crypto; mFingerprint = fingerprint; + mUserId = userId; } /** @@ -286,6 +288,12 @@ public class FingerprintManager { * @hide */ public Fingerprint getFingerprint() { return mFingerprint; } + + /** + * Obtain the userId for which this fingerprint was authenticated. + * @hide + */ + public int getUserId() { return mUserId; } }; /** @@ -792,7 +800,7 @@ public class FingerprintManager { sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */); break; case MSG_AUTHENTICATION_SUCCEEDED: - sendAuthenticatedSucceeded((Fingerprint) msg.obj); + sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */); break; case MSG_AUTHENTICATION_FAILED: sendAuthenticatedFailed(); @@ -840,9 +848,10 @@ public class FingerprintManager { } } - private void sendAuthenticatedSucceeded(Fingerprint fp) { + private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) { if (mAuthenticationCallback != null) { - final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); + final AuthenticationResult result = + new AuthenticationResult(mCryptoObject, fp, userId); mAuthenticationCallback.onAuthenticationSucceeded(result); } } @@ -981,8 +990,8 @@ public class FingerprintManager { } @Override // binder call - public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) { - mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget(); + public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) { + mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget(); } @Override // binder call diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl index 57a429fe5fa757614f4dd7d90ad540190d1ae672..b024b29fef06b023e4feaafde9b337c88f5bb1b9 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl @@ -26,7 +26,7 @@ import android.os.UserHandle; oneway interface IFingerprintServiceReceiver { void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining); void onAcquired(long deviceId, int acquiredInfo); - void onAuthenticationSucceeded(long deviceId, in Fingerprint fp); + void onAuthenticationSucceeded(long deviceId, in Fingerprint fp, int userId); void onAuthenticationFailed(long deviceId); void onError(long deviceId, int error); void onRemoved(long deviceId, int fingerId, int groupId); diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java index 10fc8e6e366ab4e1f2bdd5fadb9cb71fc8189236..01a540484f1a94a1e9be6de16a93dff5ccea437f 100644 --- a/core/java/android/hardware/input/InputManagerInternal.java +++ b/core/java/android/hardware/input/InputManagerInternal.java @@ -59,4 +59,9 @@ public abstract class InputManagerInternal { * @param deviceId The id of input device. */ public abstract void toggleCapsLock(int deviceId); + + /** + * Set whether the input stack should deliver pulse gesture events when the device is asleep. + */ + public abstract void setPulseGestureEnabled(boolean enabled); } diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index 0c3d4b3d7be6b4c1bca79ddba067509c67eb95d8..d4dcacceb76164805c7f52e7df99baaab9a88dc4 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -123,10 +123,18 @@ public final class ContextHubManager { /** * Load a nano app on a specified context hub. * + * Note that loading is asynchronous. When we return from this method, + * the nano app (probably) hasn't loaded yet. Assuming a return of 0 + * from this method, then the final success/failure for the load, along + * with the "handle" for the nanoapp, is all delivered in a byte + * string via a call to Callback.onMessageReceipt. + * + * TODO(b/30784270): Provide a better success/failure and "handle" delivery. + * * @param hubHandle handle of context hub to load the app on. * @param app the nanoApp to load on the hub * - * @return int nanoAppInstance of the loaded nanoApp on success, + * @return 0 if the command for loading was sent to the context hub; * -1 otherwise * * @see NanoApp @@ -150,9 +158,17 @@ public final class ContextHubManager { /** * Unload a specified nanoApp * - * @param nanoAppHandle handle of the nanoApp to load + * Note that unloading is asynchronous. When we return from this method, + * the nano app (probably) hasn't unloaded yet. Assuming a return of 0 + * from this method, then the final success/failure for the unload is + * delivered in a byte string via a call to Callback.onMessageReceipt. + * + * TODO(b/30784270): Provide a better success/failure delivery. * - * @return int 0 on success, -1 otherwise + * @param nanoAppHandle handle of the nanoApp to unload + * + * @return 0 if the command for unloading was sent to the context hub; + * -1 otherwise */ public int unloadNanoApp(int nanoAppHandle) { int retVal = -1; @@ -169,6 +185,24 @@ public final class ContextHubManager { /** * get information about the nano app instance * + * NOTE: The returned NanoAppInstanceInfo does _not_ contain correct + * information for several fields, specifically: + * - getName() + * - getPublisher() + * - getNeededExecMemBytes() + * - getNeededReadMemBytes() + * - getNeededWriteMemBytes() + * + * For example, say you call loadNanoApp() with a NanoApp that has + * getName() returning "My Name". Later, if you call getNanoAppInstanceInfo + * for that nanoapp, the returned NanoAppInstanceInfo's getName() + * method will claim "Preloaded app, unknown", even though you would + * have expected "My Name". For now, as the user, you'll need to + * separately track the above fields if they are of interest to you. + * + * TODO(b/30943489): Have the returned NanoAppInstanceInfo contain the + * correct information. + * * @param nanoAppHandle handle of the nanoAppInstance * @return NanoAppInstanceInfo Information about the nano app instance. * @@ -209,6 +243,14 @@ public final class ContextHubManager { /** * Send a message to a specific nano app instance on a context hub. * + * Note that the return value of this method only speaks of success + * up to the point of sending this to the Context Hub. It is not + * an assurance that the Context Hub successfully sent this message + * on to the nanoapp. If assurance is desired, a protocol should be + * established between your code and the nanoapp, with the nanoapp + * sending a confirmation message (which will be reported via + * Callback.onMessageReceipt). + * * @param hubHandle handle of the hub to send the message to * @param nanoAppHandle handle of the nano app to send to * @param message Message to be sent diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java index 43e596fe5566ba525f8e8f69bb2190d1d37d08fb..06af46122a7b5ba533d39463c3f96acc66d011b8 100644 --- a/core/java/android/hardware/location/ContextHubService.java +++ b/core/java/android/hardware/location/ContextHubService.java @@ -16,6 +16,13 @@ package android.hardware.location; +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.HashMap; + import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; @@ -53,10 +60,14 @@ public class ContextHubService extends IContextHubService.Stub { private static final int PRE_LOADED_APP_MEM_REQ = 0; private static final int MSG_HEADER_SIZE = 4; - private static final int MSG_FIELD_TYPE = 0; - private static final int MSG_FIELD_VERSION = 1; - private static final int MSG_FIELD_HUB_HANDLE = 2; - private static final int MSG_FIELD_APP_INSTANCE = 3; + private static final int HEADER_FIELD_MSG_TYPE = 0; + private static final int HEADER_FIELD_MSG_VERSION = 1; + private static final int HEADER_FIELD_HUB_HANDLE = 2; + private static final int HEADER_FIELD_APP_INSTANCE = 3; + + private static final int HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE; + private static final int HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1; + private static final int MSG_LOAD_APP_HEADER_SIZE = MSG_HEADER_SIZE + 2; private static final int OS_APP_INSTANCE = -1; @@ -137,6 +148,36 @@ public class ContextHubService extends IContextHubService.Stub { return mContextHubInfo[contextHubHandle]; } + // TODO(b/30808791): Remove this when NanoApp's API is correctly treating + // app IDs as 64-bits. + private static long parseAppId(NanoApp app) { + // NOTE: If this shifting seems odd (since it's actually "ONAN"), note + // that it matches how this is defined in context_hub.h. + final int HEADER_MAGIC = + (((int)'N' << 0) | + ((int)'A' << 8) | + ((int)'N' << 16) | + ((int)'O' << 24)); + final int HEADER_MAGIC_OFFSET = 4; + final int HEADER_APP_ID_OFFSET = 8; + + ByteBuffer header = ByteBuffer.wrap(app.getAppBinary()) + .order(ByteOrder.LITTLE_ENDIAN); + + try { + if (header.getInt(HEADER_MAGIC_OFFSET) == HEADER_MAGIC) { + // This is a legitimate nanoapp header. Let's grab the app ID. + return header.getLong(HEADER_APP_ID_OFFSET); + } + } catch (IndexOutOfBoundsException e) { + // The header is undersized. We'll fall through to our code + // path below, which handles being unable to parse the header. + } + // We failed to parse the header. Even through it's probably wrong, + // let's give NanoApp's idea of our ID. This is at least consistent. + return app.getAppId(); + } + @Override public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException { checkPermissions(); @@ -146,15 +187,32 @@ public class ContextHubService extends IContextHubService.Stub { return -1; } - int[] msgHeader = new int[MSG_HEADER_SIZE]; - msgHeader[MSG_FIELD_HUB_HANDLE] = contextHubHandle; - msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE; - msgHeader[MSG_FIELD_VERSION] = 0; - msgHeader[MSG_FIELD_TYPE] = MSG_LOAD_NANO_APP; + int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE]; + msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle; + msgHeader[HEADER_FIELD_APP_INSTANCE] = OS_APP_INSTANCE; + msgHeader[HEADER_FIELD_MSG_VERSION] = 0; + msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP; + + long appId = app.getAppId(); + // TODO(b/30808791): Remove this hack when the NanoApp API is fixed, + // and getAppId() returns a 'long' instead of an 'int'. + if ((appId >> 32) != 0) { + // We're unlikely to notice this warning, but at least + // we can avoid running our hack logic. + Log.w(TAG, "Code has not been updated since API fix."); + } else { + appId = parseAppId(app); + } + + msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF); + msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF); - if (nativeSendMessage(msgHeader, app.getAppBinary()) != 0) { + int errVal = nativeSendMessage(msgHeader, app.getAppBinary()); + if (errVal != 0) { + Log.e(TAG, "Send Message returns error" + contextHubHandle); return -1; } + // Do not add an entry to mNanoAppInstance Hash yet. The HAL may reject the app return 0; } @@ -169,12 +227,14 @@ public class ContextHubService extends IContextHubService.Stub { // Call Native interface here int[] msgHeader = new int[MSG_HEADER_SIZE]; - msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB; - msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE; - msgHeader[MSG_FIELD_VERSION] = 0; - msgHeader[MSG_FIELD_TYPE] = MSG_UNLOAD_NANO_APP; + msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB; + msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppInstanceHandle; + msgHeader[HEADER_FIELD_MSG_VERSION] = 0; + msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_UNLOAD_NANO_APP; + + byte msg[] = new byte[0]; - if (nativeSendMessage(msgHeader, null) != 0) { + if (nativeSendMessage(msgHeader, msg) != 0) { return -1; } @@ -222,10 +282,10 @@ public class ContextHubService extends IContextHubService.Stub { checkPermissions(); int[] msgHeader = new int[MSG_HEADER_SIZE]; - msgHeader[MSG_FIELD_HUB_HANDLE] = hubHandle; - msgHeader[MSG_FIELD_APP_INSTANCE] = nanoAppHandle; - msgHeader[MSG_FIELD_VERSION] = msg.getVersion(); - msgHeader[MSG_FIELD_TYPE] = msg.getMsgType(); + msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle; + msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle; + msgHeader[HEADER_FIELD_MSG_VERSION] = msg.getVersion(); + msgHeader[HEADER_FIELD_MSG_TYPE] = msg.getMsgType(); return nativeSendMessage(msgHeader, msg.getData()); } @@ -269,15 +329,17 @@ public class ContextHubService extends IContextHubService.Stub { Log.v(TAG, "No message callbacks registered."); return 0; } - ContextHubMessage message = - new ContextHubMessage(header[MSG_FIELD_TYPE], header[MSG_FIELD_VERSION], data); + + ContextHubMessage msg = new ContextHubMessage(header[HEADER_FIELD_MSG_TYPE], + header[HEADER_FIELD_MSG_VERSION], + data); for (int i = 0; i < callbacksCount; ++i) { IContextHubCallback callback = mCallbacksList.getBroadcastItem(i); try { callback.onMessageReceipt( - header[MSG_FIELD_HUB_HANDLE], - header[MSG_FIELD_APP_INSTANCE], - message); + header[HEADER_FIELD_HUB_HANDLE], + header[HEADER_FIELD_APP_INSTANCE], + msg); } catch (RemoteException e) { Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ")."); continue; @@ -301,19 +363,34 @@ public class ContextHubService extends IContextHubService.Stub { appInfo.setNeededReadMemBytes(PRE_LOADED_APP_MEM_REQ); appInfo.setNeededWriteMemBytes(PRE_LOADED_APP_MEM_REQ); + String action; + if (mNanoAppHash.containsKey(appInstanceHandle)) { + action = "Updated"; + } else { + action = "Added"; + } + mNanoAppHash.put(appInstanceHandle, appInfo); - Log.d(TAG, "Added app instance " + appInstanceHandle + " with id " + appId - + " version " + appVersion); + Log.d(TAG, action + " app instance " + appInstanceHandle + " with id " + + appId + " version " + appVersion); + + return 0; + } + + private int deleteAppInstance(int appInstanceHandle) { + if (mNanoAppHash.remove(appInstanceHandle) == null) { + return -1; + } return 0; } private void sendVrStateChangeMessageToApp(NanoAppInstanceInfo app, boolean vrModeEnabled) { int[] msgHeader = new int[MSG_HEADER_SIZE]; - msgHeader[MSG_FIELD_TYPE] = 0; - msgHeader[MSG_FIELD_VERSION] = 0; - msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB; - msgHeader[MSG_FIELD_APP_INSTANCE] = app.getHandle(); + msgHeader[HEADER_FIELD_MSG_TYPE] = 0; + msgHeader[HEADER_FIELD_MSG_VERSION] = 0; + msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB; + msgHeader[HEADER_FIELD_APP_INSTANCE] = app.getHandle(); byte[] data = new byte[1]; data[0] = (byte) ((vrModeEnabled) ? 1 : 0); diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java index 8db70e9c53f1c6f47fa5c76b65ee67a17731e7b5..bf35a3d6fbd69ad25d192fc2a5a1e210f988f158 100644 --- a/core/java/android/hardware/location/NanoAppFilter.java +++ b/core/java/android/hardware/location/NanoAppFilter.java @@ -43,7 +43,8 @@ public class NanoAppFilter { private long mAppIdVendorMask; // Id of the context hub this instance is expected on - private int mContextHubId; + // TODO: Provide an API which will let us change this HubId. + private int mContextHubId = HUB_ANY; /** * Flag indicating any version. With this flag set, all versions shall match provided version. diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java index 71a5a8816f5830f544e46ffd8cfd5eaef6d3ace9..ac6d83f622b2dfa003b5ea31cb7f9466b4dae855 100644 --- a/core/java/android/hardware/location/NanoAppInstanceInfo.java +++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java @@ -113,7 +113,12 @@ public class NanoAppInstanceInfo { } /** - * Set the application version + * Get the application version + * + * NOTE: There is a race condition where shortly after loading, this + * may return -1 instead of the correct version. + * + * TODO(b/30970527): Fix this race condition. * * @return int - version of the app */ diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java index c062b3a311526ba094303c8782c9dd3f0fcd48bd..893b9541ff3d2647dff30e6e7d2583342fcd1443 100644 --- a/core/java/android/hardware/usb/UsbDeviceConnection.java +++ b/core/java/android/hardware/usb/UsbDeviceConnection.java @@ -16,8 +16,10 @@ package android.hardware.usb; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; import android.os.ParcelFileDescriptor; - import java.io.FileDescriptor; @@ -31,6 +33,8 @@ public class UsbDeviceConnection { private final UsbDevice mDevice; + private Context mContext; + // used by the JNI code private long mNativeContext; @@ -42,10 +46,21 @@ public class UsbDeviceConnection { mDevice = device; } - /* package */ boolean open(String name, ParcelFileDescriptor pfd) { + /* package */ boolean open(String name, ParcelFileDescriptor pfd, @NonNull Context context) { + mContext = context.getApplicationContext(); + return native_open(name, pfd.getFileDescriptor()); } + /** + * @return The application context the connection was created for. + * + * @hide + */ + public @Nullable Context getContext() { + return mContext; + } + /** * Releases all system resources related to the device. * Once the object is closed it cannot be used again. diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 6341cbc79f3f08728677a70b23bd47c98910d387..3df57bcb704f8ba2760fb148fc290978f1943ce1 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -21,6 +21,7 @@ import com.android.internal.util.Preconditions; import android.app.PendingIntent; import android.content.Context; +import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.Process; @@ -42,7 +43,7 @@ import java.util.HashMap; *
*

Developer Guides

*

For more information about communicating with USB hardware, read the - * USB developer guide.

+ * USB developer guide.

*
*/ public class UsbManager { @@ -329,7 +330,7 @@ public class UsbManager { ParcelFileDescriptor pfd = mService.openDevice(deviceName); if (pfd != null) { UsbDeviceConnection connection = new UsbDeviceConnection(device); - boolean result = connection.open(deviceName, pfd); + boolean result = connection.open(deviceName, pfd, mContext); pfd.close(); if (result) { return connection; @@ -475,6 +476,26 @@ public class UsbManager { } } + /** + * Grants permission to specified package for USB device without showing system dialog. + * Only system components can call this function, as it requires the MANAGE_USB permission. + * @param device to request permissions for + * @param packageName of package to grant permissions + * + * {@hide} + */ + public void grantPermission(UsbDevice device, String packageName) { + try { + int uid = mContext.getPackageManager() + .getPackageUidAsUser(packageName, mContext.getUserId()); + mService.grantDevicePermission(device, uid); + } catch (NameNotFoundException e) { + Log.e(TAG, "Package " + packageName + " not found.", e); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Returns true if the specified USB function is currently enabled when in device mode. *

diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java index 3531926d347ca313145ede6e15031b1ecf4ea8f2..29177b6b47cf81a7aeb122c69bb2ea2b721e96e7 100644 --- a/core/java/android/inputmethodservice/AbstractInputMethodService.java +++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java @@ -16,11 +16,14 @@ package android.inputmethodservice; +import android.annotation.NonNull; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputContentInfo; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodSession; @@ -208,7 +211,7 @@ public abstract class AbstractInputMethodService extends Service * * @param event The motion event being received. * @return True if the event was handled in this function, false otherwise. - * @see View#onTrackballEvent + * @see android.view.View#onTrackballEvent(MotionEvent) */ public boolean onTrackballEvent(MotionEvent event) { return false; @@ -219,9 +222,30 @@ public abstract class AbstractInputMethodService extends Service * * @param event The motion event being received. * @return True if the event was handled in this function, false otherwise. - * @see View#onGenericMotionEvent + * @see android.view.View#onGenericMotionEvent(MotionEvent) */ public boolean onGenericMotionEvent(MotionEvent event) { return false; } + + /** + * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access + * permission to the content. + * + *

Default implementation does nothing.

+ * + * @param inputContentInfo Content to be temporarily exposed from the input method to the + * application. + * This cannot be {@code null}. + * @param inputConnection {@link InputConnection} with which + * {@link InputConnection#commitContent(InputContentInfo, int, android.os.Bundle)} will be + * called. + * @return {@code false} if we cannot allow a temporary access permission. + * @hide + */ + public void exposeContent(@NonNull InputContentInfo inputContentInfo, + @NonNull InputConnection inputConnection) { + return; + } + } diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index cc71a9c24bfbcc82f7b674018c1d89cc8af2179a..167d5a09a2dc42e3c37d920c3daec8d4f069c51f 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -168,7 +168,7 @@ class IInputMethodWrapper extends IInputMethod.Stub int missingMethods = msg.arg1; IInputContext inputContext = (IInputContext)args.arg1; InputConnection ic = inputContext != null - ? new InputConnectionWrapper(inputContext, missingMethods) : null; + ? new InputConnectionWrapper(mTarget, inputContext, missingMethods) : null; EditorInfo info = (EditorInfo)args.arg2; info.makeCompatible(mTargetSdkVersion); inputMethod.startInput(ic, info); @@ -180,7 +180,7 @@ class IInputMethodWrapper extends IInputMethod.Stub int missingMethods = msg.arg1; IInputContext inputContext = (IInputContext)args.arg1; InputConnection ic = inputContext != null - ? new InputConnectionWrapper(inputContext, missingMethods) : null; + ? new InputConnectionWrapper(mTarget, inputContext, missingMethods) : null; EditorInfo info = (EditorInfo)args.arg2; info.makeCompatible(mTargetSdkVersion); inputMethod.restartInput(ic, info); @@ -251,7 +251,7 @@ class IInputMethodWrapper extends IInputMethod.Stub public void bindInput(InputBinding binding) { // This IInputContext is guaranteed to implement all the methods. final int missingMethodFlags = 0; - InputConnection ic = new InputConnectionWrapper( + InputConnection ic = new InputConnectionWrapper(mTarget, IInputContext.Stub.asInterface(binding.getConnectionToken()), missingMethodFlags); InputBinding nu = new InputBinding(ic, binding); mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu)); diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 4799773d9ed694b29a3f547056008b81c3788688..fede77d9bb1d84fe93f5eb2069222c7ba4356b25 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -23,6 +23,7 @@ import android.annotation.CallSuper; import android.annotation.DrawableRes; import android.annotation.IntDef; import android.annotation.MainThread; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.Dialog; import android.content.Context; @@ -65,6 +66,7 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputBinding; import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputContentInfo; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; @@ -2597,6 +2599,29 @@ public class InputMethodService extends AbstractInputMethodService { return mImm.getInputMethodWindowVisibleHeight(); } + /** + * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access + * permission to the content. + * + * @param inputContentInfo Content to be temporarily exposed from the input method to the + * application. + * This cannot be {@code null}. + * @param inputConnection {@link InputConnection} with which + * {@link InputConnection#commitContent(InputContentInfo, Bundle)} will be called. + * @hide + */ + @Override + public final void exposeContent(@NonNull InputContentInfo inputContentInfo, + @NonNull InputConnection inputConnection) { + if (inputConnection == null) { + return; + } + if (getCurrentInputConnection() != inputConnection) { + return; + } + mImm.exposeContent(mToken, inputContentInfo, getCurrentInputEditorInfo()); + } + /** * Performs a dump of the InputMethodService's internal state. Override * to add your own information to the dump. diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a45e6f51d8030e7fa5fcb1415d66e74a7ef861f3..0afb546aa4e471f2032c37a0fe43fc3a305e91ed 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -342,6 +342,15 @@ public class ConnectivityManager { */ public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED"; + /** + * Action used to display a dialog that asks the user whether to avoid a network that is no + * longer validated. This intent is used to start the dialog in settings via startActivity. + * + * @hide + */ + public static final String ACTION_PROMPT_LOST_VALIDATION = + "android.net.conn.PROMPT_LOST_VALIDATION"; + /** * Invalid tethering type. * @see #startTethering(int, OnStartTetheringCallback, boolean) @@ -1034,6 +1043,26 @@ public class ConnectivityManager { } } + /** + * Request that this callback be invoked at ConnectivityService's earliest + * convenience with the current satisfying network's LinkProperties. + * If no such network exists no callback invocation is performed. + * + * The callback must have been registered with #requestNetwork() or + * #registerDefaultNetworkCallback(); callbacks registered with + * registerNetworkCallback() are not specific to any particular Network so + * do not cause any updates. + * + * @hide + */ + public void requestLinkProperties(NetworkCallback networkCallback) { + try { + mService.requestLinkProperties(networkCallback.networkRequest); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This * will return {@code null} if the network is unknown. @@ -1051,6 +1080,26 @@ public class ConnectivityManager { } } + /** + * Request that this callback be invoked at ConnectivityService's earliest + * convenience with the current satisfying network's NetworkCapabilities. + * If no such network exists no callback invocation is performed. + * + * The callback must have been registered with #requestNetwork() or + * #registerDefaultNetworkCallback(); callbacks registered with + * registerNetworkCallback() are not specific to any particular Network so + * do not cause any updates. + * + * @hide + */ + public void requestNetworkCapabilities(NetworkCallback networkCallback) { + try { + mService.requestNetworkCapabilities(networkCallback.networkRequest); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Gets the URL that should be used for resolving whether a captive portal is present. * 1. This URL should respond with a 204 response to a GET request to indicate no captive @@ -1776,6 +1825,16 @@ public class ConnectivityManager { return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); } + /* TODO: These permissions checks don't belong in client-side code. Move them to + * services.jar, possibly in com.android.server.net. */ + + /** {@hide} */ + public static final boolean checkChangePermission(Context context) { + int uid = Binder.getCallingUid(); + return Settings.checkAndNoteChangeNetworkStateOperation(context, uid, Settings + .getPackageNameForUid(context, uid), false /* throwException */); + } + /** {@hide} */ public static final void enforceChangePermission(Context context) { int uid = Binder.getCallingUid(); @@ -3103,14 +3162,11 @@ public class ConnectivityManager { throw new IllegalArgumentException("Invalid NetworkCallback"); } try { + // CallbackHandler will release callback when receiving CALLBACK_RELEASED. mService.releaseNetworkRequest(networkCallback.networkRequest); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - - synchronized (sNetworkCallback) { - sNetworkCallback.remove(networkCallback.networkRequest); - } } /** @@ -3151,6 +3207,27 @@ public class ConnectivityManager { } } + /** + * Informs the system to penalize {@code network}'s score when it becomes unvalidated. This is + * only meaningful if the system is configured not to penalize such networks, e.g., if the + * {@code config_networkAvoidBadWifi} configuration variable is set to 0 and the {@code + * NETWORK_AVOID_BAD_WIFI setting is unset}. + * + *

This method requires the caller to hold the permission + * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} + * + * @param network The network to accept. + * + * @hide + */ + public void setAvoidUnvalidated(Network network) { + try { + mService.setAvoidUnvalidated(network); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Resets all connectivity manager settings back to factory defaults. * @hide diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java index d8cdde94a2f189bef8fef99c9c1ee27cfd20c6c1..9a2d4e0a31242a01bf3b0a0f014d65eec2cd9cda 100644 --- a/core/java/android/net/ConnectivityMetricsLogger.java +++ b/core/java/android/net/ConnectivityMetricsLogger.java @@ -23,6 +23,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + /** {@hide} */ @SystemApi public class ConnectivityMetricsLogger { @@ -33,28 +35,58 @@ public class ConnectivityMetricsLogger { // Component Tags public static final int COMPONENT_TAG_CONNECTIVITY = 0; - public static final int COMPONENT_TAG_BLUETOOTH = 1; - public static final int COMPONENT_TAG_WIFI = 2; - public static final int COMPONENT_TAG_TELECOM = 3; - public static final int COMPONENT_TAG_TELEPHONY = 4; - - public static final int NUMBER_OF_COMPONENTS = 5; + public static final int COMPONENT_TAG_BLUETOOTH = 1; + public static final int COMPONENT_TAG_WIFI = 2; + public static final int COMPONENT_TAG_TELECOM = 3; + public static final int COMPONENT_TAG_TELEPHONY = 4; + public static final int NUMBER_OF_COMPONENTS = 5; // Event Tag public static final int TAG_SKIPPED_EVENTS = -1; public static final String DATA_KEY_EVENTS_COUNT = "count"; - private IConnectivityMetricsLogger mService; - - private long mServiceUnblockedTimestampMillis = 0; - private int mNumSkippedEvents = 0; + /** {@hide} */ protected IConnectivityMetricsLogger mService; + /** {@hide} */ protected volatile long mServiceUnblockedTimestampMillis; + private int mNumSkippedEvents; public ConnectivityMetricsLogger() { - mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService( - CONNECTIVITY_METRICS_LOGGER_SERVICE)); + // TODO: consider not initializing mService in constructor + this(IConnectivityMetricsLogger.Stub.asInterface( + ServiceManager.getService(CONNECTIVITY_METRICS_LOGGER_SERVICE))); + } + + /** {@hide} */ + @VisibleForTesting + public ConnectivityMetricsLogger(IConnectivityMetricsLogger service) { + mService = service; } + /** {@hide} */ + protected boolean checkLoggerService() { + if (mService != null) { + return true; + } + // Two threads racing here will write the same pointer because getService + // is idempotent once MetricsLoggerService is initialized. + mService = IConnectivityMetricsLogger.Stub.asInterface( + ServiceManager.getService(CONNECTIVITY_METRICS_LOGGER_SERVICE)); + return mService != null; + } + + /** + * Log a ConnectivityMetricsEvent. + * + * This method keeps track of skipped events when MetricsLoggerService throttles input events. + * It skips logging when MetricsLoggerService is active. When throttling ends, it logs a + * meta-event containing the number of events dropped. It is not safe to call this method + * concurrently from different threads. + * + * @param timestamp is the epoch timestamp of the event in ms. + * @param componentTag is the COMPONENT_* constant the event belongs to. + * @param eventTag is an event type constant whose meaning is specific to the component tag. + * @param data is a Parcelable instance representing the event. + */ public void logEvent(long timestamp, int componentTag, int eventTag, Parcelable data) { if (mService == null) { if (DBG) { @@ -77,6 +109,12 @@ public class ConnectivityMetricsLogger { // Log number of skipped events Bundle b = new Bundle(); b.putInt(DATA_KEY_EVENTS_COUNT, mNumSkippedEvents); + + // Log the skipped event. + // TODO: Note that some of the clients push all states events into the server, + // If we lose some states logged here, we might mess up the statistics happened at the + // backend. One of the options is to introduce a non-skippable flag for important events + // that are logged. skippedEventsEvent = new ConnectivityMetricsEvent(mServiceUnblockedTimestampMillis, componentTag, TAG_SKIPPED_EVENTS, b); @@ -104,7 +142,7 @@ public class ConnectivityMetricsLogger { } } } catch (RemoteException e) { - Log.e(TAG, "Error logging event " + e.getMessage()); + Log.e(TAG, "Error logging event", e); } } @@ -121,8 +159,8 @@ public class ConnectivityMetricsLogger { public ConnectivityMetricsEvent[] getEvents(ConnectivityMetricsEvent.Reference reference) { try { return mService.getEvents(reference); - } catch (RemoteException ex) { - Log.e(TAG, "IConnectivityMetricsLogger.getEvents: " + ex); + } catch (RemoteException e) { + Log.e(TAG, "IConnectivityMetricsLogger.getEvents", e); return null; } } @@ -133,8 +171,8 @@ public class ConnectivityMetricsLogger { public boolean register(PendingIntent newEventsIntent) { try { return mService.register(newEventsIntent); - } catch (RemoteException ex) { - Log.e(TAG, "IConnectivityMetricsLogger.register: " + ex); + } catch (RemoteException e) { + Log.e(TAG, "IConnectivityMetricsLogger.register", e); return false; } } @@ -142,11 +180,10 @@ public class ConnectivityMetricsLogger { public boolean unregister(PendingIntent newEventsIntent) { try { mService.unregister(newEventsIntent); - } catch (RemoteException ex) { - Log.e(TAG, "IConnectivityMetricsLogger.unregister: " + ex); + return true; + } catch (RemoteException e) { + Log.e(TAG, "IConnectivityMetricsLogger.unregister", e); return false; } - - return true; } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 0d518cc14049a51d2fefa325ce2977d0424739a2..4aabda9eb09d217df491518f53e645faad277b6c 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -156,9 +156,12 @@ interface IConnectivityManager void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, in PendingIntent operation); + void requestLinkProperties(in NetworkRequest networkRequest); + void requestNetworkCapabilities(in NetworkRequest networkRequest); void releaseNetworkRequest(in NetworkRequest networkRequest); void setAcceptUnvalidated(in Network network, boolean accept, boolean always); + void setAvoidUnvalidated(in Network network); int getRestoreDefaultNetworkDelay(int networkType); diff --git a/core/java/android/net/metrics/IpConnectivityEvent.java b/core/java/android/net/IIpConnectivityMetrics.aidl similarity index 51% rename from core/java/android/net/metrics/IpConnectivityEvent.java rename to core/java/android/net/IIpConnectivityMetrics.aidl index 95576c2853dde713fd6312ddd816a3a85ab5af76..8f634bbf0cc9a113e71da730c8cf96c6eabbeaf4 100644 --- a/core/java/android/net/metrics/IpConnectivityEvent.java +++ b/core/java/android/net/IIpConnectivityMetrics.aidl @@ -14,22 +14,16 @@ * limitations under the License. */ -package android.net.metrics; +package android.net; -import android.net.ConnectivityMetricsLogger; -import android.os.Parcel; import android.os.Parcelable; +import android.net.ConnectivityMetricsEvent; -/** - * {@hide} - */ -public abstract class IpConnectivityEvent { - private static final int COMPONENT_TAG = ConnectivityMetricsLogger.COMPONENT_TAG_CONNECTIVITY; - - private static final ConnectivityMetricsLogger sMetricsLogger = new ConnectivityMetricsLogger(); +/** {@hide} */ +interface IIpConnectivityMetrics { - public static void logEvent(T event) { - // TODO: consider using different component for DNS event. - sMetricsLogger.logEvent(System.currentTimeMillis(), COMPONENT_TAG, 0, event); - } -}; + /** + * @return number of remaining available slots in buffer. + */ + int logEvent(in ConnectivityMetricsEvent event); +} diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index 384ab1c8f50cc97208fc5eedf4b21e2b44265645..6e74f14bd138a9944d3ce5af1b9b12bf70e122cb 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -103,7 +103,7 @@ public class LinkAddress implements Parcelable { private boolean isIPv6ULA() { if (address != null && address instanceof Inet6Address) { byte[] bytes = address.getAddress(); - return ((bytes[0] & (byte)0xfc) == (byte)0xfc); + return ((bytes[0] & (byte)0xfe) == (byte)0xfc); } return false; } diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index cbb6dfe75faece0421b923f1d096691f103f4c4e..dacea55baabaae11722903410b2ce3d085e13354 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -182,8 +182,15 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; + /** + * Indicates that this network is available for use by apps, and not a network that is being + * kept up in the background to facilitate fast network switching. + * @hide + */ + public static final int NET_CAPABILITY_FOREGROUND = 18; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_CAPTIVE_PORTAL; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -194,7 +201,8 @@ public final class NetworkCapabilities implements Parcelable { // http://b/18206275 (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_VALIDATED) | - (1 << NET_CAPABILITY_CAPTIVE_PORTAL); + (1 << NET_CAPABILITY_CAPTIVE_PORTAL) | + (1 << NET_CAPABILITY_FOREGROUND); /** * Network specifier for factories which want to match any network specifier @@ -217,8 +225,7 @@ public final class NetworkCapabilities implements Parcelable { * get immediately torn down because they do not have the requested capability. */ private static final long NON_REQUESTABLE_CAPABILITIES = - (1 << NET_CAPABILITY_VALIDATED) | - (1 << NET_CAPABILITY_CAPTIVE_PORTAL); + MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_TRUSTED); /** * Capabilities that are set by default when the object is constructed. @@ -325,6 +332,7 @@ public final class NetworkCapabilities implements Parcelable { public String describeFirstNonRequestableCapability() { if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED"; if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL"; + if (hasCapability(NET_CAPABILITY_FOREGROUND)) return "NET_CAPABILITY_FOREGROUND"; // This cannot happen unless the preceding checks are incomplete. if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) { return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities); @@ -352,6 +360,11 @@ public final class NetworkCapabilities implements Parcelable { (that.mNetworkCapabilities & ~MUTABLE_CAPABILITIES)); } + private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) { + return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) == + (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)); + } + /** * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are * typically provided by restricted networks. @@ -756,6 +769,19 @@ public final class NetworkCapabilities implements Parcelable { equalsSpecifier(nc)); } + /** + * Checks that our requestable capabilities are the same as those of the given + * {@code NetworkCapabilities}. + * + * @hide + */ + public boolean equalRequestableCapabilities(NetworkCapabilities nc) { + if (nc == null) return false; + return (equalsNetCapabilitiesRequestable(nc) && + equalsTransportTypes(nc) && + equalsSpecifier(nc)); + } + @Override public boolean equals(Object obj) { if (obj == null || (obj instanceof NetworkCapabilities == false)) return false; @@ -840,6 +866,7 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_NOT_VPN: capabilities += "NOT_VPN"; break; case NET_CAPABILITY_VALIDATED: capabilities += "VALIDATED"; break; case NET_CAPABILITY_CAPTIVE_PORTAL: capabilities += "CAPTIVE_PORTAL"; break; + case NET_CAPABILITY_FOREGROUND: capabilities += "FOREGROUND"; break; } if (++i < types.length) capabilities += "&"; } diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 9cd563e87c4a8c9dcac668b5d2b3601c0bdddb0f..d570e66a24357e74744b311308a5a9f513e8348f 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -175,7 +175,11 @@ public class NetworkIdentity implements Comparable { if (isNetworkTypeMobile(type)) { if (state.subscriberId == null) { - Slog.w(TAG, "Active mobile network without subscriber!"); + if (state.networkInfo.getState() != NetworkInfo.State.DISCONNECTED && + state.networkInfo.getState() != NetworkInfo.State.UNKNOWN) { + Slog.w(TAG, "Active mobile network without subscriber! ni = " + + state.networkInfo); + } } subscriberId = state.subscriberId; diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java index 5511a248b6aa9d47921847fc2bc085099b3709f5..69f50a272af0c8aa5c28d5b569aba87e8199c89f 100644 --- a/core/java/android/net/NetworkMisc.java +++ b/core/java/android/net/NetworkMisc.java @@ -51,6 +51,15 @@ public class NetworkMisc implements Parcelable { */ public boolean acceptUnvalidated; + /** + * Set to avoid surfacing the "Sign in to network" notification. + * if carrier receivers/apps are registered to handle the carrier-specific provisioning + * procedure, a carrier specific provisioning notification will be placed. + * only one notification should be displayed. This field is set based on + * which notification should be used for provisioning. + */ + public boolean provisioningNotificationDisabled; + /** * For mobile networks, this is the subscriber ID (such as IMSI). */ @@ -65,6 +74,7 @@ public class NetworkMisc implements Parcelable { explicitlySelected = nm.explicitlySelected; acceptUnvalidated = nm.acceptUnvalidated; subscriberId = nm.subscriberId; + provisioningNotificationDisabled = nm.provisioningNotificationDisabled; } } @@ -79,6 +89,7 @@ public class NetworkMisc implements Parcelable { out.writeInt(explicitlySelected ? 1 : 0); out.writeInt(acceptUnvalidated ? 1 : 0); out.writeString(subscriberId); + out.writeInt(provisioningNotificationDisabled ? 1 : 0); } public static final Creator CREATOR = new Creator() { @@ -89,6 +100,7 @@ public class NetworkMisc implements Parcelable { networkMisc.explicitlySelected = in.readInt() != 0; networkMisc.acceptUnvalidated = in.readInt() != 0; networkMisc.subscriberId = in.readString(); + networkMisc.provisioningNotificationDisabled = in.readInt() != 0; return networkMisc; } diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 51c45e056092ae343683129ee925e74d9acb3dda..11b861aef5aa3898843f2d193ebb20965389aee3 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -18,7 +18,6 @@ package android.net; import static android.content.pm.PackageManager.GET_SIGNATURES; import static android.net.NetworkPolicy.CYCLE_NONE; -import static android.text.format.Time.MONTH_DAY; import android.content.Context; import android.content.Intent; @@ -27,12 +26,13 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.os.RemoteException; import android.os.UserHandle; -import android.text.format.Time; import android.util.DebugUtils; import com.google.android.collect.Sets; +import java.util.Calendar; import java.util.HashSet; +import java.util.TimeZone; /** * Manager for creating and modifying network policy rules. @@ -253,28 +253,18 @@ public class NetworkPolicyManager { throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); } - final Time now = new Time(policy.cycleTimezone); - now.set(currentTime); - - // first, find cycle boundary for current month - final Time cycle = new Time(now); - cycle.hour = cycle.minute = cycle.second = 0; - snapToCycleDay(cycle, policy.cycleDay); - - if (Time.compare(cycle, now) >= 0) { - // cycle boundary is beyond now, use last cycle boundary; start by - // pushing ourselves squarely into last month. - final Time lastMonth = new Time(now); - lastMonth.hour = lastMonth.minute = lastMonth.second = 0; - lastMonth.monthDay = 1; - lastMonth.month -= 1; - lastMonth.normalize(true); - - cycle.set(lastMonth); - snapToCycleDay(cycle, policy.cycleDay); + final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(policy.cycleTimezone)); + cal.setTimeInMillis(currentTime); + snapToCycleDay(cal, policy.cycleDay); + + if (cal.getTimeInMillis() >= currentTime) { + // Cycle boundary is beyond now, use last cycle boundary + cal.set(Calendar.DAY_OF_MONTH, 1); + cal.add(Calendar.MONTH, -1); + snapToCycleDay(cal, policy.cycleDay); } - return cycle.toMillis(true); + return cal.getTimeInMillis(); } /** {@hide} */ @@ -283,28 +273,18 @@ public class NetworkPolicyManager { throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); } - final Time now = new Time(policy.cycleTimezone); - now.set(currentTime); - - // first, find cycle boundary for current month - final Time cycle = new Time(now); - cycle.hour = cycle.minute = cycle.second = 0; - snapToCycleDay(cycle, policy.cycleDay); - - if (Time.compare(cycle, now) <= 0) { - // cycle boundary is before now, use next cycle boundary; start by - // pushing ourselves squarely into next month. - final Time nextMonth = new Time(now); - nextMonth.hour = nextMonth.minute = nextMonth.second = 0; - nextMonth.monthDay = 1; - nextMonth.month += 1; - nextMonth.normalize(true); - - cycle.set(nextMonth); - snapToCycleDay(cycle, policy.cycleDay); + final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(policy.cycleTimezone)); + cal.setTimeInMillis(currentTime); + snapToCycleDay(cal, policy.cycleDay); + + if (cal.getTimeInMillis() <= currentTime) { + // Cycle boundary is before now, use next cycle boundary + cal.set(Calendar.DAY_OF_MONTH, 1); + cal.add(Calendar.MONTH, 1); + snapToCycleDay(cal, policy.cycleDay); } - return cycle.toMillis(true); + return cal.getTimeInMillis(); } /** @@ -313,16 +293,17 @@ public class NetworkPolicyManager { * * @hide */ - public static void snapToCycleDay(Time time, int cycleDay) { - if (cycleDay > time.getActualMaximum(MONTH_DAY)) { - // cycle day isn't valid this month; snap to last second of month - time.month += 1; - time.monthDay = 1; - time.second = -1; + public static void snapToCycleDay(Calendar cal, int cycleDay) { + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + if (cycleDay > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) { + cal.set(Calendar.DAY_OF_MONTH, 1); + cal.add(Calendar.MONTH, 1); + cal.add(Calendar.SECOND, -1); } else { - time.monthDay = cycleDay; + cal.set(Calendar.DAY_OF_MONTH, cycleDay); } - time.normalize(true); } /** diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index f1edcbe30df65305749051d9f2ef4d12c3b22e76..ae724709c6c62e92f6bcf975984753ef92cdfbec 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -19,6 +19,8 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * Defines a request for a network, made through {@link NetworkRequest.Builder} and used * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes @@ -47,15 +49,69 @@ public class NetworkRequest implements Parcelable { public final int legacyType; /** + * A NetworkRequest as used by the system can be one of the following types: + * + * - LISTEN, for which the framework will issue callbacks about any + * and all networks that match the specified NetworkCapabilities, + * + * - REQUEST, capable of causing a specific network to be created + * first (e.g. a telephony DUN request), the framework will issue + * callbacks about the single, highest scoring current network + * (if any) that matches the specified NetworkCapabilities, or + * + * - TRACK_DEFAULT, a hybrid of the two designed such that the + * framework will issue callbacks for the single, highest scoring + * current network (if any) that matches the capabilities of the + * default Internet request (mDefaultRequest), but which cannot cause + * the framework to either create or retain the existence of any + * specific network. Note that from the point of view of the request + * matching code, TRACK_DEFAULT is identical to REQUEST: its special + * behaviour is not due to different semantics, but to the fact that + * the system will only ever create a TRACK_DEFAULT with capabilities + * that are identical to the default request's capabilities, thus + * causing it to share fate in every way with the default request. + * + * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks + * to retain the NET_CAPABILITY_FOREGROUND capability. A network with + * no foreground requests is in the background. A network that has + * one or more background requests and loses its last foreground + * request to a higher-scoring network will not go into the + * background immediately, but will linger and go into the background + * after the linger timeout. + * + * - The value NONE is used only by applications. When an application + * creates a NetworkRequest, it does not have a type; the type is set + * by the system depending on the method used to file the request + * (requestNetwork, registerNetworkCallback, etc.). + * + * @hide + */ + public static enum Type { + NONE, + LISTEN, + TRACK_DEFAULT, + REQUEST, + BACKGROUND_REQUEST, + }; + + /** + * The type of the request. This is only used by the system and is always NONE elsewhere. + * * @hide */ - public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) { + public final Type type; + + /** + * @hide + */ + public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type) { if (nc == null) { throw new NullPointerException(); } requestId = rId; networkCapabilities = nc; this.legacyType = legacyType; + this.type = type; } /** @@ -65,6 +121,7 @@ public class NetworkRequest implements Parcelable { networkCapabilities = new NetworkCapabilities(that.networkCapabilities); requestId = that.requestId; this.legacyType = that.legacyType; + this.type = that.type; } /** @@ -90,14 +147,14 @@ public class NetworkRequest implements Parcelable { final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); nc.maybeMarkCapabilitiesRestricted(); return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, - ConnectivityManager.REQUEST_ID_UNSET); + ConnectivityManager.REQUEST_ID_UNSET, Type.NONE); } /** * Add the given capability requirement to this builder. These represent * the requested network's required capabilities. Note that when searching * for a network to satisfy a request, all capabilities requested must be - * satisfied. See {@link NetworkCapabilities} for {@code NET_CAPABILITIY_*} + * satisfied. See {@link NetworkCapabilities} for {@code NET_CAPABILITY_*} * definitions. * * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to add. @@ -223,6 +280,7 @@ public class NetworkRequest implements Parcelable { dest.writeParcelable(networkCapabilities, flags); dest.writeInt(legacyType); dest.writeInt(requestId); + dest.writeString(type.name()); } public static final Creator CREATOR = new Creator() { @@ -230,7 +288,8 @@ public class NetworkRequest implements Parcelable { NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null); int legacyType = in.readInt(); int requestId = in.readInt(); - NetworkRequest result = new NetworkRequest(nc, legacyType, requestId); + Type type = Type.valueOf(in.readString()); // IllegalArgumentException if invalid. + NetworkRequest result = new NetworkRequest(nc, legacyType, requestId, type); return result; } public NetworkRequest[] newArray(int size) { @@ -238,8 +297,64 @@ public class NetworkRequest implements Parcelable { } }; + /** + * Returns true iff. this NetworkRequest is of type LISTEN. + * + * @hide + */ + public boolean isListen() { + return type == Type.LISTEN; + } + + /** + * Returns true iff. the contained NetworkRequest is one that: + * + * - should be associated with at most one satisfying network + * at a time; + * + * - should cause a network to be kept up, but not necessarily in + * the foreground, if it is the best network which can satisfy the + * NetworkRequest. + * + * For full detail of how isRequest() is used for pairing Networks with + * NetworkRequests read rematchNetworkAndRequests(). + * + * @hide + */ + public boolean isRequest() { + return isForegroundRequest() || isBackgroundRequest(); + } + + /** + * Returns true iff. the contained NetworkRequest is one that: + * + * - should be associated with at most one satisfying network + * at a time; + * + * - should cause a network to be kept up and in the foreground if + * it is the best network which can satisfy the NetworkRequest. + * + * For full detail of how isRequest() is used for pairing Networks with + * NetworkRequests read rematchNetworkAndRequests(). + * + * @hide + */ + public boolean isForegroundRequest() { + return type == Type.TRACK_DEFAULT || type == Type.REQUEST; + } + + /** + * Returns true iff. this NetworkRequest is of type BACKGROUND_REQUEST. + * + * @hide + */ + public boolean isBackgroundRequest() { + return type == Type.BACKGROUND_REQUEST; + } + public String toString() { - return "NetworkRequest [ id=" + requestId + ", legacyType=" + legacyType + + return "NetworkRequest [ " + type + " id=" + requestId + + (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") + ", " + networkCapabilities.toString() + " ]"; } @@ -248,13 +363,11 @@ public class NetworkRequest implements Parcelable { NetworkRequest that = (NetworkRequest)obj; return (that.legacyType == this.legacyType && that.requestId == this.requestId && - ((that.networkCapabilities == null && this.networkCapabilities == null) || - (that.networkCapabilities != null && - that.networkCapabilities.equals(this.networkCapabilities)))); + that.type == this.type && + Objects.equals(that.networkCapabilities, this.networkCapabilities)); } public int hashCode() { - return requestId + (legacyType * 1013) + - (networkCapabilities.hashCode() * 1051); + return Objects.hash(requestId, legacyType, networkCapabilities, type); } } diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 141af3d4956337e3bdcbed01f842bdd49a629827..35e3065b078f05cc418181bdfb47fba9784f2042 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -45,12 +45,19 @@ public class NetworkUtils { public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException; /** - * Attaches a socket filter that accepts ICMP6 router advertisement packets to the given socket. + * Attaches a socket filter that accepts ICMPv6 router advertisements to the given socket. * @param fd the socket's {@link FileDescriptor}. * @param packetType the hardware address type, one of ARPHRD_*. */ public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException; + /** + * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements. + * @param fd the socket's {@link FileDescriptor}. + * @param ifIndex the interface index. + */ + public native static void setupRaSocket(FileDescriptor fd, int ifIndex) throws SocketException; + /** * Binds the current process to the network designated by {@code netId}. All sockets created * in the future (and not explicitly bound via a bound {@link SocketFactory} (see diff --git a/core/java/android/net/metrics/ApfProgramEvent.java b/core/java/android/net/metrics/ApfProgramEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..258d8e13951fadee7e731587f4361f559f913b97 --- /dev/null +++ b/core/java/android/net/metrics/ApfProgramEvent.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.metrics; + +import android.annotation.IntDef; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; +import android.util.SparseArray; + +import com.android.internal.util.MessageUtils; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.List; + +/** + * An event logged when there is a change or event that requires updating the + * the APF program in place with a new APF program. + * {@hide} + */ +@SystemApi +public final class ApfProgramEvent implements Parcelable { + + // Bitflag constants describing what an Apf program filters. + // Bits are indexeds from LSB to MSB, starting at index 0. + public static final int FLAG_MULTICAST_FILTER_ON = 0; + public static final int FLAG_HAS_IPV4_ADDRESS = 1; + + /** {@hide} */ + @IntDef(flag = true, value = {FLAG_MULTICAST_FILTER_ON, FLAG_HAS_IPV4_ADDRESS}) + @Retention(RetentionPolicy.SOURCE) + public @interface Flags {} + + public final long lifetime; // Lifetime of the program in seconds + public final int filteredRas; // Number of RAs filtered by the APF program + public final int currentRas; // Total number of current RAs at generation time + public final int programLength; // Length of the APF program in bytes + public final int flags; // Bitfield compound of FLAG_* constants + + /** {@hide} */ + public ApfProgramEvent( + long lifetime, int filteredRas, int currentRas, int programLength, @Flags int flags) { + this.lifetime = lifetime; + this.filteredRas = filteredRas; + this.currentRas = currentRas; + this.programLength = programLength; + this.flags = flags; + } + + private ApfProgramEvent(Parcel in) { + this.lifetime = in.readLong(); + this.filteredRas = in.readInt(); + this.currentRas = in.readInt(); + this.programLength = in.readInt(); + this.flags = in.readInt(); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeLong(lifetime); + out.writeInt(filteredRas); + out.writeInt(currentRas); + out.writeInt(programLength); + out.writeInt(flags); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + String lifetimeString = (lifetime < Long.MAX_VALUE) ? lifetime + "s" : "forever"; + return String.format("ApfProgramEvent(%d/%d RAs %dB %s %s)", + filteredRas, currentRas, programLength, lifetimeString, namesOf(flags)); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public ApfProgramEvent createFromParcel(Parcel in) { + return new ApfProgramEvent(in); + } + + public ApfProgramEvent[] newArray(int size) { + return new ApfProgramEvent[size]; + } + }; + + /** {@hide} */ + public static @Flags int flagsFor(boolean hasIPv4, boolean multicastFilterOn) { + int bitfield = 0; + if (hasIPv4) { + bitfield |= (1 << FLAG_HAS_IPV4_ADDRESS); + } + if (multicastFilterOn) { + bitfield |= (1 << FLAG_MULTICAST_FILTER_ON); + } + return bitfield; + } + + private static String namesOf(@Flags int bitfield) { + List names = new ArrayList<>(Integer.bitCount(bitfield)); + BitSet set = BitSet.valueOf(new long[]{bitfield & Integer.MAX_VALUE}); + // Only iterate over flag bits which are set. + for (int bit = set.nextSetBit(0); bit >= 0; bit = set.nextSetBit(bit+1)) { + names.add(Decoder.constants.get(bit)); + } + return TextUtils.join("|", names); + } + + final static class Decoder { + static final SparseArray constants = + MessageUtils.findMessageNames( + new Class[]{ApfProgramEvent.class}, new String[]{"FLAG_"}); + } +} diff --git a/core/java/android/net/metrics/ApfStats.java b/core/java/android/net/metrics/ApfStats.java new file mode 100644 index 0000000000000000000000000000000000000000..8451e539a7f677beb71c293a1c5d0d321c4fbbed --- /dev/null +++ b/core/java/android/net/metrics/ApfStats.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.metrics; + +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * An event logged for an interface with APF capabilities when its IpManager state machine exits. + * {@hide} + */ +@SystemApi +public final class ApfStats implements Parcelable { + + public final long durationMs; // time interval in milliseconds these stastistics covers + public final int receivedRas; // number of received RAs + public final int matchingRas; // number of received RAs matching a known RA + public final int droppedRas; // number of received RAs ignored due to the MAX_RAS limit + public final int zeroLifetimeRas; // number of received RAs with a minimum lifetime of 0 + public final int parseErrors; // number of received RAs that could not be parsed + public final int programUpdates; // number of APF program updates + public final int maxProgramSize; // maximum APF program size advertised by hardware + + /** {@hide} */ + public ApfStats(long durationMs, int receivedRas, int matchingRas, int droppedRas, + int zeroLifetimeRas, int parseErrors, int programUpdates, int maxProgramSize) { + this.durationMs = durationMs; + this.receivedRas = receivedRas; + this.matchingRas = matchingRas; + this.droppedRas = droppedRas; + this.zeroLifetimeRas = zeroLifetimeRas; + this.parseErrors = parseErrors; + this.programUpdates = programUpdates; + this.maxProgramSize = maxProgramSize; + } + + private ApfStats(Parcel in) { + this.durationMs = in.readLong(); + this.receivedRas = in.readInt(); + this.matchingRas = in.readInt(); + this.droppedRas = in.readInt(); + this.zeroLifetimeRas = in.readInt(); + this.parseErrors = in.readInt(); + this.programUpdates = in.readInt(); + this.maxProgramSize = in.readInt(); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeLong(durationMs); + out.writeInt(receivedRas); + out.writeInt(matchingRas); + out.writeInt(droppedRas); + out.writeInt(zeroLifetimeRas); + out.writeInt(parseErrors); + out.writeInt(programUpdates); + out.writeInt(maxProgramSize); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + return new StringBuilder("ApfStats(") + .append(String.format("%dms ", durationMs)) + .append(String.format("%dB RA: {", maxProgramSize)) + .append(String.format("%d received, ", receivedRas)) + .append(String.format("%d matching, ", matchingRas)) + .append(String.format("%d dropped, ", droppedRas)) + .append(String.format("%d zero lifetime, ", zeroLifetimeRas)) + .append(String.format("%d parse errors, ", parseErrors)) + .append(String.format("%d program updates})", programUpdates)) + .toString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public ApfStats createFromParcel(Parcel in) { + return new ApfStats(in); + } + + public ApfStats[] newArray(int size) { + return new ApfStats[size]; + } + }; +} diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java index f8b59925cb9105b76610e107faf1672ca7b0dd27..9f0bad7ee9fe2d96d564f9462cac628425871d42 100644 --- a/core/java/android/net/metrics/DefaultNetworkEvent.java +++ b/core/java/android/net/metrics/DefaultNetworkEvent.java @@ -22,10 +22,11 @@ import android.os.Parcel; import android.os.Parcelable; /** + * An event recorded by ConnectivityService when there is a change in the default network. * {@hide} */ @SystemApi -public final class DefaultNetworkEvent extends IpConnectivityEvent implements Parcelable { +public final class DefaultNetworkEvent implements Parcelable { // The ID of the network that has become the new default or NETID_UNSET if none. public final int netId; // The list of transport types of the new default network, for example TRANSPORT_WIFI, as @@ -37,7 +38,8 @@ public final class DefaultNetworkEvent extends IpConnectivityEvent implements Pa public final boolean prevIPv4; public final boolean prevIPv6; - private DefaultNetworkEvent(int netId, int[] transportTypes, + /** {@hide} */ + public DefaultNetworkEvent(int netId, int[] transportTypes, int prevNetId, boolean prevIPv4, boolean prevIPv6) { this.netId = netId; this.transportTypes = transportTypes; @@ -54,6 +56,7 @@ public final class DefaultNetworkEvent extends IpConnectivityEvent implements Pa this.prevIPv6 = (in.readByte() > 0); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(netId); out.writeIntArray(transportTypes); @@ -62,6 +65,7 @@ public final class DefaultNetworkEvent extends IpConnectivityEvent implements Pa out.writeByte(prevIPv6 ? (byte) 1 : (byte) 0); } + @Override public int describeContents() { return 0; } @@ -105,6 +109,5 @@ public final class DefaultNetworkEvent extends IpConnectivityEvent implements Pa public static void logEvent( int netId, int[] transports, int prevNetId, boolean hadIPv4, boolean hadIPv6) { - logEvent(new DefaultNetworkEvent(netId, transports, prevNetId, hadIPv4, hadIPv6)); } -}; +} diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java index ec560bf64ccc3d2ac250a39728d2798f8a00594c..4a9ff051124699380047033cde83df45295618e3 100644 --- a/core/java/android/net/metrics/DhcpClientEvent.java +++ b/core/java/android/net/metrics/DhcpClientEvent.java @@ -21,35 +21,50 @@ import android.os.Parcel; import android.os.Parcelable; /** + * An event recorded when a DhcpClient state machine transitions to a new state. * {@hide} */ @SystemApi -public final class DhcpClientEvent extends IpConnectivityEvent implements Parcelable { +public final class DhcpClientEvent implements Parcelable { + + // Names for recording DhcpClient pseudo-state transitions. + /** {@hide} Represents transitions from DhcpInitState to DhcpBoundState */ + public static final String INITIAL_BOUND = "InitialBoundState"; + /** {@hide} Represents transitions from and to DhcpBoundState via DhcpRenewingState */ + public static final String RENEWING_BOUND = "RenewingBoundState"; + public final String ifName; public final String msg; + public final int durationMs; - private DhcpClientEvent(String ifName, String msg) { + /** {@hide} */ + public DhcpClientEvent(String ifName, String msg, int durationMs) { this.ifName = ifName; this.msg = msg; + this.durationMs = durationMs; } private DhcpClientEvent(Parcel in) { this.ifName = in.readString(); this.msg = in.readString(); + this.durationMs = in.readInt(); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeString(ifName); out.writeString(msg); + out.writeInt(durationMs); } + @Override public int describeContents() { return 0; } @Override public String toString() { - return String.format("DhcpClientEvent(%s, %s)", ifName, msg); + return String.format("DhcpClientEvent(%s, %s, %dms)", ifName, msg, durationMs); } public static final Parcelable.Creator CREATOR @@ -64,6 +79,5 @@ public final class DhcpClientEvent extends IpConnectivityEvent implements Parcel }; public static void logStateEvent(String ifName, String state) { - logEvent(new DhcpClientEvent(ifName, state)); } -}; +} diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java index 84795b89bb6b0369ef4b0c87514f2b14f7429fa1..c3abcf7610b4e420bb458d41aae7972c0c898624 100644 --- a/core/java/android/net/metrics/DhcpErrorEvent.java +++ b/core/java/android/net/metrics/DhcpErrorEvent.java @@ -24,10 +24,11 @@ import android.util.SparseArray; import com.android.internal.util.MessageUtils; /** - * {@hide} Event class used to record error events when parsing DHCP response packets. + * Event class used to record error events when parsing DHCP response packets. + * {@hide} */ @SystemApi -public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcelable { +public final class DhcpErrorEvent implements Parcelable { public static final int L2_ERROR = 1; public static final int L3_ERROR = 2; public static final int L4_ERROR = 3; @@ -49,9 +50,13 @@ public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcela public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3); public static final int DHCP_NO_MSG_TYPE = makeErrorCode(DHCP_ERROR, 4); public static final int DHCP_UNKNOWN_MSG_TYPE = makeErrorCode(DHCP_ERROR, 5); + /** {@hide} */ + public static final int DHCP_NO_COOKIE = makeErrorCode(DHCP_ERROR, 6); public static final int BUFFER_UNDERFLOW = makeErrorCode(MISC_ERROR, 1); public static final int RECEIVE_ERROR = makeErrorCode(MISC_ERROR, 2); + /** {@hide} */ + public static final int PARSING_ERROR = makeErrorCode(MISC_ERROR, 3); public final String ifName; // error code byte format (MSB to LSB): @@ -61,7 +66,8 @@ public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcela // byte 3: optional code public final int errorCode; - private DhcpErrorEvent(String ifName, int errorCode) { + /** {@hide} */ + public DhcpErrorEvent(String ifName, int errorCode) { this.ifName = ifName; this.errorCode = errorCode; } @@ -71,11 +77,13 @@ public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcela this.errorCode = in.readInt(); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeString(ifName); out.writeInt(errorCode); } + @Override public int describeContents() { return 0; } @@ -92,11 +100,9 @@ public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcela }; public static void logParseError(String ifName, int errorCode) { - logEvent(new DhcpErrorEvent(ifName, errorCode)); } public static void logReceiveError(String ifName) { - logEvent(new DhcpErrorEvent(ifName, RECEIVE_ERROR)); } public static int errorCodeWithOption(int errorCode, int option) { @@ -113,8 +119,9 @@ public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcela } final static class Decoder { - static final SparseArray constants = - MessageUtils.findMessageNames(new Class[]{DhcpErrorEvent.class}, - new String[]{"L2_", "L3_", "L4_", "BOOTP_", "DHCP_", "BUFFER_", "RECEIVE_"}); + static final SparseArray constants = MessageUtils.findMessageNames( + new Class[]{DhcpErrorEvent.class}, + new String[]{"L2_", "L3_", "L4_", "BOOTP_", "DHCP_", "BUFFER_", "RECEIVE_", + "PARSING_"}); } } diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java index b94dda079cd8efddabc235e05f7f9f4fc697c9df..6176b2c58deb40deb41b299a20509366685dbbb3 100644 --- a/core/java/android/net/metrics/DnsEvent.java +++ b/core/java/android/net/metrics/DnsEvent.java @@ -21,10 +21,11 @@ import android.os.Parcel; import android.os.Parcelable; /** + * A DNS event recorded by NetdEventListenerService. * {@hide} */ @SystemApi -final public class DnsEvent extends IpConnectivityEvent implements Parcelable { +final public class DnsEvent implements Parcelable { public final int netId; // The event type is currently only 1 or 2, so we store it as a byte. @@ -37,7 +38,8 @@ final public class DnsEvent extends IpConnectivityEvent implements Parcelable { // queries. public final int[] latenciesMs; - private DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) { + /** {@hide} */ + public DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) { this.netId = netId; this.eventTypes = eventTypes; this.returnCodes = returnCodes; @@ -59,6 +61,7 @@ final public class DnsEvent extends IpConnectivityEvent implements Parcelable { out.writeIntArray(latenciesMs); } + @Override public int describeContents() { return 0; } @@ -82,6 +85,5 @@ final public class DnsEvent extends IpConnectivityEvent implements Parcelable { public static void logEvent( int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) { - logEvent(new DnsEvent(netId, eventTypes, returnCodes, latenciesMs)); } } diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java new file mode 100644 index 0000000000000000000000000000000000000000..173e5fd0fbc179c04d9eb38565580bd31ca1f58d --- /dev/null +++ b/core/java/android/net/metrics/IpConnectivityLog.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.metrics; + +import android.net.ConnectivityMetricsEvent; +import android.net.IIpConnectivityMetrics; +import android.os.Parcelable; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + +/** + * Class for logging IpConnectvity events with IpConnectivityMetrics + * {@hide} + */ +public class IpConnectivityLog { + private static final String TAG = IpConnectivityLog.class.getSimpleName(); + private static final boolean DBG = false; + + public static final String SERVICE_NAME = "connmetrics"; + + private IIpConnectivityMetrics mService; + + public IpConnectivityLog() { + } + + @VisibleForTesting + public IpConnectivityLog(IIpConnectivityMetrics service) { + mService = service; + } + + private boolean checkLoggerService() { + if (mService != null) { + return true; + } + final IIpConnectivityMetrics service = + IIpConnectivityMetrics.Stub.asInterface(ServiceManager.getService(SERVICE_NAME)); + if (service == null) { + return false; + } + // Two threads racing here will write the same pointer because getService + // is idempotent once MetricsLoggerService is initialized. + mService = service; + return true; + } + + /** + * Log an IpConnectivity event. + * @param timestamp is the epoch timestamp of the event in ms. + * @param data is a Parcelable instance representing the event. + * @return true if the event was successfully logged. + */ + public boolean log(long timestamp, Parcelable data) { + if (!checkLoggerService()) { + if (DBG) { + Log.d(TAG, SERVICE_NAME + " service was not ready"); + } + return false; + } + + try { + int left = mService.logEvent(new ConnectivityMetricsEvent(timestamp, 0, 0, data)); + return left >= 0; + } catch (RemoteException e) { + Log.e(TAG, "Error logging event", e); + return false; + } + } + + public void log(Parcelable event) { + log(System.currentTimeMillis(), event); + } +} diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java index 0940bd06c3d34587923dacbeb093b7c6b9b0e7d7..a5b4eb5aff86f7920c3e28bb5de7b770e5317333 100644 --- a/core/java/android/net/metrics/IpManagerEvent.java +++ b/core/java/android/net/metrics/IpManagerEvent.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.IntDef; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -23,21 +24,32 @@ import android.util.SparseArray; import com.android.internal.util.MessageUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** + * An event recorded by IpManager when IP provisioning completes for a network or + * when a network disconnects. * {@hide} */ @SystemApi -public final class IpManagerEvent extends IpConnectivityEvent implements Parcelable { +public final class IpManagerEvent implements Parcelable { public static final int PROVISIONING_OK = 1; public static final int PROVISIONING_FAIL = 2; public static final int COMPLETE_LIFECYCLE = 3; + /** {@hide} */ + @IntDef(value = {PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE}) + @Retention(RetentionPolicy.SOURCE) + public @interface EventType {} + public final String ifName; - public final int eventType; + public final @EventType int eventType; public final long durationMs; - private IpManagerEvent(String ifName, int eventType, long duration) { + /** {@hide} */ + public IpManagerEvent(String ifName, @EventType int eventType, long duration) { this.ifName = ifName; this.eventType = eventType; this.durationMs = duration; @@ -49,12 +61,14 @@ public final class IpManagerEvent extends IpConnectivityEvent implements Parcela this.durationMs = in.readLong(); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeString(ifName); out.writeInt(eventType); out.writeLong(durationMs); } + @Override public int describeContents() { return 0; } @@ -71,7 +85,6 @@ public final class IpManagerEvent extends IpConnectivityEvent implements Parcela }; public static void logEvent(int eventType, String ifName, long durationMs) { - logEvent(new IpManagerEvent(ifName, eventType, durationMs)); } @Override @@ -84,4 +97,4 @@ public final class IpManagerEvent extends IpConnectivityEvent implements Parcela static final SparseArray constants = MessageUtils.findMessageNames( new Class[]{IpManagerEvent.class}, new String[]{"PROVISIONING_", "COMPLETE_"}); } -}; +} diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java index d40389c03986712c6ca9953081cdc9066242c274..ee09e229266164b301742de36590d9ba5d6c1ad1 100644 --- a/core/java/android/net/metrics/IpReachabilityEvent.java +++ b/core/java/android/net/metrics/IpReachabilityEvent.java @@ -24,24 +24,35 @@ import android.util.SparseArray; import com.android.internal.util.MessageUtils; /** + * An event recorded when IpReachabilityMonitor sends a neighbor probe or receives + * a neighbor probe result. * {@hide} */ @SystemApi -public final class IpReachabilityEvent extends IpConnectivityEvent implements Parcelable { - - public static final int PROBE = 1 << 8; - public static final int NUD_FAILED = 2 << 8; - public static final int PROVISIONING_LOST = 3 << 8; +public final class IpReachabilityEvent implements Parcelable { + + // Event types. + /** A probe forced by IpReachabilityMonitor. */ + public static final int PROBE = 1 << 8; + /** Neighbor unreachable after a forced probe. */ + public static final int NUD_FAILED = 2 << 8; + /** Neighbor unreachable after a forced probe, IP provisioning is also lost. */ + public static final int PROVISIONING_LOST = 3 << 8; + /** {@hide} Neighbor unreachable notification from kernel. */ + public static final int NUD_FAILED_ORGANIC = 4 << 8; + /** {@hide} Neighbor unreachable notification from kernel, IP provisioning is also lost. */ + public static final int PROVISIONING_LOST_ORGANIC = 5 << 8; public final String ifName; // eventType byte format (MSB to LSB): // byte 0: unused // byte 1: unused // byte 2: type of event: PROBE, NUD_FAILED, PROVISIONING_LOST - // byte 3: kernel errno from RTNetlink or IpReachabilityMonitor + // byte 3: when byte 2 == PROBE, errno code from RTNetlink or IpReachabilityMonitor. public final int eventType; - private IpReachabilityEvent(String ifName, int eventType) { + /** {@hide} */ + public IpReachabilityEvent(String ifName, int eventType) { this.ifName = ifName; this.eventType = eventType; } @@ -51,11 +62,13 @@ public final class IpReachabilityEvent extends IpConnectivityEvent implements Pa this.eventType = in.readInt(); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeString(ifName); out.writeInt(eventType); } + @Override public int describeContents() { return 0; } @@ -72,21 +85,32 @@ public final class IpReachabilityEvent extends IpConnectivityEvent implements Pa }; public static void logProbeEvent(String ifName, int nlErrorCode) { - logEvent(new IpReachabilityEvent(ifName, PROBE | (nlErrorCode & 0xFF))); } public static void logNudFailed(String ifName) { - logEvent(new IpReachabilityEvent(ifName, NUD_FAILED)); } public static void logProvisioningLost(String ifName) { - logEvent(new IpReachabilityEvent(ifName, PROVISIONING_LOST)); + } + + /** + * Returns the NUD failure event type code corresponding to the given conditions. + * {@hide} + */ + public static int nudFailureEventType(boolean isFromProbe, boolean isProvisioningLost) { + if (isFromProbe) { + return isProvisioningLost ? PROVISIONING_LOST : NUD_FAILED; + } else { + return isProvisioningLost ? PROVISIONING_LOST_ORGANIC : NUD_FAILED_ORGANIC; + } } @Override public String toString() { - return String.format("IpReachabilityEvent(%s, %s)", ifName, - Decoder.constants.get(eventType)); + int hi = eventType & 0xff00; + int lo = eventType & 0x00ff; + String eventName = Decoder.constants.get(hi); + return String.format("IpReachabilityEvent(%s, %s:%02x)", ifName, eventName, lo); } final static class Decoder { @@ -94,4 +118,4 @@ public final class IpReachabilityEvent extends IpConnectivityEvent implements Pa MessageUtils.findMessageNames(new Class[]{IpReachabilityEvent.class}, new String[]{"PROBE", "PROVISIONING_", "NUD_"}); } -}; +} diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java index 08c9c758bbc8696aa04b76626c8b9719413a971e..3b3fa6976fc982181a7ee57103b47b62ef00bf93 100644 --- a/core/java/android/net/metrics/NetworkEvent.java +++ b/core/java/android/net/metrics/NetworkEvent.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.IntDef; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -23,11 +24,14 @@ import android.util.SparseArray; import com.android.internal.util.MessageUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * {@hide} */ @SystemApi -public final class NetworkEvent extends IpConnectivityEvent implements Parcelable { +public final class NetworkEvent implements Parcelable { public static final int NETWORK_CONNECTED = 1; public static final int NETWORK_VALIDATED = 2; @@ -37,28 +41,49 @@ public final class NetworkEvent extends IpConnectivityEvent implements Parcelabl public static final int NETWORK_UNLINGER = 6; public static final int NETWORK_DISCONNECTED = 7; + /** {@hide} */ + @IntDef(value = { + NETWORK_CONNECTED, + NETWORK_VALIDATED, + NETWORK_VALIDATION_FAILED, + NETWORK_CAPTIVE_PORTAL_FOUND, + NETWORK_LINGER, + NETWORK_UNLINGER, + NETWORK_DISCONNECTED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EventType {} + public final int netId; - public final int eventType; + public final @EventType int eventType; public final long durationMs; - private NetworkEvent(int netId, int eventType, long durationMs) { + /** {@hide} */ + public NetworkEvent(int netId, @EventType int eventType, long durationMs) { this.netId = netId; this.eventType = eventType; this.durationMs = durationMs; } + /** {@hide} */ + public NetworkEvent(int netId, @EventType int eventType) { + this(netId, eventType, 0); + } + private NetworkEvent(Parcel in) { netId = in.readInt(); eventType = in.readInt(); durationMs = in.readLong(); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(netId); out.writeInt(eventType); out.writeLong(durationMs); } + @Override public int describeContents() { return 0; } @@ -75,15 +100,12 @@ public final class NetworkEvent extends IpConnectivityEvent implements Parcelabl }; public static void logEvent(int netId, int eventType) { - logEvent(new NetworkEvent(netId, eventType, 0)); } public static void logValidated(int netId, long durationMs) { - logEvent(new NetworkEvent(netId, NETWORK_VALIDATED, durationMs)); } public static void logCaptivePortalFound(int netId, long durationMs) { - logEvent(new NetworkEvent(netId, NETWORK_CAPTIVE_PORTAL_FOUND, durationMs)); } @Override @@ -96,4 +118,4 @@ public final class NetworkEvent extends IpConnectivityEvent implements Parcelabl static final SparseArray constants = MessageUtils.findMessageNames( new Class[]{NetworkEvent.class}, new String[]{"NETWORK_"}); } -}; +} diff --git a/core/java/android/net/metrics/RaEvent.java b/core/java/android/net/metrics/RaEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..91bd023cd56cb19033a1337139747db98130702b --- /dev/null +++ b/core/java/android/net/metrics/RaEvent.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.metrics; + +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * An event logged when the APF packet socket receives an RA packet. + * {@hide} + */ +@SystemApi +public final class RaEvent implements Parcelable { + + /** {@hide} */ + public static final long NO_LIFETIME = -1L; + + // Lifetime in seconds of options found in a single RA packet. + // When an option is not set, the value of the associated field is -1; + public final long routerLifetime; + public final long prefixValidLifetime; + public final long prefixPreferredLifetime; + public final long routeInfoLifetime; + public final long rdnssLifetime; + public final long dnsslLifetime; + + /** {@hide} */ + public RaEvent(long routerLifetime, long prefixValidLifetime, long prefixPreferredLifetime, + long routeInfoLifetime, long rdnssLifetime, long dnsslLifetime) { + this.routerLifetime = routerLifetime; + this.prefixValidLifetime = prefixValidLifetime; + this.prefixPreferredLifetime = prefixPreferredLifetime; + this.routeInfoLifetime = routeInfoLifetime; + this.rdnssLifetime = rdnssLifetime; + this.dnsslLifetime = dnsslLifetime; + } + + private RaEvent(Parcel in) { + routerLifetime = in.readLong(); + prefixValidLifetime = in.readLong(); + prefixPreferredLifetime = in.readLong(); + routeInfoLifetime = in.readLong(); + rdnssLifetime = in.readLong(); + dnsslLifetime = in.readLong(); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeLong(routerLifetime); + out.writeLong(prefixValidLifetime); + out.writeLong(prefixPreferredLifetime); + out.writeLong(routeInfoLifetime); + out.writeLong(rdnssLifetime); + out.writeLong(dnsslLifetime); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + return new StringBuilder("RaEvent(lifetimes: ") + .append(String.format("router=%ds, ", routerLifetime)) + .append(String.format("prefix_valid=%ds, ", prefixValidLifetime)) + .append(String.format("prefix_preferred=%ds, ", prefixPreferredLifetime)) + .append(String.format("route_info=%ds, ", routeInfoLifetime)) + .append(String.format("rdnss=%ds, ", rdnssLifetime)) + .append(String.format("dnssl=%ds)", dnsslLifetime)) + .toString(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public RaEvent createFromParcel(Parcel in) { + return new RaEvent(in); + } + + public RaEvent[] newArray(int size) { + return new RaEvent[size]; + } + }; + + /** {@hide} */ + public static class Builder { + + long routerLifetime = NO_LIFETIME; + long prefixValidLifetime = NO_LIFETIME; + long prefixPreferredLifetime = NO_LIFETIME; + long routeInfoLifetime = NO_LIFETIME; + long rdnssLifetime = NO_LIFETIME; + long dnsslLifetime = NO_LIFETIME; + + public Builder() { + } + + public RaEvent build() { + return new RaEvent(routerLifetime, prefixValidLifetime, prefixPreferredLifetime, + routeInfoLifetime, rdnssLifetime, dnsslLifetime); + } + + public Builder updateRouterLifetime(long lifetime) { + routerLifetime = updateLifetime(routerLifetime, lifetime); + return this; + } + + public Builder updatePrefixValidLifetime(long lifetime) { + prefixValidLifetime = updateLifetime(prefixValidLifetime, lifetime); + return this; + } + + public Builder updatePrefixPreferredLifetime(long lifetime) { + prefixPreferredLifetime = updateLifetime(prefixPreferredLifetime, lifetime); + return this; + } + + public Builder updateRouteInfoLifetime(long lifetime) { + routeInfoLifetime = updateLifetime(routeInfoLifetime, lifetime); + return this; + } + + public Builder updateRdnssLifetime(long lifetime) { + rdnssLifetime = updateLifetime(rdnssLifetime, lifetime); + return this; + } + + public Builder updateDnsslLifetime(long lifetime) { + dnsslLifetime = updateLifetime(dnsslLifetime, lifetime); + return this; + } + + private long updateLifetime(long currentLifetime, long newLifetime) { + if (currentLifetime == RaEvent.NO_LIFETIME) { + return newLifetime; + } + return Math.min(currentLifetime, newLifetime); + } + } +} diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java index 751c35f8a1443c5a7c63d140fa1c81b0cc3c6cdf..1a31b56f1ffb62f8a46d51af360e1ecb17b7ba68 100644 --- a/core/java/android/net/metrics/ValidationProbeEvent.java +++ b/core/java/android/net/metrics/ValidationProbeEvent.java @@ -16,6 +16,7 @@ package android.net.metrics; +import android.annotation.IntDef; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -23,26 +24,44 @@ import android.util.SparseArray; import com.android.internal.util.MessageUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** + * An event recorded by NetworkMonitor when sending a probe for finding captive portals. * {@hide} */ @SystemApi -public final class ValidationProbeEvent extends IpConnectivityEvent implements Parcelable { +public final class ValidationProbeEvent implements Parcelable { - public static final int PROBE_DNS = 0; - public static final int PROBE_HTTP = 1; - public static final int PROBE_HTTPS = 2; - public static final int PROBE_PAC = 3; + public static final int PROBE_DNS = 0; + public static final int PROBE_HTTP = 1; + public static final int PROBE_HTTPS = 2; + public static final int PROBE_PAC = 3; + /** {@hide} */ + public static final int PROBE_FALLBACK = 4; public static final int DNS_FAILURE = 0; public static final int DNS_SUCCESS = 1; + /** {@hide} */ + @IntDef(value = {PROBE_DNS, PROBE_HTTP, PROBE_HTTPS, PROBE_PAC}) + @Retention(RetentionPolicy.SOURCE) + public @interface ProbeType {} + + /** {@hide} */ + @IntDef(value = {DNS_FAILURE, DNS_SUCCESS}) + @Retention(RetentionPolicy.SOURCE) + public @interface ReturnCode {} + public final int netId; public final long durationMs; - public final int probeType; - public final int returnCode; + public final @ProbeType int probeType; + public final @ReturnCode int returnCode; - private ValidationProbeEvent(int netId, long durationMs, int probeType, int returnCode) { + /** {@hide} */ + public ValidationProbeEvent( + int netId, long durationMs, @ProbeType int probeType, @ReturnCode int returnCode) { this.netId = netId; this.durationMs = durationMs; this.probeType = probeType; @@ -56,6 +75,7 @@ public final class ValidationProbeEvent extends IpConnectivityEvent implements P returnCode = in.readInt(); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(netId); out.writeLong(durationMs); @@ -63,6 +83,7 @@ public final class ValidationProbeEvent extends IpConnectivityEvent implements P out.writeInt(returnCode); } + @Override public int describeContents() { return 0; } @@ -84,7 +105,6 @@ public final class ValidationProbeEvent extends IpConnectivityEvent implements P } public static void logEvent(int netId, long durationMs, int probeType, int returnCode) { - logEvent(new ValidationProbeEvent(netId, durationMs, probeType, returnCode)); } @Override @@ -97,4 +117,4 @@ public final class ValidationProbeEvent extends IpConnectivityEvent implements P static final SparseArray constants = MessageUtils.findMessageNames( new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"}); } -}; +} diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 41ff9fdf8382b9067c3188d630914bebf1e4ce2a..783c25aa4d08502df6b15cc3623cb994659b5136 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -290,6 +290,7 @@ public final class NfcAdapter { // Guarded by NfcAdapter.class static boolean sIsInitialized = false; + static boolean sHasNfcFeature; // Final after first constructor, except for // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort @@ -434,6 +435,26 @@ public final class NfcAdapter { } } + /** + * Helper to check if this device is NFC HCE capable, by checking for + * FEATURE_NFC_HOST_CARD_EMULATION and/or FEATURE_NFC_HOST_CARD_EMULATION_NFCF, + * but without using a context. + */ + private static boolean hasNfcHceFeature() { + IPackageManager pm = ActivityThread.getPackageManager(); + if (pm == null) { + Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); + return false; + } + try { + return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0) + || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0); + } catch (RemoteException e) { + Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); + return false; + } + } + /** * Returns the NfcAdapter for application context, * or throws if NFC is not available. @@ -441,36 +462,39 @@ public final class NfcAdapter { */ public static synchronized NfcAdapter getNfcAdapter(Context context) { if (!sIsInitialized) { + sHasNfcFeature = hasNfcFeature(); + boolean hasHceFeature = hasNfcHceFeature(); /* is this device meant to have NFC */ - if (!hasNfcFeature()) { + if (!sHasNfcFeature && !hasHceFeature) { Log.v(TAG, "this device does not have NFC support"); throw new UnsupportedOperationException(); } - sService = getServiceInterface(); if (sService == null) { Log.e(TAG, "could not retrieve NFC service"); throw new UnsupportedOperationException(); } - try { - sTagService = sService.getNfcTagInterface(); - } catch (RemoteException e) { - Log.e(TAG, "could not retrieve NFC Tag service"); - throw new UnsupportedOperationException(); - } - - try { - sCardEmulationService = sService.getNfcCardEmulationInterface(); - } catch (RemoteException e) { - Log.e(TAG, "could not retrieve card emulation service"); - throw new UnsupportedOperationException(); + if (sHasNfcFeature) { + try { + sTagService = sService.getNfcTagInterface(); + } catch (RemoteException e) { + Log.e(TAG, "could not retrieve NFC Tag service"); + throw new UnsupportedOperationException(); + } } - - try { - sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface(); - } catch (RemoteException e) { - Log.e(TAG, "could not retrieve NFC-F card emulation service"); - throw new UnsupportedOperationException(); + if (hasHceFeature) { + try { + sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface(); + } catch (RemoteException e) { + Log.e(TAG, "could not retrieve NFC-F card emulation service"); + throw new UnsupportedOperationException(); + } + try { + sCardEmulationService = sService.getNfcCardEmulationInterface(); + } catch (RemoteException e) { + Log.e(TAG, "could not retrieve card emulation service"); + throw new UnsupportedOperationException(); + } } sIsInitialized = true; @@ -838,8 +862,14 @@ public final class NfcAdapter { * * @param uris an array of Uri(s) to push over Android Beam * @param activity activity for which the Uri(s) will be pushed + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void setBeamPushUris(Uri[] uris, Activity activity) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } if (activity == null) { throw new NullPointerException("activity cannot be null"); } @@ -914,8 +944,14 @@ public final class NfcAdapter { * * @param callback callback, or null to disable * @param activity activity for which the Uri(s) will be pushed + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } if (activity == null) { throw new NullPointerException("activity cannot be null"); } @@ -992,9 +1028,15 @@ public final class NfcAdapter { * @param activities optional additional activities, however we strongly recommend * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void setNdefPushMessage(NdefMessage message, Activity activity, Activity ... activities) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } int targetSdkVersion = getSdkVersion(); try { if (activity == null) { @@ -1024,6 +1066,11 @@ public final class NfcAdapter { */ @SystemApi public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } if (activity == null) { throw new NullPointerException("activity cannot be null"); } @@ -1094,9 +1141,15 @@ public final class NfcAdapter { * @param activities optional additional activities, however we strongly recommend * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, Activity ... activities) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } int targetSdkVersion = getSdkVersion(); try { if (activity == null) { @@ -1168,9 +1221,15 @@ public final class NfcAdapter { * @param activities optional additional activities, however we strongly recommend * to only register one at a time, and to do so in that activity's * {@link Activity#onCreate} + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback, Activity activity, Activity ... activities) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } int targetSdkVersion = getSdkVersion(); try { if (activity == null) { @@ -1227,9 +1286,15 @@ public final class NfcAdapter { * @param techLists the tech lists used to perform matching for dispatching of the * {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent * @throws IllegalStateException if the Activity is not currently in the foreground + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void enableForegroundDispatch(Activity activity, PendingIntent intent, IntentFilter[] filters, String[][] techLists) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } if (activity == null || intent == null) { throw new NullPointerException(); } @@ -1263,8 +1328,14 @@ public final class NfcAdapter { * * @param activity the Activity to disable dispatch to * @throws IllegalStateException if the Activity has already been paused + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void disableForegroundDispatch(Activity activity) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, mForegroundDispatchListener); disableForegroundDispatchInternal(activity, false); @@ -1309,9 +1380,15 @@ public final class NfcAdapter { * @param callback the callback to be called when a tag is discovered * @param flags Flags indicating poll technologies and other optional parameters * @param extras Additional extras for configuring reader mode. + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, Bundle extras) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } mNfcActivityManager.enableReaderMode(activity, callback, flags, extras); } @@ -1321,8 +1398,14 @@ public final class NfcAdapter { * all supported tag technologies. * * @param activity the Activity that currently has reader mode enabled + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public void disableReaderMode(Activity activity) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } mNfcActivityManager.disableReaderMode(activity); } @@ -1349,8 +1432,14 @@ public final class NfcAdapter { * * @param activity the current foreground Activity that has registered data to share * @return whether the Beam animation was successfully invoked + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public boolean invokeBeam(Activity activity) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } if (activity == null) { throw new NullPointerException("activity may not be null."); } @@ -1404,10 +1493,16 @@ public final class NfcAdapter { * @param activity foreground activity * @param message a NDEF Message to push over NFC * @throws IllegalStateException if the activity is not currently in the foreground + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. * @deprecated use {@link #setNdefPushMessage} instead */ @Deprecated public void enableForegroundNdefPush(Activity activity, NdefMessage message) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } if (activity == null || message == null) { throw new NullPointerException(); } @@ -1432,10 +1527,16 @@ public final class NfcAdapter { * * @param activity the Foreground activity * @throws IllegalStateException if the Activity has already been paused + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. * @deprecated use {@link #setNdefPushMessage} instead */ @Deprecated public void disableForegroundNdefPush(Activity activity) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } if (activity == null) { throw new NullPointerException(); } @@ -1452,6 +1553,9 @@ public final class NfcAdapter { */ @SystemApi public boolean enableNdefPush() { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } try { return sService.enableNdefPush(); } catch (RemoteException e) { @@ -1467,6 +1571,11 @@ public final class NfcAdapter { */ @SystemApi public boolean disableNdefPush() { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } try { return sService.disableNdefPush(); } catch (RemoteException e) { @@ -1497,8 +1606,14 @@ public final class NfcAdapter { * * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS * @return true if NDEF Push feature is enabled + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. */ public boolean isNdefPushEnabled() { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } try { return sService.isNdefPushEnabled(); } catch (RemoteException e) { @@ -1623,6 +1738,11 @@ public final class NfcAdapter { @SystemApi public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler, String[] tagTechnologies) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } // If there are no tag technologies, don't bother adding unlock handler if (tagTechnologies.length == 0) { return false; @@ -1666,6 +1786,11 @@ public final class NfcAdapter { */ @SystemApi public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } try { synchronized (mLock) { if (mNfcUnlockHandlers.containsKey(unlockHandler)) { diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index 63f39c59b1b7f0010eab71aa1a80c0486b189100..fea64ec5ee1eb9e1d24addeefc1160e994d8747e 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -35,8 +35,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; /** - *

AsyncTask enables proper and easy use of the UI thread. This class allows to - * perform background operations and publish results on the UI thread without + *

AsyncTask enables proper and easy use of the UI thread. This class allows you + * to perform background operations and publish results on the UI thread without * having to manipulate threads and/or handlers.

* *

AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} @@ -55,7 +55,7 @@ import java.util.concurrent.atomic.AtomicInteger; *

*

Developer Guides

*

For more information about using tasks and threads, read the - * Processes and + * Processes and * Threads developer guide.

*
* @@ -298,12 +298,19 @@ public abstract class AsyncTask { mWorker = new WorkerRunnable() { public Result call() throws Exception { mTaskInvoked.set(true); - - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - //noinspection unchecked - Result result = doInBackground(mParams); - Binder.flushPendingCommands(); - return postResult(result); + Result result = null; + try { + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + //noinspection unchecked + result = doInBackground(mParams); + Binder.flushPendingCommands(); + } catch (Throwable tr) { + mCancelled.set(true); + throw tr; + } finally { + postResult(result); + } + return result; } }; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 4acb729b6a76026adfaf001c44ad7e1bc507a47e..a0c2efd407ba0387936c732bf175ab7ec5bd41b3 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -30,6 +30,8 @@ import android.content.pm.ApplicationInfo; import android.telephony.SignalStrength; import android.text.format.DateFormat; import android.util.ArrayMap; +import android.util.Log; +import android.util.LongSparseArray; import android.util.MutableBoolean; import android.util.Pair; import android.util.Printer; @@ -47,6 +49,7 @@ import com.android.internal.os.BatteryStatsHelper; * @hide */ public abstract class BatteryStats implements Parcelable { + private static final String TAG = "BatteryStats"; private static final boolean LOCAL_LOGV = false; @@ -175,8 +178,11 @@ public abstract class BatteryStats implements Parcelable { /** * Current version of checkin data format. + * + * New in version 19: + * - Wakelock data (wl) gets current and max times. */ - static final String CHECKIN_VERSION = "18"; + static final String CHECKIN_VERSION = "19"; /** * Old version, we hit 9 and ran out of room, need to remove. @@ -351,6 +357,32 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getTimeSinceMarkLocked(long elapsedRealtimeUs); + /** + * Returns the max duration if it is being tracked. + * Not all Timer subclasses track the max duration and the current duration. + + */ + public long getMaxDurationMsLocked(long elapsedRealtimeMs) { + return -1; + } + + /** + * Returns the current time the timer has been active, if it is being tracked. + * Not all Timer subclasses track the max duration and the current duration. + */ + public long getCurrentDurationMsLocked(long elapsedRealtimeMs) { + return -1; + } + + /** + * Returns whether the timer is currently running. Some types of timers + * (e.g. BatchTimers) don't know whether the event is currently active, + * and report false. + */ + public boolean isRunningLocked() { + return false; + } + /** * Temporary for debugging. */ @@ -546,6 +578,20 @@ public abstract class BatteryStats implements Parcelable { */ public abstract long getTimeAtCpuSpeed(int cluster, int step, int which); + /** + * Returns the number of times this UID woke up the Application Processor to + * process a mobile radio packet. + * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. + */ + public abstract long getMobileRadioApWakeupCount(int which); + + /** + * Returns the number of times this UID woke up the Application Processor to + * process a WiFi packet. + * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. + */ + public abstract long getWifiRadioApWakeupCount(int which); + public static abstract class Sensor { /* * FIXME: it's not correct to use this magic value because it @@ -1285,9 +1331,14 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_TEMP_WHITELIST = 0x0011; // Event for the screen waking up. public static final int EVENT_SCREEN_WAKE_UP = 0x0012; + // Event for the UID that woke up the application processor. + // Used for wakeups coming from WiFi, modem, etc. + public static final int EVENT_WAKEUP_AP = 0x0013; + // Event for reporting that a specific partial wake lock has been held for a long duration. + public static final int EVENT_LONG_WAKE_LOCK = 0x0014; // Number of event types. - public static final int EVENT_COUNT = 0x0013; + public static final int EVENT_COUNT = 0x0015; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -1315,6 +1366,10 @@ public abstract class BatteryStats implements Parcelable { EVENT_TEMP_WHITELIST | EVENT_FLAG_START; public static final int EVENT_TEMP_WHITELIST_FINISH = EVENT_TEMP_WHITELIST | EVENT_FLAG_FINISH; + public static final int EVENT_LONG_WAKE_LOCK_START = + EVENT_LONG_WAKE_LOCK | EVENT_FLAG_START; + public static final int EVENT_LONG_WAKE_LOCK_FINISH = + EVENT_LONG_WAKE_LOCK | EVENT_FLAG_FINISH; // For CMD_EVENT. public int eventCode; @@ -1979,13 +2034,13 @@ public abstract class BatteryStats implements Parcelable { public static final String[] HISTORY_EVENT_NAMES = new String[] { "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist", - "screenwake", + "screenwake", "wakeupap", "longwake" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw", - "Esw", + "Esw", "Ewa", "Elw" }; /** @@ -2535,6 +2590,22 @@ public abstract class BatteryStats implements Parcelable { sb.append('('); sb.append(count); sb.append(" times)"); + final long maxDurationMs = timer.getMaxDurationMsLocked(elapsedRealtimeUs/1000); + if (maxDurationMs >= 0) { + sb.append(" max="); + sb.append(maxDurationMs); + } + if (timer.isRunningLocked()) { + final long currentMs = timer.getCurrentDurationMsLocked(elapsedRealtimeUs/1000); + if (currentMs >= 0) { + sb.append(" (running for "); + sb.append(currentMs); + sb.append("ms)"); + } else { + sb.append(" (running)"); + } + } + return ", "; } } @@ -2542,6 +2613,7 @@ public abstract class BatteryStats implements Parcelable { } /** + * Prints details about a timer, if its total time was greater than 0. * * @param pw a PrintWriter object to print to. * @param sb a StringBuilder object. @@ -2550,24 +2622,40 @@ public abstract class BatteryStats implements Parcelable { * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. * @param prefix a String to be prepended to each line of output. * @param type the name of the timer. + * @return true if anything was printed. */ private static final boolean printTimer(PrintWriter pw, StringBuilder sb, Timer timer, - long rawRealtime, int which, String prefix, String type) { + long rawRealtimeUs, int which, String prefix, String type) { if (timer != null) { // Convert from microseconds to milliseconds with rounding - final long totalTime = (timer.getTotalTimeLocked( - rawRealtime, which) + 500) / 1000; + final long totalTimeMs = (timer.getTotalTimeLocked( + rawRealtimeUs, which) + 500) / 1000; final int count = timer.getCountLocked(which); - if (totalTime != 0) { + if (totalTimeMs != 0) { sb.setLength(0); sb.append(prefix); sb.append(" "); sb.append(type); sb.append(": "); - formatTimeMs(sb, totalTime); + formatTimeMs(sb, totalTimeMs); sb.append("realtime ("); sb.append(count); sb.append(" times)"); + final long maxDurationMs = timer.getMaxDurationMsLocked(rawRealtimeUs/1000); + if (maxDurationMs >= 0) { + sb.append(" max="); + sb.append(maxDurationMs); + } + if (timer.isRunningLocked()) { + final long currentMs = timer.getCurrentDurationMsLocked(rawRealtimeUs/1000); + if (currentMs >= 0) { + sb.append(" (running for "); + sb.append(currentMs); + sb.append("ms)"); + } else { + sb.append(" (running)"); + } + } pw.println(sb.toString()); return true; } @@ -2590,15 +2678,23 @@ public abstract class BatteryStats implements Parcelable { long elapsedRealtimeUs, String name, int which, String linePrefix) { long totalTimeMicros = 0; int count = 0; + long max = -1; + long current = -1; if (timer != null) { totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which); count = timer.getCountLocked(which); + current = timer.getCurrentDurationMsLocked(elapsedRealtimeUs/1000); + max = timer.getMaxDurationMsLocked(elapsedRealtimeUs/1000); } sb.append(linePrefix); sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding sb.append(','); sb.append(name != null ? name + "," : ""); sb.append(count); + sb.append(','); + sb.append(current); + sb.append(','); + sb.append(max); return ","; } @@ -3105,20 +3201,22 @@ public abstract class BatteryStats implements Parcelable { final long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which); final long mobileActiveTime = u.getMobileRadioActiveTime(which); final int mobileActiveCount = u.getMobileRadioActiveCount(which); + final long mobileWakeup = u.getMobileRadioApWakeupCount(which); final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); + final long wifiWakeup = u.getWifiRadioApWakeupCount(which); final long btBytesRx = u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which); final long btBytesTx = u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which); if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0 || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0 || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0 - || btBytesRx > 0 || btBytesTx > 0) { + || btBytesRx > 0 || btBytesTx > 0 || mobileWakeup > 0 || wifiWakeup > 0) { dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx, wifiBytesRx, wifiBytesTx, mobilePacketsRx, mobilePacketsTx, wifiPacketsRx, wifiPacketsTx, mobileActiveTime, mobileActiveCount, - btBytesRx, btBytesTx); + btBytesRx, btBytesTx, mobileWakeup, wifiWakeup); } // Dump modem controller data, per UID. @@ -4125,6 +4223,9 @@ public abstract class BatteryStats implements Parcelable { final int wifiScanCount = u.getWifiScanCount(which); final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); + final long mobileWakeup = u.getMobileRadioApWakeupCount(which); + final long wifiWakeup = u.getWifiRadioApWakeupCount(which); + if (mobileRxBytes > 0 || mobileTxBytes > 0 || mobileRxPackets > 0 || mobileTxPackets > 0) { pw.print(prefix); pw.print(" Mobile network: "); @@ -4150,6 +4251,14 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } + if (mobileWakeup > 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Mobile radio AP wakeups: "); + sb.append(mobileWakeup); + pw.println(sb.toString()); + } + printControllerActivityIfInteresting(pw, sb, prefix + " ", "Modem", u.getModemControllerActivity(), which); @@ -4181,6 +4290,14 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); } + if (wifiWakeup > 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" WiFi AP wakeups: "); + sb.append(wifiWakeup); + pw.println(sb.toString()); + } + printControllerActivityIfInteresting(pw, sb, prefix + " ", "WiFi", u.getWifiControllerActivity(), which); @@ -4922,7 +5039,9 @@ public abstract class BatteryStats implements Parcelable { pw.print(','); pw.print(rec.stepDetails.statIdlTime); pw.print(','); - pw.print(rec.stepDetails.statPlatformIdleState); + if (rec.stepDetails.statPlatformIdleState != null) { + pw.print(rec.stepDetails.statPlatformIdleState); + } pw.println(); } } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index dc7be6b5ad613f3a9c18c9fad08089e060e86955..151239bed02b462e7d520b28385c67ba59161f6a 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -669,9 +669,62 @@ public class Build { public static final int M = 23; /** - * N is for ¯\_(ツ)_/¯. + * N is for Nougat. + * + *

Applications targeting this or a later release will get these + * new changes in behavior:

+ *
    + *
  • {@link android.app.DownloadManager.Request#setAllowedNetworkTypes + * DownloadManager.Request.setAllowedNetworkTypes} + * will disable "allow over metered" when specifying only + * {@link android.app.DownloadManager.Request#NETWORK_WIFI}.
  • + *
  • {@link android.app.DownloadManager} no longer allows access to raw + * file paths.
  • + *
  • {@link android.app.Notification.Builder#setShowWhen + * Notification.Builder.setShowWhen} + * must be called explicitly to have the time shown, and various other changes in + * {@link android.app.Notification.Builder Notification.Builder} to how notifications + * are shown.
  • + *
  • {@link android.content.Context#MODE_WORLD_READABLE} and + * {@link android.content.Context#MODE_WORLD_WRITEABLE} are no longer supported.
  • + *
  • {@link android.os.FileUriExposedException} will be thrown to applications.
  • + *
  • Applications will see global drag and drops as per + * {@link android.view.View#DRAG_FLAG_GLOBAL}.
  • + *
  • {@link android.webkit.WebView#evaluateJavascript WebView.evaluateJavascript} + * will not persist state from an empty WebView.
  • + *
  • {@link android.animation.AnimatorSet} will not ignore calls to end() before + * start().
  • + *
  • {@link android.app.AlarmManager#cancel(android.app.PendingIntent) + * AlarmManager.cancel} will throw a NullPointerException if given a null operation.
  • + *
  • {@link android.app.FragmentManager} will ensure fragments have been created + * before being placed on the back stack.
  • + *
  • {@link android.app.FragmentManager} restores fragments in + * {@link android.app.Fragment#onCreate Fragment.onCreate} rather than after the + * method returns.
  • + *
  • {@link android.R.attr#resizeableActivity} defaults to true.
  • + *
  • {@link android.graphics.drawable.AnimatedVectorDrawable} throws exceptions when + * opening invalid VectorDrawable animations.
  • + *
  • {@link android.view.ViewGroup.MarginLayoutParams} will no longer be dropped + * when converting between some types of layout params (such as + * {@link android.widget.LinearLayout.LayoutParams LinearLayout.LayoutParams} to + * {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams}).
  • + *
  • Your application processes will not be killed when the device density changes.
  • + *
  • Drag and drop. After a view receives the + * {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, when the drag shadow moves into + * a descendant view that can accept the data, the view receives the + * {@link android.view.DragEvent#ACTION_DRAG_EXITED} event and won’t receive + * {@link android.view.DragEvent#ACTION_DRAG_LOCATION} and + * {@link android.view.DragEvent#ACTION_DROP} events while the drag shadow is within that + * descendant view, even if the descendant view returns false from its handler + * for these events.
  • + *
*/ public static final int N = 24; + + /** + * N MR1: Nougat++. + */ + public static final int N_MR1 = 25; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index ca64a965af0b5f8702e3c49981d0c2b160d3d50d..62fa7721702eeb126069abbba7ed9d90fab6404c 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -309,25 +309,49 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { * Filter values in Bundle to only basic types. * @hide */ - public void filterValues() { + public Bundle filterValues() { unparcel(); + Bundle bundle = this; if (mMap != null) { - for (int i = mMap.size() - 1; i >= 0; i--) { - Object value = mMap.valueAt(i); + ArrayMap map = mMap; + for (int i = map.size() - 1; i >= 0; i--) { + Object value = map.valueAt(i); if (PersistableBundle.isValidType(value)) { continue; } if (value instanceof Bundle) { - ((Bundle)value).filterValues(); + Bundle newBundle = ((Bundle)value).filterValues(); + if (newBundle != value) { + if (map == mMap) { + // The filter had to generate a new bundle, but we have not yet + // created a new one here. Do that now. + bundle = new Bundle(this); + // Note the ArrayMap<> constructor is guaranteed to generate + // a new object with items in the same order as the original. + map = bundle.mMap; + } + // Replace this current entry with the new child bundle. + map.setValueAt(i, newBundle); + } + continue; } if (value.getClass().getName().startsWith("android.")) { continue; } - mMap.removeAt(i); + if (map == mMap) { + // This is the first time we have had to remove something, that means we + // need to switch to a new Bundle. + bundle = new Bundle(this); + // Note the ArrayMap<> constructor is guaranteed to generate + // a new object with items in the same order as the original. + map = bundle.mMap; + } + map.removeAt(i); } } mFlags |= FLAG_HAS_FDS_KNOWN; mFlags &= ~FLAG_HAS_FDS; + return bundle; } /** diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 93fc13c78b5acb41853b50a3efec086f6f6f6d39..4616af8f7768963dc31bbc9421e6ae5c2e7a5e70 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -344,6 +344,41 @@ public class Environment { return new File(getDataUserDeDirectory(volumeUuid, userId), packageName); } + /** + * Return preloads directory. + *

This directory may contain pre-loaded content such as + * {@link #getDataPreloadsDemoDirectory() demo videos} and + * {@link #getDataPreloadsAppsDirectory() APK files} . + * {@hide} + */ + public static File getDataPreloadsDirectory() { + return new File(getDataDirectory(), "preloads"); + } + + /** + * @see #getDataPreloadsDirectory() + * {@hide} + */ + public static File getDataPreloadsDemoDirectory() { + return new File(getDataPreloadsDirectory(), "demo"); + } + + /** + * @see #getDataPreloadsDirectory() + * {@hide} + */ + public static File getDataPreloadsAppsDirectory() { + return new File(getDataPreloadsDirectory(), "apps"); + } + + /** + * @see #getDataPreloadsDirectory() + * {@hide} + */ + public static File getDataPreloadsMediaDirectory() { + return new File(getDataPreloadsDirectory(), "media"); + } + /** * Return the primary shared/external storage directory. This directory may * not currently be accessible if it has been mounted by the user on their diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java index 4e705e04b447f3bfb7f2230238345109ad1a9766..dd85e1584f0ea2841e960eefc1cfaafd29f39fbf 100644 --- a/core/java/android/os/FileObserver.java +++ b/core/java/android/os/FileObserver.java @@ -16,6 +16,7 @@ package android.os; +import android.annotation.Nullable; import android.util.Log; import java.lang.ref.WeakReference; @@ -204,7 +205,8 @@ public abstract class FileObserver { * * @param event The type of event which happened * @param path The path, relative to the main monitored file or directory, - * of the file or directory which triggered the event + * of the file or directory which triggered the event. This value can + * be {@code null} for certain events, such as {@link #MOVE_SELF}. */ - public abstract void onEvent(int event, String path); + public abstract void onEvent(int event, @Nullable String path); } diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index fa32848e63626b61ba8123b5452a2375c378dd6d..8e24caf478393bc94ef80b9eec1349e0d47c9372 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -605,6 +605,22 @@ public class FileUtils { return null; } + private static File buildUniqueFileWithExtension(File parent, String name, String ext) + throws FileNotFoundException { + File file = buildFile(parent, name, ext); + + // If conflicting file, try adding counter suffix + int n = 0; + while (file.exists()) { + if (n++ >= 32) { + throw new FileNotFoundException("Failed to create unique file"); + } + file = buildFile(parent, name + " (" + n + ")", ext); + } + + return file; + } + /** * Generates a unique file name under the given parent directory. If the display name doesn't * have an extension that matches the requested MIME type, the default extension for that MIME @@ -619,20 +635,29 @@ public class FileUtils { public static File buildUniqueFile(File parent, String mimeType, String displayName) throws FileNotFoundException { final String[] parts = splitFileName(mimeType, displayName); - final String name = parts[0]; - final String ext = parts[1]; - File file = buildFile(parent, name, ext); + return buildUniqueFileWithExtension(parent, parts[0], parts[1]); + } - // If conflicting file, try adding counter suffix - int n = 0; - while (file.exists()) { - if (n++ >= 32) { - throw new FileNotFoundException("Failed to create unique file"); - } - file = buildFile(parent, name + " (" + n + ")", ext); + /** + * Generates a unique file name under the given parent directory, keeping + * any extension intact. + */ + public static File buildUniqueFile(File parent, String displayName) + throws FileNotFoundException { + final String name; + final String ext; + + // Extract requested extension from display name + final int lastDot = displayName.lastIndexOf('.'); + if (lastDot >= 0) { + name = displayName.substring(0, lastDot); + ext = displayName.substring(lastDot + 1); + } else { + name = displayName; + ext = null; } - return file; + return buildUniqueFileWithExtension(parent, name, ext); } /** diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index e1dd02ac198498b1fb434b0d917da9a626260d46..1c3d6bdba861e38854e5ffdb60bf9364b01c7988 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -18,6 +18,7 @@ package android.os; import android.net.InterfaceConfiguration; +import android.net.INetd; import android.net.INetworkManagementEventObserver; import android.net.Network; import android.net.NetworkStats; @@ -35,7 +36,7 @@ interface INetworkManagementService **/ /** - * Register an observer to receive events + * Register an observer to receive events. */ void registerObserver(INetworkManagementEventObserver obs); @@ -44,6 +45,11 @@ interface INetworkManagementService */ void unregisterObserver(INetworkManagementEventObserver obs); + /** + * Retrieve an INetd to talk to netd. + */ + INetd getNetdService(); + /** * Returns a list of currently known network interfaces */ @@ -414,6 +420,7 @@ interface INetworkManagementService void addInterfaceToLocalNetwork(String iface, in List routes); void removeInterfaceFromLocalNetwork(String iface); + int removeRoutesFromLocalNetwork(in List routes); void setAllowOnlyVpnForUids(boolean enable, in UidRange[] uidRanges); } diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index b27cb32bd4eb6216834c2593762361bb01ad2f6f..eeb641d33c20d4da561c1dc8f577e7b6e89b95a6 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -81,4 +81,5 @@ interface IUserManager { void clearSeedAccountData(); boolean someUserHasSeedAccount(in String accountName, in String accountType); boolean isManagedProfile(int userId); + boolean isDemoUser(int userId); } diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java index b58ff1fd4755afd2913763fede2d7f944ccf2637..d299672ea1d5e15b3d7375d888595c4e0a774435 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -147,7 +147,7 @@ public final class Looper { } final long traceTag = me.mTraceTag; - if (traceTag != 0) { + if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 74dcc0787b3bd91ed1009cd1bad48465c8a565df..f6e6ad6067bb0bae21b2aed51ac111e489e19f3e 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -36,6 +36,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.Serializable; +import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -2571,6 +2572,20 @@ public final class Parcel { return p; } + /** @hide */ + public final T[] readParcelableArray(ClassLoader loader, + Class clazz) { + int N = readInt(); + if (N < 0) { + return null; + } + T[] p = (T[]) Array.newInstance(clazz, N); + for (int i = 0; i < N; i++) { + p[i] = readParcelable(loader); + } + return p; + } + /** * Read and return a new Serializable object from the parcel. * @return the Serializable object, or null if the Serializable name diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java index 56dc837549a75ee9fe66ef4dc782717e74a1a476..3890fbfafb326f2e4bd297e0db5e9a8e0a606d19 100644 --- a/core/java/android/os/PatternMatcher.java +++ b/core/java/android/os/PatternMatcher.java @@ -16,6 +16,10 @@ package android.os; +import android.util.Log; + +import java.util.Arrays; + /** * A simple pattern matcher, which is safe to use on untrusted data: it does * not provide full reg-exp support, only simple globbing that can not be @@ -44,13 +48,59 @@ public class PatternMatcher implements Parcelable { * wildcard part of a normal regexp. */ public static final int PATTERN_SIMPLE_GLOB = 2; - + + /** + * Pattern type: the given pattern is interpreted with a regular + * expression-like syntax for matching against the string it is tested + * against. Supported tokens include dot ({@code .}) and sets ({@code [...]}) + * with full support for character ranges and the not ({@code ^}) modifier. + * Supported modifiers include star ({@code *}) for zero-or-more, plus ({@code +}) + * for one-or-more and full range ({@code {...}}) support. This is a simple + * evaulation implementation in which matching is done against the pattern in + * realtime with no backtracking support. + * + * {@hide} Pending approval for public API + */ + public static final int PATTERN_ADVANCED_GLOB = 3; + + // token types for advanced matching + private static final int TOKEN_TYPE_LITERAL = 0; + private static final int TOKEN_TYPE_ANY = 1; + private static final int TOKEN_TYPE_SET = 2; + private static final int TOKEN_TYPE_INVERSE_SET = 3; + + // Return for no match + private static final int NO_MATCH = -1; + + private static final String TAG = "PatternMatcher"; + + // Parsed placeholders for advanced patterns + private static final int PARSED_TOKEN_CHAR_SET_START = -1; + private static final int PARSED_TOKEN_CHAR_SET_INVERSE_START = -2; + private static final int PARSED_TOKEN_CHAR_SET_STOP = -3; + private static final int PARSED_TOKEN_CHAR_ANY = -4; + private static final int PARSED_MODIFIER_RANGE_START = -5; + private static final int PARSED_MODIFIER_RANGE_STOP = -6; + private static final int PARSED_MODIFIER_ZERO_OR_MORE = -7; + private static final int PARSED_MODIFIER_ONE_OR_MORE = -8; + private final String mPattern; private final int mType; - + private final int[] mParsedPattern; + + + private static final int MAX_PATTERN_STORAGE = 2048; + // workspace to use for building a parsed advanced pattern; + private static final int[] sParsedPatternScratch = new int[MAX_PATTERN_STORAGE]; + public PatternMatcher(String pattern, int type) { mPattern = pattern; mType = type; + if (mType == PATTERN_ADVANCED_GLOB) { + mParsedPattern = parseAndVerifyAdvancedPattern(pattern); + } else { + mParsedPattern = null; + } } public final String getPath() { @@ -62,7 +112,7 @@ public class PatternMatcher implements Parcelable { } public boolean match(String str) { - return matchPattern(mPattern, str, mType); + return matchPattern(str, mPattern, mParsedPattern, mType); } public String toString() { @@ -77,6 +127,9 @@ public class PatternMatcher implements Parcelable { case PATTERN_SIMPLE_GLOB: type = "GLOB: "; break; + case PATTERN_ADVANCED_GLOB: + type = "ADVANCED: "; + break; } return "PatternMatcher{" + type + mPattern + "}"; } @@ -88,11 +141,13 @@ public class PatternMatcher implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeString(mPattern); dest.writeInt(mType); + dest.writeIntArray(mParsedPattern); } public PatternMatcher(Parcel src) { mPattern = src.readString(); mType = src.readInt(); + mParsedPattern = src.createIntArray(); } public static final Parcelable.Creator CREATOR @@ -106,16 +161,21 @@ public class PatternMatcher implements Parcelable { } }; - static boolean matchPattern(String pattern, String match, int type) { + static boolean matchPattern(String match, String pattern, int[] parsedPattern, int type) { if (match == null) return false; if (type == PATTERN_LITERAL) { return pattern.equals(match); } if (type == PATTERN_PREFIX) { return match.startsWith(pattern); - } else if (type != PATTERN_SIMPLE_GLOB) { - return false; + } else if (type == PATTERN_SIMPLE_GLOB) { + return matchGlobPattern(pattern, match); + } else if (type == PATTERN_ADVANCED_GLOB) { + return matchAdvancedPattern(parsedPattern, match); } - + return false; + } + + static boolean matchGlobPattern(String pattern, String match) { final int NP = pattern.length(); if (NP <= 0) { return match.length() <= 0; @@ -194,4 +254,310 @@ public class PatternMatcher implements Parcelable { return false; } -} + + /** + * Parses the advanced pattern and returns an integer array representation of it. The integer + * array treats each field as a character if positive and a unique token placeholder if + * negative. This method will throw on any pattern structure violations. + */ + synchronized static int[] parseAndVerifyAdvancedPattern(String pattern) { + int ip = 0; + final int LP = pattern.length(); + + int it = 0; + + boolean inSet = false; + boolean inRange = false; + boolean inCharClass = false; + + boolean addToParsedPattern; + + while (ip < LP) { + if (it > MAX_PATTERN_STORAGE - 3) { + throw new IllegalArgumentException("Pattern is too large!"); + } + + char c = pattern.charAt(ip); + addToParsedPattern = false; + + switch (c) { + case '[': + if (inSet) { + addToParsedPattern = true; // treat as literal or char class in set + } else { + if (pattern.charAt(ip + 1) == '^') { + sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_SET_INVERSE_START; + ip++; // skip over the '^' + } else { + sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_SET_START; + } + ip++; // move to the next pattern char + inSet = true; + continue; + } + break; + case ']': + if (!inSet) { + addToParsedPattern = true; // treat as literal outside of set + } else { + int parsedToken = sParsedPatternScratch[it - 1]; + if (parsedToken == PARSED_TOKEN_CHAR_SET_START || + parsedToken == PARSED_TOKEN_CHAR_SET_INVERSE_START) { + throw new IllegalArgumentException( + "You must define characters in a set."); + } + sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_SET_STOP; + inSet = false; + inCharClass = false; + } + break; + case '{': + if (!inSet) { + if (it == 0 || isParsedModifier(sParsedPatternScratch[it - 1])) { + throw new IllegalArgumentException("Modifier must follow a token."); + } + sParsedPatternScratch[it++] = PARSED_MODIFIER_RANGE_START; + ip++; + inRange = true; + } + break; + case '}': + if (inRange) { // only terminate the range if we're currently in one + sParsedPatternScratch[it++] = PARSED_MODIFIER_RANGE_STOP; + inRange = false; + } + break; + case '*': + if (!inSet) { + if (it == 0 || isParsedModifier(sParsedPatternScratch[it - 1])) { + throw new IllegalArgumentException("Modifier must follow a token."); + } + sParsedPatternScratch[it++] = PARSED_MODIFIER_ZERO_OR_MORE; + } + break; + case '+': + if (!inSet) { + if (it == 0 || isParsedModifier(sParsedPatternScratch[it - 1])) { + throw new IllegalArgumentException("Modifier must follow a token."); + } + sParsedPatternScratch[it++] = PARSED_MODIFIER_ONE_OR_MORE; + } + break; + case '.': + if (!inSet) { + sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_ANY; + } + break; + case '\\': // escape + if (ip + 1 >= LP) { + throw new IllegalArgumentException("Escape found at end of pattern!"); + } + c = pattern.charAt(++ip); + addToParsedPattern = true; + break; + default: + addToParsedPattern = true; + break; + } + if (inSet) { + if (inCharClass) { + sParsedPatternScratch[it++] = c; + inCharClass = false; + } else { + // look forward for character class + if (ip + 2 < LP + && pattern.charAt(ip + 1) == '-' + && pattern.charAt(ip + 2) != ']') { + inCharClass = true; + sParsedPatternScratch[it++] = c; // set first token as lower end of range + ip++; // advance past dash + } else { // literal + sParsedPatternScratch[it++] = c; // set first token as literal + sParsedPatternScratch[it++] = c; // set second set as literal + } + } + } else if (inRange) { + int endOfSet = pattern.indexOf('}', ip); + if (endOfSet < 0) { + throw new IllegalArgumentException("Range not ended with '}'"); + } + String rangeString = pattern.substring(ip, endOfSet); + int commaIndex = rangeString.indexOf(','); + try { + final int rangeMin; + final int rangeMax; + if (commaIndex < 0) { + int parsedRange = Integer.parseInt(rangeString); + rangeMin = rangeMax = parsedRange; + } else { + rangeMin = Integer.parseInt(rangeString.substring(0, commaIndex)); + if (commaIndex == rangeString.length() - 1) { // e.g. {n,} (n or more) + rangeMax = Integer.MAX_VALUE; + } else { + rangeMax = Integer.parseInt(rangeString.substring(commaIndex + 1)); + } + } + if (rangeMin > rangeMax) { + throw new IllegalArgumentException( + "Range quantifier minimum is greater than maximum"); + } + sParsedPatternScratch[it++] = rangeMin; + sParsedPatternScratch[it++] = rangeMax; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Range number format incorrect", e); + } + ip = endOfSet; + continue; // don't increment ip + } else if (addToParsedPattern) { + sParsedPatternScratch[it++] = c; + } + ip++; + } + if (inSet) { + throw new IllegalArgumentException("Set was not terminated!"); + } + return Arrays.copyOf(sParsedPatternScratch, it); + } + + private static boolean isParsedModifier(int parsedChar) { + return parsedChar == PARSED_MODIFIER_ONE_OR_MORE || + parsedChar == PARSED_MODIFIER_ZERO_OR_MORE || + parsedChar == PARSED_MODIFIER_RANGE_STOP || + parsedChar == PARSED_MODIFIER_RANGE_START; + } + + static boolean matchAdvancedPattern(int[] parsedPattern, String match) { + + // create indexes + int ip = 0, im = 0; + + // one-time length check + final int LP = parsedPattern.length, LM = match.length(); + + // The current character being analyzed in the pattern + int patternChar; + + int tokenType; + + int charSetStart = 0, charSetEnd = 0; + + while (ip < LP) { // we still have content in the pattern + + patternChar = parsedPattern[ip]; + // get the match type of the next verb + + switch (patternChar) { + case PARSED_TOKEN_CHAR_ANY: + tokenType = TOKEN_TYPE_ANY; + ip++; + break; + case PARSED_TOKEN_CHAR_SET_START: + case PARSED_TOKEN_CHAR_SET_INVERSE_START: + tokenType = patternChar == PARSED_TOKEN_CHAR_SET_START + ? TOKEN_TYPE_SET + : TOKEN_TYPE_INVERSE_SET; + charSetStart = ip + 1; // start from the char after the set start + while (++ip < LP && parsedPattern[ip] != PARSED_TOKEN_CHAR_SET_STOP); + charSetEnd = ip - 1; // we're on the set stop, end is the previous + ip++; // move the pointer to the next pattern entry + break; + default: + charSetStart = ip; + tokenType = TOKEN_TYPE_LITERAL; + ip++; + break; + } + + final int minRepetition; + final int maxRepetition; + + // look for a match length modifier + if (ip >= LP) { + minRepetition = maxRepetition = 1; + } else { + patternChar = parsedPattern[ip]; + switch (patternChar) { + case PARSED_MODIFIER_ZERO_OR_MORE: + minRepetition = 0; + maxRepetition = Integer.MAX_VALUE; + ip++; + break; + case PARSED_MODIFIER_ONE_OR_MORE: + minRepetition = 1; + maxRepetition = Integer.MAX_VALUE; + ip++; + break; + case PARSED_MODIFIER_RANGE_START: + minRepetition = parsedPattern[++ip]; + maxRepetition = parsedPattern[++ip]; + ip += 2; // step over PARSED_MODIFIER_RANGE_STOP and on to the next token + break; + default: + minRepetition = maxRepetition = 1; // implied literal + break; + } + } + if (minRepetition > maxRepetition) { + return false; + } + + // attempt to match as many characters as possible + int matched = matchChars(match, im, LM, tokenType, minRepetition, maxRepetition, + parsedPattern, charSetStart, charSetEnd); + + // if we found a conflict, return false immediately + if (matched == NO_MATCH) { + return false; + } + + // move the match pointer the number of characters matched + im += matched; + } + return ip >= LP && im >= LM; // have parsed entire string and regex + } + + private static int matchChars(String match, int im, final int lm, int tokenType, + int minRepetition, int maxRepetition, int[] parsedPattern, + int tokenStart, int tokenEnd) { + int matched = 0; + + while(matched < maxRepetition + && matchChar(match, im + matched, lm, tokenType, parsedPattern, tokenStart, + tokenEnd)) { + matched++; + } + + return matched < minRepetition ? NO_MATCH : matched; + } + + private static boolean matchChar(String match, int im, final int lm, int tokenType, + int[] parsedPattern, int tokenStart, int tokenEnd) { + if (im >= lm) { // we've overrun the string, no match + return false; + } + switch (tokenType) { + case TOKEN_TYPE_ANY: + return true; + case TOKEN_TYPE_SET: + for (int i = tokenStart; i < tokenEnd; i += 2) { + char matchChar = match.charAt(im); + if (matchChar >= parsedPattern[i] && matchChar <= parsedPattern[i + 1]) { + return true; + } + } + return false; + case TOKEN_TYPE_INVERSE_SET: + for (int i = tokenStart; i < tokenEnd; i += 2) { + char matchChar = match.charAt(im); + if (matchChar >= parsedPattern[i] && matchChar <= parsedPattern[i + 1]) { + return false; + } + } + return true; + case TOKEN_TYPE_LITERAL: + return match.charAt(im) == parsedPattern[tokenStart]; + default: + return false; + } + } +} \ No newline at end of file diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index ce7a1243fe7a710ff0dbb930798161a00e857925..8d4d0a55833452fa526f6388bdaf0542d9915f3c 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -1339,6 +1339,11 @@ public final class PowerManager { mTag = tag; } + /** @hide */ + public String getTag() { + return mTag; + } + /** @hide */ public void setHistoryTag(String tag) { mHistoryTag = tag; @@ -1358,5 +1363,34 @@ public final class PowerManager { + " held=" + mHeld + ", refCount=" + mCount + "}"; } } + + /** + * Wraps a Runnable such that this method immediately acquires the wake lock and then + * once the Runnable is done the wake lock is released. + * + *

Example: + * + *

+         * mHandler.post(mWakeLock.wrap(() -> {
+         *     // do things on handler, lock is held while we're waiting for this
+         *     // to get scheduled and until the runnable is done executing.
+         * });
+         * 
+ * + *

Note: you must make sure that the Runnable eventually gets executed, otherwise you'll + * leak the wakelock! + * + * @hide + */ + public Runnable wrap(Runnable r) { + acquire(); + return () -> { + try { + r.run(); + } finally { + release(); + } + }; + } } } diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index b3cf710094e037573dba086dcae5f98bb57dbff5..9bbe8f951834694a7ce3ceb169bd6345f1f9fb14 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -57,14 +57,19 @@ public abstract class PowerManagerInternal { /** * Power hint: * Interaction: The user is interacting with the device. The corresponding data field must be - * the expected duration of the fling, or 0 if unknown. + * the expected duration of the interaction, or 0 if unknown. * - * Sustained Performance Mode: Enable/Disables Sustained Performance Mode. + * Sustained Performance Mode: The corresponding data field must be Enable/Disable + * Sustained Performance Mode. + * + * Launch: This is specific for activity launching. The corresponding data field must be + * the expected duration of the required boost, or 0 if unknown. * * These must be kept in sync with the values in hardware/libhardware/include/hardware/power.h */ public static final int POWER_HINT_INTERACTION = 2; public static final int POWER_HINT_SUSTAINED_PERFORMANCE_MODE = 6; + public static final int POWER_HINT_LAUNCH = 8; public static String wakefulnessToString(int wakefulness) { switch (wakefulness) { diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 3fccdb0345a658fe4bdc7907664daf6279aa978e..4eee8541f3bb381c9f44c9c296d5271d39e1f911 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -16,7 +16,9 @@ package android.os; +import android.annotation.TestApi; import android.system.Os; +import android.system.OsConstants; import android.util.Log; import android.webkit.WebViewZygote; import dalvik.system.VMRuntime; @@ -304,6 +306,12 @@ public class Process { */ public static final int SCHED_IDLE = 5; + /** + * Reset scheduler choice on fork. + * @hide + */ + public static final int SCHED_RESET_ON_FORK = 0x40000000; + // Keep in sync with SP_* constants of enum type SchedPolicy // declared in system/core/include/cutils/sched_policy.h, // except THREAD_GROUP_DEFAULT does not correspond to any SP_* value. @@ -636,6 +644,9 @@ public class Process { * priority. * If the thread is a thread group leader, that is it's gettid() == getpid(), * then the other threads in the same thread group are _not_ affected. + * + * Does not set cpuset for some historical reason, just calls + * libcutils::set_sched_policy(). */ public static final native void setThreadGroup(int tid, int group) throws IllegalArgumentException, SecurityException; @@ -657,6 +668,8 @@ public class Process { * priority threads alone. group == THREAD_GROUP_BG_NONINTERACTIVE moves all * threads, regardless of priority, to the background scheduling group. * group == THREAD_GROUP_FOREGROUND is not allowed. + * + * Always sets cpusets. */ public static final native void setProcessGroup(int pid, int group) throws IllegalArgumentException, SecurityException; @@ -727,6 +740,24 @@ public class Process { public static final native int getThreadPriority(int tid) throws IllegalArgumentException; + /** + * Return the current scheduling policy of a thread, based on Linux. + * + * @param tid The identifier of the thread/process to get the scheduling policy. + * + * @throws IllegalArgumentException Throws IllegalArgumentException if + * tid does not exist, or if priority is out of range for the policy. + * @throws SecurityException Throws SecurityException if your process does + * not have permission to modify the given thread, or to use the given + * scheduling policy or priority. + * + * {@hide} + */ + + @TestApi + public static final native int getThreadScheduler(int tid) + throws IllegalArgumentException; + /** * Set the scheduling policy and priority of a thread, based on Linux. * @@ -742,6 +773,7 @@ public class Process { * * {@hide} */ + public static final native void setThreadScheduler(int tid, int policy, int priority) throws IllegalArgumentException; @@ -915,4 +947,26 @@ public class Process { * @hide */ public static final native void removeAllProcessGroups(); + + /** + * Check to see if a thread belongs to a given process. This may require + * more permissions than apps generally have. + * @return true if this thread belongs to a process + * @hide + */ + public static final boolean isThreadInProcess(int tid, int pid) { + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + if (Os.access("/proc/" + tid + "/task/" + pid, OsConstants.F_OK)) { + return true; + } else { + return false; + } + } catch (Exception e) { + return false; + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + + } } diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 662e14cce49b7e0fdf4f47e06d0af00e943099f8..d48431afe6913eca2ad5703428fe11d7678610c1 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -578,18 +578,19 @@ public class RecoverySystem { * @throws SecurityException if the current user is not allowed to wipe data. */ public static void rebootWipeUserData(Context context) throws IOException { - rebootWipeUserData(context, false, context.getPackageName()); + rebootWipeUserData(context, false /* shutdown */, context.getPackageName(), + false /* force */); } /** {@hide} */ public static void rebootWipeUserData(Context context, String reason) throws IOException { - rebootWipeUserData(context, false, reason); + rebootWipeUserData(context, false /* shutdown */, reason, false /* force */); } /** {@hide} */ public static void rebootWipeUserData(Context context, boolean shutdown) throws IOException { - rebootWipeUserData(context, shutdown, context.getPackageName()); + rebootWipeUserData(context, shutdown, context.getPackageName(), false /* force */); } /** @@ -603,6 +604,9 @@ public class RecoverySystem { * @param shutdown if true, the device will be powered down after * the wipe completes, rather than being rebooted * back to the regular system. + * @param reason the reason for the wipe that is visible in the logs + * @param force whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction + * should be ignored * * @throws IOException if writing the recovery command file * fails, or if the reboot itself fails. @@ -610,10 +614,10 @@ public class RecoverySystem { * * @hide */ - public static void rebootWipeUserData(Context context, boolean shutdown, String reason) - throws IOException { + public static void rebootWipeUserData(Context context, boolean shutdown, String reason, + boolean force) throws IOException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); - if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { + if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { throw new SecurityException("Wiping data is not allowed for this user."); } final ConditionVariable condition = new ConditionVariable(); @@ -665,6 +669,31 @@ public class RecoverySystem { bootCommand(context, "--wipe_cache", reasonArg, localeArg); } + /** + * Reboot into recovery and wipe the A/B device. + * + * @param Context the Context to use. + * @param packageFile the wipe package to be applied. + * @param reason the reason to wipe. + * + * @throws IOException if something goes wrong. + * + * @hide + */ + @SystemApi + public static void rebootWipeAb(Context context, File packageFile, String reason) + throws IOException { + String reasonArg = null; + if (!TextUtils.isEmpty(reason)) { + reasonArg = "--reason=" + sanitizeArg(reason); + } + + final String filename = packageFile.getCanonicalPath(); + final String filenameArg = "--wipe_package=" + filename; + final String localeArg = "--locale=" + Locale.getDefault().toString(); + bootCommand(context, "--wipe_ab", filenameArg, reasonArg, localeArg); + } + /** * Reboot into the recovery system with the supplied argument. * @param args to pass to the recovery utility. diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 5849350cc49ebb885e41587ec41c90b164fdefd3..3546e17698b9fa867f20aa13236330c1c6e2f39a 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -288,20 +288,22 @@ public class RemoteCallbackList { * @see #beginBroadcast */ public void finishBroadcast() { - if (mBroadcastCount < 0) { - throw new IllegalStateException( - "finishBroadcast() called outside of a broadcast"); - } - - Object[] active = mActiveBroadcast; - if (active != null) { - final int N = mBroadcastCount; - for (int i=0; ifalse. @@ -618,6 +628,18 @@ public class UserManager { */ public static final String DISALLOW_SET_USER_ICON = "no_set_user_icon"; + /** + * Specifies if a user is not allowed to enable the oem unlock setting. The default value is + * false. Setting this restriction has no effect if the bootloader is already + * unlocked. + * + * @see DevicePolicyManager#addUserRestriction(ComponentName, String) + * @see DevicePolicyManager#clearUserRestriction(ComponentName, String) + * @see #getUserRestrictions() + * @hide + */ + public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock"; + /** * Allows apps in the parent profile to handle web links from the managed profile. * @@ -805,7 +827,7 @@ public class UserManager { */ public boolean isPrimaryUser() { UserInfo user = getUserInfo(UserHandle.myUserId()); - return user != null ? user.isPrimary() : false; + return user != null && user.isPrimary(); } /** @@ -871,7 +893,21 @@ public class UserManager { */ public boolean isGuestUser() { UserInfo user = getUserInfo(UserHandle.myUserId()); - return user != null ? user.isGuest() : false; + return user != null && user.isGuest(); + } + + /** + * Checks if the calling app is running in a demo user. When running in a demo user, + * apps can be more helpful to the user, or explain their features in more detail. + * + * @return whether the caller is a demo user. + */ + public boolean isDemoUser() { + try { + return mService.isDemoUser(UserHandle.myUserId()); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } } /** @@ -1991,6 +2027,10 @@ public class UserManager { if (!supportsMultipleUsers()) { return false; } + // If Demo Mode is on, don't show user switcher + if (isDeviceInDemoMode(mContext)) { + return false; + } List users = getUsers(true); if (users == null) { return false; @@ -2006,6 +2046,14 @@ public class UserManager { return switchableUserCount > 1 || guestEnabled; } + /** + * @hide + */ + public static boolean isDeviceInDemoMode(Context context) { + return Settings.Global.getInt(context.getContentResolver(), + Settings.Global.DEVICE_DEMO_MODE, 0) > 0; + } + /** * Returns a serial number on this device for a given userHandle. User handles can be recycled * when deleting and creating users, but serial numbers are not reused until the device is wiped. diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index d5206d4afead713d625d34d62041ce9baadf8f02..c45fe5a6185275f2d527535ea200c81d727ea276 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -249,6 +249,15 @@ public class ZygoteProcess { ZygoteState zygoteState, ArrayList args) throws ZygoteStartFailedEx { try { + // Throw early if any of the arguments are malformed. This means we can + // avoid writing a partial response to the zygote. + int sz = args.size(); + for (int i = 0; i < sz; i++) { + if (args.get(i).indexOf('\n') >= 0) { + throw new ZygoteStartFailedEx("embedded newlines not allowed"); + } + } + /** * See com.android.internal.os.SystemZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: @@ -265,13 +274,8 @@ public class ZygoteProcess { writer.write(Integer.toString(args.size())); writer.newLine(); - int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); - if (arg.indexOf('\n') >= 0) { - throw new ZygoteStartFailedEx( - "embedded newlines not allowed"); - } writer.write(arg); writer.newLine(); } @@ -280,11 +284,16 @@ public class ZygoteProcess { // Should there be a timeout on this? Process.ProcessStartResult result = new Process.ProcessStartResult(); + + // Always read the entire result from the input stream to avoid leaving + // bytes in the stream for future process starts to accidentally stumble + // upon. result.pid = inputStream.readInt(); + result.usingWrapper = inputStream.readBoolean(); + if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } - result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 485bbd105603b23790a507fec5ce4f24f40f3e62..c5507b9841bc6b2694ff885dc1350a9db7d5d988 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -20,6 +20,7 @@ import static android.net.TrafficStats.MB_IN_BYTES; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.app.ActivityThread; import android.content.ContentResolver; import android.content.Context; @@ -45,8 +46,11 @@ import android.util.SparseArray; import com.android.internal.os.SomeArgs; import com.android.internal.util.Preconditions; +import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; @@ -92,6 +96,19 @@ public class StorageManager { /** {@hide} */ public static final String UUID_PRIMARY_PHYSICAL = "primary_physical"; + + /** + * Activity Action: Allows the user to manage their storage. This activity provides the ability + * to free up space on the device by deleting data such as apps. + *

+ * Input: Nothing. + *

+ * Output: Nothing. + */ + @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_STORAGE + = "android.os.storage.action.MANAGE_STORAGE"; + /** {@hide} */ public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0; /** {@hide} */ @@ -116,6 +133,15 @@ public class StorageManager { private static volatile IMountService sMountService = null; + // TODO: the location of the primary storage block varies from device to device, so we need to + // try the most likely candidates - a long-term solution would be a device-specific vold + // function that returns the calculated size. + private static final String[] INTERNAL_STORAGE_SIZE_PATHS = { + "/sys/block/mmcblk0/size", + "/sys/block/sda/size" + }; + private static final int INTERNAL_STORAGE_SECTOR_SIZE = 512; + private final Context mContext; private final ContentResolver mResolver; @@ -903,6 +929,27 @@ public class StorageManager { return getVolumeList(UserHandle.myUserId(), FLAG_REAL_STATE | FLAG_INCLUDE_INVISIBLE)[0]; } + /** {@hide} */ + public long getPrimaryStorageSize() { + for (String path : INTERNAL_STORAGE_SIZE_PATHS) { + final long numberBlocks = readLong(path); + if (numberBlocks > 0) { + return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE; + } + } + return 0; + } + + private long readLong(String path) { + try (final FileInputStream fis = new FileInputStream(path); + final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) { + return Long.parseLong(reader.readLine()); + } catch (Exception e) { + Slog.w(TAG, "Could not read " + path, e); + return 0; + } + } + /** @removed */ public @NonNull StorageVolume[] getVolumeList() { return getVolumeList(mContext.getUserId(), 0); diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java index 5a9848238382266eb8b27dce49fa7331129c0323..19210b5291e553cdde7a4396eb9c1a1bca4bafbb 100644 --- a/core/java/android/os/storage/VolumeInfo.java +++ b/core/java/android/os/storage/VolumeInfo.java @@ -437,7 +437,7 @@ public class VolumeInfo implements Parcelable { final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE); intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.setData(uri); + intent.setDataAndType(uri, DocumentsContract.Root.MIME_TYPE_ITEM); // note that docsui treats this as *force* show advanced. So sending // false permits advanced to be shown based on user preferences. diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java index b1cad0538d312ce193c12456b71fb4205fbee336..ec1e102c92896fb41a5b7bfe84740e8e55bf1851 100644 --- a/core/java/android/preference/Preference.java +++ b/core/java/android/preference/Preference.java @@ -719,6 +719,9 @@ public class Preference implements Comparable { * @see #setIcon(Drawable) */ public Drawable getIcon() { + if (mIcon == null && mIconResId != 0) { + mIcon = getContext().getDrawable(mIconResId); + } return mIcon; } diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java index 3e496b6eb550b9bd7630961e9967cd8ae843c3d9..73fa01e592011cca5bb4686bec29ce51ff02ed5a 100644 --- a/core/java/android/preference/PreferenceFragment.java +++ b/core/java/android/preference/PreferenceFragment.java @@ -27,12 +27,14 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.text.TextUtils; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnKeyListener; import android.view.ViewGroup; import android.widget.ListView; +import android.widget.TextView; /** * Shows a hierarchy of {@link Preference} objects as @@ -189,12 +191,10 @@ public abstract class PreferenceFragment extends Fragment implements 0); ListView lv = (ListView) view.findViewById(android.R.id.list); - if (lv != null) { - Drawable divider = - a.getDrawable(com.android.internal.R.styleable.PreferenceFragment_divider); - if (divider != null) { - lv.setDivider(divider); - } + if (lv != null + && a.hasValueOrEmpty(com.android.internal.R.styleable.PreferenceFragment_divider)) { + lv.setDivider( + a.getDrawable(com.android.internal.R.styleable.PreferenceFragment_divider)); } a.recycle(); @@ -368,6 +368,20 @@ public abstract class PreferenceFragment extends Fragment implements private void bindPreferences() { final PreferenceScreen preferenceScreen = getPreferenceScreen(); if (preferenceScreen != null) { + View root = getView(); + if (root != null) { + View titleView = root.findViewById(android.R.id.title); + if (titleView instanceof TextView) { + CharSequence title = preferenceScreen.getTitle(); + if (TextUtils.isEmpty(title)) { + titleView.setVisibility(View.GONE); + } else { + ((TextView) titleView).setText(title); + titleView.setVisibility(View.VISIBLE); + } + } + } + preferenceScreen.bind(getListView()); } onBindPreferences(); diff --git a/core/java/android/preference/PreferenceScreen.java b/core/java/android/preference/PreferenceScreen.java index b1317e656e3e4287d5cfe8b2618846d176d66b18..2305b0564e4995033ab4de326e8e81e2338af83a 100644 --- a/core/java/android/preference/PreferenceScreen.java +++ b/core/java/android/preference/PreferenceScreen.java @@ -19,6 +19,8 @@ package android.preference; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -31,6 +33,7 @@ import android.widget.Adapter; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.ListView; +import android.widget.TextView; /** * Represents a top-level {@link Preference} that @@ -91,13 +94,33 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi private Dialog mDialog; private ListView mListView; - + + private int mLayoutResId = com.android.internal.R.layout.preference_list_fragment; + private Drawable mDividerDrawable; + private boolean mDividerSpecified; + /** * Do NOT use this constructor, use {@link PreferenceManager#createPreferenceScreen(Context)}. * @hide- */ public PreferenceScreen(Context context, AttributeSet attrs) { super(context, attrs, com.android.internal.R.attr.preferenceScreenStyle); + + TypedArray a = context.obtainStyledAttributes(null, + com.android.internal.R.styleable.PreferenceScreen, + com.android.internal.R.attr.preferenceScreenStyle, + 0); + + mLayoutResId = a.getResourceId( + com.android.internal.R.styleable.PreferenceScreen_screenLayout, + mLayoutResId); + if (a.hasValueOrEmpty(com.android.internal.R.styleable.PreferenceScreen_divider)) { + mDividerDrawable = + a.getDrawable(com.android.internal.R.styleable.PreferenceScreen_divider); + mDividerSpecified = true; + } + + a.recycle(); } /** @@ -163,18 +186,30 @@ public final class PreferenceScreen extends PreferenceGroup implements AdapterVi LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View childPrefScreen = inflater.inflate( - com.android.internal.R.layout.preference_list_fragment, null); + View childPrefScreen = inflater.inflate(mLayoutResId, null); + View titleView = childPrefScreen.findViewById(android.R.id.title); mListView = (ListView) childPrefScreen.findViewById(android.R.id.list); + if (mDividerSpecified) { + mListView.setDivider(mDividerDrawable); + } + bind(mListView); // Set the title bar if title is available, else no title bar final CharSequence title = getTitle(); Dialog dialog = mDialog = new Dialog(context, context.getThemeResId()); if (TextUtils.isEmpty(title)) { + if (titleView != null) { + titleView.setVisibility(View.GONE); + } dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); } else { - dialog.setTitle(title); + if (titleView instanceof TextView) { + ((TextView) titleView).setText(title); + titleView.setVisibility(View.VISIBLE); + } else { + dialog.setTitle(title); + } } dialog.setContentView(childPrefScreen); dialog.setOnDismissListener(this); diff --git a/core/java/android/print/PrintServiceRecommendationsLoader.java b/core/java/android/print/PrintServiceRecommendationsLoader.java index bb5d065c6430e59aa98ff47dcded0f03eb9e3d95..c6a4d5103a479f764b9f4137c6374641f9d4d73a 100644 --- a/core/java/android/print/PrintServiceRecommendationsLoader.java +++ b/core/java/android/print/PrintServiceRecommendationsLoader.java @@ -36,7 +36,7 @@ public class PrintServiceRecommendationsLoader extends Loader> { private final @NonNull PrintManager mPrintManager; /** Handler to sequentialize the delivery of the results to the main thread */ - private Handler mHandler; + private final @NonNull Handler mHandler; /** Listens for updates to the data from the platform */ private PrintManager.PrintServicesChangeListener mListener; @@ -54,6 +54,7 @@ public class PrintServicesLoader extends Loader> { public PrintServicesLoader(@NonNull PrintManager printManager, @NonNull Context context, int selectionFlags) { super(Preconditions.checkNotNull(context)); + mHandler = new MyHandler(); mPrintManager = Preconditions.checkNotNull(printManager); mSelectionFlags = Preconditions.checkFlagsArgument(selectionFlags, PrintManager.ALL_SERVICES); @@ -75,7 +76,6 @@ public class PrintServicesLoader extends Loader> { @Override protected void onStartLoading() { - mHandler = new MyHandler(); mListener = new PrintManager.PrintServicesChangeListener() { @Override public void onPrintServicesChanged() { queueNewResult(); @@ -95,10 +95,7 @@ public class PrintServicesLoader extends Loader> { mListener = null; } - if (mHandler != null) { - mHandler.removeMessages(0); - mHandler = null; - } + mHandler.removeMessages(0); } @Override @@ -119,8 +116,6 @@ public class PrintServicesLoader extends Loader> { @Override public void handleMessage(Message msg) { - super.handleMessage(msg); - if (isStarted()) { deliverResult((List) msg.obj); } diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 893eb3701df463b029a5c9232212fc91199e636f..c7c6ceb5c16d5b661cc699f1f16e9e1e037c12c0 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -179,6 +179,7 @@ public class CallLog { *

  • {@link #VOICEMAIL_TYPE}
  • *
  • {@link #REJECTED_TYPE}
  • *
  • {@link #BLOCKED_TYPE}
  • + *
  • {@link #ANSWERED_EXTERNALLY_TYPE}
  • * *

    */ @@ -200,7 +201,6 @@ public class CallLog { * Call log type for a call which was answered on another device. Used in situations where * a call rings on multiple devices simultaneously and it ended up being answered on a * device other than the current one. - * @hide */ public static final int ANSWERED_EXTERNALLY_TYPE = 7; @@ -214,10 +214,7 @@ public class CallLog { /** Call had video. */ public static final int FEATURES_VIDEO = 0x1; - /** - * Call was pulled externally. - * @hide - */ + /** Call was pulled externally. */ public static final int FEATURES_PULLED_EXTERNALLY = 0x2; /** @@ -287,8 +284,10 @@ public class CallLog { /** * The cached name associated with the phone number, if it exists. - * This value is not guaranteed to be current, if the contact information - * associated with this number has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: TEXT

    */ public static final String CACHED_NAME = "name"; @@ -296,8 +295,10 @@ public class CallLog { /** * The cached number type (Home, Work, etc) associated with the * phone number, if it exists. - * This value is not guaranteed to be current, if the contact information - * associated with this number has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: INTEGER

    */ public static final String CACHED_NUMBER_TYPE = "numbertype"; @@ -305,8 +306,10 @@ public class CallLog { /** * The cached number label, for a custom number type, associated with the * phone number, if it exists. - * This value is not guaranteed to be current, if the contact information - * associated with this number has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: TEXT

    */ public static final String CACHED_NUMBER_LABEL = "numberlabel"; @@ -342,40 +345,50 @@ public class CallLog { /** * The cached URI to look up the contact associated with the phone number, if it exists. - * This value may not be current if the contact information associated with this number - * has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: TEXT

    */ public static final String CACHED_LOOKUP_URI = "lookup_uri"; /** * The cached phone number of the contact which matches this entry, if it exists. - * This value may not be current if the contact information associated with this number - * has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: TEXT

    */ public static final String CACHED_MATCHED_NUMBER = "matched_number"; /** * The cached normalized(E164) version of the phone number, if it exists. - * This value may not be current if the contact information associated with this number - * has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: TEXT

    */ public static final String CACHED_NORMALIZED_NUMBER = "normalized_number"; /** * The cached photo id of the picture associated with the phone number, if it exists. - * This value may not be current if the contact information associated with this number - * has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: INTEGER (long)

    */ public static final String CACHED_PHOTO_ID = "photo_id"; /** * The cached photo URI of the picture associated with the phone number, if it exists. - * This value may not be current if the contact information associated with this number - * has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: TEXT (URI)

    */ public static final String CACHED_PHOTO_URI = "photo_uri"; @@ -383,9 +396,10 @@ public class CallLog { /** * The cached phone number, formatted with formatting rules based on the country the * user was in when the call was made or received. - * This value is not guaranteed to be present, and may not be current if the contact - * information associated with this number - * has changed. + * + *

    This value is typically filled in by the dialer app for the caching purpose, + * so it's not guaranteed to be present, and may not be current if the contact + * information associated with this number has changed. *

    Type: TEXT

    */ public static final String CACHED_FORMATTED_NUMBER = "formatted_number"; diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index c70304e140cffd567fb336ac343390d6c2736446..c495e6c163ac6bb0fae8da19ddd169ba71851471 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -35,6 +35,7 @@ import android.content.Intent; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.database.Cursor; +import android.database.CursorWrapper; import android.database.DatabaseUtils; import android.graphics.Rect; import android.net.Uri; @@ -138,8 +139,20 @@ public final class ContactsContract { public static final String DIRECTORY_PARAM_KEY = "directory"; /** - * A query parameter that limits the number of results returned. The + * A query parameter that limits the number of results returned for supported URIs. The * parameter value should be an integer. + * + *

    This parameter is not supported by all URIs. Supported URIs include, but not limited to, + * {@link Contacts#CONTENT_URI}, + * {@link RawContacts#CONTENT_URI}, + * {@link Data#CONTENT_URI}, + * {@link CommonDataKinds.Phone#CONTENT_URI}, + * {@link CommonDataKinds.Callable#CONTENT_URI}, + * {@link CommonDataKinds.Email#CONTENT_URI}, + * {@link CommonDataKinds.Contactables#CONTENT_URI}, + * + *

    In order to limit the number of rows returned by a non-supported URI, you can implement a + * {@link CursorWrapper} and override the {@link CursorWrapper#getCount()} methods. */ public static final String LIMIT_PARAM_KEY = "limit"; @@ -437,6 +450,9 @@ public final class ContactsContract { /** * _ID of the default directory, which represents locally stored contacts. + * This is only supported by {@link ContactsContract.Contacts#CONTENT_URI} and + * {@link ContactsContract.Contacts#CONTENT_FILTER_URI}. + * Other URLs do not support the concept of "visible" or "invisible" contacts. */ public static final long DEFAULT = 0; diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 1158776f5fd1715af3f3399bd83039a85eabc7df..d587ba80a18c7dbfddfcbb2cf740af00d4a77452 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -235,7 +235,6 @@ public final class DocumentsContract { * @see #FLAG_DIR_PREFERS_GRID * @see #FLAG_DIR_PREFERS_LAST_MODIFIED * @see #FLAG_VIRTUAL_DOCUMENT - * @see #FLAG_ARCHIVE * @see #FLAG_SUPPORTS_COPY * @see #FLAG_SUPPORTS_MOVE * @see #FLAG_SUPPORTS_REMOVE @@ -326,7 +325,7 @@ public final class DocumentsContract { * Flag indicating that a document can be renamed. * * @see #COLUMN_FLAGS - * @see DocumentsContract#renameDocument(ContentProviderClient, Uri, + * @see DocumentsContract#renameDocument(ContentResolver, Uri, * String) * @see DocumentsProvider#renameDocument(String, String) */ @@ -337,7 +336,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#copyDocument(ContentProviderClient, Uri, Uri) + * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#copyDocument(String, String) */ public static final int FLAG_SUPPORTS_COPY = 1 << 7; @@ -347,7 +346,7 @@ public final class DocumentsContract { * within the same document provider. * * @see #COLUMN_FLAGS - * @see DocumentsContract#moveDocument(ContentProviderClient, Uri, Uri, Uri) + * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri) * @see DocumentsProvider#moveDocument(String, String, String) */ public static final int FLAG_SUPPORTS_MOVE = 1 << 8; @@ -368,7 +367,7 @@ public final class DocumentsContract { * Flag indicating that a document can be removed from a parent. * * @see #COLUMN_FLAGS - * @see DocumentsContract#removeDocument(ContentProviderClient, Uri, Uri) + * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri) * @see DocumentsProvider#removeDocument(String, String) */ public static final int FLAG_SUPPORTS_REMOVE = 1 << 10; @@ -870,7 +869,7 @@ public final class DocumentsContract { * Test if the given URI represents a {@link Document} tree. * * @see #buildTreeDocumentUri(String, String) - * @see #getTreeDocumentId(Uri, String) + * @see #getTreeDocumentId(Uri) */ public static boolean isTreeUri(Uri uri) { final List paths = uri.getPathSegments(); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f8c120ad4ef216e16201f971019a23ddf8f67365..ea0f6b6785d18fe9321c7eecc5f787677442143e 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -44,7 +44,6 @@ import android.net.ConnectivityManager; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; -import android.os.Binder; import android.os.Bundle; import android.os.DropBoxManager; import android.os.IBinder; @@ -455,6 +454,22 @@ public final class Settings { public static final String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS"; + /** + * Activity Action: Show settings to allow configuration of Night display. + *

    + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + *

    + * Input: Nothing. + *

    + * Output: Nothing. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_NIGHT_DISPLAY_SETTINGS = + "android.settings.NIGHT_DISPLAY_SETTINGS"; + /** * Activity Action: Show settings to allow configuration of locale. *

    @@ -1283,6 +1298,19 @@ public final class Settings { public static final String ACTION_VR_LISTENER_SETTINGS = "android.settings.VR_LISTENER_SETTINGS"; + /** + * Activity Action: Show Storage Manager settings. + *

    + * Input: Nothing. + *

    + * Output: Nothing. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_STORAGE_MANAGER_SETTINGS + = "android.settings.STORAGE_MANAGER_SETTINGS"; + /** * Activity Action: Allows user to select current webview implementation. *

    @@ -1564,7 +1592,7 @@ public final class Settings { private IContentProvider lazyGetProvider(ContentResolver cr) { IContentProvider cp = null; - synchronized (this) { + synchronized (NameValueCache.this) { cp = mContentProvider; if (cp == null) { cp = mContentProvider = cr.acquireProvider(mUri.getAuthority()); @@ -1591,7 +1619,7 @@ public final class Settings { public String getStringForUser(ContentResolver cr, String name, final int userHandle) { final boolean isSelf = (userHandle == UserHandle.myUserId()); if (isSelf) { - synchronized (this) { + synchronized (NameValueCache.this) { if (mGenerationTracker != null) { if (mGenerationTracker.isGenerationChanged()) { if (DEBUG) { @@ -1624,7 +1652,7 @@ public final class Settings { args.putInt(CALL_METHOD_USER_KEY, userHandle); } boolean needsGenerationTracker = false; - synchronized (this) { + synchronized (NameValueCache.this) { if (isSelf && mGenerationTracker == null) { needsGenerationTracker = true; if (args == null) { @@ -1643,7 +1671,7 @@ public final class Settings { String value = b.getString(Settings.NameValueTable.VALUE); // Don't update our cache for reads of other users' data if (isSelf) { - synchronized (this) { + synchronized (NameValueCache.this) { if (needsGenerationTracker) { MemoryIntArray array = b.getParcelable( CALL_METHOD_TRACK_GENERATION_KEY); @@ -1660,7 +1688,7 @@ public final class Settings { } mGenerationTracker = new GenerationTracker(array, index, generation, () -> { - synchronized (this) { + synchronized (NameValueCache.this) { Log.e(TAG, "Error accessing generation" + " tracker - removing"); if (mGenerationTracker != null) { @@ -1701,7 +1729,7 @@ public final class Settings { } String value = c.moveToNext() ? c.getString(0) : null; - synchronized (this) { + synchronized (NameValueCache.this) { mValues.put(name, value); } if (LOCAL_LOGV) { @@ -1838,7 +1866,6 @@ public final class Settings { MOVED_TO_GLOBAL.add(Settings.Global.CALL_AUTO_RETRY); MOVED_TO_GLOBAL.add(Settings.Global.DEBUG_APP); MOVED_TO_GLOBAL.add(Settings.Global.WAIT_FOR_DEBUGGER); - MOVED_TO_GLOBAL.add(Settings.Global.SHOW_PROCESSES); MOVED_TO_GLOBAL.add(Settings.Global.ALWAYS_FINISH_ACTIVITIES); MOVED_TO_GLOBAL.add(Settings.Global.TZINFO_UPDATE_CONTENT_URL); MOVED_TO_GLOBAL.add(Settings.Global.TZINFO_UPDATE_METADATA_URL); @@ -2775,7 +2802,8 @@ public final class Settings { /** * Control whether the process CPU usage meter should be shown. * - * @deprecated Use {@link Global#SHOW_PROCESSES} instead + * @deprecated This functionality is no longer available as of + * {@link android.os.Build.VERSION_CODES#N_MR1}. */ @Deprecated public static final String SHOW_PROCESSES = Global.SHOW_PROCESSES; @@ -5310,15 +5338,6 @@ public final class Settings { public static final String ACCESSIBILITY_DISPLAY_DALTONIZER = "accessibility_display_daltonizer"; - /** - * Float list that specifies the color matrix to apply to - * the display. Valid values are defined in AccessibilityManager. - * - * @hide - */ - public static final String ACCESSIBILITY_DISPLAY_COLOR_MATRIX = - "accessibility_display_color_matrix"; - /** * Setting that specifies whether automatic click when the mouse pointer stops moving is * enabled. @@ -5353,6 +5372,13 @@ public final class Settings { */ public static final String LONG_PRESS_TIMEOUT = "long_press_timeout"; + /** + * The duration in milliseconds between the first tap's up event and the second tap's + * down event for an interaction to be considered part of the same multi-press. + * @hide + */ + public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout"; + /** * List of the enabled print services. * @@ -5848,6 +5874,8 @@ public final class Settings { /** * If nonzero, ANRs in invisible background processes bring up a dialog. * Otherwise, the process will be silently killed. + * + * Also prevents ANRs and crash dialogs from being suppressed. * @hide */ public static final String ANR_SHOW_BACKGROUND = "anr_show_background"; @@ -5923,6 +5951,36 @@ public final class Settings { public static final int INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT = INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF; + /** + * What happens when the user presses the Back button while in-call + * and the screen is on.
    + * Values:
    + * 0 - The Back buttons does nothing different.
    + * 1 - The Back button hangs up the current call.
    + * + * @hide + */ + public static final String INCALL_BACK_BUTTON_BEHAVIOR = "incall_back_button_behavior"; + + /** + * INCALL_BACK_BUTTON_BEHAVIOR value for no action. + * @hide + */ + public static final int INCALL_BACK_BUTTON_BEHAVIOR_NONE = 0x0; + + /** + * INCALL_BACK_BUTTON_BEHAVIOR value for "hang up". + * @hide + */ + public static final int INCALL_BACK_BUTTON_BEHAVIOR_HANGUP = 0x1; + + /** + * INCALL_POWER_BUTTON_BEHAVIOR default value. + * @hide + */ + public static final int INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT = + INCALL_BACK_BUTTON_BEHAVIOR_NONE; + /** * Whether the device should wake when the wake gesture sensor detects motion. * @hide @@ -5935,6 +5993,18 @@ public final class Settings { */ public static final String DOZE_ENABLED = "doze_enabled"; + /** + * Whether the device should pulse on pick up gesture. + * @hide + */ + public static final String DOZE_PULSE_ON_PICK_UP = "doze_pulse_on_pick_up"; + + /** + * Whether the device should pulse on double tap gesture. + * @hide + */ + public static final String DOZE_PULSE_ON_DOUBLE_TAP = "doze_pulse_on_double_tap"; + /** * The current night mode that has been selected by the user. Owned * and controlled by UiModeManagerService. Constants are as per @@ -6027,6 +6097,17 @@ public final class Settings { */ public static final String ASSIST_SCREENSHOT_ENABLED = "assist_screenshot_enabled"; + /** + * Specifies whether the screen will show an animation if screen contents are sent to the + * assist application (active voice interaction service). + * + * Note that the disclosure will be forced for third-party assistants or if the device + * does not support disabling it. + * + * @hide + */ + public static final String ASSIST_DISCLOSURE_ENABLED = "assist_disclosure_enabled"; + /** * Names of the service components that the current user has explicitly allowed to * see all of the user's notifications, separated by ':'. @@ -6163,44 +6244,39 @@ public final class Settings { "camera_double_tap_power_gesture_disabled"; /** - - /** - * Behavior of twilight on the device. - * One of {@link #TWILIGHT_MODE_LOCKED_OFF}, {@link #TWILIGHT_MODE_LOCKED_ON} - * or {@link #TWILIGHT_MODE_AUTO}. - * @hide - */ - public static final String TWILIGHT_MODE = "twilight_mode"; - - /** - * Twilight mode always off. + * Whether the camera double twist gesture to flip between front and back mode should be + * enabled. + * * @hide */ - public static final int TWILIGHT_MODE_LOCKED_OFF = 0; + public static final String CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED = + "camera_double_twist_to_flip_enabled"; /** - * Twilight mode always on. + * Control whether Night display is currently activated. * @hide */ - public static final int TWILIGHT_MODE_LOCKED_ON = 1; + public static final String NIGHT_DISPLAY_ACTIVATED = "night_display_activated"; /** - * Twilight mode auto. + * Control whether Night display will automatically activate/deactivate. * @hide */ - public static final int TWILIGHT_MODE_AUTO = 2; + public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode"; /** - * Twilight mode auto, temporarily overriden to on. + * Custom time when Night display is scheduled to activate. + * Represented as milliseconds from midnight (e.g. 79200000 == 10pm). * @hide */ - public static final int TWILIGHT_MODE_AUTO_OVERRIDE_OFF = 3; + public static final String NIGHT_DISPLAY_CUSTOM_START_TIME = "night_display_custom_start_time"; /** - * Twilight mode auto, temporarily overriden to off. + * Custom time when Night display is scheduled to deactivate. + * Represented as milliseconds from midnight (e.g. 21600000 == 6am). * @hide */ - public static final int TWILIGHT_MODE_AUTO_OVERRIDE_ON = 4; + public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time"; /** * Whether brightness should automatically adjust based on twilight state. @@ -6243,6 +6319,20 @@ public final class Settings { */ public static final int VR_DISPLAY_MODE_OFF = 1; + /** + * Whether CarrierAppUtils#disableCarrierAppsUntilPrivileged has been executed at least + * once. + * + *

    This is used to ensure that we only take one pass which will disable apps that are not + * privileged (if any). From then on, we only want to enable apps (when a matching SIM is + * inserted), to avoid disabling an app that the user might actively be using. + * + *

    Will be set to 1 once executed. + * + * @hide + */ + public static final String CARRIER_APPS_HANDLED = "carrier_apps_handled"; + /** * Whether parent user can access remote contact in managed profile. * @@ -6251,6 +6341,80 @@ public final class Settings { public static final String MANAGED_PROFILE_CONTACT_REMOTE_SEARCH = "managed_profile_contact_remote_search"; + /** + * Whether or not the automatic storage manager is enabled and should run on the device. + * + * @hide + */ + public static final String AUTOMATIC_STORAGE_MANAGER_ENABLED = + "automatic_storage_manager_enabled"; + + /** + * How many days of information for the automatic storage manager to retain on the device. + * + * @hide + */ + public static final String AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN = + "automatic_storage_manager_days_to_retain"; + + /** + * Default number of days of information for the automatic storage manager to retain. + * + * @hide + */ + public static final int AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_DEFAULT = 90; + + /** + * How many bytes the automatic storage manager has cleared out. + * + * @hide + */ + public static final String AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED = + "automatic_storage_manager_bytes_cleared"; + + + /** + * Last run time for the automatic storage manager. + * + * @hide + */ + public static final String AUTOMATIC_STORAGE_MANAGER_LAST_RUN = + "automatic_storage_manager_last_run"; + + + /** + * Whether SystemUI navigation keys is enabled. + * @hide + */ + public static final String SYSTEM_NAVIGATION_KEYS_ENABLED = + "system_navigation_keys_enabled"; + + /** + * Holds comma separated list of ordering of QS tiles. + * @hide + */ + public static final String QS_TILES = "sysui_qs_tiles"; + + /** + * Whether preloaded APKs have been installed for the user. + * @hide + */ + public static final String DEMO_USER_SETUP_COMPLETE + = "demo_user_setup_complete"; + + /** + * Specifies whether the web action API is enabled. + * + * @hide + */ + public static final String WEB_ACTION_ENABLED = "web_action_enabled"; + + /** + * Has this pairable device been paired or upgraded from a previously paired system. + * @hide + */ + public static final String DEVICE_PAIRED = "device_paired"; + /** * This are the settings to be backed up. * @@ -6268,7 +6432,6 @@ public final class Settings { USB_MASS_STORAGE_ENABLED, // moved to global ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, ACCESSIBILITY_DISPLAY_DALTONIZER, - ACCESSIBILITY_DISPLAY_COLOR_MATRIX, ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, @@ -6324,7 +6487,18 @@ public final class Settings { PREFERRED_TTY_MODE, ENHANCED_VOICE_PRIVACY_ENABLED, TTY_MODE_ENABLED, - INCALL_POWER_BUTTON_BEHAVIOR + INCALL_POWER_BUTTON_BEHAVIOR, + NIGHT_DISPLAY_CUSTOM_START_TIME, + NIGHT_DISPLAY_CUSTOM_END_TIME, + NIGHT_DISPLAY_AUTO_MODE, + NIGHT_DISPLAY_ACTIVATED, + CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, + CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + SYSTEM_NAVIGATION_KEYS_ENABLED, + QS_TILES, + DOZE_ENABLED, + DOZE_PULSE_ON_PICK_UP, + DOZE_PULSE_ON_DOUBLE_TAP }; /** @@ -7326,27 +7500,54 @@ public final class Settings { public static final String WEBVIEW_DATA_REDUCTION_PROXY_KEY = "webview_data_reduction_proxy_key"; - /** - * Whether or not the WebView fallback mechanism should be enabled. - * 0=disabled, 1=enabled. - * @hide - */ - public static final String WEBVIEW_FALLBACK_LOGIC_ENABLED = - "webview_fallback_logic_enabled"; + /** + * Whether or not the WebView fallback mechanism should be enabled. + * 0=disabled, 1=enabled. + * @hide + */ + public static final String WEBVIEW_FALLBACK_LOGIC_ENABLED = + "webview_fallback_logic_enabled"; - /** - * Name of the package used as WebView provider (if unset the provider is instead determined - * by the system). - * @hide - */ - public static final String WEBVIEW_PROVIDER = "webview_provider"; + /** + * Name of the package used as WebView provider (if unset the provider is instead determined + * by the system). + * @hide + */ + public static final String WEBVIEW_PROVIDER = "webview_provider"; - /** - * Developer setting to enable WebView multiprocess rendering. - * @hide - */ - @SystemApi - public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess"; + /** + * Developer setting to enable WebView multiprocess rendering. + * @hide + */ + @SystemApi + public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess"; + + /** + * The maximum number of notifications shown in 24 hours when switching networks. + * @hide + */ + public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT = + "network_switch_notification_daily_limit"; + + /** + * The minimum time in milliseconds between notifications when switching networks. + * @hide + */ + public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS = + "network_switch_notification_rate_limit_millis"; + + /** + * Whether to automatically switch away from wifi networks that lose Internet access. + * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always + * avoids such networks. Valid values are: + * + * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013. + * null: Ask the user whether to switch away from bad wifi. + * 1: Avoid bad wifi. + * + * @hide + */ + public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi"; /** * Whether Wifi display is enabled/disabled @@ -7834,11 +8035,36 @@ public final class Settings { /** * The server used for captive portal detection upon a new conection. A * 204 response code from the server is used for validation. + * TODO: remove this deprecated symbol. * * @hide */ public static final String CAPTIVE_PORTAL_SERVER = "captive_portal_server"; + /** + * The URL used for HTTPS captive portal detection upon a new connection. + * A 204 response code from the server is used for validation. + * + * @hide + */ + public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url"; + + /** + * The URL used for HTTP captive portal detection upon a new connection. + * A 204 response code from the server is used for validation. + * + * @hide + */ + public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url"; + + /** + * The URL used for fallback HTTP captive portal detection when previous HTTP + * and HTTPS captive portal detection attemps did not return a conclusive answer. + * + * @hide + */ + public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url"; + /** * Whether to use HTTPS for network validation. This is enabled by default and the setting * needs to be set to 0 to disable it. This setting is a misnomer because captive portals @@ -7848,6 +8074,14 @@ public final class Settings { */ public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https"; + /** + * Which User-Agent string to use in the header of the captive portal detection probes. + * The User-Agent field is unset when this setting has no value (HttpUrlConnection default). + * + * @hide + */ + public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent"; + /** * Whether network service discovery is enabled. * @@ -8269,7 +8503,11 @@ public final class Settings { /** * Control whether the process CPU usage meter should be shown. + * + * @deprecated This functionality is no longer available as of + * {@link android.os.Build.VERSION_CODES#N_MR1}. */ + @Deprecated public static final String SHOW_PROCESSES = "show_processes"; /** @@ -8534,8 +8772,6 @@ public final class Settings { /** * The name of the device - * - * @hide */ public static final String DEVICE_NAME = "device_name"; @@ -8583,7 +8819,7 @@ public final class Settings { public static final String WFC_IMS_ENABLED = "wfc_ims_enabled"; /** - * WFC Mode. + * WFC mode on home/non-roaming network. *

    * Type: int - 2=Wi-Fi preferred, 1=Cellular preferred, 0=Wi-Fi only * @@ -8591,6 +8827,15 @@ public final class Settings { */ public static final String WFC_IMS_MODE = "wfc_ims_mode"; + /** + * WFC mode on roaming network. + *

    + * Type: int - see {@link WFC_IMS_MODE} for values + * + * @hide + */ + public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode"; + /** * Whether WFC roaming is enabled *

    @@ -8618,6 +8863,34 @@ public final class Settings { public static final String EPHEMERAL_COOKIE_MAX_SIZE_BYTES = "ephemeral_cookie_max_size_bytes"; + /** + * Toggle to enable/disable the entire ephemeral feature. By default, ephemeral is + * enabled. Set to zero to disable. + *

    + * Type: int (0 for false, 1 for true) + * + * @hide + */ + public static final String ENABLE_EPHEMERAL_FEATURE = "enable_ephemeral_feature"; + + /** + * A mask applied to the ephemeral hash to generate the hash prefix. + *

    + * Type: int + * + * @hide + */ + public static final String EPHEMERAL_HASH_PREFIX_MASK = "ephemeral_hash_prefix_mask"; + + /** + * Number of hash prefixes to send during ephemeral resolution. + *

    + * Type: int + * + * @hide + */ + public static final String EPHEMERAL_HASH_PREFIX_COUNT = "ephemeral_hash_prefix_count"; + /** * The duration for caching uninstalled ephemeral apps. *

    @@ -8653,6 +8926,41 @@ public final class Settings { */ public static final String SAFE_BOOT_DISALLOWED = "safe_boot_disallowed"; + /** + * Whether this device is currently in retail demo mode. If true, device + * usage is severely limited. + *

    + * Type: int (0 for false, 1 for true) + * @hide + */ + public static final String DEVICE_DEMO_MODE = "device_demo_mode"; + + /** + * Retail mode specific settings. This is encoded as a key=value list, separated by commas. + * Ex: "user_inactivity_timeout_ms=30000,warning_dialog_timeout_ms=10000". The following + * keys are supported: + * + *

    +         * user_inactivity_timeout_ms  (long)
    +         * warning_dialog_timeout_ms   (long)
    +         * 
    + *

    + * Type: string + * + * @hide + */ + public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants"; + + /** + * The reason for the settings database being downgraded. This is only for + * troubleshooting purposes and its value should not be interpreted in any way. + * + * Type: string + * + * @hide + */ + public static final String DATABASE_DOWNGRADE_REASON = "database_downgrade_reason"; + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. @@ -9058,6 +9366,12 @@ public final class Settings { * @hide */ public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate"; + + /** + * Whether cell is enabled/disabled + * @hide + */ + public static final String CELL_ON = "cell_on"; } /** diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java index 6a3cc0205f1812873336dbf08d29e180fb8e932e..5099eebf6eb1600000495e4ee17c6115f6282214 100644 --- a/core/java/android/provider/VoicemailContract.java +++ b/core/java/android/provider/VoicemailContract.java @@ -25,13 +25,11 @@ import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; -import android.database.Cursor; import android.net.Uri; import android.provider.CallLog.Calls; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.Voicemail; - import java.util.List; /** @@ -106,12 +104,74 @@ public class VoicemailContract { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL"; + /** + * Broadcast intent to inform a new visual voicemail SMS has been received. This intent will + * only be delivered to the voicemail client. The intent will have the following extra values: + * + *

      + *
    • {@link #EXTRA_VOICEMAIL_SMS_TYPE} - (String) The event type of the SMS. Common + * values are "SYNC" or "STATUS"
    • + *
    • {@link #EXTRA_VOICEMAIL_SMS_DATA} - (Bundle) The fields sent by the SMS
    • + *
    • {@link #EXTRA_VOICEMAIL_SMS_SUBID} - (Integer) The subscription ID of the + * phone account that received the SMS
    • + *
    + */ + /** @hide */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_VOICEMAIL_SMS_RECEIVED = + "android.intent.action.VOICEMAIL_SMS_RECEIVED"; + + /** + * Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to + * indicate the event type of the SMS. Common values are "SYNC" or "STATUS". The extra will not + * exist if the framework cannot parse the SMS as voicemail but the carrier pattern indicates + * it is. + */ + /** @hide */ + public static final String EXTRA_VOICEMAIL_SMS_PREFIX = + "com.android.voicemail.extra.VOICEMAIL_SMS_PREFIX"; + + /** + * Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to + * indicate the fields sent by the SMS. The extra will not exist if the framework cannot + * parse the SMS as voicemail but the carrier pattern indicates it is. + */ + /** @hide */ + public static final String EXTRA_VOICEMAIL_SMS_FIELDS = + "com.android.voicemail.extra.VOICEMAIL_SMS_FIELDS"; + + /** + * Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate the + * message body of the SMS. This extra is included if the framework cannot + * parse the SMS as voicemail but the carrier pattern indicates it is. + */ + /** + * @hide + */ + public static final String EXTRA_VOICEMAIL_SMS_MESSAGE_BODY = + "com.android.voicemail.extra.VOICEMAIL_SMS_MESSAGE_BODY"; + + /** + * Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate he + * subscription ID of the phone account that received the SMS. + */ + /** @hide */ + public static final String EXTRA_VOICEMAIL_SMS_SUBID = + "com.android.voicemail.extra.VOICEMAIL_SMS_SUBID"; + /** * Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the * receiving package made this change. */ public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE"; + /** + * Extra included in {@link #ACTION_SYNC_VOICEMAIL} broadcast intents to indicate which {@link + * PhoneAccountHandle} to sync. + */ + public static final String EXTRA_PHONE_ACCOUNT_HANDLE = + "android.provider.extra.PHONE_ACCOUNT_HANDLE"; + /** * Name of the source package field, which must be same across all voicemail related tables. * This is an internal field. @@ -360,6 +420,20 @@ public class VoicemailContract { */ public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD; + /** + * The type of the source, which determines how to interpret source-specific states. + * Typically this will be set to the same string as + * {@link android.telephony.CarrierConfigManager#KEY_VVM_TYPE_STRING}. For example, + * "vvm_type_omtp". + * + *

    Type: TEXT

    + * + * @see #CONFIGURATION_STATE + * @see #DATA_CHANNEL_STATE + * @see #NOTIFICATION_CHANNEL_STATE + */ + public static final String SOURCE_TYPE = "source_type"; + // Note: Multiple entries may exist for a single source if they are differentiated by the // PHONE_ACCOUNT_* fields. @@ -392,21 +466,21 @@ public class VoicemailContract { public static final String VOICEMAIL_ACCESS_URI = "voicemail_access_uri"; /** * The configuration state of the voicemail source. + * + *

    Negative values are reserved to the source for source-specific states, see + * {@link #SOURCE_TYPE} + * *

    Possible values: * {@link #CONFIGURATION_STATE_OK}, * {@link #CONFIGURATION_STATE_NOT_CONFIGURED}, * {@link #CONFIGURATION_STATE_CAN_BE_CONFIGURED} + * {@link #CONFIGURATION_STATE_CONFIGURING} + * {@link #CONFIGURATION_STATE_FAILED} + * {@link #CONFIGURATION_STATE_DISABLED} *

    Type: INTEGER

    */ public static final String CONFIGURATION_STATE = "configuration_state"; - /** - * Value of {@link #CONFIGURATION_STATE} passed into - * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the - * {@link #CONFIGURATION_STATE} field is not to be changed - * - * @hide - */ - public static final int CONFIGURATION_STATE_IGNORE = -1; + /** Value of {@link #CONFIGURATION_STATE} to indicate an all OK configuration status. */ public static final int CONFIGURATION_STATE_OK = 0; /** @@ -421,9 +495,28 @@ public class VoicemailContract { * upgraded to visual voicemail and would like to show a set up invitation message. */ public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; + /** + * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail still is being + * configured. + */ + public static final int CONFIGURATION_STATE_CONFIGURING = 3; + /** + * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail has failed to + * be configured. + */ + public static final int CONFIGURATION_STATE_FAILED = 4; + /** + * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail is disabled by + * the user. + */ + public static final int CONFIGURATION_STATE_DISABLED = 5; /** * The data channel state of the voicemail source. This the channel through which the source * pulls voicemail data from a remote server. + * + *

    Negative values are reserved to the source for source-specific states, see + * {@link #SOURCE_TYPE} + * *

    Possible values: * {@link #DATA_CHANNEL_STATE_OK}, * {@link #DATA_CHANNEL_STATE_NO_CONNECTION} @@ -431,14 +524,7 @@ public class VoicemailContract { *

    Type: INTEGER

    */ public static final String DATA_CHANNEL_STATE = "data_channel_state"; - /** - * Value of {@link #DATA_CHANNEL_STATE} passed into - * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the - * {@link #DATA_CHANNEL_STATE} field is not to be changed - * - * @hide - */ - public static final int DATA_CHANNEL_STATE_IGNORE = -1; + /** * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel is working fine. */ @@ -478,6 +564,10 @@ public class VoicemailContract { /** * The notification channel state of the voicemail source. This is the channel through which * the source gets notified of new voicemails on the remote server. + * + *

    Negative values are reserved to the source for source-specific states, see + * {@link #SOURCE_TYPE} + * *

    Possible values: * {@link #NOTIFICATION_CHANNEL_STATE_OK}, * {@link #NOTIFICATION_CHANNEL_STATE_NO_CONNECTION}, @@ -486,14 +576,7 @@ public class VoicemailContract { *

    Type: INTEGER

    */ public static final String NOTIFICATION_CHANNEL_STATE = "notification_channel_state"; - /** - * Value of {@link #NOTIFICATION_CHANNEL_STATE} passed into - * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the - * {@link #NOTIFICATION_CHANNEL_STATE} field is not to be changed - * - * @hide - */ - public static final int NOTIFICATION_CHANNEL_STATE_IGNORE = -1; + /** * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel is * working fine. @@ -543,67 +626,5 @@ public class VoicemailContract { return Status.CONTENT_URI.buildUpon() .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build(); } - - /** - * A helper method to set the status of a voicemail source. - * - * @param context The context from the package calling the method. This will be the source. - * @param accountHandle The handle for the account the source is associated with. - * @param configurationState See {@link Status#CONFIGURATION_STATE} - * @param dataChannelState See {@link Status#DATA_CHANNEL_STATE} - * @param notificationChannelState See {@link Status#NOTIFICATION_CHANNEL_STATE} - * - * @hide - */ - public static void setStatus(Context context, PhoneAccountHandle accountHandle, - int configurationState, int dataChannelState, int notificationChannelState) { - ContentValues values = new ContentValues(); - values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME, - accountHandle.getComponentName().flattenToString()); - values.put(Status.PHONE_ACCOUNT_ID, accountHandle.getId()); - if(configurationState != CONFIGURATION_STATE_IGNORE) { - values.put(Status.CONFIGURATION_STATE, configurationState); - } - if(dataChannelState != DATA_CHANNEL_STATE_IGNORE) { - values.put(Status.DATA_CHANNEL_STATE, dataChannelState); - } - if(notificationChannelState != NOTIFICATION_CHANNEL_STATE_IGNORE) { - values.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState); - } - ContentResolver contentResolver = context.getContentResolver(); - Uri statusUri = buildSourceUri(context.getPackageName()); - contentResolver.insert(statusUri, values); - } - - /** - * A helper method to set the quota of a voicemail source. Unit is unspecified. - * - * @param context The context from the package calling the method. This will be the source. - * @param accountHandle The handle for the account the source is associated with. - * @param occupied See {@link Status#QUOTA_OCCUPIED} - * @param total See {@link Status#QUOTA_TOTAL} - * - * @hide - */ - public static void setQuota(Context context, PhoneAccountHandle accountHandle, int occupied, - int total) { - if (occupied == QUOTA_UNAVAILABLE && total == QUOTA_UNAVAILABLE) { - return; - } - ContentValues values = new ContentValues(); - values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME, - accountHandle.getComponentName().flattenToString()); - values.put(Status.PHONE_ACCOUNT_ID, accountHandle.getId()); - if (occupied != QUOTA_UNAVAILABLE) { - values.put(Status.QUOTA_OCCUPIED,occupied); - } - if (total != QUOTA_UNAVAILABLE) { - values.put(Status.QUOTA_TOTAL,total); - } - - ContentResolver contentResolver = context.getContentResolver(); - Uri statusUri = buildSourceUri(context.getPackageName()); - contentResolver.insert(statusUri, values); - } } } diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl index 8689dce3fef5505ca439de4ed44c324264730a9d..641e1ada6eaa2382a0866779769c353fe4d764b1 100644 --- a/core/java/android/security/IKeystoreService.aidl +++ b/core/java/android/security/IKeystoreService.aidl @@ -76,4 +76,5 @@ interface IKeystoreService { int onUserAdded(int userId, int parentId); int onUserRemoved(int userId); int attestKey(String alias, in KeymasterArguments params, out KeymasterCertificateChain chain); + int onDeviceOffBody(); } diff --git a/core/java/android/security/net/config/DirectoryCertificateSource.java b/core/java/android/security/net/config/DirectoryCertificateSource.java index e3c9d659c91bb579dcecc3419cbbf1771cca2bfa..119f5d0de0a06c9859c795ec07407485be887640 100644 --- a/core/java/android/security/net/config/DirectoryCertificateSource.java +++ b/core/java/android/security/net/config/DirectoryCertificateSource.java @@ -19,6 +19,7 @@ package android.security.net.config; import android.os.Environment; import android.os.UserHandle; import android.util.ArraySet; +import android.util.Log; import android.util.Pair; import java.io.BufferedInputStream; import java.io.File; @@ -44,6 +45,7 @@ import javax.security.auth.x500.X500Principal; * @hide */ abstract class DirectoryCertificateSource implements CertificateSource { + private static final String LOG_TAG = "DirectoryCertificateSrc"; private final File mDir; private final Object mLock = new Object(); private final CertificateFactory mCertFactory; @@ -149,6 +151,9 @@ abstract class DirectoryCertificateSource implements CertificateSource { continue; } X509Certificate cert = readCertificate(fileName); + if (cert == null) { + continue; + } if (!subj.equals(cert.getSubjectX500Principal())) { continue; } @@ -173,6 +178,9 @@ abstract class DirectoryCertificateSource implements CertificateSource { continue; } X509Certificate cert = readCertificate(fileName); + if (cert == null) { + continue; + } if (!subj.equals(cert.getSubjectX500Principal())) { continue; } @@ -194,6 +202,7 @@ abstract class DirectoryCertificateSource implements CertificateSource { is = new BufferedInputStream(new FileInputStream(new File(mDir, file))); return (X509Certificate) mCertFactory.generateCertificate(is); } catch (CertificateException | IOException e) { + Log.e(LOG_TAG, "Failed to read certificate from " + file, e); return null; } finally { IoUtils.closeQuietly(is); diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java index a70c24d6886b2fe697f13e6fe6ac71a873b105c0..b47e872d47f832a82cc569589ceb55345bb05ff0 100644 --- a/core/java/android/service/carrier/CarrierIdentifier.java +++ b/core/java/android/service/carrier/CarrierIdentifier.java @@ -126,4 +126,13 @@ public class CarrierIdentifier implements Parcelable { mGid1 = in.readString(); mGid2 = in.readString(); } + + /** @hide */ + public interface MatchType { + int ALL = 0; + int SPN = 1; + int IMSI_PREFIX = 2; + int GID1 = 3; + int GID2 = 4; + } } diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 0557d138eb741a11c77d43c22d2577b274bfe1bd..94505d37310deebd319f9b8e326f48cbab0d5766 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -27,6 +27,7 @@ import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.os.Handler; import android.os.IBinder; +import android.os.IRemoteCallback; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; @@ -942,8 +943,9 @@ public class DreamService extends Service implements Window.Callback { * Must run on mHandler. * * @param windowToken A window token that will allow a window to be created in the correct layer. + * @param started A callback that will be invoked once onDreamingStarted has completed. */ - private final void attach(IBinder windowToken, boolean canDoze) { + private final void attach(IBinder windowToken, boolean canDoze, IRemoteCallback started) { if (mWindowToken != null) { Slog.e(TAG, "attach() called when already attached with token=" + mWindowToken); return; @@ -1017,7 +1019,15 @@ public class DreamService extends Service implements Window.Callback { if (mWindow != null || mWindowless) { if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()"); mStarted = true; - onDreamingStarted(); + try { + onDreamingStarted(); + } finally { + try { + started.sendResult(null); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } } }); @@ -1092,11 +1102,12 @@ public class DreamService extends Service implements Window.Callback { private final class DreamServiceWrapper extends IDreamService.Stub { @Override - public void attach(final IBinder windowToken, final boolean canDoze) { + public void attach(final IBinder windowToken, final boolean canDoze, + IRemoteCallback started) { mHandler.post(new Runnable() { @Override public void run() { - DreamService.this.attach(windowToken, canDoze); + DreamService.this.attach(windowToken, canDoze, started); } }); } diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl index 9bb18044e3eab7b8d1b6daa086dd59f5ffa2b778..ce04354989179e46cc49fc29ea4f7b071bc57ebd 100644 --- a/core/java/android/service/dreams/IDreamService.aidl +++ b/core/java/android/service/dreams/IDreamService.aidl @@ -16,11 +16,13 @@ package android.service.dreams; +import android.os.IRemoteCallback; + /** * @hide */ oneway interface IDreamService { - void attach(IBinder windowToken, boolean canDoze); + void attach(IBinder windowToken, boolean canDoze, IRemoteCallback started); void detach(); void wakeUp(); } diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 1d9784b6e23f39d97432f840d6c781ad38990050..474a9b63f96ea58a76cb98bf45e64e6a4a86d239 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -20,6 +20,8 @@ import android.app.ActivityManager; import android.app.NotificationManager.Policy; import android.content.ComponentName; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.Uri; import android.os.Parcel; @@ -42,6 +44,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import java.util.Objects; @@ -118,6 +121,7 @@ public class ZenModeConfig implements Parcelable { private static final String RULE_ATT_ZEN = "zen"; private static final String RULE_ATT_CONDITION_ID = "conditionId"; private static final String RULE_ATT_CREATION_TIME = "creationTime"; + private static final String RULE_ATT_ENABLER = "enabler"; public boolean allowCalls = DEFAULT_ALLOW_CALLS; public boolean allowRepeatCallers = DEFAULT_ALLOW_REPEAT_CALLERS; @@ -502,6 +506,7 @@ public class ZenModeConfig implements Parcelable { rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID); rt.component = safeComponentName(parser, RULE_ATT_COMPONENT); rt.creationTime = safeLong(parser, RULE_ATT_CREATION_TIME, 0); + rt.enabler = parser.getAttributeValue(null, RULE_ATT_ENABLER); rt.condition = readConditionXml(parser); return rt; } @@ -520,6 +525,9 @@ public class ZenModeConfig implements Parcelable { out.attribute(null, RULE_ATT_CONDITION_ID, rule.conditionId.toString()); } out.attribute(null, RULE_ATT_CREATION_TIME, Long.toString(rule.creationTime)); + if (rule.enabler != null) { + out.attribute(null, RULE_ATT_ENABLER, rule.enabler); + } if (rule.condition != null) { writeConditionXml(rule.condition, out); } @@ -889,9 +897,13 @@ public class ZenModeConfig implements Parcelable { ", endHour=" + endHour + ", endMinute=" + endMinute + ", exitAtAlarm=" + exitAtAlarm + - ", nextAlarm=" + nextAlarm + + ", nextAlarm=" + ts(nextAlarm) + '}'; } + + protected static String ts(long time) { + return new Date(time) + " (" + time + ")"; + } } // ==== Built-in system condition: event ==== @@ -989,6 +1001,25 @@ public class ZenModeConfig implements Parcelable { return UUID.randomUUID().toString().replace("-", ""); } + private static String getOwnerCaption(Context context, String owner) { + final PackageManager pm = context.getPackageManager(); + try { + final ApplicationInfo info = pm.getApplicationInfo(owner, 0); + if (info != null) { + final CharSequence seq = info.loadLabel(pm); + if (seq != null) { + final String str = seq.toString().trim(); + if (str.length() > 0) { + return str; + } + } + } + } catch (Throwable e) { + Slog.w(TAG, "Error loading owner caption", e); + } + return ""; + } + public static String getConditionSummary(Context context, ZenModeConfig config, int userHandle, boolean shortVersion) { return getConditionLine(context, config, userHandle, false /*useLine1*/, shortVersion); @@ -997,23 +1028,28 @@ public class ZenModeConfig implements Parcelable { private static String getConditionLine(Context context, ZenModeConfig config, int userHandle, boolean useLine1, boolean shortVersion) { if (config == null) return ""; + String summary = ""; if (config.manualRule != null) { final Uri id = config.manualRule.conditionId; - if (id == null) { - return context.getString(com.android.internal.R.string.zen_mode_forever); - } - final long time = tryParseCountdownConditionId(id); - Condition c = config.manualRule.condition; - if (time > 0) { - final long now = System.currentTimeMillis(); - final long span = time - now; - c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS), - userHandle, shortVersion); + if (config.manualRule.enabler != null) { + summary = getOwnerCaption(context, config.manualRule.enabler); + } else { + if (id == null) { + summary = context.getString(com.android.internal.R.string.zen_mode_forever); + } else { + final long time = tryParseCountdownConditionId(id); + Condition c = config.manualRule.condition; + if (time > 0) { + final long now = System.currentTimeMillis(); + final long span = time - now; + c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS), + userHandle, shortVersion); + } + final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary; + summary = TextUtils.isEmpty(rt) ? "" : rt; + } } - final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary; - return TextUtils.isEmpty(rt) ? "" : rt; } - String summary = ""; for (ZenRule automaticRule : config.automaticRules.values()) { if (automaticRule.isAutomaticActive()) { if (summary.isEmpty()) { @@ -1023,6 +1059,7 @@ public class ZenModeConfig implements Parcelable { .getString(R.string.zen_mode_rule_name_combination, summary, automaticRule.name); } + } } return summary; @@ -1038,6 +1075,7 @@ public class ZenModeConfig implements Parcelable { public ComponentName component; // optional public String id; // required for automatic (unique) public long creationTime; // required for automatic + public String enabler; // package name, only used for manual rules. public ZenRule() { } @@ -1055,6 +1093,9 @@ public class ZenModeConfig implements Parcelable { id = source.readString(); } creationTime = source.readLong(); + if (source.readInt() == 1) { + enabler = source.readString(); + } } @Override @@ -1083,6 +1124,12 @@ public class ZenModeConfig implements Parcelable { dest.writeInt(0); } dest.writeLong(creationTime); + if (enabler != null) { + dest.writeInt(1); + dest.writeString(enabler); + } else { + dest.writeInt(0); + } } @Override @@ -1097,6 +1144,7 @@ public class ZenModeConfig implements Parcelable { .append(",component=").append(component) .append(",id=").append(id) .append(",creationTime=").append(creationTime) + .append(",enabler=").append(enabler) .append(']').toString(); } @@ -1143,6 +1191,9 @@ public class ZenModeConfig implements Parcelable { if (creationTime != to.creationTime) { d.addLine(item, "creationTime", creationTime, to.creationTime); } + if (enabler != to.enabler) { + d.addLine(item, "enabler", enabler, to.enabler); + } } @Override @@ -1158,13 +1209,14 @@ public class ZenModeConfig implements Parcelable { && Objects.equals(other.condition, condition) && Objects.equals(other.component, component) && Objects.equals(other.id, id) - && other.creationTime == creationTime; + && other.creationTime == creationTime + && Objects.equals(other.enabler, enabler); } @Override public int hashCode() { return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition, - component, id, creationTime); + component, id, creationTime, enabler); } public boolean isAutomaticActive() { diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java index cfeed51da86f2bd3e6f3edc6792556582fcabe5f..0f92ed04a457b91786150dc30c4b2b339bc1d437 100644 --- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java +++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java @@ -163,10 +163,9 @@ public class PersistentDataBlockManager { /** * Retrieves available information about this device's flash lock state. * - * @return FLASH_LOCK_STATE_LOCKED if device bootloader is locked, - * FLASH_LOCK_STATE_UNLOCKED if device bootloader is unlocked, - * or FLASH_LOCK_STATE unknown if this information cannot be ascertained - * on this device. + * @return {@link #FLASH_LOCK_LOCKED} if device bootloader is locked, + * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN} + * if this information cannot be ascertained on this device. */ @FlashLockState public int getFlashLockState() { diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl index bf963570b040e036e0626c3571221442d2d1a10d..d03ff93be5ceefb1e3267b6fb02b701aa23cb5c2 100644 --- a/core/java/android/service/quicksettings/IQSService.aidl +++ b/core/java/android/service/quicksettings/IQSService.aidl @@ -23,16 +23,16 @@ import android.service.quicksettings.Tile; * @hide */ interface IQSService { - Tile getTile(in ComponentName component); - void updateQsTile(in Tile tile); - void updateStatusIcon(in Tile tile, in Icon icon, + Tile getTile(in IBinder tile); + void updateQsTile(in Tile tile, in IBinder service); + void updateStatusIcon(in IBinder tile, in Icon icon, String contentDescription); - void onShowDialog(in Tile tile); - void onStartActivity(in Tile tile); + void onShowDialog(in IBinder tile); + void onStartActivity(in IBinder tile); boolean isLocked(); boolean isSecure(); - void startUnlockAndRun(in Tile tile); + void startUnlockAndRun(in IBinder tile); - void onDialogHidden(in Tile tile); - void onStartSuccessful(in Tile tile); + void onDialogHidden(in IBinder tile); + void onStartSuccessful(in IBinder tile); } diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java index 3d7d53ea67e8a2bb9d6f5455ff7ae534bddb2e5c..4b81a726085227f32aef95fb8f53b08783a04cb1 100644 --- a/core/java/android/service/quicksettings/Tile.java +++ b/core/java/android/service/quicksettings/Tile.java @@ -15,8 +15,8 @@ */ package android.service.quicksettings; -import android.content.ComponentName; import android.graphics.drawable.Icon; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; @@ -59,7 +59,7 @@ public final class Tile implements Parcelable { */ public static final int STATE_ACTIVE = 2; - private ComponentName mComponentName; + private IBinder mToken; private Icon mIcon; private CharSequence mLabel; private CharSequence mContentDescription; @@ -78,29 +78,15 @@ public final class Tile implements Parcelable { /** * @hide */ - public Tile(ComponentName componentName) { - mComponentName = componentName; + public Tile() { } /** * @hide */ - public void setService(IQSService service) { + public void setService(IQSService service, IBinder stub) { mService = service; - } - - /** - * @hide - */ - public ComponentName getComponentName() { - return mComponentName; - } - - /** - * @hide - */ - public IQSService getQsService() { - return mService; + mToken = stub; } /** @@ -193,7 +179,7 @@ public final class Tile implements Parcelable { */ public void updateTile() { try { - mService.updateQsTile(this); + mService.updateQsTile(this, mToken); } catch (RemoteException e) { Log.e(TAG, "Couldn't update tile"); } @@ -201,12 +187,6 @@ public final class Tile implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - if (mComponentName != null) { - dest.writeByte((byte) 1); - mComponentName.writeToParcel(dest, flags); - } else { - dest.writeByte((byte) 0); - } if (mIcon != null) { dest.writeByte((byte) 1); mIcon.writeToParcel(dest, flags); @@ -219,11 +199,6 @@ public final class Tile implements Parcelable { } private void readFromParcel(Parcel source) { - if (source.readByte() != 0) { - mComponentName = ComponentName.CREATOR.createFromParcel(source); - } else { - mComponentName = null; - } if (source.readByte() != 0) { mIcon = Icon.CREATOR.createFromParcel(source); } else { diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index 50411ab7d15e926f1286ed4ed13073f20f2cfc35..887f4b6577b9171fb587cce22807dc3bf33b96ed 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -120,6 +120,11 @@ public class TileService extends Service { */ public static final String EXTRA_SERVICE = "service"; + /** + * @hide + */ + public static final String EXTRA_TOKEN = "token"; + /** * @hide */ @@ -132,6 +137,7 @@ public class TileService extends Service { private IBinder mToken; private IQSService mService; private Runnable mUnlockRunnable; + private IBinder mTileToken; @Override public void onDestroy() { @@ -197,7 +203,7 @@ public class TileService extends Service { public final void setStatusIcon(Icon icon, String contentDescription) { if (mService != null) { try { - mService.updateStatusIcon(mTile, icon, contentDescription); + mService.updateStatusIcon(mTileToken, icon, contentDescription); } catch (RemoteException e) { } } @@ -224,14 +230,14 @@ public class TileService extends Service { @Override public void onViewDetachedFromWindow(View v) { try { - mService.onDialogHidden(getQsTile()); + mService.onDialogHidden(mTileToken); } catch (RemoteException e) { } } }); dialog.show(); try { - mService.onShowDialog(mTile); + mService.onShowDialog(mTileToken); } catch (RemoteException e) { } } @@ -246,7 +252,7 @@ public class TileService extends Service { public final void unlockAndRun(Runnable runnable) { mUnlockRunnable = runnable; try { - mService.startUnlockAndRun(mTile); + mService.startUnlockAndRun(mTileToken); } catch (RemoteException e) { } } @@ -292,7 +298,7 @@ public class TileService extends Service { public final void startActivityAndCollapse(Intent intent) { startActivity(intent); try { - mService.onStartActivity(mTile); + mService.onStartActivity(mTileToken); } catch (RemoteException e) { } } @@ -311,14 +317,14 @@ public class TileService extends Service { @Override public IBinder onBind(Intent intent) { mService = IQSService.Stub.asInterface(intent.getIBinderExtra(EXTRA_SERVICE)); + mTileToken = intent.getIBinderExtra(EXTRA_TOKEN); try { - ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT); - mTile = mService.getTile(component); + mTile = mService.getTile(mTileToken); } catch (RemoteException e) { throw new RuntimeException("Unable to reach IQSService", e); } if (mTile != null) { - mTile.setService(mService); + mTile.setService(mService, mTileToken); mHandler.sendEmptyMessage(H.MSG_START_SUCCESS); } return new IQSTileService.Stub() { @@ -403,7 +409,7 @@ public class TileService extends Service { break; case MSG_START_SUCCESS: try { - mService.onStartSuccessful(mTile); + mService.onStartSuccessful(mTileToken); } catch (RemoteException e) { } break; diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index de8133b33aa6fa6cf83a04b07d814310658fe98d..06d87f84699d1052f52a60d83e3747f9fe5173b3 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -55,6 +55,7 @@ import android.view.SurfaceHolder; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; import java.io.FileDescriptor; @@ -628,9 +629,9 @@ public abstract class WallpaperService extends Service { mCurWindowFlags = mWindowFlags; mLayout.flags = mWindowFlags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - ; + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; mCurWindowPrivateFlags = mWindowPrivateFlags; mLayout.privateFlags = mWindowPrivateFlags; diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java index b62cc66b52690f8752f506d685da640361e47564..b6d720d453e9eebf6f7e9ada6533b20e68e56119 100644 --- a/core/java/android/text/Emoji.java +++ b/core/java/android/text/Emoji.java @@ -32,111 +32,112 @@ public class Emoji { 0x23EC, 0x23ED, 0x23EE, 0x23EF, 0x23F0, 0x23F1, 0x23F2, 0x23F3, 0x23F8, 0x23F9, 0x23FA, 0x24C2, 0x25AA, 0x25AB, 0x25B6, 0x25C0, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x2600, 0x2601, 0x2602, 0x2603, 0x2604, 0x260E, 0x2611, 0x2614, 0x2615, 0x2618, 0x261D, 0x2620, 0x2622, - 0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2648, 0x2649, 0x264A, - 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, 0x2660, 0x2663, - 0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2696, 0x2697, 0x2699, - 0x269B, 0x269C, 0x26A0, 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1, 0x26BD, 0x26BE, 0x26C4, - 0x26C5, 0x26C8, 0x26CE, 0x26CF, 0x26D1, 0x26D3, 0x26D4, 0x26E9, 0x26EA, 0x26F0, 0x26F1, - 0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, 0x26F9, 0x26FA, 0x26FD, 0x2702, 0x2705, - 0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270F, 0x2712, 0x2714, 0x2716, 0x271D, - 0x2721, 0x2728, 0x2733, 0x2734, 0x2744, 0x2747, 0x274C, 0x274E, 0x2753, 0x2754, 0x2755, - 0x2757, 0x2763, 0x2764, 0x2795, 0x2796, 0x2797, 0x27A1, 0x27B0, 0x27BF, 0x2934, 0x2935, - 0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299, - 0x1F004, 0x1F0CF, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F18E, 0x1F191, 0x1F192, 0x1F193, - 0x1F194, 0x1F195, 0x1F196, 0x1F197, 0x1F198, 0x1F199, 0x1F19A, 0x1F1E6, 0x1F1E7, 0x1F1E8, - 0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE, 0x1F1EF, 0x1F1F0, 0x1F1F1, 0x1F1F2, - 0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7, 0x1F1F8, 0x1F1F9, 0x1F1FA, 0x1F1FB, 0x1F1FC, - 0x1F1FD, 0x1F1FE, 0x1F1FF, 0x1F201, 0x1F202, 0x1F21A, 0x1F22F, 0x1F232, 0x1F233, 0x1F234, - 0x1F235, 0x1F236, 0x1F237, 0x1F238, 0x1F239, 0x1F23A, 0x1F250, 0x1F251, 0x1F300, 0x1F301, - 0x1F302, 0x1F303, 0x1F304, 0x1F305, 0x1F306, 0x1F307, 0x1F308, 0x1F309, 0x1F30A, 0x1F30B, - 0x1F30C, 0x1F30D, 0x1F30E, 0x1F30F, 0x1F310, 0x1F311, 0x1F312, 0x1F313, 0x1F314, 0x1F315, - 0x1F316, 0x1F317, 0x1F318, 0x1F319, 0x1F31A, 0x1F31B, 0x1F31C, 0x1F31D, 0x1F31E, 0x1F31F, - 0x1F320, 0x1F321, 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328, 0x1F329, 0x1F32A, 0x1F32B, - 0x1F32C, 0x1F32D, 0x1F32E, 0x1F32F, 0x1F330, 0x1F331, 0x1F332, 0x1F333, 0x1F334, 0x1F335, - 0x1F336, 0x1F337, 0x1F338, 0x1F339, 0x1F33A, 0x1F33B, 0x1F33C, 0x1F33D, 0x1F33E, 0x1F33F, - 0x1F340, 0x1F341, 0x1F342, 0x1F343, 0x1F344, 0x1F345, 0x1F346, 0x1F347, 0x1F348, 0x1F349, - 0x1F34A, 0x1F34B, 0x1F34C, 0x1F34D, 0x1F34E, 0x1F34F, 0x1F350, 0x1F351, 0x1F352, 0x1F353, - 0x1F354, 0x1F355, 0x1F356, 0x1F357, 0x1F358, 0x1F359, 0x1F35A, 0x1F35B, 0x1F35C, 0x1F35D, - 0x1F35E, 0x1F35F, 0x1F360, 0x1F361, 0x1F362, 0x1F363, 0x1F364, 0x1F365, 0x1F366, 0x1F367, - 0x1F368, 0x1F369, 0x1F36A, 0x1F36B, 0x1F36C, 0x1F36D, 0x1F36E, 0x1F36F, 0x1F370, 0x1F371, - 0x1F372, 0x1F373, 0x1F374, 0x1F375, 0x1F376, 0x1F377, 0x1F378, 0x1F379, 0x1F37A, 0x1F37B, - 0x1F37C, 0x1F37D, 0x1F37E, 0x1F37F, 0x1F380, 0x1F381, 0x1F382, 0x1F383, 0x1F384, 0x1F385, - 0x1F386, 0x1F387, 0x1F388, 0x1F389, 0x1F38A, 0x1F38B, 0x1F38C, 0x1F38D, 0x1F38E, 0x1F38F, - 0x1F390, 0x1F391, 0x1F392, 0x1F393, 0x1F396, 0x1F397, 0x1F399, 0x1F39A, 0x1F39B, 0x1F39E, - 0x1F39F, 0x1F3A0, 0x1F3A1, 0x1F3A2, 0x1F3A3, 0x1F3A4, 0x1F3A5, 0x1F3A6, 0x1F3A7, 0x1F3A8, - 0x1F3A9, 0x1F3AA, 0x1F3AB, 0x1F3AC, 0x1F3AD, 0x1F3AE, 0x1F3AF, 0x1F3B0, 0x1F3B1, 0x1F3B2, - 0x1F3B3, 0x1F3B4, 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B8, 0x1F3B9, 0x1F3BA, 0x1F3BB, 0x1F3BC, - 0x1F3BD, 0x1F3BE, 0x1F3BF, 0x1F3C0, 0x1F3C1, 0x1F3C2, 0x1F3C3, 0x1F3C4, 0x1F3C5, 0x1F3C6, - 0x1F3C7, 0x1F3C8, 0x1F3C9, 0x1F3CA, 0x1F3CB, 0x1F3CC, 0x1F3CD, 0x1F3CE, 0x1F3CF, 0x1F3D0, - 0x1F3D1, 0x1F3D2, 0x1F3D3, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7, 0x1F3D8, 0x1F3D9, 0x1F3DA, - 0x1F3DB, 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3E0, 0x1F3E1, 0x1F3E2, 0x1F3E3, 0x1F3E4, - 0x1F3E5, 0x1F3E6, 0x1F3E7, 0x1F3E8, 0x1F3E9, 0x1F3EA, 0x1F3EB, 0x1F3EC, 0x1F3ED, 0x1F3EE, - 0x1F3EF, 0x1F3F0, 0x1F3F3, 0x1F3F4, 0x1F3F5, 0x1F3F7, 0x1F3F8, 0x1F3F9, 0x1F3FA, 0x1F3FB, - 0x1F3FC, 0x1F3FD, 0x1F3FE, 0x1F3FF, 0x1F400, 0x1F401, 0x1F402, 0x1F403, 0x1F404, 0x1F405, - 0x1F406, 0x1F407, 0x1F408, 0x1F409, 0x1F40A, 0x1F40B, 0x1F40C, 0x1F40D, 0x1F40E, 0x1F40F, - 0x1F410, 0x1F411, 0x1F412, 0x1F413, 0x1F414, 0x1F415, 0x1F416, 0x1F417, 0x1F418, 0x1F419, - 0x1F41A, 0x1F41B, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41F, 0x1F420, 0x1F421, 0x1F422, 0x1F423, - 0x1F424, 0x1F425, 0x1F426, 0x1F427, 0x1F428, 0x1F429, 0x1F42A, 0x1F42B, 0x1F42C, 0x1F42D, - 0x1F42E, 0x1F42F, 0x1F430, 0x1F431, 0x1F432, 0x1F433, 0x1F434, 0x1F435, 0x1F436, 0x1F437, - 0x1F438, 0x1F439, 0x1F43A, 0x1F43B, 0x1F43C, 0x1F43D, 0x1F43E, 0x1F43F, 0x1F440, 0x1F441, - 0x1F442, 0x1F443, 0x1F444, 0x1F445, 0x1F446, 0x1F447, 0x1F448, 0x1F449, 0x1F44A, 0x1F44B, - 0x1F44C, 0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F451, 0x1F452, 0x1F453, 0x1F454, 0x1F455, - 0x1F456, 0x1F457, 0x1F458, 0x1F459, 0x1F45A, 0x1F45B, 0x1F45C, 0x1F45D, 0x1F45E, 0x1F45F, - 0x1F460, 0x1F461, 0x1F462, 0x1F463, 0x1F464, 0x1F465, 0x1F466, 0x1F467, 0x1F468, 0x1F469, - 0x1F46A, 0x1F46B, 0x1F46C, 0x1F46D, 0x1F46E, 0x1F46F, 0x1F470, 0x1F471, 0x1F472, 0x1F473, - 0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F479, 0x1F47A, 0x1F47B, 0x1F47C, 0x1F47D, - 0x1F47E, 0x1F47F, 0x1F480, 0x1F481, 0x1F482, 0x1F483, 0x1F484, 0x1F485, 0x1F486, 0x1F487, - 0x1F488, 0x1F489, 0x1F48A, 0x1F48B, 0x1F48C, 0x1F48D, 0x1F48E, 0x1F48F, 0x1F490, 0x1F491, - 0x1F492, 0x1F493, 0x1F494, 0x1F495, 0x1F496, 0x1F497, 0x1F498, 0x1F499, 0x1F49A, 0x1F49B, - 0x1F49C, 0x1F49D, 0x1F49E, 0x1F49F, 0x1F4A0, 0x1F4A1, 0x1F4A2, 0x1F4A3, 0x1F4A4, 0x1F4A5, - 0x1F4A6, 0x1F4A7, 0x1F4A8, 0x1F4A9, 0x1F4AA, 0x1F4AB, 0x1F4AC, 0x1F4AD, 0x1F4AE, 0x1F4AF, - 0x1F4B0, 0x1F4B1, 0x1F4B2, 0x1F4B3, 0x1F4B4, 0x1F4B5, 0x1F4B6, 0x1F4B7, 0x1F4B8, 0x1F4B9, - 0x1F4BA, 0x1F4BB, 0x1F4BC, 0x1F4BD, 0x1F4BE, 0x1F4BF, 0x1F4C0, 0x1F4C1, 0x1F4C2, 0x1F4C3, - 0x1F4C4, 0x1F4C5, 0x1F4C6, 0x1F4C7, 0x1F4C8, 0x1F4C9, 0x1F4CA, 0x1F4CB, 0x1F4CC, 0x1F4CD, - 0x1F4CE, 0x1F4CF, 0x1F4D0, 0x1F4D1, 0x1F4D2, 0x1F4D3, 0x1F4D4, 0x1F4D5, 0x1F4D6, 0x1F4D7, - 0x1F4D8, 0x1F4D9, 0x1F4DA, 0x1F4DB, 0x1F4DC, 0x1F4DD, 0x1F4DE, 0x1F4DF, 0x1F4E0, 0x1F4E1, - 0x1F4E2, 0x1F4E3, 0x1F4E4, 0x1F4E5, 0x1F4E6, 0x1F4E7, 0x1F4E8, 0x1F4E9, 0x1F4EA, 0x1F4EB, - 0x1F4EC, 0x1F4ED, 0x1F4EE, 0x1F4EF, 0x1F4F0, 0x1F4F1, 0x1F4F2, 0x1F4F3, 0x1F4F4, 0x1F4F5, - 0x1F4F6, 0x1F4F7, 0x1F4F8, 0x1F4F9, 0x1F4FA, 0x1F4FB, 0x1F4FC, 0x1F4FD, 0x1F4FF, 0x1F500, - 0x1F501, 0x1F502, 0x1F503, 0x1F504, 0x1F505, 0x1F506, 0x1F507, 0x1F508, 0x1F509, 0x1F50A, - 0x1F50B, 0x1F50C, 0x1F50D, 0x1F50E, 0x1F50F, 0x1F510, 0x1F511, 0x1F512, 0x1F513, 0x1F514, - 0x1F515, 0x1F516, 0x1F517, 0x1F518, 0x1F519, 0x1F51A, 0x1F51B, 0x1F51C, 0x1F51D, 0x1F51E, - 0x1F51F, 0x1F520, 0x1F521, 0x1F522, 0x1F523, 0x1F524, 0x1F525, 0x1F526, 0x1F527, 0x1F528, - 0x1F529, 0x1F52A, 0x1F52B, 0x1F52C, 0x1F52D, 0x1F52E, 0x1F52F, 0x1F530, 0x1F531, 0x1F532, - 0x1F533, 0x1F534, 0x1F535, 0x1F536, 0x1F537, 0x1F538, 0x1F539, 0x1F53A, 0x1F53B, 0x1F53C, - 0x1F53D, 0x1F549, 0x1F54A, 0x1F54B, 0x1F54C, 0x1F54D, 0x1F54E, 0x1F550, 0x1F551, 0x1F552, - 0x1F553, 0x1F554, 0x1F555, 0x1F556, 0x1F557, 0x1F558, 0x1F559, 0x1F55A, 0x1F55B, 0x1F55C, - 0x1F55D, 0x1F55E, 0x1F55F, 0x1F560, 0x1F561, 0x1F562, 0x1F563, 0x1F564, 0x1F565, 0x1F566, - 0x1F567, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576, 0x1F577, 0x1F578, 0x1F579, - 0x1F57A, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590, 0x1F595, 0x1F596, 0x1F5A4, - 0x1F5A5, 0x1F5A8, 0x1F5B1, 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3, 0x1F5C4, 0x1F5D1, 0x1F5D2, - 0x1F5D3, 0x1F5DC, 0x1F5DD, 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8, 0x1F5EF, 0x1F5F3, 0x1F5FA, - 0x1F5FB, 0x1F5FC, 0x1F5FD, 0x1F5FE, 0x1F5FF, 0x1F600, 0x1F601, 0x1F602, 0x1F603, 0x1F604, - 0x1F605, 0x1F606, 0x1F607, 0x1F608, 0x1F609, 0x1F60A, 0x1F60B, 0x1F60C, 0x1F60D, 0x1F60E, - 0x1F60F, 0x1F610, 0x1F611, 0x1F612, 0x1F613, 0x1F614, 0x1F615, 0x1F616, 0x1F617, 0x1F618, - 0x1F619, 0x1F61A, 0x1F61B, 0x1F61C, 0x1F61D, 0x1F61E, 0x1F61F, 0x1F620, 0x1F621, 0x1F622, - 0x1F623, 0x1F624, 0x1F625, 0x1F626, 0x1F627, 0x1F628, 0x1F629, 0x1F62A, 0x1F62B, 0x1F62C, - 0x1F62D, 0x1F62E, 0x1F62F, 0x1F630, 0x1F631, 0x1F632, 0x1F633, 0x1F634, 0x1F635, 0x1F636, - 0x1F637, 0x1F638, 0x1F639, 0x1F63A, 0x1F63B, 0x1F63C, 0x1F63D, 0x1F63E, 0x1F63F, 0x1F640, - 0x1F641, 0x1F642, 0x1F643, 0x1F644, 0x1F645, 0x1F646, 0x1F647, 0x1F648, 0x1F649, 0x1F64A, - 0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F680, 0x1F681, 0x1F682, 0x1F683, 0x1F684, - 0x1F685, 0x1F686, 0x1F687, 0x1F688, 0x1F689, 0x1F68A, 0x1F68B, 0x1F68C, 0x1F68D, 0x1F68E, - 0x1F68F, 0x1F690, 0x1F691, 0x1F692, 0x1F693, 0x1F694, 0x1F695, 0x1F696, 0x1F697, 0x1F698, - 0x1F699, 0x1F69A, 0x1F69B, 0x1F69C, 0x1F69D, 0x1F69E, 0x1F69F, 0x1F6A0, 0x1F6A1, 0x1F6A2, - 0x1F6A3, 0x1F6A4, 0x1F6A5, 0x1F6A6, 0x1F6A7, 0x1F6A8, 0x1F6A9, 0x1F6AA, 0x1F6AB, 0x1F6AC, - 0x1F6AD, 0x1F6AE, 0x1F6AF, 0x1F6B0, 0x1F6B1, 0x1F6B2, 0x1F6B3, 0x1F6B4, 0x1F6B5, 0x1F6B6, - 0x1F6B7, 0x1F6B8, 0x1F6B9, 0x1F6BA, 0x1F6BB, 0x1F6BC, 0x1F6BD, 0x1F6BE, 0x1F6BF, 0x1F6C0, - 0x1F6C1, 0x1F6C2, 0x1F6C3, 0x1F6C4, 0x1F6C5, 0x1F6CB, 0x1F6CC, 0x1F6CD, 0x1F6CE, 0x1F6CF, - 0x1F6D0, 0x1F6D1, 0x1F6D2, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3, 0x1F6E4, 0x1F6E5, 0x1F6E9, - 0x1F6EB, 0x1F6EC, 0x1F6F0, 0x1F6F3, 0x1F6F4, 0x1F6F5, 0x1F6F6, 0x1F910, 0x1F911, 0x1F912, - 0x1F913, 0x1F914, 0x1F915, 0x1F916, 0x1F917, 0x1F918, 0x1F919, 0x1F91A, 0x1F91B, 0x1F91C, - 0x1F91D, 0x1F91E, 0x1F920, 0x1F921, 0x1F922, 0x1F923, 0x1F924, 0x1F925, 0x1F926, 0x1F927, - 0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938, 0x1F939, 0x1F93A, 0x1F93B, - 0x1F93C, 0x1F93D, 0x1F93E, 0x1F940, 0x1F941, 0x1F942, 0x1F943, 0x1F944, 0x1F945, 0x1F946, - 0x1F947, 0x1F948, 0x1F949, 0x1F94A, 0x1F94B, 0x1F950, 0x1F951, 0x1F952, 0x1F953, 0x1F954, - 0x1F955, 0x1F956, 0x1F957, 0x1F958, 0x1F959, 0x1F95A, 0x1F95B, 0x1F95C, 0x1F95D, 0x1F95E, - 0x1F980, 0x1F981, 0x1F982, 0x1F983, 0x1F984, 0x1F985, 0x1F986, 0x1F987, 0x1F988, 0x1F989, - 0x1F98A, 0x1F98B, 0x1F98C, 0x1F98D, 0x1F98E, 0x1F98F, 0x1F990, 0x1F991, 0x1F9C0 + 0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2640, 0x2642, 0x2648, + 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, + 0x2660, 0x2663, 0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2695, + 0x2696, 0x2697, 0x2699, 0x269B, 0x269C, 0x26A0, 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1, + 0x26BD, 0x26BE, 0x26C4, 0x26C5, 0x26C8, 0x26CE, 0x26CF, 0x26D1, 0x26D3, 0x26D4, 0x26E9, + 0x26EA, 0x26F0, 0x26F1, 0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, 0x26F9, 0x26FA, + 0x26FD, 0x2702, 0x2705, 0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270F, 0x2712, + 0x2714, 0x2716, 0x271D, 0x2721, 0x2728, 0x2733, 0x2734, 0x2744, 0x2747, 0x274C, 0x274E, + 0x2753, 0x2754, 0x2755, 0x2757, 0x2763, 0x2764, 0x2795, 0x2796, 0x2797, 0x27A1, 0x27B0, + 0x27BF, 0x2934, 0x2935, 0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030, + 0x303D, 0x3297, 0x3299, 0x1F004, 0x1F0CF, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F18E, + 0x1F191, 0x1F192, 0x1F193, 0x1F194, 0x1F195, 0x1F196, 0x1F197, 0x1F198, 0x1F199, 0x1F19A, + 0x1F1E6, 0x1F1E7, 0x1F1E8, 0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE, 0x1F1EF, + 0x1F1F0, 0x1F1F1, 0x1F1F2, 0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7, 0x1F1F8, 0x1F1F9, + 0x1F1FA, 0x1F1FB, 0x1F1FC, 0x1F1FD, 0x1F1FE, 0x1F1FF, 0x1F201, 0x1F202, 0x1F21A, 0x1F22F, + 0x1F232, 0x1F233, 0x1F234, 0x1F235, 0x1F236, 0x1F237, 0x1F238, 0x1F239, 0x1F23A, 0x1F250, + 0x1F251, 0x1F300, 0x1F301, 0x1F302, 0x1F303, 0x1F304, 0x1F305, 0x1F306, 0x1F307, 0x1F308, + 0x1F309, 0x1F30A, 0x1F30B, 0x1F30C, 0x1F30D, 0x1F30E, 0x1F30F, 0x1F310, 0x1F311, 0x1F312, + 0x1F313, 0x1F314, 0x1F315, 0x1F316, 0x1F317, 0x1F318, 0x1F319, 0x1F31A, 0x1F31B, 0x1F31C, + 0x1F31D, 0x1F31E, 0x1F31F, 0x1F320, 0x1F321, 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328, + 0x1F329, 0x1F32A, 0x1F32B, 0x1F32C, 0x1F32D, 0x1F32E, 0x1F32F, 0x1F330, 0x1F331, 0x1F332, + 0x1F333, 0x1F334, 0x1F335, 0x1F336, 0x1F337, 0x1F338, 0x1F339, 0x1F33A, 0x1F33B, 0x1F33C, + 0x1F33D, 0x1F33E, 0x1F33F, 0x1F340, 0x1F341, 0x1F342, 0x1F343, 0x1F344, 0x1F345, 0x1F346, + 0x1F347, 0x1F348, 0x1F349, 0x1F34A, 0x1F34B, 0x1F34C, 0x1F34D, 0x1F34E, 0x1F34F, 0x1F350, + 0x1F351, 0x1F352, 0x1F353, 0x1F354, 0x1F355, 0x1F356, 0x1F357, 0x1F358, 0x1F359, 0x1F35A, + 0x1F35B, 0x1F35C, 0x1F35D, 0x1F35E, 0x1F35F, 0x1F360, 0x1F361, 0x1F362, 0x1F363, 0x1F364, + 0x1F365, 0x1F366, 0x1F367, 0x1F368, 0x1F369, 0x1F36A, 0x1F36B, 0x1F36C, 0x1F36D, 0x1F36E, + 0x1F36F, 0x1F370, 0x1F371, 0x1F372, 0x1F373, 0x1F374, 0x1F375, 0x1F376, 0x1F377, 0x1F378, + 0x1F379, 0x1F37A, 0x1F37B, 0x1F37C, 0x1F37D, 0x1F37E, 0x1F37F, 0x1F380, 0x1F381, 0x1F382, + 0x1F383, 0x1F384, 0x1F385, 0x1F386, 0x1F387, 0x1F388, 0x1F389, 0x1F38A, 0x1F38B, 0x1F38C, + 0x1F38D, 0x1F38E, 0x1F38F, 0x1F390, 0x1F391, 0x1F392, 0x1F393, 0x1F396, 0x1F397, 0x1F399, + 0x1F39A, 0x1F39B, 0x1F39E, 0x1F39F, 0x1F3A0, 0x1F3A1, 0x1F3A2, 0x1F3A3, 0x1F3A4, 0x1F3A5, + 0x1F3A6, 0x1F3A7, 0x1F3A8, 0x1F3A9, 0x1F3AA, 0x1F3AB, 0x1F3AC, 0x1F3AD, 0x1F3AE, 0x1F3AF, + 0x1F3B0, 0x1F3B1, 0x1F3B2, 0x1F3B3, 0x1F3B4, 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B8, 0x1F3B9, + 0x1F3BA, 0x1F3BB, 0x1F3BC, 0x1F3BD, 0x1F3BE, 0x1F3BF, 0x1F3C0, 0x1F3C1, 0x1F3C2, 0x1F3C3, + 0x1F3C4, 0x1F3C5, 0x1F3C6, 0x1F3C7, 0x1F3C8, 0x1F3C9, 0x1F3CA, 0x1F3CB, 0x1F3CC, 0x1F3CD, + 0x1F3CE, 0x1F3CF, 0x1F3D0, 0x1F3D1, 0x1F3D2, 0x1F3D3, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7, + 0x1F3D8, 0x1F3D9, 0x1F3DA, 0x1F3DB, 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3E0, 0x1F3E1, + 0x1F3E2, 0x1F3E3, 0x1F3E4, 0x1F3E5, 0x1F3E6, 0x1F3E7, 0x1F3E8, 0x1F3E9, 0x1F3EA, 0x1F3EB, + 0x1F3EC, 0x1F3ED, 0x1F3EE, 0x1F3EF, 0x1F3F0, 0x1F3F3, 0x1F3F4, 0x1F3F5, 0x1F3F7, 0x1F3F8, + 0x1F3F9, 0x1F3FA, 0x1F3FB, 0x1F3FC, 0x1F3FD, 0x1F3FE, 0x1F3FF, 0x1F400, 0x1F401, 0x1F402, + 0x1F403, 0x1F404, 0x1F405, 0x1F406, 0x1F407, 0x1F408, 0x1F409, 0x1F40A, 0x1F40B, 0x1F40C, + 0x1F40D, 0x1F40E, 0x1F40F, 0x1F410, 0x1F411, 0x1F412, 0x1F413, 0x1F414, 0x1F415, 0x1F416, + 0x1F417, 0x1F418, 0x1F419, 0x1F41A, 0x1F41B, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41F, 0x1F420, + 0x1F421, 0x1F422, 0x1F423, 0x1F424, 0x1F425, 0x1F426, 0x1F427, 0x1F428, 0x1F429, 0x1F42A, + 0x1F42B, 0x1F42C, 0x1F42D, 0x1F42E, 0x1F42F, 0x1F430, 0x1F431, 0x1F432, 0x1F433, 0x1F434, + 0x1F435, 0x1F436, 0x1F437, 0x1F438, 0x1F439, 0x1F43A, 0x1F43B, 0x1F43C, 0x1F43D, 0x1F43E, + 0x1F43F, 0x1F440, 0x1F441, 0x1F442, 0x1F443, 0x1F444, 0x1F445, 0x1F446, 0x1F447, 0x1F448, + 0x1F449, 0x1F44A, 0x1F44B, 0x1F44C, 0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F451, 0x1F452, + 0x1F453, 0x1F454, 0x1F455, 0x1F456, 0x1F457, 0x1F458, 0x1F459, 0x1F45A, 0x1F45B, 0x1F45C, + 0x1F45D, 0x1F45E, 0x1F45F, 0x1F460, 0x1F461, 0x1F462, 0x1F463, 0x1F464, 0x1F465, 0x1F466, + 0x1F467, 0x1F468, 0x1F469, 0x1F46A, 0x1F46B, 0x1F46C, 0x1F46D, 0x1F46E, 0x1F46F, 0x1F470, + 0x1F471, 0x1F472, 0x1F473, 0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F479, 0x1F47A, + 0x1F47B, 0x1F47C, 0x1F47D, 0x1F47E, 0x1F47F, 0x1F480, 0x1F481, 0x1F482, 0x1F483, 0x1F484, + 0x1F485, 0x1F486, 0x1F487, 0x1F488, 0x1F489, 0x1F48A, 0x1F48B, 0x1F48C, 0x1F48D, 0x1F48E, + 0x1F48F, 0x1F490, 0x1F491, 0x1F492, 0x1F493, 0x1F494, 0x1F495, 0x1F496, 0x1F497, 0x1F498, + 0x1F499, 0x1F49A, 0x1F49B, 0x1F49C, 0x1F49D, 0x1F49E, 0x1F49F, 0x1F4A0, 0x1F4A1, 0x1F4A2, + 0x1F4A3, 0x1F4A4, 0x1F4A5, 0x1F4A6, 0x1F4A7, 0x1F4A8, 0x1F4A9, 0x1F4AA, 0x1F4AB, 0x1F4AC, + 0x1F4AD, 0x1F4AE, 0x1F4AF, 0x1F4B0, 0x1F4B1, 0x1F4B2, 0x1F4B3, 0x1F4B4, 0x1F4B5, 0x1F4B6, + 0x1F4B7, 0x1F4B8, 0x1F4B9, 0x1F4BA, 0x1F4BB, 0x1F4BC, 0x1F4BD, 0x1F4BE, 0x1F4BF, 0x1F4C0, + 0x1F4C1, 0x1F4C2, 0x1F4C3, 0x1F4C4, 0x1F4C5, 0x1F4C6, 0x1F4C7, 0x1F4C8, 0x1F4C9, 0x1F4CA, + 0x1F4CB, 0x1F4CC, 0x1F4CD, 0x1F4CE, 0x1F4CF, 0x1F4D0, 0x1F4D1, 0x1F4D2, 0x1F4D3, 0x1F4D4, + 0x1F4D5, 0x1F4D6, 0x1F4D7, 0x1F4D8, 0x1F4D9, 0x1F4DA, 0x1F4DB, 0x1F4DC, 0x1F4DD, 0x1F4DE, + 0x1F4DF, 0x1F4E0, 0x1F4E1, 0x1F4E2, 0x1F4E3, 0x1F4E4, 0x1F4E5, 0x1F4E6, 0x1F4E7, 0x1F4E8, + 0x1F4E9, 0x1F4EA, 0x1F4EB, 0x1F4EC, 0x1F4ED, 0x1F4EE, 0x1F4EF, 0x1F4F0, 0x1F4F1, 0x1F4F2, + 0x1F4F3, 0x1F4F4, 0x1F4F5, 0x1F4F6, 0x1F4F7, 0x1F4F8, 0x1F4F9, 0x1F4FA, 0x1F4FB, 0x1F4FC, + 0x1F4FD, 0x1F4FF, 0x1F500, 0x1F501, 0x1F502, 0x1F503, 0x1F504, 0x1F505, 0x1F506, 0x1F507, + 0x1F508, 0x1F509, 0x1F50A, 0x1F50B, 0x1F50C, 0x1F50D, 0x1F50E, 0x1F50F, 0x1F510, 0x1F511, + 0x1F512, 0x1F513, 0x1F514, 0x1F515, 0x1F516, 0x1F517, 0x1F518, 0x1F519, 0x1F51A, 0x1F51B, + 0x1F51C, 0x1F51D, 0x1F51E, 0x1F51F, 0x1F520, 0x1F521, 0x1F522, 0x1F523, 0x1F524, 0x1F525, + 0x1F526, 0x1F527, 0x1F528, 0x1F529, 0x1F52A, 0x1F52B, 0x1F52C, 0x1F52D, 0x1F52E, 0x1F52F, + 0x1F530, 0x1F531, 0x1F532, 0x1F533, 0x1F534, 0x1F535, 0x1F536, 0x1F537, 0x1F538, 0x1F539, + 0x1F53A, 0x1F53B, 0x1F53C, 0x1F53D, 0x1F549, 0x1F54A, 0x1F54B, 0x1F54C, 0x1F54D, 0x1F54E, + 0x1F550, 0x1F551, 0x1F552, 0x1F553, 0x1F554, 0x1F555, 0x1F556, 0x1F557, 0x1F558, 0x1F559, + 0x1F55A, 0x1F55B, 0x1F55C, 0x1F55D, 0x1F55E, 0x1F55F, 0x1F560, 0x1F561, 0x1F562, 0x1F563, + 0x1F564, 0x1F565, 0x1F566, 0x1F567, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576, + 0x1F577, 0x1F578, 0x1F579, 0x1F57A, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590, + 0x1F595, 0x1F596, 0x1F5A4, 0x1F5A5, 0x1F5A8, 0x1F5B1, 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3, + 0x1F5C4, 0x1F5D1, 0x1F5D2, 0x1F5D3, 0x1F5DC, 0x1F5DD, 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8, + 0x1F5EF, 0x1F5F3, 0x1F5FA, 0x1F5FB, 0x1F5FC, 0x1F5FD, 0x1F5FE, 0x1F5FF, 0x1F600, 0x1F601, + 0x1F602, 0x1F603, 0x1F604, 0x1F605, 0x1F606, 0x1F607, 0x1F608, 0x1F609, 0x1F60A, 0x1F60B, + 0x1F60C, 0x1F60D, 0x1F60E, 0x1F60F, 0x1F610, 0x1F611, 0x1F612, 0x1F613, 0x1F614, 0x1F615, + 0x1F616, 0x1F617, 0x1F618, 0x1F619, 0x1F61A, 0x1F61B, 0x1F61C, 0x1F61D, 0x1F61E, 0x1F61F, + 0x1F620, 0x1F621, 0x1F622, 0x1F623, 0x1F624, 0x1F625, 0x1F626, 0x1F627, 0x1F628, 0x1F629, + 0x1F62A, 0x1F62B, 0x1F62C, 0x1F62D, 0x1F62E, 0x1F62F, 0x1F630, 0x1F631, 0x1F632, 0x1F633, + 0x1F634, 0x1F635, 0x1F636, 0x1F637, 0x1F638, 0x1F639, 0x1F63A, 0x1F63B, 0x1F63C, 0x1F63D, + 0x1F63E, 0x1F63F, 0x1F640, 0x1F641, 0x1F642, 0x1F643, 0x1F644, 0x1F645, 0x1F646, 0x1F647, + 0x1F648, 0x1F649, 0x1F64A, 0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F680, 0x1F681, + 0x1F682, 0x1F683, 0x1F684, 0x1F685, 0x1F686, 0x1F687, 0x1F688, 0x1F689, 0x1F68A, 0x1F68B, + 0x1F68C, 0x1F68D, 0x1F68E, 0x1F68F, 0x1F690, 0x1F691, 0x1F692, 0x1F693, 0x1F694, 0x1F695, + 0x1F696, 0x1F697, 0x1F698, 0x1F699, 0x1F69A, 0x1F69B, 0x1F69C, 0x1F69D, 0x1F69E, 0x1F69F, + 0x1F6A0, 0x1F6A1, 0x1F6A2, 0x1F6A3, 0x1F6A4, 0x1F6A5, 0x1F6A6, 0x1F6A7, 0x1F6A8, 0x1F6A9, + 0x1F6AA, 0x1F6AB, 0x1F6AC, 0x1F6AD, 0x1F6AE, 0x1F6AF, 0x1F6B0, 0x1F6B1, 0x1F6B2, 0x1F6B3, + 0x1F6B4, 0x1F6B5, 0x1F6B6, 0x1F6B7, 0x1F6B8, 0x1F6B9, 0x1F6BA, 0x1F6BB, 0x1F6BC, 0x1F6BD, + 0x1F6BE, 0x1F6BF, 0x1F6C0, 0x1F6C1, 0x1F6C2, 0x1F6C3, 0x1F6C4, 0x1F6C5, 0x1F6CB, 0x1F6CC, + 0x1F6CD, 0x1F6CE, 0x1F6CF, 0x1F6D0, 0x1F6D1, 0x1F6D2, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3, + 0x1F6E4, 0x1F6E5, 0x1F6E9, 0x1F6EB, 0x1F6EC, 0x1F6F0, 0x1F6F3, 0x1F6F4, 0x1F6F5, 0x1F6F6, + 0x1F910, 0x1F911, 0x1F912, 0x1F913, 0x1F914, 0x1F915, 0x1F916, 0x1F917, 0x1F918, 0x1F919, + 0x1F91A, 0x1F91B, 0x1F91C, 0x1F91D, 0x1F91E, 0x1F920, 0x1F921, 0x1F922, 0x1F923, 0x1F924, + 0x1F925, 0x1F926, 0x1F927, 0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938, + 0x1F939, 0x1F93A, 0x1F93B, 0x1F93C, 0x1F93D, 0x1F93E, 0x1F940, 0x1F941, 0x1F942, 0x1F943, + 0x1F944, 0x1F945, 0x1F946, 0x1F947, 0x1F948, 0x1F949, 0x1F94A, 0x1F94B, 0x1F950, 0x1F951, + 0x1F952, 0x1F953, 0x1F954, 0x1F955, 0x1F956, 0x1F957, 0x1F958, 0x1F959, 0x1F95A, 0x1F95B, + 0x1F95C, 0x1F95D, 0x1F95E, 0x1F980, 0x1F981, 0x1F982, 0x1F983, 0x1F984, 0x1F985, 0x1F986, + 0x1F987, 0x1F988, 0x1F989, 0x1F98A, 0x1F98B, 0x1F98C, 0x1F98D, 0x1F98E, 0x1F98F, 0x1F990, + 0x1F991, 0x1F9C0 }; // See http://www.unicode.org/Public/emoji/3.0/emoji-data.txt diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java index 47e71be333d8c82fe458bf28905e1cf1d6440c18..4b02df86c82e5491f474a8bce4e070ab25d83516 100644 --- a/core/java/android/text/SpannableStringInternal.java +++ b/core/java/android/text/SpannableStringInternal.java @@ -33,6 +33,7 @@ import java.lang.reflect.Array; mText = source.toString().substring(start, end); mSpans = EmptyArray.OBJECT; + // Invariant: mSpanData.length = mSpans.length * COLUMNS mSpanData = EmptyArray.INT; if (source instanceof Spanned) { @@ -99,7 +100,7 @@ import java.lang.reflect.Array; Object[] srcSpans = src.mSpans; mSpanCount = count; mSpans = ArrayUtils.newUnpaddedObjectArray(mSpanCount); - mSpanData = new int[mSpanCount * COLUMNS]; + mSpanData = new int[mSpans.length * COLUMNS]; for (int i = 0, j = 0; i < limit; i++) { int spanStart = srcData[i * COLUMNS + START]; int spanEnd = srcData[i * COLUMNS + END]; diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java index 3770a45d2172e9c39359b1fbceef359868a70993..2f327f3cb4950fc9387ab62840cb28fa7604b143 100644 --- a/core/java/android/text/method/BaseKeyListener.java +++ b/core/java/android/text/method/BaseKeyListener.java @@ -129,8 +129,8 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener // The offset is immediately before a variation selector. final int STATE_BEFORE_VS = 6; - // The offset is immediately before a ZWJ emoji. - final int STATE_BEFORE_ZWJ_EMOJI = 7; + // The offset is immediately before an emoji. + final int STATE_BEFORE_EMOJI = 7; // The offset is immediately before a ZWJ that were seen before a ZWJ emoji. final int STATE_BEFORE_ZWJ = 8; // The offset is immediately before a variation selector and a ZWJ that were seen before a @@ -169,7 +169,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener } else if (codePoint == Emoji.COMBINING_ENCLOSING_KEYCAP) { state = STATE_BEFORE_KEYCAP; } else if (Emoji.isEmoji(codePoint)) { - state = STATE_BEFORE_ZWJ_EMOJI; + state = STATE_BEFORE_EMOJI; } else { state = STATE_FINISHED; } @@ -232,7 +232,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener case STATE_BEFORE_VS: if (Emoji.isEmoji(codePoint)) { deleteCharCount += Character.charCount(codePoint); - state = STATE_BEFORE_ZWJ_EMOJI; + state = STATE_BEFORE_EMOJI; break; } @@ -242,7 +242,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener } state = STATE_FINISHED; break; - case STATE_BEFORE_ZWJ_EMOJI: + case STATE_BEFORE_EMOJI: if (codePoint == Emoji.ZERO_WIDTH_JOINER) { state = STATE_BEFORE_ZWJ; } else { @@ -252,7 +252,8 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener case STATE_BEFORE_ZWJ: if (Emoji.isEmoji(codePoint)) { deleteCharCount += Character.charCount(codePoint) + 1; // +1 for ZWJ. - state = STATE_BEFORE_ZWJ_EMOJI; + state = Emoji.isEmojiModifier(codePoint) ? + STATE_BEFORE_EMOJI_MODIFIER : STATE_BEFORE_EMOJI; } else if (isVariationSelector(codePoint)) { lastSeenVSCharCount = Character.charCount(codePoint); state = STATE_BEFORE_VS_AND_ZWJ; @@ -265,7 +266,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener // +1 for ZWJ. deleteCharCount += lastSeenVSCharCount + 1 + Character.charCount(codePoint); lastSeenVSCharCount = 0; - state = STATE_BEFORE_ZWJ_EMOJI; + state = STATE_BEFORE_EMOJI; } else { state = STATE_FINISHED; } diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index 316c7e3f6084408222c6c4ec6132b1af0e23f3f4..8823605c52b6ef251d2ca5e699bb0e86f05375e9 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -1940,6 +1940,26 @@ public abstract class Transition implements Cloneable { } } + /** + * Force the transition to move to its end state, ending all the animators. + * + * @hide + */ + void forceToEnd(ViewGroup sceneRoot) { + ArrayMap runningAnimators = getRunningAnimators(); + int numOldAnims = runningAnimators.size(); + if (sceneRoot != null) { + WindowId windowId = sceneRoot.getWindowId(); + for (int i = numOldAnims - 1; i >= 0; i--) { + AnimationInfo info = runningAnimators.valueAt(i); + if (info.view != null && windowId != null && windowId.equals(info.windowId)) { + Animator anim = runningAnimators.keyAt(i); + anim.end(); + } + } + } + } + /** * This method cancels a transition that is currently running. * diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java index 71c80991bb197c9bbd379c47b0cd7c7af6cf69ba..f2c871e3c718d77a425e613c5039451dec36b230 100644 --- a/core/java/android/transition/TransitionManager.java +++ b/core/java/android/transition/TransitionManager.java @@ -440,7 +440,7 @@ public class TransitionManager { ArrayList copy = new ArrayList(runningTransitions); for (int i = copy.size() - 1; i >= 0; i--) { final Transition transition = copy.get(i); - transition.end(); + transition.forceToEnd(sceneRoot); } } diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java index 583dc0f1ef2c4062fb367fb152ae130d262fde5d..a41fe64d0be10655b309795ab6a7fc9371f63acd 100644 --- a/core/java/android/transition/TransitionSet.java +++ b/core/java/android/transition/TransitionSet.java @@ -16,8 +16,6 @@ package android.transition; -import com.android.internal.R; - import android.animation.TimeInterpolator; import android.content.Context; import android.content.res.TypedArray; @@ -26,6 +24,8 @@ import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; +import com.android.internal.R; + import java.util.ArrayList; /** @@ -498,6 +498,16 @@ public class TransitionSet extends Transition { } } + /** @hide */ + @Override + void forceToEnd(ViewGroup sceneRoot) { + super.forceToEnd(sceneRoot); + int numTransitions = mTransitions.size(); + for (int i = 0; i < numTransitions; ++i) { + mTransitions.get(i).forceToEnd(sceneRoot); + } + } + @Override TransitionSet setSceneRoot(ViewGroup sceneRoot) { super.setSceneRoot(sceneRoot); diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java index d39e91fd98b2e05804602b092b24f5bca1e3277a..a02c070d4889f6dbfc9e261be40dd6a8f5873794 100644 --- a/core/java/android/util/ArraySet.java +++ b/core/java/android/util/ArraySet.java @@ -156,28 +156,46 @@ public final class ArraySet implements Collection, Set { synchronized (ArraySet.class) { if (mTwiceBaseCache != null) { final Object[] array = mTwiceBaseCache; - mArray = array; - mTwiceBaseCache = (Object[])array[0]; - mHashes = (int[])array[1]; - array[0] = array[1] = null; - mTwiceBaseCacheSize--; - if (DEBUG) Log.d(TAG, "Retrieving 2x cache " + mHashes - + " now have " + mTwiceBaseCacheSize + " entries"); - return; + try { + mArray = array; + mTwiceBaseCache = (Object[]) array[0]; + mHashes = (int[]) array[1]; + array[0] = array[1] = null; + mTwiceBaseCacheSize--; + if (DEBUG) Log.d(TAG, "Retrieving 2x cache " + mHashes + + " now have " + mTwiceBaseCacheSize + " entries"); + return; + } catch (ClassCastException e) { + } + // Whoops! Someone trampled the array (probably due to not protecting + // their access with a lock). Our cache is corrupt; report and give up. + Slog.wtf(TAG, "Found corrupt ArraySet cache: [0]=" + array[0] + + " [1]=" + array[1]); + mTwiceBaseCache = null; + mTwiceBaseCacheSize = 0; } } } else if (size == BASE_SIZE) { synchronized (ArraySet.class) { if (mBaseCache != null) { final Object[] array = mBaseCache; - mArray = array; - mBaseCache = (Object[])array[0]; - mHashes = (int[])array[1]; - array[0] = array[1] = null; - mBaseCacheSize--; - if (DEBUG) Log.d(TAG, "Retrieving 1x cache " + mHashes - + " now have " + mBaseCacheSize + " entries"); - return; + try { + mArray = array; + mBaseCache = (Object[]) array[0]; + mHashes = (int[]) array[1]; + array[0] = array[1] = null; + mBaseCacheSize--; + if (DEBUG) Log.d(TAG, "Retrieving 1x cache " + mHashes + + " now have " + mBaseCacheSize + " entries"); + return; + } catch (ClassCastException e) { + } + // Whoops! Someone trampled the array (probably due to not protecting + // their access with a lock). Our cache is corrupt; report and give up. + Slog.wtf(TAG, "Found corrupt ArraySet cache: [0]=" + array[0] + + " [1]=" + array[1]); + mBaseCache = null; + mBaseCacheSize = 0; } } } @@ -402,11 +420,14 @@ public final class ArraySet implements Collection, Set { throw new IllegalStateException("Array is full"); } if (index > 0 && mHashes[index - 1] > hash) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Log.w(TAG, "New hash " + hash - + " is before end of array hash " + mHashes[index - 1] - + " at index " + index, e); + // Cannot optimize since it would break the sorted order - fallback to add() + if (DEBUG) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Log.w(TAG, "New hash " + hash + + " is before end of array hash " + mHashes[index - 1] + + " at index " + index, e); + } add(value); return; } diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index d201adef2d4d4e51e479985d40de8c4e44063b3d..f4db4d6611eaff35e44182a377d82ade4dbe652c 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -61,6 +61,13 @@ public class DisplayMetrics { */ public static final int DENSITY_HIGH = 240; + /** + * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and + * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target, + * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them. + */ + public static final int DENSITY_260 = 260; + /** * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target, @@ -68,11 +75,26 @@ public class DisplayMetrics { */ public static final int DENSITY_280 = 280; + /** + * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and + * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target, + * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them. + */ + public static final int DENSITY_300 = 300; + /** * Standard quantized DPI for extra-high-density screens. */ public static final int DENSITY_XHIGH = 320; + /** + * Intermediate density for screens that sit somewhere between + * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi). + * This is not a density that applications should target, instead relying + * on the system to scale their {@link #DENSITY_XXHIGH} assets for them. + */ + public static final int DENSITY_340 = 340; + /** * Intermediate density for screens that sit somewhere between * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi). diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java index 8f9b36e84ca27c0fc5f21206a70b879ea211f9fe..83e693c49c146c7c1d1170fd0359c819a5bd8379 100644 --- a/core/java/android/util/MemoryIntArray.java +++ b/core/java/android/util/MemoryIntArray.java @@ -54,7 +54,7 @@ public final class MemoryIntArray implements Parcelable, Closeable { private final int mOwnerPid; private final boolean mClientWritable; private final long mMemoryAddr; - private ParcelFileDescriptor mFd; + private int mFd; /** * Creates a new instance. @@ -71,22 +71,23 @@ public final class MemoryIntArray implements Parcelable, Closeable { mOwnerPid = Process.myPid(); mClientWritable = clientWritable; final String name = UUID.randomUUID().toString(); - mFd = ParcelFileDescriptor.fromFd(nativeCreate(name, size)); - mMemoryAddr = nativeOpen(mFd.getFd(), true, clientWritable); + mFd = nativeCreate(name, size); + mMemoryAddr = nativeOpen(mFd, true, clientWritable); } private MemoryIntArray(Parcel parcel) throws IOException { mOwnerPid = parcel.readInt(); mClientWritable = (parcel.readInt() == 1); - mFd = parcel.readParcelable(null); - if (mFd == null) { + ParcelFileDescriptor pfd = parcel.readParcelable(null); + if (pfd == null) { throw new IOException("No backing file descriptor"); } + mFd = pfd.detachFd(); final long memoryAddress = parcel.readLong(); if (isOwner()) { mMemoryAddr = memoryAddress; } else { - mMemoryAddr = nativeOpen(mFd.getFd(), false, mClientWritable); + mMemoryAddr = nativeOpen(mFd, false, mClientWritable); } } @@ -108,7 +109,7 @@ public final class MemoryIntArray implements Parcelable, Closeable { public int get(int index) throws IOException { enforceNotClosed(); enforceValidIndex(index); - return nativeGet(mFd.getFd(), mMemoryAddr, index, isOwner()); + return nativeGet(mFd, mMemoryAddr, index, isOwner()); } /** @@ -124,7 +125,7 @@ public final class MemoryIntArray implements Parcelable, Closeable { enforceNotClosed(); enforceWritable(); enforceValidIndex(index); - nativeSet(mFd.getFd(), mMemoryAddr, index, value, isOwner()); + nativeSet(mFd, mMemoryAddr, index, value, isOwner()); } /** @@ -134,7 +135,7 @@ public final class MemoryIntArray implements Parcelable, Closeable { */ public int size() throws IOException { enforceNotClosed(); - return nativeSize(mFd.getFd()); + return nativeSize(mFd); } /** @@ -145,9 +146,8 @@ public final class MemoryIntArray implements Parcelable, Closeable { @Override public void close() throws IOException { if (!isClosed()) { - ParcelFileDescriptor pfd = mFd; - mFd = null; - nativeClose(pfd.getFd(), mMemoryAddr, isOwner()); + nativeClose(mFd, mMemoryAddr, isOwner()); + mFd = -1; } } @@ -155,7 +155,7 @@ public final class MemoryIntArray implements Parcelable, Closeable { * @return Whether this array is closed and shouldn't be used. */ public boolean isClosed() { - return mFd == null; + return mFd == -1; } @Override @@ -171,10 +171,15 @@ public final class MemoryIntArray implements Parcelable, Closeable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeInt(mOwnerPid); - parcel.writeInt(mClientWritable ? 1 : 0); - parcel.writeParcelable(mFd, 0); - parcel.writeLong(mMemoryAddr); + ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd); + try { + parcel.writeInt(mOwnerPid); + parcel.writeInt(mClientWritable ? 1 : 0); + parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + parcel.writeLong(mMemoryAddr); + } finally { + pfd.detachFd(); + } } @Override @@ -189,19 +194,12 @@ public final class MemoryIntArray implements Parcelable, Closeable { return false; } MemoryIntArray other = (MemoryIntArray) obj; - if (mFd == null) { - if (other.mFd != null) { - return false; - } - } else if (mFd.getFd() != other.mFd.getFd()) { - return false; - } - return true; + return mFd == other.mFd; } @Override public int hashCode() { - return mFd != null ? mFd.hashCode() : 1; + return mFd; } private boolean isOwner() { diff --git a/core/java/android/util/PackageUtils.java b/core/java/android/util/PackageUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..6531aef9a50ca1765a926c948c50276c2e12a464 --- /dev/null +++ b/core/java/android/util/PackageUtils.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.Signature; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * Helper functions applicable to packages. + * @hide + */ +public final class PackageUtils { + private final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + + private PackageUtils() { + /* hide constructor */ + } + + /** + * Computes the SHA256 digest of the signing cert for a package. + * @param packageManager The package manager. + * @param packageName The package for which to generate the digest. + * @param userId The user for which to generate the digest. + * @return The digest or null if the package does not exist for this user. + */ + public static @Nullable String computePackageCertSha256Digest( + @NonNull PackageManager packageManager, + @NonNull String packageName, int userId) { + final PackageInfo packageInfo; + try { + packageInfo = packageManager.getPackageInfoAsUser(packageName, + PackageManager.GET_SIGNATURES, userId); + } catch (PackageManager.NameNotFoundException e) { + return null; + } + return computeCertSha256Digest(packageInfo.signatures[0]); + } + + /** + * Computes the SHA256 digest of a cert. + * @param signature The signature. + * @return The digest or null if an error occurs. + */ + public static @Nullable String computeCertSha256Digest(@NonNull Signature signature) { + return computeSha256Digest(signature.toByteArray()); + } + + /** + * Computes the SHA256 digest of some data. + * @param data The data. + * @return The digest or null if an error occurs. + */ + public static @Nullable String computeSha256Digest(@NonNull byte[] data) { + MessageDigest messageDigest; + try { + messageDigest = MessageDigest.getInstance("SHA256"); + } catch (NoSuchAlgorithmException e) { + /* can't happen */ + return null; + } + + messageDigest.update(data); + + final byte[] digest = messageDigest.digest(); + final int digestLength = digest.length; + final int charCount = 2 * digestLength; + + final char[] chars = new char[charCount]; + for (int i = 0; i < digestLength; i++) { + final int byteHex = digest[i] & 0xFF; + chars[i * 2] = HEX_ARRAY[byteHex >>> 4]; + chars[i * 2 + 1] = HEX_ARRAY[byteHex & 0x0F]; + } + return new String(chars); + } +} diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index d3db74d1ea249e27ccdcf3158441fa813b3e881c..3316f3aeb60b5b0ccde7b2f8e7e0c52b78a312ba 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -25,6 +25,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.util.Log; import android.util.TimeUtils; +import android.view.animation.AnimationUtils; import java.io.PrintWriter; @@ -608,6 +609,7 @@ public final class Choreographer { try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame"); + AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS); mFrameInfo.markInputHandlingStart(); doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); @@ -620,6 +622,7 @@ public final class Choreographer { doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); } finally { + AnimationUtils.unlockAnimationClock(); Trace.traceEnd(Trace.TRACE_TAG_VIEW); } diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 2f2fe57f68fa01db41d98ad3d9eb4e34424ebf43..85a4bf9d9e8f92e4b6d61b8e828c4e2fc0593604 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -36,7 +36,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; -import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM; +import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE; /** * Provides information about the size and density of a logical display. @@ -284,6 +284,27 @@ public final class Display { */ public static final int STATE_DOZE_SUSPEND = 4; + /* The color mode constants defined below must be kept in sync with the ones in + * system/graphics.h */ + + /** + * Display color mode: The current color mode is unknown or invalid. + * @hide + */ + public static final int COLOR_MODE_INVALID = -1; + + /** + * Display color mode: The default or native gamut of the display. + * @hide + */ + public static final int COLOR_MODE_DEFAULT = 0; + + /** + * Display color mode: SRGB + * @hide + */ + public static final int COLOR_MODE_SRGB = 7; + /** * Internal method to create a display. * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} @@ -463,20 +484,29 @@ public final class Display { /** * Gets the size of the display, in pixels. + * Value returned by this method does not necessarily represent the actual raw size + * (native resolution) of the display. *

    - * Note that this value should not be used for computing layouts, - * since a device will typically have screen decoration (such as a status bar) - * along the edges of the display that reduce the amount of application - * space available from the size returned here. Layouts should instead use - * the window size. - *

    - * The size is adjusted based on the current rotation of the display. + * 1. The returned size may be adjusted to exclude certain system decor elements + * that are always visible. *

    - * The size returned by this method does not necessarily represent the - * actual raw size (native resolution) of the display. The returned size may - * be adjusted to exclude certain system decoration elements that are always visible. - * It may also be scaled to provide compatibility with older applications that + * 2. It may be scaled to provide compatibility with older applications that * were originally designed for smaller displays. + *

    + * 3. It can be different depending on the WindowManager to which the display belongs. + *

    + * - If requested from non-Activity context (e.g. Application context via + * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}) + * it will report the size of the entire display based on current rotation and with subtracted + * system decoration areas. + *

    + * - If requested from activity (either using {@code getWindowManager()} or + * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting size will + * correspond to current app window size. In this case it can be smaller than physical size in + * multi-window mode. + *

    + * Typically for the purposes of layout apps should make a request from activity context + * to obtain size available for the app content. *

    * * @param outSize A {@link Point} object to receive the size information. @@ -687,33 +717,22 @@ public final class Display { } /** - * Request the display applies a color transform. + * Request the display applies a color mode. * @hide */ - @RequiresPermission(CONFIGURE_DISPLAY_COLOR_TRANSFORM) - public void requestColorTransform(ColorTransform colorTransform) { - mGlobal.requestColorTransform(mDisplayId, colorTransform.getId()); + @RequiresPermission(CONFIGURE_DISPLAY_COLOR_MODE) + public void requestColorMode(int colorMode) { + mGlobal.requestColorMode(mDisplayId, colorMode); } /** - * Returns the active color transform of this display + * Returns the active color mode of this display * @hide */ - public ColorTransform getColorTransform() { + public int getColorMode() { synchronized (this) { updateDisplayInfoLocked(); - return mDisplayInfo.getColorTransform(); - } - } - - /** - * Returns the default color transform of this display - * @hide - */ - public ColorTransform getDefaultColorTransform() { - synchronized (this) { - updateDisplayInfoLocked(); - return mDisplayInfo.getDefaultColorTransform(); + return mDisplayInfo.colorMode; } } @@ -728,14 +747,14 @@ public final class Display { } /** - * Gets the supported color transforms of this device. + * Gets the supported color modes of this device. * @hide */ - public ColorTransform[] getSupportedColorTransforms() { + public int[] getSupportedColorModes() { synchronized (this) { updateDisplayInfoLocked(); - ColorTransform[] transforms = mDisplayInfo.supportedColorTransforms; - return Arrays.copyOf(transforms, transforms.length); + int[] colorModes = mDisplayInfo.supportedColorModes; + return Arrays.copyOf(colorModes, colorModes.length); } } @@ -785,13 +804,16 @@ public final class Display { * were originally designed for smaller displays. *

    * 3. It can be different depending on the WindowManager to which the display belongs. - *

    +     * 

    * - If requested from non-Activity context (e.g. Application context via * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}) - * metrics will report real size of the display based on current rotation. - * - If requested from activity resulting metrics will correspond to current window metrics. - * In this case the size can be smaller than physical size in multi-window mode. - *

    + * metrics will report the size of the entire display based on current rotation and with + * subtracted system decoration areas. + *

    + * - If requested from activity (either using {@code getWindowManager()} or + * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting metrics will + * correspond to current app window metrics. In this case the size can be smaller than physical + * size in multi-window mode. *

    * * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. @@ -1205,6 +1227,33 @@ public final class Display { return mMinLuminance; } + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!(other instanceof HdrCapabilities)) { + return false; + } + HdrCapabilities that = (HdrCapabilities) other; + + return Arrays.equals(mSupportedHdrTypes, that.mSupportedHdrTypes) + && mMaxLuminance == that.mMaxLuminance + && mMaxAverageLuminance == that.mMaxAverageLuminance + && mMinLuminance == that.mMinLuminance; + } + + @Override + public int hashCode() { + int hash = 23; + hash = hash * 17 + Arrays.hashCode(mSupportedHdrTypes); + hash = hash * 17 + Float.floatToIntBits(mMaxLuminance); + hash = hash * 17 + Float.floatToIntBits(mMaxAverageLuminance); + hash = hash * 17 + Float.floatToIntBits(mMinLuminance); + return hash; + } + public static final Creator CREATOR = new Creator() { @Override public HdrCapabilities createFromParcel(Parcel source) { @@ -1251,89 +1300,4 @@ public final class Display { return 0; } } - - /** - * A color transform supported by a given display. - * - * @see Display#getSupportedColorTransforms() - * @hide - */ - public static final class ColorTransform implements Parcelable { - public static final ColorTransform[] EMPTY_ARRAY = new ColorTransform[0]; - - private final int mId; - private final int mColorTransform; - - public ColorTransform(int id, int colorTransform) { - mId = id; - mColorTransform = colorTransform; - } - - public int getId() { - return mId; - } - - public int getColorTransform() { - return mColorTransform; - } - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!(other instanceof ColorTransform)) { - return false; - } - ColorTransform that = (ColorTransform) other; - return mId == that.mId - && mColorTransform == that.mColorTransform; - } - - @Override - public int hashCode() { - int hash = 1; - hash = hash * 17 + mId; - hash = hash * 17 + mColorTransform; - return hash; - } - - @Override - public String toString() { - return new StringBuilder("{") - .append("id=").append(mId) - .append(", colorTransform=").append(mColorTransform) - .append("}") - .toString(); - } - - @Override - public int describeContents() { - return 0; - } - - private ColorTransform(Parcel in) { - this(in.readInt(), in.readInt()); - } - - @Override - public void writeToParcel(Parcel out, int parcelableFlags) { - out.writeInt(mId); - out.writeInt(mColorTransform); - } - - @SuppressWarnings("hiding") - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - @Override - public ColorTransform createFromParcel(Parcel in) { - return new ColorTransform(in); - } - - @Override - public ColorTransform[] newArray(int size) { - return new ColorTransform[size]; - } - }; - } } diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 8aeeffd906439527c6f2ec2a0cb41bec6034760e..bc40849a47bc03157fffde1f7f185fb517e147f9 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -169,14 +169,11 @@ public final class DisplayInfo implements Parcelable { */ public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY; - /** The active color transform. */ - public int colorTransformId; + /** The active color mode. */ + public int colorMode; - /** The default color transform. */ - public int defaultColorTransformId; - - /** The list of supported color transforms */ - public Display.ColorTransform[] supportedColorTransforms = Display.ColorTransform.EMPTY_ARRAY; + /** The list of supported color modes */ + public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; /** The display's HDR capabilities */ public Display.HdrCapabilities hdrCapabilities; @@ -291,8 +288,8 @@ public final class DisplayInfo implements Parcelable { && rotation == other.rotation && modeId == other.modeId && defaultModeId == other.defaultModeId - && colorTransformId == other.colorTransformId - && defaultColorTransformId == other.defaultColorTransformId + && colorMode == other.colorMode + && Arrays.equals(supportedColorModes, other.supportedColorModes) && Objects.equal(hdrCapabilities, other.hdrCapabilities) && logicalDensityDpi == other.logicalDensityDpi && physicalXDpi == other.physicalXDpi @@ -332,10 +329,9 @@ public final class DisplayInfo implements Parcelable { modeId = other.modeId; defaultModeId = other.defaultModeId; supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); - colorTransformId = other.colorTransformId; - defaultColorTransformId = other.defaultColorTransformId; - supportedColorTransforms = Arrays.copyOf( - other.supportedColorTransforms, other.supportedColorTransforms.length); + colorMode = other.colorMode; + supportedColorModes = Arrays.copyOf( + other.supportedColorModes, other.supportedColorModes.length); hdrCapabilities = other.hdrCapabilities; logicalDensityDpi = other.logicalDensityDpi; physicalXDpi = other.physicalXDpi; @@ -373,12 +369,11 @@ public final class DisplayInfo implements Parcelable { for (int i = 0; i < nModes; i++) { supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source); } - colorTransformId = source.readInt(); - defaultColorTransformId = source.readInt(); - int nColorTransforms = source.readInt(); - supportedColorTransforms = new Display.ColorTransform[nColorTransforms]; - for (int i = 0; i < nColorTransforms; i++) { - supportedColorTransforms[i] = Display.ColorTransform.CREATOR.createFromParcel(source); + colorMode = source.readInt(); + int nColorModes = source.readInt(); + supportedColorModes = new int[nColorModes]; + for (int i = 0; i < nColorModes; i++) { + supportedColorModes[i] = source.readInt(); } hdrCapabilities = source.readParcelable(null); logicalDensityDpi = source.readInt(); @@ -418,11 +413,10 @@ public final class DisplayInfo implements Parcelable { for (int i = 0; i < supportedModes.length; i++) { supportedModes[i].writeToParcel(dest, flags); } - dest.writeInt(colorTransformId); - dest.writeInt(defaultColorTransformId); - dest.writeInt(supportedColorTransforms.length); - for (int i = 0; i < supportedColorTransforms.length; i++) { - supportedColorTransforms[i].writeToParcel(dest, flags); + dest.writeInt(colorMode); + dest.writeInt(supportedColorModes.length); + for (int i = 0; i < supportedColorModes.length; i++) { + dest.writeInt(supportedColorModes[i]); } dest.writeParcelable(hdrCapabilities, flags); dest.writeInt(logicalDensityDpi); @@ -496,24 +490,6 @@ public final class DisplayInfo implements Parcelable { return result; } - public Display.ColorTransform getColorTransform() { - return findColorTransform(colorTransformId); - } - - public Display.ColorTransform getDefaultColorTransform() { - return findColorTransform(defaultColorTransformId); - } - - private Display.ColorTransform findColorTransform(int colorTransformId) { - for (int i = 0; i < supportedColorTransforms.length; i++) { - Display.ColorTransform colorTransform = supportedColorTransforms[i]; - if (colorTransform.getId() == colorTransformId) { - return colorTransform; - } - } - throw new IllegalStateException("Unable to locate color transform: " + colorTransformId); - } - public void getAppMetrics(DisplayMetrics outMetrics) { getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); } @@ -615,12 +591,10 @@ public final class DisplayInfo implements Parcelable { sb.append(defaultModeId); sb.append(", modes "); sb.append(Arrays.toString(supportedModes)); - sb.append(", colorTransformId "); - sb.append(colorTransformId); - sb.append(", defaultColorTransformId "); - sb.append(defaultColorTransformId); - sb.append(", supportedColorTransforms "); - sb.append(Arrays.toString(supportedColorTransforms)); + sb.append(", colorMode "); + sb.append(colorMode); + sb.append(", supportedColorModes "); + sb.append(Arrays.toString(supportedColorModes)); sb.append(", hdrCapabilities "); sb.append(hdrCapabilities); sb.append(", rotation "); diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java index fb482b4e33ff5529c8f7c538e544961ad33b4fbf..2baa0b4691ab6a6ef5ef46edcc0ef2931af4e3d8 100644 --- a/core/java/android/view/DragEvent.java +++ b/core/java/android/view/DragEvent.java @@ -102,8 +102,8 @@ import com.android.internal.view.IDragAndDropPermissions; * * * ACTION_DRAG_ENDED - * X - * X + *   + *   *   *   *   @@ -134,6 +134,7 @@ public class DragEvent implements Parcelable { Object mLocalState; boolean mDragResult; + boolean mEventHandlerWasCalled; private DragEvent mNext; private RuntimeException mRecycledLocation; @@ -152,12 +153,16 @@ public class DragEvent implements Parcelable { * if it can accept a drop. The onDragEvent() or onDrag() methods usually inspect the metadata * from {@link #getClipDescription()} to determine if they can accept the data contained in * this drag. For an operation that doesn't represent data transfer, these methods may - * perform other actions to determine whether or not the View should accept the drag. + * perform other actions to determine whether or not the View should accept the data. * If the View wants to indicate that it is a valid drop target, it can also react by * changing its appearance. *

    - * A View only receives further drag events if it returns {@code true} in response to - * ACTION_DRAG_STARTED. + * Views added or becoming visible for the first time during a drag operation receive this + * event when they are added or becoming visible. + *

    + *

    + * A View only receives further drag events if it returns {@code true} in response to + * ACTION_DRAG_STARTED. *

    * @see #ACTION_DRAG_ENDED * @see #getX() @@ -176,9 +181,10 @@ public class DragEvent implements Parcelable { *

    *

    * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the - * drag shadow out of the View object's bounding box. If the user moves the drag shadow back - * into the View object's bounding box, the View receives an ACTION_DRAG_ENTERED again before - * receiving any more ACTION_DRAG_LOCATION events. + * drag shadow out of the View object's bounding box or into a descendant view that can accept + * the data. If the user moves the drag shadow back into the View object's bounding box or out + * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again + * before receiving any more ACTION_DRAG_LOCATION events. *

    * @see #ACTION_DRAG_ENTERED * @see #getX() @@ -188,7 +194,8 @@ public class DragEvent implements Parcelable { /** * Action constant returned by {@link #getAction()}: Signals to a View that the user - * has released the drag shadow, and the drag point is within the bounding box of the View. + * has released the drag shadow, and the drag point is within the bounding box of the View and + * not within a descendant view that can accept the data. * The View should retrieve the data from the DragEvent by calling {@link #getClipData()}. * The methods {@link #getX()} and {@link #getY()} return the X and Y position of the drop point * within the View object's bounding box. @@ -211,8 +218,10 @@ public class DragEvent implements Parcelable { * operation has concluded. A View that changed its appearance during the operation should * return to its usual drawing state in response to this event. *

    - * All views that received an ACTION_DRAG_STARTED event will receive the - * ACTION_DRAG_ENDED event even if they are not currently visible when the drag ends. + * All views with listeners that returned boolean true for the ACTION_DRAG_STARTED + * event will receive the ACTION_DRAG_ENDED event even if they are not currently visible when + * the drag ends. Views removed during the drag operation won't receive the ACTION_DRAG_ENDED + * event. *

    *

    * The View object can call {@link #getResult()} to see the result of the operation. @@ -233,9 +242,10 @@ public class DragEvent implements Parcelable { * drop target. *

    * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the - * drag shadow out of the View object's bounding box. If the user moves the drag shadow back - * into the View object's bounding box, the View receives an ACTION_DRAG_ENTERED again before - * receiving any more ACTION_DRAG_LOCATION events. + * drag shadow out of the View object's bounding box or into a descendant view that can accept + * the data. If the user moves the drag shadow back into the View object's bounding box or out + * of a descendant view that can accept the data, the View receives an ACTION_DRAG_ENTERED again + * before receiving any more ACTION_DRAG_LOCATION events. *

    * @see #ACTION_DRAG_ENTERED * @see #ACTION_DRAG_LOCATION @@ -244,7 +254,8 @@ public class DragEvent implements Parcelable { /** * Action constant returned by {@link #getAction()}: Signals that the user has moved the - * drag shadow outside the bounding box of the View. + * drag shadow out of the bounding box of the View or into a descendant view that can accept + * the data. * The View can react by changing its appearance in a way that tells the user that * View is no longer the immediate drop target. *

    @@ -359,7 +370,7 @@ public class DragEvent implements Parcelable { * The drag handler or listener for a View can use the metadata in this object to decide if the * View can accept the dragged View object's data. *

    - * This method returns valid data for all event actions. + * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}. * @return The ClipDescription that was part of the ClipData sent to the system by startDrag(). */ public ClipDescription getClipDescription() { @@ -377,7 +388,11 @@ public class DragEvent implements Parcelable { * The object is intended to provide local information about the drag and drop operation. For * example, it can indicate whether the drag and drop operation is a copy or a move. *

    - * This method returns valid data for all event actions. + * The local state is available only to views in the activity which has started the drag + * operation. In all other activities this method will return null + *

    + *

    + * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}. *

    * @return The local state object sent to the system by startDrag(). */ @@ -435,6 +450,7 @@ public class DragEvent implements Parcelable { mClipData = null; mClipDescription = null; mLocalState = null; + mEventHandlerWasCalled = false; synchronized (gRecyclerLock) { if (gRecyclerUsed < MAX_RECYCLED) { diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java index 5c4450a4ed183b02477ded2b8217e2939a5be91b..2b938d0df7eb44104a03b1f07126bc36a0e9ed0e 100644 --- a/core/java/android/view/FrameMetrics.java +++ b/core/java/android/view/FrameMetrics.java @@ -198,7 +198,7 @@ public final class FrameMetrics { int SWAP_BUFFERS = 12; int FRAME_COMPLETED = 13; - int FRAME_STATS_COUNT = 14; // must always be last + int FRAME_STATS_COUNT = 16; // must always be last } /* diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 72126d0329a35bd7a9bc5bad2cee1ea72d06a72b..855b1bce115842baa10db62737061abb2ed43ffb 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -73,8 +73,8 @@ interface IWindowManager void clearForcedDisplaySize(int displayId); int getInitialDisplayDensity(int displayId); int getBaseDisplayDensity(int displayId); - void setForcedDisplayDensity(int displayId, int density); - void clearForcedDisplayDensity(int displayId); + void setForcedDisplayDensityForUser(int displayId, int density, int userId); + void clearForcedDisplayDensityForUser(int displayId, int userId); void setForcedDisplayScalingMode(int displayId, int mode); // 0 = auto, 1 = disable void setOverscan(int displayId, int left, int top, int right, int bottom); @@ -112,7 +112,7 @@ interface IWindowManager int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, int configChanges, boolean voiceInteraction, boolean launchTaskBehind, in Rect taskBounds, in Configuration configuration, int taskResizeMode, - boolean alwaysFocusable, boolean homeTask, int targetSdkVersion); + boolean alwaysFocusable, boolean homeTask, int targetSdkVersion, int rotationAnimationHint); /** * * @param token The token we are adding to the input task Id. @@ -173,7 +173,8 @@ interface IWindowManager in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded); void setAppVisibility(IBinder token, boolean visible); - void notifyAppStopped(IBinder token, boolean stopped); + void notifyAppResumed(IBinder token, boolean wasStopped, boolean allowSavedSurface); + void notifyAppStopped(IBinder token); void startAppFreezingScreen(IBinder token, int configChanges); void stopAppFreezingScreen(IBinder token, boolean force); void removeAppToken(IBinder token); @@ -305,6 +306,11 @@ interface IWindowManager */ boolean isRotationFrozen(); + /** + * Screenshot the current wallpaper layer, including the whole screen. + */ + Bitmap screenshotWallpaper(); + /** * Used only for assist -- request a screenshot of the current application. */ @@ -324,6 +330,16 @@ interface IWindowManager */ oneway void statusBarVisibilityChanged(int visibility); + /** + * Called by System UI to notify of changes to the visibility of Recents. + */ + oneway void setRecentsVisibility(boolean visible); + + /** + * Called by System UI to notify of changes to the visibility of PIP. + */ + oneway void setTvPipVisibility(boolean visible); + /** * Device has a software navigation bar (separate from the status bar). */ diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 636384c616e0daf888ac521d259dce95e74ab430..b73acdaf6d8b2d8387fa7dd8f06625c21f007253 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -796,8 +796,16 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final int KEYCODE_COPY = 278; /** Key code constant: Paste key. */ public static final int KEYCODE_PASTE = 279; + /** Key code constant: Consumed by the system for navigation up */ + public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; + /** Key code constant: Consumed by the system for navigation down */ + public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281; + /** Key code constant: Consumed by the system for navigation left*/ + public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; + /** Key code constant: Consumed by the system for navigation right */ + public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; - private static final int LAST_KEYCODE = KEYCODE_PASTE; + private static final int LAST_KEYCODE = KEYCODE_SYSTEM_NAVIGATION_RIGHT; // NOTE: If you add a new keycode here you must also add it to: // isSystem() @@ -1281,8 +1289,9 @@ public class KeyEvent extends InputEvent implements Parcelable { boolean onKeyUp(int keyCode, KeyEvent event); /** - * Called when multiple down/up pairs of the same key have occurred - * in a row. + * Called when a user's interaction with an analog control, such as + * flinging a trackball, generates simulated down/up events for the same + * key multiple times in quick succession. * * @param keyCode The value in event.getKeyCode(). * @param count Number of pairs as returned by event.getRepeatCount(). @@ -1844,6 +1853,10 @@ public class KeyEvent extends InputEvent implements Parcelable { case KeyEvent.KEYCODE_BRIGHTNESS_DOWN: case KeyEvent.KEYCODE_BRIGHTNESS_UP: case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: + case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: + case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: + case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: + case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: return true; } @@ -2929,11 +2942,13 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override public KeyEvent createFromParcel(Parcel in) { in.readInt(); // skip token, we already know this is a KeyEvent return KeyEvent.createFromParcelBody(in); } + @Override public KeyEvent[] newArray(int size) { return new KeyEvent[size]; } @@ -2957,6 +2972,7 @@ public class KeyEvent extends InputEvent implements Parcelable { mEventTime = in.readLong(); } + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(PARCEL_TOKEN_KEY_EVENT); diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index ab4cbcf21bed885bb06d45c1eef5abad73a8e504..0164fcd4f01673a1c3a347dab0fe28d7ba78359f 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -793,12 +793,12 @@ public class RenderNode { return mOwningView != null && mOwningView.mAttachInfo != null; } - public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) { + public void registerVectorDrawableAnimator( + AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) { if (mOwningView == null || mOwningView.mAttachInfo == null) { throw new IllegalStateException("Cannot start this animator on a detached view!"); } - nAddAnimator(mNativeRenderNode, animatorSet.getAnimatorNativePtr()); - mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); + mOwningView.mAttachInfo.mViewRootImpl.registerVectorDrawableAnimator(animatorSet); } public void endAllAnimators() { diff --git a/core/java/android/view/RoundScrollbarRenderer.java b/core/java/android/view/RoundScrollbarRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..b77be8c00e697063609964029ed605d710559b8b --- /dev/null +++ b/core/java/android/view/RoundScrollbarRenderer.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Rect; + +/** + * Helper class for drawing round scroll bars on round Wear devices. + */ +class RoundScrollbarRenderer { + // The range of the scrollbar position represented as an angle in degrees. + private static final int SCROLLBAR_ANGLE_RANGE = 90; + private static final int MAX_SCROLLBAR_ANGLE_SWIPE = 16; + private static final int MIN_SCROLLBAR_ANGLE_SWIPE = 6; + private static final float WIDTH_PERCENTAGE = 0.02f; + private static final int DEFAULT_THUMB_COLOR = 0xFF757575; + private static final int DEFAULT_TRACK_COLOR = 0x21FFFFFF; + + private final Paint mThumbPaint = new Paint(); + private final Paint mTrackPaint = new Paint(); + private final RectF mRect = new RectF(); + private final View mParent; + + public RoundScrollbarRenderer(View parent) { + // Paints for the round scrollbar. + // Set up the thumb paint + mThumbPaint.setAntiAlias(true); + mThumbPaint.setStrokeCap(Paint.Cap.ROUND); + mThumbPaint.setStyle(Paint.Style.STROKE); + + // Set up the track paint + mTrackPaint.setAntiAlias(true); + mTrackPaint.setStrokeCap(Paint.Cap.ROUND); + mTrackPaint.setStyle(Paint.Style.STROKE); + + mParent = parent; + } + + public void drawRoundScrollbars(Canvas canvas, float alpha, Rect bounds) { + if (alpha == 0) { + return; + } + // Get information about the current scroll state of the parent view. + float maxScroll = mParent.computeVerticalScrollRange(); + float scrollExtent = mParent.computeVerticalScrollExtent(); + if (scrollExtent <= 0 || maxScroll <= scrollExtent) { + return; + } + float currentScroll = Math.max(0, mParent.computeVerticalScrollOffset()); + float linearThumbLength = mParent.computeVerticalScrollExtent(); + float thumbWidth = mParent.getWidth() * WIDTH_PERCENTAGE; + mThumbPaint.setStrokeWidth(thumbWidth); + mTrackPaint.setStrokeWidth(thumbWidth); + + setThumbColor(applyAlpha(DEFAULT_THUMB_COLOR, alpha)); + setTrackColor(applyAlpha(DEFAULT_TRACK_COLOR, alpha)); + + // Normalize the sweep angle for the scroll bar. + float sweepAngle = (linearThumbLength / maxScroll) * SCROLLBAR_ANGLE_RANGE; + sweepAngle = clamp(sweepAngle, MIN_SCROLLBAR_ANGLE_SWIPE, MAX_SCROLLBAR_ANGLE_SWIPE); + // Normalize the start angle so that it falls on the track. + float startAngle = (currentScroll * (SCROLLBAR_ANGLE_RANGE - sweepAngle)) + / (maxScroll - linearThumbLength) - SCROLLBAR_ANGLE_RANGE / 2; + startAngle = clamp(startAngle, -SCROLLBAR_ANGLE_RANGE / 2, + SCROLLBAR_ANGLE_RANGE / 2 - sweepAngle); + + // Draw the track and the scroll bar. + mRect.set( + bounds.left - thumbWidth / 2, + bounds.top, + bounds.right - thumbWidth / 2, + bounds.bottom); + + canvas.drawArc(mRect, -SCROLLBAR_ANGLE_RANGE / 2, SCROLLBAR_ANGLE_RANGE, false, + mTrackPaint); + canvas.drawArc(mRect, startAngle, sweepAngle, false, mThumbPaint); + } + + private static float clamp(float val, float min, float max) { + if (val < min) { + return min; + } else if (val > max) { + return max; + } else { + return val; + } + } + + private static int applyAlpha(int color, float alpha) { + int alphaByte = (int) (Color.alpha(color) * alpha); + return Color.argb(alphaByte, Color.red(color), Color.green(color), Color.blue(color)); + } + + private void setThumbColor(int thumbColor) { + if (mThumbPaint.getColor() != thumbColor) { + mThumbPaint.setColor(thumbColor); + } + } + + private void setTrackColor(int trackColor) { + if (mTrackPaint.getColor() != trackColor) { + mTrackPaint.setColor(trackColor); + } + } +} diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 7da849a832e4d52d7b2ae8d52e43bef37d601cb2..22e68a3b909cb0c9b7cbca420f372b3e808b8025 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -33,6 +33,18 @@ import dalvik.system.CloseGuard; /** * Handle onto a raw buffer that is being managed by the screen compositor. + * + *

    A Surface is generally created by or from a consumer of image buffers (such as a + * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or + * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as + * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL}, + * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or + * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw + * into.

    + * + *

    Note: A Surface acts like a + * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By + * itself it will not keep its parent consumer from being reclaimed.

    */ public class Surface implements Parcelable { private static final String TAG = "Surface"; @@ -58,6 +70,8 @@ public class Surface implements Parcelable { private static native long nativeGetNextFrameNumber(long nativeObject); private static native int nativeSetScalingMode(long nativeObject, int scalingMode); + private static native void nativeSetBuffersTransform(long nativeObject, long transform); + private static native int nativeForceScopedDisconnect(long nativeObject); public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -95,6 +109,8 @@ public class Surface implements Parcelable { private HwuiContext mHwuiContext; + private boolean mIsSingleBuffered; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({SCALING_MODE_FREEZE, SCALING_MODE_SCALE_TO_WINDOW, @@ -157,7 +173,7 @@ public class Surface implements Parcelable { if (surfaceTexture == null) { throw new IllegalArgumentException("surfaceTexture must not be null"); } - + mIsSingleBuffered = surfaceTexture.isSingleBuffered(); synchronized (mLock) { mName = surfaceTexture.toString(); setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture)); @@ -456,7 +472,10 @@ public class Surface implements Parcelable { // create a new native Surface and return it after reducing // the reference count on mNativeObject. Either way, it is // not necessary to call nativeRelease() here. + // NOTE: This must be kept synchronized with the native parceling code + // in frameworks/native/libs/Surface.cpp mName = source.readString(); + mIsSingleBuffered = source.readInt() != 0; setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source)); } } @@ -467,7 +486,10 @@ public class Surface implements Parcelable { throw new IllegalArgumentException("dest must not be null"); } synchronized (mLock) { + // NOTE: This must be kept synchronized with the native parceling code + // in frameworks/native/libs/Surface.cpp dest.writeString(mName); + dest.writeInt(mIsSingleBuffered ? 1 : 0); nativeWriteToParcel(mNativeObject, dest); } if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) { @@ -529,6 +551,24 @@ public class Surface implements Parcelable { } } + void forceScopedDisconnect() { + synchronized (mLock) { + checkNotReleasedLocked(); + int err = nativeForceScopedDisconnect(mNativeObject); + if (err != 0) { + throw new RuntimeException("Failed to disconnect Surface instance (bad object?)"); + } + } + } + + /** + * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture + * @hide + */ + public boolean isSingleBuffered() { + return mIsSingleBuffered; + } + /** * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or * when a SurfaceTexture could not successfully be allocated. diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 415e70ca03fdfb82015f63e47578857cc2057e52..e778a7f16f257f4432c8ae95710f945b7a92c005 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -51,7 +51,7 @@ public class SurfaceControl { private static native void nativeSetLayer(long nativeObject, int zorder); private static native void nativeSetPosition(long nativeObject, float x, float y); - private static native void nativeSetPositionAppliesWithResize(long nativeObject); + private static native void nativeSetGeometryAppliesWithResize(long nativeObject); private static native void nativeSetSize(long nativeObject, int w, int h); private static native void nativeSetTransparentRegionHint(long nativeObject, Region region); private static native void nativeSetAlpha(long nativeObject, float alpha); @@ -82,6 +82,10 @@ public class SurfaceControl { IBinder displayToken); private static native int nativeGetActiveConfig(IBinder displayToken); private static native boolean nativeSetActiveConfig(IBinder displayToken, int id); + private static native int[] nativeGetDisplayColorModes(IBinder displayToken); + private static native int nativeGetActiveColorMode(IBinder displayToken); + private static native boolean nativeSetActiveColorMode(IBinder displayToken, + int colorMode); private static native void nativeSetDisplayPowerMode( IBinder displayToken, int mode); private static native void nativeDeferTransactionUntil(long nativeObject, @@ -89,6 +93,8 @@ public class SurfaceControl { private static native void nativeSetOverrideScalingMode(long nativeObject, int scalingMode); private static native IBinder nativeGetHandle(long nativeObject); + private static native boolean nativeGetTransformToDisplayInverse(long nativeObject); + private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken); @@ -393,6 +399,10 @@ public class SurfaceControl { return nativeGetHandle(mNativeObject); } + public boolean getTransformToDisplayInverse() { + return nativeGetTransformToDisplayInverse(mNativeObject); + } + /** flag the transaction as an animation */ public static void setAnimationTransaction() { nativeSetAnimationTransaction(); @@ -409,13 +419,15 @@ public class SurfaceControl { } /** - * If the size changes in this transaction, position updates specified + * If the buffer size changes in this transaction, position and crop updates specified * in this transaction will not complete until a buffer of the new size - * arrives. + * arrives. As transform matrix and size are already frozen in this fashion, + * this enables totally freezing the surface until the resize has completed + * (at which point the geometry influencing aspects of this transaction will then occur) */ - public void setPositionAppliesWithResize() { + public void setGeometryAppliesWithResize() { checkNotReleased(); - nativeSetPositionAppliesWithResize(mNativeObject); + nativeSetGeometryAppliesWithResize(mNativeObject); } public void setSize(int w, int h) { @@ -539,7 +551,6 @@ public class SurfaceControl { public boolean secure; public long appVsyncOffsetNanos; public long presentationDeadlineNanos; - public int colorTransform; public PhysicalDisplayInfo() { } @@ -563,8 +574,7 @@ public class SurfaceControl { && yDpi == other.yDpi && secure == other.secure && appVsyncOffsetNanos == other.appVsyncOffsetNanos - && presentationDeadlineNanos == other.presentationDeadlineNanos - && colorTransform == other.colorTransform; + && presentationDeadlineNanos == other.presentationDeadlineNanos; } @Override @@ -582,7 +592,6 @@ public class SurfaceControl { secure = other.secure; appVsyncOffsetNanos = other.appVsyncOffsetNanos; presentationDeadlineNanos = other.presentationDeadlineNanos; - colorTransform = other.colorTransform; } // For debugging purposes @@ -591,8 +600,7 @@ public class SurfaceControl { return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, " + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure + ", appVsyncOffset " + appVsyncOffsetNanos - + ", bufferDeadline " + presentationDeadlineNanos - + ", colorTransform " + colorTransform + "}"; + + ", bufferDeadline " + presentationDeadlineNanos + "}"; } } @@ -624,6 +632,27 @@ public class SurfaceControl { return nativeSetActiveConfig(displayToken, id); } + public static int[] getDisplayColorModes(IBinder displayToken) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + return nativeGetDisplayColorModes(displayToken); + } + + public static int getActiveColorMode(IBinder displayToken) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + return nativeGetActiveColorMode(displayToken); + } + + public static boolean setActiveColorMode(IBinder displayToken, int colorMode) { + if (displayToken == null) { + throw new IllegalArgumentException("displayToken must not be null"); + } + return nativeSetActiveColorMode(displayToken, colorMode); + } + public static void setDisplayProjection(IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect) { if (displayToken == null) { diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 203b82563ef86d3d308cf769e195763a57bc2be1..4b9a5708173f456ee87392d91fb4951aa9255134 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -115,6 +115,7 @@ public class SurfaceView extends View { final Rect mStableInsets = new Rect(); final Rect mOutsets = new Rect(); final Rect mBackdropFrame = new Rect(); + final Rect mTmpRect = new Rect(); final Configuration mConfiguration = new Configuration(); static final int KEEP_SCREEN_ON_MSG = 1; @@ -193,26 +194,20 @@ public class SurfaceView extends View { private boolean mGlobalListenersAdded; public SurfaceView(Context context) { - super(context); - init(); + this(context, null); } public SurfaceView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); + this(context, attrs, 0); } public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); + this(context, attrs, defStyleAttr, 0); } public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - init(); - } - private void init() { setWillNotDraw(true); } @@ -233,6 +228,7 @@ public class SurfaceView extends View { mSession = getWindowSession(); mLayout.token = getWindowToken(); mLayout.setTitle("SurfaceView - " + getViewRootImpl().getTitle()); + mLayout.packageName = mContext.getOpPackageName(); mViewVisibility = getVisibility() == VISIBLE; if (!mGlobalListenersAdded) { @@ -499,7 +495,7 @@ public class SurfaceView extends View { | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE ; - if (!creating && !force && !mUpdateWindowNeeded && !sizeChanged) { + if (!creating && !force && !sizeChanged) { mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY; } else { @@ -591,6 +587,20 @@ public class SurfaceView extends View { for (SurfaceHolder.Callback c : callbacks) { c.surfaceDestroyed(mSurfaceHolder); } + // Since Android N the same surface may be reused and given to us + // again by the system server at a later point. However + // as we didn't do this in previous releases, clients weren't + // necessarily required to clean up properly in + // surfaceDestroyed. This leads to problems for example when + // clients don't destroy their EGL context, and try + // and create a new one on the same surface following reuse. + // Since there is no valid use of the surface in-between + // surfaceDestroyed and surfaceCreated, we force a disconnect, + // so the next connect will always work if we end up reusing + // the surface. + if (mSurface.isValid()) { + mSurface.forceScopedDisconnect(); + } } } @@ -666,21 +676,21 @@ public class SurfaceView extends View { transformFromViewToWindowSpace(mLocation); - mWinFrame.set(mWindowSpaceLeft, mWindowSpaceTop, + mTmpRect.set(mWindowSpaceLeft, mWindowSpaceTop, mLocation[0], mLocation[1]); if (mTranslator != null) { - mTranslator.translateRectInAppWindowToScreen(mWinFrame); + mTranslator.translateRectInAppWindowToScreen(mTmpRect); } if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) { try { if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition UI, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), - mWinFrame.left, mWinFrame.top, - mWinFrame.right, mWinFrame.bottom)); - mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top, - mWinFrame.right, mWinFrame.bottom, -1, mWinFrame); + mTmpRect.left, mTmpRect.top, + mTmpRect.right, mTmpRect.bottom)); + mSession.repositionChild(mWindow, mTmpRect.left, mTmpRect.top, + mTmpRect.right, mTmpRect.bottom, -1, mTmpRect); } catch (RemoteException ex) { Log.e(TAG, "Exception from relayout", ex); } @@ -692,10 +702,10 @@ public class SurfaceView extends View { private Rect mRTLastReportedPosition = new Rect(); /** - * Called by native on RenderThread to update the window position + * Called by native by a Rendering Worker thread to update the window position * @hide */ - public final void updateWindowPositionRT(long frameNumber, + public final void updateWindowPosition_renderWorker(long frameNumber, int left, int top, int right, int bottom) { IWindowSession session = mSession; MyWindow window = mWindow; @@ -720,7 +730,7 @@ public class SurfaceView extends View { } try { if (DEBUG) { - Log.d(TAG, String.format("%d updateWindowPosition RT, frameNr = %d, " + + Log.d(TAG, String.format("%d updateWindowPosition RenderWorker, frameNr = %d, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), frameNumber, left, top, right, bottom)); } @@ -737,12 +747,12 @@ public class SurfaceView extends View { /** * Called by native on RenderThread to notify that the window is no longer in the - * draw tree + * draw tree. UI thread is blocked at this point. * @hide */ - public final void windowPositionLostRT(long frameNumber) { + public final void windowPositionLost_uiRtSync(long frameNumber) { if (DEBUG) { - Log.d(TAG, String.format("%d windowPositionLostRT RT, frameNr = %d", + Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d", System.identityHashCode(this), frameNumber)); } IWindowSession session = mSession; @@ -757,14 +767,18 @@ public class SurfaceView extends View { // safely access other member variables at this time. // So do what the UI thread would have done if RT wasn't handling position // updates. - if (!mWinFrame.isEmpty() && !mWinFrame.equals(mRTLastReportedPosition)) { + mTmpRect.set(mLayout.x, mLayout.y, + mLayout.x + mLayout.width, + mLayout.y + mLayout.height); + + if (!mTmpRect.isEmpty() && !mTmpRect.equals(mRTLastReportedPosition)) { try { if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition, " + "postion = [%d, %d, %d, %d]", System.identityHashCode(this), - mWinFrame.left, mWinFrame.top, - mWinFrame.right, mWinFrame.bottom)); - session.repositionChild(window, mWinFrame.left, mWinFrame.top, - mWinFrame.right, mWinFrame.bottom, frameNumber, mWinFrame); + mTmpRect.left, mTmpRect.top, + mTmpRect.right, mTmpRect.bottom)); + session.repositionChild(window, mTmpRect.left, mTmpRect.top, + mTmpRect.right, mTmpRect.bottom, frameNumber, mWinFrame); } catch (RemoteException ex) { Log.e(TAG, "Exception from relayout", ex); } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 1a712c3916db759bed43f16ecf85e0853f59fc73..645ab5cdd3fa396441d17390d0706c5929d3086c 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -218,15 +218,33 @@ public class TextureView extends View { /** @hide */ @Override protected void onDetachedFromWindowInternal() { - destroySurface(); + destroyHardwareLayer(); + releaseSurfaceTexture(); super.onDetachedFromWindowInternal(); } - private void destroySurface() { + /** + * @hide + */ + @Override + protected void destroyHardwareResources() { + super.destroyHardwareResources(); + destroyHardwareLayer(); + } + + private void destroyHardwareLayer() { if (mLayer != null) { mLayer.detachSurfaceTexture(); + mLayer.destroy(); + mLayer = null; + mMatrixChanged = true; + } + } + private void releaseSurfaceTexture() { + if (mSurface != null) { boolean shouldRelease = true; + if (mListener != null) { shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface); } @@ -235,14 +253,10 @@ public class TextureView extends View { nDestroyNativeWindow(); } - mLayer.destroy(); - if (shouldRelease) mSurface.release(); + if (shouldRelease) { + mSurface.release(); + } mSurface = null; - mLayer = null; - - // Make sure if/when new layer gets re-created, transform matrix will - // be re-applied. - mMatrixChanged = true; mHadSurface = true; } } @@ -355,17 +369,6 @@ public class TextureView extends View { } } - /** - * @hide - */ - @Override - protected void destroyHardwareResources() { - super.destroyHardwareResources(); - destroySurface(); - invalidateParentCaches(); - invalidate(true); - } - HardwareLayer getHardwareLayer() { if (mLayer == null) { if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) { @@ -373,17 +376,17 @@ public class TextureView extends View { } mLayer = mAttachInfo.mHardwareRenderer.createTextureLayer(); - if (!mUpdateSurface) { + boolean createNewSurface = (mSurface == null); + if (createNewSurface) { // Create a new SurfaceTexture for the layer. mSurface = new SurfaceTexture(false); - mLayer.setSurfaceTexture(mSurface); + nCreateNativeWindow(mSurface); } + mLayer.setSurfaceTexture(mSurface); mSurface.setDefaultBufferSize(getWidth(), getHeight()); - nCreateNativeWindow(mSurface); - mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler); - if (mListener != null && !mUpdateSurface) { + if (mListener != null && createNewSurface) { mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight()); } mLayer.setLayerPaint(mLayerPaint); @@ -717,7 +720,7 @@ public class TextureView extends View { /** * Set the {@link SurfaceTexture} for this view to use. If a {@link * SurfaceTexture} is already being used by this view, it is immediately - * released and not be usable any more. The {@link + * released and not usable any more. The {@link * SurfaceTextureListener#onSurfaceTextureDestroyed} callback is not * called for the previous {@link SurfaceTexture}. Similarly, the {@link * SurfaceTextureListener#onSurfaceTextureAvailable} callback is not @@ -742,9 +745,11 @@ public class TextureView extends View { "released SurfaceTexture"); } if (mSurface != null) { + nDestroyNativeWindow(); mSurface.release(); } mSurface = surfaceTexture; + nCreateNativeWindow(mSurface); /* * If the view is visible and we already made a layer, update the diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index e650d956915ac52afe53997b87d996bbecd73a85..2e0729be8b6368d075e8e5aaa29fb7ca24fa13fb 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -16,6 +16,7 @@ package android.view; +import android.app.ActivityManagerNative; import android.annotation.IntDef; import android.annotation.NonNull; import android.content.Context; @@ -23,6 +24,7 @@ import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.Rect; +import android.graphics.drawable.AnimatedVectorDrawable; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -517,16 +519,6 @@ public final class ThreadedRenderer { } } - /** - * This method should be invoked whenever the current hardware renderer - * context should be reset. - * - * @param surface The surface to hardware accelerate - */ - void invalidate(Surface surface) { - updateSurface(surface); - } - /** * Detaches the layer's surface texture from the GL context and releases * the texture id @@ -881,6 +873,12 @@ public final class ThreadedRenderer { nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode); } + void registerVectorDrawableAnimator( + AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) { + nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode, + animator.getAnimatorNativePtr()); + } + public void serializeDisplayListTree() { nSerializeDisplayListTree(mNativeProxy); } @@ -910,10 +908,20 @@ public final class ThreadedRenderer { synchronized void init(Context context, long renderProxy) { if (mInitialized) return; mInitialized = true; + initSched(context, renderProxy); initGraphicsStats(context, renderProxy); initAssetAtlas(context, renderProxy); } + private static void initSched(Context context, long renderProxy) { + try { + int tid = nGetRenderThreadTid(renderProxy); + ActivityManagerNative.getDefault().setRenderThread(tid); + } catch (Throwable t) { + Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t); + } + } + private static void initGraphicsStats(Context context, long renderProxy) { try { IBinder binder = ServiceManager.getService("graphicsstats"); @@ -972,6 +980,7 @@ public final class ThreadedRenderer { private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map); private static native void nSetProcessStatsBuffer(long nativeProxy, int fd); + private static native int nGetRenderThreadTid(long nativeProxy); private static native long nCreateRootRenderNode(); private static native long nCreateProxy(boolean translucent, long rootRenderNode); @@ -992,6 +1001,7 @@ public final class ThreadedRenderer { private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size); private static native void nDestroy(long nativeProxy, long rootRenderNode); private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode); + private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator); private static native void nInvokeFunctor(long functor, boolean waitForCompletion); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d3f0c77870f737bcf6c80d0987b0e71050e42b72..d13f6d6d6ae0b002e94eb514b8860b440a78552b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -819,6 +819,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static boolean sTextureViewIgnoresDrawableSetters = false; + /** + * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend + * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to + * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API + * check is implemented for backwards compatibility. + * + * {@hide} + */ + protected static boolean sPreserveMarginParamsInLayoutParamConversion; + + /** + * Prior to N, when drag enters into child of a view that has already received an + * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event. + * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned + * false from its event handler for these events. + * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its + * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent. + * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation. + */ + static boolean sCascadedDragDrop; + /** * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when * calling setFlags. @@ -2435,6 +2456,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED * 1 PFLAG3_TEMPORARY_DETACH + * 1 PFLAG3_NO_REVEAL_ON_FOCUS * |-------|-------|-------|-------| */ @@ -2676,6 +2698,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static final int PFLAG3_TEMPORARY_DETACH = 0x2000000; + /** + * Flag indicating that the view does not wish to be revealed within its parent + * hierarchy when it gains focus. Expressed in the negative since the historical + * default behavior is to reveal on focus; this flag suppresses that behavior. + * + * @see #setRevealOnFocusHint(boolean) + * @see #getRevealOnFocusHint() + */ + private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000; + /* End of masks for mPrivateFlags3 */ /** @@ -3061,20 +3093,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000; - /** - * @hide - * - * Whether Recents is visible or not. - */ - public static final int RECENT_APPS_VISIBLE = 0x00004000; - - /** - * @hide - * - * Whether the TV's picture-in-picture is visible or not. - */ - public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000; - /** * @hide * @@ -3744,12 +3762,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Flag indicating that a drag can cross window boundaries. When * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called - * with this flag set, all visible applications will be able to participate + * with this flag set, all visible applications with targetSdkVersion >= + * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate * in the drag operation and receive the dragged content. * - * If this is the only flag set, then the drag recipient will only have access to text data + *

    If this is the only flag set, then the drag recipient will only have access to text data * and intents contained in the {@link ClipData} object. Access to URIs contained in the - * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags. + * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags

    */ public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256 @@ -3979,6 +3998,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ String mStartActivityRequestWho; + @Nullable + private RoundScrollbarRenderer mRoundScrollbarRenderer; + /** * Simple constructor to use when creating a view from code. * @@ -4036,6 +4058,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // On N+, we throw, but that breaks compatibility with apps that use these methods. sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M; + // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs + // in apps so we target check it to avoid breaking existing apps. + sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N; + + sCascadedDragDrop = targetSdkVersion < N; + sCompatibilityDone = true; } } @@ -4214,25 +4242,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setAlpha(a.getFloat(attr, 1f)); break; case com.android.internal.R.styleable.View_transformPivotX: - setPivotX(a.getDimensionPixelOffset(attr, 0)); + setPivotX(a.getDimension(attr, 0)); break; case com.android.internal.R.styleable.View_transformPivotY: - setPivotY(a.getDimensionPixelOffset(attr, 0)); + setPivotY(a.getDimension(attr, 0)); break; case com.android.internal.R.styleable.View_translationX: - tx = a.getDimensionPixelOffset(attr, 0); + tx = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_translationY: - ty = a.getDimensionPixelOffset(attr, 0); + ty = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_translationZ: - tz = a.getDimensionPixelOffset(attr, 0); + tz = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_elevation: - elevation = a.getDimensionPixelOffset(attr, 0); + elevation = a.getDimension(attr, 0); transformSet = true; break; case com.android.internal.R.styleable.View_rotation: @@ -5939,6 +5967,47 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } + /** + * Sets this view's preference for reveal behavior when it gains focus. + * + *

    When set to true, this is a signal to ancestor views in the hierarchy that + * this view would prefer to be brought fully into view when it gains focus. + * For example, a text field that a user is meant to type into. Other views such + * as scrolling containers may prefer to opt-out of this behavior.

    + * + *

    The default value for views is true, though subclasses may change this + * based on their preferred behavior.

    + * + * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise + * + * @see #getRevealOnFocusHint() + */ + public final void setRevealOnFocusHint(boolean revealOnFocus) { + if (revealOnFocus) { + mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS; + } else { + mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS; + } + } + + /** + * Returns this view's preference for reveal behavior when it gains focus. + * + *

    When this method returns true for a child view requesting focus, ancestor + * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)} + * should make a best effort to make the newly focused child fully visible to the user. + * When it returns false, ancestor views should preferably not disrupt scroll positioning or + * other properties affecting visibility to the user as part of the focus change.

    + * + * @return true if this view would prefer to become fully visible when it gains focus, + * false if it would prefer not to disrupt scroll positioning + * + * @see #setRevealOnFocusHint(boolean) + */ + public final boolean getRevealOnFocusHint() { + return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0; + } + /** * Populates outRect with the hotspot bounds. By default, * the hotspot bounds are identical to the screen bounds. @@ -7990,7 +8059,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Set the enabled state of this view. + * Set the visibility state of this view. * * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. * @attr ref android.R.styleable#View_visibility @@ -9780,6 +9849,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()} + * and {@link #onFinishTemporaryDetach()}. + * + *

    This method always returns {@code true} when called directly or indirectly from + * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from + * {@link #onFinishTemporaryDetach()}, however, depends on the OS version. + *

      + *
    • {@code true} on {@link android.os.Build.VERSION_CODES#N API 24}
    • + *
    • {@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later
    • + *
    + *

    + * * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()} * and {@link #onFinishTemporaryDetach()}. */ @@ -9814,8 +9895,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @CallSuper public void dispatchFinishTemporaryDetach() { - onFinishTemporaryDetach(); mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; + onFinishTemporaryDetach(); + if (hasWindowFocus() && hasFocus()) { + InputMethodManager.getInstance().focusIn(this); + } } /** @@ -10298,7 +10382,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * ancestors or by window visibility * @return true if this view is visible to the user, not counting clipping or overlapping */ - @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) { + boolean dispatchVisibilityAggregated(boolean isVisible) { final boolean thisVisible = getVisibility() == VISIBLE; // If we're not visible but something is telling us we are, ignore it. if (thisVisible || !isVisible) { @@ -12302,6 +12386,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) { ensureTransformationInfo(); if (mTransformationInfo.mAlpha != alpha) { + // Report visibility changes, which can affect children, to accessibility + if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) { + notifySubtreeAccessibilityStateChangedIfNeeded(); + } mTransformationInfo.mAlpha = alpha; if (onSetAlpha((int) (alpha * 255))) { mPrivateFlags |= PFLAG_ALPHA_SET; @@ -12312,8 +12400,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags &= ~PFLAG_ALPHA_SET; invalidateViewProperty(true, false); mRenderNode.setAlpha(getFinalAlpha()); - notifyViewAccessibilityStateChangedIfNeeded( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); } } } @@ -14713,6 +14799,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void getVerticalScrollBarBounds(Rect bounds) { + if (mRoundScrollbarRenderer == null) { + getStraightVerticalScrollBarBounds(bounds); + } else { + getRoundVerticalScrollBarBounds(bounds); + } + } + + private void getRoundVerticalScrollBarBounds(Rect bounds) { + final int width = mRight - mLeft; + final int height = mBottom - mTop; + // Do not take padding into account as we always want the scrollbars + // to hug the screen for round wearable devices. + bounds.left = mScrollX; + bounds.top = mScrollY; + bounds.right = bounds.left + width; + bounds.bottom = mScrollY + height; + } + + private void getStraightVerticalScrollBarBounds(Rect bounds) { final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; final int size = getVerticalScrollbarWidth(); int verticalScrollbarPosition = mVerticalScrollbarPosition; @@ -14747,6 +14852,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, protected final void onDrawScrollBars(Canvas canvas) { // scrollbars are drawn only when the animation is running final ScrollabilityCache cache = mScrollCache; + if (cache != null) { int state = cache.state; @@ -14787,13 +14893,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden(); - if (drawVerticalScrollBar || drawHorizontalScrollBar) { + // Fork out the scroll bar drawing for round wearable devices. + if (mRoundScrollbarRenderer != null) { + if (drawVerticalScrollBar) { + final Rect bounds = cache.mScrollBarBounds; + getVerticalScrollBarBounds(bounds); + mRoundScrollbarRenderer.drawRoundScrollbars( + canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds); + if (invalidate) { + invalidate(); + } + } + // Do not draw horizontal scroll bars for round wearable devices. + } else if (drawVerticalScrollBar || drawHorizontalScrollBar) { final ScrollBarDrawable scrollBar = cache.scrollBar; if (drawHorizontalScrollBar) { scrollBar.setParameters(computeHorizontalScrollRange(), - computeHorizontalScrollOffset(), - computeHorizontalScrollExtent(), false); + computeHorizontalScrollOffset(), + computeHorizontalScrollExtent(), false); final Rect bounds = cache.mScrollBarBounds; getHorizontalScrollBarBounds(bounds); onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top, @@ -14805,8 +14923,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (drawVerticalScrollBar) { scrollBar.setParameters(computeVerticalScrollRange(), - computeVerticalScrollOffset(), - computeVerticalScrollExtent(), true); + computeVerticalScrollOffset(), + computeVerticalScrollExtent(), true); final Rect bounds = cache.mScrollBarBounds; getVerticalScrollBarBounds(bounds); onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top, @@ -15407,7 +15525,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (vis != GONE) { onWindowVisibilityChanged(vis); if (isShown()) { - // Calling onVisibilityChanged directly here since the subtree will also + // Calling onVisibilityAggregated directly here since the subtree will also // receive dispatchAttachedToWindow and this same call onVisibilityAggregated(vis == VISIBLE); } @@ -17517,6 +17635,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { onLayout(changed, l, t, r, b); + + if (shouldDrawRoundScrollbar()) { + if(mRoundScrollbarRenderer == null) { + mRoundScrollbarRenderer = new RoundScrollbarRenderer(this); + } + } else { + mRoundScrollbarRenderer = null; + } + mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; ListenerInfo li = mListenerInfo; @@ -20151,8 +20278,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // remove it from the transparent region. final int[] location = attachInfo.mTransparentLocation; getLocationInWindow(location); - region.op(location[0], location[1], location[0] + mRight - mLeft, - location[1] + mBottom - mTop, Region.Op.DIFFERENCE); + // When a view has Z value, then it will be better to leave some area below the view + // for drawing shadow. The shadow outset is proportional to the Z value. Note that + // the bottom part needs more offset than the left, top and right parts due to the + // spot light effects. + int shadowOffset = getZ() > 0 ? (int) getZ() : 0; + region.op(location[0] - shadowOffset, location[1] - shadowOffset, + location[0] + mRight - mLeft + shadowOffset, + location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE); } else { if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) { // The SKIP_DRAW flag IS set and the background drawable exists, we remove @@ -20520,8 +20653,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the * drag shadow. * @param myLocalState An {@link java.lang.Object} containing local data about the drag and - * drop operation. This Object is put into every DragEvent object sent by the system during the - * current drag. + * drop operation. When dispatching drag events to views in the same activity this object + * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other + * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()} + * will return null). *

    * myLocalState is a lightweight mechanism for the sending information from the dragged View * to the target Views. For example, it can contain flags that differentiate between a @@ -20533,7 +20668,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, *

  • {@link #DRAG_FLAG_GLOBAL}
  • *
  • {@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}
  • *
  • {@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}
  • - *
  • {@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}
  • *
  • {@link #DRAG_FLAG_GLOBAL_URI_READ}
  • *
  • {@link #DRAG_FLAG_GLOBAL_URI_WRITE}
  • *
  • {@link #DRAG_FLAG_OPAQUE}
  • @@ -20723,6 +20857,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return false; } + // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps. + boolean dispatchDragEnterExitInPreN(DragEvent event) { + return callDragEventHandler(event); + } + /** * Detects if this View is enabled and has a drag event listener. * If both are true, then it calls the drag event listener with the @@ -20740,13 +20879,44 @@ public class View implements Drawable.Callback, KeyEvent.Callback, *

    */ public boolean dispatchDragEvent(DragEvent event) { + event.mEventHandlerWasCalled = true; + if (event.mAction == DragEvent.ACTION_DRAG_LOCATION || + event.mAction == DragEvent.ACTION_DROP) { + // About to deliver an event with coordinates to this view. Notify that now this view + // has drag focus. This will send exit/enter events as needed. + getViewRootImpl().setDragFocus(this, event); + } + return callDragEventHandler(event); + } + + final boolean callDragEventHandler(DragEvent event) { + final boolean result; + ListenerInfo li = mListenerInfo; //noinspection SimplifiableIfStatement if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnDragListener.onDrag(this, event)) { - return true; + result = true; + } else { + result = onDragEvent(event); + } + + switch (event.mAction) { + case DragEvent.ACTION_DRAG_ENTERED: { + mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED; + refreshDrawableState(); + } break; + case DragEvent.ACTION_DRAG_EXITED: { + mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED; + refreshDrawableState(); + } break; + case DragEvent.ACTION_DRAG_ENDED: { + mPrivateFlags2 &= ~View.DRAG_MASK; + refreshDrawableState(); + } break; } - return onDragEvent(event); + + return result; } boolean canAcceptDrag() { @@ -22850,7 +23020,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Last global system UI visibility reported by the window manager. */ - int mGlobalSystemUiVisibility; + int mGlobalSystemUiVisibility = -1; /** * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener @@ -22897,7 +23067,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final int[] mInvalidateChildLocation = new int[2]; /** - * Global to the view hierarchy used as a temporary for dealng with + * Global to the view hierarchy used as a temporary for dealing with * computing absolute on-screen location. */ final int[] mTmpLocation = new int[2]; @@ -23735,4 +23905,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, stream.addProperty("accessibility:labelFor", getLabelFor()); stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); } + + /** + * Determine if this view is rendered on a round wearable device and is the main view + * on the screen. + */ + private boolean shouldDrawRoundScrollbar() { + if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) { + return false; + } + + final View rootView = getRootView(); + final WindowInsets insets = getRootWindowInsets(); + + int height = getHeight(); + int width = getWidth(); + int displayHeight = rootView.getHeight(); + int displayWidth = rootView.getWidth(); + + if (height != displayHeight || width != displayWidth) { + return false; + } + + getLocationOnScreen(mAttachInfo.mTmpLocation); + return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft() + && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop(); + } } diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index 4d584a3df4fb829beaf9b73f3565bbd2c4f48fea..8b8525f2f1b5399b6971fe3ff75e811a681edaae 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -16,6 +16,7 @@ package android.view; +import android.annotation.SystemApi; import android.app.AppGlobals; import android.content.Context; import android.content.res.Configuration; @@ -63,6 +64,12 @@ public class ViewConfiguration { */ private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500; + /** + * Defines the default duration in milliseconds between the first tap's up event and the second + * tap's down event for an interaction to be considered part of the same multi-press. + */ + private static final int DEFAULT_MULTI_PRESS_TIMEOUT = 300; + /** * Defines the time between successive key repeats in milliseconds. */ @@ -212,6 +219,12 @@ public class ViewConfiguration { */ private static final int OVERFLING_DISTANCE = 6; + /** + * Amount to scroll in response to a {@link MotionEvent#ACTION_SCROLL} event, in dips per + * axis value. + */ + private static final int SCROLL_FACTOR = 64; + /** * Default duration to hide an action mode for. */ @@ -240,6 +253,7 @@ public class ViewConfiguration { private final int mOverflingDistance; private final boolean mFadingMarqueeEnabled; private final long mGlobalActionsKeyTimeout; + private final int mScrollFactor; private boolean sHasPermanentMenuKey; private boolean sHasPermanentMenuKeySet; @@ -268,6 +282,7 @@ public class ViewConfiguration { mOverflingDistance = OVERFLING_DISTANCE; mFadingMarqueeEnabled = true; mGlobalActionsKeyTimeout = GLOBAL_ACTIONS_KEY_TIMEOUT; + mScrollFactor = SCROLL_FACTOR; } /** @@ -351,6 +366,8 @@ public class ViewConfiguration { com.android.internal.R.dimen.config_viewMaxFlingVelocity); mGlobalActionsKeyTimeout = res.getInteger( com.android.internal.R.integer.config_globalActionsKeyTimeout); + mScrollFactor = res.getDimensionPixelSize( + com.android.internal.R.dimen.config_scrollFactor); } /** @@ -440,6 +457,16 @@ public class ViewConfiguration { DEFAULT_LONG_PRESS_TIMEOUT); } + /** + * @return the duration in milliseconds between the first tap's up event and the second tap's + * down event for an interaction to be considered part of the same multi-press. + * @hide + */ + public static int getMultiPressTimeout() { + return AppGlobals.getIntCoreSetting(Settings.Secure.MULTI_PRESS_TIMEOUT, + DEFAULT_MULTI_PRESS_TIMEOUT); + } + /** * @return the time before the first key repeat in milliseconds. */ @@ -652,6 +679,16 @@ public class ViewConfiguration { return mMaximumFlingVelocity; } + /** + * @return Amount to scroll in response to a {@link MotionEvent#ACTION_SCROLL} event. Multiply + * this by the event's axis value to obtain the number of pixels to be scrolled. + * @hide + * @SystemApi + */ + public int getScaledScrollFactor() { + return mScrollFactor; + } + /** * The maximum drawing cache size expressed in bytes. * diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 3ff8d4f2e2b1b6a0cc56c7ec51d2dda762011c60..d4b7d3bdd76aacee53f635c0d1cd8f142e2b6b7e 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -153,8 +153,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ Transformation mInvalidationTransformation; - // View currently under an ongoing drag. Can be null, a child or this window. - private View mCurrentDragView; + // Current frontmost child that can accept drag and lies under the drag location. + // Used only to generate ENTER/EXIT events for pre-Nougat aps. + private View mCurrentDragChild; // Metadata about the ongoing drag private DragEvent mCurrentDragStartEvent; @@ -1355,6 +1356,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return mLocalPoint; } + @Override + boolean dispatchDragEnterExitInPreN(DragEvent event) { + if (event.mAction == DragEvent.ACTION_DRAG_EXITED && mCurrentDragChild != null) { + // The drag exited a sub-tree of views; notify of the exit all descendants that are in + // entered state. + // We don't need this recursive delivery for ENTERED events because they get generated + // from the recursive delivery of LOCATION/DROP events, and hence, don't need their own + // recursion. + mCurrentDragChild.dispatchDragEnterExitInPreN(event); + mCurrentDragChild = null; + } + return mIsInterestedInDrag && super.dispatchDragEnterExitInPreN(event); + } + // TODO: Write real docs @Override public boolean dispatchDragEvent(DragEvent event) { @@ -1362,15 +1377,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final float tx = event.mX; final float ty = event.mY; - ViewRootImpl root = getViewRootImpl(); - // Dispatch down the view hierarchy final PointF localPoint = getLocalPoint(); switch (event.mAction) { case DragEvent.ACTION_DRAG_STARTED: { - // clear state to recalculate which views we drag over - mCurrentDragView = null; + // Clear the state to recalculate which views we drag over. + mCurrentDragChild = null; // Set up our tracking of drag-started notifications mCurrentDragStartEvent = DragEvent.obtain(event); @@ -1416,8 +1429,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (child.dispatchDragEvent(event)) { retval = true; } - child.mPrivateFlags2 &= ~View.DRAG_MASK; - child.refreshDrawableState(); } childrenInterestedInDrag.clear(); } @@ -1434,60 +1445,45 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } break; - case DragEvent.ACTION_DRAG_LOCATION: { + case DragEvent.ACTION_DRAG_LOCATION: + case DragEvent.ACTION_DROP: { // Find the [possibly new] drag target View target = findFrontmostDroppableChildAt(event.mX, event.mY, localPoint); - if (target == null && mIsInterestedInDrag) { - target = this; - } - // If we've changed apparent drag target, tell the view root which view - // we're over now [for purposes of the eventual drag-recipient-changed - // notifications to the framework] and tell the new target that the drag - // has entered its bounds. The root will see setDragFocus() calls all - // the way down to the final leaf view that is handling the LOCATION event - // before reporting the new potential recipient to the framework. - if (mCurrentDragView != target) { - root.setDragFocus(target); - - final int action = event.mAction; - // Position should not be available for ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED. - event.mX = 0; - event.mY = 0; - - // If we've dragged off of a child view or this window, send it the EXITED message - if (mCurrentDragView != null) { - final View view = mCurrentDragView; - event.mAction = DragEvent.ACTION_DRAG_EXITED; - if (view != this) { - view.dispatchDragEvent(event); - view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED; - view.refreshDrawableState(); - } else { - super.dispatchDragEvent(event); + if (target != mCurrentDragChild) { + if (sCascadedDragDrop) { + // For pre-Nougat apps, make sure that the whole hierarchy of views that contain + // the drag location is kept in the state between ENTERED and EXITED events. + // (Starting with N, only the innermost view will be in that state). + + final int action = event.mAction; + // Position should not be available for ACTION_DRAG_ENTERED and + // ACTION_DRAG_EXITED. + event.mX = 0; + event.mY = 0; + + if (mCurrentDragChild != null) { + event.mAction = DragEvent.ACTION_DRAG_EXITED; + mCurrentDragChild.dispatchDragEnterExitInPreN(event); } - } - mCurrentDragView = target; - - // If we've dragged over a new child view, send it the ENTERED message, otherwise - // send it to this window. - if (target != null) { - event.mAction = DragEvent.ACTION_DRAG_ENTERED; - if (target != this) { - target.dispatchDragEvent(event); - target.mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED; - target.refreshDrawableState(); - } else { - super.dispatchDragEvent(event); + if (target != null) { + event.mAction = DragEvent.ACTION_DRAG_ENTERED; + target.dispatchDragEnterExitInPreN(event); } + + event.mAction = action; + event.mX = tx; + event.mY = ty; } - event.mAction = action; // restore the event's original state - event.mX = tx; - event.mY = ty; + mCurrentDragChild = target; } - // Dispatch the actual drag location notice, localized into its coordinates + if (target == null && mIsInterestedInDrag) { + target = this; + } + + // Dispatch the actual drag notice, localized into the target coordinates. if (target != null) { if (target != this) { event.mX = localPoint.x; @@ -1497,55 +1493,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager event.mX = tx; event.mY = ty; - } else { - retval = super.dispatchDragEvent(event); - } - } - } break; - /* Entered / exited dispatch - * - * DRAG_ENTERED is not dispatched downwards from ViewGroup. The reason for this is - * that we're about to get the corresponding LOCATION event, which we will use to - * determine which of our children is the new target; at that point we will - * push a DRAG_ENTERED down to the new target child [which may itself be a ViewGroup]. - * If no suitable child is detected, dispatch to this window. - * - * DRAG_EXITED *is* dispatched all the way down immediately: once we know the - * drag has left this ViewGroup, we know by definition that every contained subview - * is also no longer under the drag point. - */ + if (mIsInterestedInDrag) { + final boolean eventWasConsumed; + if (sCascadedDragDrop) { + eventWasConsumed = retval; + } else { + eventWasConsumed = event.mEventHandlerWasCalled; + } - case DragEvent.ACTION_DRAG_EXITED: { - if (mCurrentDragView != null) { - final View view = mCurrentDragView; - if (view != this) { - view.dispatchDragEvent(event); - view.mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED; - view.refreshDrawableState(); + if (!eventWasConsumed) { + retval = super.dispatchDragEvent(event); + } + } } else { - super.dispatchDragEvent(event); - } - - mCurrentDragView = null; - } - } break; - - case DragEvent.ACTION_DROP: { - if (ViewDebug.DEBUG_DRAG) Log.d(View.VIEW_LOG_TAG, "Drop event: " + event); - View target = findFrontmostDroppableChildAt(event.mX, event.mY, localPoint); - if (target != null) { - if (ViewDebug.DEBUG_DRAG) Log.d(View.VIEW_LOG_TAG, " dispatch drop to " + target); - event.mX = localPoint.x; - event.mY = localPoint.y; - retval = target.dispatchDragEvent(event); - event.mX = tx; - event.mY = ty; - } else if (mIsInterestedInDrag) { - retval = super.dispatchDragEvent(event); - } else { - if (ViewDebug.DEBUG_DRAG) { - Log.d(View.VIEW_LOG_TAG, " not dropped on an accepting view"); + retval = super.dispatchDragEvent(event); } } } break; @@ -1592,6 +1554,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final boolean canAccept = child.dispatchDragEvent(mCurrentDragStartEvent); mCurrentDragStartEvent.mX = tx; mCurrentDragStartEvent.mY = ty; + mCurrentDragStartEvent.mEventHandlerWasCalled = false; if (canAccept) { mChildrenInterestedInDrag.add(child); if (!child.canAcceptDrag()) { @@ -6406,16 +6369,28 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return true; } super.gatherTransparentRegion(region); - final View[] children = mChildren; - final int count = mChildrenCount; + // Instead of naively traversing the view tree, we have to traverse according to the Z + // order here. We need to go with the same order as dispatchDraw(). + // One example is that after surfaceView punch a hole, we will still allow other views drawn + // on top of that hole. In this case, those other views should be able to cut the + // transparent region into smaller area. + final int childrenCount = mChildrenCount; boolean noneOfTheChildrenAreTransparent = true; - for (int i = 0; i < count; i++) { - final View child = children[i]; - if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { - if (!child.gatherTransparentRegion(region)) { - noneOfTheChildrenAreTransparent = false; + if (childrenCount > 0) { + final ArrayList preorderedList = buildOrderedChildList(); + final boolean customOrder = preorderedList == null + && isChildrenDrawingOrderEnabled(); + final View[] children = mChildren; + for (int i = 0; i < childrenCount; i++) { + final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder); + final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex); + if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { + if (!child.gatherTransparentRegion(region)) { + noneOfTheChildrenAreTransparent = false; + } } } + if (preorderedList != null) preorderedList.clear(); } return meOpaque || noneOfTheChildrenAreTransparent; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 195786dfcf2a921dc68a282efd7154ed215bdb75..f761b9b4ea147660d41550de6a342e42d23c267a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -44,6 +44,7 @@ import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.Region; +import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; @@ -822,6 +823,13 @@ public final class ViewRootImpl implements ViewParent, } } + public void registerVectorDrawableAnimator( + AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) { + if (mAttachInfo.mHardwareRenderer != null) { + mAttachInfo.mHardwareRenderer.registerVectorDrawableAnimator(animator); + } + } + private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) { mAttachInfo.mHardwareAccelerated = false; mAttachInfo.mHardwareAccelerationRequested = false; @@ -1459,6 +1467,8 @@ public final class ViewRootImpl implements ViewParent, final int viewVisibility = getHostVisibility(); final boolean viewVisibilityChanged = !mFirst && (mViewVisibility != viewVisibility || mNewSurfaceNeeded); + final boolean viewUserVisibilityChanged = !mFirst && + ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE)); WindowManager.LayoutParams params = null; if (mWindowAttributesChanged) { @@ -1532,7 +1542,9 @@ public final class ViewRootImpl implements ViewParent, if (viewVisibilityChanged) { mAttachInfo.mWindowVisibility = viewVisibility; host.dispatchWindowVisibilityChanged(viewVisibility); - host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE); + if (viewUserVisibilityChanged) { + host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE); + } if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { endDragResizing(); destroyHardwareResources(); @@ -1723,7 +1735,7 @@ public final class ViewRootImpl implements ViewParent, } boolean hwInitialized = false; - boolean framesChanged = false; + boolean contentInsetsChanged = false; boolean hadSurface = mSurface.isValid(); try { @@ -1763,7 +1775,7 @@ public final class ViewRootImpl implements ViewParent, final boolean overscanInsetsChanged = !mPendingOverscanInsets.equals( mAttachInfo.mOverscanInsets); - boolean contentInsetsChanged = !mPendingContentInsets.equals( + contentInsetsChanged = !mPendingContentInsets.equals( mAttachInfo.mContentInsets); final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals( mAttachInfo.mVisibleInsets); @@ -1813,19 +1825,6 @@ public final class ViewRootImpl implements ViewParent, + mAttachInfo.mVisibleInsets); } - // If any of the insets changed, do a forceLayout on the view so that the - // measure cache is cleared. We might have a pending MSG_RESIZED_REPORT - // that is supposed to take care of it, but since pending insets are - // already modified here, it won't detect the frame change after this. - framesChanged = overscanInsetsChanged - || contentInsetsChanged - || stableInsetsChanged - || visibleInsetsChanged - || outsetsChanged; - if (mAdded && mView != null && framesChanged) { - forceLayout(mView); - } - if (!hadSurface) { if (mSurface.isValid()) { // If we are creating a new surface, then we need to @@ -2009,7 +2008,7 @@ public final class ViewRootImpl implements ViewParent, boolean focusChangedDueToTouchMode = ensureTouchModeLocally( (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0); if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() - || mHeight != host.getMeasuredHeight() || framesChanged || + || mHeight != host.getMeasuredHeight() || contentInsetsChanged || updatedConfiguration) { int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height); @@ -2018,7 +2017,7 @@ public final class ViewRootImpl implements ViewParent, + mWidth + " measuredWidth=" + host.getMeasuredWidth() + " mHeight=" + mHeight + " measuredHeight=" + host.getMeasuredHeight() - + " framesChanged=" + framesChanged); + + " coveredInsetsChanged=" + contentInsetsChanged); // Ask host how big it wants to be performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); @@ -2168,7 +2167,12 @@ public final class ViewRootImpl implements ViewParent, } if (changedVisibility || regainedFocus) { - host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + // Toasts are presented as notifications - don't present them as windows as well + boolean isToast = (mWindowAttributes == null) ? false + : (mWindowAttributes.type == WindowManager.LayoutParams.TYPE_TOAST); + if (!isToast) { + host.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + } } mFirst = false; @@ -3178,7 +3182,7 @@ public final class ViewRootImpl implements ViewParent, } focusNode.recycle(); } - if (mAccessibilityFocusedHost != null) { + if ((mAccessibilityFocusedHost != null) && (mAccessibilityFocusedHost != view)) { // Clear accessibility focus in the view. mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks( AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); @@ -5507,22 +5511,24 @@ public final class ViewRootImpl implements ViewParent, if (mView != null && mAdded) { final int what = event.mAction; + // Cache the drag description when the operation starts, then fill it in + // on subsequent calls as a convenience + if (what == DragEvent.ACTION_DRAG_STARTED) { + mCurrentDragView = null; // Start the current-recipient tracking + mDragDescription = event.mClipDescription; + } else { + event.mClipDescription = mDragDescription; + } + if (what == DragEvent.ACTION_DRAG_EXITED) { // A direct EXITED event means that the window manager knows we've just crossed // a window boundary, so the current drag target within this one must have - // just been exited. Send it the usual notifications and then we're done - // for now. - mView.dispatchDragEvent(event); - } else { - // Cache the drag description when the operation starts, then fill it in - // on subsequent calls as a convenience - if (what == DragEvent.ACTION_DRAG_STARTED) { - mCurrentDragView = null; // Start the current-recipient tracking - mDragDescription = event.mClipDescription; - } else { - event.mClipDescription = mDragDescription; + // just been exited. Send the EXITED notification to the current drag view, if any. + if (View.sCascadedDragDrop) { + mView.dispatchDragEnterExitInPreN(event); } - + setDragFocus(null, event); + } else { // For events with a [screen] location, translate into window coordinates if ((what == DragEvent.ACTION_DRAG_LOCATION) || (what == DragEvent.ACTION_DROP)) { mDragPoint.set(event.mX, event.mY); @@ -5544,6 +5550,12 @@ public final class ViewRootImpl implements ViewParent, // Now dispatch the drag/drop event boolean result = mView.dispatchDragEvent(event); + if (what == DragEvent.ACTION_DRAG_LOCATION && !event.mEventHandlerWasCalled) { + // If the LOCATION event wasn't delivered to any handler, no view now has a drag + // focus. + setDragFocus(null, event); + } + // If we changed apparent drag target, tell the OS about it if (prevDragView != mCurrentDragView) { try { @@ -5571,6 +5583,7 @@ public final class ViewRootImpl implements ViewParent, // When the drag operation ends, reset drag-related state if (what == DragEvent.ACTION_DRAG_ENDED) { + mCurrentDragView = null; setLocalDragState(null); mAttachInfo.mDragToken = null; if (mAttachInfo.mDragSurface != null) { @@ -5630,10 +5643,33 @@ public final class ViewRootImpl implements ViewParent, return mLastTouchSource; } - public void setDragFocus(View newDragTarget) { - if (mCurrentDragView != newDragTarget) { - mCurrentDragView = newDragTarget; + public void setDragFocus(View newDragTarget, DragEvent event) { + if (mCurrentDragView != newDragTarget && !View.sCascadedDragDrop) { + // Send EXITED and ENTERED notifications to the old and new drag focus views. + + final float tx = event.mX; + final float ty = event.mY; + final int action = event.mAction; + // Position should not be available for ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED. + event.mX = 0; + event.mY = 0; + + if (mCurrentDragView != null) { + event.mAction = DragEvent.ACTION_DRAG_EXITED; + mCurrentDragView.callDragEventHandler(event); + } + + if (newDragTarget != null) { + event.mAction = DragEvent.ACTION_DRAG_ENTERED; + newDragTarget.callDragEventHandler(event); + } + + event.mAction = action; + event.mX = tx; + event.mY = ty; } + + mCurrentDragView = newDragTarget; } private AudioManager getAudioManager() { @@ -6044,7 +6080,8 @@ public final class ViewRootImpl implements ViewParent, return true; } return mEvent instanceof MotionEvent - && mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER); + && (mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER) + || mEvent.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)); } public boolean shouldSendToSynthesizer() { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index fe2423093c881e087aefb2c7b46e0a9cc06b4bfb..395f73844b0721d3447f4ec286920c66990815d3 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -221,6 +221,7 @@ public interface WindowManager extends ViewManager { * @see #TYPE_BASE_APPLICATION * @see #TYPE_APPLICATION * @see #TYPE_APPLICATION_STARTING + * @see #TYPE_DRAWN_APPLICATION * @see #TYPE_APPLICATION_PANEL * @see #TYPE_APPLICATION_MEDIA * @see #TYPE_APPLICATION_SUB_PANEL @@ -244,6 +245,7 @@ public interface WindowManager extends ViewManager { @ViewDebug.IntToString(from = TYPE_BASE_APPLICATION, to = "TYPE_BASE_APPLICATION"), @ViewDebug.IntToString(from = TYPE_APPLICATION, to = "TYPE_APPLICATION"), @ViewDebug.IntToString(from = TYPE_APPLICATION_STARTING, to = "TYPE_APPLICATION_STARTING"), + @ViewDebug.IntToString(from = TYPE_DRAWN_APPLICATION, to = "TYPE_DRAWN_APPLICATION"), @ViewDebug.IntToString(from = TYPE_APPLICATION_PANEL, to = "TYPE_APPLICATION_PANEL"), @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA, to = "TYPE_APPLICATION_MEDIA"), @ViewDebug.IntToString(from = TYPE_APPLICATION_SUB_PANEL, to = "TYPE_APPLICATION_SUB_PANEL"), @@ -314,6 +316,13 @@ public interface WindowManager extends ViewManager { */ public static final int TYPE_APPLICATION_STARTING = 3; + /** + * Window type: a variation on TYPE_APPLICATION that ensures the window + * manager will wait for this window to be drawn before the app is shown. + * In multiuser systems shows only on the owning user's window. + */ + public static final int TYPE_DRAWN_APPLICATION = 4; + /** * End of types of application windows. */ @@ -636,7 +645,7 @@ public interface WindowManager extends ViewManager { /** * Window type: shares similar characteristics with {@link #TYPE_DREAM}. The layer is - * reserved for screenshot region selection. + * reserved for screenshot region selection. These windows must not take input focus. * @hide */ public static final int TYPE_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36; @@ -1580,6 +1589,15 @@ public interface WindowManager extends ViewManager { */ public static final int ROTATION_ANIMATION_JUMPCUT = 2; + /** + * Value for {@link #rotationAnimation} to specify seamless rotation mode. + * This works like JUMPCUT but will fall back to CROSSFADE if rotation + * can't be applied without pausing the screen. + * + * @hide + */ + public static final int ROTATION_ANIMATION_SEAMLESS = 3; + /** * Define the exit and entry animations used on this window when the device is rotated. * This only has an affect if the incoming and outgoing topmost @@ -1734,14 +1752,18 @@ public interface WindowManager extends ViewManager { public CharSequence accessibilityTitle; /** - * Sets a timeout in milliseconds before which the window will be removed + * Sets a timeout in milliseconds before which the window will be hidden * by the window manager. Useful for transient notifications like toasts * so we don't have to rely on client cooperation to ensure the window - * is removed. Must be specified at window creation time. + * is hidden. Must be specified at window creation time. Note that apps + * are not prepared to handle their windows being removed without their + * explicit request and may try to interact with the removed window + * resulting in undefined behavior and crashes. Therefore, we do hide + * such windows to prevent them from overlaying other apps. * * @hide */ - public long removeTimeoutMilliseconds = -1; + public long hideTimeoutMilliseconds = -1; public LayoutParams() { super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); @@ -1877,7 +1899,7 @@ public interface WindowManager extends ViewManager { out.writeInt(needsMenuKey); out.writeInt(accessibilityIdOfAnchor); TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags); - out.writeLong(removeTimeoutMilliseconds); + out.writeLong(hideTimeoutMilliseconds); } public static final Parcelable.Creator CREATOR @@ -1931,7 +1953,7 @@ public interface WindowManager extends ViewManager { needsMenuKey = in.readInt(); accessibilityIdOfAnchor = in.readInt(); accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - removeTimeoutMilliseconds = in.readLong(); + hideTimeoutMilliseconds = in.readLong(); } @SuppressWarnings({"PointlessBitwiseExpression"}) @@ -2153,7 +2175,7 @@ public interface WindowManager extends ViewManager { } // This can't change, it's only set at window creation time. - removeTimeoutMilliseconds = o.removeTimeoutMilliseconds; + hideTimeoutMilliseconds = o.hideTimeoutMilliseconds; return changes; } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index e6f5b8386d492bc5a498752bfd40baffbd586496..46a0194b1b09e2c19ff32985429fa2431b6f8ccf 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -135,6 +135,12 @@ public interface WindowManagerPolicy { void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) throws RemoteException; + /** + * @return true if windows with FLAG_DISMISS_KEYGUARD should be allowed to show even if + * the keyguard is locked. + */ + boolean canShowDismissingWindowWhileLockedLw(); + /** * Interface to the Window Manager state associated with a particular * window. You can hold on to an instance of this interface from the call @@ -416,6 +422,8 @@ public interface WindowManagerPolicy { * screen with other application windows. */ public boolean isInMultiWindowMode(); + + public int getRotationAnimationHint(); } /** @@ -476,6 +484,7 @@ public interface WindowManagerPolicy { public void switchInputMethod(boolean forwardDirection); public void shutdown(boolean confirm); + public void reboot(boolean confirm); public void rebootSafeMode(boolean confirm); /** @@ -498,6 +507,11 @@ public interface WindowManagerPolicy { * Retrieves the {@param outBounds} from the stack with id {@param stackId}. */ void getStackBounds(int stackId, Rect outBounds); + + /** + * Overrides all currently playing app animations with {@param a}. + */ + void overridePlayingAppAnimationsLw(Animation a); } public interface PointerEventListener { @@ -1291,6 +1305,16 @@ public interface WindowManagerPolicy { */ public int adjustSystemUiVisibilityLw(int visibility); + /** + * Called by System UI to notify of changes to the visibility of Recents. + */ + public void setRecentsVisibilityLw(boolean visible); + + /** + * Called by System UI to notify of changes to the visibility of PIP. + */ + public void setTvPipVisibilityLw(boolean visible); + /** * Specifies whether there is an on-screen navigation bar separate from the status bar. */ @@ -1410,4 +1434,6 @@ public interface WindowManagerPolicy { * Called when the configuration has changed, and it's safe to load new values from resources. */ public void onConfigurationChanged(); + + public boolean shouldRotateSeamlessly(int oldRotation, int newRotation); } diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 81ec3306c4c740fad4f78958803d89ef08537c9f..2dfa8cdd3db9e6850286607f6aa67f1307575df3 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -305,7 +305,18 @@ public final class AccessibilityManager { return; } if (!mIsEnabled) { - throw new IllegalStateException("Accessibility off. Did you forget to check that?"); + Looper myLooper = Looper.myLooper(); + if (myLooper == Looper.getMainLooper()) { + throw new IllegalStateException( + "Accessibility off. Did you forget to check that?"); + } else { + // If we're not running on the thread with the main looper, it's possible for + // the state of accessibility to change between checking isEnabled and + // calling this method. So just log the error rather than throwing the + // exception. + Log.e(LOG_TAG, "AccessibilityEvent sent with accessibility disabled"); + return; + } } userId = mUserId; } diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java index a54d94c5c2e322fe9c156745083549b01b2792a1..351b6dbd66162ad595ddef1a1dc4a7c9676e1b4a 100644 --- a/core/java/android/view/animation/AnimationUtils.java +++ b/core/java/android/view/animation/AnimationUtils.java @@ -44,6 +44,31 @@ public class AnimationUtils { private static final int TOGETHER = 0; private static final int SEQUENTIALLY = 1; + private static class AnimationState { + boolean animationClockLocked; + long currentVsyncTimeMillis; + long lastReportedTimeMillis; + }; + + private static ThreadLocal sAnimationState + = new ThreadLocal() { + @Override + protected AnimationState initialValue() { + return new AnimationState(); + } + }; + + /** @hide */ + public static void lockAnimationClock(long vsyncMillis) { + AnimationState state = sAnimationState.get(); + state.animationClockLocked = true; + state.currentVsyncTimeMillis = vsyncMillis; + } + + /** @hide */ + public static void unlockAnimationClock() { + sAnimationState.get().animationClockLocked = false; + } /** * Returns the current animation time in milliseconds. This time should be used when invoking @@ -56,7 +81,14 @@ public class AnimationUtils { * @see android.os.SystemClock */ public static long currentAnimationTimeMillis() { - return SystemClock.uptimeMillis(); + AnimationState state = sAnimationState.get(); + if (state.animationClockLocked) { + // It's important that time never rewinds + return Math.max(state.currentVsyncTimeMillis, + state.lastReportedTimeMillis); + } + state.lastReportedTimeMillis = SystemClock.uptimeMillis(); + return state.lastReportedTimeMillis; } /** diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 89dec2d22d7a74abf37d0833d72643ed0ef1ac6e..38962a36dd701155d2d39241dd873d4758adbb8f 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -851,4 +851,11 @@ public class BaseInputConnection implements InputConnection { endBatchEdit(); } + + /** + * The default implementation does nothing. + */ + public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) { + return false; + } } diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index 7b7ccae62dede0f5b6ab07b82d80e6d6687b249b..80380897fd398a6057ea1c960d27fa5278d14e3f 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -25,6 +25,8 @@ import android.text.InputType; import android.text.TextUtils; import android.util.Printer; +import java.util.Arrays; + /** * An EditorInfo describes several attributes of a text editing object * that an input method is communicating with (typically an EditText), most @@ -363,6 +365,18 @@ public class EditorInfo implements InputType, Parcelable { @Nullable public LocaleList hintLocales = null; + + /** + * List of acceptable MIME types for + * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)}. + * + *

    {@code null} or an empty array means that + * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} is not supported in this + * editor.

    + */ + @Nullable + public String[] contentMimeTypes = null; + /** * Ensure that the data in this EditorInfo is compatible with an application * that was developed against the given target API version. This can @@ -418,6 +432,7 @@ public class EditorInfo implements InputType, Parcelable { + " fieldName=" + fieldName); pw.println(prefix + "extras=" + extras); pw.println(prefix + "hintLocales=" + hintLocales); + pw.println(prefix + "contentMimeTypes=" + Arrays.toString(contentMimeTypes)); } /** @@ -446,6 +461,7 @@ public class EditorInfo implements InputType, Parcelable { } else { LocaleList.getEmptyLocaleList().writeToParcel(dest, flags); } + dest.writeStringArray(contentMimeTypes); } /** @@ -471,6 +487,7 @@ public class EditorInfo implements InputType, Parcelable { res.extras = source.readBundle(); LocaleList hintLocales = LocaleList.CREATOR.createFromParcel(source); res.hintLocales = hintLocales.isEmpty() ? null : hintLocales; + res.contentMimeTypes = source.readStringArray(); return res; } diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index 9f664293476835b2eb8f6f54d0340deb1b3d092b..8023201bc284034231557b006bf2c463670fe441 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -16,6 +16,8 @@ package android.view.inputmethod; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Bundle; import android.os.Handler; import android.view.KeyCharacterMap; @@ -41,12 +43,14 @@ import android.view.KeyEvent; * in {@link android.os.Build.VERSION_CODES#HONEYCOMB}. *
  • {@link #requestCursorUpdates(int)}, which was introduced in * {@link android.os.Build.VERSION_CODES#LOLLIPOP}.
  • - *
  • {@link #deleteSurroundingTextInCodePoints(int, int)}}, which + *
  • {@link #deleteSurroundingTextInCodePoints(int, int)}, which * was introduced in {@link android.os.Build.VERSION_CODES#N}.
  • - *
  • {@link #getHandler()}}, which was introduced in + *
  • {@link #getHandler()}, which was introduced in * {@link android.os.Build.VERSION_CODES#N}.
  • - *
  • {@link #closeConnection()}}, which was introduced in + *
  • {@link #closeConnection()}, which was introduced in * {@link android.os.Build.VERSION_CODES#N}.
  • + *
  • {@link #commitContent(InputContentInfo, int, Bundle)}, which was + * introduced in {@link android.os.Build.VERSION_CODES#N_MR1}.
  • * * *

    Implementing an IME or an editor

    @@ -836,4 +840,53 @@ public interface InputConnection { *

    Note: This does nothing when called from input methods.

    */ public void closeConnection(); + + /** + * When this flag is used, the editor will be able to request read access to the content URI + * contained in the {@link InputContentInfo} object. + * + *

    Make sure that the content provider owning the Uri sets the + * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions + * grantUriPermissions} attribute in its manifest or included the + * {@link android.R.styleable#AndroidManifestGrantUriPermission + * <grant-uri-permissions>} tag. Otherwise {@link InputContentInfo#requestPermission()} + * can fail.

    + * + *

    Although calling this API is allowed only for the IME that is currently selected, the + * client is able to request a temporary read-only access even after the current IME is switched + * to any other IME as long as the client keeps {@link InputContentInfo} object.

    + **/ + public static int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = + android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; // 0x00000001 + + /** + * Called by the input method to commit a content such as PNG image to the editor. + * + *

    In order to avoid variety of compatibility issues, this focuses on a simple use case, + * where we expect editors and IMEs work cooperatively as follows:

    + *
      + *
    • Editor must keep {@link EditorInfo#contentMimeTypes} to be {@code null} if it does + * not support this method at all.
    • + *
    • Editor can ignore this request when the MIME type specified in + * {@code inputContentInfo} does not match to any of {@link EditorInfo#contentMimeTypes}. + *
    • + *
    • Editor can ignore the cursor position when inserting the provided context.
    • + *
    • Editor can return {@code true} asynchronously, even before it starts loading the + * content.
    • + *
    • Editor should provide a way to delete the content inserted by this method, or revert + * the effect caused by this method.
    • + *
    • IME should not call this method when there is any composing text, in case calling + * this method causes focus change.
    • + *
    • IME should grant a permission for the editor to read the content. See + * {@link EditorInfo#packageName} about how to obtain the package name of the editor.
    • + *
    + * + * @param inputContentInfo Content to be inserted. + * @param flags {@code 0} or {@link #INPUT_CONTENT_GRANT_READ_URI_PERMISSION}. + * @param opts optional bundle data. This can be {@code null}. + * @return {@code true} if this request is accepted by the application, no matter if the request + * is already handled or still being handled in background. + */ + public boolean commitContent(@NonNull InputContentInfo inputContentInfo, int flags, + @Nullable Bundle opts); } diff --git a/core/java/android/view/inputmethod/InputConnectionInspector.java b/core/java/android/view/inputmethod/InputConnectionInspector.java index 118a61f8d571c3d447b694971144bffd5dcd6d85..2b292bbca84993c269c455379208365224b0bbbf 100644 --- a/core/java/android/view/inputmethod/InputConnectionInspector.java +++ b/core/java/android/view/inputmethod/InputConnectionInspector.java @@ -19,6 +19,7 @@ package android.view.inputmethod; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.os.Bundle; import java.lang.annotation.Retention; import java.lang.reflect.Method; @@ -41,6 +42,8 @@ public final class InputConnectionInspector { MissingMethodFlags.REQUEST_CURSOR_UPDATES, MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS, MissingMethodFlags.GET_HANDLER, + MissingMethodFlags.CLOSE_CONNECTION, + MissingMethodFlags.COMMIT_CONTENT, }) public @interface MissingMethodFlags { /** @@ -78,6 +81,11 @@ public final class InputConnectionInspector { * {@link android.os.Build.VERSION_CODES#N} and later. */ int CLOSE_CONNECTION = 1 << 6; + /** + * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} is available in + * {@link android.os.Build.VERSION_CODES#N} MR-1 and later. + */ + int COMMIT_CONTENT = 1 << 7; } private static final Map sMissingMethodsMap = Collections.synchronizedMap( @@ -127,6 +135,9 @@ public final class InputConnectionInspector { if (!hasCloseConnection(clazz)) { flags |= MissingMethodFlags.CLOSE_CONNECTION; } + if (!hasCommitContent(clazz)) { + flags |= MissingMethodFlags.COMMIT_CONTENT; + } sMissingMethodsMap.put(clazz, flags); return flags; } @@ -195,6 +206,16 @@ public final class InputConnectionInspector { } } + private static boolean hasCommitContent(@NonNull final Class clazz) { + try { + final Method method = clazz.getMethod("commitContent", InputContentInfo.class, + int.class, Bundle.class); + return !Modifier.isAbstract(method.getModifiers()); + } catch (NoSuchMethodException e) { + return false; + } + } + public static String getMissingMethodFlagsAsString(@MissingMethodFlags final int flags) { final StringBuilder sb = new StringBuilder(); boolean isEmpty = true; @@ -242,6 +263,12 @@ public final class InputConnectionInspector { } sb.append("closeConnection()"); } + if ((flags & MissingMethodFlags.COMMIT_CONTENT) != 0) { + if (!isEmpty) { + sb.append(","); + } + sb.append("commitContent(InputContentInfo, Bundle)"); + } return sb.toString(); } } diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java index e743f62a5a0a6df97288951d4acdc5e6e1d7f51b..317730ca092c6752bef971b15e2f97d52b0cd4b8 100644 --- a/core/java/android/view/inputmethod/InputConnectionWrapper.java +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -269,4 +269,12 @@ public class InputConnectionWrapper implements InputConnection { public void closeConnection() { mTarget.closeConnection(); } + + /** + * {@inheritDoc} + * @throws NullPointerException if the target is {@code null}. + */ + public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) { + return mTarget.commitContent(inputContentInfo, flags, opts); + } } diff --git a/core/java/android/view/inputmethod/InputContentInfo.aidl b/core/java/android/view/inputmethod/InputContentInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1afeee3b4b245692e760e38229966456dddae54d --- /dev/null +++ b/core/java/android/view/inputmethod/InputContentInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.inputmethod; + +parcelable InputContentInfo; diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..b39705e0b1fa686b1d6ceabc3ee9a1e10a5e27df --- /dev/null +++ b/core/java/android/view/inputmethod/InputContentInfo.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package android.view.inputmethod; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.ClipDescription; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.RemoteException; + +import com.android.internal.inputmethod.IInputContentUriToken; + +import java.security.InvalidParameterException; + +/** + * A container object with which input methods can send content files to the target application. + */ +public final class InputContentInfo implements Parcelable { + + @NonNull + private final Uri mContentUri; + @NonNull + private final ClipDescription mDescription; + @Nullable + private final Uri mLinkUri; + @NonNull + private IInputContentUriToken mUriToken; + + /** + * Constructs {@link InputContentInfo} object only with mandatory data. + * + * @param contentUri Content URI to be exported from the input method. + * This cannot be {@code null}. + * @param description A {@link ClipDescription} object that contains the metadata of + * {@code contentUri} such as MIME type(s). This object cannot be {@code null}. Also + * {@link ClipDescription#getLabel()} should be describing the content specified by + * {@code contentUri} for accessibility reasons. + */ + public InputContentInfo(@NonNull Uri contentUri, @NonNull ClipDescription description) { + this(contentUri, description, null /* link Uri */); + } + + /** + * Constructs {@link InputContentInfo} object with additional link URI. + * + * @param contentUri Content URI to be exported from the input method. + * This cannot be {@code null}. + * @param description A {@link ClipDescription} object that contains the metadata of + * {@code contentUri} such as MIME type(s). This object cannot be {@code null}. Also + * {@link ClipDescription#getLabel()} should be describing the content specified by + * {@code contentUri} for accessibility reasons. + * @param linkUri An optional {@code http} or {@code https} URI. The editor author may provide + * a way to navigate the user to the specified web page if this is not {@code null}. + * @throws InvalidParameterException if any invalid parameter is specified. + */ + public InputContentInfo(@NonNull Uri contentUri, @NonNull ClipDescription description, + @Nullable Uri linkUri) { + validateInternal(contentUri, description, linkUri, true /* throwException */); + mContentUri = contentUri; + mDescription = description; + mLinkUri = linkUri; + } + + /** + * @return {@code true} if all the fields are valid. + * @hide + */ + public boolean validate() { + return validateInternal(mContentUri, mDescription, mLinkUri, false /* throwException */); + } + + /** + * Constructs {@link InputContentInfo} object with additional link URI. + * + * @param contentUri Content URI to be exported from the input method. + * This cannot be {@code null}. + * @param description A {@link ClipDescription} object that contains the metadata of + * {@code contentUri} such as MIME type(s). This object cannot be {@code null}. Also + * {@link ClipDescription#getLabel()} should be describing the content specified by + * {@code contentUri} for accessibility reasons. + * @param linkUri An optional {@code http} or {@code https} URI. The editor author may provide + * a way to navigate the user to the specified web page if this is not {@code null}. + * @param throwException {@code true} if this method should throw an + * {@link InvalidParameterException}. + * @throws InvalidParameterException if any invalid parameter is specified. + */ + private static boolean validateInternal(@NonNull Uri contentUri, + @NonNull ClipDescription description, @Nullable Uri linkUri, boolean throwException) { + if (contentUri == null) { + if (throwException) { + throw new NullPointerException("contentUri"); + } + return false; + } + if (description == null) { + if (throwException) { + throw new NullPointerException("description"); + } + return false; + } + final String contentUriScheme = contentUri.getScheme(); + if (!"content".equals(contentUriScheme)) { + if (throwException) { + throw new InvalidParameterException("contentUri must have content scheme"); + } + return false; + } + if (linkUri != null) { + final String scheme = linkUri.getScheme(); + if (scheme == null || + (!scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https"))) { + if (throwException) { + throw new InvalidParameterException( + "linkUri must have either http or https scheme"); + } + return false; + } + } + return true; + } + + /** + * @return Content URI with which the content can be obtained. + */ + @NonNull + public Uri getContentUri() { return mContentUri; } + + /** + * @return {@link ClipDescription} object that contains the metadata of {@code #getContentUri()} + * such as MIME type(s). {@link ClipDescription#getLabel()} can be used for accessibility + * purpose. + */ + @NonNull + public ClipDescription getDescription() { return mDescription; } + + /** + * @return An optional {@code http} or {@code https} URI that is related to this content. + */ + @Nullable + public Uri getLinkUri() { return mLinkUri; } + + void setUriToken(IInputContentUriToken token) { + if (mUriToken != null) { + throw new IllegalStateException("URI token is already set"); + } + mUriToken = token; + } + + /** + * Requests a temporary read-only access permission for content URI associated with this object. + * + *

    Does nothing if the temporary permission is already granted.

    + */ + public void requestPermission() { + if (mUriToken == null) { + return; + } + try { + mUriToken.take(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Releases a temporary read-only access permission for content URI associated with this object. + * + *

    Does nothing if the temporary permission is not granted.

    + */ + public void releasePermission() { + if (mUriToken == null) { + return; + } + try { + mUriToken.release(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Used to package this object into a {@link Parcel}. + * + * @param dest The {@link Parcel} to be written. + * @param flags The flags used for parceling. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + Uri.writeToParcel(dest, mContentUri); + mDescription.writeToParcel(dest, flags); + Uri.writeToParcel(dest, mLinkUri); + if (mUriToken != null) { + dest.writeInt(1); + dest.writeStrongBinder(mUriToken.asBinder()); + } else { + dest.writeInt(0); + } + } + + private InputContentInfo(@NonNull Parcel source) { + mContentUri = Uri.CREATOR.createFromParcel(source); + mDescription = ClipDescription.CREATOR.createFromParcel(source); + mLinkUri = Uri.CREATOR.createFromParcel(source); + if (source.readInt() == 1) { + mUriToken = IInputContentUriToken.Stub.asInterface(source.readStrongBinder()); + } else { + mUriToken = null; + } + } + + /** + * Used to make this class parcelable. + */ + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + @Override + public InputContentInfo createFromParcel(Parcel source) { + return new InputContentInfo(source); + } + + @Override + public InputContentInfo[] newArray(int size) { + return new InputContentInfo[size]; + } + }; + + /** + * {@inheritDoc} + */ + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 0b7ac88c6925eb167999f69381288c276b0ec703..2e9cbf20607bcd5a9b4db4ec74c07cd333aaf6b4 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -16,6 +16,7 @@ package android.view.inputmethod; +import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.os.SomeArgs; import com.android.internal.view.IInputConnectionWrapper; import com.android.internal.view.IInputContext; @@ -30,6 +31,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.content.Context; import android.graphics.Rect; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -56,6 +58,7 @@ import android.view.ViewRootImpl; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -2286,6 +2289,40 @@ public final class InputMethodManager { } } + /** + * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access + * permission to the content. + * + *

    See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo, EditorInfo)} + * for details.

    + * + * @param token Supplies the identifying token given to an input method when it was started, + * which allows it to perform this operation on itself. + * @param inputContentInfo Content to be temporarily exposed from the input method to the + * application. + * This cannot be {@code null}. + * @param editorInfo The editor that receives {@link InputContentInfo}. + * @hide + */ + public void exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo, + @NonNull EditorInfo editorInfo) { + final IInputContentUriToken uriToken; + final Uri contentUri = inputContentInfo.getContentUri(); + try { + uriToken = mService.createInputContentUriToken(token, contentUri, + editorInfo.packageName); + if (uriToken == null) { + return; + } + } catch (RemoteException e) { + Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString() + + " packageName=" + editorInfo.packageName, e); + return; + } + inputContentInfo.setUriToken(uriToken); + return; + } + void doDump(FileDescriptor fd, PrintWriter fout, String[] args) { final Printer p = new PrintWriterPrinter(fout); p.println("Input method client state for " + this + ":"); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index b331be72b4cf128899bd69038f9fc630313c02d8..f1bfadee5f36f14ba8a075b896b8c72e4ff79d61 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -21,6 +21,7 @@ import android.annotation.DrawableRes; import android.annotation.NonNull; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; @@ -75,6 +76,7 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputContentInfo; import android.view.inputmethod.InputMethodManager; import android.widget.RemoteViews.OnClickHandler; @@ -615,6 +617,8 @@ public abstract class AbsListView extends AdapterView implements Te private int mTouchSlop; private float mDensityScale; + private float mScrollFactor; + private InputConnection mDefInputConnection; private InputConnectionWrapper mPublicInputConnection; @@ -856,6 +860,10 @@ public abstract class AbsListView extends AdapterView implements Te R.styleable.AbsListView_fastScrollAlwaysVisible, false)); a.recycle(); + + if (context.getResources().getConfiguration().uiMode == Configuration.UI_MODE_TYPE_WATCH) { + setRevealOnFocusHint(false); + } } private void initAbsListView() { @@ -868,6 +876,7 @@ public abstract class AbsListView extends AdapterView implements Te final ViewConfiguration configuration = ViewConfiguration.get(mContext); mTouchSlop = configuration.getScaledTouchSlop(); + mScrollFactor = configuration.getScaledScrollFactor(); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); @@ -1545,7 +1554,7 @@ public abstract class AbsListView extends AdapterView implements Te switch (action) { case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: case R.id.accessibilityActionScrollDown: { - if (isEnabled() && getLastVisiblePosition() < getCount() - 1) { + if (isEnabled() && canScrollDown()) { final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom; smoothScrollBy(viewportHeight, PositionScroller.SCROLL_DURATION); return true; @@ -1553,7 +1562,7 @@ public abstract class AbsListView extends AdapterView implements Te } return false; case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: case R.id.accessibilityActionScrollUp: { - if (isEnabled() && mFirstPosition > 0) { + if (isEnabled() && canScrollUp()) { final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom; smoothScrollBy(-viewportHeight, PositionScroller.SCROLL_DURATION); return true; @@ -2315,22 +2324,24 @@ public abstract class AbsListView extends AdapterView implements Te } /** - * Get a view and have it show the data associated with the specified - * position. This is called when we have already discovered that the view is - * not available for reuse in the recycle bin. The only choices left are + * Gets a view and have it show the data associated with the specified + * position. This is called when we have already discovered that the view + * is not available for reuse in the recycle bin. The only choices left are * converting an old view or making a new one. * - * @param position The position to display - * @param isScrap Array of at least 1 boolean, the first entry will become true if - * the returned view was taken from the "temporary detached" scrap heap, false if - * otherwise. + * @param position the position to display + * @param outMetadata an array of at least 1 boolean where the first entry + * will be set {@code true} if the view is currently + * attached to the window, {@code false} otherwise (e.g. + * newly-inflated or remained scrap for multiple layout + * passes) * * @return A view displaying the data associated with the specified position */ - View obtainView(int position, boolean[] isScrap) { + View obtainView(int position, boolean[] outMetadata) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView"); - isScrap[0] = false; + outMetadata[0] = false; // Check whether we have a transient state view. Attempt to re-bind the // data and discard the view if we fail. @@ -2349,7 +2360,7 @@ public abstract class AbsListView extends AdapterView implements Te } } - isScrap[0] = true; + outMetadata[0] = true; // Finish the temporary detach started in addScrapView(). transientView.dispatchFinishTemporaryDetach(); @@ -2362,19 +2373,11 @@ public abstract class AbsListView extends AdapterView implements Te if (child != scrapView) { // Failed to re-bind the data, return scrap to the heap. mRecycler.addScrapView(scrapView, position); - } else { - if (child.isTemporarilyDetached()) { - isScrap[0] = true; - - // Finish the temporary detach started in addScrapView(). - child.dispatchFinishTemporaryDetach(); - } else { - // we set isScrap to "true" only if the view is temporarily detached. - // if the view is fully detached, it is as good as a view created by the - // adapter - isScrap[0] = false; - } + } else if (child.isTemporarilyDetached()) { + outMetadata[0] = true; + // Finish the temporary detach started in addScrapView(). + child.dispatchFinishTemporaryDetach(); } } @@ -4206,21 +4209,26 @@ public abstract class AbsListView extends AdapterView implements Te @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: - if (mTouchMode == TOUCH_MODE_REST) { - final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - if (vscroll != 0) { - final int delta = (int) (vscroll * getVerticalScrollFactor()); - if (!trackMotionScroll(delta, delta)) { - return true; - } - } - } - break; + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: + final float axisValue; + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_VSCROLL); + } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL); + } else { + axisValue = 0; + } - case MotionEvent.ACTION_BUTTON_PRESS: + final int delta = Math.round(axisValue * mScrollFactor); + if (delta != 0) { + if (!trackMotionScroll(delta, delta)) { + return true; + } + } + break; + case MotionEvent.ACTION_BUTTON_PRESS: + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { int actionButton = event.getActionButton(); if ((actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY || actionButton == MotionEvent.BUTTON_SECONDARY) @@ -4230,8 +4238,8 @@ public abstract class AbsListView extends AdapterView implements Te removeCallbacks(mPendingCheckForTap); } } - break; - } + } + break; } return super.onGenericMotionEvent(event); @@ -5982,6 +5990,11 @@ public abstract class AbsListView extends AdapterView implements Te public void closeConnection() { getTarget().closeConnection(); } + + @Override + public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) { + return getTarget().commitContent(inputContentInfo, flags, opts); + } } /** diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index 8613f9989abcc76d9837899a51f43aab854df4e2..54818a1f7a6ccdc554e8052ab21092f74bf15453 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -18,7 +18,9 @@ package android.widget; import com.android.internal.R; +import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.TestApi; import android.annotation.Widget; import android.content.Context; import android.content.res.Configuration; @@ -32,6 +34,8 @@ import android.util.SparseArray; import android.view.View; import android.view.accessibility.AccessibilityEvent; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Locale; /** @@ -75,11 +79,36 @@ import java.util.Locale; */ @Widget public class DatePicker extends FrameLayout { - private static final int MODE_SPINNER = 1; - private static final int MODE_CALENDAR = 2; + /** + * Presentation mode for the Holo-style date picker that uses a set of + * {@link android.widget.NumberPicker}s. + * + * @see #getMode() + * @hide Visible for testing only. + */ + @TestApi + public static final int MODE_SPINNER = 1; + + /** + * Presentation mode for the Material-style date picker that uses a + * calendar. + * + * @see #getMode() + * @hide Visible for testing only. + */ + @TestApi + public static final int MODE_CALENDAR = 2; + + /** @hide */ + @IntDef({MODE_SPINNER, MODE_CALENDAR}) + @Retention(RetentionPolicy.SOURCE) + public @interface DatePickerMode {} private final DatePickerDelegate mDelegate; + @DatePickerMode + private final int mMode; + /** * The callback used to indicate the user changed the date. */ @@ -114,11 +143,20 @@ public class DatePicker extends FrameLayout { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, defStyleAttr, defStyleRes); - final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER); + final boolean isDialogMode = a.getBoolean(R.styleable.DatePicker_dialogMode, false); + final int requestedMode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER); final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0); a.recycle(); - switch (mode) { + if (requestedMode == MODE_CALENDAR && isDialogMode) { + // You want MODE_CALENDAR? YOU CAN'T HANDLE MODE_CALENDAR! Well, + // maybe you can depending on your screen size. Let's check... + mMode = context.getResources().getInteger(R.integer.date_picker_mode); + } else { + mMode = requestedMode; + } + + switch (mMode) { case MODE_CALENDAR: mDelegate = createCalendarUIDelegate(context, attrs, defStyleAttr, defStyleRes); break; @@ -144,6 +182,18 @@ public class DatePicker extends FrameLayout { defStyleRes); } + /** + * @return the picker's presentation mode, one of {@link #MODE_CALENDAR} or + * {@link #MODE_SPINNER} + * @attr ref android.R.styleable#DatePicker_datePickerMode + * @hide Visible for testing only. + */ + @DatePickerMode + @TestApi + public int getMode() { + return mMode; + } + /** * Initialize the state. If the provided values designate an inconsistent * date the values are normalized before updating the spinners. diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java index 2fd52b5f1230a360a5c218502a34360649de7a08..af22ec7bc755f37942833acb62f8202ee52f69d3 100755 --- a/core/java/android/widget/DatePickerCalendarDelegate.java +++ b/core/java/android/widget/DatePickerCalendarDelegate.java @@ -65,6 +65,8 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { private SimpleDateFormat mYearFormat; private SimpleDateFormat mMonthDayFormat; + private SimpleDateFormat mAccessibilityEventFormat; + // Top-level container. private ViewGroup mContainer; @@ -307,6 +309,9 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { mMonthDayFormat.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE); mYearFormat = new SimpleDateFormat("y", locale); + // Clear out the lazily-initialized accessibility event formatter. + mAccessibilityEventFormat = null; + // Update the header text. onCurrentDateChanged(false); } @@ -586,7 +591,12 @@ class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate { @Override public void onPopulateAccessibilityEvent(AccessibilityEvent event) { - event.getText().add(mCurrentDate.getTime().toString()); + if (mAccessibilityEventFormat == null) { + final String pattern = DateFormat.getBestDateTimePattern(mCurrentLocale, "EMMMMdy"); + mAccessibilityEventFormat = new SimpleDateFormat(pattern); + } + final CharSequence text = mAccessibilityEventFormat.format(mCurrentDate.getTime()); + event.getText().add(text); } public CharSequence getAccessibilityClassName() { diff --git a/core/java/android/widget/ForwardingListener.java b/core/java/android/widget/ForwardingListener.java index b383e1c55aada780f40b6d9d45de0b5801d0b599..a5fcbc7934122abff7b76148c88f31f35199747a 100644 --- a/core/java/android/widget/ForwardingListener.java +++ b/core/java/android/widget/ForwardingListener.java @@ -58,13 +58,14 @@ public abstract class ForwardingListener public ForwardingListener(View src) { mSrc = src; + src.setLongClickable(true); + src.addOnAttachStateChangeListener(this); + mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop(); mTapTimeout = ViewConfiguration.getTapTimeout(); // Use a medium-press timeout. Halfway between tap and long-press. mLongPressTimeout = (mTapTimeout + ViewConfiguration.getLongPressTimeout()) / 2; - - src.addOnAttachStateChangeListener(this); } /** diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 029313c539389a878364a70f90d3508684ebc583..b8c74d88b58079a14d990b3bd97e0b594c37eb9f 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -382,13 +382,14 @@ public class FrameLayout extends ViewGroup { @Override protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { - if (lp instanceof LayoutParams) { - return new LayoutParams((LayoutParams) lp); - } else if (lp instanceof MarginLayoutParams) { - return new LayoutParams((MarginLayoutParams) lp); - } else { - return new LayoutParams(lp); + if (sPreserveMarginParamsInLayoutParamConversion) { + if (lp instanceof LayoutParams) { + return new LayoutParams((LayoutParams) lp); + } else if (lp instanceof MarginLayoutParams) { + return new LayoutParams((MarginLayoutParams) lp); + } } + return new LayoutParams(lp); } @Override diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index 726586ee8d5f305fcbc6610ff2958048dfd8298a..af2852cde22a124e87d3dea28a60325072717908 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -868,13 +868,14 @@ public class GridLayout extends ViewGroup { @Override protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { - if (lp instanceof LayoutParams) { - return new LayoutParams((LayoutParams) lp); - } else if (lp instanceof MarginLayoutParams) { - return new LayoutParams((MarginLayoutParams) lp); - } else { - return new LayoutParams(lp); + if (sPreserveMarginParamsInLayoutParamConversion) { + if (lp instanceof LayoutParams) { + return new LayoutParams((LayoutParams) lp); + } else if (lp instanceof MarginLayoutParams) { + return new LayoutParams((MarginLayoutParams) lp); + } } + return new LayoutParams(lp); } // Draw grid diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index 6d7313da00438154986a9f9f0b9eb921f42c6ce0..b95aa52c11e985c330f78b8ace9279549c7c4d51 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -1407,72 +1407,73 @@ public class GridView extends AbsListView { /** - * Obtain the view and add it to our list of children. The view can be made - * fresh, converted from an unused view, or used as is if it was in the - * recycle bin. + * Obtains the view and adds it to our list of children. The view can be + * made fresh, converted from an unused view, or used as is if it was in + * the recycle bin. * - * @param position Logical position in the list - * @param y Top or bottom edge of the view to add - * @param flow if true, align top edge to y. If false, align bottom edge to - * y. - * @param childrenLeft Left edge where children should be positioned - * @param selected Is this position selected? - * @param where to add new item in the list + * @param position logical position in the list + * @param y top or bottom edge of the view to add + * @param flow {@code true} to align top edge to y, {@code false} to align + * bottom edge to y + * @param childrenLeft left edge where children should be positioned + * @param selected {@code true} if the position is selected, {@code false} + * otherwise + * @param where position at which to add new item in the list * @return View that was added */ private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, boolean selected, int where) { - View child; - if (!mDataChanged) { // Try to use an existing view for this position - child = mRecycler.getActiveView(position); - if (child != null) { + final View activeView = mRecycler.getActiveView(position); + if (activeView != null) { // Found it -- we're using an existing child // This just needs to be positioned - setupChild(child, position, y, flow, childrenLeft, selected, true, where); - return child; + setupChild(activeView, position, y, flow, childrenLeft, selected, true, where); + return activeView; } } // Make a new view for this position, or convert an unused view if - // possible - child = obtainView(position, mIsScrap); + // possible. + final View child = obtainView(position, mIsScrap); - // This needs to be positioned and measured + // This needs to be positioned and measured. setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0], where); return child; } /** - * Add a view as a child and make sure it is measured (if necessary) and + * Adds a view as a child and make sure it is measured (if necessary) and * positioned properly. * - * @param child The view to add - * @param position The position of the view - * @param y The y position relative to which this view will be positioned - * @param flow if true, align top edge to y. If false, align bottom edge - * to y. - * @param childrenLeft Left edge where children should be positioned - * @param selected Is this position selected? - * @param recycled Has this view been pulled from the recycle bin? If so it - * does not need to be remeasured. - * @param where Where to add the item in the list + * @param child the view to add + * @param position the position of this child + * @param y the y position relative to which this view will be positioned + * @param flowDown {@code true} to align top edge to y, {@code false} to + * align bottom edge to y + * @param childrenLeft left edge where children should be positioned + * @param selected {@code true} if the position is selected, {@code false} + * otherwise + * @param isAttachedToWindow {@code true} if the view is already attached + * to the window, e.g. whether it was reused, or + * {@code false} otherwise + * @param where position at which to add new item in the list * */ - private void setupChild(View child, int position, int y, boolean flow, int childrenLeft, - boolean selected, boolean recycled, int where) { + private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft, + boolean selected, boolean isAttachedToWindow, int where) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "setupGridItem"); boolean isSelected = selected && shouldShowSelector(); final boolean updateChildSelected = isSelected != child.isSelected(); final int mode = mTouchMode; - final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL && - mMotionPosition == position; + final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL + && mMotionPosition == position; final boolean updateChildPressed = isPressed != child.isPressed(); - - boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested(); + final boolean needToMeasure = !isAttachedToWindow || updateChildSelected + || child.isLayoutRequested(); // Respect layout params that are already in the view. Otherwise make // some up... @@ -1483,13 +1484,9 @@ public class GridView extends AbsListView { p.viewType = mAdapter.getItemViewType(position); p.isEnabled = mAdapter.isEnabled(position); - if (recycled && !p.forceAdd) { - attachViewToParent(child, where, p); - } else { - p.forceAdd = false; - addViewInLayout(child, where, p, true); - } - + // Set up view state before attaching the view, since we may need to + // rely on the jumpDrawablesToCurrentState() call that occurs as part + // of view attachment. if (updateChildSelected) { child.setSelected(isSelected); if (isSelected) { @@ -1510,6 +1507,21 @@ public class GridView extends AbsListView { } } + if (isAttachedToWindow && !p.forceAdd) { + attachViewToParent(child, where, p); + + // If the view isn't attached, or if it's attached but for a different + // position, then jump the drawables. + if (!isAttachedToWindow + || (((AbsListView.LayoutParams) child.getLayoutParams()).scrappedFromPosition) + != position) { + child.jumpDrawablesToCurrentState(); + } + } else { + p.forceAdd = false; + addViewInLayout(child, where, p, true); + } + if (needToMeasure) { int childHeightSpec = ViewGroup.getChildMeasureSpec( MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height); @@ -1525,7 +1537,7 @@ public class GridView extends AbsListView { final int h = child.getMeasuredHeight(); int childLeft; - final int childTop = flow ? y : y - h; + final int childTop = flowDown ? y : y - h; final int layoutDirection = getLayoutDirection(); final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection); @@ -1553,15 +1565,10 @@ public class GridView extends AbsListView { child.offsetTopAndBottom(childTop - child.getTop()); } - if (mCachingStarted) { + if (mCachingStarted && !child.isDrawingCacheEnabled()) { child.setDrawingCacheEnabled(true); } - if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition) - != position) { - child.jumpDrawablesToCurrentState(); - } - Trace.traceEnd(Trace.TRACE_TAG_VIEW); } diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 00f368e3abe313ede051f8c053f7fd8eeec67a2f..918b6c0d65ff588dfd5dd3f3acc7263684e955a7 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -18,6 +18,7 @@ package android.widget; import android.annotation.NonNull; import android.content.Context; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; @@ -128,6 +129,8 @@ public class HorizontalScrollView extends FrameLayout { private int mOverscrollDistance; private int mOverflingDistance; + private float mScrollFactor; + /** * ID of the active pointer. This is used to retain consistency during * drags/flings if multiple pointers are used. @@ -165,6 +168,10 @@ public class HorizontalScrollView extends FrameLayout { setFillViewport(a.getBoolean(android.R.styleable.HorizontalScrollView_fillViewport, false)); a.recycle(); + + if (context.getResources().getConfiguration().uiMode == Configuration.UI_MODE_TYPE_WATCH) { + setRevealOnFocusHint(false); + } } @Override @@ -217,6 +224,7 @@ public class HorizontalScrollView extends FrameLayout { mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); mOverflingDistance = configuration.getScaledOverflingDistance(); + mScrollFactor = configuration.getScaledScrollFactor(); } @Override @@ -719,30 +727,35 @@ public class HorizontalScrollView extends FrameLayout { @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: { - if (!mIsBeingDragged) { - final float hscroll; + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: { + if (!mIsBeingDragged) { + final float axisValue; + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) { - hscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL); + axisValue = -event.getAxisValue(MotionEvent.AXIS_VSCROLL); } else { - hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL); + axisValue = event.getAxisValue(MotionEvent.AXIS_HSCROLL); } - if (hscroll != 0) { - final int delta = (int) (hscroll * getHorizontalScrollFactor()); - final int range = getScrollRange(); - int oldScrollX = mScrollX; - int newScrollX = oldScrollX + delta; - if (newScrollX < 0) { - newScrollX = 0; - } else if (newScrollX > range) { - newScrollX = range; - } - if (newScrollX != oldScrollX) { - super.scrollTo(newScrollX, mScrollY); - return true; - } + } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL); + } else { + axisValue = 0; + } + + final int delta = Math.round(axisValue * mScrollFactor); + if (delta != 0) { + final int range = getScrollRange(); + int oldScrollX = mScrollX; + int newScrollX = oldScrollX + delta; + if (newScrollX < 0) { + newScrollX = 0; + } else if (newScrollX > range) { + newScrollX = range; + } + if (newScrollX != oldScrollX) { + super.scrollTo(newScrollX, mScrollY); + return true; } } } @@ -1430,11 +1443,13 @@ public class HorizontalScrollView extends FrameLayout { @Override public void requestChildFocus(View child, View focused) { - if (!mIsLayoutDirty) { - scrollToChild(focused); - } else { - // The child may not be laid out yet, we can't compute the scroll yet - mChildToScrollTo = focused; + if (focused.getRevealOnFocusHint()) { + if (!mIsLayoutDirty) { + scrollToChild(focused); + } else { + // The child may not be laid out yet, we can't compute the scroll yet + mChildToScrollTo = focused; + } } super.requestChildFocus(child, focused); } diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index 222a040d2b3caf2cddbc888aa584370af70004ba..4d405c5a86276762c4c84ab48570828d90d41d07 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -22,7 +22,6 @@ import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.content.res.ColorStateList; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -115,11 +114,17 @@ public class ImageView extends View { private int mBaseline = -1; private boolean mBaselineAlignBottom = false; - // AdjustViewBounds behavior will be in compatibility mode for older apps. - private boolean mAdjustViewBoundsCompat = false; + /** Compatibility modes dependent on targetSdkVersion of the app. */ + private static boolean sCompatDone; + + /** AdjustViewBounds behavior will be in compatibility mode for older apps. */ + private static boolean sCompatAdjustViewBounds; /** Whether to pass Resources when creating the source from a stream. */ - private boolean mUseCorrectStreamDensity; + private static boolean sCompatUseCorrectStreamDensity; + + /** Whether to use pre-Nougat drawable visibility dispatching conditions. */ + private static boolean sCompatDrawableVisibilityDispatch; private static final ScaleType[] sScaleTypeArray = { ScaleType.MATRIX, @@ -206,9 +211,13 @@ public class ImageView extends View { mMatrix = new Matrix(); mScaleType = ScaleType.FIT_CENTER; - final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; - mAdjustViewBoundsCompat = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1; - mUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M; + if (!sCompatDone) { + final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; + sCompatAdjustViewBounds = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1; + sCompatUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M; + sCompatDrawableVisibilityDispatch = targetSdkVersion < Build.VERSION_CODES.N; + sCompatDone = true; + } } @Override @@ -458,6 +467,14 @@ public class ImageView extends View { * {@link #setImageBitmap(android.graphics.Bitmap)} and * {@link android.graphics.BitmapFactory} instead.

    * + *

    On devices running SDK < 24, this method will fail to + * apply correct density scaling to images loaded from + * {@link ContentResolver#SCHEME_CONTENT content} and + * {@link ContentResolver#SCHEME_FILE file} schemes. Applications running + * on devices with SDK >= 24 MUST specify the + * {@code targetSdkVersion} in their manifest as 24 or above for density + * scaling to be applied to images loaded from these schemes.

    + * * @param uri the Uri of an image, or {@code null} to clear the content */ @android.view.RemotableViewMethod(asyncImpl="setImageURIAsync") @@ -545,6 +562,13 @@ public class ImageView extends View { * Subsequent calls to {@link #setImageDrawable(Drawable)} will automatically * mutate the drawable and apply the specified tint and tint mode using * {@link Drawable#setTintList(ColorStateList)}. + *

    + * Note: The default tint mode used by this setter is NOT + * consistent with the default tint mode used by the + * {@link android.R.styleable#ImageView_tint android:tint} + * attribute. If the {@code android:tint} attribute is specified, the + * default tint mode will be set to {@link PorterDuff.Mode#SRC_ATOP} to + * ensure consistency with earlier versions of the platform. * * @param tint the tint to apply, may be {@code null} to clear tint * @@ -874,8 +898,8 @@ public class ImageView extends View { InputStream stream = null; try { stream = mContext.getContentResolver().openInputStream(uri); - return Drawable.createFromResourceStream( - mUseCorrectStreamDensity ? getResources() : null, null, stream, null); + return Drawable.createFromResourceStream(sCompatUseCorrectStreamDensity + ? getResources() : null, null, stream, null); } catch (Exception e) { Log.w(LOG_TAG, "Unable to open content: " + uri, e); } finally { @@ -910,10 +934,13 @@ public class ImageView extends View { mRecycleableBitmapDrawable.setBitmap(null); } + boolean sameDrawable = false; + if (mDrawable != null) { + sameDrawable = mDrawable == d; mDrawable.setCallback(null); unscheduleDrawable(mDrawable); - if (isAttachedToWindow()) { + if (!sCompatDrawableVisibilityDispatch && !sameDrawable && isAttachedToWindow()) { mDrawable.setVisible(false, false); } } @@ -926,8 +953,11 @@ public class ImageView extends View { if (d.isStateful()) { d.setState(getDrawableState()); } - if (isAttachedToWindow()) { - d.setVisible(getWindowVisibility() == VISIBLE && isShown(), true); + if (!sameDrawable || sCompatDrawableVisibilityDispatch) { + final boolean visible = sCompatDrawableVisibilityDispatch + ? getVisibility() == VISIBLE + : isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown(); + d.setVisible(visible, true); } d.setLevel(mLevel); mDrawableWidth = d.getIntrinsicWidth(); @@ -1051,7 +1081,7 @@ public class ImageView extends View { pleft + pright; // Allow the width to outgrow its original estimate if height is fixed. - if (!resizeHeight && !mAdjustViewBoundsCompat) { + if (!resizeHeight && !sCompatAdjustViewBounds) { widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec); } @@ -1067,7 +1097,7 @@ public class ImageView extends View { ptop + pbottom; // Allow the height to outgrow its original estimate if width is fixed. - if (!resizeWidth && !mAdjustViewBoundsCompat) { + if (!resizeWidth && !sCompatAdjustViewBounds) { heightSize = resolveAdjustedSize(newHeight, mMaxHeight, heightMeasureSpec); } @@ -1419,7 +1449,9 @@ public class ImageView extends View { /** * Returns the alpha that will be applied to the drawable of this ImageView. * - * @return the alpha that will be applied to the drawable of this ImageView + * @return the alpha value that will be applied to the drawable of this + * ImageView (between 0 and 255 inclusive, with 0 being transparent and + * 255 being opaque) * * @see #setImageAlpha(int) */ @@ -1430,7 +1462,8 @@ public class ImageView extends View { /** * Sets the alpha value that should be applied to the image. * - * @param alpha the alpha value that should be applied to the image + * @param alpha the alpha value that should be applied to the image (between + * 0 and 255 inclusive, with 0 being transparent and 255 being opaque) * * @see #getImageAlpha() */ @@ -1506,11 +1539,40 @@ public class ImageView extends View { @Override public void onVisibilityAggregated(boolean isVisible) { super.onVisibilityAggregated(isVisible); - if (mDrawable != null) { + // Only do this for new apps post-Nougat + if (mDrawable != null && !sCompatDrawableVisibilityDispatch) { mDrawable.setVisible(isVisible, false); } } + @RemotableViewMethod + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated + if (mDrawable != null && sCompatDrawableVisibilityDispatch) { + mDrawable.setVisible(visibility == VISIBLE, false); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated + if (mDrawable != null && sCompatDrawableVisibilityDispatch) { + mDrawable.setVisible(getVisibility() == VISIBLE, false); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated + if (mDrawable != null && sCompatDrawableVisibilityDispatch) { + mDrawable.setVisible(false, false); + } + } + @Override public CharSequence getAccessibilityClassName() { return ImageView.class.getName(); diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index f75b74bb9a14c785ffd77833885349cbfa74aef3..f897372c1f01918288c37b6c9bb986e21d2ce71c 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -890,7 +890,9 @@ public class LinearLayout extends ViewGroup { remainingWeightSum -= childWeight; final int childHeight; - if (lp.height == 0 && (!mAllowInconsistentMeasurement + if (mUseLargestChild && heightMode != MeasureSpec.EXACTLY) { + childHeight = largestChildHeight; + } else if (lp.height == 0 && (!mAllowInconsistentMeasurement || heightMode == MeasureSpec.EXACTLY)) { // This child needs to be laid out from scratch using // only its share of excess space. @@ -1272,7 +1274,9 @@ public class LinearLayout extends ViewGroup { remainingWeightSum -= childWeight; final int childWidth; - if (lp.width == 0 && (!mAllowInconsistentMeasurement + if (mUseLargestChild && widthMode != MeasureSpec.EXACTLY) { + childWidth = largestChildWidth; + } else if (lp.width == 0 && (!mAllowInconsistentMeasurement || widthMode == MeasureSpec.EXACTLY)) { // This child needs to be laid out from scratch using // only its share of excess space. @@ -1840,13 +1844,14 @@ public class LinearLayout extends ViewGroup { @Override protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { - if (lp instanceof LayoutParams) { - return new LayoutParams((LayoutParams) lp); - } else if (lp instanceof MarginLayoutParams) { - return new LayoutParams((MarginLayoutParams) lp); - } else { - return new LayoutParams(lp); + if (sPreserveMarginParamsInLayoutParamConversion) { + if (lp instanceof LayoutParams) { + return new LayoutParams((LayoutParams) lp); + } else if (lp instanceof MarginLayoutParams) { + return new LayoutParams((MarginLayoutParams) lp); + } } + return new LayoutParams(lp); } diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 0e04e3003d7c9577a704cb199469caea43ea6e50..b0f19d7a0b49fce927f8818d397b45f6158c60fd 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -112,8 +112,8 @@ public class ListView extends AbsListView { public boolean isSelectable; } - private ArrayList mHeaderViewInfos = Lists.newArrayList(); - private ArrayList mFooterViewInfos = Lists.newArrayList(); + ArrayList mHeaderViewInfos = Lists.newArrayList(); + ArrayList mFooterViewInfos = Lists.newArrayList(); Drawable mDivider; int mDividerHeight; @@ -279,7 +279,7 @@ public class ListView extends AbsListView { // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof HeaderViewListAdapter)) { - mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); + wrapHeaderListAdapterInternal(); } // In the case of re-adding a header view, or adding one later on, @@ -373,7 +373,7 @@ public class ListView extends AbsListView { // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof HeaderViewListAdapter)) { - mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); + wrapHeaderListAdapterInternal(); } // In the case of re-adding a footer view, or adding one later on, @@ -476,7 +476,7 @@ public class ListView extends AbsListView { mRecycler.clear(); if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { - mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); + mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter); } else { mAdapter = adapter; } @@ -1939,72 +1939,73 @@ public class ListView extends AbsListView { } /** - * Obtain the view and add it to our list of children. The view can be made - * fresh, converted from an unused view, or used as is if it was in the - * recycle bin. + * Obtains the view and adds it to our list of children. The view can be + * made fresh, converted from an unused view, or used as is if it was in + * the recycle bin. * - * @param position Logical position in the list - * @param y Top or bottom edge of the view to add - * @param flow If flow is true, align top edge to y. If false, align bottom - * edge to y. - * @param childrenLeft Left edge where children should be positioned - * @param selected Is this position selected? - * @return View that was added + * @param position logical position in the list + * @param y top or bottom edge of the view to add + * @param flow {@code true} to align top edge to y, {@code false} to align + * bottom edge to y + * @param childrenLeft left edge where children should be positioned + * @param selected {@code true} if the position is selected, {@code false} + * otherwise + * @return the view that was added */ private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, boolean selected) { - View child; - - if (!mDataChanged) { - // Try to use an existing view for this position - child = mRecycler.getActiveView(position); - if (child != null) { - // Found it -- we're using an existing child - // This just needs to be positioned - setupChild(child, position, y, flow, childrenLeft, selected, true); - - return child; + // Try to use an existing view for this position. + final View activeView = mRecycler.getActiveView(position); + if (activeView != null) { + // Found it. We're reusing an existing child, so it just needs + // to be positioned like a scrap view. + setupChild(activeView, position, y, flow, childrenLeft, selected, true); + return activeView; } } - // Make a new view for this position, or convert an unused view if possible - child = obtainView(position, mIsScrap); + // Make a new view for this position, or convert an unused view if + // possible. + final View child = obtainView(position, mIsScrap); - // This needs to be positioned and measured + // This needs to be positioned and measured. setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]); return child; } /** - * Add a view as a child and make sure it is measured (if necessary) and + * Adds a view as a child and make sure it is measured (if necessary) and * positioned properly. * - * @param child The view to add - * @param position The position of this child - * @param y The y position relative to which this view will be positioned - * @param flowDown If true, align top edge to y. If false, align bottom - * edge to y. - * @param childrenLeft Left edge where children should be positioned - * @param selected Is this position selected? - * @param recycled Has this view been pulled from the recycle bin? If so it - * does not need to be remeasured. + * @param child the view to add + * @param position the position of this child + * @param y the y position relative to which this view will be positioned + * @param flowDown {@code true} to align top edge to y, {@code false} to + * align bottom edge to y + * @param childrenLeft left edge where children should be positioned + * @param selected {@code true} if the position is selected, {@code false} + * otherwise + * @param isAttachedToWindow {@code true} if the view is already attached + * to the window, e.g. whether it was reused, or + * {@code false} otherwise */ private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft, - boolean selected, boolean recycled) { + boolean selected, boolean isAttachedToWindow) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "setupListItem"); final boolean isSelected = selected && shouldShowSelector(); final boolean updateChildSelected = isSelected != child.isSelected(); final int mode = mTouchMode; - final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL && - mMotionPosition == position; + final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL + && mMotionPosition == position; final boolean updateChildPressed = isPressed != child.isPressed(); - final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested(); + final boolean needToMeasure = !isAttachedToWindow || updateChildSelected + || child.isLayoutRequested(); - // Respect layout params that are already in the view. Otherwise make some up... - // noinspection unchecked + // Respect layout params that are already in the view. Otherwise make + // some up... AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams(); if (p == null) { p = (AbsListView.LayoutParams) generateDefaultLayoutParams(); @@ -2012,17 +2013,9 @@ public class ListView extends AbsListView { p.viewType = mAdapter.getItemViewType(position); p.isEnabled = mAdapter.isEnabled(position); - if ((recycled && !p.forceAdd) || (p.recycledHeaderFooter - && p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) { - attachViewToParent(child, flowDown ? -1 : 0, p); - } else { - p.forceAdd = false; - if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { - p.recycledHeaderFooter = true; - } - addViewInLayout(child, flowDown ? -1 : 0, p, true); - } - + // Set up view state before attaching the view, since we may need to + // rely on the jumpDrawablesToCurrentState() call that occurs as part + // of view attachment. if (updateChildSelected) { child.setSelected(isSelected); } @@ -2040,6 +2033,27 @@ public class ListView extends AbsListView { } } + if ((isAttachedToWindow && !p.forceAdd) || (p.recycledHeaderFooter + && p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) { + attachViewToParent(child, flowDown ? -1 : 0, p); + + // If the view was previously attached for a different position, + // then manually jump the drawables. + if (isAttachedToWindow + && (((AbsListView.LayoutParams) child.getLayoutParams()).scrappedFromPosition) + != position) { + child.jumpDrawablesToCurrentState(); + } + } else { + p.forceAdd = false; + if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { + p.recycledHeaderFooter = true; + } + addViewInLayout(child, flowDown ? -1 : 0, p, true); + // add view in layout will reset the RTL properties. We have to re-resolve them + child.resolveRtlPropertiesIfNeeded(); + } + if (needToMeasure) { final int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, mListPadding.left + mListPadding.right, p.width); @@ -2073,11 +2087,6 @@ public class ListView extends AbsListView { child.setDrawingCacheEnabled(true); } - if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition) - != position) { - child.jumpDrawablesToCurrentState(); - } - Trace.traceEnd(Trace.TRACE_TAG_VIEW); } @@ -2219,7 +2228,7 @@ public class ListView extends AbsListView { * after the header views. */ public void setSelectionAfterHeaderView() { - final int count = mHeaderViewInfos.size(); + final int count = getHeaderViewsCount(); if (count > 0) { mNextSelectedPosition = 0; return; @@ -3347,7 +3356,7 @@ public class ListView extends AbsListView { bounds.right = mRight - mLeft - mPaddingRight; final int count = getChildCount(); - final int headerCount = mHeaderViewInfos.size(); + final int headerCount = getHeaderViewsCount(); final int itemCount = mItemCount; final int footerLimit = (itemCount - mFooterViewInfos.size()); final boolean headerDividers = mHeaderDividersEnabled; @@ -3931,7 +3940,7 @@ public class ListView extends AbsListView { if (drawDividers) { final boolean fillForMissingDividers = isOpaque() && !super.isOpaque(); final int itemCount = mItemCount; - final int headerCount = mHeaderViewInfos.size(); + final int headerCount = getHeaderViewsCount(); final int footerLimit = (itemCount - mFooterViewInfos.size()); final boolean isHeader = (itemIndex < headerCount); final boolean isFooter = (itemIndex >= footerLimit); @@ -4043,4 +4052,24 @@ public class ListView extends AbsListView { encoder.addProperty("recycleOnMeasure", recycleOnMeasure()); } + + /** @hide */ + protected HeaderViewListAdapter wrapHeaderListAdapterInternal( + ArrayList headerViewInfos, + ArrayList footerViewInfos, + ListAdapter adapter) { + return new HeaderViewListAdapter(headerViewInfos, footerViewInfos, adapter); + } + + /** @hide */ + protected void wrapHeaderListAdapterInternal() { + mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, mAdapter); + } + + /** @hide */ + protected void dispatchDataSetObserverOnChangedInternal() { + if (mDataSetObserver != null) { + mDataSetObserver.onChanged(); + } + } } diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index c3ddec787bfa4569f260641befd6ab2982e70a6f..25580fd2496e5a8aed18701cd5ba6d98862ebd94 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -16,6 +16,8 @@ package android.widget; +import com.android.internal.R; + import android.annotation.CallSuper; import android.annotation.IntDef; import android.annotation.Widget; @@ -29,10 +31,12 @@ import android.graphics.Paint.Align; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.text.Editable; import android.text.InputFilter; import android.text.InputType; import android.text.Spanned; import android.text.TextUtils; +import android.text.TextWatcher; import android.text.method.NumberKeyListener; import android.util.AttributeSet; import android.util.SparseArray; @@ -52,9 +56,6 @@ import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; -import com.android.internal.R; -import libcore.icu.LocaleData; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -62,6 +63,8 @@ import java.util.Collections; import java.util.List; import java.util.Locale; +import libcore.icu.LocaleData; + /** * A widget that enables the user to select a number from a predefined range. * There are two flavors of this widget and which one is presented to the user @@ -1991,7 +1994,7 @@ public class NumberPicker extends LinearLayout { removeCallbacks(mChangeCurrentByOneFromLongPressCommand); } if (mSetSelectionCommand != null) { - removeCallbacks(mSetSelectionCommand); + mSetSelectionCommand.cancel(); } if (mBeginSoftInputOnLongPressCommand != null) { removeCallbacks(mBeginSoftInputOnLongPressCommand); @@ -2033,18 +2036,14 @@ public class NumberPicker extends LinearLayout { } /** - * Posts an {@link SetSelectionCommand} from the given selectionStart - * to selectionEnd. + * Posts a {@link SetSelectionCommand} from the given + * {@code selectionStart} to {@code selectionEnd}. */ private void postSetSelectionCommand(int selectionStart, int selectionEnd) { if (mSetSelectionCommand == null) { - mSetSelectionCommand = new SetSelectionCommand(); - } else { - removeCallbacks(mSetSelectionCommand); + mSetSelectionCommand = new SetSelectionCommand(mInputText); } - mSetSelectionCommand.mSelectionStart = selectionStart; - mSetSelectionCommand.mSelectionEnd = selectionEnd; - post(mSetSelectionCommand); + mSetSelectionCommand.post(selectionStart, selectionEnd); } /** @@ -2090,6 +2089,12 @@ public class NumberPicker extends LinearLayout { @Override public CharSequence filter( CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { + // We don't know what the output will be, so always cancel any + // pending set selection command. + if (mSetSelectionCommand != null) { + mSetSelectionCommand.cancel(); + } + if (mDisplayedValues == null) { CharSequence filtered = super.filter(source, start, end, dest, dstart, dend); if (filtered == null) { @@ -2237,12 +2242,39 @@ public class NumberPicker extends LinearLayout { /** * Command for setting the input text selection. */ - class SetSelectionCommand implements Runnable { - private int mSelectionStart; + private static class SetSelectionCommand implements Runnable { + private final EditText mInputText; + private int mSelectionStart; private int mSelectionEnd; + /** Whether this runnable is currently posted. */ + private boolean mPosted; + + public SetSelectionCommand(EditText inputText) { + mInputText = inputText; + } + + public void post(int selectionStart, int selectionEnd) { + mSelectionStart = selectionStart; + mSelectionEnd = selectionEnd; + + if (!mPosted) { + mInputText.post(this); + mPosted = true; + } + } + + public void cancel() { + if (mPosted) { + mInputText.removeCallbacks(this); + mPosted = false; + } + } + + @Override public void run() { + mPosted = false; mInputText.setSelection(mSelectionStart, mSelectionEnd); } } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 6477f079cb7fea7f725dd6fee78fc4f7e576dbf2..9b89491ce408c39ae73a788c185322f208d29c30 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -193,6 +193,8 @@ public class PopupWindow { private int mAnimationStyle = ANIMATION_STYLE_DEFAULT; + private int mGravity = Gravity.NO_GRAVITY; + private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] { com.android.internal.R.attr.state_above_anchor }; @@ -1141,15 +1143,11 @@ public class PopupWindow { mIsShowing = true; mIsDropdown = false; + mGravity = gravity; final WindowManager.LayoutParams p = createPopupLayoutParams(token); preparePopup(p); - // Only override the default if some gravity was specified. - if (gravity != Gravity.NO_GRAVITY) { - p.gravity = gravity; - } - p.x = x; p.y = y; @@ -1394,9 +1392,9 @@ public class PopupWindow { } private int computeGravity() { - int gravity = Gravity.START | Gravity.TOP; - if (mClipToScreen || mClippingEnabled) { - gravity |= Gravity.DISPLAY_CLIP_VERTICAL | Gravity.DISPLAY_CLIP_HORIZONTAL; + int gravity = mGravity == Gravity.NO_GRAVITY ? Gravity.START | Gravity.TOP : mGravity; + if (mIsDropdown && (mClipToScreen || mClippingEnabled)) { + gravity |= Gravity.DISPLAY_CLIP_VERTICAL; } return gravity; } @@ -1547,7 +1545,7 @@ public class PopupWindow { } // Let the window manager know to align the top to y. - outParams.gravity = Gravity.LEFT | Gravity.TOP; + outParams.gravity = computeGravity(); outParams.width = width; outParams.height = height; @@ -1760,11 +1758,22 @@ public class PopupWindow { */ public int getMaxAvailableHeight( @NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) { - final Rect displayFrame = new Rect(); + Rect displayFrame = null; + final Rect visibleDisplayFrame = new Rect(); + + anchor.getWindowVisibleDisplayFrame(visibleDisplayFrame); if (ignoreBottomDecorations) { + // In the ignore bottom decorations case we want to + // still respect all other decorations so we use the inset visible + // frame on the top right and left and take the bottom + // value from the full frame. + displayFrame = new Rect(); anchor.getWindowDisplayFrame(displayFrame); + displayFrame.top = visibleDisplayFrame.top; + displayFrame.right = visibleDisplayFrame.right; + displayFrame.left = visibleDisplayFrame.left; } else { - anchor.getWindowVisibleDisplayFrame(displayFrame); + displayFrame = visibleDisplayFrame; } final int[] anchorPos = mTmpDrawingLocation; diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 3c967acdfc5588105f604d7744d7d4da00a945b4..1f379c94cc03a3680aadea00cb4750b842dc5994 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.res.ColorStateList; +import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -230,7 +231,7 @@ public class ProgressBar extends View { private Drawable mCurrentDrawable; private ProgressTintInfo mProgressTintInfo; - Bitmap mSampleTile; + int mSampleWidth = 0; private boolean mNoInvalidate; private Interpolator mInterpolator; private RefreshProgressRunnable mRefreshProgressRunnable; @@ -505,15 +506,14 @@ public class ProgressBar extends View { } if (drawable instanceof BitmapDrawable) { - final BitmapDrawable bitmap = (BitmapDrawable) drawable; - final Bitmap tileBitmap = bitmap.getBitmap(); - if (mSampleTile == null) { - mSampleTile = tileBitmap; - } - - final BitmapDrawable clone = (BitmapDrawable) bitmap.getConstantState().newDrawable(); + final Drawable.ConstantState cs = drawable.getConstantState(); + final BitmapDrawable clone = (BitmapDrawable) cs.newDrawable(getResources()); clone.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); + if (mSampleWidth <= 0) { + mSampleWidth = clone.getIntrinsicWidth(); + } + if (clip) { return new ClipDrawable(clone, Gravity.LEFT, ClipDrawable.HORIZONTAL); } else { diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java index 02ee2df18aafd2ecfc0fddc93d5d43df0ff5ed3d..6f198e78df8a1c5b41023a64ca2cca4ffb7b068a 100644 --- a/core/java/android/widget/RadialTimePickerView.java +++ b/core/java/android/widget/RadialTimePickerView.java @@ -16,7 +16,11 @@ package android.widget; +import com.android.internal.R; +import com.android.internal.widget.ExploreByTouchHelper; + import android.animation.ObjectAnimator; +import android.annotation.IntDef; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -43,9 +47,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; -import com.android.internal.R; -import com.android.internal.widget.ExploreByTouchHelper; - +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Calendar; import java.util.Locale; @@ -55,11 +58,16 @@ import java.util.Locale; * @hide */ public class RadialTimePickerView extends View { - private static final String TAG = "RadialTimePickerView"; public static final int HOURS = 0; public static final int MINUTES = 1; + + /** @hide */ + @IntDef({HOURS, MINUTES}) + @Retention(RetentionPolicy.SOURCE) + @interface PickerType {} + private static final int HOURS_INNER = 2; private static final int SELECTOR_CIRCLE = 0; @@ -185,8 +193,24 @@ public class RadialTimePickerView extends View { private boolean mInputEnabled = true; - public interface OnValueSelectedListener { - void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance); + interface OnValueSelectedListener { + /** + * Called when the selected value at a given picker index has changed. + * + * @param pickerType the type of value that has changed, one of: + *

      + *
    • {@link #MINUTES} + *
    • {@link #HOURS} + *
    + * @param newValue the new value as minute in hour (0-59) or hour in + * day (0-23) + * @param autoAdvance when the picker type is {@link #HOURS}, + * {@code true} to switch to the {@link #MINUTES} + * picker or {@code false} to stay on the current + * picker. No effect when picker type is + * {@link #MINUTES}. + */ + void onValueSelected(@PickerType int pickerType, int newValue, boolean autoAdvance); } /** @@ -977,7 +1001,7 @@ public class RadialTimePickerView extends View { // Ensure we're showing the correct picker. animatePicker(mShowHours, ANIM_DURATION_TOUCH); - final int type; + final @PickerType int type; final int newValue; final boolean valueChanged; diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java index 223096116adbac74368812c846b550ffb5ceebb4..62dd90fddcd0c94eb89575948f4daaebb3f30b1e 100644 --- a/core/java/android/widget/RatingBar.java +++ b/core/java/android/widget/RatingBar.java @@ -110,8 +110,8 @@ public class RatingBar extends AbsSeekBar { } // A touch inside a star fill up to that fractional area (slightly more - // than 1 so boundaries round up). - mTouchProgressOffset = 1.1f; + // than 0.5 so boundaries round up). + mTouchProgressOffset = 0.6f; } public RatingBar(Context context, AttributeSet attrs) { @@ -281,10 +281,8 @@ public class RatingBar extends AbsSeekBar { protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mSampleTile != null) { - // TODO: Once ProgressBar's TODOs are gone, this can be done more - // cleanly than mSampleTile - final int width = mSampleTile.getWidth() * mNumStars; + if (mSampleWidth > 0) { + final int width = mSampleWidth * mNumStars; setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0), getMeasuredHeight()); } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 0136542ef4ac867d34ec62ec1dace4a44161551c..a189d3c0cc9126bc2c2c5304c22b1a3dbda0d1e3 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -1104,13 +1104,14 @@ public class RelativeLayout extends ViewGroup { @Override protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { - if (lp instanceof LayoutParams) { - return new LayoutParams((LayoutParams) lp); - } else if (lp instanceof MarginLayoutParams) { - return new LayoutParams((MarginLayoutParams) lp); - } else { - return new LayoutParams(lp); + if (sPreserveMarginParamsInLayoutParamConversion) { + if (lp instanceof LayoutParams) { + return new LayoutParams((LayoutParams) lp); + } else if (lp instanceof MarginLayoutParams) { + return new LayoutParams((MarginLayoutParams) lp); + } } + return new LayoutParams(lp); } /** @hide */ diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 1f745185d01b16823dc43575a33bb194733106bc..d0d233ebe975e06bcd263873b41de12950856960 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -2787,6 +2787,18 @@ public class RemoteViews implements Parcelable, Filter { setInt(viewId, "setTextColor", color); } + /** + * @hide + * Equivalent to calling {@link android.widget.TextView#setTextColor(ColorStateList)}. + * + * @param viewId The id of the view whose text color should change + * @param colors the text colors to set + */ + public void setTextColor(int viewId, @ColorInt ColorStateList colors) { + addAction(new ReflectionAction(viewId, "setTextColor", ReflectionAction.COLOR_STATE_LIST, + colors)); + } + /** * Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}. * @@ -3195,7 +3207,9 @@ public class RemoteViews implements Parcelable, Filter { // we don't add a filter to the static version returned by getSystemService. inflater = inflater.cloneInContext(inflationContext); inflater.setFilter(this); - return inflater.inflate(rv.getLayoutId(), parent, false); + View v = inflater.inflate(rv.getLayoutId(), parent, false); + v.setTagInternal(R.id.widget_frame, rv.getLayoutId()); + return v; } private static void loadTransitionOverride(Context context, @@ -3373,7 +3387,7 @@ public class RemoteViews implements Parcelable, Filter { // across orientation change, and has the RemoteViews re-applied in the new orientation, // we throw an exception, since the layouts may be completely unrelated. if (hasLandscapeAndPortraitLayouts()) { - if (v.getId() != rvToApply.getLayoutId()) { + if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) { throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" + " that does not share the same root layout id."); } @@ -3409,7 +3423,7 @@ public class RemoteViews implements Parcelable, Filter { // across orientation change, and has the RemoteViews re-applied in the new orientation, // we throw an exception, since the layouts may be completely unrelated. if (hasLandscapeAndPortraitLayouts()) { - if (v.getId() != rvToApply.getLayoutId()) { + if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) { throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" + " that does not share the same root layout id."); } diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index 0555cd403b00581c0ca4811a26b90dfabfdeb23a..e696ff7229e8fa8a3e12405c8984f2793848594c 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -17,6 +17,7 @@ package android.widget; import android.annotation.NonNull; +import android.content.res.Configuration; import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Parcel; @@ -134,6 +135,8 @@ public class ScrollView extends FrameLayout { private int mOverscrollDistance; private int mOverflingDistance; + private int mScrollFactor; + /** * ID of the active pointer. This is used to retain consistency during * drags/flings if multiple pointers are used. @@ -186,6 +189,10 @@ public class ScrollView extends FrameLayout { setFillViewport(a.getBoolean(R.styleable.ScrollView_fillViewport, false)); a.recycle(); + + if (context.getResources().getConfiguration().uiMode == Configuration.UI_MODE_TYPE_WATCH) { + setRevealOnFocusHint(false); + } } @Override @@ -243,6 +250,7 @@ public class ScrollView extends FrameLayout { mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mOverscrollDistance = configuration.getScaledOverscrollDistance(); mOverflingDistance = configuration.getScaledOverflingDistance(); + mScrollFactor = configuration.getScaledScrollFactor(); } @Override @@ -777,30 +785,35 @@ public class ScrollView extends FrameLayout { @Override public boolean onGenericMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: { - if (!mIsBeingDragged) { - final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - if (vscroll != 0) { - final int delta = (int) (vscroll * getVerticalScrollFactor()); - final int range = getScrollRange(); - int oldScrollY = mScrollY; - int newScrollY = oldScrollY - delta; - if (newScrollY < 0) { - newScrollY = 0; - } else if (newScrollY > range) { - newScrollY = range; - } - if (newScrollY != oldScrollY) { - super.scrollTo(mScrollX, newScrollY); - return true; - } - } + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: + final float axisValue; + if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_VSCROLL); + } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) { + axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL); + } else { + axisValue = 0; + } + + final int delta = Math.round(axisValue * mScrollFactor); + if (delta != 0) { + final int range = getScrollRange(); + int oldScrollY = mScrollY; + int newScrollY = oldScrollY - delta; + if (newScrollY < 0) { + newScrollY = 0; + } else if (newScrollY > range) { + newScrollY = range; + } + if (newScrollY != oldScrollY) { + super.scrollTo(mScrollX, newScrollY); + return true; } } - } + break; } + return super.onGenericMotionEvent(event); } @@ -1455,11 +1468,13 @@ public class ScrollView extends FrameLayout { @Override public void requestChildFocus(View child, View focused) { - if (!mIsLayoutDirty) { - scrollToChild(focused); - } else { - // The child may not be laid out yet, we can't compute the scroll yet - mChildToScrollTo = focused; + if (focused.getRevealOnFocusHint()) { + if (!mIsLayoutDirty) { + scrollToChild(focused); + } else { + // The child may not be laid out yet, we can't compute the scroll yet + mChildToScrollTo = focused; + } } super.requestChildFocus(child, focused); } diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index 5878cad2f9a34845193f4b3c5e2903669f58711f..9139361eda7c9cb42d3eea973fc3a2004041241c 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -816,9 +816,11 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { switch (heightMode) { case MeasureSpec.AT_MOST: - case MeasureSpec.UNSPECIFIED: height = Math.min(getPreferredHeight(), height); break; + case MeasureSpec.UNSPECIFIED: + height = getPreferredHeight(); + break; } heightMode = MeasureSpec.EXACTLY; diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index c4a17715896c1b3ed89b01eb4a9346eefbdc5186..a01d65a1df202806d99389d3f598fb03f90c8455 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -65,6 +65,9 @@ import com.android.internal.R; * {@link #setSwitchTextAppearance(android.content.Context, int) switchTextAppearance} and * the related setSwitchTypeface() methods control that of the thumb. * + *

    {@link android.support.v7.widget.SwitchCompat} is a version of + * the Switch widget which runs on devices back to API 7.

    + * *

    See the Toggle Buttons * guide.

    * diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java index a585d75e5d7ab77e735cfab5df5a1c7cbc7f7c5c..49380b745564aacc65185cbfcee41e6eb555dac5 100644 --- a/core/java/android/widget/TextClock.java +++ b/core/java/android/widget/TextClock.java @@ -130,7 +130,7 @@ public class TextClock extends TextView { private CharSequence mDescFormat; - private boolean mAttached; + private boolean mRegistered; private Calendar mTime; private String mTimeZone; @@ -250,7 +250,7 @@ public class TextClock extends TextView { } createTime(mTimeZone); - // Wait until onAttachedToWindow() to handle the ticker + // Wait until registering for events to handle the ticker chooseFormat(false); } @@ -501,7 +501,7 @@ public class TextClock extends TextView { boolean hadSeconds = mHasSeconds; mHasSeconds = DateFormat.hasSeconds(mFormat); - if (handleTicker && mAttached && hadSeconds != mHasSeconds) { + if (handleTicker && mRegistered && hadSeconds != mHasSeconds) { if (hadSeconds) getHandler().removeCallbacks(mTicker); else mTicker.run(); } @@ -515,11 +515,9 @@ public class TextClock extends TextView { } @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - if (!mAttached) { - mAttached = true; + public void onVisibilityAggregated(boolean isVisible) { + if (!mRegistered && isVisible) { + mRegistered = true; registerReceiver(); registerObserver(); @@ -531,20 +529,13 @@ public class TextClock extends TextView { } else { onTimeChanged(); } - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - - if (mAttached) { + } else if (mRegistered && !isVisible) { unregisterReceiver(); unregisterObserver(); getHandler().removeCallbacks(mTicker); - mAttached = false; + mRegistered = false; } } @@ -567,7 +558,7 @@ public class TextClock extends TextView { } private void registerObserver() { - if (isAttachedToWindow()) { + if (mRegistered) { if (mFormatChangeObserver == null) { mFormatChangeObserver = new FormatChangeObserver(getHandler()); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 5cbd2841b57a30993d10847c3c737af7fefcdaf4..f8daa8823d2125371a65536f92f63c93f40c2831 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3234,6 +3234,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Sets the text color for all the states (normal, selected, * focused) to be this color. * + * @param color A color value in the form 0xAARRGGBB. + * Do not pass a resource ID. To get a color value from a resource ID, call + * {@link android.support.v4.content.ContextCompat#getColor(Context, int) getColor}. + * * @see #setTextColor(ColorStateList) * @see #getTextColors() * @@ -3255,6 +3259,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @attr ref android.R.styleable#TextView_textColor */ + @android.view.RemotableViewMethod public void setTextColor(ColorStateList colors) { if (colors == null) { throw new NullPointerException(); diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java index f2fc617ccc33ea607576f423755e73eb4a4e14d8..a1c854bd8f639c3621c1f6677f180773b8c6adf2 100644 --- a/core/java/android/widget/TimePicker.java +++ b/core/java/android/widget/TimePicker.java @@ -16,20 +16,24 @@ package android.widget; +import com.android.internal.R; + +import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; -import android.annotation.Nullable; +import android.annotation.TestApi; import android.annotation.Widget; import android.content.Context; -import android.content.res.Configuration; import android.content.res.TypedArray; import android.os.Parcel; import android.os.Parcelable; -import android.os.Parcelable.Creator; import android.util.AttributeSet; +import android.util.MathUtils; import android.view.View; import android.view.accessibility.AccessibilityEvent; -import com.android.internal.R; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Locale; import libcore.icu.LocaleData; @@ -45,11 +49,36 @@ import libcore.icu.LocaleData; */ @Widget public class TimePicker extends FrameLayout { - private static final int MODE_SPINNER = 1; - private static final int MODE_CLOCK = 2; + /** + * Presentation mode for the Holo-style time picker that uses a set of + * {@link android.widget.NumberPicker}s. + * + * @see #getMode() + * @hide Visible for testing only. + */ + @TestApi + public static final int MODE_SPINNER = 1; + + /** + * Presentation mode for the Material-style time picker that uses a clock + * face. + * + * @see #getMode() + * @hide Visible for testing only. + */ + @TestApi + public static final int MODE_CLOCK = 2; + + /** @hide */ + @IntDef({MODE_SPINNER, MODE_CLOCK}) + @Retention(RetentionPolicy.SOURCE) + public @interface TimePickerMode {} private final TimePickerDelegate mDelegate; + @TimePickerMode + private final int mMode; + /** * The callback interface used to indicate the time has been adjusted. */ @@ -80,10 +109,19 @@ public class TimePicker extends FrameLayout { final TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes); - final int mode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER); + final boolean isDialogMode = a.getBoolean(R.styleable.TimePicker_dialogMode, false); + final int requestedMode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER); a.recycle(); - switch (mode) { + if (requestedMode == MODE_CLOCK && isDialogMode) { + // You want MODE_CLOCK? YOU CAN'T HANDLE MODE_CLOCK! Well, maybe + // you can depending on your screen size. Let's check... + mMode = context.getResources().getInteger(R.integer.time_picker_mode); + } else { + mMode = requestedMode; + } + + switch (mMode) { case MODE_CLOCK: mDelegate = new TimePickerClockDelegate( this, context, attrs, defStyleAttr, defStyleRes); @@ -96,14 +134,26 @@ public class TimePicker extends FrameLayout { } } + /** + * @return the picker's presentation mode, one of {@link #MODE_CLOCK} or + * {@link #MODE_SPINNER} + * @attr ref android.R.styleable#TimePicker_timePickerMode + * @hide Visible for testing only. + */ + @TimePickerMode + @TestApi + public int getMode() { + return mMode; + } + /** * Sets the currently selected hour using 24-hour time. * * @param hour the hour to set, in the range (0-23) * @see #getHour() */ - public void setHour(int hour) { - mDelegate.setHour(hour); + public void setHour(@IntRange(from = 0, to = 23) int hour) { + mDelegate.setHour(MathUtils.constrain(hour, 0, 23)); } /** @@ -117,13 +167,13 @@ public class TimePicker extends FrameLayout { } /** - * Sets the currently selected minute.. + * Sets the currently selected minute. * * @param minute the minute to set, in the range (0-59) * @see #getMinute() */ - public void setMinute(int minute) { - mDelegate.setMinute(minute); + public void setMinute(@IntRange(from = 0, to = 59) int minute) { + mDelegate.setMinute(MathUtils.constrain(minute, 0, 59)); } /** @@ -137,8 +187,9 @@ public class TimePicker extends FrameLayout { } /** - * Sets the current hour. + * Sets the currently selected hour using 24-hour time. * + * @param currentHour the hour to set, in the range (0-23) * @deprecated Use {@link #setHour(int)} */ @Deprecated @@ -147,33 +198,34 @@ public class TimePicker extends FrameLayout { } /** - * @return the current hour in the range (0-23) + * @return the currently selected hour, in the range (0-23) * @deprecated Use {@link #getHour()} */ @NonNull @Deprecated public Integer getCurrentHour() { - return mDelegate.getHour(); + return getHour(); } /** - * Set the current minute (0-59). + * Sets the currently selected minute. * + * @param currentMinute the minute to set, in the range (0-59) * @deprecated Use {@link #setMinute(int)} */ @Deprecated public void setCurrentMinute(@NonNull Integer currentMinute) { - mDelegate.setMinute(currentMinute); + setMinute(currentMinute); } /** - * @return the current minute + * @return the currently selected minute, in the range (0-59) * @deprecated Use {@link #getMinute()} */ @NonNull @Deprecated public Integer getCurrentMinute() { - return mDelegate.getMinute(); + return getMinute(); } /** @@ -256,10 +308,10 @@ public class TimePicker extends FrameLayout { * for the real behavior. */ interface TimePickerDelegate { - void setHour(int hour); + void setHour(@IntRange(from = 0, to = 23) int hour); int getHour(); - void setMinute(int minute); + void setMinute(@IntRange(from = 0, to = 59) int minute); int getMinute(); void setIs24Hour(boolean is24Hour); diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index c21f1dfe0ed13c386c1719e51c124351f5ca6c0c..aa0b93d76a15ad07abe25edbdc42558bbdced3d7 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -61,9 +61,6 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { private static final int HOUR_INDEX = RadialTimePickerView.HOURS; private static final int MINUTE_INDEX = RadialTimePickerView.MINUTES; - // NOT a real index for the purpose of what's showing. - private static final int AMPM_INDEX = 2; - private static final int[] ATTRS_TEXT_COLOR = new int[] {R.attr.textColor}; private static final int[] ATTRS_DISABLED_ALPHA = new int[] {R.attr.disabledAlpha}; @@ -701,22 +698,21 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { /** Listener for RadialTimePickerView interaction. */ private final OnValueSelectedListener mOnValueSelectedListener = new OnValueSelectedListener() { @Override - public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { - switch (pickerIndex) { - case HOUR_INDEX: + public void onValueSelected(int pickerType, int newValue, boolean autoAdvance) { + switch (pickerType) { + case RadialTimePickerView.HOURS: final boolean isTransition = mAllowAutoAdvance && autoAdvance; setHourInternal(newValue, true, !isTransition); if (isTransition) { setCurrentItemShowing(MINUTE_INDEX, true, false); - mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes); + + final int localizedHour = getLocalizedHour(newValue); + mDelegator.announceForAccessibility(localizedHour + ". " + mSelectMinutes); } break; - case MINUTE_INDEX: + case RadialTimePickerView.MINUTES: setMinuteInternal(newValue, true); break; - case AMPM_INDEX: - updateAmPmLabelStates(newValue); - break; } if (mOnTimeChangedListener != null) { diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 77626754264f1931b2fa63e2cd5b53d938edacac..a400d90c64c5afe446e30c1d785030cc4e6e791f 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -25,6 +25,8 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.Handler; +import android.os.IBinder; +import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; @@ -326,13 +328,6 @@ public class Toast { } private static class TN extends ITransientNotification.Stub { - final Runnable mShow = new Runnable() { - @Override - public void run() { - handleShow(); - } - }; - final Runnable mHide = new Runnable() { @Override public void run() { @@ -343,7 +338,13 @@ public class Toast { }; private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(); - final Handler mHandler = new Handler(); + final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + IBinder token = (IBinder) msg.obj; + handleShow(token); + } + }; int mGravity; int mX, mY; @@ -379,9 +380,9 @@ public class Toast { * schedule handleShow into the right thread */ @Override - public void show() { + public void show(IBinder windowToken) { if (localLOGV) Log.v(TAG, "SHOW: " + this); - mHandler.post(mShow); + mHandler.obtainMessage(0, windowToken).sendToTarget(); } /** @@ -393,7 +394,7 @@ public class Toast { mHandler.post(mHide); } - public void handleShow() { + public void handleShow(IBinder windowToken) { if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView + " mNextView=" + mNextView); if (mView != mNextView) { @@ -422,8 +423,9 @@ public class Toast { mParams.verticalMargin = mVerticalMargin; mParams.horizontalMargin = mHorizontalMargin; mParams.packageName = packageName; - mParams.removeTimeoutMilliseconds = mDuration == + mParams.hideTimeoutMilliseconds = mDuration == Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT; + mParams.token = windowToken; if (mView.getParent() != null) { if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this); mWM.removeView(mView); @@ -458,7 +460,7 @@ public class Toast { // the view isn't yet added, so let's try not to crash. if (mView.getParent() != null) { if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this); - mWM.removeView(mView); + mWM.removeViewImmediate(mView); } mView = null; diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index 9cdb73ae51ce88c494862e4e9ef05310b09a0b9c..0988c928cb2633b624f15d0402b271a2833afaf3 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -161,7 +161,7 @@ public class Toolbar extends ViewGroup { private int mTitleMarginTop; private int mTitleMarginBottom; - private final RtlSpacingHelper mContentInsets = new RtlSpacingHelper(); + private RtlSpacingHelper mContentInsets; private int mContentInsetStartWithNavigation; private int mContentInsetEndWithActions; @@ -270,6 +270,7 @@ public class Toolbar extends ViewGroup { final int contentInsetRight = a.getDimensionPixelSize(R.styleable.Toolbar_contentInsetRight, 0); + ensureContentInsets(); mContentInsets.setAbsolute(contentInsetLeft, contentInsetRight); if (contentInsetStart != RtlSpacingHelper.UNDEFINED || @@ -463,13 +464,13 @@ public class Toolbar extends ViewGroup { */ public void setTitleMarginBottom(int margin) { mTitleMarginBottom = margin; - requestLayout(); } @Override public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) { super.onRtlPropertiesChanged(layoutDirection); + ensureContentInsets(); mContentInsets.setDirection(layoutDirection == LAYOUT_DIRECTION_RTL); } @@ -1092,6 +1093,7 @@ public class Toolbar extends ViewGroup { * @attr ref android.R.styleable#Toolbar_contentInsetStart */ public void setContentInsetsRelative(int contentInsetStart, int contentInsetEnd) { + ensureContentInsets(); mContentInsets.setRelative(contentInsetStart, contentInsetEnd); } @@ -1112,7 +1114,7 @@ public class Toolbar extends ViewGroup { * @attr ref android.R.styleable#Toolbar_contentInsetStart */ public int getContentInsetStart() { - return mContentInsets.getStart(); + return mContentInsets != null ? mContentInsets.getStart() : 0; } /** @@ -1132,7 +1134,7 @@ public class Toolbar extends ViewGroup { * @attr ref android.R.styleable#Toolbar_contentInsetEnd */ public int getContentInsetEnd() { - return mContentInsets.getEnd(); + return mContentInsets != null ? mContentInsets.getEnd() : 0; } /** @@ -1154,6 +1156,7 @@ public class Toolbar extends ViewGroup { * @attr ref android.R.styleable#Toolbar_contentInsetRight */ public void setContentInsetsAbsolute(int contentInsetLeft, int contentInsetRight) { + ensureContentInsets(); mContentInsets.setAbsolute(contentInsetLeft, contentInsetRight); } @@ -1174,7 +1177,7 @@ public class Toolbar extends ViewGroup { * @attr ref android.R.styleable#Toolbar_contentInsetLeft */ public int getContentInsetLeft() { - return mContentInsets.getLeft(); + return mContentInsets != null ? mContentInsets.getLeft() : 0; } /** @@ -1194,7 +1197,7 @@ public class Toolbar extends ViewGroup { * @attr ref android.R.styleable#Toolbar_contentInsetRight */ public int getContentInsetRight() { - return mContentInsets.getRight(); + return mContentInsets != null ? mContentInsets.getRight() : 0; } /** @@ -2128,6 +2131,12 @@ public class Toolbar extends ViewGroup { } } + private void ensureContentInsets() { + if (mContentInsets == null) { + mContentInsets = new RtlSpacingHelper(); + } + } + /** * Accessor to enable LayoutLib to get ActionMenuPresenter directly. */ diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index f084db2d1589b4092ed80da574e4c1775aa3f01e..b973324dee8c9e7577d011f8b7dcc1ff6f639f40 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -70,46 +70,49 @@ import java.util.Vector; */ public class VideoView extends SurfaceView implements MediaPlayerControl, SubtitleController.Anchor { - private String TAG = "VideoView"; - // settable by the client - private Uri mUri; - private Map mHeaders; + private static final String TAG = "VideoView"; // all possible internal states - private static final int STATE_ERROR = -1; - private static final int STATE_IDLE = 0; - private static final int STATE_PREPARING = 1; - private static final int STATE_PREPARED = 2; - private static final int STATE_PLAYING = 3; - private static final int STATE_PAUSED = 4; + private static final int STATE_ERROR = -1; + private static final int STATE_IDLE = 0; + private static final int STATE_PREPARING = 1; + private static final int STATE_PREPARED = 2; + private static final int STATE_PLAYING = 3; + private static final int STATE_PAUSED = 4; private static final int STATE_PLAYBACK_COMPLETED = 5; + private final Vector> mPendingSubtitleTracks = new Vector<>(); + + // settable by the client + private Uri mUri; + private Map mHeaders; + // mCurrentState is a VideoView object's current state. // mTargetState is the state that a method caller intends to reach. // For instance, regardless the VideoView object's current state, // calling pause() intends to bring the object to a target state // of STATE_PAUSED. private int mCurrentState = STATE_IDLE; - private int mTargetState = STATE_IDLE; + private int mTargetState = STATE_IDLE; // All the stuff we need for playing and showing a video private SurfaceHolder mSurfaceHolder = null; private MediaPlayer mMediaPlayer = null; - private int mAudioSession; - private int mVideoWidth; - private int mVideoHeight; - private int mSurfaceWidth; - private int mSurfaceHeight; + private int mAudioSession; + private int mVideoWidth; + private int mVideoHeight; + private int mSurfaceWidth; + private int mSurfaceHeight; private MediaController mMediaController; private OnCompletionListener mOnCompletionListener; private MediaPlayer.OnPreparedListener mOnPreparedListener; - private int mCurrentBufferPercentage; + private int mCurrentBufferPercentage; private OnErrorListener mOnErrorListener; - private OnInfoListener mOnInfoListener; - private int mSeekWhenPrepared; // recording the seek position while preparing - private boolean mCanPause; - private boolean mCanSeekBack; - private boolean mCanSeekForward; + private OnInfoListener mOnInfoListener; + private int mSeekWhenPrepared; // recording the seek position while preparing + private boolean mCanPause; + private boolean mCanSeekBack; + private boolean mCanSeekForward; /** Subtitle rendering widget overlaid on top of the video. */ private RenderingWidget mSubtitleWidget; @@ -118,13 +121,11 @@ public class VideoView extends SurfaceView private RenderingWidget.OnChangedListener mSubtitlesChangedListener; public VideoView(Context context) { - super(context); - initVideoView(); + this(context, null); } public VideoView(Context context, AttributeSet attrs) { this(context, attrs, 0); - initVideoView(); } public VideoView(Context context, AttributeSet attrs, int defStyleAttr) { @@ -133,7 +134,19 @@ public class VideoView extends SurfaceView public VideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - initVideoView(); + + mVideoWidth = 0; + mVideoHeight = 0; + + getHolder().addCallback(mSHCallback); + getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + + setFocusable(true); + setFocusableInTouchMode(true); + requestFocus(); + + mCurrentState = STATE_IDLE; + mTargetState = STATE_IDLE; } @Override @@ -209,19 +222,6 @@ public class VideoView extends SurfaceView return getDefaultSize(desiredSize, measureSpec); } - private void initVideoView() { - mVideoWidth = 0; - mVideoHeight = 0; - getHolder().addCallback(mSHCallback); - getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - setFocusable(true); - setFocusableInTouchMode(true); - requestFocus(); - mPendingSubtitleTracks = new Vector>(); - mCurrentState = STATE_IDLE; - mTargetState = STATE_IDLE; - } - /** * Sets video path. * @@ -294,8 +294,6 @@ public class VideoView extends SurfaceView } } - private Vector> mPendingSubtitleTracks; - public void stopPlayback() { if (mMediaPlayer != null) { mMediaPlayer.stop(); diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java index ed48b0d1610c5e25f0fa428c69be12ce51bd2b28..35ffa71de56f87aa64144d56c2725468c810ec80 100644 --- a/core/java/com/android/internal/app/AlertActivity.java +++ b/core/java/com/android/internal/app/AlertActivity.java @@ -49,7 +49,7 @@ public abstract class AlertActivity extends Activity implements DialogInterface protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mAlert = new AlertController(this, this, getWindow()); + mAlert = AlertController.create(this, this, getWindow()); mAlertParams = new AlertController.AlertParams(this); } diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index b7ac6008a1fdc04bf0d32eb2e793869afd28b8ad..95c291a9e8fea495b7636ff047a5afa590c42e76 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -24,6 +24,7 @@ import android.annotation.Nullable; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.Drawable; @@ -61,14 +62,15 @@ import android.widget.TextView; import java.lang.ref.WeakReference; public class AlertController { + public static final int MICRO = 1; private final Context mContext; private final DialogInterface mDialogInterface; - private final Window mWindow; + protected final Window mWindow; private CharSequence mTitle; - private CharSequence mMessage; - private ListView mListView; + protected CharSequence mMessage; + protected ListView mListView; private View mView; private int mViewLayoutResId; @@ -91,14 +93,14 @@ public class AlertController { private CharSequence mButtonNeutralText; private Message mButtonNeutralMessage; - private ScrollView mScrollView; + protected ScrollView mScrollView; private int mIconId = 0; private Drawable mIcon; private ImageView mIconView; private TextView mTitleView; - private TextView mMessageView; + protected TextView mMessageView; private View mCustomTitleView; private boolean mForceInverseBackground; @@ -176,7 +178,21 @@ public class AlertController { return outValue.data != 0; } - public AlertController(Context context, DialogInterface di, Window window) { + public static final AlertController create(Context context, DialogInterface di, Window window) { + final TypedArray a = context.obtainStyledAttributes( + null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0); + int controllerType = a.getInt(R.styleable.AlertDialog_controllerType, 0); + a.recycle(); + + switch (controllerType) { + case MICRO: + return new MicroAlertController(context, di, window); + default: + return new AlertController(context, di, window); + } + } + + protected AlertController(Context context, DialogInterface di, Window window) { mContext = context; mDialogInterface = di; mWindow = window; @@ -597,7 +613,7 @@ public class AlertController { } } - private void setupTitle(ViewGroup topPanel) { + protected void setupTitle(ViewGroup topPanel) { if (mCustomTitleView != null && mShowTitle) { // Add the custom title view directly to the topPanel layout final LayoutParams lp = new LayoutParams( @@ -643,7 +659,7 @@ public class AlertController { } } - private void setupContent(ViewGroup contentPanel) { + protected void setupContent(ViewGroup contentPanel) { mScrollView = (ScrollView) contentPanel.findViewById(R.id.scrollView); mScrollView.setFocusable(false); @@ -680,7 +696,7 @@ public class AlertController { } } - private void setupButtons(ViewGroup buttonPanel) { + protected void setupButtons(ViewGroup buttonPanel) { int BIT_BUTTON_POSITIVE = 1; int BIT_BUTTON_NEGATIVE = 2; int BIT_BUTTON_NEUTRAL = 4; @@ -872,7 +888,8 @@ public class AlertController { final int checkedItem = mCheckedItem; if (checkedItem > -1) { listView.setItemChecked(checkedItem, true); - listView.setSelection(checkedItem); + listView.setSelectionFromTop(checkedItem, + a.getDimensionPixelSize(R.styleable.AlertDialog_selectionScrollOffset, 0)); } } } @@ -1072,7 +1089,8 @@ public class AlertController { public void bindView(View view, Context context, Cursor cursor) { CheckedTextView text = (CheckedTextView) view.findViewById(R.id.text1); text.setText(cursor.getString(mLabelIndex)); - listView.setItemChecked(cursor.getPosition(), + listView.setItemChecked( + cursor.getPosition(), cursor.getInt(mIsCheckedIndex) == 1); } diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java index d552e542e5274ad7dfcff9f74dbe0d26156d36b1..294007946c773c4134cb171dfc96f0e159aaa317 100644 --- a/core/java/com/android/internal/app/AssistUtils.java +++ b/core/java/com/android/internal/app/AssistUtils.java @@ -16,10 +16,13 @@ package com.android.internal.app; +import com.android.internal.R; + import android.app.SearchManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; @@ -132,6 +135,16 @@ public class AssistUtils { } } + public void registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener) { + try { + if (mVoiceInteractionManagerService != null) { + mVoiceInteractionManagerService.registerVoiceInteractionSessionListener(listener); + } + } catch (RemoteException e) { + Log.w(TAG, "Failed to register voice interaction listener", e); + } + } + public ComponentName getAssistComponentForUser(int userId) { final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId); @@ -156,4 +169,41 @@ public class AssistUtils { return null; } + public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) { + if (assistant == null) { + return false; + } + ApplicationInfo applicationInfo; + try { + applicationInfo = context.getPackageManager().getApplicationInfo( + assistant.getPackageName(), 0); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp(); + } + + private static boolean isDisclosureEnabled(Context context) { + return Settings.Secure.getInt(context.getContentResolver(), + Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0; + } + + /** + * @return if the disclosure animation should trigger for the given assistant. + * + * Third-party assistants will always need to disclose, while the user can configure this for + * pre-installed assistants. + */ + public static boolean shouldDisclose(Context context, ComponentName assistant) { + if (!allowDisablingAssistDisclosure(context)) { + return true; + } + + return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant); + } + + public static boolean allowDisablingAssistDisclosure(Context context) { + return context.getResources().getBoolean( + com.android.internal.R.bool.config_allowDisablingAssistDisclosure); + } } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 216a4f1c9a4486f70a6e42aecd52d0c110a38465..5623a2cb430c15e0bf132a1ecc7ec903de6b2e22 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -79,6 +79,8 @@ interface IBatteryStats { String newHistoryName, int newType, boolean newUnimportantForLogging); void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, String historyName, int type); + void noteLongPartialWakelockStart(String name, String historyName, int uid); + void noteLongPartialWakelockFinish(String name, String historyName, int uid); void noteVibratorOn(int uid, long durationMillis); void noteVibratorOff(int uid); @@ -118,7 +120,7 @@ interface IBatteryStats { void noteWifiBatchedScanStoppedFromSource(in WorkSource ws); void noteWifiMulticastEnabledFromSource(in WorkSource ws); void noteWifiMulticastDisabledFromSource(in WorkSource ws); - void noteWifiRadioPowerState(int powerState, long timestampNs); + void noteWifiRadioPowerState(int powerState, long timestampNs, int uid); void noteNetworkInterfaceType(String iface, int type); void noteNetworkStatsEnabled(); void noteDeviceIdleMode(int mode, String activeReason, int activeUid); diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 1a963f30ca075e81ba70e93fa008387c800cde5d..033dd13046eab1a56c8b38008c1209c2ee0638a4 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -22,6 +22,7 @@ import android.os.Bundle; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; +import com.android.internal.app.IVoiceInteractionSessionListener; import android.hardware.soundtrigger.IRecognitionStatusCallback; import android.hardware.soundtrigger.SoundTrigger; import android.service.voice.IVoiceInteractionService; @@ -136,4 +137,9 @@ interface IVoiceInteractionManagerService { * Called when the lockscreen got shown. */ void onLockscreenShown(); + + /** + * Register a voice interaction listener. + */ + void registerVoiceInteractionSessionListener(IVoiceInteractionSessionListener listener); } diff --git a/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl b/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl new file mode 100644 index 0000000000000000000000000000000000000000..87749d26e4a0c09c2c275983388a4ca07486e104 --- /dev/null +++ b/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package com.android.internal.app; + + oneway interface IVoiceInteractionSessionListener { + /** + * Called when a voice session is shown. + */ + void onVoiceSessionShown(); + + /** + * Called when a voice session is hidden. + */ + void onVoiceSessionHidden(); + } \ No newline at end of file diff --git a/core/java/com/android/internal/app/MicroAlertController.java b/core/java/com/android/internal/app/MicroAlertController.java new file mode 100644 index 0000000000000000000000000000000000000000..4431f3c6a50f682c0817d39b3deb7238246c7a46 --- /dev/null +++ b/core/java/com/android/internal/app/MicroAlertController.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import android.content.Context; +import android.content.DialogInterface; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; + +import com.android.internal.app.AlertController; +import com.android.internal.R; + +public class MicroAlertController extends AlertController { + public MicroAlertController(Context context, DialogInterface di, Window window) { + super(context, di, window); + } + + @Override + protected void setupContent(ViewGroup contentPanel) { + // Special case for small screen - the scroll view is higher in hierarchy + mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView); + + // Special case for users that only want to display a String + mMessageView = (TextView) contentPanel.findViewById(R.id.message); + if (mMessageView == null) { + return; + } + + if (mMessage != null) { + mMessageView.setText(mMessage); + } else { + // no message, remove associated views + mMessageView.setVisibility(View.GONE); + contentPanel.removeView(mMessageView); + + if (mListView != null) { + // has ListView, swap scrollView with ListView + + // move topPanel into top of scrollParent + View topPanel = mScrollView.findViewById(R.id.topPanel); + ((ViewGroup) topPanel.getParent()).removeView(topPanel); + FrameLayout.LayoutParams topParams = + new FrameLayout.LayoutParams(topPanel.getLayoutParams()); + topParams.gravity = Gravity.TOP; + topPanel.setLayoutParams(topParams); + + // move buttonPanel into bottom of scrollParent + View buttonPanel = mScrollView.findViewById(R.id.buttonPanel); + ((ViewGroup) buttonPanel.getParent()).removeView(buttonPanel); + FrameLayout.LayoutParams buttonParams = + new FrameLayout.LayoutParams(buttonPanel.getLayoutParams()); + buttonParams.gravity = Gravity.BOTTOM; + buttonPanel.setLayoutParams(buttonParams); + + // remove scrollview + final ViewGroup scrollParent = (ViewGroup) mScrollView.getParent(); + final int childIndex = scrollParent.indexOfChild(mScrollView); + scrollParent.removeViewAt(childIndex); + + // add list view + scrollParent.addView(mListView, + new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + + // add top and button panel + scrollParent.addView(topPanel); + scrollParent.addView(buttonPanel); + } else { + // no content, just hide everything + contentPanel.setVisibility(View.GONE); + } + } + } + + @Override + protected void setupTitle(ViewGroup topPanel) { + super.setupTitle(topPanel); + if (topPanel.getVisibility() == View.GONE) { + topPanel.setVisibility(View.INVISIBLE); + } + } + + @Override + protected void setupButtons(ViewGroup buttonPanel) { + super.setupButtons(buttonPanel); + if (buttonPanel.getVisibility() == View.GONE) { + buttonPanel.setVisibility(View.INVISIBLE); + } + } +} diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java new file mode 100644 index 0000000000000000000000000000000000000000..03cd729db62ba0554d0db0cd46b7735b733575c0 --- /dev/null +++ b/core/java/com/android/internal/app/NightDisplayController.java @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; +import android.provider.Settings.Secure; +import android.util.Slog; + +import com.android.internal.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Calendar; +import java.util.Locale; + +/** + * Controller for managing Night display settings. + *

    + * Night display tints your screen red at night. This makes it easier to look at your screen in + * dim light and may help you fall asleep more easily. + */ +public final class NightDisplayController { + + private static final String TAG = "NightDisplayController"; + private static final boolean DEBUG = false; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ AUTO_MODE_DISABLED, AUTO_MODE_CUSTOM, AUTO_MODE_TWILIGHT }) + public @interface AutoMode {} + + /** + * Auto mode value to prevent Night display from being automatically activated. It can still + * be activated manually via {@link #setActivated(boolean)}. + * + * @see #setAutoMode(int) + */ + public static final int AUTO_MODE_DISABLED = 0; + /** + * Auto mode value to automatically activate Night display at a specific start and end time. + * + * @see #setAutoMode(int) + * @see #setCustomStartTime(LocalTime) + * @see #setCustomEndTime(LocalTime) + */ + public static final int AUTO_MODE_CUSTOM = 1; + /** + * Auto mode value to automatically activate Night display from sunset to sunrise. + * + * @see #setAutoMode(int) + */ + public static final int AUTO_MODE_TWILIGHT = 2; + + private final Context mContext; + private final int mUserId; + + private final ContentObserver mContentObserver; + + private Callback mCallback; + + public NightDisplayController(@NonNull Context context) { + this(context, UserHandle.myUserId()); + } + + public NightDisplayController(@NonNull Context context, int userId) { + mContext = context.getApplicationContext(); + mUserId = userId; + + mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + + final String setting = uri == null ? null : uri.getLastPathSegment(); + if (setting != null) { + onSettingChanged(setting); + } + } + }; + } + + /** + * Returns {@code true} when Night display is activated (the display is tinted red). + */ + public boolean isActivated() { + return Secure.getIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_ACTIVATED, 0, mUserId) == 1; + } + + /** + * Sets whether Night display should be activated. + * + * @param activated {@code true} if Night display should be activated + * @return {@code true} if the activated value was set successfully + */ + public boolean setActivated(boolean activated) { + return Secure.putIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_ACTIVATED, activated ? 1 : 0, mUserId); + } + + /** + * Returns the current auto mode value controlling when Night display will be automatically + * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or + * {@link #AUTO_MODE_TWILIGHT}. + */ + public @AutoMode int getAutoMode() { + int autoMode = Secure.getIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_AUTO_MODE, -1, mUserId); + if (autoMode == -1) { + if (DEBUG) { + Slog.d(TAG, "Using default value for setting: " + Secure.NIGHT_DISPLAY_AUTO_MODE); + } + autoMode = mContext.getResources().getInteger( + R.integer.config_defaultNightDisplayAutoMode); + } + + if (autoMode != AUTO_MODE_DISABLED + && autoMode != AUTO_MODE_CUSTOM + && autoMode != AUTO_MODE_TWILIGHT) { + Slog.e(TAG, "Invalid autoMode: " + autoMode); + autoMode = AUTO_MODE_DISABLED; + } + + return autoMode; + } + + /** + * Sets the current auto mode value controlling when Night display will be automatically + * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or + * {@link #AUTO_MODE_TWILIGHT}. + * + * @param autoMode the new auto mode to use + * @return {@code true} if new auto mode was set successfully + */ + public boolean setAutoMode(@AutoMode int autoMode) { + if (autoMode != AUTO_MODE_DISABLED + && autoMode != AUTO_MODE_CUSTOM + && autoMode != AUTO_MODE_TWILIGHT) { + throw new IllegalArgumentException("Invalid autoMode: " + autoMode); + } + + return Secure.putIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId); + } + + /** + * Returns the local time when Night display will be automatically activated when using + * {@link #AUTO_MODE_CUSTOM}. + */ + public @NonNull LocalTime getCustomStartTime() { + int startTimeValue = Secure.getIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, -1, mUserId); + if (startTimeValue == -1) { + if (DEBUG) { + Slog.d(TAG, "Using default value for setting: " + + Secure.NIGHT_DISPLAY_CUSTOM_START_TIME); + } + startTimeValue = mContext.getResources().getInteger( + R.integer.config_defaultNightDisplayCustomStartTime); + } + + return LocalTime.valueOf(startTimeValue); + } + + /** + * Sets the local time when Night display will be automatically activated when using + * {@link #AUTO_MODE_CUSTOM}. + * + * @param startTime the local time to automatically activate Night display + * @return {@code true} if the new custom start time was set successfully + */ + public boolean setCustomStartTime(@NonNull LocalTime startTime) { + if (startTime == null) { + throw new IllegalArgumentException("startTime cannot be null"); + } + return Secure.putIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toMillis(), mUserId); + } + + /** + * Returns the local time when Night display will be automatically deactivated when using + * {@link #AUTO_MODE_CUSTOM}. + */ + public @NonNull LocalTime getCustomEndTime() { + int endTimeValue = Secure.getIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, -1, mUserId); + if (endTimeValue == -1) { + if (DEBUG) { + Slog.d(TAG, "Using default value for setting: " + + Secure.NIGHT_DISPLAY_CUSTOM_END_TIME); + } + endTimeValue = mContext.getResources().getInteger( + R.integer.config_defaultNightDisplayCustomEndTime); + } + + return LocalTime.valueOf(endTimeValue); + } + + /** + * Sets the local time when Night display will be automatically deactivated when using + * {@link #AUTO_MODE_CUSTOM}. + * + * @param endTime the local time to automatically deactivate Night display + * @return {@code true} if the new custom end time was set successfully + */ + public boolean setCustomEndTime(@NonNull LocalTime endTime) { + if (endTime == null) { + throw new IllegalArgumentException("endTime cannot be null"); + } + return Secure.putIntForUser(mContext.getContentResolver(), + Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toMillis(), mUserId); + } + + private void onSettingChanged(@NonNull String setting) { + if (DEBUG) { + Slog.d(TAG, "onSettingChanged: " + setting); + } + + if (mCallback != null) { + switch (setting) { + case Secure.NIGHT_DISPLAY_ACTIVATED: + mCallback.onActivated(isActivated()); + break; + case Secure.NIGHT_DISPLAY_AUTO_MODE: + mCallback.onAutoModeChanged(getAutoMode()); + break; + case Secure.NIGHT_DISPLAY_CUSTOM_START_TIME: + mCallback.onCustomStartTimeChanged(getCustomStartTime()); + break; + case Secure.NIGHT_DISPLAY_CUSTOM_END_TIME: + mCallback.onCustomEndTimeChanged(getCustomEndTime()); + break; + } + } + } + + /** + * Register a callback to be invoked whenever the Night display settings are changed. + */ + public void setListener(Callback callback) { + final Callback oldCallback = mCallback; + if (oldCallback != callback) { + mCallback = callback; + + if (callback == null) { + // Stop listening for changes now that there IS NOT a listener. + mContext.getContentResolver().unregisterContentObserver(mContentObserver); + } else if (oldCallback == null) { + // Start listening for changes now that there IS a listener. + final ContentResolver cr = mContext.getContentResolver(); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_ACTIVATED), + false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_AUTO_MODE), + false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME), + false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME), + false /* notifyForDescendants */, mContentObserver, mUserId); + } + } + } + + /** + * Returns {@code true} if Night display is supported by the device. + */ + public static boolean isAvailable(Context context) { + return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable); + } + + /** + * A time without a time-zone or date. + */ + public static class LocalTime { + + /** + * The hour of the day from 0 - 23. + */ + public final int hourOfDay; + /** + * The minute within the hour from 0 - 59. + */ + public final int minute; + + public LocalTime(int hourOfDay, int minute) { + if (hourOfDay < 0 || hourOfDay > 23) { + throw new IllegalArgumentException("Invalid hourOfDay: " + hourOfDay); + } else if (minute < 0 || minute > 59) { + throw new IllegalArgumentException("Invalid minute: " + minute); + } + + this.hourOfDay = hourOfDay; + this.minute = minute; + } + + /** + * Returns the first date time corresponding to this local time that occurs before the + * provided date time. + * + * @param time the date time to compare against + * @return the prior date time corresponding to this local time + */ + public Calendar getDateTimeBefore(Calendar time) { + final Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, time.get(Calendar.YEAR)); + c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR)); + + c.set(Calendar.HOUR_OF_DAY, hourOfDay); + c.set(Calendar.MINUTE, minute); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + // Check if the local time has past, if so return the same time tomorrow. + if (c.after(time)) { + c.add(Calendar.DATE, -1); + } + + return c; + } + + /** + * Returns the first date time corresponding to this local time that occurs after the + * provided date time. + * + * @param time the date time to compare against + * @return the next date time corresponding to this local time + */ + public Calendar getDateTimeAfter(Calendar time) { + final Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, time.get(Calendar.YEAR)); + c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR)); + + c.set(Calendar.HOUR_OF_DAY, hourOfDay); + c.set(Calendar.MINUTE, minute); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + // Check if the local time has past, if so return the same time tomorrow. + if (c.before(time)) { + c.add(Calendar.DATE, 1); + } + + return c; + } + + /** + * Returns a local time corresponding the given number of milliseconds from midnight. + * + * @param millis the number of milliseconds from midnight + * @return the corresponding local time + */ + private static LocalTime valueOf(int millis) { + final int hourOfDay = (millis / 3600000) % 24; + final int minutes = (millis / 60000) % 60; + return new LocalTime(hourOfDay, minutes); + } + + /** + * Returns the local time represented as milliseconds from midnight. + */ + private int toMillis() { + return hourOfDay * 3600000 + minute * 60000; + } + + @Override + public String toString() { + return String.format(Locale.US, "%02d:%02d", hourOfDay, minute); + } + } + + /** + * Callback invoked whenever the Night display settings are changed. + */ + public interface Callback { + /** + * Callback invoked when the activated state changes. + * + * @param activated {@code true} if Night display is activated + */ + default void onActivated(boolean activated) {} + /** + * Callback invoked when the auto mode changes. + * + * @param autoMode the auto mode to use + */ + default void onAutoModeChanged(int autoMode) {} + /** + * Callback invoked when the time to automatically activate Night display changes. + * + * @param startTime the local time to automatically activate Night display + */ + default void onCustomStartTimeChanged(LocalTime startTime) {} + /** + * Callback invoked when the time to automatically deactivate Night display changes. + * + * @param endTime the local time to automatically deactivate Night display + */ + default void onCustomEndTimeChanged(LocalTime endTime) {} + } +} diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 085e159c8b21765c8bb322a9a7d6253f0ea50a8f..1e26c92dd7644bbdc89430a0723aad6e7ef18fc2 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -69,9 +69,13 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.MetricsProto; import com.android.internal.widget.ResolverDrawerLayout; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -359,6 +363,12 @@ public class ResolverActivity extends Activity { if (isVoiceInteraction()) { onSetupVoiceInteraction(); } + final Set categories = intent.getCategories(); + MetricsLogger.action(this, mAdapter.hasFilteredItem() + ? MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_APP_FEATURED + : MetricsProto.MetricsEvent.ACTION_SHOW_APP_DISAMBIG_NONE_FEATURED, + intent.getAction() + ":" + intent.getType() + ":" + + (categories != null ? Arrays.toString(categories.toArray()) : "")); } public final void setFilteredComponents(ComponentName[] components) { @@ -649,6 +659,19 @@ public class ResolverActivity extends Activity { TargetInfo target = mAdapter.targetInfoForPosition(which, filtered); if (onTargetSelected(target, always)) { + if (always && filtered) { + MetricsLogger.action( + this, MetricsProto.MetricsEvent.ACTION_APP_DISAMBIG_ALWAYS); + } else if (filtered) { + MetricsLogger.action( + this, MetricsProto.MetricsEvent.ACTION_APP_DISAMBIG_JUST_ONCE); + } else { + MetricsLogger.action( + this, MetricsProto.MetricsEvent.ACTION_APP_DISAMBIG_TAP); + } + MetricsLogger.action(this, mAdapter.hasFilteredItem() + ? MetricsProto.MetricsEvent.ACTION_HIDE_APP_DISAMBIG_APP_FEATURED + : MetricsProto.MetricsEvent.ACTION_HIDE_APP_DISAMBIG_NONE_FEATURED); finish(); } } @@ -1446,7 +1469,7 @@ public class ResolverActivity extends Activity { boolean found = false; // Only loop to the end of into as it was before we started; no dupes in from. for (int j = 0; j < intoCount; j++) { - final ResolvedComponentInfo rci = into.get(i); + final ResolvedComponentInfo rci = into.get(j); if (isSameResolvedComponent(newInfo, rci)) { found = true; rci.add(intent, newInfo); diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java index 03a3a3821f6a92181c077002c464057cb41d3e4f..4d4c7ceb16550b299e155f03b7fa447f3ea4a158 100644 --- a/core/java/com/android/internal/app/ResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverComparator.java @@ -157,7 +157,10 @@ class ResolverComparator implements Comparator { // We want to put the one targeted to another user at the end of the dialog. if (lhs.targetUserId != UserHandle.USER_CURRENT) { - return 1; + return rhs.targetUserId != UserHandle.USER_CURRENT ? 0 : 1; + } + if (rhs.targetUserId != UserHandle.USER_CURRENT) { + return -1; } if (mHttp) { diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java index a4b5a8e6595c891f142679be1d2650d229f8e9e5..cb2b0191b8831830367d3491a978be8ffa97a670 100644 --- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java +++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java @@ -145,7 +145,11 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { if (itemType == TYPE_HEADER_SUGGESTED) { textView.setText(R.string.language_picker_section_suggested); } else { - textView.setText(R.string.language_picker_section_all); + if (mCountryMode) { + textView.setText(R.string.region_picker_section_all); + } else { + textView.setText(R.string.language_picker_section_all); + } } textView.setTextLocale(Locale.getDefault()); break; diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java index d24cefeecf077239d378426375c795c03433338d..0a539f19c48aa416158be63f64bfd59cdc3aaf14 100644 --- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java +++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java @@ -37,6 +37,7 @@ import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import android.view.Window; import android.widget.TextView; import com.android.internal.R; @@ -59,6 +60,9 @@ public class UnlaunchableAppActivity extends Activity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // As this activity has nothing to show, we should hide the title bar also + // TODO: Use AlertActivity so we don't need to hide title bar and create a dialog + requestWindowFeature(Window.FEATURE_NO_TITLE); Intent intent = getIntent(); mReason = intent.getIntExtra(EXTRA_UNLAUNCHABLE_REASON, -1); mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl index 4260e50a31f26120cf34b33409424d810e0af968..951a45a7b4376a42de8a624c916e1acac6f4cb94 100644 --- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl @@ -34,7 +34,7 @@ interface IAppWidgetService { // for AppWidgetHost // ParceledListSlice startListening(IAppWidgetHost host, String callingPackage, int hostId, - in int[] appWidgetIds, out int[] updatedIds); + in int[] appWidgetIds); void stopListening(String callingPackage, int hostId); int allocateAppWidgetId(String callingPackage, int hostId); void deleteAppWidgetId(String callingPackage, int appWidgetId); diff --git a/core/java/com/android/internal/graphics/drawable/AnimationScaleListDrawable.java b/core/java/com/android/internal/graphics/drawable/AnimationScaleListDrawable.java new file mode 100644 index 0000000000000000000000000000000000000000..62f18eac4aa4be83add35620b3ca7e0e05f0ea7c --- /dev/null +++ b/core/java/com/android/internal/graphics/drawable/AnimationScaleListDrawable.java @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.graphics.drawable; + +import android.animation.ValueAnimator; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.res.Resources; +import android.content.res.Resources.Theme; +import android.content.res.TypedArray; +import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.DrawableContainer; +import android.util.AttributeSet; + +import com.android.internal.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * An internal DrawableContainer class, used to draw different things depending on animation scale. + * i.e: animation scale can be 0 in battery saver mode. + * This class contains 2 drawable, one is animatable, the other is static. When animation scale is + * not 0, the animatable drawable will the drawn. Otherwise, the static drawable will be drawn. + *

    This class implements Animatable since ProgressBar can pick this up similarly as an + * AnimatedVectorDrawable. + *

    It can be defined in an XML file with the {@code } + * element. + */ +public class AnimationScaleListDrawable extends DrawableContainer implements Animatable { + private static final String TAG = "AnimationScaleListDrawable"; + private AnimationScaleListState mAnimationScaleListState; + private boolean mMutated; + + public AnimationScaleListDrawable() { + this(null, null); + } + + private AnimationScaleListDrawable(@Nullable AnimationScaleListState state, + @Nullable Resources res) { + // Every scale list drawable has its own constant state. + final AnimationScaleListState newState = new AnimationScaleListState(state, this, res); + setConstantState(newState); + onStateChange(getState()); + } + + /** + * Set the current drawable according to the animation scale. If scale is 0, then pick the + * static drawable, otherwise, pick the animatable drawable. + */ + @Override + protected boolean onStateChange(int[] stateSet) { + final boolean changed = super.onStateChange(stateSet); + int idx = mAnimationScaleListState.getCurrentDrawableIndexBasedOnScale(); + return selectDrawable(idx) || changed; + } + + + @Override + public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Theme theme) + throws XmlPullParserException, IOException { + final TypedArray a = obtainAttributes(r, theme, attrs, + R.styleable.AnimationScaleListDrawable); + updateDensity(r); + a.recycle(); + + inflateChildElements(r, parser, attrs, theme); + + onStateChange(getState()); + } + + /** + * Inflates child elements from XML. + */ + private void inflateChildElements(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Theme theme) + throws XmlPullParserException, IOException { + final AnimationScaleListState state = mAnimationScaleListState; + final int innerDepth = parser.getDepth() + 1; + int type; + int depth; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth + || type != XmlPullParser.END_TAG)) { + if (type != XmlPullParser.START_TAG) { + continue; + } + + if (depth > innerDepth || !parser.getName().equals("item")) { + continue; + } + + // Either pick up the android:drawable attribute. + final TypedArray a = obtainAttributes(r, theme, attrs, + R.styleable.AnimationScaleListDrawableItem); + Drawable dr = a.getDrawable(R.styleable.AnimationScaleListDrawableItem_drawable); + a.recycle(); + + // Or parse the child element under . + if (dr == null) { + while ((type = parser.next()) == XmlPullParser.TEXT) { + } + if (type != XmlPullParser.START_TAG) { + throw new XmlPullParserException( + parser.getPositionDescription() + + ": tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); + } + dr = Drawable.createFromXmlInner(r, parser, attrs, theme); + } + + state.addDrawable(dr); + } + } + + @Override + public Drawable mutate() { + if (!mMutated && super.mutate() == this) { + mAnimationScaleListState.mutate(); + mMutated = true; + } + return this; + } + + @Override + public void clearMutated() { + super.clearMutated(); + mMutated = false; + } + + @Override + public void start() { + Drawable dr = getCurrent(); + if (dr != null && dr instanceof Animatable) { + ((Animatable) dr).start(); + } + } + + @Override + public void stop() { + Drawable dr = getCurrent(); + if (dr != null && dr instanceof Animatable) { + ((Animatable) dr).stop(); + } + } + + @Override + public boolean isRunning() { + boolean result = false; + Drawable dr = getCurrent(); + if (dr != null && dr instanceof Animatable) { + result = ((Animatable) dr).isRunning(); + } + return result; + } + + static class AnimationScaleListState extends DrawableContainerState { + int[] mThemeAttrs = null; + // The index of the last static drawable. + int mStaticDrawableIndex = -1; + // The index of the last animatable drawable. + int mAnimatableDrawableIndex = -1; + + AnimationScaleListState(AnimationScaleListState orig, AnimationScaleListDrawable owner, + Resources res) { + super(orig, owner, res); + + if (orig != null) { + // Perform a shallow copy and rely on mutate() to deep-copy. + mThemeAttrs = orig.mThemeAttrs; + + mStaticDrawableIndex = orig.mStaticDrawableIndex; + mAnimatableDrawableIndex = orig.mAnimatableDrawableIndex; + } + + } + + void mutate() { + mThemeAttrs = mThemeAttrs != null ? mThemeAttrs.clone() : null; + } + + /** + * Add the drawable into the container. + * This class only keep track one animatable drawable, and one static. If there are multiple + * defined in the XML, then pick the last one. + */ + int addDrawable(Drawable drawable) { + final int pos = addChild(drawable); + if (drawable instanceof Animatable) { + mAnimatableDrawableIndex = pos; + } else { + mStaticDrawableIndex = pos; + } + return pos; + } + + @Override + public Drawable newDrawable() { + return new AnimationScaleListDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new AnimationScaleListDrawable(this, res); + } + + @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || super.canApplyTheme(); + } + + public int getCurrentDrawableIndexBasedOnScale() { + if (ValueAnimator.getDurationScale() == 0) { + return mStaticDrawableIndex; + } + return mAnimatableDrawableIndex; + } + } + + @Override + public void applyTheme(@NonNull Theme theme) { + super.applyTheme(theme); + + onStateChange(getState()); + } + + @Override + protected void setConstantState(@NonNull DrawableContainerState state) { + super.setConstantState(state); + + if (state instanceof AnimationScaleListState) { + mAnimationScaleListState = (AnimationScaleListState) state; + } + } +} + diff --git a/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl b/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl new file mode 100644 index 0000000000000000000000000000000000000000..8abc8074b5acc376deff9976b0fdcc15c8d032e4 --- /dev/null +++ b/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl @@ -0,0 +1,27 @@ +/* +** Copyright 2016, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package com.android.internal.inputmethod; + +import android.os.IBinder; + +/** + * {@hide} + */ +interface IInputContentUriToken { + void take(); + void release(); +} diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java index a1f92cdf2170be5a333161423db0c3d7b7cc5d3f..ab52f2f9a9c863f353bb89a31a300a09d529e560 100644 --- a/core/java/com/android/internal/net/VpnProfile.java +++ b/core/java/com/android/internal/net/VpnProfile.java @@ -176,6 +176,11 @@ public class VpnProfile implements Cloneable, Parcelable { * connection. */ public boolean isValidLockdownProfile() { + // b/7064069: lockdown firewall blocks ports that would be used for PPTP + if (type == TYPE_PPTP) { + return false; + } + try { InetAddress.parseNumericAddress(server); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index a1df8c186982dbd2324d0a4889b44536355f842d..3b3344e7d9346f6dca44edb3be0d24a39d45c968 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -108,7 +108,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 147 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 150 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -1415,22 +1415,6 @@ public class BatteryStatsImpl extends BatteryStats { mUnpluggedReportedCount = 0; return true; } - - @Override - public void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { - super.writeSummaryFromParcelLocked(out, batteryRealtime); - out.writeLong(mCurrentReportedTotalTime); - out.writeInt(mCurrentReportedCount); - out.writeInt(mTrackingReportedValues ? 1 : 0); - } - - @Override - public void readSummaryFromParcelLocked(Parcel in) { - super.readSummaryFromParcelLocked(in); - mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); - mUnpluggedReportedCount = mCurrentReportedCount = in.readInt(); - mTrackingReportedValues = in.readInt() == 1; - } } /** @@ -1566,6 +1550,186 @@ public class BatteryStatsImpl extends BatteryStats { } } + + /** + * A StopwatchTimer that also tracks the total and max individual + * time spent active according to the given timebase. Whereas + * StopwatchTimer apportions the time amongst all in the pool, + * the total and max durations are not apportioned. + */ + public static class DurationTimer extends StopwatchTimer { + /** + * The time (in ms) that the timer was last acquired or the time base + * last (re-)started. Increasing the nesting depth does not reset this time. + * + * -1 if the timer is currently not running or the time base is not running. + * + * If written to a parcel, the start time is reset, as is mNesting in the base class + * StopwatchTimer. + */ + long mStartTimeMs = -1; + + /** + * The longest time period (in ms) that the timer has been active. + */ + long mMaxDurationMs; + + /** + * The total time (in ms) that that the timer has been active since reset(). + */ + long mCurrentDurationMs; + + public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList timerPool, + TimeBase timeBase, Parcel in) { + super(clocks, uid, type, timerPool, timeBase, in); + mMaxDurationMs = in.readLong(); + } + + public DurationTimer(Clocks clocks, Uid uid, int type, ArrayList timerPool, + TimeBase timeBase) { + super(clocks, uid, type, timerPool, timeBase); + } + + @Override + public void writeToParcel(Parcel out, long elapsedRealtimeUs) { + super.writeToParcel(out, elapsedRealtimeUs); + out.writeLong(mMaxDurationMs); + } + + /** + * Write the summary to the parcel. + * + * Since the time base is probably meaningless after we come back, reading + * from this will have the effect of stopping the timer. So here all we write + * is the max duration. + */ + @Override + public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) { + super.writeSummaryFromParcelLocked(out, elapsedRealtimeUs); + out.writeLong(mMaxDurationMs); + } + + /** + * Read the summary parcel. + * + * Has the side effect of stopping the timer. + */ + @Override + public void readSummaryFromParcelLocked(Parcel in) { + super.readSummaryFromParcelLocked(in); + mMaxDurationMs = in.readLong(); + mStartTimeMs = -1; + mCurrentDurationMs = 0; + } + + /** + * The TimeBase time started (again). + * + * If the timer is also running, store the start time. + */ + public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) { + super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime); + if (mNesting > 0) { + mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000; + } + } + + /** + * The TimeBase stopped running. + * + * If the timer is running, add the duration into mCurrentDurationMs. + */ + @Override + public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtime) { + super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtime); + if (mNesting > 0) { + mCurrentDurationMs += (elapsedRealtimeUs / 1000) - mStartTimeMs; + } + mStartTimeMs = -1; + } + + @Override + public void logState(Printer pw, String prefix) { + super.logState(pw, prefix); + } + + @Override + public void startRunningLocked(long elapsedRealtimeMs) { + super.startRunningLocked(elapsedRealtimeMs); + if (mNesting == 1 && mTimeBase.isRunning()) { + // Just started + mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000; + } + } + + /** + * Decrements the mNesting ref-count on this timer. + * + * If it actually stopped (mNesting went to 0), then possibly update + * mMaxDuration if the current duration was the longest ever. + */ + @Override + public void stopRunningLocked(long elapsedRealtimeMs) { + super.stopRunningLocked(elapsedRealtimeMs); + if (mNesting == 0) { + final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs); + if (durationMs > mMaxDurationMs) { + mMaxDurationMs = durationMs; + } + mStartTimeMs = -1; + mCurrentDurationMs = 0; + } + } + + @Override + public boolean reset(boolean detachIfReset) { + boolean result = super.reset(detachIfReset); + mMaxDurationMs = 0; + mCurrentDurationMs = 0; + if (mNesting > 0) { + mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime()*1000) / 1000; + } else { + mStartTimeMs = -1; + } + return result; + } + + /** + * Returns the max duration that this timer has ever seen. + * + * Note that this time is NOT split between the timers in the timer group that + * this timer is attached to. It is the TOTAL time. + */ + @Override + public long getMaxDurationMsLocked(long elapsedRealtimeMs) { + if (mNesting > 0) { + final long durationMs = getCurrentDurationMsLocked(elapsedRealtimeMs); + if (durationMs > mMaxDurationMs) { + return durationMs; + } + } + return mMaxDurationMs; + } + + /** + * Returns the time since the timer was started. + * + * Note that this time is NOT split between the timers in the timer group that + * this timer is attached to. It is the TOTAL time. + */ + @Override + public long getCurrentDurationMsLocked(long elapsedRealtimeMs) { + long durationMs = mCurrentDurationMs; + if (mNesting > 0) { + if (mTimeBase.isRunning()) { + durationMs += (mTimeBase.getRealtime(elapsedRealtimeMs*1000)/1000) + - mStartTimeMs; + } + } + return durationMs; + } + } + /** * State for keeping track of timing information. */ @@ -1791,11 +1955,17 @@ public class BatteryStatsImpl extends BatteryStats { public abstract class OverflowArrayMap { private static final String OVERFLOW_NAME = "*overflow*"; + final int mUid; final ArrayMap mMap = new ArrayMap<>(); T mCurOverflow; ArrayMap mActiveOverflow; + long mLastOverflowTime; + long mLastOverflowFinishTime; + long mLastClearTime; + long mLastCleanupTime; - public OverflowArrayMap() { + public OverflowArrayMap(int uid) { + mUid = uid; } public ArrayMap getMap() { @@ -1803,6 +1973,7 @@ public class BatteryStatsImpl extends BatteryStats { } public void clear() { + mLastClearTime = SystemClock.elapsedRealtime(); mMap.clear(); mCurOverflow = null; mActiveOverflow = null; @@ -1819,6 +1990,7 @@ public class BatteryStatsImpl extends BatteryStats { } public void cleanup() { + mLastCleanupTime = SystemClock.elapsedRealtime(); if (mActiveOverflow != null) { if (mActiveOverflow.size() == 0) { mActiveOverflow = null; @@ -1885,6 +2057,7 @@ public class BatteryStatsImpl extends BatteryStats { mActiveOverflow = new ArrayMap<>(); } mActiveOverflow.put(name, new MutableInt(1)); + mLastOverflowTime = SystemClock.elapsedRealtime(); return obj; } @@ -1914,6 +2087,7 @@ public class BatteryStatsImpl extends BatteryStats { over.value--; if (over.value <= 0) { mActiveOverflow.remove(name); + mLastOverflowFinishTime = SystemClock.elapsedRealtime(); } return obj; } @@ -1922,9 +2096,35 @@ public class BatteryStatsImpl extends BatteryStats { // Huh, they are stopping an active operation but we can't find one! // That's not good. - Slog.wtf(TAG, "Unable to find object for " + name + " mapsize=" - + mMap.size() + " activeoverflow=" + mActiveOverflow - + " curoverflow=" + mCurOverflow); + StringBuilder sb = new StringBuilder(); + sb.append("Unable to find object for "); + sb.append(name); + sb.append(" in uid "); + sb.append(mUid); + sb.append(" mapsize="); + sb.append(mMap.size()); + sb.append(" activeoverflow="); + sb.append(mActiveOverflow); + sb.append(" curoverflow="); + sb.append(mCurOverflow); + long now = SystemClock.elapsedRealtime(); + if (mLastOverflowTime != 0) { + sb.append(" lastOverflowTime="); + TimeUtils.formatDuration(mLastOverflowTime-now, sb); + } + if (mLastOverflowFinishTime != 0) { + sb.append(" lastOverflowFinishTime="); + TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb); + } + if (mLastClearTime != 0) { + sb.append(" lastClearTime="); + TimeUtils.formatDuration(mLastClearTime-now, sb); + } + if (mLastCleanupTime != 0) { + sb.append(" lastCleanupTime="); + TimeUtils.formatDuration(mLastCleanupTime-now, sb); + } + Slog.wtf(TAG, sb.toString()); return null; } @@ -3285,6 +3485,36 @@ public class BatteryStatsImpl extends BatteryStats { } } + public void noteLongPartialWakelockStart(String name, String historyName, int uid) { + uid = mapUid(uid); + final long elapsedRealtime = mClocks.elapsedRealtime(); + final long uptime = mClocks.uptimeMillis(); + if (historyName == null) { + historyName = name; + } + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid, + 0)) { + return; + } + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START, + historyName, uid); + } + + public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { + uid = mapUid(uid); + final long elapsedRealtime = mClocks.elapsedRealtime(); + final long uptime = mClocks.uptimeMillis(); + if (historyName == null) { + historyName = name; + } + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid, + 0)) { + return; + } + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, + historyName, uid); + } + void aggregateLastWakeupUptimeLocked(long uptimeMs) { if (mLastWakeupReason != null) { long deltaUptime = uptimeMs - mLastWakeupUptimeMs; @@ -3554,6 +3784,14 @@ public class BatteryStatsImpl extends BatteryStats { mNumConnectivityChange++; } + private void noteMobileRadioApWakeupLocked(final long elapsedRealtimeMillis, + final long uptimeMillis, int uid) { + uid = mapUid(uid); + addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", + uid); + getUidStatsLocked(uid).noteMobileRadioApWakeupLocked(); + } + public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) { final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); @@ -3563,6 +3801,10 @@ public class BatteryStatsImpl extends BatteryStats { powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; if (active) { + if (uid > 0) { + noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid); + } + mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000); mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; } else { @@ -4239,7 +4481,15 @@ public class BatteryStatsImpl extends BatteryStats { } } - public void noteWifiRadioPowerState(int powerState, long timestampNs) { + private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis, + final long uptimeMillis, int uid) { + uid = mapUid(uid); + addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", + uid); + getUidStatsLocked(uid).noteWifiRadioApWakeupLocked(); + } + + public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) { final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); if (mWifiRadioPowerState != powerState) { @@ -4247,6 +4497,9 @@ public class BatteryStatsImpl extends BatteryStats { powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; if (active) { + if (uid > 0) { + noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid); + } mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG; } else { mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG; @@ -4874,6 +5127,33 @@ public class BatteryStatsImpl extends BatteryStats { return mUidStats; } + private static void detachTimerIfNotNull(BatteryStatsImpl.Timer timer) { + if (timer != null) { + timer.detach(); + } + } + + private static boolean resetTimerIfNotNull(BatteryStatsImpl.Timer timer, + boolean detachIfReset) { + if (timer != null) { + return timer.reset(detachIfReset); + } + return true; + } + + private static void detachLongCounterIfNotNull(LongSamplingCounter counter) { + if (counter != null) { + counter.detach(); + } + } + + private static void resetLongCounterIfNotNull(LongSamplingCounter counter, + boolean detachIfReset) { + if (counter != null) { + counter.reset(detachIfReset); + } + } + /** * The statistics associated with a particular uid. */ @@ -4920,6 +5200,16 @@ public class BatteryStatsImpl extends BatteryStats { LongSamplingCounter mMobileRadioActiveTime; LongSamplingCounter mMobileRadioActiveCount; + /** + * How many times this UID woke up the Application Processor due to a Mobile radio packet. + */ + private LongSamplingCounter mMobileRadioApWakeupCount; + + /** + * How many times this UID woke up the Application Processor due to a Wifi packet. + */ + private LongSamplingCounter mWifiRadioApWakeupCount; + /** * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode. * Can be null if the UID has had no such activity. @@ -4994,18 +5284,18 @@ public class BatteryStatsImpl extends BatteryStats { mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); - mWakelockStats = mBsi.new OverflowArrayMap() { + mWakelockStats = mBsi.new OverflowArrayMap(uid) { @Override public Wakelock instantiateObject() { return new Wakelock(mBsi, Uid.this); } }; - mSyncStats = mBsi.new OverflowArrayMap() { + mSyncStats = mBsi.new OverflowArrayMap(uid) { @Override public StopwatchTimer instantiateObject() { return new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null, mBsi.mOnBatteryTimeBase); } }; - mJobStats = mBsi.new OverflowArrayMap() { + mJobStats = mBsi.new OverflowArrayMap(uid) { @Override public StopwatchTimer instantiateObject() { return new StopwatchTimer(mBsi.mClocks, Uid.this, JOB, null, mBsi.mOnBatteryTimeBase); @@ -5629,6 +5919,36 @@ public class BatteryStatsImpl extends BatteryStats { return 0; } + public void noteMobileRadioApWakeupLocked() { + if (mMobileRadioApWakeupCount == null) { + mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); + } + mMobileRadioApWakeupCount.addCountLocked(1); + } + + @Override + public long getMobileRadioApWakeupCount(int which) { + if (mMobileRadioApWakeupCount != null) { + return mMobileRadioApWakeupCount.getCountLocked(which); + } + return 0; + } + + public void noteWifiRadioApWakeupLocked() { + if (mWifiRadioApWakeupCount == null) { + mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); + } + mWifiRadioApWakeupCount.addCountLocked(1); + } + + @Override + public long getWifiRadioApWakeupCount(int which) { + if (mWifiRadioApWakeupCount != null) { + return mWifiRadioApWakeupCount.getCountLocked(which); + } + return 0; + } + void initNetworkActivityLocked() { mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; @@ -5671,24 +5991,14 @@ public class BatteryStatsImpl extends BatteryStats { active |= !mWifiMulticastTimer.reset(false); active |= mWifiMulticastEnabled; } - if (mAudioTurnedOnTimer != null) { - active |= !mAudioTurnedOnTimer.reset(false); - } - if (mVideoTurnedOnTimer != null) { - active |= !mVideoTurnedOnTimer.reset(false); - } - if (mFlashlightTurnedOnTimer != null) { - active |= !mFlashlightTurnedOnTimer.reset(false); - } - if (mCameraTurnedOnTimer != null) { - active |= !mCameraTurnedOnTimer.reset(false); - } - if (mForegroundActivityTimer != null) { - active |= !mForegroundActivityTimer.reset(false); - } - if (mBluetoothScanTimer != null) { - active |= !mBluetoothScanTimer.reset(false); - } + + active |= !resetTimerIfNotNull(mAudioTurnedOnTimer, false); + active |= !resetTimerIfNotNull(mVideoTurnedOnTimer, false); + active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false); + active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false); + active |= !resetTimerIfNotNull(mForegroundActivityTimer, false); + active |= !resetTimerIfNotNull(mBluetoothScanTimer, false); + if (mProcessStateTimer != null) { for (int i = 0; i < NUM_PROCESS_STATE; i++) { if (mProcessStateTimer[i] != null) { @@ -5749,6 +6059,9 @@ public class BatteryStatsImpl extends BatteryStats { } } + resetLongCounterIfNotNull(mMobileRadioApWakeupCount, false); + resetLongCounterIfNotNull(mWifiRadioApWakeupCount, false); + final ArrayMap wakeStats = mWakelockStats.getMap(); for (int iw=wakeStats.size()-1; iw>=0; iw--) { Wakelock wl = wakeStats.valueAt(iw); @@ -5908,6 +6221,9 @@ public class BatteryStatsImpl extends BatteryStats { } } } + + detachLongCounterIfNotNull(mMobileRadioApWakeupCount); + detachLongCounterIfNotNull(mWifiRadioApWakeupCount); } return !active; @@ -6114,6 +6430,20 @@ public class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } + + if (mMobileRadioApWakeupCount != null) { + out.writeInt(1); + mMobileRadioApWakeupCount.writeToParcel(out); + } else { + out.writeInt(0); + } + + if (mWifiRadioApWakeupCount != null) { + out.writeInt(1); + mWifiRadioApWakeupCount.writeToParcel(out); + } else { + out.writeInt(0); + } } void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) { @@ -6338,6 +6668,18 @@ public class BatteryStatsImpl extends BatteryStats { } else { mCpuClusterSpeed = null; } + + if (in.readInt() != 0) { + mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in); + } else { + mMobileRadioApWakeupCount = null; + } + + if (in.readInt() != 0) { + mWifiRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in); + } else { + mWifiRadioApWakeupCount = null; + } } /** @@ -6357,7 +6699,7 @@ public class BatteryStatsImpl extends BatteryStats { /** * How long (in ms) this uid has been keeping the device partially awake. */ - StopwatchTimer mTimerPartial; + DurationTimer mTimerPartial; /** * How long (in ms) this uid has been keeping the device fully awake. @@ -6386,8 +6728,8 @@ public class BatteryStatsImpl extends BatteryStats { * @param in the Parcel to be read from. * return a new Timer, or null. */ - private StopwatchTimer readTimerFromParcel(int type, ArrayList pool, - TimeBase timeBase, Parcel in) { + private StopwatchTimer readStopwatchTimerFromParcel(int type, + ArrayList pool, TimeBase timeBase, Parcel in) { if (in.readInt() == 0) { return null; } @@ -6395,6 +6737,22 @@ public class BatteryStatsImpl extends BatteryStats { return new StopwatchTimer(mBsi.mClocks, mUid, type, pool, timeBase, in); } + /** + * Reads a possibly null Timer from a Parcel. The timer is associated with the + * proper timer pool from the given BatteryStatsImpl object. + * + * @param in the Parcel to be read from. + * return a new Timer, or null. + */ + private DurationTimer readDurationTimerFromParcel(int type, + ArrayList pool, TimeBase timeBase, Parcel in) { + if (in.readInt() == 0) { + return null; + } + + return new DurationTimer(mBsi.mClocks, mUid, type, pool, timeBase, in); + } + boolean reset() { boolean wlactive = false; if (mTimerFull != null) { @@ -6431,11 +6789,14 @@ public class BatteryStatsImpl extends BatteryStats { } void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) { - mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, + mTimerPartial = readDurationTimerFromParcel(WAKE_TYPE_PARTIAL, mBsi.mPartialTimers, screenOffTimeBase, in); - mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, mBsi.mFullTimers, timeBase, in); - mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, mBsi.mWindowTimers, timeBase, in); - mTimerDraw = readTimerFromParcel(WAKE_TYPE_DRAW, mBsi.mDrawTimers, timeBase, in); + mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL, + mBsi.mFullTimers, timeBase, in); + mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW, + mBsi.mWindowTimers, timeBase, in); + mTimerDraw = readStopwatchTimerFromParcel(WAKE_TYPE_DRAW, + mBsi.mDrawTimers, timeBase, in); } void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) { @@ -6457,40 +6818,43 @@ public class BatteryStatsImpl extends BatteryStats { } public StopwatchTimer getStopwatchTimer(int type) { - StopwatchTimer t; switch (type) { - case WAKE_TYPE_PARTIAL: - t = mTimerPartial; + case WAKE_TYPE_PARTIAL: { + DurationTimer t = mTimerPartial; if (t == null) { - t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL, + t = new DurationTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL, mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase); mTimerPartial = t; } return t; - case WAKE_TYPE_FULL: - t = mTimerFull; + } + case WAKE_TYPE_FULL: { + StopwatchTimer t = mTimerFull; if (t == null) { t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL, mBsi.mFullTimers, mBsi.mOnBatteryTimeBase); mTimerFull = t; } return t; - case WAKE_TYPE_WINDOW: - t = mTimerWindow; + } + case WAKE_TYPE_WINDOW: { + StopwatchTimer t = mTimerWindow; if (t == null) { t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW, mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase); mTimerWindow = t; } return t; - case WAKE_TYPE_DRAW: - t = mTimerDraw; + } + case WAKE_TYPE_DRAW: { + StopwatchTimer t = mTimerDraw; if (t == null) { t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW, mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase); mTimerDraw = t; } return t; + } default: throw new IllegalArgumentException("type=" + type); } @@ -10348,8 +10712,22 @@ public class BatteryStatsImpl extends BatteryStats { u.mCpuClusterSpeed = null; } + if (in.readInt() != 0) { + u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase); + u.mMobileRadioApWakeupCount.readSummaryFromParcelLocked(in); + } else { + u.mMobileRadioApWakeupCount = null; + } + + if (in.readInt() != 0) { + u.mWifiRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase); + u.mWifiRadioApWakeupCount.readSummaryFromParcelLocked(in); + } else { + u.mWifiRadioApWakeupCount = null; + } + int NW = in.readInt(); - if (NW > 100) { + if (NW > (MAX_WAKELOCKS_PER_UID+1)) { throw new ParcelFormatException("File corrupt: too many wake locks " + NW); } for (int iw = 0; iw < NW; iw++) { @@ -10358,7 +10736,7 @@ public class BatteryStatsImpl extends BatteryStats { } int NS = in.readInt(); - if (NS > 100) { + if (NS > (MAX_WAKELOCKS_PER_UID+1)) { throw new ParcelFormatException("File corrupt: too many syncs " + NS); } for (int is = 0; is < NS; is++) { @@ -10367,7 +10745,7 @@ public class BatteryStatsImpl extends BatteryStats { } int NJ = in.readInt(); - if (NJ > 100) { + if (NJ > (MAX_WAKELOCKS_PER_UID+1)) { throw new ParcelFormatException("File corrupt: too many job timers " + NJ); } for (int ij = 0; ij < NJ; ij++) { @@ -10708,6 +11086,20 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } + if (u.mMobileRadioApWakeupCount != null) { + out.writeInt(1); + u.mMobileRadioApWakeupCount.writeSummaryFromParcelLocked(out); + } else { + out.writeInt(0); + } + + if (u.mWifiRadioApWakeupCount != null) { + out.writeInt(1); + u.mWifiRadioApWakeupCount.writeSummaryFromParcelLocked(out); + } else { + out.writeInt(0); + } + final ArrayMap wakeStats = u.mWakelockStats.getMap(); int NW = wakeStats.size(); out.writeInt(NW); diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index c828d11fd3d20e7bbdc3d1817441b86a6cdc3924..e8919ede82b52bd5553972d75c290bf896755682 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -120,7 +120,7 @@ public class KernelUidCpuTimeReader { sb.append(" s="); TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb); sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms"); - Slog.wtf(TAG, sb.toString()); + Slog.e(TAG, sb.toString()); userTimeDeltaUs = 0; systemTimeDeltaUs = 0; diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java index b7e57187108671eff54c79031e481f943b00bf89..e46dfc4e0cb65102193a195141548c20809d23ec 100644 --- a/core/java/com/android/internal/os/ProcessCpuTracker.java +++ b/core/java/com/android/internal/os/ProcessCpuTracker.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; +import java.util.List; import java.util.StringTokenizer; public class ProcessCpuTracker { @@ -177,6 +178,11 @@ public class ProcessCpuTracker { private byte[] mBuffer = new byte[4096]; + public interface FilterStats { + /** Which stats to pick when filtering */ + boolean needed(Stats stats); + } + public static class Stats { public final int pid; public final int uid; @@ -695,6 +701,18 @@ public class ProcessCpuTracker { return mProcStats.get(index); } + final public List getStats(FilterStats filter) { + final ArrayList statses = new ArrayList<>(mProcStats.size()); + final int N = mProcStats.size(); + for (int p = 0; p < N; p++) { + Stats stats = mProcStats.get(p); + if (filter.needed(stats)) { + statses.add(stats); + } + } + return statses; + } + final public int countWorkingStats() { buildWorkingProcs(); return mWorkingProcs.size(); diff --git a/core/java/com/android/internal/os/TransferPipe.java b/core/java/com/android/internal/os/TransferPipe.java index f9041507ffddca94a7ea34777fdce314b00de67e..e76b395e9e2d4d55045937a7db5eecb3aee51def 100644 --- a/core/java/com/android/internal/os/TransferPipe.java +++ b/core/java/com/android/internal/os/TransferPipe.java @@ -16,7 +16,6 @@ package com.android.internal.os; -import java.io.Closeable; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -33,13 +32,13 @@ import android.util.Slog; /** * Helper for transferring data through a pipe from a client app. */ -public final class TransferPipe implements Runnable, Closeable { +public final class TransferPipe implements Runnable { static final String TAG = "TransferPipe"; static final boolean DEBUG = false; static final long DEFAULT_TIMEOUT = 5000; // 5 seconds - final Thread mThread; + final Thread mThread;; final ParcelFileDescriptor[] mFds; FileDescriptor mOutFd; @@ -55,13 +54,8 @@ public final class TransferPipe implements Runnable, Closeable { } public TransferPipe() throws IOException { - this(null); - } - - public TransferPipe(String bufferPrefix) throws IOException { mThread = new Thread(this, "TransferPipe"); mFds = ParcelFileDescriptor.createPipe(); - mBufferPrefix = bufferPrefix; } ParcelFileDescriptor getReadFd() { @@ -76,11 +70,6 @@ public final class TransferPipe implements Runnable, Closeable { mBufferPrefix = prefix; } - public static void dumpAsync(IBinder binder, FileDescriptor out, String[] args) - throws IOException, RemoteException { - goDump(binder, out, args); - } - static void go(Caller caller, IInterface iface, FileDescriptor out, String prefix, String[] args) throws IOException, RemoteException { go(caller, iface, out, prefix, args, DEFAULT_TIMEOUT); @@ -97,9 +86,12 @@ public final class TransferPipe implements Runnable, Closeable { return; } - try (TransferPipe tp = new TransferPipe()) { + TransferPipe tp = new TransferPipe(); + try { caller.go(iface, tp.getWriteFd().getFileDescriptor(), prefix, args); tp.go(out, timeout); + } finally { + tp.kill(); } } @@ -119,9 +111,12 @@ public final class TransferPipe implements Runnable, Closeable { return; } - try (TransferPipe tp = new TransferPipe()) { + TransferPipe tp = new TransferPipe(); + try { binder.dumpAsync(tp.getWriteFd().getFileDescriptor(), args); tp.go(out, timeout); + } finally { + tp.kill(); } } @@ -178,11 +173,6 @@ public final class TransferPipe implements Runnable, Closeable { } } - @Override - public void close() { - kill(); - } - public void kill() { synchronized (this) { closeFd(0); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 9979b84dc9c0b0bbc19059c5f9d4e8bd51531016..e1118d84ed7b4226a6dc7efca4e0500eff22b610 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -502,21 +502,42 @@ public class ZygoteInit { // System server is fully AOTed and never profiled // for profile guided compilation. // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING? - final int dexoptNeeded = DexFile.getDexOptNeeded( + + int dexoptNeeded; + try { + dexoptNeeded = DexFile.getDexOptNeeded( classPathElement, instructionSet, "speed", false /* newProfile */); + } catch (FileNotFoundException ignored) { + // Do not add to the classpath. + Log.w(TAG, "Missing classpath element for system server: " + classPathElement); + continue; + } catch (IOException e) { + // Not fully clear what to do here as we don't know the cause of the + // IO exception. Add to the classpath to be conservative, but don't + // attempt to compile it. + Log.w(TAG, "Error checking classpath element for system server: " + + classPathElement, e); + dexoptNeeded = DexFile.NO_DEXOPT_NEEDED; + } + if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) { - installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet, - dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/, - sharedLibraries); + try { + installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet, + dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/, + sharedLibraries); + } catch (InstallerException e) { + // Ignore (but log), we need this on the classpath for fallback mode. + Log.w(TAG, "Failed compiling classpath element for system server: " + + classPathElement, e); + } } + if (!sharedLibraries.isEmpty()) { sharedLibraries += ":"; } sharedLibraries += classPathElement; } - } catch (IOException | InstallerException e) { - throw new RuntimeException("Error starting system_server", e); } finally { installer.disconnect(); } @@ -678,7 +699,7 @@ public class ZygoteInit { zygoteServer.closeServerSocket(); } catch (Zygote.MethodAndArgsCaller caller) { caller.run(); - } catch (RuntimeException ex) { + } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); zygoteServer.closeServerSocket(); throw ex; diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java index 488f769cdf3182188d95d33e444033a922eb8ec0..1abb59b006dd97382faabbeb7b7154e103495df7 100644 --- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java +++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java @@ -110,12 +110,15 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame int statusBarColor, int navigationBarColor) { mDecorView = decorView; mResizingBackgroundDrawable = resizingBackgroundDrawable != null + && resizingBackgroundDrawable.getConstantState() != null ? resizingBackgroundDrawable.getConstantState().newDrawable() : null; mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable != null + && captionBackgroundDrawableDrawable.getConstantState() != null ? captionBackgroundDrawableDrawable.getConstantState().newDrawable() : null; mUserCaptionBackgroundDrawable = userCaptionBackgroundDrawable != null + && userCaptionBackgroundDrawable.getConstantState() != null ? userCaptionBackgroundDrawable.getConstantState().newDrawable() : null; if (mCaptionBackgroundDrawable == null) { @@ -371,6 +374,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame systemInsets.bottom); final int rightInset = DecorView.getColorViewRightInset(stableInsets.right, systemInsets.right); + final int leftInset = DecorView.getColorViewLeftInset(stableInsets.left, + systemInsets.left); if (mStatusBarColor != null) { mStatusBarColor.setBounds(0, 0, left + width, topInset); mStatusBarColor.draw(canvas); @@ -380,9 +385,11 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame // don't want the navigation bar background be moving around when resizing in docked mode. // However, we need it for the transitions into/out of docked mode. if (mNavigationBarColor != null && fullscreen) { - final int size = DecorView.getNavBarSize(bottomInset, rightInset); + final int size = DecorView.getNavBarSize(bottomInset, rightInset, leftInset); if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) { mNavigationBarColor.setBounds(width - size, 0, width, height); + } else if (DecorView.isNavBarToLeftEdge(bottomInset, leftInset)) { + mNavigationBarColor.setBounds(0, 0, size, height); } else { mNavigationBarColor.setBounds(0, height - size, width, height); } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 3cf7a4e6b9ecc75f52493fd0203e2531f9cfdea8..92ab3246e354b3e427369f5701ddd836fe4332e6 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -97,11 +97,11 @@ import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACK import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; -import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL; /** @hide */ @@ -162,13 +162,13 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private final ColorViewState mStatusColorViewState = new ColorViewState( SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS, - Gravity.TOP, Gravity.LEFT, + Gravity.TOP, Gravity.LEFT, Gravity.RIGHT, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME, com.android.internal.R.id.statusBarBackground, FLAG_FULLSCREEN); private final ColorViewState mNavigationColorViewState = new ColorViewState( SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION, - Gravity.BOTTOM, Gravity.RIGHT, + Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME, com.android.internal.R.id.navigationBarBackground, 0 /* hideWindowFlag */); @@ -184,9 +184,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private int mLastTopInset = 0; private int mLastBottomInset = 0; private int mLastRightInset = 0; + private int mLastLeftInset = 0; private boolean mLastHasTopStableInset = false; private boolean mLastHasBottomStableInset = false; private boolean mLastHasRightStableInset = false; + private boolean mLastHasLeftStableInset = false; private int mLastWindowFlags = 0; private boolean mLastShouldAlwaysConsumeNavBar = false; @@ -991,12 +993,21 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind return Math.min(stableRight, systemRight); } + static int getColorViewLeftInset(int stableLeft, int systemLeft) { + return Math.min(stableLeft, systemLeft); + } + static boolean isNavBarToRightEdge(int bottomInset, int rightInset) { return bottomInset == 0 && rightInset > 0; } - static int getNavBarSize(int bottomInset, int rightInset) { - return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset : bottomInset; + static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) { + return bottomInset == 0 && leftInset > 0; + } + + static int getNavBarSize(int bottomInset, int rightInset, int leftInset) { + return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset + : isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset; } WindowInsets updateColorViews(WindowInsets insets, boolean animate) { @@ -1016,6 +1027,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind insets.getSystemWindowInsetBottom()); mLastRightInset = getColorViewRightInset(insets.getStableInsetRight(), insets.getSystemWindowInsetRight()); + mLastLeftInset = getColorViewRightInset(insets.getStableInsetLeft(), + insets.getSystemWindowInsetLeft()); // Don't animate if the presence of stable insets has changed, because that // indicates that the window was either just added and received them for the @@ -1031,21 +1044,32 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind boolean hasRightStableInset = insets.getStableInsetRight() != 0; disallowAnimate |= (hasRightStableInset != mLastHasRightStableInset); mLastHasRightStableInset = hasRightStableInset; + + boolean hasLeftStableInset = insets.getStableInsetLeft() != 0; + disallowAnimate |= (hasLeftStableInset != mLastHasLeftStableInset); + mLastHasLeftStableInset = hasLeftStableInset; + mLastShouldAlwaysConsumeNavBar = insets.shouldAlwaysConsumeNavBar(); } boolean navBarToRightEdge = isNavBarToRightEdge(mLastBottomInset, mLastRightInset); - int navBarSize = getNavBarSize(mLastBottomInset, mLastRightInset); + boolean navBarToLeftEdge = isNavBarToLeftEdge(mLastBottomInset, mLastLeftInset); + int navBarSize = getNavBarSize(mLastBottomInset, mLastRightInset, mLastLeftInset); updateColorViewInt(mNavigationColorViewState, sysUiVisibility, - mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge, - 0 /* rightInset */, animate && !disallowAnimate, false /* force */); + mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge || navBarToLeftEdge, + navBarToLeftEdge, + 0 /* sideInset */, animate && !disallowAnimate, false /* force */); boolean statusBarNeedsRightInset = navBarToRightEdge && mNavigationColorViewState.present; - int statusBarRightInset = statusBarNeedsRightInset ? mLastRightInset : 0; + boolean statusBarNeedsLeftInset = navBarToLeftEdge + && mNavigationColorViewState.present; + int statusBarSideInset = statusBarNeedsRightInset ? mLastRightInset + : statusBarNeedsLeftInset ? mLastLeftInset : 0; updateColorViewInt(mStatusColorViewState, sysUiVisibility, calculateStatusBarColor(), mLastTopInset, - false /* matchVertical */, statusBarRightInset, animate && !disallowAnimate, + false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset, + animate && !disallowAnimate, mForceWindowDrawsStatusBarBackground); } @@ -1070,15 +1094,17 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind int consumedTop = consumingStatusBar ? mLastTopInset : 0; int consumedRight = consumingNavBar ? mLastRightInset : 0; int consumedBottom = consumingNavBar ? mLastBottomInset : 0; + int consumedLeft = consumingNavBar ? mLastLeftInset : 0; if (mContentRoot != null && mContentRoot.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams lp = (MarginLayoutParams) mContentRoot.getLayoutParams(); if (lp.topMargin != consumedTop || lp.rightMargin != consumedRight - || lp.bottomMargin != consumedBottom) { + || lp.bottomMargin != consumedBottom || lp.leftMargin != consumedLeft) { lp.topMargin = consumedTop; lp.rightMargin = consumedRight; lp.bottomMargin = consumedBottom; + lp.leftMargin = consumedLeft; mContentRoot.setLayoutParams(lp); if (insets == null) { @@ -1089,7 +1115,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } if (insets != null) { insets = insets.replaceSystemWindowInsets( - insets.getSystemWindowInsetLeft(), + insets.getSystemWindowInsetLeft() - consumedLeft, insets.getSystemWindowInsetTop() - consumedTop, insets.getSystemWindowInsetRight() - consumedRight, insets.getSystemWindowInsetBottom() - consumedBottom); @@ -1126,11 +1152,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind * @param size the current size in the non-parent-matching dimension. * @param verticalBar if true the view is attached to a vertical edge, otherwise to a * horizontal edge, - * @param rightMargin rightMargin for the color view. + * @param sideMargin sideMargin for the color view. * @param animate if true, the change will be animated. */ private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color, - int size, boolean verticalBar, int rightMargin, boolean animate, boolean force) { + int size, boolean verticalBar, boolean seascape, int sideMargin, + boolean animate, boolean force) { state.present = (sysUiVis & state.systemUiHideFlag) == 0 && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0 && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 @@ -1145,7 +1172,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size; int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT; - int resolvedGravity = verticalBar ? state.horizontalGravity : state.verticalGravity; + int resolvedGravity = verticalBar + ? (seascape ? state.seascapeGravity : state.horizontalGravity) + : state.verticalGravity; if (view == null) { if (showView) { @@ -1159,7 +1188,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind LayoutParams lp = new LayoutParams(resolvedWidth, resolvedHeight, resolvedGravity); - lp.rightMargin = rightMargin; + if (seascape) { + lp.leftMargin = sideMargin; + } else { + lp.rightMargin = sideMargin; + } addView(view, lp); updateColorViewTranslations(); } @@ -1168,12 +1201,16 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind visibilityChanged = state.targetVisibility != vis; state.targetVisibility = vis; LayoutParams lp = (LayoutParams) view.getLayoutParams(); + int rightMargin = seascape ? 0 : sideMargin; + int leftMargin = seascape ? sideMargin : 0; if (lp.height != resolvedHeight || lp.width != resolvedWidth - || lp.gravity != resolvedGravity || lp.rightMargin != rightMargin) { + || lp.gravity != resolvedGravity || lp.rightMargin != rightMargin + || lp.leftMargin != leftMargin) { lp.height = resolvedHeight; lp.width = resolvedWidth; lp.gravity = resolvedGravity; lp.rightMargin = rightMargin; + lp.leftMargin = leftMargin; view.setLayoutParams(lp); } if (showView) { @@ -1824,7 +1861,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } final WindowManager.LayoutParams attrs = mWindow.getAttributes(); final boolean isApplication = attrs.type == TYPE_BASE_APPLICATION || - attrs.type == TYPE_APPLICATION; + attrs.type == TYPE_APPLICATION || attrs.type == TYPE_DRAWN_APPLICATION; // Only a non floating application window on one of the allowed workspaces can get a caption if (!mWindow.isFloating() && isApplication && StackId.hasWindowDecor(mStackId)) { // Dependent on the brightness of the used title we either use the @@ -2217,17 +2254,19 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final int translucentFlag; final int verticalGravity; final int horizontalGravity; + final int seascapeGravity; final String transitionName; final int hideWindowFlag; ColorViewState(int systemUiHideFlag, int translucentFlag, int verticalGravity, int horizontalGravity, - String transitionName, int id, int hideWindowFlag) { + int seascapeGravity, String transitionName, int id, int hideWindowFlag) { this.id = id; this.systemUiHideFlag = systemUiHideFlag; this.translucentFlag = translucentFlag; this.verticalGravity = verticalGravity; this.horizontalGravity = horizontalGravity; + this.seascapeGravity = seascapeGravity; this.transitionName = transitionName; this.hideWindowFlag = hideWindowFlag; } diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl index 171a264eea8b2c4bc210b3e8ed4930c2290e04fd..e51ad3f737b8ecb73f824e9d710b42a65e500491 100644 --- a/core/java/com/android/internal/policy/IKeyguardService.aidl +++ b/core/java/com/android/internal/policy/IKeyguardService.aidl @@ -28,13 +28,14 @@ oneway interface IKeyguardService { * FLAG_SHOW_ON_LOCK_SCREEN. * * @param isOccluded Whether the Keyguard is occluded by another window. + * @param animate Whether to play an animation for the state change. */ - void setOccluded(boolean isOccluded); + void setOccluded(boolean isOccluded, boolean animate); void addStateMonitorCallback(IKeyguardStateCallback callback); void verifyUnlock(IKeyguardExitCallback callback); void keyguardDone(boolean authenticated, boolean wakeup); - void dismiss(); + void dismiss(boolean allowWhileOccluded); void onDreamingStarted(); void onDreamingStopped(); diff --git a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl index db3b40b29903e62822a5179490e63e9a69207ce6..8e454db4cb040146664e9e58f5c0829680ead6eb 100644 --- a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl +++ b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl @@ -19,4 +19,6 @@ interface IKeyguardStateCallback { void onShowingStateChanged(boolean showing); void onSimSecureStateChanged(boolean simSecure); void onInputRestrictedStateChanged(boolean inputRestricted); + void onTrustedChanged(boolean trusted); + void onHasLockscreenWallpaperChanged(boolean hasLockscreenWallpaper); } \ No newline at end of file diff --git a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java index 2cb9c250d2d171666397bb19ee2ad79faad5f648..fb0edea398cee25efbe6cc4bcd792fd3677ea0be 100644 --- a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java +++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java @@ -150,6 +150,7 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { sendCloseSystemWindows(); // Broadcast an intent that the Camera button was longpressed Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_KEY_EVENT, event); mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF, null, null, null, 0, null, null); diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 9ad750d3a59945c280f753872f4fa17ac6f64bb9..878f3a69a504bd3f329c01f53fcf2c98108c54ea 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -92,8 +92,6 @@ import android.util.EventLog; import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityNodeProvider; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.FrameLayout; @@ -2057,9 +2055,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } static private final String FOCUSED_ID_TAG = "android:focusedViewId"; - static private final String ACCESSIBILITY_FOCUSED_ID_TAG = "android:accessibilityFocusedViewId"; - static private final String ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG = - "android:accessibilityFocusedVirtualViewId"; static private final String VIEWS_TAG = "android:views"; static private final String PANELS_TAG = "android:Panels"; static private final String ACTION_BAR_TAG = "android:ActionBar"; @@ -2082,26 +2077,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { outState.putInt(FOCUSED_ID_TAG, focusedView.getId()); } - // Save the accessibility focused view ID. - if (mDecor != null) { - final ViewRootImpl viewRootImpl = mDecor.getViewRootImpl(); - if (viewRootImpl != null) { - final View accessFocusHost = viewRootImpl.getAccessibilityFocusedHost(); - if (accessFocusHost != null && accessFocusHost.getId() != View.NO_ID) { - outState.putInt(ACCESSIBILITY_FOCUSED_ID_TAG, accessFocusHost.getId()); - - // If we have a focused virtual node ID, save that too. - final AccessibilityNodeInfo accessFocusedNode = - viewRootImpl.getAccessibilityFocusedVirtualView(); - if (accessFocusedNode != null) { - final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId( - accessFocusedNode.getSourceNodeId()); - outState.putInt(ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, virtualNodeId); - } - } - } - } - // save the panels SparseArray panelStates = new SparseArray(); savePanelState(panelStates); @@ -2144,13 +2119,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } - // Restore the accessibility focused view. - final int accessFocusHostViewId = savedInstanceState.getInt( - ACCESSIBILITY_FOCUSED_ID_TAG, View.NO_ID); - final int accessFocusVirtualViewId = savedInstanceState.getInt( - ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, AccessibilityNodeInfo.UNDEFINED_ITEM_ID); - tryRestoreAccessibilityFocus(accessFocusHostViewId, accessFocusVirtualViewId); - // Restore the panels. SparseArray panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG); if (panelStates != null) { @@ -2170,33 +2138,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } - private void tryRestoreAccessibilityFocus(int hostViewId, int virtualViewId) { - if (hostViewId != View.NO_ID && mDecor != null) { - final View needsAccessFocus = mDecor.findViewById(hostViewId); - if (needsAccessFocus != null) { - if (!tryFocusingVirtualView(needsAccessFocus, virtualViewId) - && !needsAccessFocus.requestAccessibilityFocus()) { - Log.w(TAG, "Failed to restore focus to previously accessibility" - + " focused view with id " + hostViewId); - } - } else { - Log.w(TAG, "Previously accessibility focused view reported id " + hostViewId - + " during save, but can't be found during restore."); - } - } - } - - private boolean tryFocusingVirtualView(View host, int virtualViewId) { - if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { - final AccessibilityNodeProvider nodeProvider = host.getAccessibilityNodeProvider(); - if (nodeProvider != null) { - return nodeProvider.performAction(virtualViewId, - AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); - } - } - return false; - } - /** * Invoked when the panels should freeze their state. * diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 7706ff7f173ffe4e48d5727b7af48f35dc89dc2d..20f10b33343b197ec22a523507e4a39b6ee5f497 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -112,4 +112,5 @@ oneway interface IStatusBar void addQsTile(in ComponentName tile); void remQsTile(in ComponentName tile); void clickQsTile(in ComponentName tile); + void handleSystemNavigationKey(in int key); } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 3d054225d2342b0ec4480683f949044cc0c1525b..698e387175fbc719a4cdff2378c52edb75d206f7 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -66,4 +66,5 @@ interface IStatusBarService void addTile(in ComponentName tile); void remTile(in ComponentName tile); void clickTile(in ComponentName tile); + void handleSystemNavigationKey(in int key); } diff --git a/core/java/com/android/internal/util/MimeIconUtils.java b/core/java/com/android/internal/util/MimeIconUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..841ec7ca994ceca849f47b29be8291a392cf4559 --- /dev/null +++ b/core/java/com/android/internal/util/MimeIconUtils.java @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.provider.DocumentsContract; + +import com.android.internal.R; + +import java.util.HashMap; + +public class MimeIconUtils { + + private static HashMap sMimeIcons = new HashMap<>(); + + private static void add(String mimeType, int resId) { + if (sMimeIcons.put(mimeType, resId) != null) { + throw new RuntimeException(mimeType + " already registered!"); + } + } + + static { + int icon; + + // Package + icon = R.drawable.ic_doc_apk; + add("application/vnd.android.package-archive", icon); + + // Audio + icon = R.drawable.ic_doc_audio; + add("application/ogg", icon); + add("application/x-flac", icon); + + // Certificate + icon = R.drawable.ic_doc_certificate; + add("application/pgp-keys", icon); + add("application/pgp-signature", icon); + add("application/x-pkcs12", icon); + add("application/x-pkcs7-certreqresp", icon); + add("application/x-pkcs7-crl", icon); + add("application/x-x509-ca-cert", icon); + add("application/x-x509-user-cert", icon); + add("application/x-pkcs7-certificates", icon); + add("application/x-pkcs7-mime", icon); + add("application/x-pkcs7-signature", icon); + + // Source code + icon = R.drawable.ic_doc_codes; + add("application/rdf+xml", icon); + add("application/rss+xml", icon); + add("application/x-object", icon); + add("application/xhtml+xml", icon); + add("text/css", icon); + add("text/html", icon); + add("text/xml", icon); + add("text/x-c++hdr", icon); + add("text/x-c++src", icon); + add("text/x-chdr", icon); + add("text/x-csrc", icon); + add("text/x-dsrc", icon); + add("text/x-csh", icon); + add("text/x-haskell", icon); + add("text/x-java", icon); + add("text/x-literate-haskell", icon); + add("text/x-pascal", icon); + add("text/x-tcl", icon); + add("text/x-tex", icon); + add("application/x-latex", icon); + add("application/x-texinfo", icon); + add("application/atom+xml", icon); + add("application/ecmascript", icon); + add("application/json", icon); + add("application/javascript", icon); + add("application/xml", icon); + add("text/javascript", icon); + add("application/x-javascript", icon); + + // Compressed + icon = R.drawable.ic_doc_compressed; + add("application/mac-binhex40", icon); + add("application/rar", icon); + add("application/zip", icon); + add("application/x-apple-diskimage", icon); + add("application/x-debian-package", icon); + add("application/x-gtar", icon); + add("application/x-iso9660-image", icon); + add("application/x-lha", icon); + add("application/x-lzh", icon); + add("application/x-lzx", icon); + add("application/x-stuffit", icon); + add("application/x-tar", icon); + add("application/x-webarchive", icon); + add("application/x-webarchive-xml", icon); + add("application/gzip", icon); + add("application/x-7z-compressed", icon); + add("application/x-deb", icon); + add("application/x-rar-compressed", icon); + + // Contact + icon = R.drawable.ic_doc_contact; + add("text/x-vcard", icon); + add("text/vcard", icon); + + // Event + icon = R.drawable.ic_doc_event; + add("text/calendar", icon); + add("text/x-vcalendar", icon); + + // Font + icon = R.drawable.ic_doc_font; + add("application/x-font", icon); + add("application/font-woff", icon); + add("application/x-font-woff", icon); + add("application/x-font-ttf", icon); + + // Image + icon = R.drawable.ic_doc_image; + add("application/vnd.oasis.opendocument.graphics", icon); + add("application/vnd.oasis.opendocument.graphics-template", icon); + add("application/vnd.oasis.opendocument.image", icon); + add("application/vnd.stardivision.draw", icon); + add("application/vnd.sun.xml.draw", icon); + add("application/vnd.sun.xml.draw.template", icon); + + // PDF + icon = R.drawable.ic_doc_pdf; + add("application/pdf", icon); + + // Presentation + icon = R.drawable.ic_doc_presentation; + add("application/vnd.stardivision.impress", icon); + add("application/vnd.sun.xml.impress", icon); + add("application/vnd.sun.xml.impress.template", icon); + add("application/x-kpresenter", icon); + add("application/vnd.oasis.opendocument.presentation", icon); + + // Spreadsheet + icon = R.drawable.ic_doc_spreadsheet; + add("application/vnd.oasis.opendocument.spreadsheet", icon); + add("application/vnd.oasis.opendocument.spreadsheet-template", icon); + add("application/vnd.stardivision.calc", icon); + add("application/vnd.sun.xml.calc", icon); + add("application/vnd.sun.xml.calc.template", icon); + add("application/x-kspread", icon); + + // Document + icon = R.drawable.ic_doc_document; + add("application/vnd.oasis.opendocument.text", icon); + add("application/vnd.oasis.opendocument.text-master", icon); + add("application/vnd.oasis.opendocument.text-template", icon); + add("application/vnd.oasis.opendocument.text-web", icon); + add("application/vnd.stardivision.writer", icon); + add("application/vnd.stardivision.writer-global", icon); + add("application/vnd.sun.xml.writer", icon); + add("application/vnd.sun.xml.writer.global", icon); + add("application/vnd.sun.xml.writer.template", icon); + add("application/x-abiword", icon); + add("application/x-kword", icon); + + // Video + icon = R.drawable.ic_doc_video; + add("application/x-quicktimeplayer", icon); + add("application/x-shockwave-flash", icon); + + // Word + icon = R.drawable.ic_doc_word; + add("application/msword", icon); + add("application/vnd.openxmlformats-officedocument.wordprocessingml.document", icon); + add("application/vnd.openxmlformats-officedocument.wordprocessingml.template", icon); + + // Excel + icon = R.drawable.ic_doc_excel; + add("application/vnd.ms-excel", icon); + add("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", icon); + add("application/vnd.openxmlformats-officedocument.spreadsheetml.template", icon); + + // Powerpoint + icon = R.drawable.ic_doc_powerpoint; + add("application/vnd.ms-powerpoint", icon); + add("application/vnd.openxmlformats-officedocument.presentationml.presentation", icon); + add("application/vnd.openxmlformats-officedocument.presentationml.template", icon); + add("application/vnd.openxmlformats-officedocument.presentationml.slideshow", icon); + } + + public static Drawable loadMimeIcon(Context context, String mimeType) { + if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) { + return context.getDrawable(R.drawable.ic_doc_folder); + } + + // Look for exact match first + Integer resId = sMimeIcons.get(mimeType); + if (resId != null) { + return context.getDrawable(resId); + } + + if (mimeType == null) { + // TODO: generic icon? + return null; + } + + // Otherwise look for partial match + final String typeOnly = mimeType.split("/")[0]; + if ("audio".equals(typeOnly)) { + return context.getDrawable(R.drawable.ic_doc_audio); + } else if ("image".equals(typeOnly)) { + return context.getDrawable(R.drawable.ic_doc_image); + } else if ("text".equals(typeOnly)) { + return context.getDrawable(R.drawable.ic_doc_text); + } else if ("video".equals(typeOnly)) { + return context.getDrawable(R.drawable.ic_doc_video); + } else { + return context.getDrawable(R.drawable.ic_doc_generic); + } + } +} diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java index 48bcc09301648ab2f9ef85b99a40050d1a3bf06e..4748e6fb19ff0f9d21d4c6de42ebebb429aaa386 100644 --- a/core/java/com/android/internal/util/NotificationColorUtil.java +++ b/core/java/com/android/internal/util/NotificationColorUtil.java @@ -271,7 +271,7 @@ public class NotificationColorUtil { * Finds a text color with sufficient contrast over bg that has the same hue as the original * color, assuming it is for large text. */ - private static int ensureLargeTextContrast(int color, int bg) { + public static int ensureLargeTextContrast(int color, int bg) { return findContrastColor(color, bg, true, 3); } @@ -340,6 +340,20 @@ public class NotificationColorUtil { return color; } + /** + * Lighten a color by a specified value + * @param baseColor the base color to lighten + * @param amount the amount to lighten the color from 0 to 100. This corresponds to the L + * increase in the LAB color space. + * @return the lightened color + */ + public static int lightenColor(int baseColor, int amount) { + final double[] result = ColorUtilsFromCompat.getTempDouble3Array(); + ColorUtilsFromCompat.colorToLAB(baseColor, result); + result[0] = Math.min(100, result[0] + amount); + return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]); + } + /** * Framework copy of functions needed from android.support.v4.graphics.ColorUtils. */ @@ -434,7 +448,7 @@ public class NotificationColorUtil { * Convert RGB components to its CIE Lab representative components. * *

      - *
    • outLab[0] is L [0 ...1)
    • + *
    • outLab[0] is L [0 ...100)
    • *
    • outLab[1] is a [-128...127)
    • *
    • outLab[2] is b [-128...127)
    • *
    @@ -516,7 +530,7 @@ public class NotificationColorUtil { * 2° Standard Observer (1931).

    * *
      - *
    • outLab[0] is L [0 ...1)
    • + *
    • outLab[0] is L [0 ...100)
    • *
    • outLab[1] is a [-128...127)
    • *
    • outLab[2] is b [-128...127)
    • *
    @@ -634,7 +648,7 @@ public class NotificationColorUtil { : (XYZ_KAPPA * component + 16) / 116; } - private static double[] getTempDouble3Array() { + public static double[] getTempDouble3Array() { double[] result = TEMP_ARRAY.get(); if (result == null) { result = new double[3]; diff --git a/core/java/com/android/internal/util/WakeupMessage.java b/core/java/com/android/internal/util/WakeupMessage.java index 7d222c74ac3beb246d1c3eb6a8b689ace04a8c30..46098c58108f6d00080b80c4e0c8d9cd31997669 100644 --- a/core/java/com/android/internal/util/WakeupMessage.java +++ b/core/java/com/android/internal/util/WakeupMessage.java @@ -108,7 +108,7 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener { } if (stillScheduled) { Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj); - mHandler.handleMessage(msg); + mHandler.dispatchMessage(msg); msg.recycle(); } } diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java index 31ab26fe4eaf17f0194a0f52f5fd3c4022c1f6b6..831c64698453c7a8d27e8fdaa52fd4aa6340c593 100644 --- a/core/java/com/android/internal/view/FloatingActionMode.java +++ b/core/java/com/android/internal/view/FloatingActionMode.java @@ -26,6 +26,7 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; +import android.util.DisplayMetrics; import com.android.internal.R; import com.android.internal.util.Preconditions; @@ -209,11 +210,9 @@ public class FloatingActionMode extends ActionMode { } private boolean isContentRectWithinBounds() { - mScreenRect.set( - 0, - 0, - mContext.getResources().getDisplayMetrics().widthPixels, - mContext.getResources().getDisplayMetrics().heightPixels); + DisplayMetrics metrics = mContext.getApplicationContext() + .getResources().getDisplayMetrics(); + mScreenRect.set(0, 0, metrics.widthPixels, metrics.heightPixels); return intersectsClosed(mContentRectOnScreen, mScreenRect) && intersectsClosed(mContentRectOnScreen, mViewRectOnScreen); diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index 59b4b35fa24ef16a5f113ef65ff2d03e375893fb..644c7e90f8b024a0ddf41d36ca28db926b7ce988 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -33,6 +33,7 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnectionInspector; import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags; +import android.view.inputmethod.InputContentInfo; public abstract class IInputConnectionWrapper extends IInputContext.Stub { static final String TAG = "IInputConnectionWrapper"; @@ -61,6 +62,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { private static final int DO_CLEAR_META_KEY_STATES = 130; private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140; private static final int DO_CLOSE_CONNECTION = 150; + private static final int DO_COMMIT_CONTENT = 160; @GuardedBy("mLock") @Nullable @@ -241,6 +243,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { dispatchMessage(obtainMessage(DO_CLOSE_CONNECTION)); } + public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts, + int seq, IInputContextCallback callback) { + dispatchMessage(obtainMessageIOOSC(DO_COMMIT_CONTENT, flags, inputContentInfo, opts, seq, + callback)); + } + void dispatchMessage(Message msg) { // If we are calling this from the main thread, then we can call // right through. Otherwise, we need to send the message to the @@ -552,6 +560,41 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } return; } + case DO_COMMIT_CONTENT: { + final int flags = msg.arg1; + final boolean grantUriPermission = + (flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0; + SomeArgs args = (SomeArgs) msg.obj; + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "commitContent on inactive InputConnection"); + args.callback.setCommitContentResult(false, args.seq); + return; + } + final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1; + if (inputContentInfo == null || !inputContentInfo.validate()) { + Log.w(TAG, "commitContent with invalid inputContentInfo=" + + inputContentInfo); + args.callback.setCommitContentResult(false, args.seq); + return; + } + if (grantUriPermission) { + inputContentInfo.requestPermission(); + } + final boolean result = + ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2); + // If this request is not handled, then there is no reason to keep the URI + // permission. + if (grantUriPermission && !result) { + inputContentInfo.releasePermission(); + } + args.callback.setCommitContentResult(result, args.seq); + } catch (RemoteException e) { + Log.w(TAG, "Got RemoteException calling commitContent", e); + } + return; + } } Log.w(TAG, "Unhandled message code: " + msg.what); } @@ -582,12 +625,14 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { return mH.obtainMessage(what, arg1, arg2, args); } - Message obtainMessageOSC(int what, Object arg1, int seq, IInputContextCallback callback) { + Message obtainMessageIOOSC(int what, int arg1, Object objArg1, Object objArg2, int seq, + IInputContextCallback callback) { SomeArgs args = new SomeArgs(); - args.arg1 = arg1; + args.arg1 = objArg1; + args.arg2 = objArg2; args.callback = callback; args.seq = seq; - return mH.obtainMessage(what, 0, 0, args); + return mH.obtainMessage(what, arg1, 0, args); } Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq, diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl index f7ec420ba6769041fc09e54cf92d2e5c9bef0282..728c55786c49c352ed4640d46f01113f1f8b9e3d 100644 --- a/core/java/com/android/internal/view/IInputContext.aidl +++ b/core/java/com/android/internal/view/IInputContext.aidl @@ -21,6 +21,7 @@ import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputContentInfo; import com.android.internal.view.IInputContextCallback; @@ -74,6 +75,9 @@ import com.android.internal.view.IInputContextCallback; void getSelectedText(int flags, int seq, IInputContextCallback callback); - void requestUpdateCursorAnchorInfo(in int cursorUpdateMode, int seq, + void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq, + IInputContextCallback callback); + + void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts, int sec, IInputContextCallback callback); } diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl index 54ea3064bd7e68058c5b307485ac7939ec770524..0f40a83d7ee4b4968f138a86ebfb010d30f74ee5 100644 --- a/core/java/com/android/internal/view/IInputContextCallback.aidl +++ b/core/java/com/android/internal/view/IInputContextCallback.aidl @@ -28,4 +28,5 @@ oneway interface IInputContextCallback { void setExtractedText(in ExtractedText extractedText, int seq); void setSelectedText(CharSequence selectedText, int seq); void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq); + void setCommitContentResult(boolean result, int seq); } diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index cb7c3bfecc89bacea0498fcb482346b2a9673312..9e4b43b6c007dcf8077f8f84a67b4c4ac499a5aa 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -16,11 +16,13 @@ package com.android.internal.view; +import android.net.Uri; import android.os.ResultReceiver; import android.text.style.SuggestionSpan; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.EditorInfo; +import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.view.InputBindResult; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; @@ -81,5 +83,8 @@ interface IInputMethodManager { int getInputMethodWindowVisibleHeight(); void clearLastInputMethodWindowForTransition(in IBinder token); + IInputContentUriToken createInputContentUriToken(in IBinder token, in Uri contentUri, + in String packageName); + oneway void notifyUserAction(int sequenceNumber); } diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java index f9884d85d52cb7337e7cf1633545ce3efa6e735b..9a09dcccd1a7b672f06a64cfea249097d8415ff2 100644 --- a/core/java/com/android/internal/view/InputConnectionWrapper.java +++ b/core/java/com/android/internal/view/InputConnectionWrapper.java @@ -16,6 +16,8 @@ package com.android.internal.view; +import android.annotation.NonNull; +import android.inputmethodservice.AbstractInputMethodService; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; @@ -29,10 +31,16 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnectionInspector; import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags; +import android.view.inputmethod.InputContentInfo; + +import java.lang.ref.WeakReference; public class InputConnectionWrapper implements InputConnection { private static final int MAX_WAIT_TIME_MILLIS = 2000; private final IInputContext mIInputContext; + @NonNull + private final WeakReference mInputMethodService; + @MissingMethodFlags private final int mMissingMethods; @@ -46,7 +54,8 @@ public class InputConnectionWrapper implements InputConnection { public ExtractedText mExtractedText; public int mCursorCapsMode; public boolean mRequestUpdateCursorAnchorInfoResult; - + public boolean mCommitContentResult; + // A 'pool' of one InputContextCallback. Each ICW request will attempt to gain // exclusive access to this object. private static InputContextCallback sInstance = new InputContextCallback(); @@ -172,6 +181,19 @@ public class InputConnectionWrapper implements InputConnection { } } + public void setCommitContentResult(boolean result, int seq) { + synchronized (this) { + if (seq == mSeq) { + mCommitContentResult = result; + mHaveValue = true; + notifyAll(); + } else { + Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq + + ") in setCommitContentResult, ignoring."); + } + } + } + /** * Waits for a result for up to {@link #MAX_WAIT_TIME_MILLIS} milliseconds. * @@ -195,8 +217,10 @@ public class InputConnectionWrapper implements InputConnection { } } - public InputConnectionWrapper(IInputContext inputContext, - @MissingMethodFlags final int missingMethods) { + public InputConnectionWrapper( + @NonNull WeakReference inputMethodService, + IInputContext inputContext, @MissingMethodFlags final int missingMethods) { + mInputMethodService = inputMethodService; mIInputContext = inputContext; mMissingMethods = missingMethods; } @@ -491,6 +515,37 @@ public class InputConnectionWrapper implements InputConnection { // Nothing should happen when called from input method. } + public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) { + boolean result = false; + if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) { + // This method is not implemented. + return false; + } + try { + if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) { + final AbstractInputMethodService inputMethodService = mInputMethodService.get(); + if (inputMethodService == null) { + // This basically should not happen, because it's the the caller of this method. + return false; + } + inputMethodService.exposeContent(inputContentInfo, this); + } + + InputContextCallback callback = InputContextCallback.getInstance(); + mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback); + synchronized (callback) { + callback.waitForResultLocked(); + if (callback.mHaveValue) { + result = callback.mCommitContentResult; + } + } + callback.dispose(); + } catch (RemoteException e) { + return false; + } + return result; + } + private boolean isMethodMissing(@MissingMethodFlags final int methodFlag) { return (mMissingMethods & methodFlag) == methodFlag; } diff --git a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java index 9e2cbdba44d475f2c634049af50d953e8c912351..d28ab078d74a612c663f027961687c2ce2b7589e 100644 --- a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java +++ b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java @@ -30,6 +30,8 @@ import android.view.Choreographer; @HasNativeInterpolator public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator { + // If the duration of an animation is more than 300 frames, we cap the sample size to 300. + private static final int MAX_SAMPLE_POINTS = 300; private TimeInterpolator mSourceInterpolator; private final float mLut[]; @@ -47,6 +49,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeI int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS); // We need 2 frame values as the minimal. int numAnimFrames = Math.max(2, (int) Math.ceil(((double) duration) / animIntervalMs)); + numAnimFrames = Math.min(numAnimFrames, MAX_SAMPLE_POINTS); float values[] = new float[numAnimFrames]; float lastFrame = numAnimFrames - 1; for (int i = 0; i < numAnimFrames; i++) { diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java index ddf3a764661297eb8320079bdaf05acd25e66e1d..69e974c672d063518a9d7d805fc5ed15e29b0638 100644 --- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java +++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java @@ -366,7 +366,7 @@ final class CascadingMenuPopup extends MenuPopup implements MenuPresenter, OnKey final int menuWidth = measureIndividualMenuWidth(adapter, null, mContext, mMenuMaxWidth); final MenuPopupWindow popupWindow = createPopupWindow(); popupWindow.setAdapter(adapter); - popupWindow.setWidth(menuWidth); + popupWindow.setContentWidth(menuWidth); popupWindow.setDropDownGravity(mDropDownGravity); final CascadingMenuInfo parentInfo; diff --git a/core/java/com/android/internal/widget/AlertDialogLayout.java b/core/java/com/android/internal/widget/AlertDialogLayout.java index 891c920af33646c1732453ae84707a77c07558ad..9bf094891f3bbbcd81b9b76e34bdfaae7e81f9d1 100644 --- a/core/java/com/android/internal/widget/AlertDialogLayout.java +++ b/core/java/com/android/internal/widget/AlertDialogLayout.java @@ -20,7 +20,9 @@ import android.annotation.AttrRes; import android.annotation.Nullable; import android.annotation.StyleRes; import android.content.Context; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; @@ -265,4 +267,92 @@ public class AlertDialogLayout extends LinearLayout { return 0; } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + final int paddingLeft = mPaddingLeft; + + // Where right end of child should go + final int width = right - left; + final int childRight = width - mPaddingRight; + + // Space available for child + final int childSpace = width - paddingLeft - mPaddingRight; + + final int totalLength = getMeasuredHeight(); + final int count = getChildCount(); + final int gravity = getGravity(); + final int majorGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + final int minorGravity = gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK; + + int childTop; + switch (majorGravity) { + case Gravity.BOTTOM: + // totalLength contains the padding already + childTop = mPaddingTop + bottom - top - totalLength; + break; + + // totalLength contains the padding already + case Gravity.CENTER_VERTICAL: + childTop = mPaddingTop + (bottom - top - totalLength) / 2; + break; + + case Gravity.TOP: + default: + childTop = mPaddingTop; + break; + } + + final Drawable dividerDrawable = getDividerDrawable(); + final int dividerHeight = dividerDrawable == null ? + 0 : dividerDrawable.getIntrinsicHeight(); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child != null && child.getVisibility() != GONE) { + final int childWidth = child.getMeasuredWidth(); + final int childHeight = child.getMeasuredHeight(); + + final LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) child.getLayoutParams(); + + int layoutGravity = lp.gravity; + if (layoutGravity < 0) { + layoutGravity = minorGravity; + } + final int layoutDirection = getLayoutDirection(); + final int absoluteGravity = Gravity.getAbsoluteGravity( + layoutGravity, layoutDirection); + + final int childLeft; + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + childLeft = paddingLeft + ((childSpace - childWidth) / 2) + + lp.leftMargin - lp.rightMargin; + break; + + case Gravity.RIGHT: + childLeft = childRight - childWidth - lp.rightMargin; + break; + + case Gravity.LEFT: + default: + childLeft = paddingLeft + lp.leftMargin; + break; + } + + if (hasDividerBeforeChildAt(i)) { + childTop += dividerHeight; + } + + childTop += lp.topMargin; + setChildFrame(child, childLeft, childTop, childWidth, childHeight); + childTop += childHeight + lp.bottomMargin; + } + } + } + + private void setChildFrame(View child, int left, int top, int width, int height) { + child.layout(left, top, left + width, top + height); + } } diff --git a/core/java/com/android/internal/widget/CachingIconView.java b/core/java/com/android/internal/widget/CachingIconView.java new file mode 100644 index 0000000000000000000000000000000000000000..293b77b91d3795d5b51a0d3ff0f9249f1490ce47 --- /dev/null +++ b/core/java/com/android/internal/widget/CachingIconView.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.internal.widget; + +import android.annotation.DrawableRes; +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.net.Uri; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.RemotableViewMethod; +import android.widget.ImageView; +import android.widget.RemoteViews; + +import libcore.util.Objects; + +/** + * An ImageView for displaying an Icon. Avoids reloading the Icon when possible. + */ +@RemoteViews.RemoteView +public class CachingIconView extends ImageView { + + private String mLastPackage; + private int mLastResId; + private boolean mInternalSetDrawable; + + public CachingIconView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + @Override + @RemotableViewMethod(asyncImpl="setImageIconAsync") + public void setImageIcon(@Nullable Icon icon) { + if (!testAndSetCache(icon)) { + mInternalSetDrawable = true; + // This calls back to setImageDrawable, make sure we don't clear the cache there. + super.setImageIcon(icon); + mInternalSetDrawable = false; + } + } + + @Override + public Runnable setImageIconAsync(@Nullable Icon icon) { + resetCache(); + return super.setImageIconAsync(icon); + } + + @Override + @RemotableViewMethod(asyncImpl="setImageResourceAsync") + public void setImageResource(@DrawableRes int resId) { + if (!testAndSetCache(resId)) { + mInternalSetDrawable = true; + // This calls back to setImageDrawable, make sure we don't clear the cache there. + super.setImageResource(resId); + mInternalSetDrawable = false; + } + } + + @Override + public Runnable setImageResourceAsync(@DrawableRes int resId) { + resetCache(); + return super.setImageResourceAsync(resId); + } + + @Override + @RemotableViewMethod(asyncImpl="setImageURIAsync") + public void setImageURI(@Nullable Uri uri) { + resetCache(); + super.setImageURI(uri); + } + + @Override + public Runnable setImageURIAsync(@Nullable Uri uri) { + resetCache(); + return super.setImageURIAsync(uri); + } + + @Override + public void setImageDrawable(@Nullable Drawable drawable) { + if (!mInternalSetDrawable) { + // Only clear the cache if we were externally called. + resetCache(); + } + super.setImageDrawable(drawable); + } + + @Override + @RemotableViewMethod + public void setImageBitmap(Bitmap bm) { + resetCache(); + super.setImageBitmap(bm); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + resetCache(); + } + + /** + * @return true if the currently set image is the same as {@param icon} + */ + private synchronized boolean testAndSetCache(Icon icon) { + if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) { + String iconPackage = normalizeIconPackage(icon); + + boolean isCached = mLastResId != 0 + && icon.getResId() == mLastResId + && Objects.equal(iconPackage, mLastPackage); + + mLastPackage = iconPackage; + mLastResId = icon.getResId(); + + return isCached; + } else { + resetCache(); + return false; + } + } + + /** + * @return true if the currently set image is the same as {@param resId} + */ + private synchronized boolean testAndSetCache(int resId) { + boolean isCached; + if (resId == 0 || mLastResId == 0) { + isCached = false; + } else { + isCached = resId == mLastResId && null == mLastPackage; + } + mLastPackage = null; + mLastResId = resId; + return isCached; + } + + /** + * Returns the normalized package name of {@param icon}. + * @return null if icon is null or if the icons package is null, empty or matches the current + * context. Otherwise returns the icon's package context. + */ + private String normalizeIconPackage(Icon icon) { + if (icon == null) { + return null; + } + + String pkg = icon.getResPackage(); + if (TextUtils.isEmpty(pkg)) { + return null; + } + if (pkg.equals(mContext.getPackageName())) { + return null; + } + return pkg; + } + + private synchronized void resetCache() { + mLastResId = 0; + mLastPackage = null; + } +} diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java index e59d7ba57ea1d9e7c52eb14494990e8aec7d385f..fc68b849ed2080f06a1c6e410faaa4711ea55f2a 100644 --- a/core/java/com/android/internal/widget/DecorCaptionView.java +++ b/core/java/com/android/internal/widget/DecorCaptionView.java @@ -244,6 +244,11 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, return mTouchDispatchList; } + @Override + public boolean shouldDelayChildPressedState() { + return false; + } + private boolean passedSlop(int x, int y) { return Math.abs(x - mTouchDownX) > mDragSlop || Math.abs(y - mTouchDownY) > mDragSlop; } diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 594581af8837f1922fda9d23c9f09de775cd3ff8..66042086e9257d16943e5c49ba2e21bb6008282b 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -737,7 +737,7 @@ public final class FloatingToolbar { protected void applyTransformation(float interpolatedTime, Transformation t) { int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth)); setWidth(mContentContainer, startWidth + deltaWidth); - if (isRTL()) { + if (isInRTLMode()) { mContentContainer.setX(left); // Lock the panels in place. @@ -766,7 +766,7 @@ public final class FloatingToolbar { } }; final float overflowButtonStartX = mOverflowButton.getX(); - final float overflowButtonTargetX = isRTL() ? + final float overflowButtonTargetX = isInRTLMode() ? overflowButtonStartX + targetWidth - mOverflowButton.getWidth() : overflowButtonStartX - targetWidth + mOverflowButton.getWidth(); Animation overflowButtonAnimation = new Animation() { @@ -774,7 +774,7 @@ public final class FloatingToolbar { protected void applyTransformation(float interpolatedTime, Transformation t) { float overflowButtonX = overflowButtonStartX + interpolatedTime * (overflowButtonTargetX - overflowButtonStartX); - float deltaContainerWidth = isRTL() ? + float deltaContainerWidth = isInRTLMode() ? 0 : mContentContainer.getWidth() - startWidth; float actualOverflowButtonX = overflowButtonX + deltaContainerWidth; @@ -812,7 +812,7 @@ public final class FloatingToolbar { protected void applyTransformation(float interpolatedTime, Transformation t) { int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth)); setWidth(mContentContainer, startWidth + deltaWidth); - if (isRTL()) { + if (isInRTLMode()) { mContentContainer.setX(left); // Lock the panels in place. @@ -843,7 +843,7 @@ public final class FloatingToolbar { } }; final float overflowButtonStartX = mOverflowButton.getX(); - final float overflowButtonTargetX = isRTL() ? + final float overflowButtonTargetX = isInRTLMode() ? overflowButtonStartX - startWidth + mOverflowButton.getWidth() : overflowButtonStartX + startWidth - mOverflowButton.getWidth(); Animation overflowButtonAnimation = new Animation() { @@ -851,7 +851,7 @@ public final class FloatingToolbar { protected void applyTransformation(float interpolatedTime, Transformation t) { float overflowButtonX = overflowButtonStartX + interpolatedTime * (overflowButtonTargetX - overflowButtonStartX); - float deltaContainerWidth = isRTL() ? + float deltaContainerWidth = isInRTLMode() ? 0 : mContentContainer.getWidth() - startWidth; float actualOverflowButtonX = overflowButtonX + deltaContainerWidth; @@ -903,7 +903,7 @@ public final class FloatingToolbar { R.string.floating_toolbar_close_overflow_description)); // Update x-coordinates depending on RTL state. - if (isRTL()) { + if (isInRTLMode()) { mContentContainer.setX(mMarginHorizontal); // align left mMainPanel.setX(0); // align left mOverflowButton.setX( // align right @@ -947,7 +947,7 @@ public final class FloatingToolbar { if (hasOverflow()) { // Update x-coordinates depending on RTL state. - if (isRTL()) { + if (isInRTLMode()) { mContentContainer.setX(mMarginHorizontal); // align left mMainPanel.setX(0); // align left mOverflowButton.setX(0); // align left @@ -1087,9 +1087,10 @@ public final class FloatingToolbar { viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer); } - private boolean isRTL() { - return mContext.getResources().getConfiguration().getLayoutDirection() - == View.LAYOUT_DIRECTION_RTL; + private boolean isInRTLMode() { + return mContext.getApplicationInfo().hasRtlSupport() + && mContext.getResources().getConfiguration().getLayoutDirection() + == View.LAYOUT_DIRECTION_RTL; } private boolean hasOverflow() { @@ -1203,7 +1204,7 @@ public final class FloatingToolbar { // The positioning of contents in RTL is wrong when the view is first rendered. // Hide the view and post a runnable to recalculate positions and render the view. // TODO: Investigate why this happens and fix. - if (isRTL()) { + if (isInRTLMode()) { mContentContainer.setAlpha(0); mContentContainer.post(mPreparePopupContentRTLHelper); } diff --git a/core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl b/core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..79717cf2b0c9f254daa4ba2119df25491142d842 --- /dev/null +++ b/core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget; + +/** {@hide} */ +oneway interface ICheckCredentialProgressCallback { + void onCredentialVerified(); +} diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 05b839df9fa4782cd4448fe49fe49fe3b1d118ed..9fa558e89ae79532e690de35d4c700c3c4e2e0c3 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -17,6 +17,7 @@ package com.android.internal.widget; import android.app.trust.IStrongAuthTracker; +import com.android.internal.widget.ICheckCredentialProgressCallback; import com.android.internal.widget.VerifyCredentialResponse; /** {@hide} */ @@ -29,10 +30,12 @@ interface ILockSettings { String getString(in String key, in String defaultValue, in int userId); void setLockPattern(in String pattern, in String savedPattern, int userId); void resetKeyStore(int userId); - VerifyCredentialResponse checkPattern(in String pattern, int userId); + VerifyCredentialResponse checkPattern(in String pattern, int userId, + in ICheckCredentialProgressCallback progressCallback); VerifyCredentialResponse verifyPattern(in String pattern, long challenge, int userId); void setLockPassword(in String password, in String savedPassword, int userId); - VerifyCredentialResponse checkPassword(in String password, int userId); + VerifyCredentialResponse checkPassword(in String password, int userId, + in ICheckCredentialProgressCallback progressCallback); VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId); VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId); boolean checkVoldPassword(int userId); diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java index 926ebd158b50feda1e642bdefc3eeebf86486776..358be604f84724aaed280425515d9fc72db3f3a5 100644 --- a/core/java/com/android/internal/widget/ImageFloatingTextView.java +++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java @@ -40,6 +40,9 @@ public class ImageFloatingTextView extends TextView { /** Number of lines from the top to indent */ private int mIndentLines; + /** Resolved layout direction */ + private int mResolvedDirection = LAYOUT_DIRECTION_UNDEFINED; + public ImageFloatingTextView(Context context) { this(context, null); } @@ -82,7 +85,7 @@ public class ImageFloatingTextView extends TextView { margins[i] = endMargin; } } - if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + if (mResolvedDirection == LAYOUT_DIRECTION_RTL) { builder.setIndents(margins, null); } else { builder.setIndents(null, margins); @@ -91,6 +94,19 @@ public class ImageFloatingTextView extends TextView { return builder.build(); } + @Override + public void onRtlPropertiesChanged(int layoutDirection) { + super.onRtlPropertiesChanged(layoutDirection); + + if (layoutDirection != mResolvedDirection && isLayoutDirectionResolved()) { + mResolvedDirection = layoutDirection; + if (mIndentLines > 0) { + // Invalidate layout. + setHint(getHint()); + } + } + } + @RemotableViewMethod public void setHasImage(boolean hasImage) { setNumIndentLines(hasImage ? 2 : 0); diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java index 713f56f46266c3a35c00122ce4b513102bc25da2..6defd1e8d9f2a6ca88bab6142ee0f4e88a64954f 100644 --- a/core/java/com/android/internal/widget/LockPatternChecker.java +++ b/core/java/com/android/internal/widget/LockPatternChecker.java @@ -4,6 +4,7 @@ import android.os.AsyncTask; import com.android.internal.widget.LockPatternUtils.RequestThrottledException; +import java.util.ArrayList; import java.util.List; /** @@ -14,6 +15,13 @@ public final class LockPatternChecker { * Interface for a callback to be invoked after security check. */ public interface OnCheckCallback { + + /** + * Invoked as soon as possible we know that the credentials match. This will be called + * earlier than {@link #onChecked} but only if the credentials match. + */ + default void onEarlyMatched() {} + /** * Invoked when a security check is finished. * @@ -54,11 +62,19 @@ public final class LockPatternChecker { final OnVerifyCallback callback) { AsyncTask task = new AsyncTask() { private int mThrottleTimeout; + private List patternCopy; + + @Override + protected void onPreExecute() { + // Make a copy of the pattern to prevent race conditions. + // No need to clone the individual cells because they are immutable. + patternCopy = new ArrayList(pattern); + } @Override protected byte[] doInBackground(Void... args) { try { - return utils.verifyPattern(pattern, challenge, userId); + return utils.verifyPattern(patternCopy, challenge, userId); } catch (RequestThrottledException ex) { mThrottleTimeout = ex.getTimeoutMs(); return null; @@ -88,11 +104,19 @@ public final class LockPatternChecker { final OnCheckCallback callback) { AsyncTask task = new AsyncTask() { private int mThrottleTimeout; + private List patternCopy; + + @Override + protected void onPreExecute() { + // Make a copy of the pattern to prevent race conditions. + // No need to clone the individual cells because they are immutable. + patternCopy = new ArrayList(pattern); + } @Override protected Boolean doInBackground(Void... args) { try { - return utils.checkPattern(pattern, userId); + return utils.checkPattern(patternCopy, userId, callback::onEarlyMatched); } catch (RequestThrottledException ex) { mThrottleTimeout = ex.getTimeoutMs(); return false; @@ -199,7 +223,7 @@ public final class LockPatternChecker { @Override protected Boolean doInBackground(Void... args) { try { - return utils.checkPassword(password, userId); + return utils.checkPassword(password, userId, callback::onEarlyMatched); } catch (RequestThrottledException ex) { mThrottleTimeout = ex.getTimeoutMs(); return false; diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 2e0dfa5fa73124531b06672309d00d86c5c7da39..479b3b7a7a71a07d2e562571e336a87aa631da1e 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -17,6 +17,7 @@ package com.android.internal.widget; import android.annotation.IntDef; +import android.annotation.Nullable; import android.app.admin.DevicePolicyManager; import android.app.trust.IStrongAuthTracker; import android.app.trust.TrustManager; @@ -32,7 +33,6 @@ import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.IMountService; @@ -149,6 +149,7 @@ public class LockPatternUtils { private DevicePolicyManager mDevicePolicyManager; private ILockSettings mLockSettingsService; private UserManager mUserManager; + private final Handler mHandler; /** * Use {@link TrustManager#isTrustUsuallyManaged(int)}. @@ -230,6 +231,9 @@ public class LockPatternUtils { public LockPatternUtils(Context context) { mContext = context; mContentResolver = context.getContentResolver(); + + Looper looper = Looper.myLooper(); + mHandler = looper != null ? new Handler(looper) : null; } private ILockSettings getLockSettings() { @@ -284,7 +288,6 @@ public class LockPatternUtils { public void reportFailedPasswordAttempt(int userId) { getDevicePolicyManager().reportFailedPasswordAttempt(userId); getTrustManager().reportUnlockAttempt(false /* authenticated */, userId); - requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL, userId); } public void reportSuccessfulPasswordAttempt(int userId) { @@ -341,10 +344,23 @@ public class LockPatternUtils { */ public boolean checkPattern(List pattern, int userId) throws RequestThrottledException { + return checkPattern(pattern, userId, null /* progressCallback */); + } + + /** + * Check to see if a pattern matches the saved pattern. If no pattern exists, + * always returns true. + * @param pattern The pattern to check. + * @return Whether the pattern matches the stored one. + */ + public boolean checkPattern(List pattern, int userId, + @Nullable CheckCredentialProgressCallback progressCallback) + throws RequestThrottledException { throwIfCalledOnMainThread(); try { VerifyCredentialResponse response = - getLockSettings().checkPattern(patternToString(pattern), userId); + getLockSettings().checkPattern(patternToString(pattern), userId, + wrapCallback(progressCallback)); if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { return true; @@ -354,7 +370,7 @@ public class LockPatternUtils { return false; } } catch (RemoteException re) { - return true; + return false; } } @@ -423,10 +439,22 @@ public class LockPatternUtils { * @return Whether the password matches the stored one. */ public boolean checkPassword(String password, int userId) throws RequestThrottledException { + return checkPassword(password, userId, null /* progressCallback */); + } + + /** + * Check to see if a password matches the saved password. If no password exists, + * always returns true. + * @param password The password to check. + * @return Whether the password matches the stored one. + */ + public boolean checkPassword(String password, int userId, + @Nullable CheckCredentialProgressCallback progressCallback) + throws RequestThrottledException { throwIfCalledOnMainThread(); try { VerifyCredentialResponse response = - getLockSettings().checkPassword(password, userId); + getLockSettings().checkPassword(password, userId, wrapCallback(progressCallback)); if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { return true; } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { @@ -435,7 +463,7 @@ public class LockPatternUtils { return false; } } catch (RemoteException re) { - return true; + return false; } } @@ -1475,6 +1503,37 @@ public class LockPatternUtils { return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_FINGERPRINT) == 0; } + private ICheckCredentialProgressCallback wrapCallback( + final CheckCredentialProgressCallback callback) { + if (callback == null) { + return null; + } else { + if (mHandler == null) { + throw new IllegalStateException("Must construct LockPatternUtils on a looper thread" + + " to use progress callbacks."); + } + return new ICheckCredentialProgressCallback.Stub() { + + @Override + public void onCredentialVerified() throws RemoteException { + mHandler.post(callback::onEarlyMatched); + } + }; + } + } + + /** + * Callback to be notified about progress when checking credentials. + */ + public interface CheckCredentialProgressCallback { + + /** + * Called as soon as possible when we know that the credentials match but the user hasn't + * been fully unlocked. + */ + void onEarlyMatched(); + } + /** * Tracks the global strong authentication state. */ @@ -1484,7 +1543,8 @@ public class LockPatternUtils { value = { STRONG_AUTH_NOT_REQUIRED, STRONG_AUTH_REQUIRED_AFTER_BOOT, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, - SOME_AUTH_REQUIRED_AFTER_USER_REQUEST}) + SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, + STRONG_AUTH_REQUIRED_AFTER_LOCKOUT}) @Retention(RetentionPolicy.SOURCE) public @interface StrongAuthFlags {} @@ -1515,13 +1575,12 @@ public class LockPatternUtils { public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8; /** - * Some authentication is required because the user has entered a wrong credential. + * Strong auth flags that do not prevent fingerprint from being accepted as auth. + * + * If any other flags are set, fingerprint is disabled. */ - public static final int SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL = 0x10; - private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED - | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST - | SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL; + | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray(); private final H mHandler; diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java index 9dd118c5a942164e06ab9c8943de8d944a3deb74..073aac542e31535da94e2f03c33e94a860a45e6a 100644 --- a/core/java/com/android/internal/widget/NotificationActionListLayout.java +++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java @@ -17,11 +17,13 @@ package com.android.internal.widget; import android.content.Context; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Pair; import android.view.Gravity; +import android.view.RemotableViewMethod; import android.view.View; -import android.view.ViewGroup; +import android.widget.LinearLayout; import android.widget.RemoteViews; import android.widget.TextView; @@ -33,11 +35,14 @@ import java.util.Comparator; * the remaining available width, and the last action consumes the remaining space. */ @RemoteViews.RemoteView -public class NotificationActionListLayout extends ViewGroup { +public class NotificationActionListLayout extends LinearLayout { private int mTotalWidth = 0; private ArrayList> mMeasureOrderTextViews = new ArrayList<>(); private ArrayList mMeasureOrderOther = new ArrayList<>(); + private boolean mMeasureLinearly; + private int mDefaultPaddingEnd; + private Drawable mDefaultBackground; public NotificationActionListLayout(Context context, AttributeSet attrs) { super(context, attrs); @@ -45,6 +50,10 @@ public class NotificationActionListLayout extends ViewGroup { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mMeasureLinearly) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } final int N = getChildCount(); int textViews = 0; int otherViews = 0; @@ -186,6 +195,10 @@ public class NotificationActionListLayout extends ViewGroup { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (mMeasureLinearly) { + super.onLayout(changed, left, top, right, bottom); + return; + } final boolean isLayoutRtl = isLayoutRtl(); final int paddingTop = mPaddingTop; @@ -241,26 +254,24 @@ public class NotificationActionListLayout extends ViewGroup { } @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new MarginLayoutParams(getContext(), attrs); - } - - @Override - protected LayoutParams generateDefaultLayoutParams() { - return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + protected void onFinishInflate() { + super.onFinishInflate(); + mDefaultPaddingEnd = getPaddingEnd(); + mDefaultBackground = getBackground(); } - @Override - protected LayoutParams generateLayoutParams(LayoutParams p) { - if (p instanceof MarginLayoutParams) { - return new MarginLayoutParams((MarginLayoutParams)p); - } - return new MarginLayoutParams(p); - } - - @Override - protected boolean checkLayoutParams(LayoutParams p) { - return p instanceof MarginLayoutParams; + /** + * Set whether the list is in a mode where some actions are emphasized. This will trigger an + * equal measuring where all actions are full height and change a few parameters like + * the padding. + */ + @RemotableViewMethod + public void setEmphasizedMode(boolean emphasizedMode) { + mMeasureLinearly = emphasizedMode; + setPaddingRelative(getPaddingStart(), getPaddingTop(), + emphasizedMode ? 0 : mDefaultPaddingEnd, getPaddingBottom()); + setBackground(emphasizedMode ? null : mDefaultBackground); + requestLayout(); } public static final Comparator> MEASURE_ORDER_COMPARATOR diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index 8b9d5034b0c24b965bd7bfe090f1170dd68d310a..e84cc279b4031327e5ce812ee43b9b517f62f0ac 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -245,7 +245,7 @@ public class ResolverDrawerLayout extends ViewGroup { final float y = ev.getY(); mInitialTouchX = x; mInitialTouchY = mLastTouchY = y; - mOpenOnClick = isListChildUnderClipped(x, y) && mCollapsibleHeight > 0; + mOpenOnClick = isListChildUnderClipped(x, y) && mCollapseOffset > 0; } break; diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java index 277fafd4adf726e983ec3e030ecdbe0af163a922..d5b6def97426d48bccacea77b197c8783a14f741 100644 --- a/core/java/com/android/internal/widget/ViewPager.java +++ b/core/java/com/android/internal/widget/ViewPager.java @@ -55,34 +55,7 @@ import java.util.Collections; import java.util.Comparator; /** - * Layout manager that allows the user to flip left and right - * through pages of data. You supply an implementation of a - * {@link android.support.v4.view.PagerAdapter} to generate the pages that the view shows. - * - *

    Note this class is currently under early design and - * development. The API will likely change in later updates of - * the compatibility library, requiring changes to the source code - * of apps when they are compiled against the newer version.

    - * - *

    ViewPager is most often used in conjunction with {@link android.app.Fragment}, - * which is a convenient way to supply and manage the lifecycle of each page. - * There are standard adapters implemented for using fragments with the ViewPager, - * which cover the most common use cases. These are - * {@link android.support.v4.app.FragmentPagerAdapter} and - * {@link android.support.v4.app.FragmentStatePagerAdapter}; each of these - * classes have simple code showing how to build a full user interface - * with them. - * - *

    For more information about how to use ViewPager, read Creating Swipe Views with - * Tabs.

    - * - *

    Below is a more complicated example of ViewPager, using it in conjunction - * with {@link android.app.ActionBar} tabs. You can find other examples of using - * ViewPager in the API 4+ Support Demos and API 13+ Support Demos sample code. - * - * {@sample development/samples/Support13Demos/src/com/example/android/supportv13/app/ActionBarTabsPager.java - * complete} + * Framework copy of the support-v4 ViewPager class. */ public class ViewPager extends ViewGroup { private static final String TAG = "ViewPager"; diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java new file mode 100644 index 0000000000000000000000000000000000000000..4fd19c37bf4737556efb5c01bb2d8ccbf13f06dd --- /dev/null +++ b/core/java/com/android/internal/widget/WatchHeaderListView.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget; + +import android.annotation.IdRes; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.HeaderViewListAdapter; + +import java.util.ArrayList; + +import com.android.internal.util.Predicate; + +public class WatchHeaderListView extends ListView { + private View mTopPanel; + + public WatchHeaderListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public WatchHeaderListView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public WatchHeaderListView( + Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected HeaderViewListAdapter wrapHeaderListAdapterInternal( + ArrayList headerViewInfos, + ArrayList footerViewInfos, + ListAdapter adapter) { + return new WatchHeaderListAdapter(headerViewInfos, footerViewInfos, adapter); + } + + @Override + public void addView(View child, ViewGroup.LayoutParams params) { + if (mTopPanel == null) { + setTopPanel(child); + } else { + throw new IllegalStateException("WatchHeaderListView can host only one header"); + } + } + + public void setTopPanel(View v) { + mTopPanel = v; + wrapAdapterIfNecessary(); + } + + @Override + public void setAdapter(ListAdapter adapter) { + super.setAdapter(adapter); + wrapAdapterIfNecessary(); + } + + @Override + protected View findViewTraversal(@IdRes int id) { + View v = super.findViewTraversal(id); + if (v == null && mTopPanel != null && !mTopPanel.isRootNamespace()) { + return mTopPanel.findViewById(id); + } + return v; + } + + @Override + protected View findViewWithTagTraversal(Object tag) { + View v = super.findViewWithTagTraversal(tag); + if (v == null && mTopPanel != null && !mTopPanel.isRootNamespace()) { + return mTopPanel.findViewWithTag(tag); + } + return v; + } + + @Override + protected View findViewByPredicateTraversal(Predicate predicate, View childToSkip) { + View v = super.findViewByPredicateTraversal(predicate, childToSkip); + if (v == null && mTopPanel != null && mTopPanel != childToSkip + && !mTopPanel.isRootNamespace()) { + return mTopPanel.findViewByPredicate(predicate); + } + return v; + } + + @Override + public int getHeaderViewsCount() { + return mTopPanel == null ? super.getHeaderViewsCount() + : super.getHeaderViewsCount() + (mTopPanel.getVisibility() == GONE ? 0 : 1); + } + + private void wrapAdapterIfNecessary() { + ListAdapter adapter = getAdapter(); + if (adapter != null && mTopPanel != null) { + if (!(adapter instanceof WatchHeaderListAdapter)) { + wrapHeaderListAdapterInternal(); + } + + ((WatchHeaderListAdapter) getAdapter()).setTopPanel(mTopPanel); + dispatchDataSetObserverOnChangedInternal(); + } + } + + private static class WatchHeaderListAdapter extends HeaderViewListAdapter { + private View mTopPanel; + + public WatchHeaderListAdapter( + ArrayList headerViewInfos, + ArrayList footerViewInfos, + ListAdapter adapter) { + super(headerViewInfos, footerViewInfos, adapter); + } + + public void setTopPanel(View v) { + mTopPanel = v; + } + + private int getTopPanelCount() { + return (mTopPanel == null || mTopPanel.getVisibility() == GONE) ? 0 : 1; + } + + @Override + public int getCount() { + return super.getCount() + getTopPanelCount(); + } + + @Override + public boolean areAllItemsEnabled() { + return getTopPanelCount() == 0 && super.areAllItemsEnabled(); + } + + @Override + public boolean isEnabled(int position) { + int topPanelCount = getTopPanelCount(); + return position < topPanelCount ? false : super.isEnabled(position - topPanelCount); + } + + @Override + public Object getItem(int position) { + int topPanelCount = getTopPanelCount(); + return position < topPanelCount ? null : super.getItem(position - topPanelCount); + } + + @Override + public long getItemId(int position) { + int numHeaders = getHeadersCount() + getTopPanelCount(); + if (getWrappedAdapter() != null && position >= numHeaders) { + int adjPosition = position - numHeaders; + int adapterCount = getWrappedAdapter().getCount(); + if (adjPosition < adapterCount) { + return getWrappedAdapter().getItemId(adjPosition); + } + } + return -1; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + int topPanelCount = getTopPanelCount(); + return position < topPanelCount + ? mTopPanel : super.getView(position - topPanelCount, convertView, parent); + } + + @Override + public int getItemViewType(int position) { + int numHeaders = getHeadersCount() + getTopPanelCount(); + if (getWrappedAdapter() != null && position >= numHeaders) { + int adjPosition = position - numHeaders; + int adapterCount = getWrappedAdapter().getCount(); + if (adjPosition < adapterCount) { + return getWrappedAdapter().getItemViewType(adjPosition); + } + } + + return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER; + } + } +} diff --git a/core/java/com/android/internal/widget/WatchListDecorLayout.java b/core/java/com/android/internal/widget/WatchListDecorLayout.java new file mode 100644 index 0000000000000000000000000000000000000000..5b49611fa4b09554bed06c370ecb528b54eedbb9 --- /dev/null +++ b/core/java/com/android/internal/widget/WatchListDecorLayout.java @@ -0,0 +1,328 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewTreeObserver; +import android.widget.ListView; +import android.widget.FrameLayout; + +import java.util.ArrayList; + + +/** + * Layout for the decor for ListViews on watch-type devices with small screens. + *

    + * Supports one panel with the gravity set to top, and one panel with gravity set to bottom. + *

    + * Use with one ListView child. The top and bottom panels will track the ListView's scrolling. + * If there is no ListView child, it will act like a normal FrameLayout. + */ +public class WatchListDecorLayout extends FrameLayout + implements ViewTreeObserver.OnScrollChangedListener { + + private int mForegroundPaddingLeft = 0; + private int mForegroundPaddingTop = 0; + private int mForegroundPaddingRight = 0; + private int mForegroundPaddingBottom = 0; + + private final ArrayList mMatchParentChildren = new ArrayList<>(1); + + /** Track the amount the ListView has to scroll up to account for padding change difference. */ + private int mPendingScroll; + private View mBottomPanel; + private View mTopPanel; + private ListView mListView; + private ViewTreeObserver mObserver; + + + public WatchListDecorLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public WatchListDecorLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public WatchListDecorLayout( + Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + mPendingScroll = 0; + + for (int i = 0; i < getChildCount(); ++i) { + View child = getChildAt(i); + if (child instanceof ListView) { + if (mListView != null) { + throw new IllegalArgumentException("only one ListView child allowed"); + } + mListView = (ListView) child; + + mListView.setNestedScrollingEnabled(true); + mObserver = mListView.getViewTreeObserver(); + mObserver.addOnScrollChangedListener(this); + } else { + int gravity = (((LayoutParams) child.getLayoutParams()).gravity + & Gravity.VERTICAL_GRAVITY_MASK); + if (gravity == Gravity.TOP && mTopPanel == null) { + mTopPanel = child; + } else if (gravity == Gravity.BOTTOM && mBottomPanel == null) { + mBottomPanel = child; + } + } + } + } + + @Override + public void onDetachedFromWindow() { + mListView = null; + mBottomPanel = null; + mTopPanel = null; + if (mObserver != null) { + if (mObserver.isAlive()) { + mObserver.removeOnScrollChangedListener(this); + } + mObserver = null; + } + } + + private void applyMeasureToChild(View child, int widthMeasureSpec, int heightMeasureSpec) { + final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); + + final int childWidthMeasureSpec; + if (lp.width == LayoutParams.MATCH_PARENT) { + final int width = Math.max(0, getMeasuredWidth() + - getPaddingLeftWithForeground() - getPaddingRightWithForeground() + - lp.leftMargin - lp.rightMargin); + childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + width, MeasureSpec.EXACTLY); + } else { + childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, + getPaddingLeftWithForeground() + getPaddingRightWithForeground() + + lp.leftMargin + lp.rightMargin, + lp.width); + } + + final int childHeightMeasureSpec; + if (lp.height == LayoutParams.MATCH_PARENT) { + final int height = Math.max(0, getMeasuredHeight() + - getPaddingTopWithForeground() - getPaddingBottomWithForeground() + - lp.topMargin - lp.bottomMargin); + childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( + height, MeasureSpec.EXACTLY); + } else { + childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, + getPaddingTopWithForeground() + getPaddingBottomWithForeground() + + lp.topMargin + lp.bottomMargin, + lp.height); + } + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + } + + private int measureAndGetHeight(View child, int widthMeasureSpec, int heightMeasureSpec) { + if (child != null) { + if (child.getVisibility() != GONE) { + applyMeasureToChild(mBottomPanel, widthMeasureSpec, heightMeasureSpec); + return child.getMeasuredHeight(); + } else if (getMeasureAllChildren()) { + applyMeasureToChild(mBottomPanel, widthMeasureSpec, heightMeasureSpec); + } + } + return 0; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int count = getChildCount(); + + final boolean measureMatchParentChildren = + MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || + MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; + mMatchParentChildren.clear(); + + int maxHeight = 0; + int maxWidth = 0; + int childState = 0; + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (getMeasureAllChildren() || child.getVisibility() != GONE) { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + maxWidth = Math.max(maxWidth, + child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); + maxHeight = Math.max(maxHeight, + child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); + childState = combineMeasuredStates(childState, child.getMeasuredState()); + if (measureMatchParentChildren) { + if (lp.width == LayoutParams.MATCH_PARENT || + lp.height == LayoutParams.MATCH_PARENT) { + mMatchParentChildren.add(child); + } + } + } + } + + // Account for padding too + maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground(); + maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground(); + + // Check against our minimum height and width + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + // Check against our foreground's minimum height and width + final Drawable drawable = getForeground(); + if (drawable != null) { + maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); + maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); + } + + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), + resolveSizeAndState(maxHeight, heightMeasureSpec, + childState << MEASURED_HEIGHT_STATE_SHIFT)); + + if (mListView != null) { + if (mPendingScroll != 0) { + mListView.scrollListBy(mPendingScroll); + mPendingScroll = 0; + } + + int paddingTop = Math.max(mListView.getPaddingTop(), + measureAndGetHeight(mTopPanel, widthMeasureSpec, heightMeasureSpec)); + int paddingBottom = Math.max(mListView.getPaddingBottom(), + measureAndGetHeight(mBottomPanel, widthMeasureSpec, heightMeasureSpec)); + + if (paddingTop != mListView.getPaddingTop() + || paddingBottom != mListView.getPaddingBottom()) { + mPendingScroll += mListView.getPaddingTop() - paddingTop; + mListView.setPadding( + mListView.getPaddingLeft(), paddingTop, + mListView.getPaddingRight(), paddingBottom); + } + } + + count = mMatchParentChildren.size(); + if (count > 1) { + for (int i = 0; i < count; i++) { + final View child = mMatchParentChildren.get(i); + if (mListView == null || (child != mTopPanel && child != mBottomPanel)) { + applyMeasureToChild(child, widthMeasureSpec, heightMeasureSpec); + } + } + } + } + + @Override + public void setForegroundGravity(int foregroundGravity) { + if (getForegroundGravity() != foregroundGravity) { + super.setForegroundGravity(foregroundGravity); + + // calling get* again here because the set above may apply default constraints + final Drawable foreground = getForeground(); + if (getForegroundGravity() == Gravity.FILL && foreground != null) { + Rect padding = new Rect(); + if (foreground.getPadding(padding)) { + mForegroundPaddingLeft = padding.left; + mForegroundPaddingTop = padding.top; + mForegroundPaddingRight = padding.right; + mForegroundPaddingBottom = padding.bottom; + } + } else { + mForegroundPaddingLeft = 0; + mForegroundPaddingTop = 0; + mForegroundPaddingRight = 0; + mForegroundPaddingBottom = 0; + } + } + } + + private int getPaddingLeftWithForeground() { + return isForegroundInsidePadding() ? Math.max(mPaddingLeft, mForegroundPaddingLeft) : + mPaddingLeft + mForegroundPaddingLeft; + } + + private int getPaddingRightWithForeground() { + return isForegroundInsidePadding() ? Math.max(mPaddingRight, mForegroundPaddingRight) : + mPaddingRight + mForegroundPaddingRight; + } + + private int getPaddingTopWithForeground() { + return isForegroundInsidePadding() ? Math.max(mPaddingTop, mForegroundPaddingTop) : + mPaddingTop + mForegroundPaddingTop; + } + + private int getPaddingBottomWithForeground() { + return isForegroundInsidePadding() ? Math.max(mPaddingBottom, mForegroundPaddingBottom) : + mPaddingBottom + mForegroundPaddingBottom; + } + + @Override + public void onScrollChanged() { + if (mListView == null) { + return; + } + + if (mTopPanel != null) { + if (mListView.getChildCount() > 0) { + if (mListView.getFirstVisiblePosition() == 0) { + View firstChild = mListView.getChildAt(0); + setScrolling(mTopPanel, + firstChild.getY() - mTopPanel.getHeight() - mTopPanel.getTop()); + } else { + // shift to hide the frame, last child is not the last position + setScrolling(mTopPanel, -mTopPanel.getHeight()); + } + } else { + setScrolling(mTopPanel, 0); // no visible child, fallback to default behaviour + } + } + + if (mBottomPanel != null) { + if (mListView.getChildCount() > 0) { + if (mListView.getLastVisiblePosition() >= mListView.getCount() - 1) { + View lastChild = mListView.getChildAt(mListView.getChildCount() - 1); + setScrolling(mBottomPanel, Math.max( + 0, + lastChild.getY() + lastChild.getHeight() - mBottomPanel.getTop())); + } else { + // shift to hide the frame, last child is not the last position + setScrolling(mBottomPanel, mBottomPanel.getHeight()); + } + } else { + setScrolling(mBottomPanel, 0); // no visible child, fallback to default behaviour + } + } + } + + /** Only set scrolling for the panel if there is a change in its translationY. */ + private void setScrolling(View panel, float translationY) { + if (panel.getTranslationY() != translationY) { + panel.setTranslationY(translationY); + } + } +} diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java index fbc51cdca6c222a2802c3eaa0a4a3e5bebd11bba..5a50fbfd52778262c1e4f0a45a2041b7bf03f3be 100644 --- a/core/java/com/android/server/BootReceiver.java +++ b/core/java/com/android/server/BootReceiver.java @@ -79,6 +79,9 @@ public class BootReceiver extends BroadcastReceiver { private static final String LOG_FILES_FILE = "log-files.xml"; private static final AtomicFile sFile = new AtomicFile(new File( Environment.getDataSystemDirectory(), LOG_FILES_FILE)); + private static final String LAST_HEADER_FILE = "last-header.txt"; + private static final File lastHeaderFile = new File( + Environment.getDataSystemDirectory(), LAST_HEADER_FILE); @Override public void onReceive(final Context context, Intent intent) { @@ -113,9 +116,17 @@ public class BootReceiver extends BroadcastReceiver { Downloads.removeAllDownloadsByPackage(context, OLD_UPDATER_PACKAGE, OLD_UPDATER_CLASS); } - private void logBootEvents(Context ctx) throws IOException { - final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE); - final String headers = new StringBuilder(512) + private String getPreviousBootHeaders() { + try { + return FileUtils.readTextFile(lastHeaderFile, 0, null); + } catch (IOException e) { + Slog.e(TAG, "Error reading " + lastHeaderFile, e); + return null; + } + } + + private String getCurrentBootHeaders() throws IOException { + return new StringBuilder(512) .append("Build: ").append(Build.FINGERPRINT).append("\n") .append("Hardware: ").append(Build.BOARD).append("\n") .append("Revision: ") @@ -125,6 +136,31 @@ public class BootReceiver extends BroadcastReceiver { .append("Kernel: ") .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n")) .append("\n").toString(); + } + + + private String getBootHeadersToLogAndUpdate() throws IOException { + final String oldHeaders = getPreviousBootHeaders(); + final String newHeaders = getCurrentBootHeaders(); + + try { + FileUtils.stringToFile(lastHeaderFile, newHeaders); + } catch (IOException e) { + Slog.e(TAG, "Error writing " + lastHeaderFile, e); + } + + if (oldHeaders == null) { + // If we failed to read the old headers, use the current headers + // but note this in the headers so we know + return "isPrevious: false\n" + newHeaders; + } + + return "isPrevious: true\n" + oldHeaders; + } + + private void logBootEvents(Context ctx) throws IOException { + final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE); + final String headers = getBootHeadersToLogAndUpdate(); final String bootReason = SystemProperties.get("ro.boot.bootreason", null); String recovery = RecoverySystem.handleAftermath(ctx); diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index 886265ac6df1a0f32983d250ffdc426cdd2f037b..429131bfd32072c56c8ef450225a7f7c12db12fd 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -42,6 +42,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** * Loads global system configuration info. @@ -122,6 +124,11 @@ public class SystemConfig { // These are the permitted backup transport service components final ArraySet mBackupTransportWhitelist = new ArraySet<>(); + // These are the packages of carrier-associated apps which should be disabled until used until + // a SIM is inserted which grants carrier privileges to that carrier app. + final ArrayMap> mDisabledUntilUsedPreinstalledCarrierAssociatedApps = + new ArrayMap<>(); + public static SystemConfig getInstance() { synchronized (SystemConfig.class) { if (sInstance == null) { @@ -183,6 +190,10 @@ public class SystemConfig { return mBackupTransportWhitelist; } + public ArrayMap> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { + return mDisabledUntilUsedPreinstalledCarrierAssociatedApps; + } + SystemConfig() { // Read configuration from system readPermissions(Environment.buildPath( @@ -476,6 +487,26 @@ public class SystemConfig { } } XmlUtils.skipCurrentTag(parser); + } else if ("disabled-until-used-preinstalled-carrier-associated-app".equals(name) + && allowAppConfigs) { + String pkgname = parser.getAttributeValue(null, "package"); + String carrierPkgname = parser.getAttributeValue(null, "carrierAppPackage"); + if (pkgname == null || carrierPkgname == null) { + Slog.w(TAG, " associatedPkgs = + mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get( + carrierPkgname); + if (associatedPkgs == null) { + associatedPkgs = new ArrayList<>(); + mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put( + carrierPkgname, associatedPkgs); + } + associatedPkgs.add(pkgname); + } + XmlUtils.skipCurrentTag(parser); } else { XmlUtils.skipCurrentTag(parser); continue; diff --git a/core/java/com/android/server/backup/AccountManagerBackupHelper.java b/core/java/com/android/server/backup/AccountManagerBackupHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..39b18c0f2c16e8f0288f1c58357fef4e3c32ea63 --- /dev/null +++ b/core/java/com/android/server/backup/AccountManagerBackupHelper.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.backup; + +import android.accounts.AccountManagerInternal; +import android.app.backup.BlobBackupHelper; +import android.os.UserHandle; +import android.util.Slog; +import com.android.server.LocalServices; + +/** + * Helper for handling backup of account manager specific state. + */ +public class AccountManagerBackupHelper extends BlobBackupHelper { + private static final String TAG = "AccountsBackup"; + private static final boolean DEBUG = false; + + // current schema of the backup state blob + private static final int STATE_VERSION = 1; + + // key under which the account access grant state blob is committed to backup + private static final String KEY_ACCOUNT_ACCESS_GRANTS = "account_access_grants"; + + public AccountManagerBackupHelper() { + super(STATE_VERSION, KEY_ACCOUNT_ACCESS_GRANTS); + } + + @Override + protected byte[] getBackupPayload(String key) { + AccountManagerInternal am = LocalServices.getService(AccountManagerInternal.class); + if (DEBUG) { + Slog.d(TAG, "Handling backup of " + key); + } + try { + switch (key) { + case KEY_ACCOUNT_ACCESS_GRANTS: { + return am.backupAccountAccessPermissions(UserHandle.USER_SYSTEM); + } + + default: { + Slog.w(TAG, "Unexpected backup key " + key); + } + } + } catch (Exception e) { + Slog.e(TAG, "Unable to store payload " + key); + } + + return new byte[0]; + } + + @Override + protected void applyRestoredPayload(String key, byte[] payload) { + AccountManagerInternal am = LocalServices.getService(AccountManagerInternal.class); + if (DEBUG) { + Slog.d(TAG, "Handling restore of " + key); + } + try { + switch (key) { + case KEY_ACCOUNT_ACCESS_GRANTS: { + am.restoreAccountAccessPermissions(payload, UserHandle.USER_SYSTEM); + } break; + + default: { + Slog.w(TAG, "Unexpected restore key " + key); + } + } + } catch (Exception e) { + Slog.w(TAG, "Unable to restore key " + key); + } + } +} diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java index 9d296fa194005947e751123e4143daf12fce4597..537565185d9b41ea74b137356c3d8210fdd67e4a 100644 --- a/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/core/java/com/android/server/backup/SystemBackupAgent.java @@ -49,6 +49,7 @@ public class SystemBackupAgent extends BackupAgentHelper { private static final String PERMISSION_HELPER = "permissions"; private static final String USAGE_STATS_HELPER = "usage_stats"; private static final String SHORTCUT_MANAGER_HELPER = "shortcut_manager"; + private static final String ACCOUNT_MANAGER_HELPER = "account_manager"; // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME // are also used in the full-backup file format, so must not change unless steps are @@ -82,6 +83,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); + addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); super.onBackup(oldState, data, newState); } @@ -111,6 +113,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); + addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); try { super.onRestore(data, appVersionCode, newState); diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 01c2a0b50c62fa3faf19804510b67cb2dbae5ecf..18c4ee3efdee77b1ac0a12e1ddbfed6b32c922b1 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -18,6 +18,7 @@ #include "CreateJavaOutputStreamAdaptor.h" #include #include +#include #include "core_jni_helpers.h" @@ -150,12 +151,12 @@ Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc, mPixelRef->unref(); } -Bitmap::Bitmap(void* address, int fd, +Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable) : mPixelStorageType(PixelStorageType::Ashmem) { mPixelStorage.ashmem.address = address; mPixelStorage.ashmem.fd = fd; - mPixelStorage.ashmem.size = ashmem_get_size_region(fd); + mPixelStorage.ashmem.size = mappedSize; mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable)); // Note: this will trigger a call to onStrongRefDestroyed(), but // we want the pixel ref to have a ref count of 0 at this point @@ -1026,7 +1027,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { // Map the pixels in place and take ownership of the ashmem region. nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(), - ctable, dupFd, const_cast(blob.data()), !isMutable); + ctable, dupFd, const_cast(blob.data()), size, !isMutable); SkSafeUnref(ctable); if (!nativeBitmap) { close(dupFd); @@ -1361,6 +1362,14 @@ static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) { return reinterpret_cast(pixelRef); } +static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) { + LocalScopedBitmap bitmapHandle(bitmapPtr); + if (!bitmapHandle.valid()) return; + SkBitmap bitmap; + bitmapHandle->getSkBitmap(&bitmap); + android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmap); +} + /////////////////////////////////////////////////////////////////////////////// static const JNINativeMethod gBitmapMethods[] = { @@ -1404,6 +1413,7 @@ static const JNINativeMethod gBitmapMethods[] = { (void*)Bitmap_copyPixelsFromBuffer }, { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs }, { "nativeRefPixelRef", "(J)J", (void*)Bitmap_refPixelRef }, + { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw }, }; int register_android_graphics_Bitmap(JNIEnv* env) diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h index eadba5c0e634166b5a7f47d41fcf8d4589790c73..aaea178e738709a207b18ee1470a124d77a71d4b 100644 --- a/core/jni/android/graphics/Bitmap.h +++ b/core/jni/android/graphics/Bitmap.h @@ -51,8 +51,8 @@ public: const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); - Bitmap(void* address, int fd, const SkImageInfo& info, size_t rowBytes, - SkColorTable* ctable); + Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, + size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info() const; diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 528541dadfb89ff947283b06393068433fc7d942..889a3db81e6f0178e9812df14a8daba83ca695f1 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -613,7 +613,7 @@ android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitm return nullptr; } - android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable); + android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable); wrapper->getSkBitmap(bitmap); // since we're already allocated, we lockPixels right away // HeapAllocator behaves this way too @@ -623,7 +623,7 @@ android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitm } android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, - SkColorTable* ctable, int fd, void* addr, bool readOnly) { + SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly) { const SkImageInfo& info = bitmap->info(); if (info.colorType() == kUnknown_SkColorType) { doThrowIAE(env, "unknown bitmap configuration"); @@ -633,7 +633,8 @@ android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, if (!addr) { // Map existing ashmem region if not already mapped. int flags = readOnly ? (PROT_READ) : (PROT_READ | PROT_WRITE); - addr = mmap(NULL, ashmem_get_size_region(fd), flags, MAP_SHARED, fd, 0); + size = ashmem_get_size_region(fd); + addr = mmap(NULL, size, flags, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { return nullptr; } @@ -643,7 +644,7 @@ android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, // attempting to compute our own. const size_t rowBytes = bitmap->rowBytes(); - android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable); + android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable); wrapper->getSkBitmap(bitmap); if (readOnly) { bitmap->pixelRef()->setImmutable(); diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index f6a9bc7c62d7ad53c5ca304bb60fb82e807a5c4b..5ec41ca1572c1f4ee149620a849469cecef7e707 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -101,7 +101,7 @@ public: SkColorTable* ctable); static android::Bitmap* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, - SkColorTable* ctable, int fd, void* addr, bool readOnly); + SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly); /** * Given a bitmap we natively allocate a memory block to store the contents diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 898cf77cb32dcd785dbb678b05a4bb0a863df934..85092ad4fdd4738bb90cea7a7816472271a70b1b 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -768,6 +768,21 @@ namespace PaintGlue { return false; } + // Don't count glyphs that are the recommended "space" glyph and are zero width. + // This logic makes assumptions about HarfBuzz layout, but does correctly handle + // cases where ligatures form and zero width space glyphs are left in as + // placeholders. + static size_t countNonSpaceGlyphs(const Layout& layout) { + size_t count = 0; + static unsigned int kSpaceGlyphId = 3; + for (size_t i = 0; i < layout.nGlyphs(); i++) { + if (layout.getGlyphId(i) != kSpaceGlyphId || layout.getCharAdvance(i) != 0.0) { + count++; + } + } + return count; + } + // Returns true if the given string is exact one pair of regional indicators. static bool isFlag(const jchar* str, size_t length) { const jchar RI_LEAD_SURROGATE = 0xD83C; @@ -831,7 +846,7 @@ namespace PaintGlue { Layout layout; MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(), str.size()); - size_t nGlyphs = layout.nGlyphs(); + size_t nGlyphs = countNonSpaceGlyphs(layout); if (nGlyphs != 1 && nChars > 1) { // multiple-character input, and was not a ligature // TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp index 9deb1259f91b5d226321f91c1e6c18d667398335..ac82457c249a721e0f207b6369d90ea56906d24b 100644 --- a/core/jni/android/graphics/pdf/PdfEditor.cpp +++ b/core/jni/android/graphics/pdf/PdfEditor.cpp @@ -56,11 +56,9 @@ static struct { } gRectClassInfo; // Also used in PdfRenderer.cpp -Mutex sPdfiumLock; int sUnmatchedPdfiumInitRequestCount = 0; static void initializeLibraryIfNeeded() { - Mutex::Autolock _l(sPdfiumLock); if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); } @@ -68,7 +66,6 @@ static void initializeLibraryIfNeeded() { } static void destroyLibraryIfNeeded() { - Mutex::Autolock _l(sPdfiumLock); sUnmatchedPdfiumInitRequestCount--; if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_DestroyLibrary(); diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp index 71bec7845fd7163fb4f57a51e4d5d218adb2230c..43550ac9ed72bdc5bf7acd5aa2943cfeaf2ebdc1 100644 --- a/core/jni/android/graphics/pdf/PdfRenderer.cpp +++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp @@ -44,11 +44,9 @@ static struct { } gPointClassInfo; // See PdfEditor.cpp -extern Mutex sPdfiumLock; extern int sUnmatchedPdfiumInitRequestCount; static void initializeLibraryIfNeeded() { - Mutex::Autolock _l(sPdfiumLock); if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_InitLibrary(); } @@ -56,7 +54,6 @@ static void initializeLibraryIfNeeded() { } static void destroyLibraryIfNeeded() { - Mutex::Autolock _l(sPdfiumLock); sUnmatchedPdfiumInitRequestCount--; if (sUnmatchedPdfiumInitRequestCount == 0) { FPDF_DestroyLibrary(); diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/android_app_ApplicationLoaders.cpp index 24ee9591fc2f90e7dab6c7b5e357b72bce096528..3e7c039e2129c7d83a432e65f9ac4d56b0473ba8 100644 --- a/core/jni/android_app_ApplicationLoaders.cpp +++ b/core/jni/android_app_ApplicationLoaders.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "ApplicationLoaders" + #include #include #include @@ -22,10 +24,17 @@ static void setupVulkanLayerPath_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring librarySearchPath) { + android_namespace_t* ns = android::FindNamespaceByClassLoader(env, classLoader); ScopedUtfChars layerPathChars(env, librarySearchPath); + vulkan::LoaderData& loader_data = vulkan::LoaderData::GetInstance(); - loader_data.layer_path = layerPathChars.c_str(); - loader_data.app_namespace = android::FindNamespaceByClassLoader(env, classLoader); + if (loader_data.layer_path.empty()) { + loader_data.layer_path = layerPathChars.c_str(); + loader_data.app_namespace = ns; + } else { + ALOGD("ignored Vulkan layer search path %s for namespace %p", + layerPathChars.c_str(), ns); + } } static const JNINativeMethod g_methods[] = { diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp index 7213414af19f4cacabca652531eff8291232fcd5..3fc3aaf6c8f36a8a5b95d5fa49a92e20febe4a93 100644 --- a/core/jni/android_database_CursorWindow.cpp +++ b/core/jni/android_database_CursorWindow.cpp @@ -16,6 +16,7 @@ #undef LOG_TAG #define LOG_TAG "CursorWindow" +#define LOG_NDEBUG 0 #include #include @@ -30,6 +31,11 @@ #include #include #include +#include +#include + +#undef LOG_NDEBUG +#define LOG_NDEBUG 1 #include #include "android_os_Parcel.h" @@ -61,6 +67,22 @@ static void throwUnknownTypeException(JNIEnv * env, jint type) { jniThrowException(env, "java/lang/IllegalStateException", msg.string()); } +static int getFdCount() { + char fdpath[PATH_MAX]; + int count = 0; + snprintf(fdpath, PATH_MAX, "/proc/%d/fd", getpid()); + DIR *dir = opendir(fdpath); + if (dir != NULL) { + struct dirent *dirent; + while ((dirent = readdir(dir))) { + count++; + } + count -= 2; // discount "." and ".." + closedir(dir); + } + return count; +} + static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) { String8 name; const char* nameStr = env->GetStringUTFChars(nameObj, NULL); @@ -85,7 +107,8 @@ static jlong nativeCreateFromParcel(JNIEnv* env, jclass clazz, jobject parcelObj CursorWindow* window; status_t status = CursorWindow::createFromParcel(parcel, &window); if (status || !window) { - ALOGE("Could not create CursorWindow from Parcel due to error %d.", status); + ALOGE("Could not create CursorWindow from Parcel due to error %d, process fd count=%d", + status, getFdCount()); return 0; } diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp index ded4daca07073d20158b89e2e7312ad8c01a7635..2ab4a356e4360c616b08c92e5453472a67c5868d 100644 --- a/core/jni/android_graphics_Canvas.cpp +++ b/core/jni/android_graphics_Canvas.cpp @@ -614,10 +614,10 @@ static const JNINativeMethod gMethods[] = { {"native_drawPath","!(JJJ)V", (void*) CanvasJNI::drawPath}, {"nativeDrawVertices", "!(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices}, {"native_drawNinePatch", "!(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch}, - {"native_drawBitmap","!(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, + {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, {"nativeDrawBitmapMatrix", "!(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix}, - {"native_drawBitmap","!(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, - {"native_drawBitmap", "!(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, + {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, + {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, {"nativeDrawBitmapMesh", "!(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, {"native_drawText","!(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars}, {"native_drawText","!(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString}, diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp index 4b2a72d8e28e39ebd6da3d1cb86f1707380ad949..ade718b9e6b80603892339bb6c5502c2b9abf656 100644 --- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp @@ -83,11 +83,13 @@ static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishLis } static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, - jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) { + jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount, + jint repeatMode) { PropertyValuesAnimatorSet* set = reinterpret_cast(animatorSetPtr); PropertyValuesHolder* holder = reinterpret_cast(propertyHolderPtr); Interpolator* interpolator = reinterpret_cast(interpolatorPtr); - set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount); + RepeatMode mode = static_cast(repeatMode); + set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount, mode); } static jlong createAnimatorSet(JNIEnv*, jobject) { @@ -95,6 +97,12 @@ static jlong createAnimatorSet(JNIEnv*, jobject) { return reinterpret_cast(animatorSet); } +static void setVectorDrawableTarget(JNIEnv*, jobject,jlong animatorPtr, jlong vectorDrawablePtr) { + VectorDrawable::Tree* tree = reinterpret_cast(vectorDrawablePtr); + PropertyValuesAnimatorSet* set = reinterpret_cast(animatorPtr); + set->setVectorDrawable(tree); +} + static jlong createGroupPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, jfloat startValue, jfloat endValue) { VectorDrawable::Group* group = reinterpret_cast(nativePtr); @@ -136,14 +144,24 @@ static jlong createRootAlphaPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jf startValue, endValue); return reinterpret_cast(newHolder); } -static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, +static void setFloatPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, jfloatArray srcData, jint length) { - jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr); - PropertyValuesHolder* holder = reinterpret_cast(propertyHolderPtr); + PropertyValuesHolderImpl* holder = + reinterpret_cast*>(propertyHolderPtr); holder->setPropertyDataSource(propertyData, length); env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT); } + +static void setIntPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, + jintArray srcData, jint length) { + jint* propertyData = env->GetIntArrayElements(srcData, nullptr); + PropertyValuesHolderImpl* holder = + reinterpret_cast*>(propertyHolderPtr); + holder->setPropertyDataSource(propertyData, length); + env->ReleaseIntArrayElements(srcData, propertyData, JNI_ABORT); +} + static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { PropertyValuesAnimatorSet* set = reinterpret_cast(animatorSetPtr); AnimationListener* listener = createAnimationListener(env, finishListener, id); @@ -168,13 +186,15 @@ static void reset(JNIEnv*, jobject, jlong animatorSetPtr) { static const JNINativeMethod gMethods[] = { {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet}, - {"nAddAnimator", "(JJJJJI)V", (void*)addAnimator}, + {"nSetVectorDrawableTarget", "(JJ)V", (void*)setVectorDrawableTarget}, + {"nAddAnimator", "(JJJJJII)V", (void*)addAnimator}, {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder}, {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder}, {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder}, {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder}, {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder}, - {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData}, + {"nSetPropertyHolderData", "(J[FI)V", (void*)setFloatPropertyHolderData}, + {"nSetPropertyHolderData", "(J[II)V", (void*)setIntPropertyHolderData}, {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start}, {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse}, {"nEnd", "!(J)V", (void*)end}, diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 94592573e61ad0706f0dbdc6baa8735381bedeaa..b9262701005986101c3f872a5e6c2f6497a741e4 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -350,9 +350,16 @@ void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, con postData(msgType, dataPtr, NULL); } -void JNICameraContext::postRecordingFrameHandleTimestamp(nsecs_t, native_handle_t*) { - // This is not needed at app layer. This should not be called because JNICameraContext cannot - // start video recording. +void JNICameraContext::postRecordingFrameHandleTimestamp(nsecs_t, native_handle_t* handle) { + // Video buffers are not needed at app layer so just return the video buffers here. + // This may be called when stagefright just releases camera but there are still outstanding + // video buffers. + if (mCamera != nullptr) { + mCamera->releaseRecordingFrameHandle(handle); + } else { + native_handle_close(handle); + native_handle_delete(handle); + } } void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_metadata_t *metadata) diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp index f37fd78f6bdd55eca59887daa064b87cad31e16d..518f99e864345e899ad980cafaa8f9437fc4cc4f 100644 --- a/core/jni/android_hardware_camera2_CameraMetadata.cpp +++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp @@ -43,8 +43,6 @@ #include // for socketpair #include // for socketpair -static const bool kIsDebug = false; - // fully-qualified class name #define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative" #define CHARACTERISTICS_KEY_CLASS_NAME "android/hardware/camera2/CameraCharacteristics$Key" @@ -787,109 +785,16 @@ static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyN // exception thrown by ScopedUtfChars return 0; } - size_t keyLength = strlen(key); - ALOGV("%s (key = '%s')", __FUNCTION__, key); - sp vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor(); - - SortedVector vendorSections; - size_t vendorSectionCount = 0; - - if (vTags != NULL) { - vendorSections = vTags->getAllSectionNames(); - vendorSectionCount = vendorSections.size(); - } - - // First, find the section by the longest string match - const char *section = NULL; - size_t sectionIndex = 0; - size_t sectionLength = 0; - size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount; - for (size_t i = 0; i < totalSectionCount; ++i) { - - const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] : - vendorSections[i - ANDROID_SECTION_COUNT].string(); - if (kIsDebug) { - ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str); - } - if (strstr(key, str) == key) { // key begins with the section name - size_t strLength = strlen(str); - - if (kIsDebug) { - ALOGV("%s: Key begins with section name", __FUNCTION__); - } - - // section name is the longest we've found so far - if (section == NULL || sectionLength < strLength) { - section = str; - sectionIndex = i; - sectionLength = strLength; - - if (kIsDebug) { - ALOGV("%s: Found new best section (%s)", __FUNCTION__, section); - } - } - } - } - - // TODO: Make above get_camera_metadata_section_from_name ? - - if (section == NULL) { - jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", - "Could not find section name for key '%s')", key); - return 0; - } else { - ALOGV("%s: Found matched section '%s' (%zu)", - __FUNCTION__, section, sectionIndex); - } - - // Get the tag name component of the key - const char *keyTagName = key + sectionLength + 1; // x.y.z -> z - if (sectionLength + 1 >= keyLength) { - jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", - "Key length too short for key '%s')", key); - return 0; - } - - // Match rest of name against the tag names in that section only uint32_t tag = 0; - if (sectionIndex < ANDROID_SECTION_COUNT) { - // Match built-in tags (typically android.*) - uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd) - tagBegin = camera_metadata_section_bounds[sectionIndex][0]; - tagEnd = camera_metadata_section_bounds[sectionIndex][1]; - - for (tag = tagBegin; tag < tagEnd; ++tag) { - const char *tagName = get_camera_metadata_tag_name(tag); - - if (strcmp(keyTagName, tagName) == 0) { - ALOGV("%s: Found matched tag '%s' (%d)", - __FUNCTION__, tagName, tag); - break; - } - } - - if (tag == tagEnd) { - jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", - "Could not find tag name for key '%s')", key); - return 0; - } - } else if (vTags != NULL) { - // Match vendor tags (typically com.*) - const String8 sectionName(section); - const String8 tagName(keyTagName); - - status_t res = OK; - if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) { - jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", - "%s: No vendor tag matches key '%s'", __FUNCTION__, key); - return 0; - } + sp vTags = + VendorTagDescriptor::getGlobalVendorTagDescriptor(); + status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag); + if (res != OK) { + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "Could not find tag for key '%s')", key); } - - // TODO: Make above get_camera_metadata_tag_from_name ? - return tag; } diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp index 3881d6d9e99f4d6e8bacc77b7c9a18eb4b3d0568..8eb39e1aac580e7651a6ccc87424ce868b900243 100644 --- a/core/jni/android_hardware_location_ContextHubService.cpp +++ b/core/jni/android_hardware_location_ContextHubService.cpp @@ -21,28 +21,43 @@ #include #include -#include -#include +#include #include #include #include #include +// TOOD: On master, alphabetize these and move into this +// grouping. +#include +#include +#include + #include #include "JNIHelp.h" #include "core_jni_helpers.h" -static constexpr int OS_APP_ID=-1; +static constexpr jint OS_APP_ID = -1; +static constexpr jint INVALID_APP_ID = -2; +static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF); + +static constexpr jint MIN_APP_ID = 1; +static constexpr jint MAX_APP_ID = 128; + +static constexpr size_t MSG_HEADER_SIZE = 4; +static constexpr size_t HEADER_FIELD_MSG_TYPE = 0; +static constexpr size_t HEADER_FIELD_MSG_VERSION = 1; +static constexpr size_t HEADER_FIELD_HUB_HANDLE = 2; +static constexpr size_t HEADER_FIELD_APP_INSTANCE = 3; -static constexpr int MIN_APP_ID=1; -static constexpr int MAX_APP_ID=128; +static constexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE; +static constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1; +static constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2; -static constexpr size_t MSG_HEADER_SIZE=4; -static constexpr int HEADER_FIELD_MSG_TYPE=0; -//static constexpr int HEADER_FIELD_MSG_VERSION=1; -static constexpr int HEADER_FIELD_HUB_HANDLE=2; -static constexpr int HEADER_FIELD_APP_INSTANCE=3; +// Monotonically increasing clock we use to determine if we can cancel +// a transaction. +using std::chrono::steady_clock; namespace android { @@ -83,6 +98,7 @@ struct jniInfo_s { jmethodID contextHubServiceMsgReceiptCallback; jmethodID contextHubServiceAddAppInstance; + jmethodID contextHubServiceDeleteAppInstance; }; struct context_hub_info_s { @@ -93,24 +109,151 @@ struct context_hub_info_s { }; struct app_instance_info_s { - uint32_t hubHandle; // Id of the hub this app is on - int instanceId; // systemwide unique instance id - assigned + uint64_t truncName; // Possibly truncated name for logging + uint32_t hubHandle; // Id of the hub this app is on + jint instanceId; // system wide unique instance id - assigned struct hub_app_info appInfo; // returned from the HAL - uint64_t truncName; // Possibly truncated name - logging +}; + + +// If a transaction takes longer than this, we'll allow it to be +// canceled by a new transaction. Note we do _not_ automatically +// cancel a transaction after this much time. We can have a +// legal transaction which takes longer than this amount of time, +// as long as no other new transactions are attempted after this +// time has expired. +// TODO(b/31105001): Establish a clean timing approach for all +// of our HAL interactions. +constexpr auto kMinTransactionCancelTime = std::chrono::seconds(29); + +/* + * TODO(ashutoshj): From original code review: + * + * So, I feel like we could possible do a better job of organizing this code, + * and being more C++-y. Consider something like this: + * class TxnManager { + * public: + * TxnManager(); + * ~TxnManager(); + * int add(hub_message_e identifier, void *data); + * int close(); + * bool isPending() const; + * int fetchData(hub_message_e *identifier, void **data) const; + * + * private: + * bool mPending; + * mutable std::mutex mLock; + * hub_message_e mIdentifier; + * void *mData; + * }; + * + * And then, for example, we'd have things like: + * TxnManager::TxnManager() : mPending(false), mLock(), mIdentifier(), mData(nullptr) {} + * int TxnManager::add(hub_message_e identifier, void *data) { + * std::lock_guard lock(mLock); + * mPending = true; + * mData = txnData; + * mIdentifier = txnIdentifier; + * return 0; + * } + * And then calling code would look like: + * if (!db.txnManager.add(CONTEXT_HUB_LOAD_APP, txnInfo)) { + * + * This would make it clearer the nothing is manipulating any state within TxnManager + * unsafely and outside of these couple of calls. + */ +struct txnManager_s { + bool txnPending; // Is a transaction pending + std::mutex m; // mutex for manager + hub_messages_e txnIdentifier; // What are we doing + void *txnData; // Details + steady_clock::time_point firstTimeTxnCanBeCanceled; }; struct contextHubServiceDb_s { int initialized; context_hub_info_s hubInfo; jniInfo_s jniInfo; - std::queue freeIds; - std::unordered_map appInstances; + std::queue freeIds; + std::unordered_map appInstances; + txnManager_s txnManager; }; } // unnamed namespace static contextHubServiceDb_s db; +static bool initTxnManager() { + txnManager_s *mgr = &db.txnManager; + + mgr->txnData = nullptr; + mgr->txnPending = false; + return true; +} + +static int addTxn(hub_messages_e txnIdentifier, void *txnData) { + txnManager_s *mgr = &db.txnManager; + + std::lock_guardlock(mgr->m); + + mgr->txnPending = true; + mgr->firstTimeTxnCanBeCanceled = steady_clock::now() + + kMinTransactionCancelTime; + mgr->txnData = txnData; + mgr->txnIdentifier = txnIdentifier; + + return 0; +} + +// Only call this if you hold the db.txnManager.m lock. +static void closeTxnUnlocked() { + txnManager_s *mgr = &db.txnManager; + mgr->txnPending = false; + free(mgr->txnData); + mgr->txnData = nullptr; +} + +static int closeTxn() { + std::lock_guardlock(db.txnManager.m); + closeTxnUnlocked(); + return 0; +} + +// If a transaction has been pending for longer than +// kMinTransactionCancelTime, this call will "cancel" that +// transaction and return that there are none pending. +static bool isTxnPending() { + txnManager_s *mgr = &db.txnManager; + std::lock_guardlock(mgr->m); + if (mgr->txnPending) { + if (steady_clock::now() >= mgr->firstTimeTxnCanBeCanceled) { + ALOGW("Transaction canceled"); + closeTxnUnlocked(); + } + } + return mgr->txnPending; +} + +static int fetchTxnData(hub_messages_e *id, void **data) { + txnManager_s *mgr = &db.txnManager; + + if (!id || !data) { + ALOGW("Null params id %p, data %p", id, data); + return -1; + } + + std::lock_guardlock(mgr->m); + if (!mgr->txnPending) { + ALOGW("No Transactions pending"); + return -1; + } + + // else + *id = mgr->txnIdentifier; + *data = mgr->txnData; + return 0; +} + int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg, void *cookie); @@ -152,18 +295,27 @@ static int get_hub_id_for_hub_handle(int hubHandle) { } } -static int get_hub_id_for_app_instance(int id) { +static int get_hub_handle_for_app_instance(jint id) { if (!db.appInstances.count(id)) { - ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id); + ALOGD("%s: Cannot find app for app instance %" PRId32, + __FUNCTION__, id); return -1; } - int hubHandle = db.appInstances[id].hubHandle; + return db.appInstances[id].hubHandle; +} + +static int get_hub_id_for_app_instance(jint id) { + int hubHandle = get_hub_handle_for_app_instance(id); + + if (hubHandle < 0) { + return -1; + } return db.hubInfo.hubs[hubHandle].hub_id; } -static int get_app_instance_for_app_id(uint64_t app_id) { +static jint get_app_instance_for_app_id(uint64_t app_id) { auto end = db.appInstances.end(); for (auto current = db.appInstances.begin(); current != end; ++current) { if (current->second.appInfo.app_name.id == app_id) { @@ -174,9 +326,10 @@ static int get_app_instance_for_app_id(uint64_t app_id) { return -1; } -static int set_dest_app(hub_message_t *msg, int id) { +static int set_dest_app(hub_message_t *msg, jint id) { if (!db.appInstances.count(id)) { - ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id); + ALOGD("%s: Cannot find app for app instance %" PRId32, + __FUNCTION__, id); return -1; } @@ -184,31 +337,47 @@ static int set_dest_app(hub_message_t *msg, int id) { return 0; } -static void send_query_for_apps() { +static void query_hub_for_apps(uint32_t hubHandle) { hub_message_t msg; + query_apps_request_t queryMsg; + + // TODO(b/30835598): When we're able to tell which request our + // response matches, then we should allow this to be more + // targetted, instead of always being every app in the + // system. + queryMsg.app_name.id = ALL_APPS; msg.message_type = CONTEXT_HUB_QUERY_APPS; - msg.message_len = 0; + msg.message_len = sizeof(queryMsg); + msg.message = &queryMsg; + + ALOGD("Sending query for apps to hub %" PRIu32, hubHandle); + set_os_app_as_destination(&msg, hubHandle); + if (send_msg_to_hub(&msg, hubHandle) != 0) { + ALOGW("Could not query hub %" PRIu32 " for apps", hubHandle); + } +} +static void sendQueryForApps() { for (int i = 0; i < db.hubInfo.numHubs; i++ ) { - ALOGD("Sending query for apps to hub %d", i); - set_os_app_as_destination(&msg, i); - if (send_msg_to_hub(&msg, i) != 0) { - ALOGW("Could not query hub %i for apps", i); - } + query_hub_for_apps(i); } } -static int return_id(int id) { +static int return_id(jint id) { // Note : This method is not thread safe. - // id returned is guarenteed to be in use - db.freeIds.push(id); - return 0; + // id returned is guaranteed to be in use + if (id >= 0) { + db.freeIds.push(id); + return 0; + } + + return -1; } -static int generate_id(void) { +static jint generate_id() { // Note : This method is not thread safe. - int retVal = -1; + jint retVal = -1; if (!db.freeIds.empty()) { retVal = db.freeIds.front(); @@ -218,55 +387,113 @@ static int generate_id(void) { return retVal; } -int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *env) { + +static jint add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, + jint appInstanceHandle, JNIEnv *env) { // Not checking if the apps are indeed distinct app_instance_info_s entry; - int appInstanceHandle = generate_id(); - assert(appInfo); - if (appInstanceHandle < 0) { - ALOGE("Cannot find resources to add app instance %d", - appInstanceHandle); - return -1; - } + const char *action = + (db.appInstances.count(appInstanceHandle) == 0) ? "Added" : "Updated"; entry.appInfo = *appInfo; + entry.instanceId = appInstanceHandle; entry.truncName = appInfo->app_name.id; entry.hubHandle = hubHandle; + db.appInstances[appInstanceHandle] = entry; - // Finally - let the service know of this app instance + // Finally - let the service know of this app instance, to populate + // the Java cache. env->CallIntMethod(db.jniInfo.jContextHubService, db.jniInfo.contextHubServiceAddAppInstance, hubHandle, entry.instanceId, entry.truncName, entry.appInfo.version); - ALOGW("Added App 0x%" PRIx64 " on hub Handle %" PRId32 - " as appInstance %d", entry.truncName, + ALOGI("%s App 0x%" PRIx64 " on hub Handle %" PRId32 + " as appInstance %" PRId32, action, entry.truncName, entry.hubHandle, appInstanceHandle); return appInstanceHandle; } -int delete_app_instance(int id) { - if (!db.appInstances.count(id)) { +int delete_app_instance(jint id, JNIEnv *env) { + bool fullyDeleted = true; + + if (db.appInstances.count(id)) { + db.appInstances.erase(id); + } else { + ALOGW("Cannot delete App id (%" PRId32 ") from the JNI C++ cache", id); + fullyDeleted = false; + } + return_id(id); + + if ((env == nullptr) || + (env->CallIntMethod(db.jniInfo.jContextHubService, + db.jniInfo.contextHubServiceDeleteAppInstance, + id) != 0)) { + ALOGW("Cannot delete App id (%" PRId32 ") from Java cache", id); + fullyDeleted = false; + } + + if (fullyDeleted) { + ALOGI("Deleted App id : %" PRId32, id); + return 0; + } + return -1; +} + +static int startLoadAppTxn(uint64_t appId, int hubHandle) { + app_instance_info_s *txnInfo = (app_instance_info_s *)malloc(sizeof(app_instance_info_s)); + jint instanceId = generate_id(); + + if (!txnInfo || instanceId < 0) { + return_id(instanceId); + free(txnInfo); return -1; } - return_id(id); - db.appInstances.erase(id); + txnInfo->truncName = appId; + txnInfo->hubHandle = hubHandle; + txnInfo->instanceId = instanceId; + + txnInfo->appInfo.app_name.id = appId; + txnInfo->appInfo.num_mem_ranges = 0; + txnInfo->appInfo.version = -1; // Awaited + + if (addTxn(CONTEXT_HUB_LOAD_APP, txnInfo) != 0) { + return_id(instanceId); + free(txnInfo); + return -1; + } return 0; } +static int startUnloadAppTxn(jint appInstanceHandle) { + jint *txnData = (jint *) malloc(sizeof(jint)); + if (!txnData) { + ALOGW("Cannot allocate memory to start unload transaction"); + return -1; + } + + *txnData = appInstanceHandle; + + if (addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) { + free(txnData); + ALOGW("Cannot start transaction to unload app"); + return -1; + } + + return 0; +} static void initContextHubService() { int err = 0; db.hubInfo.hubs = nullptr; db.hubInfo.numHubs = 0; - int i; err = hw_get_module(CONTEXT_HUB_MODULE_ID, (hw_module_t const**)(&db.hubInfo.contextHubModule)); @@ -277,10 +504,11 @@ static void initContextHubService() { } // Prep for storing app info - for(i = MIN_APP_ID; i <= MAX_APP_ID; i++) { + for (jint i = MIN_APP_ID; i <= MAX_APP_ID; i++) { db.freeIds.push(i); } + initTxnManager(); if (db.hubInfo.contextHubModule) { int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule, &db.hubInfo.hubs); @@ -296,8 +524,9 @@ static void initContextHubService() { return; } - for (i = 0; i < db.hubInfo.numHubs; i++) { + for (int i = 0; i < db.hubInfo.numHubs; i++) { db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id; + ALOGI("Subscribing to hubHandle %d with OS App name %" PRIu64, i, db.hubInfo.hubs[i].os_app_name.id); if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id, context_hub_callback, &db.hubInfo.cookies[i]) == 0) { @@ -305,7 +534,7 @@ static void initContextHubService() { } } - send_query_for_apps(); + sendQueryForApps(); } else { ALOGW("No Context Hub Module present"); } @@ -342,61 +571,303 @@ static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_ return ret; } -int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) { +int handle_query_apps_response(const uint8_t *msg, int msgLen, + uint32_t hubHandle) { JNIEnv *env; if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) { return -1; } - int numApps = msgLen/sizeof(hub_app_info); - hub_app_info info; - hub_app_info *unalignedInfoAddr = (hub_app_info*)msg; + int numApps = msgLen / sizeof(hub_app_info); + const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg; + + // We use this information to sync our JNI and Java caches of nanoapp info. + // We want to accomplish two things here: + // 1) Remove entries from our caches which are stale, and pertained to + // apps no longer running on Context Hub. + // 2) Populate our caches with the latest information of all these apps. + + // We make a couple of assumptions here: + // A) The JNI and Java caches are in sync with each other (this isn't + // necessarily true; any failure of a single call into Java land to + // update its cache will leave that cache in a bad state. For NYC, + // we're willing to tolerate this for now). + // B) The total number of apps is relatively small, so horribly inefficent + // algorithms aren't too painful. + // C) We're going to call this relatively infrequently, so its inefficency + // isn't a big impact. + + + // (1). Looking for stale cache entries. Yes, this is O(N^2). See + // assumption (B). Per assumption (A), it is sufficient to iterate + // over just the JNI cache. + auto end = db.appInstances.end(); + for (auto current = db.appInstances.begin(); current != end; ) { + app_instance_info_s cache_entry = current->second; + // We perform our iteration here because if we call + // delete_app_instance() below, it will erase() this entry. + current++; + bool entryIsStale = true; + for (int i = 0; i < numApps; i++) { + // We use memcmp since this could be unaligned. + if (memcmp(&unalignedInfoAddr[i].app_name.id, + &cache_entry.appInfo.app_name.id, + sizeof(cache_entry.appInfo.app_name.id)) == 0) { + // We found a match; this entry is current. + entryIsStale = false; + break; + } + } + if (entryIsStale) { + delete_app_instance(cache_entry.instanceId, env); + } + } - for (int i = 0; i < numApps; i++, unalignedInfoAddr++) { - memcpy(&info, unalignedInfoAddr, sizeof(info)); - add_app_instance(&info, hubHandle, env); + // (2). Update our caches with the latest. + for (int i = 0; i < numApps; i++) { + hub_app_info query_info; + memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info)); + // We will only have one instance of the app + // TODO : Change this logic once we support multiple instances of the same app + jint appInstance = get_app_instance_for_app_id(query_info.app_name.id); + if (appInstance == -1) { + // This is a previously unknown app, let's allocate an "id" for it. + appInstance = generate_id(); + } + add_app_instance(&query_info, hubHandle, appInstance, env); } return 0; } +// TODO(b/30807327): Do not use raw bytes for additional data. Use the +// JNI interfaces for the appropriate types. +static void passOnOsResponse(uint32_t hubHandle, uint32_t msgType, + status_response_t *rsp, int8_t *additionalData, + size_t additionalDataLen) { + JNIEnv *env; -int handle_os_message(uint32_t msgType, uint32_t hubHandle, - char *msg, int msgLen) { - int retVal; + if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) { + ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32, msgType); + return; + } - //ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d", - // hubHandle, msgType, msgLen); + uint32_t header[MSG_HEADER_SIZE]; + memset(header, 0, sizeof(header)); - switch(msgType) { - case CONTEXT_HUB_APPS_ENABLE: - retVal = 0; - break; + if (!additionalData) { + additionalDataLen = 0; // clamp + } + int msgLen = 1 + additionalDataLen; - case CONTEXT_HUB_APPS_DISABLE: - retVal = 0; - break; + int8_t *msg = new int8_t[msgLen]; - case CONTEXT_HUB_LOAD_APP: - retVal = 0; - break; + if (!msg) { + ALOGW("Unexpected : Ran out of memory, cannot send response"); + return; + } - case CONTEXT_HUB_UNLOAD_APP: - retVal = 0; - break; + header[HEADER_FIELD_MSG_TYPE] = msgType; + header[HEADER_FIELD_MSG_VERSION] = 0; + header[HEADER_FIELD_HUB_HANDLE] = hubHandle; + header[HEADER_FIELD_APP_INSTANCE] = OS_APP_ID; + + // Due to API constraints, at the moment we can't change the fact that + // we're changing our 4-byte response to a 1-byte value. But we can prevent + // the possible change in sign (and thus meaning) that would happen from + // a naive cast. Further, we can log when we're losing part of the value. + // TODO(b/30918279): Don't truncate this result. + int8_t truncatedResult; + bool neededToTruncate; + if (rsp->result < INT8_MIN) { + neededToTruncate = true; + truncatedResult = INT8_MIN; + } else if (rsp->result > INT8_MAX) { + neededToTruncate = true; + truncatedResult = INT8_MAX; + } else { + neededToTruncate = false; + // Since this value fits within an int8_t, this is a safe cast which + // won't change the value or sign. + truncatedResult = static_cast(rsp->result); + } + if (neededToTruncate) { + ALOGW("Response from Context Hub truncated. Value was %" PRId32 + ", but giving Java layer %" PRId8, + rsp->result, (int)truncatedResult); + } + + msg[0] = truncatedResult; + + if (additionalData) { + memcpy(&msg[1], additionalData, additionalDataLen); + } + + jbyteArray jmsg = env->NewByteArray(msgLen); + jintArray jheader = env->NewIntArray(sizeof(header)); - case CONTEXT_HUB_QUERY_APPS: - retVal = handle_query_apps_response(msg, msgLen, hubHandle); - break; + env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg); + env->SetIntArrayRegion(jheader, 0, sizeof(header), (jint *)header); + + ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32, + header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE], + header[HEADER_FIELD_HUB_HANDLE]); - case CONTEXT_HUB_QUERY_MEMORY: - retVal = 0; - break; + env->CallIntMethod(db.jniInfo.jContextHubService, + db.jniInfo.contextHubServiceMsgReceiptCallback, + jheader, jmsg); + env->DeleteLocalRef(jmsg); + env->DeleteLocalRef(jheader); - default: - retVal = -1; - break; + delete[] msg; +} +void closeUnloadTxn(bool success) { + void *txnData = nullptr; + hub_messages_e txnId; + + if (success && fetchTxnData(&txnId, &txnData) == 0 && + txnId == CONTEXT_HUB_UNLOAD_APP) { + JNIEnv *env; + if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) { + ALOGW("Could not attach to JVM !"); + env = nullptr; + } + jint handle = *reinterpret_cast(txnData); + delete_app_instance(handle, env); + } else { + ALOGW("Could not unload the app successfully ! success %d, txnData %p", success, txnData); + } + + closeTxn(); +} + +static bool closeLoadTxn(bool success, jint *appInstanceHandle) { + void *txnData; + hub_messages_e txnId; + + if (success && fetchTxnData(&txnId, &txnData) == 0 && + txnId == CONTEXT_HUB_LOAD_APP) { + app_instance_info_s *info = (app_instance_info_s *)txnData; + *appInstanceHandle = info->instanceId; + + JNIEnv *env; + if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) == JNI_OK) { + add_app_instance(&info->appInfo, info->hubHandle, info->instanceId, env); + } else { + ALOGW("Could not attach to JVM !"); + success = false; + } + // While we just called add_app_instance above, our info->appInfo was + // incomplete (for example, the 'version' is hardcoded to -1). So we + // trigger an additional query to the CHRE, so we'll be able to get + // all the app "info", and have our JNI and Java caches with the + // full information. + sendQueryForApps(); + } else { + ALOGW("Could not load the app successfully ! Unexpected failure"); + *appInstanceHandle = INVALID_APP_ID; + success = false; + } + + closeTxn(); + return success; +} + +static bool isValidOsStatus(const uint8_t *msg, size_t msgLen, + status_response_t *rsp) { + // Workaround a bug in some HALs + if (msgLen == 1) { + rsp->result = msg[0]; + return true; + } + + if (!msg || msgLen != sizeof(*rsp)) { + ALOGW("Received invalid response %p of size %zu", msg, msgLen); + return false; + } + + memcpy(rsp, msg, sizeof(*rsp)); + + // No sanity checks on return values + return true; +} + +static int handle_os_message(uint32_t msgType, uint32_t hubHandle, + const uint8_t *msg, int msgLen) { + int retVal = -1; + + ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d", + hubHandle, msgType, msgLen); + + struct status_response_t rsp; + + switch(msgType) { + + case CONTEXT_HUB_APPS_ENABLE: + case CONTEXT_HUB_APPS_DISABLE: + case CONTEXT_HUB_LOAD_APP: + case CONTEXT_HUB_UNLOAD_APP: + if (isValidOsStatus(msg, msgLen, &rsp)) { + if (msgType == CONTEXT_HUB_LOAD_APP) { + jint appInstanceHandle = INVALID_APP_ID; + bool appRunningOnHub = (rsp.result == 0); + if (!(closeLoadTxn(appRunningOnHub, &appInstanceHandle))) { + if (appRunningOnHub) { + // Now we're in an odd situation. Our nanoapp + // is up and running on the Context Hub. However, + // something went wrong in our Service code so that + // we're not able to properly track this nanoapp + // in our Service code. If we tell the Java layer + // things are good, it's a lie because the handle + // we give them will fail when used with the Service. + // If we tell the Java layer this failed, it's kind + // of a lie as well, since this nanoapp is running. + // + // We leave a more robust fix for later, and for + // now just tell the user things have failed. + // + // TODO(b/30835981): Make this situation better. + rsp.result = -1; + } + } + passOnOsResponse(hubHandle, msgType, &rsp, (int8_t *)(&appInstanceHandle), + sizeof(appInstanceHandle)); + } else if (msgType == CONTEXT_HUB_UNLOAD_APP) { + closeUnloadTxn(rsp.result == 0); + passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0); + } else { + passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0); + } + retVal = 0; + } + break; + + case CONTEXT_HUB_QUERY_APPS: + rsp.result = 0; + retVal = handle_query_apps_response(msg, msgLen, hubHandle); + passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0); + break; + + case CONTEXT_HUB_QUERY_MEMORY: + // Deferring this use + retVal = 0; + break; + + case CONTEXT_HUB_OS_REBOOT: + if (isValidOsStatus(msg, msgLen, &rsp)) { + rsp.result = 0; + ALOGW("Context Hub handle %d restarted", hubHandle); + closeTxn(); + passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0); + query_hub_for_apps(hubHandle); + retVal = 0; + } + break; + + default: + retVal = -1; + break; } return retVal; @@ -416,10 +887,12 @@ static bool sanity_check_cookie(void *cookie, uint32_t hub_id) { } } + int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg, void *cookie) { if (!msg) { + ALOGW("NULL message"); return -1; } if (!sanity_check_cookie(cookie, hubId)) { @@ -429,13 +902,14 @@ int context_hub_callback(uint32_t hubId, return -1; } + uint32_t messageType = msg->message_type; uint32_t hubHandle = *(uint32_t*) cookie; if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) { - handle_os_message(messageType, hubHandle, (char*) msg->message, msg->message_len); + handle_os_message(messageType, hubHandle, (uint8_t*) msg->message, msg->message_len); } else { - int appHandle = get_app_instance_for_app_id(msg->app_name.id); + jint appHandle = get_app_instance_for_app_id(msg->app_name.id); if (appHandle < 0) { ALOGE("Filtering out message due to invalid App Instance."); } else { @@ -524,7 +998,9 @@ static int init_jni(JNIEnv *env, jobject instance) { env->GetMethodID(db.jniInfo.contextHubServiceClass, "addAppInstance", "(IIJI)I"); - + db.jniInfo.contextHubServiceDeleteAppInstance = + env->GetMethodID(db.jniInfo.contextHubServiceClass, + "deleteAppInstance", "(I)I"); return 0; } @@ -534,8 +1010,6 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t jintArray jintBuf; jobjectArray jmemBuf; - int dummyConnectedSensors[] = {1, 2, 3, 4, 5}; - jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass, db.jniInfo.contextHubInfoCtor); env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id); @@ -565,11 +1039,21 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t hub->max_supported_msg_len); - // TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors); - // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, - // hub->connected_sensors); - jintBuf = env->NewIntArray(array_length(dummyConnectedSensors)); - env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors); + jintBuf = env->NewIntArray(hub->num_connected_sensors); + int *connectedSensors = new int[hub->num_connected_sensors]; + + if (!connectedSensors) { + ALOGW("Cannot allocate memory! Unexpected"); + assert(false); + } else { + for (unsigned int i = 0; i < hub->num_connected_sensors; i++) { + connectedSensors[i] = hub->connected_sensors[i].sensor_id; + } + } + + env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, + connectedSensors); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf); env->DeleteLocalRef(jintBuf); @@ -580,6 +1064,7 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t env->DeleteLocalRef(jmemBuf); + delete[] connectedSensors; return jHub; } @@ -618,33 +1103,100 @@ static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_, jbyte *data = env->GetByteArrayElements(data_, 0); int dataBufferLength = env->GetArrayLength(data_); + if (numHeaderElements < MSG_HEADER_SIZE) { + ALOGW("Malformed header len"); + return -1; + } + + uint32_t appInstanceHandle = header[HEADER_FIELD_APP_INSTANCE]; + uint32_t msgType = header[HEADER_FIELD_MSG_TYPE]; + int hubHandle = -1; + int hubId; + uint64_t appId; + + if (msgType == CONTEXT_HUB_UNLOAD_APP) { + hubHandle = get_hub_handle_for_app_instance(appInstanceHandle); + } else if (msgType == CONTEXT_HUB_LOAD_APP) { + if (numHeaderElements < MSG_HEADER_SIZE_LOAD_APP) { + return -1; + } + uint64_t appIdLo = header[HEADER_FIELD_LOAD_APP_ID_LO]; + uint64_t appIdHi = header[HEADER_FIELD_LOAD_APP_ID_HI]; + appId = appIdHi << 32 | appIdLo; + + hubHandle = header[HEADER_FIELD_HUB_HANDLE]; + } else { + hubHandle = header[HEADER_FIELD_HUB_HANDLE]; + } + + if (hubHandle < 0) { + ALOGD("Invalid hub Handle %d", hubHandle); + return -1; + } + + if (msgType == CONTEXT_HUB_LOAD_APP || + msgType == CONTEXT_HUB_UNLOAD_APP) { + + if (isTxnPending()) { + ALOGW("Cannot load or unload app while a transaction is pending !"); + return -1; + } + + if (msgType == CONTEXT_HUB_LOAD_APP) { + if (startLoadAppTxn(appId, hubHandle) != 0) { + ALOGW("Cannot Start Load Transaction"); + return -1; + } + } else if (msgType == CONTEXT_HUB_UNLOAD_APP) { + if (startUnloadAppTxn(appInstanceHandle) != 0) { + ALOGW("Cannot Start UnLoad Transaction"); + return -1; + } + } + } + + bool setAddressSuccess = false; + hub_message_t msg; + + msg.message_type = msgType; - if (numHeaderElements >= MSG_HEADER_SIZE) { - bool setAddressSuccess; - int hubId; - hub_message_t msg; + if (msgType == CONTEXT_HUB_UNLOAD_APP) { + msg.message_len = sizeof(db.appInstances[appInstanceHandle].appInfo.app_name); + msg.message = &db.appInstances[appInstanceHandle].appInfo.app_name; + setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0); + hubId = get_hub_id_for_hub_handle(hubHandle); + } else { + msg.message_len = dataBufferLength; + msg.message = data; if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) { - setAddressSuccess = (set_os_app_as_destination(&msg, header[HEADER_FIELD_HUB_HANDLE]) == 0); - hubId = get_hub_id_for_hub_handle(header[HEADER_FIELD_HUB_HANDLE]); + setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0); + hubId = get_hub_id_for_hub_handle(hubHandle); } else { setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0); hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]); } + } - if (setAddressSuccess && hubId >= 0) { - msg.message_type = header[HEADER_FIELD_MSG_TYPE]; - msg.message_len = dataBufferLength; - msg.message = data; - retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg); - } else { - ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d", - header[HEADER_FIELD_APP_INSTANCE], - header[HEADER_FIELD_HUB_HANDLE], - (int)setAddressSuccess); - } + if (setAddressSuccess && hubId >= 0) { + ALOGD("Asking HAL to remove app"); + retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg); } else { - ALOGD("Malformed header len"); + ALOGD("Could not find app instance %" PRId32 " on hubHandle %" PRId32 + ", setAddress %d", + header[HEADER_FIELD_APP_INSTANCE], + header[HEADER_FIELD_HUB_HANDLE], + (int)setAddressSuccess); + } + + if (retVal != 0) { + ALOGD("Send Message failure - %d", retVal); + if (msgType == CONTEXT_HUB_LOAD_APP) { + jint ignored; + closeLoadTxn(false, &ignored); + } else if (msgType == CONTEXT_HUB_UNLOAD_APP) { + closeUnloadTxn(false); + } } env->ReleaseIntArrayElements(header_, header, 0); diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index 6513304463820584efe6cbd95f285ee57cdaf6bf..092aaf62bbc0a6c1de681b1abbcd76bf2c2fe89d 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -20,18 +20,20 @@ #include // keep these values in sync with AudioFormat.java -#define ENCODING_PCM_16BIT 2 -#define ENCODING_PCM_8BIT 3 -#define ENCODING_PCM_FLOAT 4 -#define ENCODING_AC3 5 -#define ENCODING_E_AC3 6 -#define ENCODING_DTS 7 -#define ENCODING_DTS_HD 8 -#define ENCODING_MP3 9 -#define ENCODING_AAC_LC 10 -#define ENCODING_AAC_HE_V1 11 -#define ENCODING_AAC_HE_V2 12 -#define ENCODING_IEC61937 13 +#define ENCODING_PCM_16BIT 2 +#define ENCODING_PCM_8BIT 3 +#define ENCODING_PCM_FLOAT 4 +#define ENCODING_AC3 5 +#define ENCODING_E_AC3 6 +#define ENCODING_DTS 7 +#define ENCODING_DTS_HD 8 +#define ENCODING_MP3 9 +#define ENCODING_AAC_LC 10 +#define ENCODING_AAC_HE_V1 11 +#define ENCODING_AAC_HE_V2 12 +#define ENCODING_IEC61937 13 +#define ENCODING_DOLBY_TRUEHD 14 + #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -65,6 +67,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC_HE_V1; case ENCODING_AAC_HE_V2: return AUDIO_FORMAT_AAC_HE_V2; + case ENCODING_DOLBY_TRUEHD: + return AUDIO_FORMAT_DOLBY_TRUEHD; case ENCODING_IEC61937: return AUDIO_FORMAT_IEC61937; case ENCODING_DEFAULT: @@ -108,6 +112,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_AAC_HE_V2; case AUDIO_FORMAT_IEC61937: return ENCODING_IEC61937; + case AUDIO_FORMAT_DOLBY_TRUEHD: + return ENCODING_DOLBY_TRUEHD; case AUDIO_FORMAT_DEFAULT: return ENCODING_DEFAULT; default: diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index ef16ef5055de4f53170d0100fc67a0414cd2c9e9..497600212095c9095c2d9a520c3696894671b125 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -20,13 +20,14 @@ #define LOG_TAG "AudioSystem-JNI" #include +#include #include #include #include "core_jni_helpers.h" #include #include - +#include #include #include #include "android_media_AudioFormat.h" @@ -903,6 +904,12 @@ static bool hasFormat(int* formats, size_t size, int format) { return false; // not found } +// TODO: pull out to separate file +template +static constexpr size_t array_size(const T (&)[N]) { + return N; +} + static jint convertAudioPortFromNative(JNIEnv *env, jobject *jAudioPort, const struct audio_port *nAudioPort) { @@ -923,6 +930,38 @@ static jint convertAudioPortFromNative(JNIEnv *env, ALOGV("convertAudioPortFromNative id %d role %d type %d name %s", nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name); + // Verify audio port array count info. + if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates) + || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks) + || nAudioPort->num_formats > array_size(nAudioPort->formats) + || nAudioPort->num_gains > array_size(nAudioPort->gains)) { + + std::stringstream ss; + ss << "convertAudioPortFromNative array count out of bounds:" + << " num_sample_rates " << nAudioPort->num_sample_rates + << " num_channel_masks " << nAudioPort->num_channel_masks + << " num_formats " << nAudioPort->num_formats + << " num_gains " << nAudioPort->num_gains + ; + std::string s = ss.str(); + + // Prefer to log through Java wtf instead of native ALOGE. + ScopedLocalRef jLogClass(env, env->FindClass("android/util/Log")); + jmethodID jWtfId = (jLogClass.get() == nullptr) + ? nullptr + : env->GetStaticMethodID(jLogClass.get(), "wtf", + "(Ljava/lang/String;Ljava/lang/String;)I"); + if (jWtfId != nullptr) { + ScopedLocalRef jMessage(env, env->NewStringUTF(s.c_str())); + ScopedLocalRef jTag(env, env->NewStringUTF(LOG_TAG)); + (void)env->CallStaticIntMethod(jLogClass.get(), jWtfId, jTag.get(), jMessage.get()); + } else { + ALOGE("%s", s.c_str()); + } + jStatus = (jint)AUDIO_JAVA_ERROR; + goto exit; + } + jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates); if (jSamplingRates == NULL) { jStatus = (jint)AUDIO_JAVA_ERROR; @@ -1066,7 +1105,7 @@ static jint convertAudioPortFromNative(JNIEnv *env, &jAudioPortConfig, &nAudioPort->active_config); if (jStatus != AUDIO_JAVA_SUCCESS) { - return jStatus; + goto exit; } env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig); diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index f79254dc2e5a5c202deadead0d5f7cd7ea082dd3..26a2cf01266c218626efd5137742891b552aa33a 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -122,6 +122,99 @@ static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject } } +static void android_net_utils_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd, + jint ifIndex) +{ + static const int kLinkLocalHopLimit = 255; + + int fd = jniGetFDFromFileDescriptor(env, javaFd); + + // Set an ICMPv6 filter that only passes Router Solicitations. + struct icmp6_filter rs_only; + ICMP6_FILTER_SETBLOCKALL(&rs_only); + ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only); + socklen_t len = sizeof(rs_only); + if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(ICMP6_FILTER): %s", strerror(errno)); + return; + } + + // Most/all of the rest of these options can be set via Java code, but + // because we're here on account of setting an icmp6_filter go ahead + // and do it all natively for now. + // + // TODO: Consider moving these out to Java. + + // Set the multicast hoplimit to 255 (link-local only). + int hops = kLinkLocalHopLimit; + len = sizeof(hops); + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno)); + return; + } + + // Set the unicast hoplimit to 255 (link-local only). + hops = kLinkLocalHopLimit; + len = sizeof(hops); + if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno)); + return; + } + + // Explicitly disable multicast loopback. + int off = 0; + len = sizeof(off); + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno)); + return; + } + + // Specify the IPv6 interface to use for outbound multicast. + len = sizeof(ifIndex); + if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno)); + return; + } + + // Additional options to be considered: + // - IPV6_TCLASS + // - IPV6_RECVPKTINFO + // - IPV6_RECVHOPLIMIT + + // Bind to [::]. + const struct sockaddr_in6 sin6 = { + .sin6_family = AF_INET6, + .sin6_port = 0, + .sin6_flowinfo = 0, + .sin6_addr = IN6ADDR_ANY_INIT, + .sin6_scope_id = 0, + }; + auto sa = reinterpret_cast(&sin6); + len = sizeof(sin6); + if (bind(fd, sa, len) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "bind(IN6ADDR_ANY): %s", strerror(errno)); + return; + } + + // Join the all-routers multicast group, ff02::2%index. + struct ipv6_mreq all_rtrs = { + .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}}, + .ipv6mr_interface = ifIndex, + }; + len = sizeof(all_rtrs); + if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno)); + return; + } +} + static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId) { return (jboolean) !setNetworkForProcess(netId); @@ -170,6 +263,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = { { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess }, { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter }, { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter }, + { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_setupRaSocket }, }; int register_android_net_NetworkUtils(JNIEnv* env) diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 1e6b125b0e961a817c07de1c13187dbce74d34a9..428159a75e875e8fd036aef90759c1623bfa5e77 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include // for AID_SYSTEM @@ -41,6 +42,7 @@ #include "ScopedUtfChars.h" #include "utils/Log.h" #include "utils/misc.h" +#include "utils/String8.h" extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap); extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap); @@ -184,11 +186,20 @@ static void verifySystemIdmaps() argv[argc++] = AssetManager::TARGET_APK_PATH; argv[argc++] = AssetManager::IDMAP_DIR; - // Directories to scan for overlays - // /vendor/overlay - if (stat(AssetManager::OVERLAY_DIR, &st) == 0) { - argv[argc++] = AssetManager::OVERLAY_DIR; - } + // Directories to scan for overlays: if OVERLAY_SKU_DIR_PROPERTY is defined, + // use OVERLAY_DIR/ if exists, otherwise + // use OVERLAY_DIR if exists. + char subdir[PROP_VALUE_MAX]; + int len = __system_property_get(AssetManager::OVERLAY_SKU_DIR_PROPERTY, subdir); + String8 overlayPath; + if (len > 0) { + overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir; + } else { + overlayPath = String8(AssetManager::OVERLAY_DIR); + } + if (stat(overlayPath.string(), &st) == 0) { + argv[argc++] = overlayPath.string(); + } // Finally, invoke idmap (if any overlay directory exists) if (argc > 5) { diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp index f45be127c99c6399263530ab62eec547720db8b6..d0c0f2f3e6d4e1301ea12b14550d2b0a6997123e 100644 --- a/core/jni/android_util_MemoryIntArray.cpp +++ b/core/jni/android_util_MemoryIntArray.cpp @@ -160,16 +160,8 @@ static jint android_util_MemoryIntArray_size(JNIEnv* env, jobject clazz, jint fd return -1; } - // Use ASHMEM_GET_SIZE to find out if the fd refers to an ashmem region. - // ASHMEM_GET_SIZE should succeed for all ashmem regions, and the kernel - // should return ENOTTY for all other valid file descriptors int ashmemSize = ashmem_get_size_region(fd); if (ashmemSize < 0) { - if (errno == ENOTTY) { - // ENOTTY means that the ioctl does not apply to this object, - // i.e., it is not an ashmem region. - return -1; - } // Some other error, throw exception jniThrowIOException(env, errno); return -1; diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 426136bfcb1d00d8db2ce4f2bddbce23f9bb4a09..1cfbd97f82b9133eb63ee94f82c79d80900ce153 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -57,21 +57,19 @@ static pthread_key_t gBgKey = -1; #endif // For both of these, err should be in the errno range (positive), not a status_t (negative) - -static void signalExceptionForPriorityError(JNIEnv* env, int err) -{ +static void signalExceptionForError(JNIEnv* env, int err, int tid) { switch (err) { case EINVAL: - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "Invalid argument: %d", tid); break; case ESRCH: - jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist"); + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "Given thread %d does not exist", tid); break; case EPERM: - jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread"); - break; - case EACCES: - jniThrowException(env, "java/lang/SecurityException", "No permission to set to given priority"); + jniThrowExceptionFmt(env, "java/lang/SecurityException", + "No permission to modify given thread %d", tid); break; default: jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); @@ -79,23 +77,27 @@ static void signalExceptionForPriorityError(JNIEnv* env, int err) } } -static void signalExceptionForGroupError(JNIEnv* env, int err) -{ +static void signalExceptionForPriorityError(JNIEnv* env, int err, int tid) { switch (err) { - case EINVAL: - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - break; - case ESRCH: - jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist"); + case EACCES: + jniThrowExceptionFmt(env, "java/lang/SecurityException", + "No permission to set the priority of %d", tid); break; - case EPERM: - jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread"); + default: + signalExceptionForError(env, err, tid); break; + } + +} + +static void signalExceptionForGroupError(JNIEnv* env, int err, int tid) { + switch (err) { case EACCES: - jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group"); + jniThrowExceptionFmt(env, "java/lang/SecurityException", + "No permission to set the group of %d", tid); break; default: - jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); + signalExceptionForError(env, err, tid); break; } } @@ -170,7 +172,7 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint SchedPolicy sp = (SchedPolicy) grp; int res = set_sched_policy(tid, sp); if (res != NO_ERROR) { - signalExceptionForGroupError(env, -res); + signalExceptionForGroupError(env, -res, tid); } } @@ -182,7 +184,7 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin struct dirent *de; if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) { - signalExceptionForGroupError(env, EINVAL); + signalExceptionForGroupError(env, EINVAL, pid); return; } @@ -218,7 +220,7 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin if (!(d = opendir(proc_path))) { // If the process exited on us, don't generate an exception if (errno != ENOENT) - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); return; } @@ -253,7 +255,7 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin #ifdef ENABLE_CPUSETS int err = set_cpuset_policy(t_pid, sp); if (err != NO_ERROR) { - signalExceptionForGroupError(env, -err); + signalExceptionForGroupError(env, -err, t_pid); break; } #endif @@ -265,14 +267,14 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin // set both cpuset and cgroup for general threads err = set_cpuset_policy(t_pid, sp); if (err != NO_ERROR) { - signalExceptionForGroupError(env, -err); + signalExceptionForGroupError(env, -err, t_pid); break; } #endif err = set_sched_policy(t_pid, sp); if (err != NO_ERROR) { - signalExceptionForGroupError(env, -err); + signalExceptionForGroupError(env, -err, t_pid); break; } @@ -284,7 +286,7 @@ jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid) { SchedPolicy sp; if (get_sched_policy(pid, &sp) != 0) { - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); } return (int) sp; } @@ -399,7 +401,7 @@ jintArray android_os_Process_getExclusiveCores(JNIEnv* env, jobject clazz) { jintArray cpus; int pid = getpid(); if (get_sched_policy(pid, &sp) != 0) { - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); return NULL; } get_exclusive_cpuset_cores(sp, &cpu_set); @@ -439,6 +441,23 @@ static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, #endif } +jint android_os_Process_getThreadScheduler(JNIEnv* env, jclass clazz, + jint tid) +{ + int policy = 0; +// linux has sched_getscheduler(), others don't. +#if defined(__linux__) + errno = 0; + policy = sched_getscheduler(tid); + if (errno != 0) { + signalExceptionForPriorityError(env, errno, tid); + } +#else + signalExceptionForPriorityError(env, ENOSYS, tid); +#endif + return policy; +} + void android_os_Process_setThreadScheduler(JNIEnv* env, jclass clazz, jint tid, jint policy, jint pri) { @@ -448,10 +467,10 @@ void android_os_Process_setThreadScheduler(JNIEnv* env, jclass clazz, param.sched_priority = pri; int rc = sched_setscheduler(tid, policy, ¶m); if (rc) { - signalExceptionForPriorityError(env, errno); + signalExceptionForPriorityError(env, errno, tid); } #else - signalExceptionForPriorityError(env, ENOSYS); + signalExceptionForPriorityError(env, ENOSYS, tid); #endif } @@ -476,9 +495,9 @@ void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz, int rc = androidSetThreadPriority(pid, pri); if (rc != 0) { if (rc == INVALID_OPERATION) { - signalExceptionForPriorityError(env, errno); + signalExceptionForPriorityError(env, errno, pid); } else { - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); } } @@ -498,7 +517,7 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz, errno = 0; jint pri = getpriority(PRIO_PROCESS, pid); if (errno != 0) { - signalExceptionForPriorityError(env, errno); + signalExceptionForPriorityError(env, errno, pid); } //ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri); return pri; @@ -1188,6 +1207,7 @@ static const JNINativeMethod methods[] = { {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground}, {"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority}, {"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority}, + {"getThreadScheduler", "(I)I", (void*)android_os_Process_getThreadScheduler}, {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup}, {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup}, {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup}, diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index b0028e1b6f5b4ca813d6256582da87ec72318107..1bad5f8ce456520ff059e979eff41a464de09c30 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -721,9 +721,9 @@ static const JNINativeMethod gMethods[] = { int register_android_view_RenderNode(JNIEnv* env) { jclass clazz = FindClassOrDie(env, "android/view/SurfaceView"); gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz, - "updateWindowPositionRT", "(JIIII)V"); + "updateWindowPosition_renderWorker", "(JIIII)V"); gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz, - "windowPositionLostRT", "(J)V"); + "windowPositionLost_uiRtSync", "(J)V"); clazz = FindClassOrDie(env, "android/view/RenderNode"); gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz, "onRenderNodeDetached", "()V"); diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 21e4d2fb229fb9493069bcad256d8dad34325bed..a0c62c366285032ec1cb23f5c2db46cff6c23d81 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -487,6 +487,11 @@ static jint nativeSetScalingMode(JNIEnv *env, jclass clazz, jlong nativeObject, return surface->setScalingMode(scalingMode); } +static jint nativeForceScopedDisconnect(JNIEnv *env, jclass clazz, jlong nativeObject) { + Surface* surface = reinterpret_cast(nativeObject); + return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal); +} + namespace uirenderer { using namespace android::uirenderer::renderthread; @@ -564,6 +569,7 @@ static const JNINativeMethod gSurfaceMethods[] = { {"nativeGetHeight", "(J)I", (void*)nativeGetHeight }, {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber }, {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode }, + {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect}, // HWUI context {"nHwuiCreate", "(JJ)J", (void*) hwui::create }, diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index ff75677536c48a2cfabee8b69196194770e90865..73b3f52f078b9be0a9ff2101ef99f5e2f825cb5e 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -58,7 +59,6 @@ static struct { jfieldID secure; jfieldID appVsyncOffsetNanos; jfieldID presentationDeadlineNanos; - jfieldID colorTransform; } gPhysicalDisplayInfoClassInfo; static struct { @@ -248,10 +248,10 @@ static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfl } } -static void nativeSetPositionAppliesWithResize(JNIEnv* env, jclass clazz, +static void nativeSetGeometryAppliesWithResize(JNIEnv* env, jclass clazz, jlong nativeObject) { SurfaceControl* const ctrl = reinterpret_cast(nativeObject); - status_t err = ctrl->setPositionAppliesWithResize(); + status_t err = ctrl->setGeometryAppliesWithResize(); if (err < 0 && err != NO_INIT) { doThrowIAE(env); } @@ -371,7 +371,12 @@ static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, if (sur != NULL) { bufferProducer = sur->getIGraphicBufferProducer(); } - SurfaceComposerClient::setDisplaySurface(token, bufferProducer); + status_t err = SurfaceComposerClient::setDisplaySurface(token, + bufferProducer); + if (err != NO_ERROR) { + doThrowIAE(env, "Illegal Surface, could not enable async mode. Was this" + " Surface created with singleBufferMode?"); + } } static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, @@ -429,8 +434,6 @@ static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz, info.appVsyncOffset); env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos, info.presentationDeadline); - env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.colorTransform, - info.colorTransform); env->SetObjectArrayElement(configArray, static_cast(c), infoObj); env->DeleteLocalRef(infoObj); } @@ -451,6 +454,43 @@ static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenOb return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; } +static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) { + sp token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return NULL; + Vector colorModes; + if (SurfaceComposerClient::getDisplayColorModes(token, &colorModes) != NO_ERROR || + colorModes.isEmpty()) { + return NULL; + } + + jintArray colorModesArray = env->NewIntArray(colorModes.size()); + if (colorModesArray == NULL) { + jniThrowException(env, "java/lang/OutOfMemoryError", NULL); + return NULL; + } + jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0); + for (size_t i = 0; i < colorModes.size(); i++) { + colorModesArrayValues[i] = static_cast(colorModes[i]); + } + env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0); + return colorModesArray; +} + +static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) { + sp token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return -1; + return static_cast(SurfaceComposerClient::getActiveColorMode(token)); +} + +static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass, + jobject tokenObj, jint colorMode) { + sp token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return JNI_FALSE; + status_t err = SurfaceComposerClient::setActiveColorMode(token, + static_cast(colorMode)); + return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; +} + static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) { sp token(ibinderForJavaObject(env, tokenObj)); if (token == NULL) return; @@ -626,6 +666,16 @@ static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) { return javaObjectForIBinder(env, ctrl->getHandle()); } +static jboolean nativeGetTransformToDisplayInverse(JNIEnv* env, jclass clazz, jlong nativeObject) { + bool out = false; + auto ctrl = reinterpret_cast(nativeObject); + status_t status = ctrl->getTransformToDisplayInverse(&out); + if (status != NO_ERROR) { + return false; + } + return out; +} + static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject tokenObject) { sp token(ibinderForJavaObject(env, tokenObject)); if (token == NULL) return NULL; @@ -667,8 +717,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetLayer }, {"nativeSetPosition", "(JFF)V", (void*)nativeSetPosition }, - {"nativeSetPositionAppliesWithResize", "(J)V", - (void*)nativeSetPositionAppliesWithResize }, + {"nativeSetGeometryAppliesWithResize", "(J)V", + (void*)nativeSetGeometryAppliesWithResize }, {"nativeSetSize", "(JII)V", (void*)nativeSetSize }, {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V", @@ -705,6 +755,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeGetActiveConfig }, {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z", (void*)nativeSetActiveConfig }, + {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I", + (void*)nativeGetDisplayColorModes}, + {"nativeGetActiveColorMode", "(Landroid/os/IBinder;)I", + (void*)nativeGetActiveColorMode}, + {"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z", + (void*)nativeSetActiveColorMode}, {"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;", (void*)nativeGetHdrCapabilities }, {"nativeClearContentFrameStats", "(J)Z", @@ -722,7 +778,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = { {"nativeSetOverrideScalingMode", "(JI)V", (void*)nativeSetOverrideScalingMode }, {"nativeGetHandle", "(J)Landroid/os/IBinder;", - (void*)nativeGetHandle } + (void*)nativeGetHandle }, + {"nativeGetTransformToDisplayInverse", "(J)Z", + (void*)nativeGetTransformToDisplayInverse }, }; int register_android_view_SurfaceControl(JNIEnv* env) @@ -745,8 +803,6 @@ int register_android_view_SurfaceControl(JNIEnv* env) clazz, "appVsyncOffsetNanos", "J"); gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env, clazz, "presentationDeadlineNanos", "J"); - gPhysicalDisplayInfoClassInfo.colorTransform = GetFieldIDOrDie(env, clazz, - "colorTransform", "I"); jclass rectClazz = FindClassOrDie(env, "android/graphics/Rect"); gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClazz, "bottom", "I"); diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 172e12d5427e0701b7629b87a5a7920c508e48ff..9c0a65a60606716e500975259c0669b3b2268063 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -122,6 +124,31 @@ private: std::vector mOnFinishedEvents; }; +class FinishAndInvokeListener : public MessageHandler { +public: + explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim) + : mAnimator(anim) { + mListener = anim->getOneShotListener(); + mRequestId = anim->getRequestId(); + } + + virtual void handleMessage(const Message& message) { + if (mAnimator->getRequestId() == mRequestId) { + // Request Id has not changed, meaning there's no animation lifecyle change since the + // message is posted, so go ahead and call finish to make sure the PlayState is properly + // updated. This is needed because before the next frame comes in from UI thread to + // trigger an animation update, there could be reverse/cancel etc. So we need to update + // the playstate in time to ensure all the subsequent events get chained properly. + mAnimator->end(); + } + mListener->onAnimationFinished(nullptr); + } +private: + sp mAnimator; + sp mListener; + uint32_t mRequestId; +}; + class RenderingException : public MessageHandler { public: RenderingException(JavaVM* vm, const std::string& message) @@ -160,6 +187,23 @@ public: virtual void prepareTree(TreeInfo& info) override { info.errorHandler = this; + + for (auto& anim : mRunningVDAnimators) { + // Assume that the property change in VD from the animators will not be consumed. Mark + // otherwise if the VDs are found in the display list tree. For VDs that are not in + // the display list tree, we stop providing animation pulses by 1) removing them from + // the animation list, 2) post a delayed message to end them at end time so their + // listeners can receive the corresponding callbacks. + anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false); + // Mark the VD dirty so it will damage itself during prepareTree. + anim->getVectorDrawable()->markDirty(); + } + if (info.mode == TreeInfo::MODE_FULL) { + for (auto &anim : mPausedVDAnimators) { + anim->getVectorDrawable()->setPropertyChangeWillBeConsumed(false); + anim->getVectorDrawable()->markDirty(); + } + } // TODO: This is hacky info.windowInsetLeft = -stagingProperties().getLeft(); info.windowInsetTop = -stagingProperties().getTop(); @@ -175,10 +219,39 @@ public: mLooper->sendMessage(handler, 0); } + void sendMessageDelayed(const sp& handler, nsecs_t delayInMs) { + mLooper->sendMessageDelayed(ms2ns(delayInMs), handler, 0); + } + void attachAnimatingNode(RenderNode* animatingNode) { mPendingAnimatingRenderNodes.push_back(animatingNode); } + void attachPendingVectorDrawableAnimators() { + mRunningVDAnimators.insert(mPendingVectorDrawableAnimators.begin(), + mPendingVectorDrawableAnimators.end()); + mPendingVectorDrawableAnimators.clear(); + } + + void detachAnimators() { + // Remove animators from the list and post a delayed message in future to end the animator + for (auto& anim : mRunningVDAnimators) { + detachVectorDrawableAnimator(anim.get()); + } + mRunningVDAnimators.clear(); + mPausedVDAnimators.clear(); + } + + // Move all the animators to the paused list, and send a delayed message to notify the finished + // listener. + void pauseAnimators() { + mPausedVDAnimators.insert(mRunningVDAnimators.begin(), mRunningVDAnimators.end()); + for (auto& anim : mRunningVDAnimators) { + detachVectorDrawableAnimator(anim.get()); + } + mRunningVDAnimators.clear(); + } + void doAttachAnimatingNodes(AnimationContext* context) { for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) { RenderNode* node = mPendingAnimatingRenderNodes[i].get(); @@ -187,17 +260,144 @@ public: mPendingAnimatingRenderNodes.clear(); } + // Run VectorDrawable animators after prepareTree. + void runVectorDrawableAnimators(AnimationContext* context, TreeInfo& info) { + // Push staging. + if (info.mode == TreeInfo::MODE_FULL) { + pushStagingVectorDrawableAnimators(context); + } + + // Run the animators in the running list. + for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) { + if ((*it)->animate(*context)) { + it = mRunningVDAnimators.erase(it); + } else { + it++; + } + } + + // Run the animators in paused list during full sync. + if (info.mode == TreeInfo::MODE_FULL) { + // During full sync we also need to pulse paused animators, in case their targets + // have been added back to the display list. All the animators that passed the + // scheduled finish time will be removed from the paused list. + for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { + if ((*it)->animate(*context)) { + // Animator has finished, remove from the list. + it = mPausedVDAnimators.erase(it); + } else { + it++; + } + } + } + + // Move the animators with a target not in DisplayList to paused list. + for (auto it = mRunningVDAnimators.begin(); it != mRunningVDAnimators.end();) { + if (!(*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) { + // Vector Drawable is not in the display list, we should remove this animator from + // the list, put it in the paused list, and post a delayed message to end the + // animator. + detachVectorDrawableAnimator(it->get()); + mPausedVDAnimators.insert(*it); + it = mRunningVDAnimators.erase(it); + } else { + it++; + } + } + + // Move the animators with a target in DisplayList from paused list to running list, and + // trim paused list. + if (info.mode == TreeInfo::MODE_FULL) { + // Check whether any paused animator's target is back in Display List. If so, put the + // animator back in the running list. + for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { + if ((*it)->getVectorDrawable()->getPropertyChangeWillBeConsumed()) { + mRunningVDAnimators.insert(*it); + it = mPausedVDAnimators.erase(it); + } else { + it++; + } + } + // Trim paused VD animators at full sync, so that when Java loses reference to an + // animator, we know we won't be requested to animate it any more, then we remove such + // animators from the paused list so they can be properly freed. We also remove the + // animators from paused list when the time elapsed since start has exceeded duration. + trimPausedVDAnimators(context); + } + + info.out.hasAnimations |= !mRunningVDAnimators.empty(); + } + + void trimPausedVDAnimators(AnimationContext* context) { + // Trim paused vector drawable animator list. + for (auto it = mPausedVDAnimators.begin(); it != mPausedVDAnimators.end();) { + // Remove paused VD animator if no one else is referencing it. Note that animators that + // have passed scheduled finish time are removed from list when they are being pulsed + // before prepare tree. + // TODO: this is a bit hacky, need to figure out a better way to track when the paused + // animators should be freed. + if ((*it)->getStrongCount() == 1) { + it = mPausedVDAnimators.erase(it); + } else { + it++; + } + } + } + + void pushStagingVectorDrawableAnimators(AnimationContext* context) { + for (auto& anim : mRunningVDAnimators) { + anim->pushStaging(*context); + } + } + void destroy() { for (auto& renderNode : mPendingAnimatingRenderNodes) { renderNode->animators().endAllStagingAnimators(); } mPendingAnimatingRenderNodes.clear(); + mPendingVectorDrawableAnimators.clear(); + } + + void addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { + mPendingVectorDrawableAnimators.insert(anim); } private: sp mLooper; JavaVM* mVm; std::vector< sp > mPendingAnimatingRenderNodes; + std::set< sp > mPendingVectorDrawableAnimators; + std::set< sp > mRunningVDAnimators; + // mPausedVDAnimators stores a list of animators that have not yet passed the finish time, but + // their VectorDrawable targets are no longer in the DisplayList. We skip these animators when + // render thread runs animators independent of UI thread (i.e. RT_ONLY mode). These animators + // need to be re-activated once their VD target is added back into DisplayList. Since that could + // only happen when we do a full sync, we need to make sure to pulse these paused animators at + // full sync. If any animator's VD target is found in DisplayList during a full sync, we move + // the animator back to the running list. + std::set< sp > mPausedVDAnimators; + void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { + if (anim->isInfinite() || !anim->isRunning()) { + // Do not need to post anything if the animation is infinite (i.e. no meaningful + // end listener action), or if the animation has already ended. + return; + } + nsecs_t remainingTimeInMs = anim->getRemainingPlayTime(); + // Post a delayed onFinished event that is scheduled to be handled when the animator ends. + if (anim->getOneShotListener()) { + // VectorDrawable's oneshot listener is updated when there are user triggered animation + // lifecycle changes, such as start(), end(), etc. By using checking and clearing + // one shot listener, we ensure the same end listener event gets posted only once. + // Therefore no duplicates. Another benefit of using one shot listener is that no + // removal is necessary: the end time of animation will not change unless triggered by + // user events, in which case the already posted listener's id will become stale, and + // the onFinished callback will then be ignored. + sp message + = new FinishAndInvokeListener(anim); + sendMessageDelayed(message, remainingTimeInMs); + anim->clearOneShotListener(); + } + } }; class AnimationContextBridge : public AnimationContext { @@ -213,6 +413,7 @@ public: virtual void startFrame(TreeInfo::TraversalMode mode) { if (mode == TreeInfo::MODE_FULL) { mRootNode->doAttachAnimatingNodes(this); + mRootNode->attachPendingVectorDrawableAnimators(); } AnimationContext::startFrame(mode); } @@ -220,9 +421,14 @@ public: // Runs any animations still left in mCurrentFrameAnimations virtual void runRemainingAnimations(TreeInfo& info) { AnimationContext::runRemainingAnimations(info); + mRootNode->runVectorDrawableAnimators(this, info); postOnFinishedEvents(); } + virtual void pauseAnimators() override { + mRootNode->pauseAnimators(); + } + virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) { OnFinishedEvent event(animator, listener); mOnFinishedEvents.push_back(event); @@ -230,6 +436,7 @@ public: virtual void destroy() { AnimationContext::destroy(); + mRootNode->detachAnimators(); postOnFinishedEvents(); } @@ -415,6 +622,12 @@ static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, job proxy->setProcessStatsBuffer(fd); } +static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz, + jlong proxyPtr) { + RenderProxy* proxy = reinterpret_cast(proxyPtr); + return proxy->getRenderThreadTid(); +} + static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { RootRenderNode* node = new RootRenderNode(env); node->incStrong(0); @@ -527,6 +740,13 @@ static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* en rootRenderNode->attachAnimatingNode(animatingNode); } +static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz, + jlong rootNodePtr, jlong animatorPtr) { + RootRenderNode* rootRenderNode = reinterpret_cast(rootNodePtr); + PropertyValuesAnimatorSet* animator = reinterpret_cast(animatorPtr); + rootRenderNode->addVectorDrawableAnimator(animator); +} + static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz, jlong functorPtr, jboolean waitForCompletion) { Functor* functor = reinterpret_cast(functorPtr); @@ -723,6 +943,7 @@ const char* const kClassPathName = "android/view/ThreadedRenderer"; static const JNINativeMethod gMethods[] = { { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas }, { "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer }, + { "nGetRenderThreadTid", "(J)I", (void*) android_view_ThreadedRenderer_getRenderThreadTid }, { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode }, { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy }, { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, @@ -738,6 +959,7 @@ static const JNINativeMethod gMethods[] = { { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, { "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy }, { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode }, + { "nRegisterVectorDrawableAnimator", "(JJ)V", (void*) android_view_ThreadedRenderer_registerVectorDrawableAnimator }, { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, { "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer }, diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index ca0970850ef124c2dd463811ea9840d1d4d600a6..d0815490159b8cf57e0b59f20ae5a8b43305c995 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -55,6 +55,7 @@ #include "ScopedLocalRef.h" #include "ScopedPrimitiveArray.h" #include "ScopedUtfChars.h" +#include "fd_utils-inl.h" #include "nativebridge/native_bridge.h" @@ -177,7 +178,9 @@ static void SetGids(JNIEnv* env, jintArray javaGids) { } int rc = setgroups(gids.size(), reinterpret_cast(&gids[0])); if (rc == -1) { - RuntimeAbort(env, __LINE__, "setgroups failed"); + std::ostringstream oss; + oss << "setgroups failed: " << strerror(errno) << ", gids.size=" << gids.size(); + RuntimeAbort(env, __LINE__, oss.str().c_str()); } } @@ -436,6 +439,9 @@ static void SetForkLoad(bool boost) { } #endif +// The list of open zygote file descriptors. +static FileDescriptorTable* gOpenFdTable = NULL; + // Utility routine to fork zygote and specialize the child process. static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, @@ -450,6 +456,22 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra SetForkLoad(true); #endif + // Close any logging related FDs before we start evaluating the list of + // file descriptors. + __android_log_close(); + + // If this is the first fork for this zygote, create the open FD table. + // If it isn't, we just need to check whether the list of open files has + // changed (and it shouldn't in the normal case). + if (gOpenFdTable == NULL) { + gOpenFdTable = FileDescriptorTable::Create(); + if (gOpenFdTable == NULL) { + RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table."); + } + } else if (!gOpenFdTable->Restat()) { + RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table."); + } + pid_t pid = fork(); if (pid == 0) { @@ -459,6 +481,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra // Clean up any descriptors which must be closed immediately DetachDescriptors(env, fdsToClose); + // Re-open all remaining open file descriptors so that they aren't shared + // with the zygote across a fork. + if (!gOpenFdTable->ReopenOrDetach()) { + RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors."); + } + // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(env); diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..af27069119492c21280c9de27fc77809aa0966ec --- /dev/null +++ b/core/jni/fd_utils-inl.h @@ -0,0 +1,563 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "JNIHelp.h" +#include "ScopedPrimitiveArray.h" + +// Whitelist of open paths that the zygote is allowed to keep open. +// +// In addition to the paths listed here, all files ending with +// ".jar" under /system/framework" are whitelisted. See +// FileDescriptorInfo::IsWhitelisted for the canonical definition. +// +// If the whitelisted path is associated with a regular file or a +// character device, the file is reopened after a fork with the same +// offset and mode. If the whilelisted path is associated with a +// AF_UNIX socket, the socket will refer to /dev/null after each +// fork, and all operations on it will fail. +static const char* kPathWhitelist[] = { + "/dev/null", + "/dev/socket/zygote", + "/dev/socket/zygote_secondary", + "/sys/kernel/debug/tracing/trace_marker", + "/system/framework/framework-res.apk", + "/dev/urandom", + "/dev/ion", + "/dev/dri/renderD129", // Fixes b/31172436 +}; + +static const char* kFdPath = "/proc/self/fd"; + +// Keeps track of all relevant information (flags, offset etc.) of an +// open zygote file descriptor. +class FileDescriptorInfo { + public: + // Create a FileDescriptorInfo for a given file descriptor. Returns + // |NULL| if an error occurred. + static FileDescriptorInfo* createFromFd(int fd) { + struct stat f_stat; + // This should never happen; the zygote should always have the right set + // of permissions required to stat all its open files. + if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { + ALOGE("Unable to stat fd %d : %s", fd, strerror(errno)); + return NULL; + } + + if (S_ISSOCK(f_stat.st_mode)) { + std::string socket_name; + if (!GetSocketName(fd, &socket_name)) { + return NULL; + } + + if (!IsWhitelisted(socket_name)) { + ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd); + return NULL; + } + + return new FileDescriptorInfo(fd); + } + + // We only handle whitelisted regular files and character devices. Whitelisted + // character devices must provide a guarantee of sensible behaviour when + // reopened. + // + // S_ISDIR : Not supported. (We could if we wanted to, but it's unused). + // S_ISLINK : Not supported. + // S_ISBLK : Not supported. + // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate + // with the child process across forks but those should have been closed + // before we got to this point. + if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) { + ALOGE("Unsupported st_mode %d", f_stat.st_mode); + return NULL; + } + + std::string file_path; + if (!Readlink(fd, &file_path)) { + return NULL; + } + + if (!IsWhitelisted(file_path)) { + ALOGE("Not whitelisted : %s", file_path.c_str()); + return NULL; + } + + // File descriptor flags : currently on FD_CLOEXEC. We can set these + // using F_SETFD - we're single threaded at this point of execution so + // there won't be any races. + const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD)); + if (fd_flags == -1) { + ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno)); + return NULL; + } + + // File status flags : + // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through + // to the open() call. + // + // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can + // do about these, since the file has already been created. We shall ignore + // them here. + // + // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL + // can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK. + // In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for + // their presence and pass them in to open(). + int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL)); + if (fs_flags == -1) { + ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno)); + return NULL; + } + + // File offset : Ignore the offset for non seekable files. + const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR)); + + // We pass the flags that open accepts to open, and use F_SETFL for + // the rest of them. + static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC); + int open_flags = fs_flags & (kOpenFlags); + fs_flags = fs_flags & (~(kOpenFlags)); + + return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset); + } + + // Checks whether the file descriptor associated with this object + // refers to the same description. + bool Restat() const { + struct stat f_stat; + if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) { + return false; + } + + return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev; + } + + bool ReopenOrDetach() const { + if (is_sock) { + return DetachSocket(); + } + + // NOTE: This might happen if the file was unlinked after being opened. + // It's a common pattern in the case of temporary files and the like but + // we should not allow such usage from the zygote. + const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags)); + + if (new_fd == -1) { + ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno)); + return false; + } + + if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) { + close(new_fd); + ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno)); + return false; + } + + if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) { + close(new_fd); + ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno)); + return false; + } + + if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) { + close(new_fd); + ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno)); + return false; + } + + if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) { + close(new_fd); + ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno)); + return false; + } + + close(new_fd); + + return true; + } + + const int fd; + const struct stat stat; + const std::string file_path; + const int open_flags; + const int fd_flags; + const int fs_flags; + const off_t offset; + const bool is_sock; + + private: + FileDescriptorInfo(int fd) : + fd(fd), + stat(), + open_flags(0), + fd_flags(0), + fs_flags(0), + offset(0), + is_sock(true) { + } + + FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags, + int fd_flags, int fs_flags, off_t offset) : + fd(fd), + stat(stat), + file_path(file_path), + open_flags(open_flags), + fd_flags(fd_flags), + fs_flags(fs_flags), + offset(offset), + is_sock(false) { + } + + // Returns true iff. a given path is whitelisted. A path is whitelisted + // if it belongs to the whitelist (see kPathWhitelist) or if it's a path + // under /system/framework that ends with ".jar" or if it is a system + // framework overlay. + static bool IsWhitelisted(const std::string& path) { + for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) { + if (kPathWhitelist[i] == path) { + return true; + } + } + + static const char* kFrameworksPrefix = "/system/framework/"; + static const char* kJarSuffix = ".jar"; + if (android::base::StartsWith(path, kFrameworksPrefix) + && android::base::EndsWith(path, kJarSuffix)) { + return true; + } + + // Whitelist files needed for Runtime Resource Overlay, like these: + // /system/vendor/overlay/framework-res.apk + // /system/vendor/overlay/PG/android-framework-runtime-resource-overlay.apk + // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap + // /data/resource-cache/system@vendor@overlay@PG@framework-res.apk@idmap + static const char* kOverlayDir = "/system/vendor/overlay/"; + static const char* kApkSuffix = ".apk"; + + if (android::base::StartsWith(path, kOverlayDir) + && android::base::EndsWith(path, kApkSuffix) + && path.find("/../") == std::string::npos) { + return true; + } + + static const char* kOverlayIdmapPrefix = "/data/resource-cache/"; + static const char* kOverlayIdmapSuffix = ".apk@idmap"; + if (android::base::StartsWith(path, kOverlayIdmapPrefix) + && android::base::EndsWith(path, kOverlayIdmapSuffix)) { + return true; + } + + return false; + } + + // TODO: Call android::base::Readlink instead of copying the code here. + static bool Readlink(const int fd, std::string* result) { + char path[64]; + snprintf(path, sizeof(path), "/proc/self/fd/%d", fd); + + // Code copied from android::base::Readlink starts here : + + // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer, + // and truncates to whatever size you do supply, so it can't be used to query. + // We could call lstat first, but that would introduce a race condition that + // we couldn't detect. + // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here. + char buf[4096]; + ssize_t len = readlink(path, buf, sizeof(buf)); + if (len == -1) return false; + + result->assign(buf, len); + return true; + } + + // Returns the locally-bound name of the socket |fd|. Returns true + // iff. all of the following hold : + // + // - the socket's sa_family is AF_UNIX. + // - the length of the path is greater than zero (i.e, not an unnamed socket). + // - the first byte of the path isn't zero (i.e, not a socket with an abstract + // address). + static bool GetSocketName(const int fd, std::string* result) { + sockaddr_storage ss; + sockaddr* addr = reinterpret_cast(&ss); + socklen_t addr_len = sizeof(ss); + + if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) { + ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno)); + return false; + } + + if (addr->sa_family != AF_UNIX) { + ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family); + return false; + } + + const sockaddr_un* unix_addr = reinterpret_cast(&ss); + + size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path); + // This is an unnamed local socket, we do not accept it. + if (path_len == 0) { + ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd); + return false; + } + + // This is a local socket with an abstract address, we do not accept it. + if (unix_addr->sun_path[0] == '\0') { + ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd); + return false; + } + + // If we're here, sun_path must refer to a null terminated filesystem + // pathname (man 7 unix). Remove the terminator before assigning it to an + // std::string. + if (unix_addr->sun_path[path_len - 1] == '\0') { + --path_len; + } + + result->assign(unix_addr->sun_path, path_len); + return true; + } + + bool DetachSocket() const { + const int dev_null_fd = open("/dev/null", O_RDWR); + if (dev_null_fd < 0) { + ALOGE("Failed to open /dev/null : %s", strerror(errno)); + return false; + } + + if (dup2(dev_null_fd, fd) == -1) { + ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno)); + return false; + } + + if (close(dev_null_fd) == -1) { + ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno)); + return false; + } + + return true; + } + + DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo); +}; + +// A FileDescriptorTable is a collection of FileDescriptorInfo objects +// keyed by their FDs. +class FileDescriptorTable { + public: + // Creates a new FileDescriptorTable. This function scans + // /proc/self/fd for the list of open file descriptors and collects + // information about them. Returns NULL if an error occurs. + static FileDescriptorTable* Create() { + DIR* d = opendir(kFdPath); + if (d == NULL) { + ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); + return NULL; + } + int dir_fd = dirfd(d); + dirent* e; + + std::unordered_map open_fd_map; + while ((e = readdir(d)) != NULL) { + const int fd = ParseFd(e, dir_fd); + if (fd == -1) { + continue; + } + + FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); + if (info == NULL) { + if (closedir(d) == -1) { + ALOGE("Unable to close directory : %s", strerror(errno)); + } + return NULL; + } + open_fd_map[fd] = info; + } + + if (closedir(d) == -1) { + ALOGE("Unable to close directory : %s", strerror(errno)); + return NULL; + } + return new FileDescriptorTable(open_fd_map); + } + + bool Restat() { + std::set open_fds; + + // First get the list of open descriptors. + DIR* d = opendir(kFdPath); + if (d == NULL) { + ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno)); + return false; + } + + int dir_fd = dirfd(d); + dirent* e; + while ((e = readdir(d)) != NULL) { + const int fd = ParseFd(e, dir_fd); + if (fd == -1) { + continue; + } + + open_fds.insert(fd); + } + + if (closedir(d) == -1) { + ALOGE("Unable to close directory : %s", strerror(errno)); + return false; + } + + return RestatInternal(open_fds); + } + + // Reopens all file descriptors that are contained in the table. Returns true + // if all descriptors were successfully re-opened or detached, and false if an + // error occurred. + bool ReopenOrDetach() { + std::unordered_map::const_iterator it; + for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) { + const FileDescriptorInfo* info = it->second; + if (info == NULL || !info->ReopenOrDetach()) { + return false; + } + } + + return true; + } + + private: + FileDescriptorTable(const std::unordered_map& map) + : open_fd_map_(map) { + } + + bool RestatInternal(std::set& open_fds) { + bool error = false; + + // Iterate through the list of file descriptors we've already recorded + // and check whether : + // + // (a) they continue to be open. + // (b) they refer to the same file. + std::unordered_map::iterator it = open_fd_map_.begin(); + while (it != open_fd_map_.end()) { + std::set::const_iterator element = open_fds.find(it->first); + if (element == open_fds.end()) { + // The entry from the file descriptor table is no longer in the list + // of open files. We warn about this condition and remove it from + // the list of FDs under consideration. + // + // TODO(narayan): This will be an error in a future android release. + // error = true; + // ALOGW("Zygote closed file descriptor %d.", it->first); + it = open_fd_map_.erase(it); + } else { + // The entry from the file descriptor table is still open. Restat + // it and check whether it refers to the same file. + const bool same_file = it->second->Restat(); + if (!same_file) { + // The file descriptor refers to a different description. We must + // update our entry in the table. + delete it->second; + it->second = FileDescriptorInfo::createFromFd(*element); + if (it->second == NULL) { + // The descriptor no longer no longer refers to a whitelisted file. + // We flag an error and remove it from the list of files we're + // tracking. + error = true; + it = open_fd_map_.erase(it); + } else { + // Successfully restatted the file, move on to the next open FD. + ++it; + } + } else { + // It's the same file. Nothing to do here. Move on to the next open + // FD. + ++it; + } + + // Finally, remove the FD from the set of open_fds. We do this last because + // |element| will not remain valid after a call to erase. + open_fds.erase(element); + } + } + + if (open_fds.size() > 0) { + // The zygote has opened new file descriptors since our last inspection. + // We warn about this condition and add them to our table. + // + // TODO(narayan): This will be an error in a future android release. + // error = true; + // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size()); + + // TODO(narayan): This code will be removed in a future android release. + std::set::const_iterator it; + for (it = open_fds.begin(); it != open_fds.end(); ++it) { + const int fd = (*it); + FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd); + if (info == NULL) { + // A newly opened file is not on the whitelist. Flag an error and + // continue. + error = true; + } else { + // Track the newly opened file. + open_fd_map_[fd] = info; + } + } + } + + return !error; + } + + static int ParseFd(dirent* e, int dir_fd) { + char* end; + const int fd = strtol(e->d_name, &end, 10); + if ((*end) != '\0') { + return -1; + } + + // Don't bother with the standard input/output/error, they're handled + // specially post-fork anyway. + if (fd <= STDERR_FILENO || fd == dir_fd) { + return -1; + } + + return fd; + } + + // Invariant: All values in this unordered_map are non-NULL. + std::unordered_map open_fd_map_; + + DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable); +}; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7ec3ba760d5c6fa71d496d9055a9e06138616a38..4e98e34d9ebdcf5ad5719980d1123eb04095105c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -49,6 +49,7 @@ + @@ -409,6 +410,8 @@ + + @@ -486,12 +489,6 @@ - - - - - - @@ -500,6 +497,8 @@ + + @@ -1281,6 +1280,11 @@ + + + + @@ -1642,7 +1647,7 @@ - - + + + + + diff --git a/core/res/res/anim-watch/progress_indeterminate_rotation_material.xml b/core/res/res/anim-watch/progress_indeterminate_rotation_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..63e66ec2441026d3e41dfaceda6496f45d8e8918 --- /dev/null +++ b/core/res/res/anim-watch/progress_indeterminate_rotation_material.xml @@ -0,0 +1,24 @@ + + + diff --git a/core/res/res/anim/dock_bottom_exit_keyguard.xml b/core/res/res/anim/dock_bottom_exit_keyguard.xml new file mode 100644 index 0000000000000000000000000000000000000000..4de3ce5b89325f49c23ea211e2a11c6036c9b818 --- /dev/null +++ b/core/res/res/anim/dock_bottom_exit_keyguard.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/layout/night_mode_settings.xml b/core/res/res/color/background_cache_hint_selector_device_default.xml similarity index 72% rename from packages/SystemUI/res/layout/night_mode_settings.xml rename to core/res/res/color/background_cache_hint_selector_device_default.xml index 3725e78cc481e369cef3bb287c600ac8778187ad..4470754f41550107eaf66a3e204ff572f55cd908 100644 --- a/packages/SystemUI/res/layout/night_mode_settings.xml +++ b/core/res/res/color/background_cache_hint_selector_device_default.xml @@ -14,11 +14,8 @@ limitations under the License. --> - + + + + - - - diff --git a/core/res/res/color/hint_foreground_material_dark.xml b/core/res/res/color/hint_foreground_material_dark.xml index 77883d975c7529716e4d408c235f1cef806967b8..5cc955952524424cfab802067f4b541331fc835a 100644 --- a/core/res/res/color/hint_foreground_material_dark.xml +++ b/core/res/res/color/hint_foreground_material_dark.xml @@ -15,6 +15,10 @@ --> + diff --git a/core/res/res/color/hint_foreground_material_light.xml b/core/res/res/color/hint_foreground_material_light.xml index 99168fdc29627b64d37f70372f647e50bd06bc1d..f7465e0e513970b885efb15d1329f85911786683 100644 --- a/core/res/res/color/hint_foreground_material_light.xml +++ b/core/res/res/color/hint_foreground_material_light.xml @@ -15,6 +15,10 @@ --> + diff --git a/core/res/res/color/watch_switch_thumb_color_material.xml b/core/res/res/color/watch_switch_thumb_color_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..f78d9b62a509b1d85927b503a50ea193fc0f3e8a --- /dev/null +++ b/core/res/res/color/watch_switch_thumb_color_material.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/core/res/res/drawable-hdpi/vpn_connected.png b/core/res/res/drawable-hdpi/vpn_connected.png index c3547e8557444e33792b51f5868615d956f9d4b1..e05e76ffc2751dbb644d4d51848722296061d331 100644 Binary files a/core/res/res/drawable-hdpi/vpn_connected.png and b/core/res/res/drawable-hdpi/vpn_connected.png differ diff --git a/core/res/res/drawable-hdpi/vpn_disconnected.png b/core/res/res/drawable-hdpi/vpn_disconnected.png index 10a9065cabdd2a1f6d63b946ffb002972c05097f..3508984b20991d82e144c24a6725e4e670d9fa58 100644 Binary files a/core/res/res/drawable-hdpi/vpn_disconnected.png and b/core/res/res/drawable-hdpi/vpn_disconnected.png differ diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png new file mode 100644 index 0000000000000000000000000000000000000000..371469c43b132be714da6e3b2057562db9120c60 Binary files /dev/null and b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png differ diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png new file mode 100644 index 0000000000000000000000000000000000000000..e47726058e3efb32aae2e0493615ac3cd5190270 Binary files /dev/null and b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png differ diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png new file mode 100644 index 0000000000000000000000000000000000000000..19a1bd3177997ecd24a4dc70f9df82fbf34246ac Binary files /dev/null and b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png differ diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png new file mode 100644 index 0000000000000000000000000000000000000000..79dc7332b60d852fdc79b970b6d2331951a28ef1 Binary files /dev/null and b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png differ diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png new file mode 100644 index 0000000000000000000000000000000000000000..6d921c0709b84101e34b7c9769eb61d46a32b593 Binary files /dev/null and b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png differ diff --git a/core/res/res/drawable-hdpi/watch_switch_track_mtrl_alpha.png b/core/res/res/drawable-hdpi/watch_switch_track_mtrl_alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..ecee3e137ef6731e73680bbd52e6d672261d1a4e Binary files /dev/null and b/core/res/res/drawable-hdpi/watch_switch_track_mtrl_alpha.png differ diff --git a/core/res/res/drawable-mdpi/vpn_connected.png b/core/res/res/drawable-mdpi/vpn_connected.png index 7e167f84dfa4b288628da0a42419948ec73cc140..f7ac2a184834f81a6b8a91a01b63f0c16f092a58 100644 Binary files a/core/res/res/drawable-mdpi/vpn_connected.png and b/core/res/res/drawable-mdpi/vpn_connected.png differ diff --git a/core/res/res/drawable-mdpi/vpn_disconnected.png b/core/res/res/drawable-mdpi/vpn_disconnected.png index a08c42a2702a3ebcbd4e7497110de1656291d63a..9db4199d026269a4cb35a9178082d3e6c3b8f914 100644 Binary files a/core/res/res/drawable-mdpi/vpn_disconnected.png and b/core/res/res/drawable-mdpi/vpn_disconnected.png differ diff --git a/core/res/res/drawable-nodpi/vpn_connected.xml b/core/res/res/drawable-nodpi/vpn_connected.xml new file mode 100644 index 0000000000000000000000000000000000000000..22a4a6cb4c6baf91315dcfbafe83e29f302cebf2 --- /dev/null +++ b/core/res/res/drawable-nodpi/vpn_connected.xml @@ -0,0 +1,24 @@ + + + + diff --git a/core/res/res/drawable-nodpi/vpn_disconnected.xml b/core/res/res/drawable-nodpi/vpn_disconnected.xml new file mode 100644 index 0000000000000000000000000000000000000000..22a4a6cb4c6baf91315dcfbafe83e29f302cebf2 --- /dev/null +++ b/core/res/res/drawable-nodpi/vpn_disconnected.xml @@ -0,0 +1,24 @@ + + + + diff --git a/packages/SystemUI/res/drawable/fab_background.xml b/core/res/res/drawable-watch/dialog_background_material.xml similarity index 68% rename from packages/SystemUI/res/drawable/fab_background.xml rename to core/res/res/drawable-watch/dialog_background_material.xml index 7f23f2b63e4196a760e57033a9400247ee371067..de52f08c00bf47968ba2c784bf1bb16543000f3c 100644 --- a/packages/SystemUI/res/drawable/fab_background.xml +++ b/core/res/res/drawable-watch/dialog_background_material.xml @@ -1,5 +1,5 @@ - - - - - - - - + + + + diff --git a/core/res/res/drawable-watch/ic_input_extract_action_done.xml b/core/res/res/drawable-watch/ic_input_extract_action_done.xml new file mode 100644 index 0000000000000000000000000000000000000000..a04b944f391fd06f133e480a361bb04234a784c0 --- /dev/null +++ b/core/res/res/drawable-watch/ic_input_extract_action_done.xml @@ -0,0 +1,19 @@ + + + + diff --git a/core/res/res/drawable-watch/ic_input_extract_action_send.xml b/core/res/res/drawable-watch/ic_input_extract_action_send.xml new file mode 100644 index 0000000000000000000000000000000000000000..3689172f72aba237e9578485d2892c9dd9da33f3 --- /dev/null +++ b/core/res/res/drawable-watch/ic_input_extract_action_send.xml @@ -0,0 +1,24 @@ + + + + diff --git a/core/res/res/drawable-xhdpi/vpn_connected.png b/core/res/res/drawable-xhdpi/vpn_connected.png index 1f46be2cea5d125b9324c9aa12522a6798719767..a8761c90af2d7ba8c43016e574dd429db8beb5cf 100644 Binary files a/core/res/res/drawable-xhdpi/vpn_connected.png and b/core/res/res/drawable-xhdpi/vpn_connected.png differ diff --git a/core/res/res/drawable-xhdpi/vpn_disconnected.png b/core/res/res/drawable-xhdpi/vpn_disconnected.png index 847d3f52701ff3e60657eb03d92f343e1f957b47..7118918ec6d52b0156642c561b8541194e6b50a2 100644 Binary files a/core/res/res/drawable-xhdpi/vpn_disconnected.png and b/core/res/res/drawable-xhdpi/vpn_disconnected.png differ diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png new file mode 100644 index 0000000000000000000000000000000000000000..7f7ca1416b7612513d1fb52f1c466d038e51452a Binary files /dev/null and b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png differ diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png new file mode 100644 index 0000000000000000000000000000000000000000..52120b8bef0263677767b2bbbe8b254eddb58d67 Binary files /dev/null and b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png differ diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png new file mode 100644 index 0000000000000000000000000000000000000000..d6e9be9e5daf234bb8974d4033af069d581e6882 Binary files /dev/null and b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png differ diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png new file mode 100644 index 0000000000000000000000000000000000000000..8d76393a1b631dde2f2e72088e58a5942a165e7c Binary files /dev/null and b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png differ diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png new file mode 100644 index 0000000000000000000000000000000000000000..ca9c66e994ff5f5f28d6a1c3b835bc95616b1b40 Binary files /dev/null and b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png differ diff --git a/core/res/res/drawable-xhdpi/watch_switch_track_mtrl_alpha.png b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl_alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa54422738054df52f10a21b14dae21348ef582 Binary files /dev/null and b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl_alpha.png differ diff --git a/core/res/res/drawable-xxhdpi/vpn_connected.png b/core/res/res/drawable-xxhdpi/vpn_connected.png index ea4930c4f420ca9676bef448a65e0114d3f61bef..16b1e4e2467b03b4f60cd07541eb615b0581c7d9 100644 Binary files a/core/res/res/drawable-xxhdpi/vpn_connected.png and b/core/res/res/drawable-xxhdpi/vpn_connected.png differ diff --git a/core/res/res/drawable-xxhdpi/vpn_disconnected.png b/core/res/res/drawable-xxhdpi/vpn_disconnected.png index 4cd0dd4a0226e64404ba071b65690b890b8b83f4..a0258186067c604a31b9bb4a1f4ecf1e8ff02ea0 100644 Binary files a/core/res/res/drawable-xxhdpi/vpn_disconnected.png and b/core/res/res/drawable-xxhdpi/vpn_disconnected.png differ diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png new file mode 100644 index 0000000000000000000000000000000000000000..c0d72d70d6dd96106671f0204188d1cfa6738009 Binary files /dev/null and b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png differ diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png new file mode 100644 index 0000000000000000000000000000000000000000..d7c0ec0fd25e0c999fa7fc56103376e96fff12e4 Binary files /dev/null and b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png differ diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png new file mode 100644 index 0000000000000000000000000000000000000000..5815ba9d3767d4d5a9cb3414e24c830d5a174160 Binary files /dev/null and b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png differ diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png new file mode 100644 index 0000000000000000000000000000000000000000..41da8c0eaaa6dcdb1a71ffffbae52904d8667578 Binary files /dev/null and b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png differ diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png new file mode 100644 index 0000000000000000000000000000000000000000..975eb01cea4a276a84611c3e71713480ea953ebe Binary files /dev/null and b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png differ diff --git a/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl_alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..af2042be7f5983405cd48323f89a6f4890c6774a Binary files /dev/null and b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl_alpha.png differ diff --git a/core/res/res/drawable/emergency_icon.xml b/core/res/res/drawable/emergency_icon.xml index 8e460d786643f68d1fdbf9750e607269477d8827..b2ffa2b4481c7a1fbb695d717fc52f7387ed2e07 100644 --- a/core/res/res/drawable/emergency_icon.xml +++ b/core/res/res/drawable/emergency_icon.xml @@ -1,5 +1,5 @@ + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?attr/colorControlNormal"> + android:pathData="M6.8,17.3C5.3,15.9 4.5,14.0 4.5,12.0c0.0,-2.0 0.8,-3.8 2.1,-5.2l1.4,1.4c-1.0,1.0 -1.6,2.4 -1.6,3.8c0.0,1.5 0.6,2.9 1.6,3.9L6.8,17.3z"/> + android:pathData="M3.3,20.2C1.2,18.0 0.0,15.1 0.0,12.0c0.0,-3.1 1.2,-6.0 3.3,-8.2l1.4,1.4C3.0,7.0 2.0,9.4 2.0,12.0s1.0,5.0 2.7,6.9L3.3,20.2z"/> + android:pathData="M17.2,17.3l-1.4,-1.4c1.1,-1.0 1.6,-2.4 1.6,-3.9c0.0,-1.4 -0.6,-2.8 -1.6,-3.8l1.4,-1.4c1.4,1.4 2.1,3.3 2.1,5.2C19.5,14.0 18.7,15.9 17.2,17.3z"/> + android:pathData="M20.7,20.2l-1.4,-1.4C21.0,17.0 22.0,14.6 22.0,12.0c0.0,-2.6 -1.0,-5.0 -2.7,-6.9l1.4,-1.4C22.8,6.0 24.0,8.9 24.0,12.0C24.0,15.1 22.8,18.0 20.7,20.2z"/> + + diff --git a/core/res/res/drawable/ic_check_circle_24px.xml b/core/res/res/drawable/ic_check_circle_24px.xml index 066a8a73644b0693d03a95597fd2109b998f03bc..e9af9e49a5dd313000e496006522b07edc68c92b 100644 --- a/core/res/res/drawable/ic_check_circle_24px.xml +++ b/core/res/res/drawable/ic_check_circle_24px.xml @@ -18,9 +18,6 @@ Copyright (C) 2015 The Android Open Source Project android:height="24.0dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> - diff --git a/core/res/res/drawable/ic_collapse_notification.xml b/core/res/res/drawable/ic_collapse_notification.xml index 603c159c0abc310a971f733b0ce6e8ecbbe2ed50..124e99e3a4bb709eb949379ccb29e7f87e3f47e8 100644 --- a/core/res/res/drawable/ic_collapse_notification.xml +++ b/core/res/res/drawable/ic_collapse_notification.xml @@ -22,7 +22,4 @@ Copyright (C) 2015 The Android Open Source Project - diff --git a/packages/DocumentsUI/res/drawable/ic_doc_apk.xml b/core/res/res/drawable/ic_doc_apk.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_apk.xml rename to core/res/res/drawable/ic_doc_apk.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_audio.xml b/core/res/res/drawable/ic_doc_audio.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_audio.xml rename to core/res/res/drawable/ic_doc_audio.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_certificate.xml b/core/res/res/drawable/ic_doc_certificate.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_certificate.xml rename to core/res/res/drawable/ic_doc_certificate.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_codes.xml b/core/res/res/drawable/ic_doc_codes.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_codes.xml rename to core/res/res/drawable/ic_doc_codes.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_compressed.xml b/core/res/res/drawable/ic_doc_compressed.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_compressed.xml rename to core/res/res/drawable/ic_doc_compressed.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_contact.xml b/core/res/res/drawable/ic_doc_contact.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_contact.xml rename to core/res/res/drawable/ic_doc_contact.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_document.xml b/core/res/res/drawable/ic_doc_document.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_document.xml rename to core/res/res/drawable/ic_doc_document.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_event.xml b/core/res/res/drawable/ic_doc_event.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_event.xml rename to core/res/res/drawable/ic_doc_event.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_excel.xml b/core/res/res/drawable/ic_doc_excel.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_excel.xml rename to core/res/res/drawable/ic_doc_excel.xml diff --git a/core/res/res/drawable/ic_doc_folder.xml b/core/res/res/drawable/ic_doc_folder.xml new file mode 100644 index 0000000000000000000000000000000000000000..dcbce010810edef6e7197a2a662ea31f4f0cc409 --- /dev/null +++ b/core/res/res/drawable/ic_doc_folder.xml @@ -0,0 +1,24 @@ + + + + diff --git a/packages/DocumentsUI/res/drawable/ic_doc_font.xml b/core/res/res/drawable/ic_doc_font.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_font.xml rename to core/res/res/drawable/ic_doc_font.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_generic.xml b/core/res/res/drawable/ic_doc_generic.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_generic.xml rename to core/res/res/drawable/ic_doc_generic.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_image.xml b/core/res/res/drawable/ic_doc_image.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_image.xml rename to core/res/res/drawable/ic_doc_image.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_pdf.xml b/core/res/res/drawable/ic_doc_pdf.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_pdf.xml rename to core/res/res/drawable/ic_doc_pdf.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_powerpoint.xml b/core/res/res/drawable/ic_doc_powerpoint.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_powerpoint.xml rename to core/res/res/drawable/ic_doc_powerpoint.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_presentation.xml b/core/res/res/drawable/ic_doc_presentation.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_presentation.xml rename to core/res/res/drawable/ic_doc_presentation.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_spreadsheet.xml b/core/res/res/drawable/ic_doc_spreadsheet.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_spreadsheet.xml rename to core/res/res/drawable/ic_doc_spreadsheet.xml diff --git a/core/res/res/drawable/ic_doc_text.xml b/core/res/res/drawable/ic_doc_text.xml new file mode 100644 index 0000000000000000000000000000000000000000..7fc04e811b1cce2dce65a4fb69af194ae301c568 --- /dev/null +++ b/core/res/res/drawable/ic_doc_text.xml @@ -0,0 +1,24 @@ + + + + diff --git a/packages/DocumentsUI/res/drawable/ic_doc_video.xml b/core/res/res/drawable/ic_doc_video.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_video.xml rename to core/res/res/drawable/ic_doc_video.xml diff --git a/packages/DocumentsUI/res/drawable/ic_doc_word.xml b/core/res/res/drawable/ic_doc_word.xml similarity index 100% rename from packages/DocumentsUI/res/drawable/ic_doc_word.xml rename to core/res/res/drawable/ic_doc_word.xml diff --git a/core/res/res/drawable/ic_expand_more_48dp.xml b/core/res/res/drawable/ic_expand_more_48dp.xml index 11323e3b0f7c5dab3e9055989906dd8b0ebbcbaf..5a71669428b571728c6b42bd5198120c5238a78b 100644 --- a/core/res/res/drawable/ic_expand_more_48dp.xml +++ b/core/res/res/drawable/ic_expand_more_48dp.xml @@ -21,7 +21,4 @@ Copyright (C) 2015 The Android Open Source Project - diff --git a/core/res/res/drawable/ic_expand_notification.xml b/core/res/res/drawable/ic_expand_notification.xml index db7d3ebbbc2198bfbdf8d0997cd02d560af03123..847e3269398d25505106e4e2dae9bfed71042ade 100644 --- a/core/res/res/drawable/ic_expand_notification.xml +++ b/core/res/res/drawable/ic_expand_notification.xml @@ -22,7 +22,4 @@ Copyright (C) 2015 The Android Open Source Project - diff --git a/core/res/res/drawable/ic_feedback.xml b/core/res/res/drawable/ic_feedback.xml index b2d1cb80c9c1742baea72254237bd6166a192e28..365863da31e210ea737e155f5b9f5be332a5d907 100644 --- a/core/res/res/drawable/ic_feedback.xml +++ b/core/res/res/drawable/ic_feedback.xml @@ -18,9 +18,6 @@ Copyright (C) 2016 The Android Open Source Project android:height="24.0dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> - diff --git a/core/res/res/drawable/ic_lock_power_off.xml b/core/res/res/drawable/ic_lock_power_off.xml index 718f17ed0c19637383bf527e85c9e494bf90a9ec..babd1be220cb086b3551742e079fcab393245351 100644 --- a/core/res/res/drawable/ic_lock_power_off.xml +++ b/core/res/res/drawable/ic_lock_power_off.xml @@ -1,19 +1,25 @@ - - - - + + + diff --git a/core/res/res/drawable/ic_more_items.xml b/core/res/res/drawable/ic_more_items.xml index 5fdcdcef7317d51aef0c0ce6ad810a7e2d0e0e54..0ec754c5c7c9d0b581433ffe66687ba17b3adac1 100644 --- a/core/res/res/drawable/ic_more_items.xml +++ b/core/res/res/drawable/ic_more_items.xml @@ -24,6 +24,5 @@ android:fillColor="#000000" android:pathData="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z" /> - + \ No newline at end of file diff --git a/core/res/res/drawable/ic_refresh.xml b/core/res/res/drawable/ic_refresh.xml index 1f671684861fbc7ffcacea938e53963dec71976e..1297407fbb8b8d8219c6727db72cb79759582348 100644 --- a/core/res/res/drawable/ic_refresh.xml +++ b/core/res/res/drawable/ic_refresh.xml @@ -21,7 +21,4 @@ Copyright (C) 2016 The Android Open Source Project - diff --git a/packages/SystemUI/res/drawable/ic_night_mode.xml b/core/res/res/drawable/ic_restart.xml similarity index 61% rename from packages/SystemUI/res/drawable/ic_night_mode.xml rename to core/res/res/drawable/ic_restart.xml index caa7a47ee5b463aa4e074b4a3dd7ae035487a350..47ac483fa3115722f6eae1f9aa9196ffa7cac134 100644 --- a/packages/SystemUI/res/drawable/ic_night_mode.xml +++ b/core/res/res/drawable/ic_restart.xml @@ -16,9 +16,13 @@ + android:tint="?attr/colorControlNormal"> + android:fillColor="#FF000000" + android:pathData="M12.0,4.0L12.0,1.0L8.0,5.0l4.0,4.0L12.0,6.0c3.9,0.0 7.0,3.1 7.0,7.0c0.0,3.9 -3.1,7.0 -7.0,7.0l0.0,2.0c5.0,0.0 9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0z"/> + diff --git a/core/res/res/drawable/ic_schedule.xml b/core/res/res/drawable/ic_schedule.xml index 899dc821844e47b109012cd9e93e8e99253b943a..55d54b139ae07e3e3d320323a17e5d4dc59478d6 100644 --- a/core/res/res/drawable/ic_schedule.xml +++ b/core/res/res/drawable/ic_schedule.xml @@ -21,9 +21,6 @@ Copyright (C) 2016 The Android Open Source Project - diff --git a/core/res/res/drawable/perm_group_calendar.xml b/core/res/res/drawable/perm_group_calendar.xml index 4dc7b37dbf254ce5fa89b3b513d787eece017300..85a783e49497408847cb5449bd8a6891b74ee408 100644 --- a/core/res/res/drawable/perm_group_calendar.xml +++ b/core/res/res/drawable/perm_group_calendar.xml @@ -24,6 +24,5 @@ android:fillColor="#000000" android:pathData="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99 .9 -1.99 2L3 19c0 1.1 .89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z" /> - + \ No newline at end of file diff --git a/core/res/res/drawable/perm_group_camera.xml b/core/res/res/drawable/perm_group_camera.xml index 741a40e2891dceb640ccc4284e3ffe0095515fe3..61903a55361f4a10df0b8270df73a638449cc415 100644 --- a/core/res/res/drawable/perm_group_camera.xml +++ b/core/res/res/drawable/perm_group_camera.xml @@ -28,6 +28,4 @@ android:pathData="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" /> - \ No newline at end of file diff --git a/core/res/res/drawable/perm_group_contacts.xml b/core/res/res/drawable/perm_group_contacts.xml index d698fd1735deb16bcd5fd8a51422ea9b640e6f35..8f9dc3e0d178eebaef6b89cad045f541832da80b 100644 --- a/core/res/res/drawable/perm_group_contacts.xml +++ b/core/res/res/drawable/perm_group_contacts.xml @@ -20,8 +20,6 @@ android:viewportWidth="24" android:viewportHeight="24"> - - \ No newline at end of file diff --git a/core/res/res/drawable/perm_group_microphone.xml b/core/res/res/drawable/perm_group_microphone.xml index c565d203caa42254a5666b6f3103dba7d4189e5a..d494e67c63ad5bdc86a9146cf56d143f302f2625 100644 --- a/core/res/res/drawable/perm_group_microphone.xml +++ b/core/res/res/drawable/perm_group_microphone.xml @@ -25,6 +25,4 @@ android:pathData="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" /> - \ No newline at end of file diff --git a/core/res/res/drawable/perm_group_phone_calls.xml b/core/res/res/drawable/perm_group_phone_calls.xml index a64789433608c764bac61cbf1c9f648af28b5a02..324d8649270342c3cf1fe43c08d36a62f0da1420 100644 --- a/core/res/res/drawable/perm_group_phone_calls.xml +++ b/core/res/res/drawable/perm_group_phone_calls.xml @@ -19,9 +19,6 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - - - \ No newline at end of file diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml index 477270d202e6cb02e4cb4a7c36e6970daa51c074..1ff169350d40e9b3b8415846c863f8e9fbba64e8 100644 --- a/core/res/res/drawable/perm_group_storage.xml +++ b/core/res/res/drawable/perm_group_storage.xml @@ -24,6 +24,4 @@ android:fillColor="#000000" android:pathData="M10 4H4c-1.1 0-1.99 .9 -1.99 2L2 18c0 1.1 .9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" /> - \ No newline at end of file diff --git a/core/res/res/drawable/progress_indeterminate_anim_large_material.xml b/core/res/res/drawable/progress_indeterminate_anim_large_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..560ec5af508f4159fa8d92ba1a2d213f42408ac2 --- /dev/null +++ b/core/res/res/drawable/progress_indeterminate_anim_large_material.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/packages/SystemUI/res/xml/color_and_appearance.xml b/core/res/res/drawable/progress_indeterminate_anim_medium_material.xml similarity index 56% rename from packages/SystemUI/res/xml/color_and_appearance.xml rename to core/res/res/drawable/progress_indeterminate_anim_medium_material.xml index 21f890eb058d235722433c23d1a6e77c039ce322..fbea22f443e1a569d046380b75ad6c1874934311 100644 --- a/packages/SystemUI/res/xml/color_and_appearance.xml +++ b/core/res/res/drawable/progress_indeterminate_anim_medium_material.xml @@ -13,18 +13,15 @@ See the License for the specific language governing permissions and limitations under the License. --> + - + - + - - - + \ No newline at end of file diff --git a/core/res/res/drawable/progress_large_material.xml b/core/res/res/drawable/progress_large_material.xml index 526f9141d716da234b86d7646fd15fc6da55d9d4..ee82e35d00f5fec117ea41c99c41010d8ad07a9d 100644 --- a/core/res/res/drawable/progress_large_material.xml +++ b/core/res/res/drawable/progress_large_material.xml @@ -13,16 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - + + + + diff --git a/core/res/res/drawable/progress_medium_material.xml b/core/res/res/drawable/progress_medium_material.xml index cc35816c9c3c61ebf5443ebf497163bba6ec651b..5c9260069e5d0eb617fe67e446df48bac590ee80 100644 --- a/core/res/res/drawable/progress_medium_material.xml +++ b/core/res/res/drawable/progress_medium_material.xml @@ -13,15 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - \ No newline at end of file + + + + diff --git a/core/res/res/drawable/progress_small_material.xml b/core/res/res/drawable/progress_small_material.xml index c6e43801cdf76c6d3ada4f50131265821e10105a..cec9d9565183dca04332aba123edc441f87560ba 100644 --- a/core/res/res/drawable/progress_small_material.xml +++ b/core/res/res/drawable/progress_small_material.xml @@ -13,16 +13,17 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - + + + + + + + + + diff --git a/core/res/res/drawable/progress_static_material.xml b/core/res/res/drawable/progress_static_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..b078fa93a15579ff0f1f9060e2ad9f76e9455de4 --- /dev/null +++ b/core/res/res/drawable/progress_static_material.xml @@ -0,0 +1,25 @@ + + + + diff --git a/core/res/res/drawable/watch_switch_thumb_material_anim.xml b/core/res/res/drawable/watch_switch_thumb_material_anim.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e3e89338dabe28c6beef0d207f6d448e5a1b7bc --- /dev/null +++ b/core/res/res/drawable/watch_switch_thumb_material_anim.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/drawable/watch_switch_track_material.xml b/core/res/res/drawable/watch_switch_track_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..79e92a3310710bd5973911f771911356e36bf12c --- /dev/null +++ b/core/res/res/drawable/watch_switch_track_material.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/core/res/res/interpolator-watch/progress_indeterminate_rotation_interpolator.xml b/core/res/res/interpolator-watch/progress_indeterminate_rotation_interpolator.xml new file mode 100644 index 0000000000000000000000000000000000000000..ed2655cb0ac8cd68002c3e45056c45a4b9fec3af --- /dev/null +++ b/core/res/res/interpolator-watch/progress_indeterminate_rotation_interpolator.xml @@ -0,0 +1,18 @@ + + + diff --git a/core/res/res/interpolator-watch/trim_end_interpolator.xml b/core/res/res/interpolator-watch/trim_end_interpolator.xml new file mode 100644 index 0000000000000000000000000000000000000000..f46d5e0e7c8211526b44c16efa6ef5fc70eaeed8 --- /dev/null +++ b/core/res/res/interpolator-watch/trim_end_interpolator.xml @@ -0,0 +1,18 @@ + + + diff --git a/core/res/res/interpolator-watch/trim_offset_interpolator.xml b/core/res/res/interpolator-watch/trim_offset_interpolator.xml new file mode 100644 index 0000000000000000000000000000000000000000..d58672e9cb42e6fd81fe7f5cd6a8d819df313b8b --- /dev/null +++ b/core/res/res/interpolator-watch/trim_offset_interpolator.xml @@ -0,0 +1,18 @@ + + + diff --git a/core/res/res/interpolator-watch/trim_start_interpolator.xml b/core/res/res/interpolator-watch/trim_start_interpolator.xml new file mode 100644 index 0000000000000000000000000000000000000000..365609c97d758916d75c22087c26ef241ee910b9 --- /dev/null +++ b/core/res/res/interpolator-watch/trim_start_interpolator.xml @@ -0,0 +1,18 @@ + + + diff --git a/core/res/res/layout-notround-watch/alert_dialog_title_material.xml b/core/res/res/layout-notround-watch/alert_dialog_title_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..307c6db91c3a86d5bf76321e675b1c02fc7a57f6 --- /dev/null +++ b/core/res/res/layout-notround-watch/alert_dialog_title_material.xml @@ -0,0 +1,38 @@ + + + + + + diff --git a/core/res/res/layout-round-watch/alert_dialog_title_material.xml b/core/res/res/layout-round-watch/alert_dialog_title_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..7e71e4180341749dc9f2b6e8354ec6c21e305547 --- /dev/null +++ b/core/res/res/layout-round-watch/alert_dialog_title_material.xml @@ -0,0 +1,37 @@ + + + + + + diff --git a/core/res/res/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml index 5e3ca14dd96caf82320a5e53d733ffd476eb83b7..cd6af463b8ff41b0af50c0a1f50af7eb102e3ffd 100644 --- a/core/res/res/layout-sw600dp/date_picker_dialog.xml +++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml @@ -22,4 +22,4 @@ android:layout_height="wrap_content" android:spinnersShown="true" android:calendarViewShown="true" - android:datePickerMode="@integer/date_picker_mode" /> + android:dialogMode="true" /> diff --git a/core/res/res/layout-watch/alert_dialog_material.xml b/core/res/res/layout-watch/alert_dialog_material.xml new file mode 100644 index 0000000000000000000000000000000000000000..2fe13de2120af06cc41a6768a32834186ee29ea7 --- /dev/null +++ b/core/res/res/layout-watch/alert_dialog_material.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + +

    diff --git a/docs/html-intl/intl/es/distribute/googleplay/families/start.jd b/docs/html-intl/intl/es/distribute/googleplay/families/start.jd index 3ed1eb39a9ae9f7c376db2fe1d859f70cc47da51..d6d6126b2d98c813fac8851ce9fabf1a5269a302 100644 --- a/docs/html-intl/intl/es/distribute/googleplay/families/start.jd +++ b/docs/html-intl/intl/es/distribute/googleplay/families/start.jd @@ -78,7 +78,7 @@ page.metaDescription=Únete a Diseñado para familias en pocos pasos sencillos.

    Nota: Las aplicaciones publicadas en el programa Diseñado para familias - también están disponibles para todos los usuarios en Google Play. + también están disponibles para todos los usuarios en Google Play.

    diff --git a/docs/html-intl/intl/es/distribute/googleplay/quality/auto.jd b/docs/html-intl/intl/es/distribute/googleplay/quality/auto.jd index c7cb65dc4066530dbd563b4f1dea47e28da37075..2b1f40382c6963fe5e6825aba40cb7b56ee16383 100644 --- a/docs/html-intl/intl/es/distribute/googleplay/quality/auto.jd +++ b/docs/html-intl/intl/es/distribute/googleplay/quality/auto.jd @@ -477,7 +477,7 @@ data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6"> No. Cuando Google inicie el proceso de aprobación, tu aplicación para Auto se someterá a una revisión de seguridad del conductor y no estará disponible para distribución hasta que se apruebe. Dado que es el mismo APK que el - que utilizas para teléfonos y tablets, tus actualizaciones en la Play Store para esos dispositivos no estará disponible hasta que + que utilizas para teléfonos y tablets, tus actualizaciones en la Play Store para esos dispositivos no estará disponible hasta que finalice el proceso de aprobación para Auto.

    diff --git a/docs/html-intl/intl/es/distribute/googleplay/quality/core.jd b/docs/html-intl/intl/es/distribute/googleplay/quality/core.jd index 8588c6b80f793da406b742b54eecc47b41ff6c3b..b972949362b3c0ea388fbc7bd293b1f3f4db4ae3 100644 --- a/docs/html-intl/intl/es/distribute/googleplay/quality/core.jd +++ b/docs/html-intl/intl/es/distribute/googleplay/quality/core.jd @@ -12,7 +12,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
  • Google Play
  • - +

    Prueba

    1. Configuración de un entorno de prueba
    2. @@ -24,7 +24,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
    3. Calidad de las aplicaciones para tablets
    4. Optimiza tu aplicación
    - + @@ -84,7 +84,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg ID - + Descripción diff --git a/docs/html-intl/intl/es/distribute/googleplay/quality/tablets.jd b/docs/html-intl/intl/es/distribute/googleplay/quality/tablets.jd index 62c6f8738a8a237be42661084bb37c0f6239c449..e0049232b969045aa9e1839d4e6b24a21f61a41f 100644 --- a/docs/html-intl/intl/es/distribute/googleplay/quality/tablets.jd +++ b/docs/html-intl/intl/es/distribute/googleplay/quality/tablets.jd @@ -56,7 +56,7 @@ Xnonavpage=true

    El primer paso en la provisión de una excelente experiencia con la aplicación en tablets es asegurarte de que la aplicación cumpla con los criterios de calidad de la aplicación principal en todos los dispositivos - y formatos a los que apunte. Para obtener información completa, consulta las Pautas de calidad de la aplicación principal. + y formatos a los que apunte. Para obtener información completa, consulta las Pautas de calidad de la aplicación principal.

    @@ -119,7 +119,7 @@ style="font-weight:500;">Despídete de tu IU "estirada": En las tablets,

  • Proporciona diseños personalizados, según sea necesario, para las pantallas large y xlarge. También puedes proporcionar diseños que se cargarán en función de la dimensión - más corta de la pantalla o la altura y el ancho + más corta de la pantalla o la altura y el ancho mínimos disponibles.
  • @@ -208,7 +208,7 @@ android.app.Fragment}. Esto te permite maximizar la reutilización de códigos entre diferentes factores y pantallas que compartan contenido.
  • Decide en qué tamaños de pantalla usarás una IU multipanel y luego proporciona los - diferentes diseños en los depósitos para el tamaño de pantalla correspondiente (como + diferentes diseños en los depósitos para el tamaño de pantalla correspondiente (como large/xlarge) o anchos mínimos de pantalla (como sw600dp/sw720).
  • @@ -492,7 +492,7 @@ o simplemente centrando el icono dentro del botón transparente.
    <uses-feature android:name="android.hardware.telephony" android:required="false" />
    -
  • En forma similar, revisa el manifiesto para detectar elementos <permission> que +
  • En forma similar, revisa el manifiesto para detectar elementos <permission> que impliquen requisitos de características de hardware que no sean adecuadas para tablets. Si encuentras esos permisos, asegúrate de declarar explícitamente un elemento @@ -735,7 +735,7 @@ o simplemente centrando el icono dentro del botón transparente.
  • distribución.

    Si la página de Sugerencias para la optimización indica problemas "Pendientes" que crees que no - corresponden a tu aplicación o afectan la calidad de la aplicación en las tablets, + corresponden a tu aplicación o afectan la calidad de la aplicación en las tablets, usa el Formulario de contacto de Diseñado para tablets» para comunicárnoslo. Revisaremos tu aplicación y actualizaremos tu página de Sugerencias para la optimización según corresponda.

    diff --git a/docs/html-intl/intl/es/distribute/googleplay/tv.jd b/docs/html-intl/intl/es/distribute/googleplay/tv.jd index e3a95bc2929db6b18e6835822601791578e5737e..e9deacbcfb6f911b81ec5ee4a6101c52bba0e6ea 100644 --- a/docs/html-intl/intl/es/distribute/googleplay/tv.jd +++ b/docs/html-intl/intl/es/distribute/googleplay/tv.jd @@ -132,7 +132,7 @@ page.metaDescription=Distribuye tus aplicaciones, juegos y contenido para Androi
    • Cumple las pautas de Calidad de la aplicación principal
        -
      • Sigue las pautas de +
      • Sigue las pautas de Diseño Android. Presta especial atención al uso de Material Design en tu aplicación.
      • @@ -261,7 +261,7 @@ page.metaDescription=Distribuye tus aplicaciones, juegos y contenido para Androi los criterios, recibirás una notificación por correo electrónico enviada a tu cuenta de desarrollador con un resumen de las áreas que debes abordar. Una vez que realices los ajustes necesarios, puedes cargar una nueva versión de tu aplicación a la Consola para - desarrolladores. + desarrolladores.

        @@ -282,7 +282,7 @@ page.metaDescription=Distribuye tus aplicaciones, juegos y contenido para Androi

      • Aprobada: se revisó tu aplicación y se aprobó. La aplicación - estará disponible de forma directa para los usuarios de Android TV. + estará disponible de forma directa para los usuarios de Android TV.
      • diff --git a/docs/html-intl/intl/es/distribute/googleplay/wear.jd b/docs/html-intl/intl/es/distribute/googleplay/wear.jd index f23315d86495f748a8f4d646804deac01e64c07b..2c8a804e90d5b1ab3c4548fd076efff0c7a6dbf2 100644 --- a/docs/html-intl/intl/es/distribute/googleplay/wear.jd +++ b/docs/html-intl/intl/es/distribute/googleplay/wear.jd @@ -127,7 +127,7 @@ Una vez que hayas leído las pautas, el paso siguientes es desarrollar tu aplica
        • Cumple las pautas de Calidad de la aplicación principal.
            -
          • Sigue las pautas de +
          • Sigue las pautas de Diseño Android. Presta especial atención al uso de Material Design en tu aplicación.
          • @@ -152,7 +152,7 @@ desarrollo de aplicaciones para Wear.

            Una vez que hayas creado tu APK listo para el lanzamiento y lo hayas probado para asegurarte de que cumple todos los criterios de Calidad de las aplicaciones para Wear, cárgalo a la Consola para desarrolladores. Actualiza el directorio de tu tienda con capturas de pantalla de tu aplicación para Wear y configura opciones - de distribución, según sea necesario. Si no sabes cómo prepararte para el lanzamiento en Google Play, consulta la + de distribución, según sea necesario. Si no sabes cómo prepararte para el lanzamiento en Google Play, consulta la Lista de comprobación para el lanzamiento.

            diff --git a/docs/html-intl/intl/es/distribute/tools/launch-checklist.jd b/docs/html-intl/intl/es/distribute/tools/launch-checklist.jd index ad42663a6f929710d1ce8dc4444b512770efb1c1..be23c863ae5fec40fcd711031d9b117a9fbe55c0 100644 --- a/docs/html-intl/intl/es/distribute/tools/launch-checklist.jd +++ b/docs/html-intl/intl/es/distribute/tools/launch-checklist.jd @@ -870,7 +870,7 @@ data-maxresults="6">
          • "Dispositivos compatibles" indica que tus aplicaciones están llegando a los dispositivos - a los que pretendías llegar. De lo contrario, deberás verificar con tu equipo de desarrollo + a los que pretendías llegar. De lo contrario, deberás verificar con tu equipo de desarrollo los requisitos y las reglas de filtrado de las aplicaciones.

          • diff --git a/docs/html-intl/intl/es/distribute/tools/localization-checklist.jd b/docs/html-intl/intl/es/distribute/tools/localization-checklist.jd index 7cb3ccb54b39c0aca8638ff4cd985dadcd27a1ba..c06849013fa7c65f69b8e41d8c7d6151b5bc9c1b 100644 --- a/docs/html-intl/intl/es/distribute/tools/localization-checklist.jd +++ b/docs/html-intl/intl/es/distribute/tools/localization-checklist.jd @@ -903,7 +903,7 @@ data-maxresults="6"> Responde las reseñas, si fuera posible. Te recomendamos que interactúes con los usuarios internacionales en sus idiomas o en un idioma común, si fuera posible. Si no lo es, puedes intentar utilizar herramientas de traducción, aunque es posible que no puedas - prever los resultados. Si tu aplicación se vuelve muy popular en un idioma, considera + prever los resultados. Si tu aplicación se vuelve muy popular en un idioma, considera la posibilidad de obtener ayuda por parte de hablantes nativos para brindar soporte.

            diff --git a/docs/html-intl/intl/es/google/play/filters.jd b/docs/html-intl/intl/es/google/play/filters.jd index 03565b9b175d14955881bf41b3c4910d1c8c47c4..07238ee327510e7df5bac6263e4e7b05749ed06e 100644 --- a/docs/html-intl/intl/es/google/play/filters.jd +++ b/docs/html-intl/intl/es/google/play/filters.jd @@ -81,7 +81,7 @@ Por ejemplo, si una aplicación requiere una cámara, Google Play no mostrará l solicite específicamente la aplicación al hacer clic en un vínculo profundo que apunte directamente a la ID de la aplicación en Google Play.

            -

            Puedes usar cualquier combinación de los filtros disponibles para tu aplicación. Por ejemplo, puedes establecer un requisito +

            Puedes usar cualquier combinación de los filtros disponibles para tu aplicación. Por ejemplo, puedes establecer un requisito minSdkVersion de "4" y configurar smallScreens="false" en la aplicación; luego, al cargar la aplicación a Google Play, podrías apuntar a países (operadores) europeos únicamente. De este modo, los filtros de Google Play evitarán que la aplicación esté disponible en un dispositivo @@ -102,7 +102,7 @@ Play, pueden ver todas las aplicaciones publicadas. No obstante, el sitio we

            Filtrado en función del manifiesto de la aplicación

            -

            La mayoría de los filtros son activados por elementos del archivo de manifiesto de una +

            La mayoría de los filtros son activados por elementos del archivo de manifiesto de una aplicación, AndroidManifest.xml (aunque no todo lo que se encuentra en el archivo de manifiesto puede desencadenar el filtrado). La tabla 1 contiene los elementos del manifiesto que debes usar para desencadenar el diff --git a/docs/html-intl/intl/es/preview/j8-jack.jd b/docs/html-intl/intl/es/guide/platform/j8-jack.jd similarity index 100% rename from docs/html-intl/intl/es/preview/j8-jack.jd rename to docs/html-intl/intl/es/guide/platform/j8-jack.jd diff --git a/docs/html-intl/intl/es/preview/features/multi-window.jd b/docs/html-intl/intl/es/guide/topics/ui/multi-window.jd similarity index 98% rename from docs/html-intl/intl/es/preview/features/multi-window.jd rename to docs/html-intl/intl/es/guide/topics/ui/multi-window.jd index 89bc3194c577c217e5b4a85cfc573f1b6b70b8e0..0a9cbe2b509e3a5db554ed160bc1744cea7782d3 100644 --- a/docs/html-intl/intl/es/preview/features/multi-window.jd +++ b/docs/html-intl/intl/es/guide/topics/ui/multi-window.jd @@ -4,8 +4,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form" @jd:body -

            -
            +
            +

            En este documento

            1. Información general
            2. @@ -69,8 +69,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form"
          - +

          Figura 1: Dos aplicaciones ejecutándose una al lado de la otra en modo de pantalla dividida.

          @@ -158,7 +158,7 @@ page.keywords="multi-window", "android N", "split screen", "free-form" si quieres que las actividades de tu aplicación admitan la visualización de ventanas múltiples. Puedes establecer atributos en tu manifiesto para controlar el tamaño y el diseño. La configuración de atributos de una actividad raíz se aplica a todas las actividades - de su pila de tareas. Por ejemplo, si + de su pila de tareas. Por ejemplo, si android:resizeableActivity está configurado en true para la actividad raíz, se puede modificar el tamaño de todas las actividades de la pila de tareas.

          @@ -474,7 +474,7 @@ android:supportsPictureInPicture=["true" | "false"]

          Ya sea que actualices o no tu aplicación para Android N, debes - verificar la forma en que se comporta en modo de ventanas múltiples en caso de que un usuario intente iniciarla + verificar la forma en que se comporta en modo de ventanas múltiples en caso de que un usuario intente iniciarla en modo de ventanas múltiples en un dispositivo con Android N.

          @@ -526,7 +526,7 @@ android:supportsPictureInPicture=["true" | "false"]
        • Cambia el tamaño de tu aplicación en modo de pantalla dividida al arrastrar la línea divisoria. - Verifica que la aplicación cambie de tamaño sin fallar y que estén visibles los elementos + Verifica que la aplicación cambie de tamaño sin fallar y que estén visibles los elementos necesarios de la IU.
        • diff --git a/docs/html-intl/intl/es/index.jd b/docs/html-intl/intl/es/index.jd index 66f9bf0281d0ea035dc526336900c144edd2fd23..1ecf47c4d8b3f32bd04f3f5234e0c2d1915a72f6 100644 --- a/docs/html-intl/intl/es/index.jd +++ b/docs/html-intl/intl/es/index.jd @@ -5,49 +5,36 @@ page.customHeadTag= - -
          -
          -
          - -

          Android N Developer Preview

          -

          - Get ready for the next version of Android! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. +

          +
          -
    - Algoritme intisari yang digunakan untuk menghasilkan pin. Saat ini, hanya + Algoritme intisari yang digunakan untuk menghasilkan pin. Saat ini, hanya {@code "SHA-256"} yang didukung.
    diff --git a/docs/html-intl/intl/in/preview/features/data-saver.jd b/docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd similarity index 99% rename from docs/html-intl/intl/in/preview/features/data-saver.jd rename to docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd index f64609bedf66392c917e5be7017113d2df0b05f5..abd4e4391dfa281a73d924272b3bd8203731ec83 100644 --- a/docs/html-intl/intl/in/preview/features/data-saver.jd +++ b/docs/html-intl/intl/id/training/basics/network-ops/data-saver.jd @@ -4,8 +4,8 @@ page.keywords="android N", "data usage", "metered network" page.image=images/cards/card-nyc_2x.jpg @jd:body -
    -
    +
    +

    Dalam dokumen ini

    @@ -50,7 +50,7 @@ page.image=images/cards/card-nyc_2x.jpg

    N Developer Preview memperluas {@link android.net.ConnectivityManager} API untuk menyediakan cara pada aplikasi untuk menerima preferensi Data Saver - pengguna dan memantau perubahan + pengguna dan memantau perubahan preferensi. Hal ini dianggap praktik terbaik bagi aplikasi untuk memeriksa apakah pengguna telah mengaktifkan DataSaver dan berusaha membatasi penggunaan data latar depan dan data latar belakang. @@ -231,4 +231,4 @@ mengonfigurasi izin jaringan: Membuang UID paket tertentu dari daftar putih untuk memblokir penggunaan data berkuota di latar belakang saat Data Saver diaktifkan. - \ No newline at end of file + diff --git a/docs/html-intl/intl/id/training/material/animations.jd b/docs/html-intl/intl/id/training/material/animations.jd new file mode 100644 index 0000000000000000000000000000000000000000..e57a03f166c88d0377ec4622ba8f4f334b53721a --- /dev/null +++ b/docs/html-intl/intl/id/training/material/animations.jd @@ -0,0 +1,550 @@ +page.title=Mendefinisikan Animasi Custom + +@jd:body + +

    + + +

    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:

    + +
      +
    • Umpan balik sentuh
    • +
    • Singkap Melingkar
    • +
    • Transisi aktivitas
    • +
    • Gerakan melengkung
    • +
    • Perubahan status tampilan
    • +
    + + +

    Menyesuaikan Umpan Balik Sentuh

    + +

    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.

    + +

    Di sebagian besar kasus, Anda harus menerapkan fungsionalitas ini dalam XML tampilan dengan menetapkan +latar belakang tampilan sebagai:

    + +
      +
    • ?android:attr/selectableItemBackground untuk riak berbatas.
    • +
    • ?android:attr/selectableItemBackgroundBorderless 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.
    • +
    + +

    Catatan: selectableItemBackgroundBorderless adalah +atribut baru yang diperkenalkan di API level 21.

    + + +

    Atau, Anda bisa mendefinisikan {@link android.graphics.drawable.RippleDrawable} +sebagai sumber daya XML dengan menggunakan elemen ripple.

    + +

    Anda bisa menetapkan warna ke objek-objek {@link android.graphics.drawable.RippleDrawable}. Untuk mengubah +warna default umpan balik sentuh, gunakan atribut android:colorControlHighlight +tema.

    + +

    Untuk informasi selengkapnya, lihat referensi API bagi kelas {@link +android.graphics.drawable.RippleDrawable}.

    + + +

    Menggunakan Reveal Effect

    + +

    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.

    + +

    Untuk memperlihatkan tampilan yang sebelumnya tidak terlihat dengan menggunakan efek ini:

    + +
    +// 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();
    +
    + +

    Untuk menyembunyikan sebuah tampilan yang sebelumnya terlihat dengan menggunakan efek ini:

    + +
    +// 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() {
    +    @Override
    +    public void onAnimationEnd(Animator animation) {
    +        super.onAnimationEnd(animation);
    +        myView.setVisibility(View.INVISIBLE);
    +    }
    +});
    +
    +// start the animation
    +anim.start();
    +
    + + +

    Menyesuaikan Transisi Aktivitas

    + + +
    +
    + +
    +
    +

    Gambar 1 - Transisi + dengan elemen bersama.

    + Untuk memutar ulang film, klik layar perangkat +
    +
    + +

    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.

    + +
      +
    • Transisi masuk menentukan cara tampilan di aktivitas memasuki suatu babak. +misalnya, dalam transisi masuk explode, tampilan memasuki babak dari sisi luar +dan melayang masuk ke arah tengah layar.
    • + +
    • Transisi keluar menentukan cara tampilan di aktivitas keluar dari suatu babak. Misalnya +, dalam transisi keluar explode, tampilan akan keluar dari babak dari bagian +tengahnya.
    • + +
    • Transisi elemen bersama 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 changeImageTransform +mentransformasikan dan menskalakan gambar secara mulus di antara aktivitas-aktivitas ini.
    • +
    + +

    Android 5.0 (API level 21) mendukung transisi masuk dan transisi keluar ini:

    + +
      +
    • explode - Memindahkan tampilan masuk ke atau keluar dari tengah babak.
    • +
    • slide - Memindahkan tampilan masuk ke atau keluar dari salah satu tepi babak.
    • +
    • fade - Menambahkan atau menghapus tampilan dari babak dengan mengubah opasitasnya.
    • +
    + +

    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}.

    + +

    Android 5.0 (API level 21) juga mendukung transisi elemen bersama ini:

    + +
      +
    • changeBounds - Menganimasikan perubahan pada batas-batas layout tampilan target.
    • +
    • changeClipBounds - Menganimasikan perubahan pada batas-batas pemangkasan tampilan target.
    • +
    • changeTransform - Menganimasikan perubahan pada skala dan rotasi tampilan target.
    • +
    • changeImageTransform - Menganimasikan perubahan pada ukuran dan skala gambar target.
    • +
    + +

    Bila Anda mengaktifkan transisi aktivitas dalam aplikasi, transisi memudar-silang default akan +diaktifkan di antara aktivitas masuk dan aktivitas keluar.

    + + +

    Gambar 2 - Transisi babak dengan satu elemen bersama. +

    + +

    Menetapkan transisi custom

    + +

    Pertama, aktifkan transisi konten jendela dengan atribut android:windowContentTransitions +bila Anda mendefinisikan gaya yang mewarisi tema bahan. Anda juga bisa menetapkan +transisi-transisi masuk, keluar, dan elemen bersama dalam definisi gaya:

    + +
    +<style name="BaseAppTheme" parent="android:Theme.Material">
    +  <!-- enable window content transitions -->
    +  <item name="android:windowContentTransitions">true</item>
    +
    +  <!-- specify enter and exit transitions -->
    +  <item name="android:windowEnterTransition">@transition/explode</item>
    +  <item name="android:windowExitTransition">@transition/explode</item>
    +
    +  <!-- specify shared element transitions -->
    +  <item name="android:windowSharedElementEnterTransition">
    +    @transition/change_image_transform</item>
    +  <item name="android:windowSharedElementExitTransition">
    +    @transition/change_image_transform</item>
    +</style>
    +
    + +

    Transisi change_image_transform dalam contoh ini didefinisikan sebagai berikut:

    + +
    +<!-- res/transition/change_image_transform.xml -->
    +<!-- (see also Shared Transitions below) -->
    +<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    +  <changeImageTransform/>
    +</transitionSet>
    +
    + +

    Elemen changeImageTransform menunjukkan +kelas {@link android.transition.ChangeImageTransform}. Untuk informasi selengkapnya, lihat referensi +API untuk {@link android.transition.Transition}.

    + +

    Sebaliknya, untuk mengaktifkan transisi konten jendela dalam kode Anda, panggil +metode {@link android.view.Window#requestFeature Window.requestFeature()}:

    + +
    +// 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());
    +
    + +

    Untuk menetapkan transisi dalam kode Anda, panggil metode-metode ini dengan objek {@link +android.transition.Transition}:

    + +
      +
    • {@link android.view.Window#setEnterTransition Window.setEnterTransition()}
    • +
    • {@link android.view.Window#setExitTransition Window.setExitTransition()}
    • +
    • {@link android.view.Window#setSharedElementEnterTransition + Window.setSharedElementEnterTransition()}
    • +
    • {@link android.view.Window#setSharedElementExitTransition + Window.setSharedElementExitTransition()}
    • +
    + +

    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.

    + +

    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).

    + +

    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.

    + +

    Memulai aktivitas dengan menggunakan transisi

    + +

    Jika Anda mengaktifkan transisi dan mengatur transisi keluar untuk aktivitas, transisi itu akan diaktifkan +bila Anda menjalankan aktivitas lain sebagai berikut:

    + +
    +startActivity(intent,
    +              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
    +
    + +

    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 null.

    + +

    Memulai aktivitas dengan satu elemen bersama

    + +

    Untuk membuat animasi transisi layar di antara dua aktivitas yang memiliki satu elemen bersama:

    + +
      +
    1. Aktifkan transisi konten jendela dalam tema Anda.
    2. +
    3. Tetapkan transisi elemen bersama dalam gaya Anda.
    4. +
    5. Definisikan transisi Anda sebagai sumber daya XML.
    6. +
    7. Tetapkan nama umum pada elemen bersama dalam kedua layout dengan + atribut android:transitionName.
    8. +
    9. Gunakan metode {@link android.app.ActivityOptions#makeSceneTransitionAnimation +ActivityOptions.makeSceneTransitionAnimation()}.
    10. +
    + +
    +// 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() {
    +    @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());
    +    }
    +});
    +
    + +

    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.

    + +

    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()}.

    + +

    Memulai aktivitas dengan beberapa elemen bersama

    + +

    Untuk membuat animasi transisi babak antara dua aktivitas yang memiliki lebih dari satu +elemen bersama, definisikan elemen bersama di kedua layout dengan atribut android:transitionName + (atau gunakan metode {@link android.view.View#setTransitionName View.setTransitionName()} +di kedua aktivitas), dan buat sebuah objek {@link android.app.ActivityOptions} sebagai berikut:

    + +
    +ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
    +        Pair.create(view1, "agreedName1"),
    +        Pair.create(view2, "agreedName2"));
    +
    + + +

    Menggunakan Gerakan Melengkung

    + +

    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.

    + +

    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:

    + +
    +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:controlX1="0.4"
    +    android:controlY1="0"
    +    android:controlX2="1"
    +    android:controlY2="1"/>
    +
    + +

    Sistem menyediakan sumber daya XML untuk tiga kurva dasar dalam +spesifikasi desain bahan:

    + +
      +
    • @interpolator/fast_out_linear_in.xml
    • +
    • @interpolator/fast_out_slow_in.xml
    • +
    • @interpolator/linear_out_slow_in.xml
    • +
    + +

    Anda bisa meneruskan objek {@link android.view.animation.PathInterpolator} ke metode {@link +android.animation.Animator#setInterpolator Animator.setInterpolator()}.

    + +

    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:

    + +
    +ObjectAnimator mAnimator;
    +mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
    +...
    +mAnimator.start();
    +
    + + +

    Menganimasikan Perubahan Status Tampilan

    + +

    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:

    + +
    +<!-- animate the translationZ property of a view when pressed -->
    +<selector xmlns:android="http://schemas.android.com/apk/res/android">
    +  <item android:state_pressed="true">
    +    <set>
    +      <objectAnimator android:propertyName="translationZ"
    +        android:duration="@android:integer/config_shortAnimTime"
    +        android:valueTo="2dp"
    +        android:valueType="floatType"/>
    +        <!-- you could have other objectAnimator elements
    +             here for "x" and "y", or other properties -->
    +    </set>
    +  </item>
    +  <item android:state_enabled="true"
    +    android:state_pressed="false"
    +    android:state_focused="true">
    +    <set>
    +      <objectAnimator android:propertyName="translationZ"
    +        android:duration="100"
    +        android:valueTo="0"
    +        android:valueType="floatType"/>
    +    </set>
    +  </item>
    +</selector>
    +
    + +

    Untuk menyertakan animasi status tampilan custom ke tampilan, definisikan animator menggunakan +elemen selector dalam sumber daya file XML sebagaimana dalam contoh ini, dan tetapkan ke +tampilan Anda dengan atribut android:stateListAnimator. 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()}.

    + +

    Bila tema Anda memperluas tema bahan, tombol-tombol akan memiliki animasi Z secara default. Untuk menghindari +perilaku ini di tombol Anda, aturlah atribut android:stateListAnimator ke +@null.

    + +

    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:

    + +
    +<!-- res/drawable/myanimstatedrawable.xml -->
    +<animated-selector
    +    xmlns:android="http://schemas.android.com/apk/res/android">
    +
    +    <!-- provide a different drawable for each state-->
    +    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
    +        android:state_pressed="true"/>
    +    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
    +        android:state_focused="true"/>
    +    <item android:id="@id/default"
    +        android:drawable="@drawable/drawableD"/>
    +
    +    <!-- specify a transition -->
    +    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
    +        <animation-list>
    +            <item android:duration="15" android:drawable="@drawable/dt1"/>
    +            <item android:duration="15" android:drawable="@drawable/dt2"/>
    +            ...
    +        </animation-list>
    +    </transition>
    +    ...
    +</animated-selector>
    +
    + + +

    Menganimasikan Drawable Vektor

    + +

    Drawable Vektor +bisa diubah skalanya tanpa kehilangan definisi. Kelas {@link android.graphics.drawable.AnimatedVectorDrawable} +memungkinkan Anda menganimasikan properti drawable vektor.

    + +

    Anda biasanya mendefinisikan drawable vektor yang dianimasikan dalam tiga file XML:

    + +
      +
    • Drawable vektor dengan elemen <vector> dalam +res/drawable/
    • +
    • Drawable vektor animasi dengan elemen <animated-vector> dalam +res/drawable/
    • +
    • Satu atau beberapa animator objek dengan elemen <objectAnimator> dalam +res/anim/
    • +
    + +

    Drawable vektor yang dianimasikan bisa menganimasikan atribut elemen <group> dan +<path>. Elemen <group> mendefinisikan satu set +path atau subgrup, dan elemen <path> mendefinisikan path yang harus digambar.

    + +

    Bila Anda mendefinisikan drawable vektor yang ingin dianimasikan, gunakan atribut android:name +untuk menetapkan nama unik ke grup dan path, sehingga Anda bisa merujuknya dari +definisi animator Anda. Misalnya:

    + +
    +<!-- res/drawable/vectordrawable.xml -->
    +<vector xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:height="64dp"
    +    android:width="64dp"
    +    android:viewportHeight="600"
    +    android:viewportWidth="600">
    +    <group
    +        android:name="rotationGroup"
    +        android:pivotX="300.0"
    +        android:pivotY="300.0"
    +        android:rotation="45.0" >
    +        <path
    +            android:name="v"
    +            android:fillColor="#000000"
    +            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    +    </group>
    +</vector>
    +
    + +

    Definisi drawable vektor yang dianimasikan merujuk pada grup dan path dalam drawable vektor +berdasarkan namanya:

    + +
    +<!-- res/drawable/animvectordrawable.xml -->
    +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    +  android:drawable="@drawable/vectordrawable" >
    +    <target
    +        android:name="rotationGroup"
    +        android:animation="@anim/rotation" />
    +    <target
    +        android:name="v"
    +        android:animation="@anim/path_morph" />
    +</animated-vector>
    +
    + +

    Definisi animasi menyatakan objek {@link android.animation.ObjectAnimator} atau {@link +android.animation.AnimatorSet}. Animator pertama dalam contoh ini memutar +grup target sebanyak 360 derajat:

    + +
    +<!-- res/anim/rotation.xml -->
    +<objectAnimator
    +    android:duration="6000"
    +    android:propertyName="rotation"
    +    android:valueFrom="0"
    +    android:valueTo="360" />
    +
    + +

    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.

    + +
    +<!-- res/anim/path_morph.xml -->
    +<set xmlns:android="http://schemas.android.com/apk/res/android">
    +    <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" />
    +</set>
    +
    + +

    Untuk informasi selengkapnya, lihat referensi API bagi {@link +android.graphics.drawable.AnimatedVectorDrawable}.

    diff --git a/docs/html-intl/intl/id/training/material/compatibility.jd b/docs/html-intl/intl/id/training/material/compatibility.jd new file mode 100644 index 0000000000000000000000000000000000000000..ef444c359b57d7a68d8574f0bb7f009250e464f2 --- /dev/null +++ b/docs/html-intl/intl/id/training/material/compatibility.jd @@ -0,0 +1,168 @@ +page.title=Mempertahankan Kompatibilitas + +@jd:body + + + + +

    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.

    + + +

    Mendefinisikan Gaya Alternatif

    + +

    Anda bisa mengonfigurasi aplikasi untuk menggunakan tema bahan pada perangkat yang mendukungnya dan mengembalikan +ke tema lama pada perangkat yang menjalankan versi Android terdahulu:

    + +
      +
    1. Definisikan tema yang mewarisi tema lama (seperti Holo) di + res/values/styles.xml.
    2. +
    3. Definisikan tema bernama sama yang mewarisi tema bahan di + res/values-v21/styles.xml.
    4. +
    5. Atur tema ini sebagai tema aplikasi Anda dalam file manifes.
    6. +
    + +

    Catatan: +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. +

    + + +

    Menyediakan Layout Alternatif

    + +

    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.

    + +

    Buatlah file layout untuk Android 5.0 (API level 21) dalam res/layout-v21/ dan +file layout alternatif untuk versi Android terdahulu dalam res/layout/. +Misalnya, res/layout/my_activity.xml adalah layout alternatif untuk +res/layout-v21/my_activity.xml.

    + +

    Untuk menghindari duplikasi kode, definisikan gaya dalam res/values/, modifikasi +gaya di res/values-v21/ untuk API baru, dan gunakan pewarisan gaya, dengan mendefinisikan +gaya dasar di res/values/ dan mewarisi gaya di res/values-v21/.

    + + +

    Menggunakan Support Library

    + +

    v7 Support Library +r21 ke atas menyertakan fitur desain bahan berikut:

    + + + +

    Widget sistem

    + +

    Tema-tema Theme.AppCompat menyediakan gaya desain bahan untuk widget ini:

    + +
      +
    • {@link android.widget.EditText}
    • +
    • {@link android.widget.Spinner}
    • +
    • {@link android.widget.CheckBox}
    • +
    • {@link android.widget.RadioButton}
    • +
    • {@link android.support.v7.widget.SwitchCompat}
    • +
    • {@link android.widget.CheckedTextView}
    • +
    + +

    Palet Warna

    + +

    Untuk memperoleh gaya desain bahan dan menyesuaikan palet warna dengan Android v7 Support +Library, terapkan salah satu tema Theme.AppCompat:

    + +
    +<!-- extend one of the Theme.AppCompat themes -->
    +<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
    +    <!-- customize the color palette -->
    +    <item name="colorPrimary">@color/material_blue_500</item>
    +    <item name="colorPrimaryDark">@color/material_blue_700</item>
    +    <item name="colorAccent">@color/material_green_A200</item>
    +</style>
    +
    + +

    Daftar dan Kartu

    + +

    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:

    +
      +
    • {@link android.support.v7.widget.CardView} memundurkan ke implementasi bayangan terprogram + dengan menggunakan pengisi tambahan.
    • +
    • {@link android.support.v7.widget.CardView} tidak memangkas tampilan anaknya yang berpotongan + dengan sudut melengkung.
    • +
    + + +

    Dependensi

    + +

    Untuk menggunakan fitur-fitur ini di versi Android sebelum 5.0 (API level 21), sertakan +Android v7 Support Library dalam proyek Anda sebagai dependensi Gradle:

    + +
    +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.+'
    +}
    +
    + + +

    Memeriksa Versi Sistem

    + +

    Fitur berikut hanya tersedia di Android 5.0 (API level 21) ke atas:

    + +
      +
    • Transisi aktivitas
    • +
    • Umpan balik sentuh
    • +
    • Animasi membuka
    • +
    • Animasi berbasis path
    • +
    • Drawable vektor
    • +
    • Pewarnaan drawable
    • +
    + +

    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:

    + +
    +// 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
    +}
    +
    + +

    Catatan: Untuk menetapkan versi Android yang didukung aplikasi Anda, +gunakan atribut android:minSdkVersion dan android:targetSdkVersion +dalam file manifes. Untuk menggunakan fitur desain bahan di Android 5.0, atur +atribut android:targetSdkVersion ke 21. Untuk informasi selengkapnya, lihat +panduan API +<uses-sdk>.

    diff --git a/docs/html-intl/intl/id/training/material/drawables.jd b/docs/html-intl/intl/id/training/material/drawables.jd new file mode 100644 index 0000000000000000000000000000000000000000..493abd46bebdfaf0c9bf56e98d74883149e26cbe --- /dev/null +++ b/docs/html-intl/intl/id/training/material/drawables.jd @@ -0,0 +1,126 @@ +page.title=Bekerja dengan Drawable + +@jd:body + + + +

    Kemampuan berikut untuk drawable membantu Anda mengimplementasikan desain bahan dalam aplikasi Anda:

    + +
      +
    • Pewarnaan drawable
    • +
    • Ekstraksi warna mencolok
    • +
    • Drawable vektor
    • +
    + +

    Pelajaran ini menampilkan cara menggunakan fitur-fitur ini dalam aplikasi Anda.

    + + +

    Mewarnai Sumber Daya Drawable

    + +

    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, ?android:attr/colorPrimary). Biasanya, Anda membuat aset ini +hanya sekali dan mewarnainya secara otomatis agar cocok dengan tema Anda.

    + +

    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 android:tint dan +android:tintMode.

    + + +

    Mengekstrak Warna Mencolok dari Gambar

    + +

    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:

    + +
      +
    • Menyala
    • +
    • Menyala pekat
    • +
    • Menyala pucat
    • +
    • Pudar
    • +
    • Pudar pekat
    • +
    • Pudar pucat
    • +
    + +

    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.

    + +

    Anda bisa mengambil warna mencolok dari gambar dengan metode getter di kelas +Palette, misalnya Palette.getVibrantColor.

    + +

    Untuk menggunakan kelas {@link android.support.v7.graphics.Palette} dalam proyek Anda, tambahkan +dependensi Gradle berikut ke +modul aplikasi Anda:

    + +
    +dependencies {
    +    ...
    +    compile 'com.android.support:palette-v7:21.0.0'
    +}
    +
    + +

    Untuk informasi selengkapnya, lihat referensi API untuk kelas {@link android.support.v7.graphics.Palette}. +

    + + +

    Membuat Drawable Vektor

    + + + +
    +

    Video

    +

    Grafis Vektor Android

    +
    +
    + +

    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 <vector>.

    + +

    Contoh berikut mendefinisikan gambar vektor berbentuk hati:

    + +
    +<!-- res/drawable/heart.xml -->
    +<vector xmlns:android="http://schemas.android.com/apk/res/android"
    +    <!-- intrinsic size of the drawable -->
    +    android:height="256dp"
    +    android:width="256dp"
    +    <!-- size of the virtual canvas -->
    +    android:viewportWidth="32"
    +    android:viewportHeight="32">
    +
    +  <!-- draw a path -->
    +  <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" />
    +</vector>
    +
    + +

    Gambar vektor direpresentasikan di Android sebagai objek {@link android.graphics.drawable.VectorDrawable}. + Untuk informasi selengkapnya tentang sintaks pathData, lihat Referensi Path SVG. Untuk informasi selengkapnya +tentang menganimasikan properti drawable vektor, lihat +Menganimasikan Drawable Vektor.

    diff --git a/docs/html-intl/intl/id/training/material/get-started.jd b/docs/html-intl/intl/id/training/material/get-started.jd new file mode 100644 index 0000000000000000000000000000000000000000..1a551a9e36a9dc1857d4b1528091cfc651afd36c --- /dev/null +++ b/docs/html-intl/intl/id/training/material/get-started.jd @@ -0,0 +1,171 @@ +page.title=Memulai + +@jd:body + + + + +

    Untuk membuat aplikasi dengan desain bahan:

    + +
      +
    1. + Tinjaulah spesifikasi desain bahan.
    2. +
    3. + Terapkan tema bahan ke aplikasi Anda.
    4. +
    5. + Buat layout agar mengikuti panduan desain bahan.
    6. +
    7. + Tetapkan ketinggian tampilan Anda untuk menghasilkan bayangan.
    8. +
    9. + Gunakan widget sistem untuk daftar dan kartu.
    10. +
    11. + Sesuaikan animasi di aplikasi Anda.
    12. +
    + +

    Mempertahankan kompatibilitas mundur

    + +

    Anda bisa menambahkan banyak fitur desain bahan ke aplikasi sekaligus mempertahankan kompatibilitas dengan +versi Android sebelum 5.0. Untuk informasi selengkapnya, lihat +Mempertahankan Kompatibilitas.

    + +

    Memperbarui aplikasi dengan desain bahan

    + +

    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.

    + +

    Membuat aplikasi baru dengan desain bahan

    + +

    Jika Anda sedang membuat aplikasi baru dengan fitur desain bahan, panduan desain bahan 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.

    + + +

    Menerapkan Tema Bahan

    + +

    Untuk menerapkan tema bahan dalam aplikasi Anda, tetapkan gaya yang mewarisi +android:Theme.Material:

    + +
    +<!-- res/values/styles.xml -->
    +<resources>
    +  <!-- your theme inherits from the material theme -->
    +  <style name="AppTheme" parent="android:Theme.Material">
    +    <!-- theme customizations -->
    +  </style>
    +</resources>
    +
    + +

    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 +Menggunakan Tema Bahan.

    + + +

    Mendesain Layout Anda

    + +

    Selain menerapkan dan menyesuaikan tema bahan, layout Anda harus mematuhi +panduan desain bahan. Bila Anda mendesain +layout, berikan perhatian khusus pada hal-hal berikut:

    + +
      +
    • Petak patokan
    • +
    • Garis utama
    • +
    • Pengaturan Jarak
    • +
    • Ukuran target sentuh
    • +
    • Struktur layout
    • +
    + + +

    Menetapkan Ketinggian di Tampilan Anda

    + +

    Tampilan bisa menghasilkan bayangan, dan nilai ketinggian tampilan +menentukan ukuran bayangan dan urutan penggambarannya. Untuk mengatur ketinggian tampilan, gunakan +atribut android:elevation dalam layout:

    + +
    +<TextView
    +    android:id="@+id/my_textview"
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
    +    android:text="@string/next"
    +    android:background="@color/white"
    +    android:elevation="5dp" />
    +
    + +

    Properti translationZ baru memungkinkan Anda membuat animasi yang mencerminkan +perubahan sementara pada ketinggian tampilan. Perubahan ketinggian bisa berguna saat +merespons +gerakan sentuh.

    + +

    Untuk detail selengkapnya, lihat Mendefinisikan +Bayangan dan Memangkas Tampilan.

    + + +

    Membuat Daftar dan Kartu

    + +

    {@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:

    + +
    +<android.support.v7.widget.CardView
    +    android:id="@+id/card_view"
    +    android:layout_width="200dp"
    +    android:layout_height="200dp"
    +    card_view:cardCornerRadius="3dp">
    +    ...
    +</android.support.v7.widget.CardView>
    +
    + +

    Untuk informasi selengkapnya, lihat Membuat Daftar +dan Kartu.

    + + +

    Menyesuaikan Animasi Anda

    + +

    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:

    + +
    +public class MyActivity extends Activity {
    +
    +    @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());
    +    }
    +}
    +
    + +

    Bila Anda memulai aktivitas lain dari aktivitas ini, transisi keluar akan diaktifkan.

    + +

    Untuk mengetahui selengkapnya tentang API animasi yang baru, lihat Mendefinisikan Animasi Custom.

    diff --git a/docs/html-intl/intl/id/training/material/index.jd b/docs/html-intl/intl/id/training/material/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..53697d2ea6669c1765e2b9e8a4ac5caa0b7b6247 --- /dev/null +++ b/docs/html-intl/intl/id/training/material/index.jd @@ -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 + +
    +
    +

    Dependensi dan Prasyarat

    +
      +
    • Android 5.0 (API Level 21)
    • +
    +
    +
    + +

    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 +spesifikasi desain bahan + dan gunakan komponen serta fungsionalitas baru yang tersedia di Android 5.0 +(API level 21).

    + +

    Kelas ini menampilkan kepada Anda cara membuat aplikasi desain bahan dengan elemen-elemen berikut:

    + +
      +
    • Tema bahan
    • +
    • Widget untuk kartu dan daftar
    • +
    • Bayangan custom dan pemangkasan tampilan
    • +
    • Drawable vektor
    • +
    • Animasi custom
    • +
    + +

    Kelas ini juga mengajarkan cara mempertahankan kompatibilitas dengan versi Android sebelum +5.0 (API level 21) bila Anda menggunakan fitur desain bahan dalam aplikasi.

    + +

    Pelajaran

    + +
    +
    Memulai
    +
    Pelajari cara memperbarui aplikasi Anda dengan fitur desain bahan.
    + +
    Menggunakan Tema Bahan
    +
    Pelajari cara menerapkan gaya desain bahan pada aplikasi Anda.
    + +
    Membuat Daftar dan Kartu
    +
    Pelajari cara membuat daftar dan kartu dengan tampilan dan cara kerja yang konsisten menggunakan widget sistem.
    + +
    Mendefinisikan Bayangan dan Memangkas Tampilan
    +
    Pelajari cara mengatur elevasi tampilan Anda untuk membuat bayangan custom dan cara memangkas tampilan.
    + +
    Bekerja dengan Drawable
    +
    Pelajari cara membuat drawable vektor dan cara mewarnai sumber daya drawable.
    + +
    Mendefinisikan Animasi Custom
    +
    Pelajari cara membuat animasi custom untuk tampilan dan transisi aktivitas dengan elemen bersama.
    + +
    Mempertahankan Kompatibilitas
    +
    Pelajari cara mempertahankan kompatibilitas dengan versi platform sebelum Android 5.0.
    +
    diff --git a/docs/html-intl/intl/id/training/material/lists-cards.jd b/docs/html-intl/intl/id/training/material/lists-cards.jd new file mode 100644 index 0000000000000000000000000000000000000000..46dd19afc4e1aea8c415e49077322b66ff231680 --- /dev/null +++ b/docs/html-intl/intl/id/training/material/lists-cards.jd @@ -0,0 +1,266 @@ +page.title=Membuat Daftar dan Kartu + +@jd:body + +
    +
    +

    Pelajaran ini mengajarkan Anda cara

    +
      +
    1. Membuat Daftar
    2. +
    3. Membuat Kartu
    4. +
    5. Menambahkan Dependensi
    6. +
    +

    Anda juga harus membaca

    + +
    +
    + + +

    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}. +

    + + +

    Membuat Daftar

    + +

    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.

    + +

    Kelas {@link android.support.v7.widget.RecyclerView} menyederhanakan penampilan dan penanganan +set data yang besar dengan menyediakan:

    + +
      +
    • Pengelola layout untuk memosisikan item
    • +
    • Animasi default untuk operasi item umum, misalnya penghapusan atau penambahan item
    • +
    + +

    Anda juga memiliki keluwesan untuk mendefinisikan pengelola layout custom dan animasi untuk widget {@link +android.support.v7.widget.RecyclerView}.

    + + +

    +Gambar 1. Widget RecyclerView. +

    + +

    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 contoh-contoh di bawah.

    + +
    + +

    +Gambar 2 - Daftar berisi RecyclerView. +

    +
    + +

    Pengelola layout 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 mendaur ulang) 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.

    + +

    {@link android.support.v7.widget.RecyclerView} menyediakan semua pengelola layout bawaan ini:

    + +
      +
    • {@link android.support.v7.widget.LinearLayoutManager} menampilkan item dalam +daftar gulir vertikal atau horizontal.
    • +
    • {@link android.support.v7.widget.GridLayoutManager} menampilkan item dalam petak.
    • +
    • {@link android.support.v7.widget.StaggeredGridLayoutManager} menampilkan item dalam petak zigzag.
    • +
    + +

    Untuk membuat pengelola layout custom, perluas kelas {@link +android.support.v7.widget.RecyclerView.LayoutManager RecyclerView.LayoutManager}.

    + +

    Animasi

    + +

    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()}. +

    + +

    Contoh

    + +

    Contoh kode berikut memperagakan cara menambahkan +{@link android.support.v7.widget.RecyclerView} ke layout:

    + +
    +<!-- A RecyclerView with some commonly used attributes -->
    +<android.support.v7.widget.RecyclerView
    +    android:id="@+id/my_recycler_view"
    +    android:scrollbars="vertical"
    +    android:layout_width="match_parent"
    +    android:layout_height="match_parent"/>
    +
    + +

    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:

    + +
    +public class MyActivity extends Activity {
    +    private RecyclerView mRecyclerView;
    +    private RecyclerView.Adapter mAdapter;
    +    private RecyclerView.LayoutManager mLayoutManager;
    +
    +    @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);
    +    }
    +    ...
    +}
    +
    + +

    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}:

    + +
    +public class MyAdapter extends RecyclerView.Adapter<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)
    +    @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)
    +    @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)
    +    @Override
    +    public int getItemCount() {
    +        return mDataset.length;
    +    }
    +}
    +
    + + +
    + +

    +Gambar 3. Contoh kartu. +

    +
    + +

    Membuat Kartu

    + +

    {@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.

    + +

    Untuk membuat kartu dengan bayangan, gunakan atribut card_view:cardElevation. +{@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 Mempertahankan +Kompatibilitas.

    + +

    Gunakan properti-properti ini untuk menyesuaikan penampilan +widget {@link android.support.v7.widget.CardView}:

    + +
      +
    • Untuk mengatur radius sudut pada layout Anda, gunakan atribut card_view:cardCornerRadius. +
    • +
    • Untuk mengatur radius sudut dalam kode Anda, gunakan metode CardView.setRadius.
    • +
    • Untuk mengatur warna latar belakang kartu, gunakan atribut card_view:cardBackgroundColor. +
    • +
    + +

    Contoh kode berikut menampilkan cara menyertakan widget {@link android.support.v7.widget.CardView} +dalam layout:

    + +
    +<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"
    +    ... >
    +    <!-- A CardView that contains a TextView -->
    +    <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">
    +
    +        <TextView
    +            android:id="@+id/info_text"
    +            android:layout_width="match_parent"
    +            android:layout_height="match_parent" />
    +    </android.support.v7.widget.CardView>
    +</LinearLayout>
    +
    + +

    Untuk informasi selengkapnya, lihat referensi API untuk {@link android.support.v7.widget.CardView}.

    + + +

    Menambahkan Dependensi

    + +

    Widget {@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView} +adalah bagian dari v7 Support +Library. Untuk menggunakan widget dalam proyek Anda, tambahkan +dependensi Gradle ini ke +modul aplikasi Anda:

    + +
    +dependencies {
    +    ...
    +    compile 'com.android.support:cardview-v7:21.0.+'
    +    compile 'com.android.support:recyclerview-v7:21.0.+'
    +}
    +
    diff --git a/docs/html-intl/intl/id/training/material/shadows-clipping.jd b/docs/html-intl/intl/id/training/material/shadows-clipping.jd new file mode 100644 index 0000000000000000000000000000000000000000..5431926721593e203e420d2b3cb97a55f175ad8b --- /dev/null +++ b/docs/html-intl/intl/id/training/material/shadows-clipping.jd @@ -0,0 +1,133 @@ +page.title=Mendefinisikan Bayangan dan Memangkas Tampilan + +@jd:body + + + +

    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.

    + +

    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.

    + +

    Bayangan digambar oleh induk tampilan yang dinaikkan, sehingga terkena pemangkasan standar tampilan, +yang dipangkas oleh induk secara default.

    + +

    Elevasi juga berguna untuk membuat animasi tempat memunculkan widget untuk sementara di atas +bidang tampilan saat melakukan beberapa tindakan.

    + +

    Untuk informasi selengkapnya tentang elevasi dalam desain bahan, lihat +Objek +di ruang 3D.

    + + +

    Menetapkan Elevasi pada Tampilan Anda

    + +

    Nilai Z untuk tampilan memiliki dua komponen: + +

      +
    • Elevasi: Komponen statis.
    • +
    • Transformasi: Komponen dinamis yang digunakan untuk animasi.
    • +
    + +

    Z = elevation + translationZ

    + + +

    Gambar 1 - Bayangan untuk berbagai elevasi tampilan.

    + +

    Untuk mengatur elevasi tampilan dalam definisi layout, gunakan atribut android:elevation. + Untuk mengatur elevasi tampilan dalam kode aktivitas, gunakan +metode {@link android.view.View#setElevation View.setElevation()}.

    + +

    Untuk mengatur transformasi tampilan, gunakan metode {@link android.view.View#setTranslationZ +View.setTranslationZ()}.

    + +

    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 Animasi Properti. +

    + +

    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 +Menganimasikan Perubahan Status Tampilan.

    + +

    Nilai Z diukur dengan satuan dp (density-independent pixel).

    + + +

    Menyesuaikan Bayangan dan Garis Luar Tampilan

    + +

    Batas-batas drawable latar belakang tampilan menentukan bentuk default bayangannya. +Garis luar menyatakan bentuk luar objek grafis dan mendefinisikan +bidang riak untuk umpan balik sentuh.

    + +

    Perhatikan tampilan ini, yang didefinisikan dengan drawable latar belakang:

    + +
    +<TextView
    +    android:id="@+id/myview"
    +    ...
    +    android:elevation="2dp"
    +    android:background="@drawable/myrect" />
    +
    + +

    Drawable latar belakang didefinisikan sebagai persegi panjang dengan sudut membulat:

    + +
    +<!-- res/drawable/myrect.xml -->
    +<shape xmlns:android="http://schemas.android.com/apk/res/android"
    +       android:shape="rectangle">
    +    <solid android:color="#42000000" />
    +    <corners android:radius="5dp" />
    +</shape>
    +
    + +

    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.

    + +

    Untuk mendefinisikan garis luar custom suatu tampilan dalam kode Anda:

    + +

      +
    1. Perluas kelas {@link android.view.ViewOutlineProvider}.
    2. +
    3. Kesampingkan metode {@link android.view.ViewOutlineProvider#getOutline getOutline()}.
    4. +
    5. Tetapkan penyedia garis luar baru untuk tampilan Anda dengan metode {@link +android.view.View#setOutlineProvider View.setOutlineProvider()}.
    6. +
    + +

    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 null.

    + + +

    Memangkas Tampilan

    + +

    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 android:clipToOutline. 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()}.

    + +

    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()}. +

    + +

    Memangkas tampilan adalah operasi yang mahal; jadi, jangan animasikan bentuk yang Anda gunakan +untuk memangkas tampilan. Untuk memperoleh efek ini, gunakan animasi Reveal Effect.

    diff --git a/docs/html-intl/intl/id/training/material/theme.jd b/docs/html-intl/intl/id/training/material/theme.jd new file mode 100644 index 0000000000000000000000000000000000000000..5acdcd2d0692c5941dfdacff8e874fb17e1395a1 --- /dev/null +++ b/docs/html-intl/intl/id/training/material/theme.jd @@ -0,0 +1,131 @@ +page.title=Menggunakan Tema Bahan + +@jd:body + +
    +
    +

    Pelajaran ini mengajarkan Anda cara

    +
      +
    1. Menyesuaikan Palet Warna
    2. +
    3. Menyesuaikan Baris Status
    4. +
    5. Tampilan Setiap Tema
    6. +
    +

    Anda juga harus membaca

    + +
    +
    + + +

    Tema bahan yang baru menyediakan:

    + +
      +
    • Widget sistem yang memungkinkan Anda mengatur palet warnanya
    • +
    • Animasi umpan balik sentuh untuk widget sistem
    • +
    • Animasi transisi aktivitas
    • +
    + +

    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 Gambar 3.

    + +

    Widget sistem memiliki desain baru dan animasi umpan balik sentuh. Anda bisa menyesuaikan +palet warna, animasi umpan balik sentuh, dan transisi aktivitas untuk aplikasi.

    + +

    Tema bahan didefinisikan sebagai:

    + +
      +
    • @android:style/Theme.Material (versi gelap)
    • +
    • @android:style/Theme.Material.Light (versi terang)
    • +
    • @android:style/Theme.Material.Light.DarkActionBar
    • +
    + +

    Untuk daftar gaya bahan yang bisa Anda gunakan, lihat referensi API untuk +{@link android.R.style R.style}.

    + + +
    +
    + +
    +

    Gambar 1. Tema bahan gelap

    +
    +
    +
    + +
    +

    Gambar 2. Tema bahan terang

    +
    +
    +
    +
    + +

    +Catatan: Tema bahan hanya tersedia di Android 5.0 (API level 21) +ke atas. v7 Support Library +menyediakan tema dengan gaya desain bahan untuk beberapa widget dan dukungan untuk menyesuaikan +palet warna. Untuk informasi selengkapnya, lihat +Mempertahankan Kompatibilitas. +

    + + +

    Menyesuaikan Palet Warna

    + +

    Untuk menyesuaikan warna dasar tema agar cocok dengan merek Anda, definisikan +warna custom menggunakan atribut tema saat Anda mewariskan dari tema bahan:

    + +
    +<resources>
    +  <!-- inherit from the material theme -->
    +  <style name="AppTheme" parent="android:Theme.Material">
    +    <!-- Main theme colors -->
    +    <!--   your app branding color for the app bar -->
    +    <item name="android:colorPrimary">@color/primary</item>
    +    <!--   darker variant for the status bar and contextual app bars -->
    +    <item name="android:colorPrimaryDark">@color/primary_dark</item>
    +    <!--   theme UI controls like checkboxes and text fields -->
    +    <item name="android:colorAccent">@color/accent</item>
    +  </style>
    +</resources>
    +
    + +
    + +

    +Gambar 3. Menyesuaikan tema bahan.

    +
    + + +

    Menyesuaikan Baris Status

    + +

    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 android:statusBarColor bila +Anda memperluas tema bahan. Secara default, android:statusBarColor mewarisi +nilai android:colorPrimaryDark.

    + +

    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 android:statusBarColor ke +@android:color/transparent dan sesuaikan flag jendela seperti yang diperlukan. Anda juga bisa +menggunakan metode {@link android.view.Window#setStatusBarColor Window.setStatusBarColor()} untuk +animasi atau pemudaran.

    + +

    +Catatan: 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. +

    + +

    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.

    + + +

    Tampilan Setiap Tema

    + +

    Elemen dalam definisi layout XML bisa menetapkan atribut android:theme, +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.

    diff --git a/docs/html-intl/intl/in/preview/features/picture-in-picture.jd b/docs/html-intl/intl/id/training/tv/playback/picture-in-picture.jd similarity index 98% rename from docs/html-intl/intl/in/preview/features/picture-in-picture.jd rename to docs/html-intl/intl/id/training/tv/playback/picture-in-picture.jd index 5df3e5d78859758408389383c71182717b9b5522..41af6de9772386d4f2e269c816c2c62ee01c27ec 100644 --- a/docs/html-intl/intl/in/preview/features/picture-in-picture.jd +++ b/docs/html-intl/intl/id/training/tv/playback/picture-in-picture.jd @@ -4,8 +4,8 @@ page.tags=androidn @jd:body -
    -
    +
    +

    Dalam dokumen ini

      @@ -59,7 +59,7 @@ PIP, dengan menekan dan menahan tombol Beranda pada remote. Jika video lain mulai diputar pada layar utama, jendela PIP secara otomatis ditutup. Pengguna juga bisa menutup jendela PIP melalui Recents.

      - +

      Gambar 1. Video Gambar-dalam-gambar terlihat di sudut layar selagi pengguna menjelajahi materi pada layar utama.

      @@ -116,7 +116,7 @@ public void onActionClicked(Action action) {

      Menambahkan tombol PIP ke baris kontrol media Anda akan memungkinkan pengguna dengan mudah beralih ke mode PIP selagi mengontrol pemutaran video.

      - +

      Gambar 1. Tombol gambar-dalam-gambar pada baris kontrol media.

      diff --git a/docs/html-intl/intl/in/preview/features/tv-recording-api.jd b/docs/html-intl/intl/id/training/tv/tif/content-recording.jd similarity index 99% rename from docs/html-intl/intl/in/preview/features/tv-recording-api.jd rename to docs/html-intl/intl/id/training/tv/tif/content-recording.jd index afedf8f31b214d1ec1e4601c931b8a8c48ba0013..3389dbf84cbfdbe2d4b15c7fddea4b20b6cb1b4a 100644 --- a/docs/html-intl/intl/in/preview/features/tv-recording-api.jd +++ b/docs/html-intl/intl/id/training/tv/tif/content-recording.jd @@ -5,8 +5,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
      -
      +
      +

      Dalam dokumen ini

      1. Menunjukkan Dukungan untuk Perekaman
      2. diff --git a/docs/html-intl/intl/in/about/versions/marshmallow/android-6.0-testing.jd b/docs/html-intl/intl/in/about/versions/marshmallow/android-6.0-testing.jd new file mode 100644 index 0000000000000000000000000000000000000000..94bc74cf3ca3146cb773e5fd529889eea227c5cd --- /dev/null +++ b/docs/html-intl/intl/in/about/versions/marshmallow/android-6.0-testing.jd @@ -0,0 +1,190 @@ +page.title=Panduan Pengujian +page.image=images/cards/card-n-guide_2x.png +meta.tags="preview", "testing" +page.tags="preview", "developer preview" + +@jd:body + + + +

        + Android N memberi Anda kesempatan untuk memastikan aplikasi bekerja pada + platform versi berikutnya. Pratinjau ini berisi beberapa API dan perubahan perilaku yang bisa + memengaruhi aplikasi Anda, sebagaimana dijelaskan dalam Ringkasan + API dan Perubahan Perilaku. Dalam menguji + aplikasi dengan pratinjau, ada beberapa perubahan sistem spesifik yang harus Anda fokuskan untuk + memastikan pengguna mendapatkan pengalaman yang bagus. +

        + +

        + Panduan ini menjelaskan apa dan bagaimana menguji fitur pratinjau dengan aplikasi Anda. Anda harus + mengutamakan pengujian fitur pratinjau spesifik ini, dikarenakan pengaruhnya yang besar pada + perilaku aplikasi Anda: +

        + + + +

        + Untuk informasi selengkapnya tentang cara menyiapkan perangkat atau perangkat maya dengan citra sistem pratinjau + untuk pengujian, lihat Menyiapkan +Android N SDK. +

        + + +

        Izin Pengujian

        + +

        + Model Izin yang baru + mengubah cara alokasi izin untuk aplikasi Anda oleh pengguna. Sebagai ganti memberi semua + izin selama prosedur pemasangan, aplikasi Anda harus meminta izin kepada pengguna secara individual + pada waktu proses. Bagi pengguna, perilaku ini memberi kontrol yang lebih detail atas setiap aktivitas aplikasi, dan + juga konteks yang lebih untuk memahami sebab aplikasi meminta izin tertentu. Pengguna + bisa memberi atau mencabut izin yang diberikan pada suatu aplikasi secara individual kapan saja. Fitur + pratinjau ini kemungkinan besar memengaruhi perilaku aplikasi Anda dan mungkin menghambat fungsi beberapa + fitur aplikasi Anda, atau mengurangi kualitas kerjanya. +

        + +

        + Perubahan ini memengaruhi semua aplikasi yang berjalan di platform baru, bahkan aplikasi yang tidak menargetkan versi + platform baru. Platform ini memberikan perilaku kompatibilitas terbatas untuk aplikasi lawas, namun Anda + harus mulai merencanakan migrasi aplikasi ke model izin baru sekarang juga, dengan tujuan + mempublikasikan versi terbaru aplikasi Anda saat peluncuran platform secara resmi. +

        + + +

        Tip pengujian

        + +

        + Gunakan tip berikut untuk membantu Anda merencanakan dan menjalankan pengujian aplikasi dengan + perilaku izin yang baru. +

        + +
          +
        • Identifikasi izin aplikasi Anda saat ini dan jalur kode terkait.
        • +
        • Uji alur pengguna pada semua layanan dan data yang dilindungi izin.
        • +
        • Uji dengan berbagai kombinasi izin yang diberikan/dicabut.
        • +
        • Gunakan alat bantu {@code adb} untuk mengelola izin dari baris perintah: +
            +
          • Cantumkan daftar izin dan status berdasarkan kelompok: +
            adb shell pm list permissions -d -g
            +
          • +
          • Beri atau cabut satu atau beberapa izin menggunakan sintaks berikut:
            +
            adb shell pm [grant|revoke] <permission.name> ...
            +
          • +
          +
        • +
        • Analisis aplikasi Anda untuk layanan yang menggunakan izin.
        • +
        + +

        Strategi pengujian

        + +

        + Perubahan izin memengaruhi struktur dan desain aplikasi Anda, begitu juga + pengalaman pengguna dan alur yang Anda sediakan untuk pengguna. Anda harus menilai penggunaan izin + aplikasi saat ini dan mulai merencanakan alur baru yang ingin ditawarkan. Rilis platform + resmi menyediakan perilaku kompatibilitas, namun Anda harus merencanakan pembaruan aplikasi dan tidak + bergantung pada perilaku ini. +

        + +

        + Identifikasi izin yang sebenarnya diperlukan dan digunakan aplikasi Anda, kemudian temukan berbagai + jalur kode yang menggunakan layanan yang dilindungi izin. Anda bisa melakukan ini melalui kombinasi + pengujian pada platform baru dan analisis kode. Dalam pengujian, Anda harus fokus pada pemilihan + izin waktu proses dengan mengubah {@code targetSdkVersion} aplikasi ke versi pratinjau. Untuk + informasi selengkapnya, lihat Menyiapkan +Android N SDK. +

        + +

        + Uji dengan berbagai kombinasi izin yang dicabut dan ditambahkan, untuk menyoroti alur pengguna yang + bergantung pada izin. Jika dependensi tidak jelas atau logis, Anda harus mempertimbangkan +optimalisasi atau kompartementalisasi alur tersebut untuk mengeliminasi dependensi atau menjelaskan alasan + diperlukannya izin. +

        + +

        + Untuk informasi selengkapnya tentang perilaku izin waktu proses, pengujian, dan praktik terbaik, lihat + halaman pratinjau Izin + pengembang. +

        + + +

        Menguji Istirahatkan dan Aplikasi Siaga

        + +

        + Fitur penghematan daya Istirahatkan dan Aplikasi Siaga membatasi jumlah pemrosesan latar belakang yang + bisa dikerjakan aplikasi Anda saat perangkat dalam keadaan diam atau saat aplikasi Anda sedang tidak fokus. Pembatasan + yang dapat diberlakukan oleh sistem pada aplikasi termasuk akses jaringan terbatas atau tidak ada, + tugas latar belakang yang ditangguhkan, Pemberitahuan yang ditangguhkan, permintaan membangunkan yang diabaikan, serta alarm. Untuk memastikan + aplikasi Anda berperilaku dengan benar pada optimalisasi penghematan daya ini, Anda harus menguji aplikasi dengan + menyimulasikan keadaan baterai yang sedang tinggal sedikit ini. +

        + +

        Menguji aplikasi Anda dengan Istirahatkan

        + +

        Untuk menguji Istirahatkan dengan aplikasi Anda:

        + +
          +
        1. Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.
        2. +
        3. Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.
        4. +
        5. Jalankan aplikasi Anda dan biarkan aktif.
        6. +
        7. Simulasikan perangkat yang sedang masuk ke dalam mode Istirahatkan dengan menjalankan perintah berikut: + +
          +$ adb shell dumpsys battery unplug
          +$ adb shell dumpsys deviceidle step
          +$ adb shell dumpsys deviceidle -h
          +
          + +
        8. +
        9. Amati perilaku aplikasi Anda saat perangkat diaktifkan kembali. Pastikan aplikasi + pulih dengan baik saat perangkat keluar dari Istirahatkan.
        10. +
        + + +

        Menguji aplikasi dengan Aplikasi Siaga

        + +

        Untuk menguji mode Aplikasi Siaga dengan aplikasi Anda:

        + +
          +
        1. Konfigurasikan perangkat keras atau perangkat maya dengan citra sistem Android N.
        2. +
        3. Hubungkan perangkat dengan mesin pengembangan dan pasang aplikasi Anda.
        4. +
        5. Jalankan aplikasi Anda dan biarkan aktif.
        6. +
        7. Simulasikan aplikasi yang sedang masuk ke dalam mode siaga dengan menjalankan perintah berikut: + +
          +$ adb shell am broadcast -a android.os.action.DISCHARGING
          +$ adb shell am set-idle <packageName> true
          +
          + +
        8. +
        9. Simulasikan membangunkan aplikasi Anda menggunakan perintah berikut: +
          $ adb shell am set-idle <packageName> false
          +
        10. +
        11. Amati perilaku aplikasi Anda saat dibangunkan. Pastikan aplikasi pulih dengan baik + dari mode siaga. Secara khusus, Anda harus memeriksa apakah Pemberitahuan aplikasi dan pekerjaan latar belakang + tetap berjalan sebagaimana yang diharapkan.
        12. +
        + +

        Auto Backup for Apps dan Identifier Perangkat Spesifik

        + +

        Jika aplikasi Anda mempertahankan identifier perangkat spesifik, seperti ID pendaftaran Google +Cloud Messaging, dalam penyimpanan internal, +pastikan Anda mengikuti praktik terbaik untuk mengecualikan lokasi +penyimpanan dari pencadangan otomatis, seperti dijelaskan dalam Auto +Backup for Apps.

        diff --git a/docs/html-intl/intl/in/about/versions/nougat/android-7.0-changes.jd b/docs/html-intl/intl/in/about/versions/nougat/android-7.0-changes.jd new file mode 100644 index 0000000000000000000000000000000000000000..af01cd23e186c1f12402c45d971e061009f8ab99 --- /dev/null +++ b/docs/html-intl/intl/in/about/versions/nougat/android-7.0-changes.jd @@ -0,0 +1,610 @@ +page.title=Perubahan Perilaku +page.keywords=pratinjau,sdk,kompatibilitas +meta.tags="preview", "compatibility" +page.tags="preview", "developer preview" +page.image=images/cards/card-n-changes_2x.png +@jd:body + + + + + +

        + Bersama fitur dan kemampuan baru, Android N + menyertakan berbagai macam perubahan sistem dan perubahan perilaku API. Dokumen ini + menyoroti beberapa perubahan utama yang harus dipahami dan diperhitungkan + dalam aplikasi Anda. +

        + +

        + Jika Anda sebelumnya telah mempublikasikan aplikasi untuk Android, ketahuilah bahwa aplikasi Anda + mungkin dipengaruhi oleh perubahan dalam platform. +

        + + +

        Baterai dan Memori

        + +

        +Android N menyertakan perubahan perilaku sistem yang bertujuan untuk meningkatkan daya tahan baterai +perangkat dan mengurangi penggunaan RAM. Perubahan ini bisa memengaruhi akses aplikasi Anda ke +sumber daya sistem, termasuk cara aplikasi Anda berinteraksi dengan aplikasi lain melalui +intent implisit tertentu. +

        + +

        Istirahatkan

        + +

        + Diperkenalkan dalam Android 6.0 (API level 23), Istirahatkan meningkatkan daya tahan baterai dengan + menangguhkan aktivitas CPU dan jaringan bila pengguna tidak mencabut perangkat, + tidak bergerak, dan layar dinonaktifkan. Android N lebih + menyempurnakan Istirahatkan dengan menerapkan subset CPU dan pembatasan jaringan + bila perangkat dicabut dan layar dinonaktifkan, namun tidak harus + diam, misalnya, bila handset dibawa bepergian di saku pengguna. +

        + + + +

        + Gambar 1. Ilustrasi tentang cara Istirahatkan menerapkan pembatasan + aktivitas sistem level pertama untuk meningkatkan daya tahan baterai. +

        + +

        + Bila perangkat sedang menggunakan daya baterai, dan layar telah nonaktif selama jangka waktu + tertentu, perangkat akan memasuki Istirahatkan dan menerapkan subset pembatasan pertama: Perangkat + akan menutup akses jaringan aplikasi, serta menangguhkan pekerjaan dan sinkronisasi. Jika perangkat sedang + diam selama jangka waktu tertentu setelah memasuki Istirahatkan, sistem akan menerapkan + pembatasan Istirahatkan selebihnya terhadap alarm {@link android.os.PowerManager.WakeLock}, + {@link android.app.AlarmManager}, GPS, dan pemindaian Wi-Fi. Tidak peduli + apakah sebagian atau semua pembatasan Istirahatkan diterapkan, sistem akan membangunkan + perangkat selama jeda pemeliharaan singkat, dan selama itu aplikasi diizinkan + mengakses jaringan dan bisa mengeksekusi semua pekerjaan/sinkronisasi yang telah ditangguhkan. +

        + + + +

        + Gambar 2. Ilustrasi tentang cara Istirahatkan menerapkan pembatasan + aktivitas sistem level kedua setelah perangkat diam selama jangka waktu tertentu. +

        + +

        + Perhatikan, mengaktifkan layar atau mencolokkan steker perangkat akan mengeluarkan dari Istirahatkan + dan membuang pembatasan pemrosesan ini. Perilaku tambahan ini tidak + memengaruhi rekomendasi dan praktik terbaik dalam menyesuaikan aplikasi Anda dengan versi + Istirahatkan sebelumnya yang diperkenalkan dalam Android 6.0 (API level 23), seperti yang dibahas di + + Mengoptimalkan untuk Istirahatkan dan Aplikasi Siaga. Anda tetap harus + mengikuti rekomendasi itu, seperti menggunakan Google Cloud Messaging (GCM) untuk + mengirim dan menerima pesan, serta mulai merencanakan pembaruan + untuk mengakomodasi perilaku Istirahatkan tambahan. +

        + + +

        Project Svelte: Optimalisasi Latar Belakang

        + +

        + Android N membuang tiga siaran implisit untuk membantu mengoptimalkan + penggunaan memori dan konsumsi daya. Perubahan ini penting karena siaran + implisit sering memulai aplikasi yang telah didaftarkan untuk mendengarkannya di + latar belakang. Membuang siaran ini bisa sangat menguntungkan + kinerja perangkat dan pengalaman pengguna. +

        + +

        + Perangkat seluler seringkali mengalami perubahan konektivitas, seperti saat berpindah + antara Wi-Fi dan data seluler. Saat ini, aplikasi bisa memantau perubahan dalam + konektivitas dengan mendaftarkan suatu penerima untuk siaran implisit {@link + android.net.ConnectivityManager#CONNECTIVITY_ACTION} dalam manifes + mereka. Karena banyak aplikasi yang didaftarkan untuk menerima siaran ini, switch jaringan tunggal + bisa menyebabkan semuanya aktif dan memproses siaran tersebut + secara bersamaan. +

        + +

        + Demikian pula, dalam Android versi sebelumnya, aplikasi bisa mendaftar untuk menerima siaran implisit {@link + android.hardware.Camera#ACTION_NEW_PICTURE} dan {@link + android.hardware.Camera#ACTION_NEW_VIDEO} dari aplikasi lain, seperti + Kamera. Bila pengguna mengambil gambar dengan aplikasi Kamera, semua aplikasi ini akan aktif + untuk memproses siaran. +

        + +

        + Untuk meminimalkan masalah ini, Android N menerapkan optimalisasi + berikut: +

        + +
          +
        • Aplikasi yang menargetkan Android N tidak menerima siaran {@link + android.net.ConnectivityManager#CONNECTIVITY_ACTION}, sekalipun + memiliki entri manifes untuk meminta pemberitahuan mengenai kejadian ini. Aplikasi + yang berjalan tetap bisa mendengarkan {@code CONNECTIVITY_CHANGE} pada thread utama + jika mereka meminta pemberitahuan dengan {@link android.content.BroadcastReceiver}. +
        • + +
        • Aplikasi tidak bisa mengirim atau menerima siaran {@link + android.hardware.Camera#ACTION_NEW_PICTURE} atau {@link + android.hardware.Camera#ACTION_NEW_VIDEO}. Optimalisasi ini + memengaruhi semua aplikasi, bukan hanya aplikasi yang menargetkan Android N. +
        • +
        + +

        Jika aplikasi Anda menggunakan intent ini, Anda harus membuang dependensi padanya + secepat mungkin agar Anda bisa menargetkan perangkat Android N dengan benar. + Kerangka kerja Android menyediakan beberapa solusi untuk mengurangi kebutuhan akan + siaran implisit ini. Misalnya, {@link + android.app.job.JobScheduler} API menyediakan mekanisme yang tangguh untuk menjadwalkan + operasi jaringan bila kondisi yang ditetapkan, seperti koneksi ke jaringan + berbiaya tetap, terpenuhi. Anda juga dapat menggunakan {@link + android.app.job.JobScheduler} untuk bereaksi terhadap perubahan pada penyedia materi. +

        + +

        + Untuk informasi selengkapnya tentang optimalisasi latar belakang di N dan cara menyesuaikan aplikasi Anda, + lihat Optimalisasi + Latar Belakang. +

        + +

        Perubahan Izin

        + +

        + Android N menyertakan perubahan pada izin yang bisa memengaruhi aplikasi Anda. +

        + +

        Perubahan izin sistem file

        + +

        + Guna meningkatkan keamanan file privat, direktori privat + aplikasi yang menargetkan Android N atau yang lebih tinggi memiliki akses terbatas (0700). + Pengaturan ini mencegah kebocoran metadata dari file privat, seperti ukuran + atau eksistensi. Perubahan izin ini memiliki beberapa efek samping: +

        + +
          +
        • + Izin file privat tidak boleh dianggap remeh oleh pemilik, + dan usaha untuk melakukannya menggunakan + {@link android.content.Context#MODE_WORLD_READABLE} dan/atau + {@link android.content.Context#MODE_WORLD_WRITEABLE}, akan memicu sebuah + {@link java.lang.SecurityException}. +

          + Catatan: Seperti sebelumnya, pembatasan ini tidak sepenuhnya diterapkan. + Aplikasi mungkin masih memodifikasi izin ke direktori privat mereka menggunakan + API asal atau {@link java.io.File File} API. Akan tetapi, kami sangat + tidak menyarankan Anda meremehkan izin direktori privat. +

          +
        • +
        • + Meneruskan URI file:// di luar domain paket dapat meninggalkan + penerima dengan jalur yang tidak bisa di akses. Karena itu, upaya untuk meneruskan URI + file:// akan memicu + FileUriExposedException. Cara yang disarankan adalah + materi file privat menggunakan {@link + android.support.v4.content.FileProvider}. +
        • +
        • + {@link android.app.DownloadManager} tidak bisa lagi berbagi + file yang tersimpan secara privat berdasarkan nama file. Aplikasi lawas dapat mengakibatkan + jalur yang tidak dapat diakses saat mengakses {@link + android.app.DownloadManager#COLUMN_LOCAL_FILENAME}. Aplikasi yang menargetkan + Android N atau yang lebih tinggi akan memicu {@link java.lang.SecurityException} saat + berupaya mengakses + {@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}. + Aplikasi lawas yang menyetel lokasi unduhan ke lokasi publik dengan + menggunakan + {@link + android.app.DownloadManager.Request#setDestinationInExternalFilesDir + DownloadManager.Request.setDestinationInExternalFilesDir()} atau + {@link + android.app.DownloadManager.Request#setDestinationInExternalPublicDir + DownloadManager.Request.setDestinationInExternalPublicDir()} + tetap bisa mengakses jalur tersebut di + {@link android.app.DownloadManager#COLUMN_LOCAL_FILENAME}, akan tetapi, + metode ini sangat tidak disarankan. Cara yang disarankan untuk mengakses file + yang diekspos oleh {@link android.app.DownloadManager} adalah menggunakan + {@link android.content.ContentResolver#openFileDescriptor + ContentResolver.openFileDescriptor()}. +
        • +
        + +

        Berbagi File Antar Aplikasi

        + +

        +Untuk aplikasi yang menargetkan Android N, kerangka kerja Android menerapkan +kebijakan {@link android.os.StrictMode} API yang melarang mengekspos URI {@code file://} +di luar aplikasi Anda. Jika sebuah intent berisi URI file meninggalkan aplikasi Anda, aplikasi tersebut akan gagal +dengan pengecualian {@code FileUriExposedException}. +

        + +

        +Untuk berbagi file antar aplikasi, Anda harus mengirim URI {@code content://} +dan memberikan izin akses sementara pada URI. Cara termudah untuk memberikan izin ini adalah dengan +menggunakan kelas {@link android.support.v4.content.FileProvider}. Untuk informasi selengkapnya +mengenai izin dan berbagi file, +lihat Berbagi File. +

        + +

        Peningkatan Aksesibilitas

        + +

        + Android N menyertakan perubahan yang bertujuan meningkatkan kegunaan + platform untuk pengguna dengan penglihatan yang rendah atau lemah. Perubahan ini umumnya tidak + memerlukan perubahan kode dalam aplikasi Anda, akan tetapi Anda harus memeriksa + fitur ini dan mengujinya dengan aplikasi untuk menilai kemungkinan dampaknya terhadap pengalaman + pengguna. +

        + + +

        Perbesaran Layar

        + +

        + Android N memungkinkan pengguna menyetel Display size yang akan memperbesar + atau memperkecil semua elemen pada layar, sehingga meningkatkan aksesibilitas perangkat + bagi pengguna yang kurang melihat. Pengguna tidak bisa memperbesar layar melewati lebar layar + minimum + sw320dp, yang merupakan lebar Nexus 4, yakni ponsel ukuran sedang pada umumnya. +

        + +
        + +
        + +
        +
        + +
        + +
        +

        + Gambar 3. Layar di sebelah kanan menampilkan efek + penambahan Display size perangkat yang menjalankan citra sistem Android N. +

        + + +

        + Bila kepadatan perangkat berubah, sistem akan memberi tahu aplikasi yang sedang berjalan dengan + cara berikut: +

        + +
          +
        • Jika aplikasi menargetkan API level 23 atau yang lebih rendah, sistem secara otomatis akan mematikan + semua proses latar belakang. Artinya, jika pengguna beralih dari + aplikasi tersebut untuk membuka layar Settings dan mengubah + setelan Display size, maka sistem akan mematikan aplikasi tersebut dengan cara yang + sama dengan saat memori tinggal sedikit. Jika aplikasi memiliki beberapa proses + latar depan, sistem akan memberi tahu proses tersebut mengenai perubahan konfigurasi seperti + dijelaskan dalam Menangani Perubahan + Waktu Proses, seolah-olah orientasi perangkat telah berubah. +
        • + +
        • Jika sebuah aplikasi menargetkan Android N, semua prosesnya + (latar depan dan latar belakang) akan diberi tahu mengenai perubahan konfigurasi seperti + dijelaskan dalam Menangani Perubahan + Waktu Proses. +
        • +
        + +

        + Sebagian besar aplikasi tidak perlu melakukan perubahan untuk mendukung fitur ini, asalkan + aplikasi tersebut mengikuti praktik terbaik Android. Hal-hal tertentu yang harus diperiksa: +

        + +
          +
        • Uji aplikasi Anda pada perangkat dengan lebar layar sw320dp + dan pastikan aplikasi berjalan dengan semestinya. +
        • + +
        • Bila konfigurasi perangkat berubah, perbarui informasi cache + yang bergantung pada kepadatan, seperti bitmap di cache atau sumber daya yang dimuat dari + jaringan. Periksa perubahan konfigurasi bila aplikasi melanjutkan dari status dihentikan + sementara. +

          + Catatan: Catatan: Jika Anda meng-cache data yang bergantung pada konfigurasi, ada + baiknya untuk menyertakan metadata yang relevan seperti ukuran layar + atau kepadatan piksel yang sesuai untuk data tersebut. Menyimpan metadata ini memungkinkan Anda untuk + memutuskan apakah Anda perlu segarkan data cache setelah perubahan + konfigurasi. +

          +
        • + +
        • Hindari menetapkan dimensi dengan satuan px, karena satuan ini tidak diskalakan dengan + kepadatan layar. Sebagai gantinya, tetapkan dimensi dengan satuan piksel yang tidak bergantung kepadatan + (dp). +
        • +
        + +

        Vision Settings di Setup Wizard

        + +

        + Android N menyertakan Vision Settings di layar Sambutan, di mana pengguna bisa + menyiapkan setelan aksesibilitas berikut pada perangkat baru: + Magnification gesture, Font size, + Display size dan TalkBack. Perubahan ini + meningkatkan visibilitas bug terkait dengan setelan layar yang berbeda. Untuk + mengurangi dampak fitur ini, Anda harus menguji aplikasi dengan setelan ini + diaktifkan. Anda bisa menemukannya pada Settings > + Accessibility. +

        + +

        Penautan Aplikasi NDK ke Pustaka Platform

        + +

        + Android N menyertakan perubahan ruang nama untuk mencegah pemuatan API non-publik. + Jika menggunakan NDK, Anda hanya boleh menggunakan API publik dari platform + Android. Menggunakan API non-publik dalam rilis Android resmi berikutnya + bisa menyebabkan aplikasi mogok. +

        + +

        + Untuk memberi tahu Anda agar menggunakan API non-publik, aplikasi yang berjalan pada perangkat + Android N akan menghasilkan kesalahan dalam keluaran logcat bila aplikasi memanggil API non-publik. + Kesalahan ini juga ditampilkan di layar perangkat berupa pesan untuk membantu + meningkatkan kepedulian terhadap situasi ini. Anda harus memeriksa kode aplikasi untuk + membuang penggunaan API platform non-publik dan secara saksama menguji aplikasi Anda menggunakan + perangkat pratinjau atau emulator. +

        + +

        + Jika aplikasi Anda bergantung pada pustaka platform, lihat dokumentasi NDK untuk + perbaikan tipikal guna menggantikan API privat umum dengan padanan API publik. + Anda mungkin juga menautkan ke pustaka platform tanpa menyadarinya, + terutama jika aplikasi Anda menggunakan pustaka yang merupakan bagian dari platform ini (seperti + libpng), namun bukan bagian dari NDK. Dalam hal itu, pastikan + APK Anda berisi semua file .so yang ingin ditautkan. +

        + +

        + Perhatian: Beberapa pustaka pihak ketiga mungkin menautkan ke API + non-publik. Jika menggunakan pustaka ini, aplikasi Anda bisa mogok saat dijalankan + pada rilis resmi Android berikutnya. +

        + +

        + Aplikasi tidak boleh bergantung pada atau menggunakan pustaka bawaan yang tidak disertakan dalam + NDK, karena bisa mengalami perubahan, atau dipindahkan dari satu rilis Android ke + rilis lainnya. Peralihan dari OpenSSL ke BoringSSL merupakan satu contoh dari perubahan semacam ini. + Selain itu, perangkat yang berbeda bisa menawarkan tingkat kompatibilitas yang berbeda, karena + tidak ada persyaratan kompatibilitas untuk pustaka platform yang tidak disertakan + dalam NDK. Jika Anda harus mengakses pustaka non-NDK pada perangkat yang lebih lama, jadikan + pemuatan bergantung pada level Android API. +

        + +

        + Untuk membantu Anda mendiagnosis tipe masalah ini ada beberapa contoh kesalahan Java dan NDK + yang mungkin Anda temui saat berusaha membangun aplikasi dengan Android N: +

        + +

        Contoh kesalahan Java:

        +
        +java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so"
        +    is not accessible for the namespace "classloader-namespace"
        +
        + +

        Contoh kesalahan NDK:

        +
        +dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
        +
        + + +

        + Inilah beberapa perbaikan tipikal untuk aplikasi yang mengalami tipe kesalahan ini: +

        + +
          +
        • Penggunaan getJavaVM dan getJNIEnv dari libandroid_runtime.so bisa diganti + dengan fungsi JNI standar: +
          +AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
          +AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
          +JavaVM::AttachCurrentThread from <jni.h>.
          +
          +
        • + +
        • Penggunaan simbol {@code property_get} dari {@code libcutils.so} bisa + diganti dengan {@code alternative __system_property_get} publik. + Caranya, gunakan {@code __system_property_get} dengan menyertakan yang berikut: +
          +#include <sys/system_properties.h>
          +
          +
        • + +
        • Penggunaan simbol {@code SSL_ctrl} dari {@code libcrypto.so} harus + diganti dengan aplikasi versi lokal. Misalnya, Anda harus menautkan + {@code libcyrpto.a} secara statis dalam file {@code .so} atau menyertakan + {@code libcrypto.so} Anda sendiri secara dinamis dari BoringSSL atau OpenSSL dalam aplikasi Anda. +
        • +
        + +

        Android for Work

        +

        + Android N berisi perubahan untuk aplikasi yang menargetkan Android for Work, termasuk + perubahan pada pemasangan sertifikat, penyetelan ulang sandi, manajemen pengguna + tambahan, dan akses ke identifier perangkat. Jika Anda membangun aplikasi untuk + lingkungan Android for Work, Anda harus meninjau perubahan ini dan memodifikasi + aplikasi sebagaimana mestinya. +

        + +
          +
        • Anda harus pasang pemasang sertifikat yang didelegasikan sebelum DPC bisa + menyetelnya. Untuk aplikasi profil dan aplikasi pemilik perangkat yang menargetkan N SDK, Anda harus + pasang pemasang sertifikat yang didelegasikan sebelum pengontrol kebijakan + perangkat (DPC) memanggil + DevicePolicyManager.setCertInstallerPackage(). Jika pemasang + belum dipasang, sistem akan melontarkan + IllegalArgumentException. +
        • + +
        • Pembatasan sandi penyetelan ulang untuk admin perangkat sekarang diterapkan ke pemilik + profil. Admin perangkat tidak bisa lagi menggunakan + {@code DevicePolicyManager.resetPassword()} untuk menghapus sandi atau mengubah + sandi yang sudah disetel. Admin perangkat tetap bisa menyetel sandi, namun hanya + bila perangkat belum memiliki sandi, PIN, atau pola. +
        • + +
        • Pemilik perangkat dan profil bisa mengelola akun meskipun pembatasan + telah disetel. Pemilik perangkat dan pemilik profil bisa memanggil Account Management API + sekalipun pembatasan pengguna DISALLOW_MODIFY_ACCOUNTS diberlakukan. +
        • + +
        • Pemilik perangkat bisa mengelola pengguna tambahan lebih mudah. Bila perangkat + berjalan dalam mode pemilik perangkat, maka pembatasan DISALLOW_ADD_USER + secara otomatis akan ditetapkan. Ini mencegah pengguna membuat pengguna tambahan yang + tidak terkelola. Selain itu, CreateUser() dan + createAndInitializeUser() metode tidak digunakan lagi; metode + DevicePolicyManager.createAndManageUser() telah menggantikannya. +
        • + +
        • Pemilik perangkat bisa mengakses identifier perangkat. Pemilik perangkat bisa mengakses + alamat MAC Wi-Fi dari perangkat, menggunakan + DevicePolicyManagewr.getWifiMacAddress(). Jika Wi-Fi belum pernah + diaktifkan pada perangkat tersebut, metode ini akan mengembalikan nilai {@code null}. +
        • + +
        • Setelan Mode Kerja mengontrol akses ke aplikasi kerja. Bila mode kerja tidak aktif, peluncur sistem + akan menunjukkan aplikasi kerja tidak tersedia dengan membuat warnanya jadi abu-abu. Mengaktifkan kembali + mode kerja akan memulihkan perilaku normal. +
        + +

        + Untuk informasi selengkapnya tentang perubahan Android for Work di Android N, lihat + Pembaruan Android for Work. +

        + +

        Retensi Anotasi

        + +

        +Android N memperbaiki bug dengan visibilitas anotasi diabaikan. +Masalah ini mengaktifkan waktu proses untuk mengakses anotasi yang seharusnya tidak bisa +dilakukan. Anotasi ini termasuk: +

        + +
          +
        • {@code VISIBILITY_BUILD}: Dimaksudkan agar hanya bisa terlihat pada waktu pembuatan.
        • +
        • {@code VISIBILITY_SYSTEM}: Dimaksud agar bisa terlihat pada waktu proses, namun hanya pada + sistem yang mendasarinya.
        • +
        + +

        +Jika aplikasi Anda mengandalkan perilaku ini, tambahkan kebijakan retensi untuk anotasi yang harus +tersedia di waktu proses. Caranya dengan menggunakan {@code @Retention(RetentionPolicy.RUNTIME)}. +

        + +

        Poin Penting Lainnya

        + +
          +
        • Bila aplikasi berjalan pada Android N, namun menargetkan level API yang lebih rendah, +dan pengguna mengubah ukuran tampilan, proses aplikasi akan dimatikan. Aplikasi +harus dapat menangani skenario ini dengan lancar. Jika tidak, maka akan mogok +bila pengguna memulihkannya dari Recents. + +

          +Anda harus menguji aplikasi untuk memastikan +perilaku ini tidak terjadi. +Anda bisa melakukannya dengan menyebabkan suatu mogok yang identik +saat mematikan aplikasi secara manual melalui DDMS. +

          + +

          +Aplikasi yang menargetkan N dan yang di atasnya tidak secara otomatis dimatikan saat perubahan kepadatan; +akan tetapi, aplikasi tersebut mungkin tetap merespons perubahan konfigurasi dengan buruk. +

          +
        • + +
        • +Aplikasi pada Android N harus mampu menangani perubahan konfigurasi dengan lancar, +dan tidak boleh mengalami mogok pada start selanjutnya. Anda bisa memverifikasi perilaku aplikasi +dengan mengubah ukuran font (Setting > +Display > Font size), kemudian memulihkan +aplikasi dari Recents. +
        • + +
        • +Dikarenakan adanya bug di versi Android sebelumnya, sistem tidak menandai penulisan + ke soket TCP di thread utama sebagai pelanggaran mode-ketat. Android N memperbaiki bug ini. +Aplikasi yang menunjukkan perilaku ini kini melontarkan sebuah {@code android.os.NetworkOnMainThreadException}. +Secara umum, melakukan operasi jaringan di thread utama tidak baik karena operasi ini +biasanya memiliki latensi tinggi yang menyebabkan ANR dan jank. +
        • + +
        • +Kelompok metode {@code Debug.startMethodTracing()} kini default ke +keluaran penyimpanan di direktori paket tertentu di penyimpanan bersama, +sebagai ganti di level teratas +kartu SD. Berarti aplikasi tidak perlu lagi meminta izin {@code WRITE_EXTERNAL_STORAGE} untuk menggunakan API ini. +
        • + +
        • +Banyak platform API yang kini mulai memeriksa beban besar yang dikirim +ke seluruh transaksi {@link android.os.Binder}, dan sistem +kini melontarkan kembali {@code TransactionTooLargeExceptions} +sebagai {@code RuntimeExceptions}, sebagai ganti logging secara diam-diam atau menyembunyikannya. Satu contoh +umum adalah menyimpan terlalu banyak data di +{@link android.app.Activity#onSaveInstanceState Activity.onSaveInstanceState()}, +yang menyebabkan {@code ActivityThread.StopInfo} melontarkan +{@code RuntimeException} bila aplikasi Anda menargetkan Android N. +
        • + +
        • +Jika sebuah aplikasi mengeposkan tugas {@link java.lang.Runnable} ke{@link android.view.View}, dan +{@link android.view.View} +tidak terpasang ke jendela, sistem +akan mengantrekan tugas {@link java.lang.Runnable} dengan {@link android.view.View}; +tugas {@link java.lang.Runnable} tidak akan dieksekusi hingga +{@link android.view.View} terpasang +ke jendela. Perilaku ini mengatasi bug berikut: +
            +
          • Jika sebuah aplikasi mengeposkan ke {@link android.view.View} dari thread selain thread UI jendela yang dimaksud, + maka {@link java.lang.Runnable} mungkin akan menjalankan thread yang salah. +
          • +
          • Jika tugas {@link java.lang.Runnable} diposkan dari thread selain + looper-thread, aplikasi bisa mengekspos tugas {@link java.lang.Runnable}.
          • +
          +
        • + +
        • +Jika sebuah aplikasi di Android N dengan +izin{@link android.Manifest.permission#DELETE_PACKAGES DELETE_PACKAGES} +mencoba menghapus sebuah paket, namun sebuah aplikasi berbeda telah memasang paket itu, +sistem akan memerlukan konfirmasi pengguna. Dalam skenario ini, aplikasi harus mengharapkan +{@link android.content.pm.PackageInstaller#STATUS_PENDING_USER_ACTION STATUS_PENDING_USER_ACTION} +sebagai status kembalian bila memanggil +{@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}. +
        • + +
        + diff --git a/docs/html-intl/intl/in/about/versions/nougat/android-7.0-samples.jd b/docs/html-intl/intl/in/about/versions/nougat/android-7.0-samples.jd new file mode 100644 index 0000000000000000000000000000000000000000..d31c0c041503e7bf1f1d920cf693c2de4c888311 --- /dev/null +++ b/docs/html-intl/intl/in/about/versions/nougat/android-7.0-samples.jd @@ -0,0 +1,85 @@ +page.title=Contoh +page.tags="preview", "samples", "android" +page.image=images/cards/card-n-samples_2x.png +@jd:body + +

        + Contoh kode berikut disediakan untuk Android N. Untuk + mengunduh contoh di Android Studio, pilih opsi menu File > Import + Samples. +

        + +

        + Catatan: Proyek yang bisa diunduh ini didesain + untuk digunakan bersama Gradle dan Android Studio. +

        + + +

        Playground Multi-Jendela

        + +

        + Contoh ini memperagakan cara memanfaatkan antarmuka pengguna + multi-jendela bersama aplikasi Anda. +

        +

        + + Dapatkan di GitHub +

        + +
        +

        Pemberitahuan Aktif

        + +

        + Ini adalah contoh yang sudah ada sebelumnya, menampilkan layanan sederhana yang mengirimkan + pemberitahuan menggunakan NotificationCompat. Setiap percakapan yang belum dibaca dari pengguna + dikirimkan sebagai pemberitahuan berbeda. +

        +

        + Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru + yang tersedia di Android N. +

        +

        + + Dapatkan di GitHub +

        + +
        +

        Layanan Perpesanan

        + +

        + Ini adalah contoh yang telah ada sebelumnya yang memperagakan cara menggunakan + NotificationManager untuk memberi tahu jumlah pemberitahuan yang saat ini ditampilkan + oleh aplikasi. +

        +

        + Contoh ini telah diperbarui untuk memanfaatkan fitur pemberitahuan baru + yang tersedia di Android N. +

        +

        + + Dapatkan di GitHub +

        + +
        +

        Direct Boot

        + +

        + Contoh ini memperagakan cara menyimpan dan mengakses data dalam penyimpanan yang dienkripsi + dengan perangkat yang selalu tersedia saat perangkat booting. +

        +

        + + Dapatkan di GitHub +

        + +
        +

        Scoped Directory Access

        + +

        + Contoh ini memperagakan cara membaca dan menulis data dari direktori + spesifik, sekaligus meminta izin lebih sedikit. +

        +

        + + Dapatkan di GitHub +

        diff --git a/docs/html-intl/intl/in/about/versions/nougat/android-7.0.jd b/docs/html-intl/intl/in/about/versions/nougat/android-7.0.jd new file mode 100644 index 0000000000000000000000000000000000000000..ff8af12db456a7f48f787e78c9200b7cd7f1f374 --- /dev/null +++ b/docs/html-intl/intl/in/about/versions/nougat/android-7.0.jd @@ -0,0 +1,1039 @@ +page.title=Android N for Developers +meta.tags="preview", "androidn" +page.tags="preview", "developer preview" +page.image=images/cards/card-n-apis_2x.png +@jd:body + + + + + + + + +

        Android N masih dalam pengembangan aktif, namun Anda bisa mencobanya +sekarang sebagai bagian dari N Developer Preview. Bagian-bagian di bawah ini akan menyoroti sebagian dari +fitur baru untuk pengembang.

        + +

        + Pastikan memeriksa Perubahan Perilaku untuk mengetahui selengkapnya tentang + bagian-bagian perubahan platform yang bisa memengaruhi aplikasi Anda, lihatlah + panduan pengembang untuk mengetahui selengkapnya tentang fitur-fitur utama, dan unduh Referensi API untuk mengetahui detail tentang + API baru. +

        + +

        Dukungan Multi-Jendela

        + + +

        Di Android N, kami memperkenalkan fitur multitasking baru dan yang banyak diminta +ke dalam platform — dukungan multi-jendela.

        + +

        Pengguna sekarang bisa membuka dua aplikasi sekaligus di layar.

        +
          +
        • Pada ponsel dan tablet +yang menjalankan Android N, pengguna bisa menjalankan dua aplikasi secara berdampingan atau +satu aplikasi di atas yang lain dalam mode layar terbagi. Pengguna bisa mengubah ukuran aplikasi dengan menyeret +pembagi di antara keduanya.
        • + +
        • Pada perangkat Android TV, aplikasi bisa menempatkan dirinya sendiri dalam mode +gambar-dalam-gambar, sehingga aplikasi bisa terus menampilkan materi sementara pengguna menjelajahi atau +berinteraksi dengan aplikasi lain.
        • +
        + +
        + +

        + Gambar 1. Aplikasi yang berjalan dalam mode layar terbagi. +

        + +
        + +

        Khususnya pada tablet dan perangkat yang berlayar lebih besar lainnya, dukungan multi-jendela +memberi Anda cara baru untuk memikat pengguna. Anda bahkan bisa mengaktifkan fitur seret-dan-lepas di +aplikasi untuk memudahkan pengguna menyeret materi ke dan dari aplikasi — cara bagus +untuk menyempurnakan pengalaman pengguna Anda.

        + +

        Tidak sulit menambahkan dukungan multi-jendela ke aplikasi Anda dan mengonfigurasi cara +menangani tampilan multi-jendela. Misalnya, Anda bisa menetapkan dimensi +minimum yang diizinkan aktivitas, sehingga mencegah pengguna mengubah ukuran aktivitas di bawah +ukuran itu. Anda juga bisa menonaktifkan tampilan multi-jendela untuk aplikasi Anda, yang + akan memastikan sistem hanya menampilkan aplikasi dalam mode layar penuh.

        + +

        + Untuk informasi selengkapnya, lihat dokumentasi pengembang Dukungan Multi-Jendela. + +

        + +

        Penyempurnaan Pemberitahuan

        + +

        Di Android N kami telah mengubah desain pemberitahuan agar lebih mudah dan lebih cepat +digunakan. Beberapa perubahan tersebut antara lain:

        + +
          +
        • + Pembaruan template: Kami telah memperbarui template pemberitahuan untuk + lebih menekankan citra pahlawan dan avatar. Pengembang akan dapat + memanfaatkan template baru dengan penyesuaian kode yang minimal. +
        • + +
        • + Penyesuaian gaya pesan: Anda bisa menyesuaikan lebih banyak + label antarmuka pengguna yang berkaitan dengan pemberitahuan Anda menggunakan kelas + MessageStyle. Anda bisa mengonfigurasi pesan, judul percakapan, + dan tampilan materi. +
        • + +
        • + Bundel pemberitahuan: Sistem bisa mengelompokkan pesan, + misalnya menurut topik pesan, dan menampilkan kelompok pesan tersebut. Seorang pengguna bisa + bertindak, misalnya Tutup atau Arsipkan, atas pesan yang ditampilkan. Jika Anda sudah + mengimplementasikan pemberitahuan untuk Android Wear, Anda akan terbiasa dengan + model ini. +
        • + +
        • + Balasan Langsung: Untuk aplikasi komunikasi real-time, sistem + Android mendukung balasan inline sehingga pengguna bisa dengan cepat membalas + SMS atau pesan teks secara langsung dari dalam antarmuka pemberitahuan. +
        • + +
        • + Tampilan khusus: Dua API baru memungkinkan Anda memanfaatkan dekorasi sistem, + misalnya header pemberitahuan dan tindakan, saat menggunakan tampilan + khusus dalam pemberitahuan. +
        • +
        + +
        + +
        + +
        + +
        + +
        + +
        + + +

        + Gambar 2. Bundel pemberitahuan dan balasan langsung. +

        + +

        Untuk mengetahui cara mengimplementasikan fitur-fitur + baru ini, lihat panduan Pemberitahuan. +

        + + + +

        Kompilasi JIT/AOT yang dipandu profil

        + +

        Di Android N, kami telah menambahkan compiler Just in Time (JIT) dengan pembuatan profil kode ke +ART, yang memungkinkannya terus meningkatkan kinerja aplikasi Android saat +dijalankan. Compiler JIT melengkapi compiler Ahead of Time (AOT) pada ART +dan membantu memperbaiki kinerja waktu proses, menghemat ruang penyimpanan, dan mempercepat +pembaruan aplikasi serta pembaruan sistem.

        + +

        Kompilasi yang dipandu profil memungkinkan ART mengelola kompilasi AOT/JIT untuk setiap aplikasi +sesuai dengan penggunaan sebenarnya, serta kondisi pada perangkat. Misalnya +,ART menyimpan profil setiap metode terbaik aplikasi dan bisa melakukan kompilasi lebih awal +serta menyimpan sementara metode-metode tersebut di cache untuk mendapatkan kinerja terbaik. Hal ini membuat bagian lain dari aplikasi +dibiarkan tidak dikompilasi hingga benar-benar digunakan.

        + +

        Di samping meningkatkan kinerja bagian-bagian penting aplikasi, kompilasi yang dipandu profil +membantu mengurangi footprint RAM keseluruhan aplikasi, termasuk biner +terkait. Fitur ini terutama penting pada perangkat dengan memori minim.

        + +

        ART mengelola kompilasi yang dipandu profil dengan cara yang meminimalkan dampak terhadap +baterai perangkat. ART melakukan prakompilasi hanya bila perangkat sedang diam dan +mengisi daya, sehingga menghemat waktu dan baterai dengan melakukan pekerjaan tersebut di awal.

        + +

        Jalur Cepat untuk Pasang Aplikasi

        + +

        Salah satu manfaat paling nyata dari compiler JIT pada ART adalah kecepatan +pemasnagan aplikasi dan pembaruan sistem. Bahkan aplikasi besar yang membutuhkan beberapa menit untuk +dioptimalkan dan dipasang di Android 6.0 sekarang bisa dipasang hanya dalam hitungan +detik. Pembaruan sistem juga lebih cepat, karena tidak ada lagi langkah optimalisasi.

        + +

        Istirahatkan Kapan Saja...

        + +

        Android 6.0 memperkenalkan Istirahatkan, yaitu mode sistem yang menghemat baterai dengan menangguhkan +aktivitas CPU dan jaringan di aplikasi bila perangkat sedang diam, misalnya saat +diletakkan di atas meja atau dalam laci.

        + +

        Sekarang di Android N, Istirahatkan selangkah lebih maju dalam menghemat baterai kapan saja. +Setiap kali layar mati dalam jangka waktu tertentu dan perangkat tidak terhubung ke sumber daya, +Istirahatkan akan menerapkan subset pembatasan umum CPU dan jaringan pada aplikasi. +Artinya pengguna bisa menghemat daya baterai meskipun perangkat dibawa di dalam +tasnya.

        + + + +

        + Gambar 3. Istirahatkan sekarang menerapkan + pembatasan untuk meningkatkan daya tahan baterai bahkan saat perangkat sedang tidak diam. +

        + + +

        Tidak lama setelah layar dimatikan saat perangkat menggunakan daya baterai, Istirahatkan +akan membatasi akses jaringan serta menangguhkan pekerjaan dan sinkronisasi. Selama jeda +pemeliharaan, aplikasi diizinkan mengakses jaringan dan menjalankan semua +pekerjaan/sinkronisasi yang ditangguhkan. Menyalakan layar atau mencolokkan perangkat akan mengeluarkan +perangkat dari Istirahatkan.

        + +

        Bila perangkat dalam kondisi diam lagi, dengan layar mati dan menggunakan daya baterai selama +jangka waktu tertentu, Istirahatkan akan menerapkan pembatasan CPU dan jaringan pada {@link +android.os.PowerManager.WakeLock}, alarm {@link android.app.AlarmManager}, dan +pemindaian GPS/Wi-Fi.

        + +

        Praktik terbaik untuk menyesuaikan aplikasi Anda dengan Istirahatkan adalah sama, baik +perangkat sedang bergerak maupun diam, jadi jika Anda sudah memperbarui aplikasi untuk +menjalankan Istirahatkan dengan lancar, berarti Anda sudah siap. Jika belum, mulailah menyesuaikan +aplikasi Anda dengan Istirahatkan sekarang juga.

        + +

        Project Svelte: Optimalisasi Latar Belakang

        + +

        Project Svelte merupakan upaya berkelanjutan untuk meminimalkan penggunaan RAM oleh sistem dan aplikasi +di semua jenis perangkat Android dalam ekosistem. Di Android N, Project +Svelte berfokus pada optimalisasi cara aplikasi berjalan di latar belakang.

        + +

        Proses latar belakang merupakan bagian terpenting dari sebagian besar aplikasi. Bila ditangani dengan benar, proses +ini bisa memberikan pengalaman pengguna yang mengagumkan — segera, cepat, dan sesuai konteks. +Bila tidak ditangani dengan benar, proses latar belakang bisa menguras RAM (dan +baterai) yang sebenarnya tidak perlu serta memengaruhi kinerja sistem untuk aplikasi lain.

        + +

        Sejak Android 5.0, {@link android.app.job.JobScheduler} telah menjadi +cara yang disukai untuk melakukan pekerjaan latar belakang dengan cara yang baik +bagi pengguna. Aplikasi bisa menjadwalkan pekerjaan sekaligus memungkinkan sistem mengoptimalkan berdasarkan +kondisi memori, daya, dan konektivitas. JobScheduler menawarkan kontrol serta +kemudahan, dan kami ingin semua aplikasi menggunakannya.

        + +

        + Opsi baik lainnya adalah + GCMNetworkManager, bagian dari Google Play Services, yang + menawarkan penjadwalan pekerjaan serupa dengan kompatibilitas pada semua versi lawas + Android. +

        + +

        Kami terus memperluas JobScheduler dan +GCMNetworkManager untuk memenuhi lebih banyak +kasus penggunaan Anda — misalnya, di Android N Anda sekarang bisa menjadwalkan pekerjaan +latar belakang berdasarkan perubahan di Content Providers. Pada saat yang sama kami mulai +menghilangkan beberapa pola lama yang bisa mengurangi kinerja sistem, +terutama pada perangkat yang minim memori.

        + +

        Di Android N kami membuang tiga siaran implisit yang umum digunakan — + {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION}, {@link + android.hardware.Camera#ACTION_NEW_PICTURE}, dan {@link + android.hardware.Camera#ACTION_NEW_VIDEO} — karena ketiganya bisa mengaktifkan +proses latar belakang pada beberapa aplikasi sekaligus serta menguras memori dan baterai. Jika +aplikasi Anda menerimanya, manfaatkan N Developer Preview untuk + beralih ke JobScheduler dan API terkait sebagai gantinya.

        + +

        + Lihat dokumentasi Optimalisasi + Latar Belakang untuk mengetahui detailnya. +

        + + +

        Data Saver

        + +
        + + +

        + Gambar 4. Data Saver di Settings. +

        +
        + +

        Selama penggunaan perangkat seluler, biaya paket data seluler biasanya + melebihi harga perangkat itu sendiri. Bagi banyak pengguna, data seluler adalah sumber daya +mahal yang ingin mereka hemat.

        + +

        Android N memperkenalkan mode Data Saver, layanan sistem baru yang mengurangi +penggunaan data seluler oleh aplikasi, baik saat roaming, mendekati akhir siklus tagihan, +atau saat menggunakan paket data prabayar yang kecil. Data Saver memberi pengguna kemampuan mengontrol cara aplikasi +menggunakan data seluler dan memungkinkan pengembang memberikan layanan yang lebih efisien bila Data +Saver aktif.

        + +

        Bila pengguna mengaktifkan Data Saver di Settings dan perangkat +dalam jaringan berkuota, sistem akan memblokir penggunaan data latar belakang dan memberi tahu aplikasi +untuk menghemat penggunaan data latar depan — misalnya dengan membatasi +kecepatan bit untuk streaming, mengurangi kualitas gambar, menangguhkan precaching optimistik, +dan seterusnya. Pengguna bisa memasukkan aplikasi tertentu ke daftar putih untuk memungkinkan penggunaan data berkuota +bila Data Saver diaktifkan.

        + +

        Android N memperluas {@link android.net.ConnectivityManager} untuk menyediakan cara pada aplikasi +untuk mengambil +preferensi Data Saver pengguna dan memantau +perubahan preferensi. Semua aplikasi harus memeriksa apakah pengguna telah mengaktifkan Data +Saver dan berusaha membatasi penggunaan data latar belakang dan latar depan.

        + + +

        Vulkan API

        + +

        + Android N mengintegrasikan Vulkan™, sebuah API rendering 3D baru, ke dalam platform. Seperti + OpenGL™ + ES, Vulkan merupakan standar terbuka untuk grafik 3D dan rendering yang dikelola + oleh Khronos Group. +

        + +

        + Vulkan didesain dari nol untuk meminimalkan overhead CPU dalam driver, + dan memungkinkan aplikasi Anda mengontrol operasi GPU lebih langsung. Vulkan + juga memungkinkan paralelisasi yang lebih baik dengan mengizinkan beberapa thread menjalankan + pekerjaan seperti pembuatan buffer perintah sekaligus. +

        + +

        + Pustaka dan alat pengembangan Vulkan telah dimasukkan ke dalam Android NDK. Ini + berisi: +

        + +
          +
        • Header +
        • + +
        • Layer validasi (pustaka debug) +
        • + +
        • SPIR-V shader compiler +
        • + +
        • Pustaka kompilasi shader waktu proses SPIR-V +
        • +
        + +

        + Vulkan hanya tersedia untuk aplikasi pada perangkat dengan perangkat keras yang mendukung Vulkan, + seperti Nexus 5X, Nexus 6P, dan Nexus Player. Kami bekerja sama erat dengan mitra + agar secepatnya makin banyak perangkat yang dilengkapi Vulkan. +

        + +

        + Untuk informasi selengkapnya, lihat dokumentasi API. +

        + +

        Quick Settings Tile API

        + + +
        + + +

        + Gambar 5. Quick Settings Tile dalam bayangan pemberitahuan. +

        + + +

        Quick Settings adalah cara populer dan mudah untuk mengekspos setelan dan tindakan utama, +langsung dari bayangan pemberitahuan. Di Android N, kami telah memperluas lingkup +Quick Settings untuk membuatnya lebih berguna dan praktis lagi.

        + +

        Kami telah menambahkan ruang lebih banyak untuk petak Quick Settings tambahan, yang bisa +diakses pengguna di semua bagian area tampilan halaman bernomor dengan mengusap ke kiri atau kanan. Kami juga memberi pengguna +kontrol untuk mengatur letak dan petak Quick Settings apa yang akan +ditampilkan — pengguna bisa menambahkan atau memindahkan petak dengan menyeret dan melepasnya.

        + +

        Bagi pengembang, Android N juga menambahkan API baru yang memungkinkan Anda mendefinisikan + petak Quick Settings untuk memberi akses mudah kepada pengguna ke berbagai kontrol dan tindakan utama dalam aplikasi Anda.

        + +

        + Petak Quick Settings dicadangkan untuk kontrol atau tindakan yang + mendesak atau sering digunakan, dan tidak boleh digunakan sebagai pintasan untuk + membuka aplikasi. +

        + +

        + Setelah mendefinisikan petak, Anda bisa menyediakannya kepada pengguna, yang bisa mereka tambahkan + ke Quick Settings cukup dengan seret dan lepas. +

        + +

        + Untuk informasi tentang pembuatan petak aplikasi, lihat dokumentasi untuk + android.service.quicksettings.Tile dalam Referensi API yang bisa diunduh. +

        + + + +

        Pemblokiran Nomor

        + +

        Android N sekarang mendukung pemblokiran nomor di platform dan menyediakan +API kerangka kerja agar penyedia layanan bisa mengelola daftar nomor blokir. Aplikasi SMS +default, aplikasi telepon default, dan aplikasi operator bisa membaca dari dan +menulis ke daftar nomor blokir. Daftar ini tidak dapat diakses oleh aplikasi lain.

        + +

        Dengan membuat pemblokiran nomor sebagai fitur standar pada platformnya, Android menyediakan +cara konsisten bagi aplikasi untuk mendukung pemblokiran nomor di berbagai +perangkat. Manfaat lain yang bisa diperoleh aplikasi antara lain:

        + +
          +
        • Nomor yang diblokir untuk panggilan juga akan diblokir untuk SMS +
        • Nomor yang diblokir tetap disimpan saat pengaturan ulang dan pada berbagai perangkat melalui fitur Backup & +Restore. +
        • Beberapa aplikasi sekaligus bisa menggunakan daftar nomor blokir yang sama. +
        + +

        Selain itu, dengan integrasi aplikasi operator melalui Android berarti operator bisa +membaca daftar nomor blokir pada perangkat dan melakukan pemblokiran di sisi layanan +bagi pengguna tersebut untuk menghentikan panggilan dan SMS yang tidak diinginkan +agar tidak sampai ke pengguna lewat media apa pun, misalnya VOIP-endpoint atau meneruskan panggilan telepon.

        + +

        + Untuk informasi selengkapnya, lihat android.provider.BlockedNumberContract + dalam Referensi + API yang bisa diunduh. +

        + +

        Penyaringan Panggilan

        + +

        + Android N memungkinkan aplikasi telepon default untuk menyaring panggilan masuk. Aplikasi + telepon melakukannya dengan mengimplementasikan CallScreeningService baru, + yang memungkinkan aplikasi telepon untuk melakukan sejumlah tindakan berdasarkan + {@link android.telecom.Call.Details Call.Details} panggilan masuk, misalnya: +

        + +
          +
        • Menolak panggilan masuk +
        • Tidak mengizinkan panggilan tersebut disimpan ke log panggilan +
        • Tidak menampilkan pemberitahuan untuk panggilan tersebut kepada pengguna +
        + +

        + Untuk informasi selengkapnya, lihat android.telecom.CallScreeningService + dalam Referensi + API yang bisa diunduh. +

        + + +

        Dukungan Multilokal, Lebih Banyak Bahasa yang Didukung

        + + +

        Android N kini memungkinkan pengguna memilih banyak lokal di Settings, +untuk mendukung kasus penggunaan dwibahasa dengan lebih baik. Aplikasi bisa menggunakan +API baru untuk mendapatkan lokal pilihan pengguna kemudian menawarkan pengalaman pengguna +yang lebih canggih untuk pengguna multilokal — seperti menampilkan hasil telusur dalam +banyak bahasa dan tidak menawarkan untuk menerjemahkan halaman web dalam bahasa +yang sudah diketahui pengguna.

        + +

        Bersama dukungan multilokal, Android N juga memperluas ragam bahasa +yang tersedia untuk pengguna. Masing-masing ditawarkan lebih dari 25 varian untuk bahasa yang umum +digunakan seperti Inggris, Spanyol, Prancis, dan Arab. Juga ditambahkan dukungan +parsial untuk lebih dari 100 bahasa baru.

        + +

        Aplikasi bisa mendapatkan daftar lokal yang disetel oleh pengguna dengan memanggil +LocaleList.GetDefault(). Untuk mendukung jumlah lokal yang diperluas, Android N sedang + mengubah cara mengatasi masalah sumber daya. Pastikan Anda menguji dan memverifikasi bahwa aplikasi Anda +berfungsi seperti yang diharapkan dengan logika resolusi sumber daya baru.

        + +

        Untuk mengetahui tentang perilaku resolusi sumber daya baru dan praktik terbaik yang +harus Anda ikuti, lihat Dukungan Multibahasa.

        + + +

        Emoji Baru

        + +

        + Android N memperkenalkan emoji tambahan dan fitur terkait emoji termasuk + emoji warna kulit dan dukungan untuk pemilih + variasi. Jika aplikasi Anda mendukung emoji, + ikuti panduan berikut untuk memanfaatkan fitur terkait emoji ini. +

        + +
          +
        • + Periksa apakah perangkat berisi emoji sebelum memasukannya. + Untuk memeriksa emoji mana yang terdapat di + font sistem, gunakan metode {@link android.graphics.Paint#hasGlyph(String)}. +
        • +
        • + Periksa apakah emoji mendukung pemilih variasi. + Pemilih variasi memungkinkan Anda + menampilkan emoji tertentu berwarna atau hitam-putih. + Pada perangkat seluler, aplikasi akan menghadirkan emoji berwarna daripada hitam-putih. Akan tetapi, + jika aplikasi Anda menampilkan emoji sebaris dengan teks, maka harus menggunakan variasi hitam-putih. + Untuk menentukan apakah sebuah emoji memiliki variasi, gunakan pemilih variasi. + Untuk daftar lengkap dari karakter dengan variasinya, tinjaulah bagian + rangkaian variasi emoji pada + + dokumentasi Unicode mengenai variasi. +
        • +
        • + Periksa apakah emoji mendukung warna kulit. Android N memungkinkan pengguna memodifikasi + warna kulit emoji yang dirender sesuai dengan preferensi mereka. Aplikasi keyboard harus menyediakan indikasi + visual untuk emoji yang memiliki beberapa warna kulit dan harus memungkinkan pengguna + memilih warna kulit yang mereka sukai. Untuk menentukan apakah emoji sistem memiliki + modifier warna kulit, gunakan metode {@link android.graphics.Paint#hasGlyph(String)}. + Anda bisa menentukan emoji mana yang menggunakan warna kulit dengan membaca + + dokumentasi Unicode. +
        • +
        + + +

        ICU4J API di Android

        + +

        + Android N kini menawarkan subset ICU4J API dalam kerangka kerja Android pada paket + android.icu. Migrasi mudah, dan biasanya hanya perlu + mengubah dari ruang nama com.java.icu ke + android.icu. Jika Anda sudah menggunakan bundel ICU4J dalam aplikasi, + maka beralih ke android.icu API yang disediakan dalam kerangka kerja + Android bisa menghasilkan penghematan besar dalam ukuran APK. +

        + +

        + Untuk mengetahui selengkapnya tentang Android ICU4J API, lihat Dukungan ICU4J. +

        + + + +

        OpenGL™ ES 3.2 API

        + +

        Android N menambahkan antarmuka kerangka kerja dan dukungan platform untuk OpenGL ES 3.2, termasuk:

        + +
          +
        • Semua ekstensi dari +Android Extension Pack (AEP) kecuali untuk EXT_texture_sRGB_decode. +
        • Floating-point framebuffer untuk HDR dan shading yang ditangguhkan. +
        • Panggilan draw BaseVertex agar batching dan streaming jadi lebih baik. +
        • Kontrol akses buffer yang tangguh untuk mengurangi overhead WebGL. +
        + +

        API kerangka kerja untuk OpenGL ES 3.2 di Android N dilengkapi dengan kelas + GLES32. Saat menggunakan OpenGL ES 3.2, pastikan +mendeklarasikan persyaratan dalam file manifes Anda, dengan tag <uses-feature> dan +atribut android:glEsVersion.

        + +

        Untuk informasi tentang menggunakan OpenGL ES, termasuk cara memeriksa versi +OpenGL ES yang didukung perangkat saat waktu proses, lihat Panduan OpenGL ES API.

        + + +

        Perekaman Android TV

        + +

        Android N menambahkan kemampuan untuk merekam dan memutar kembali materi dari layanan masukan +Android TV melalui API perekaman baru. Karena dibangun dengan API perekaman yang sudah +ada, layanan masukan TV bisa mengontrol data saluran apa yang bisa direkam, cara menyimpan +sesi rekaman, dan mengelola interaksi pengguna dengan materi rekaman.

        + +

        Untuk informasi selengkapnya, lihat API Perekaman Android TV.

        + + +

        Android for Work

        + +

        Android for Work menambahkan berbagai fitur dan API baru untuk perangkat yang menjalankan Android N. +Beberapa fitur unggulannya ada di bawah ini — untuk mengetahui daftar lengkap perubahannya, lihat +Pembaruan Android for Work.

        + +

        Pertanyaan Keamanan Profil Kerja

        + +

        + Pemilik profil yang menargetkan N SDK + bisa menetapkan pertanyaan keamanan terpisah untuk aplikasi yang berjalan di + profil kerja. Pertanyaan kerja ditampilkan bila pengguna mencoba membuka + aplikasi kerja apa pun. Jawaban pertanyaan keamanan yang benar akan membuka + profil kerja dan mendekripsinya jika diperlukan. Untuk pemilik profil, + ACTION_SET_NEW_PASSWORD akan meminta pengguna untuk menetapkan pertanyaan + kerja, dan ACTION_SET_NEW_PARENT_PROFILE_PASSWORD meminta + pengguna menyetel kunci perangkat. +

        + +

        + Pemilik profil bisa menyetel kebijakan kode sandi untuk pertanyaan kerja + (seperti berapa lama seharusnya PIN, atau apakah sidik jari bisa digunakan + untuk membuka kunci profil) menggunakan setPasswordQuality(), + setPasswordMinimumLength() dan metode terkait. Pemilik profil + juga bisa menyetel kunci perangkat, menggunakan instance DevicePolicyManager + yang dikembalikan oleh metode getParentProfileInstance() baru. + Selain itu, pemilik profil bisa menyesuaikan layar kredensial untuk + pertanyaan kerja menggunakan metode baru setOrganizationColor() dan + setOrganizationName(). +

        +

        Menonaktifkan pekerjaan

        + +

        Pada perangkat dengan profil kerja, pengguna bisa beralih mode kerja. Bila mode +kerja dinonaktifkan, profil yang dikelola akan dinonaktifkan untuk sementara, yang akan menonaktifkan aplikasi +profil kerja, sinkronisasi latar belakang, dan pemberitahuan. Termasuk aplikasi pemilik +profil. Bila profil kerja dinonaktifkan, sistem akan menampilkan ikon status +tetap untuk mengingatkan pengguna bahwa mereka tidak bisa meluncurkan aplikasi kerja. Peluncur +menunjukkan bahwa aplikasi kerja dan widget tidak bisa diakses.

        + +

        Always-On VPN

        + +

        Pemilik perangkat dan pemilik profil bisa memastikan bahwa aplikasi kerja selalu menghubungkan +melalui VPN yang ditetapkan. Sistem secara otomatis akan memulai VPN itu setelah booting +perangkat.

        + +

        + Metode DevicePolicyManager baru adalah + setAlwaysOnVpnPackage() dan + getAlwaysOnVpnPackage(). +

        + +

        Karena layanan VPN bisa diikat langsung oleh sistem tanpa interaksi +aplikasi, klien VPN perlu menangani titik masuk baru untuk Always-On VPN. Seperti +sebelumnya, layanan ditunjukkan ke sistem melalui +tindakan pencocokan filter intent android.net.VpnService.

        + +

        + Pengguna bisa secara manual menyetel klien Always-On VPN yang mengimplementasikan + metode VPNService dalam pengguna utama dengan menggunakan + Settings>More>Vpn. +

        + +

        Penyediaan yang disesuaikan

        + +

        + Aplikasi bisa menyesuaikan alur penyediaan pemilik profil dan pemilik perangkat + dengan warna dan logo perusahaan. + DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR menyesuaikan + warna alur. DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI + menyesuaikan alur dengan logo perusahaan. +

        + +

        Penyempurnaan Aksesibilitas

        + +

        Android N saat ini menawarkan Vision Settings langsung di layar Sambutan untuk +persiapan perangkat baru. Ini sangat memudahkan pengguna untuk menemukan dan mengonfigurasi +fitur aksesibilitas pada perangkat mereka, termasuk isyarat perbesaran, ukuran +font, ukuran layar, dan TalkBack.

        + +

        Dengan fitur aksesibilitas yang penempatannya semakin jelas, pengguna Anda +kemungkinan besar akan mencoba aplikasi dengan fitur-fitur yang diaktifkan itu. Pastikan Anda menguji aplikasi +lebih dini dengan mengaktifkan dahulu setelan ini. Anda bisa mengaktifkannya dari Settings > +Accessibility.

        + +

        Di Android N, layanan aksesibilitas sekarang bisa membantu pengguna yang mengalami gangguan +motorik untuk menyentuh layar. API baru memungkinkan membangun layanan dengan +fitur-fitur seperti pelacakan wajah, pelacakan mata, pemindaian titik, dan seterusnya, untuk +memenuhi kebutuhan para pengguna tersebut.

        + +

        Untuk informasi selengkapnya, lihat android.accessibilityservice.GestureDescription + dalam Referensi API yang bisa diunduh.

        + + +

        Direct Boot

        + +

        Direct Boot memperbaiki waktu startup perangkat dan memungkinkan aplikasi +yang telah didaftarkan memiliki fungsionalitas terbatas bahkan setelah boot ulang tak terduga. +Misalnya, jika perangkat yang dienkripsi melakukan boot ulang selagi pengguna tidur, +alarm terdaftar, pesan dan panggilan masuk sekarang bisa terus memberi tahu +pengguna seperti biasa. Ini juga berarti layanan aksesibilitas bisa + segera tersedia setelah restart.

        + +

        Direct Boot memanfaatkan enkripsi berbasis file di Android N +untuk mengaktifkan kebijakan enkripsi yang telah disesuaikan bagi sistem dan data aplikasi. +Sistem akan menggunakan penyimpanan yang dienkripsi dengan perangkat untuk data sistem terpilih dan data +aplikasi yang terdaftar secara eksplisit. Secara default, penyimpanan yang dienkripsi dengan kredensial digunakan untuk semua + data sistem lainnya, data pengguna, aplikasi, dan data aplikasi.

        + +

        Saat booting, sistem dimulai dalam mode terbatas dengan akses +ke data yang dienkripsi dengan perangkat saja, dan tanpa akses umum ke aplikasi atau data. +Jika Anda memiliki komponen yang ingin Anda jalankan dalam mode ini, Anda bisa mendaftarkannya +dengan menyetel flag dalam manifes. Setelah restart, sistem akan mengaktifkan +komponen terdaftar dengan menyiarkan intent LOCKED_BOOT_COMPLETED. + Sistem akan memastikan data aplikasi yang dienkripsi dengan perangkat tersedia +sebelum membuka kunci. Semua data lainnya tidak tersedia sebelum Pengguna mengonfirmasi + kredensial layar kunci mereka untuk mendekripsinya.

        + +Untuk informasi selengkapnya, lihat Direct Boot.

        +

        + + +

        Key Attestation

        + +

        Keystore yang didukung perangkat keras menyediakan metode yang jauh lebih aman untuk membuat, menyimpan, +dan menggunakan kunci kriptografi pada perangkat Android. Keystore itu melindungi kunci dari +kernel Linux, potensi kerentanan Android, dan ekstraksi +dari perangkat yang di-root.

        + +

        Agar lebih mudah dan lebih aman dalam menggunakan keystore yang didukung perangkat keras, +Android N memperkenalkan Key Attestation. Aplikasi dan perangkat-nonaktif bisa menggunakan Key +Attestation untuk menentukan apakah penyandingan kunci RSA atau EC +didukung perangkat keras, apa properti dari penyandingan kunci, dan batasan + apa yang diterapkan terhadap penggunaan dan validitasnya.

        + +

        Aplikasi dan layanan perangkat-nonaktif bisa meminta informasi tentang penyandingan kunci +melalui sertifikat pengesahan X.509 yang harus ditandatangani dengan kunci +pengesahan yang valid. Kunci pengesahan adalah kunci penandatanganan ECDSA yang +telah diinjeksikan ke dalam keystore yang didukung perangkat keras pada perangkat saat di pabriknya. +Karena itu, sertifikat pengesahan yang ditandatangani oleh kunci pengesahan yang +valid akan mengonfirmasi keberadaan keystore yang didukung perangkat keras, bersama + detail pasangan kunci dalam keystore itu.

        + +

        Untuk memastikan perangkat ini menggunakan citra Android resmi yang +aman dari pabrik, Key Attestation mengharuskan bootloader perangkat +menyediakan informasi berikut pada Trusted +Execution Environment (TEE):

        + +
          +
        • Versi OS dan level patch yang dipasang pada perangkat
        • +
        • Kunci publik Verified Boot dan status kunci
        • +
        + +

        Untuk informasi selengkapnya tentang fitur keystore yang didukung perangkat keras, +lihat panduan untuk Keystore yang Didukung Perangkat Keras.

        + +

        Selain Key Attestation, Android N juga memperkenalkan + kunci yang terikat sidik jari yang tidak dipanggil saat pendaftaran sidik jari.

        + +

        Network Security Config

        + +

        Di Android N, aplikasi bisa menyesuaikan perilaku koneksi aman mereka +(HTTPS, TLS) secara aman, tanpa modifikasi kode, dengan menggunakan +Network Security Config deklaratif sebagai ganti menggunakan API programatik +konvensional yang rawan kesalahan (mis. X509TrustManager).

        + +

        Fitur yang didukung:

        +
          +
        • Trust-anchor khusus. Memungkinkan aplikasi menyesuaikan +Certificate Authorities (CA) mana yang dipercaya untuk koneksi amannya. Misalnya, +mempercayai sertifikat tertentu yang ditandatangani sendiri atau set CA publik yang dibatasi. +
        • +
        • Penggantian hanya-debug. Memungkinkan pengembang aplikasi dengan aman men-debug +koneksi aman aplikasi mereka tanpa menambah risiko pada basis yang sudah +dipasang. +
        • +
        • Berhenti dari lalu lintas cleartext. Memungkinkan aplikasi melindungi dirinya sendiri dari +penggunaan lalu lintas cleartext yang tidak disengaja.
        • +
        • Penyematan sertifikat. Sebuah fitur canggih yang memungkinkan aplikasi + membatasi kunci server mana yang dipercaya untuk koneksi aman.
        • +
        + +

        Untuk informasi selengkapnya, lihat Network Security +Config.

        + +

        Certificate Authority Tepercaya Default

        + +

        Secara default, aplikasi yang menargetkan Android N hanya mempercayai sertifikat yang disediakan sistem +dan tidak lagi mempercayai Certificate Authorities (CA) yang ditambahkan pengguna. Aplikasi yang menargetkan Android +N dan ingin mempercayai CA yang ditambahkan pengguna harus menggunakan +Network Security Config untuk +menetapkan cara mempercayai CA pengguna.

        + +

        APK Signature Scheme v2

        + +

        + Android N memperkenalkan APK Signature Scheme v2, sebuah skema penandatanganan aplikasi baru yang + menawarkan waktu pasang aplikasi lebih cepat dan lebih banyak perlindungan terhadap perubahan + tidak sah pada file APK. Secara default, Android Studio 2.2 dan Android + Plugin untuk Gradle 2.2 menandatangani aplikasi Anda menggunakan APK Signature Scheme v2 dan + skema penandatanganan tradisional, yang menggunakan penandatanganan JAR. +

        + +

        + Meskipun kami menyarankan untuk menerapkan APK Signature Scheme v2 pada aplikasi Anda, skema + baru ini tidak wajib. Jika aplikasi Anda tidak dibangun dengan benar saat menggunakan APK + Signature Scheme v2, Anda bisa menonaktifkan skema baru ini. Proses penonaktifan + menyebabkan Android Studio 2.2 dan Android Plugin untuk Gradle 2.2 menandatangani aplikasi Anda + menggunakan skema penandatanganan tradisional saja. Untuk menandatangani dengan + skema tradisional saja, buka file build.gradle level-modul, kemudian + tambahkan baris v2SigningEnabled false ke konfigurasi + penandatanganan rilis Anda: +

        + +
        +  android {
        +    ...
        +    defaultConfig { ... }
        +    signingConfigs {
        +      release {
        +        storeFile file("myreleasekey.keystore")
        +        storePassword "password"
        +        keyAlias "MyReleaseKey"
        +        keyPassword "password"
        +        v2SigningEnabled false
        +      }
        +    }
        +  }
        +
        + +

        Perhatian: Jika Anda menandatangani aplikasi menggunakan APK + Signature Scheme v2 dan membuat perubahan lebih jauh pada aplikasi, tanda tangan aplikasi + menjadi tidak valid. Untuk alasan ini, gunakan alat seperti zipalign + sebelum menandatangani aplikasi Anda menggunakan APK Signature Scheme v2, bukan setelahnya. +

        + +

        + Untuk informasi selengkapnya, baca dokumen Android Studio yang menjelaskan cara + + menandatangani aplikasi di Android Studio dan cara mengonfigurasi + file build untuk menandatangani aplikasi menggunakan Android Plugin untuk Gradle. +

        + +

        Scoped Directory Access

        + +

        Di Android N, aplikasi bisa menggunakan API baru untuk meminta akses ke direktori penyimpanan +eksternal tertentu, termasuk direktori di media lepas-pasang seperti kartu +SD. API baru ini sangat menyederhanakan cara aplikasi Anda mengakses direktori +penyimpanan eksternal standar, seperti direktori Pictures. Aplikasi +seperti aplikasi foto bisa menggunakan API ini sebagai ganti menggunakan +READ_EXTERNAL_STORAGE, yang memberikan akses ke semua direktori +penyimpanan, atau Storage Access Framework, yang membuat pengguna mengarah ke +direktori tersebut.

        + +

        Selain itu, API baru ini menyederhanakan langkah-langkah yang diambil pengguna untuk memberikan akses +penyimpanan eksternal ke aplikasi Anda. Bila Anda menggunakan API baru, sistem akan menggunakan UI izin +sederhana yang memperinci dengan jelas direktori apa yang aksesnya diminta +oleh aplikasi.

        + +

        Untuk informasi selengkapnya, lihat dokumentasi pengembang +Scoped +Directory Access.

        + +

        Keyboard Shortcuts Helper

        + +

        +Di Android N, pengguna bisa menekan "Alt + /" untuk memunculkan layar Keyboard Shortcuts +yang menampilkan semua pintasan yang tersedia baik dari sistem maupun dari +aplikasi yang sedang mendapatkan fokus. Ini diambil secara otomatis dari menu aplikasi +jika tersedia, namun pengembang bisa menyediakan daftar pintasan yang telah disesuaikan +untuk layar. Anda bisa melakukannya dengan mengganti metode +Activity.onProvideKeyboardShortcuts() baru, yang dijelaskan dalam +Referensi API yang bisa diunduh. +

        + +

        +Untuk memunculkan Keyboard Shortcuts Helper dari mana saja di aplikasi Anda, +panggil {@code Activity.requestKeyboardShortcutsHelper()} untuk aktivitas terkait. +

        + +

        Sustained Performance API

        + +

        +Kinerja bisa berfluktuasi secara dramatis untuk aplikasi yang berjalan lama, karena +sistem melakukan throttle pada mesin sistem-di-chip saat komponen perangkat mencapai +batas suhunya. Fluktuasi ini memberikan target bergerak bagi pengembang +aplikasi yang sedang membuat aplikasi berkinerja tinggi dan berjalan lama. +

        + +

        +Untuk menangani batasan ini, Android N menyertakan dukungan untuk +mode kinerja kontinu, yang memungkinkan OEM memberikan petunjuk mengenai kemampuan kinerja +perangkat untuk aplikasi yang berjalan lama. Pengembang aplikasi +bisa menggunakan petunjuk ini untuk menyesuaikan aplikasi agar kinerja perangkat bisa diprediksi +dan pada level yang konsisten dalam jangka waktu lama. +

        + +

        +Pengembang aplikasi bisa mencoba API baru ini dalam N Developer Preview pada +perangkat Nexus 6P saja. Untuk menggunakan fitur ini, +setel flag jendela kinerja kontinu +yang ingin Anda jalankan dalam mode kinerja kontinu. Setel flag ini menggunakan metode +{@code Window.setSustainedPerformanceMode()}. Sistem secara otomatis +akan menonaktifkan mode ini bila jendela tidak lagi mendapatkan fokus. +

        + +

        Dukungan VR

        + +

        +Android N menambahkan dukungan platform dan optimalisasi untuk VR Mode baru yang memungkinkan +pengembang membuat pengalaman VR berkualitas tinggi di seluler bagi para pengguna. Ada banyak perbaikan +kinerja, termasuk akses ke inti CPU yang eksklusif untuk aplikasi VR. +Di dalam aplikasi, Anda bisa memanfaatkan pelacakan kepala yang cerdas, +dan pemberitahuan stereo yang bekerja untuk VR. Hal terpenting adalah Android N menyediakan +grafis dengan latensi sangat rendah. Untuk informasi selengkapnya tentang membangun aplikasi VR untuk Android N, +lihat Google VR SDK untuk Android. +

        + + + + +

        + Di Android N, pengembang layanan cetak kini bisa menampilkan informasi tambahan + tentang masing-masing printer dan pekerjaan cetak. +

        + +

        + Saat mendaftarkan masing-masing printer, layanan cetak kini bisa menyetel + ikon per printer dalam dua cara: +

        + +
          +
        • Anda bisa menyetel ikon dari ID sumber daya dengan memanggil + PrinterInfo.Builder.setResourceIconId() +
        • + +
        • Anda bisa menampilkan ikon dari jaringan dengan memanggil + PrinterInfo.Builder.setHasCustomPrinterIcon(), dan menyetel sebuah + callback bila ikon diminta menggunakan + android.printservice.PrinterDiscoverySession.onRequestCustomPrinterIcon() +
        • +
        + +

        + Selain itu, Anda bisa menyediakan aktivitas per printer untuk menampilkan informasi + tambahan dengan memanggil PrinterInfo.Builder.setInfoIntent(). +

        + +

        + Anda bisa menunjukkan kemajuan dan status pekerjaan cetak di + pemberitahuan pekerjaan cetak dengan memanggil masing-masing + android.printservice.PrintJob.setProgress() dan + android.printservice.PrintJob.setStatus(). +

        + +

        + Untuk informasi selengkapnya tentang metode ini,lihat dalam Referensi API yang bisa diunduh. +

        + +

        FrameMetricsListener API

        + +

        +FrameMetricsListener API memungkinkan aplikasi untuk memantau +kinerja rendering UI. API tersebut menyediakan kemampuan ini dengan mengekspos Pub/Sub API streaming +untuk mentransfer info frame-timing untuk jendela aplikasi saat ini. Data yang dikembalikan +setara dengan yang ditampilkan adb shell +dumpsys gfxinfo framestats, namun tidak dibatasi pada 120 bingkai. +

        + +

        +Anda bisa menggunakan FrameMetricsListener untuk mengukur kinerja UI +level interaksi di produksi, tanpa koneksi USB. API +ini memungkinkan pengumpulan data dengan granularitas lebih tinggi daripada +{@code adb shell dumpsys gfxinfo}. Granularitas lebih tinggi ini dimungkinkan karena +sistem bisa mengumpulkan data untuk interaksi tertentu di aplikasi; sistem +tidak perlu merekam ringkasan global untuk keseluruhan kinerja +aplikasi, atau mengosongkan status global yang ada. Anda bisa menggunakan kemampuan ini +untuk mengumpulkan data kinerja dan menangkap regresi di kinerja UI +untuk kasus penggunaan sungguhan di dalam aplikasi. +

        + +

        +Untuk memantau sebuah jendela, implementasikan metode callback FrameMetricsListener.onMetricsAvailable() +dan daftarkan di jendela itu. Untuk informasi selengkapnya, lihat +dokumentasi kelas {@code FrameMetricsListener} di +Referensi API yang bisa diunduh. +

        + +

        +API menyediakan objek {@code FrameMetrics}, yang berisi data timing yang +dilaporkan subsistem rendering untuk berbagai tahap pencapaian dalam daur hidup bingkai. +Metrik yang didukung adalah: {@code UNKNOWN_DELAY_DURATION}, +{@code INPUT_HANDLING_DURATION}, {@code ANIMATION_DURATION}, +{@code LAYOUT_MEASURE_DURATION}, {@code DRAW_DURATION}, {@code SYNC_DURATION}, +{@code COMMAND_ISSUE_DURATION}, {@code SWAP_BUFFERS_DURATION}, +{@code TOTAL_DURATION}, dan {@code FIRST_DRAW_FRAME}. +

        + + +

        File Maya

        + +

        + Di versi Android sebelumnya, aplikasi Anda bisa menggunakan Storage Access + Framework untuk memungkinkan pengguna memilih file dari akun penyimpanan awan mereka, + seperti Google Drive. Akan tetapi, tidak ada cara untuk merepresentasikan file yang + tidak memiliki representasi bytecode langsung; setiap file diharuskan menyediakan + aliran masukan. +

        + +

        + Android N menambahkan konsep file maya pada Storage Access + Framework. Fitur file maya memungkinkan + {@link android.provider.DocumentsProvider} Anda mengembalikan URI dokumen yang bisa + digunakan bersama intent {@link android.content.Intent#ACTION_VIEW} sekalipun + tidak memiliki representasi bytecode langsung. Android N juga memungkinkan Anda untuk + menyediakan format alternatif untuk file pengguna, maya atau dengan cara lain. +

        + +

        + Untuk mendapatkan URI sebuah dokumen maya di aplikasi Anda, terlebih dahulu Anda membuat + {@link android.content.Intent} untuk membuka UI pemilih file. Karena aplikasi + tidak bisa membuka file maya secara langsung dengan menggunakan metode + {@link android.content.ContentResolver#openInputStream(Uri) openInputStream()}, + aplikasi Anda tidak akan menerima file maya jika Anda memasukkan kategori + {@link android.content.Intent#CATEGORY_OPENABLE}. +

        + +

        + Setelah pengguna menentukan pilihan, sistem akan memanggil metode + {@link android.app.Activity#onActivityResult onActivityResult()}. + Aplikasi Anda bisa mengambil URI file maya dan mendapatkan aliran masukan, seperti yang + diperagakan dalam cuplikan kode di bawah. +

        + +
        +  // Other Activity code ...
        +
        +  final static private int REQUEST_CODE = 64;
        +
        +  // We listen to the OnActivityResult event to respond to the user's selection.
        +  @Override
        +  public void onActivityResult(int requestCode, int resultCode,
        +    Intent resultData) {
        +      try {
        +        if (requestCode == REQUEST_CODE &&
        +            resultCode == Activity.RESULT_OK) {
        +
        +            Uri uri = null;
        +
        +            if (resultData != null) {
        +                uri = resultData.getData();
        +
        +                ContentResolver resolver = getContentResolver();
        +
        +                // Before attempting to coerce a file into a MIME type,
        +                // check to see what alternative MIME types are available to
        +                // coerce this file into.
        +                String[] streamTypes =
        +                  resolver.getStreamTypes(uri, "*/*");
        +
        +                AssetFileDescriptor descriptor =
        +                    resolver.openTypedAssetFileDescriptor(
        +                        uri,
        +                        streamTypes[0],
        +                        null);
        +
        +                // Retrieve a stream to the virtual file.
        +                InputStream inputStream = descriptor.createInputStream();
        +            }
        +        }
        +      } catch (Exception ex) {
        +        Log.e("EXCEPTION", "ERROR: ", ex);
        +      }
        +  }
        +
        + +

        + Untuk informasi selengkapnya tentang mengakses file pengguna, lihat + Panduan Storage + Access Frameworks. +

        diff --git a/docs/html-intl/intl/in/about/versions/nougat/index.jd b/docs/html-intl/intl/in/about/versions/nougat/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..212870a183d5e1fcbae3f2607e2114abb83b82fd --- /dev/null +++ b/docs/html-intl/intl/in/about/versions/nougat/index.jd @@ -0,0 +1,110 @@ +page.title=Android 7.0 Nougat +page.tags="androidn","versions" +meta.tags="android n", "nougat", "android 7.0" +fullpage=true +forcelocalnav=true +header.hide=1 +footer.hide=1 +@jd:body + +
        + +
        + + + + +
        +

        Terbaru

        +
        +
        + +
        +

        Videos

        +
        + New Android capabilities and the right way to use them in your apps. +
        + +
        +
        +
        + +
        +

        Sumber Daya

        +
        + Informasi penting guna membantu mempersiapkan aplikasi untuk Android Nougat. +
        + +
        +
        +
        \ No newline at end of file diff --git a/docs/html-intl/intl/in/design/get-started/principles.jd b/docs/html-intl/intl/in/design/get-started/principles.jd index 9aed08e289d6663900396efa51fb022312e99543..2a1d194b0616c27a25255ca70e3f96e0fdd88fa5 100644 --- a/docs/html-intl/intl/in/design/get-started/principles.jd +++ b/docs/html-intl/intl/in/design/get-started/principles.jd @@ -277,7 +277,7 @@ meskipun hanya sesuatu yang sederhana.

        Lakukan pekerjaan yang sulit untuk saya

        -

        Buatlah pemula merasa seperti ahli dengan memungkinkan mereka untuk melakukan hal-hal yang mereka pikir tidak akan bisa. +

        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.

        diff --git a/docs/html-intl/intl/in/design/patterns/navigation.jd b/docs/html-intl/intl/in/design/patterns/navigation.jd index a8afaaa794e0915677db5680be165b968df65073..491570030b5392aac25fe417c050805e1b5e9e41 100644 --- a/docs/html-intl/intl/in/design/patterns/navigation.jd +++ b/docs/html-intl/intl/in/design/patterns/navigation.jd @@ -121,7 +121,7 @@ pemberitahuan tunggal yang mengarahkan pengguna ke layar antara. Layar ini meran kejadian tersebut, dan menyediakan path bagi pengguna untuk menjelajah ke dalam aplikasi. Pemberitahuan dengan gaya seperti ini disebut pemberitahuan tidak langsung.

        -

        Berbeda dengan pemberitahuan standar (langsung), menekan tombol Back dari +

        Berbeda dengan pemberitahuan standar (langsung), menekan tombol Back dari layar antara pada pemberitahuan tidak langsung akan mengembalikan pengguna ke titik pemicu pemberitahuan tersebut—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: @@ -168,7 +168,7 @@ yang akan dibahas di bawah ini.

        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.

        -

        Tugas adalah urutan aktivitas yang diikuti pengguna untuk mencapai tujuan. +

        Tugas 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.

        diff --git a/docs/html-intl/intl/in/guide/components/activities.jd b/docs/html-intl/intl/in/guide/components/activities.jd index 6cac69638f49a6cc37da974ee4debd85ab9d26ba..bbc061cdc8cbb5de451b182b47d8b6274d8645f8 100644 --- a/docs/html-intl/intl/in/guide/components/activities.jd +++ b/docs/html-intl/intl/in/guide/components/activities.jd @@ -53,7 +53,7 @@ jendela lain.

        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 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", @@ -67,7 +67,7 @@ melalui metode callback daur hidupnya. Ada beberapa metode callback yang mungkin diterima aktivitas, karena sebuah perubahan dalam statusnya—apakah sistem sedang membuatnya, menghentikannya, melanjutkannya, atau menghapuskannya—dan masing-masing callback memberi Anda kesempatan melakukan pekerjaan tertentu yang -sesuai untuk perubahan status itu. Misalnya, bila dihentikan, aktivitas Anda harus melepas +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.

        @@ -89,7 +89,7 @@ terpenting adalah:

        {@link android.app.Activity#onCreate onCreate()}
        Anda harus mengimplementasikan metode ini. Sistem memanggilnya saat membuat - aktivitas Anda. Dalam implementasi, Anda harus menginisialisasi komponen-komponen esensial + 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.
        @@ -115,7 +115,7 @@ dalam jendela aktivitas dan bisa merespons interaksi pengguna. Misalnya, sebuah tombol yang mengawali suatu tindakan bila pengguna menyentuhnya.

        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, +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 @@ -124,7 +124,7 @@ layout Anda sendiri dan menerapkannya ke layout aktivitas Anda.

        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 +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 @@ -169,7 +169,7 @@ untuk informasi selengkapnya tentang cara mendeklarasikan aktivitas Anda dalam m

        Elemen {@code <activity>} juga bisa menetapkan berbagai filter intent—dengan menggunakan elemen {@code -<intent-filter>} —untuk mendeklarasikan cara komponen aplikasi lain +<intent-filter>} —untuk mendeklarasikan cara komponen aplikasi lain mengaktifkannya.

        Bila Anda membuat aplikasi baru dengan Android SDK Tools, aktivitas stub @@ -251,7 +251,7 @@ startActivity(intent);

        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" + 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.

        @@ -297,7 +297,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        Contoh ini menunjukkan logika dasar yang harus Anda gunakan dalam metode {@link -android.app.Activity#onActivityResult onActivityResult()} Anda untuk menangani +android.app.Activity#onActivityResult onActivityResult()} Anda untuk menangani hasil aktivitas. Syarat pertama memeriksa apakah permintaan berhasil—jika ya, maka {@code resultCode} akan berupa {@link android.app.Activity#RESULT_OK}—dan apakah permintaan yang direspons hasil ini dikenal—dalam hal ini, {@code requestCode} cocok dengan @@ -602,19 +602,19 @@ tidak berubah. Sebagai gantinya, sistem harus membuat ulang objek {@link android 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 +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()}.

        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 +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 +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 @@ -639,7 +639,7 @@ onPause()}.

        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, +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 @@ -696,7 +696,7 @@ menggunakan aplikasi.

        , 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 +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).

        @@ -722,7 +722,7 @@ Perubahan Runtime.

        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 +Sebagai gantinya, proses akan memulai aktivitas kedua secara tumpang tindih dengan proses penghentian aktivitas pertama.

        Urutan callback daur hidup didefinisikan dengan baik, khususnya bila kedua aktivitas berada dalam diff --git a/docs/html-intl/intl/in/guide/components/bound-services.jd b/docs/html-intl/intl/in/guide/components/bound-services.jd index 5d1f65ed7c8edfe0e61bf16a9a804672319add74..6e5e65a167e8aefeb38b4bfa0ec520af2eb676a7 100644 --- a/docs/html-intl/intl/in/guide/components/bound-services.jd +++ b/docs/html-intl/intl/in/guide/components/bound-services.jd @@ -137,7 +137,7 @@ mendefinisikan {@link android.os.Handler} yang akan merespons aneka tipe objek { 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} +android.os.Message}. Selain itu, klien bisa mendefinisikan sendiri {@link android.os.Messenger} sehingga layanan bisa mengirim balik pesan.

        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 @@ -539,7 +539,7 @@ selengkapnya di bawah ini.)

      Misalnya, cuplikan berikut menghubungkan klien ke layanan yang dibuat di atas dengan -memperluas kelas Binder, sehingga tinggal mengkonversi +memperluas kelas Binder, sehingga tinggal mengkonversi {@link android.os.IBinder} yang dihasilkan ke kelas {@code LocalService} dan meminta instance {@code LocalService}:

      @@ -573,7 +573,7 @@ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        -
      • Parameter pertama {@link android.content.Context#bindService bindService()} adalah sebuah +
      • 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).
      • Parameter kedua adalah objek {@link android.content.ServiceConnection}.
      • diff --git a/docs/html-intl/intl/in/guide/components/fragments.jd b/docs/html-intl/intl/in/guide/components/fragments.jd index 14d4ef3eccbfc404c7ecf4b1ca153f5b589a2a3a..9f7199cd8a0b3eb425e56764e464ae90179ea792 100644 --- a/docs/html-intl/intl/in/guide/components/fragments.jd +++ b/docs/html-intl/intl/in/guide/components/fragments.jd @@ -36,7 +36,7 @@ parent.link=activities.html
      • {@link android.app.FragmentManager}
      • {@link android.app.FragmentTransaction}
    - +

    Lihat juga

    1. Membangun UI Dinamis dengan Fragmen
    2. @@ -47,32 +47,32 @@ dan Handset

    {@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 +{@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).

    -

    Fragmen harus selalu tertanam dalam aktivitas dan daur hidup fragmen secara langsung +

    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 status daur hidup dilanjutkan, Anda bisa -memanipulasi setiap fragmen secara terpisah, seperti menambah atau menghapusnya. Saat melakukan transaksi +aktivitas berjalan (dalam status daur hidup dilanjutkan, 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 -—setiap entri back-stack merupakan record transaksi fragmen yang +—setiap entri back-stack merupakan record transaksi fragmen yang terjadi. Dengan back-stack pengguna dapat membalikkan transaksi fragmen (mengarah mundur), dengan menekan tombol Back.

    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 +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 <fragment>}, 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 + {@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.

    -

    Dokumen ini menjelaskan cara membangun aplikasi menggunakan fragmen, termasuk +

    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.

    @@ -80,45 +80,45 @@ aktivitas, dan lainnya.

    Filosofi Desain

    -

    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 +

    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.

    -

    Misalnya, aplikasi berita bisa menggunakan satu fragmen untuk menampilkan daftar artikel di -sebelah kiri dan fragmen lainnya untuk menampilkan artikel di sebelah kanan—kedua fragmen ini muncul di satu -aktivitas, berdampingan, dan masing-masing fragmen memiliki serangkaian metode callback daur hidup dan menangani kejadian input +

    Misalnya, aplikasi berita bisa menggunakan satu fragmen untuk menampilkan daftar artikel di +sebelah kiri dan fragmen lainnya untuk menampilkan artikel di sebelah kanan—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 +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.

    -

    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 +

    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 +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 +, pada handset, fragmen mungkin perlu dipisahkan untuk menyediakan UI panel tunggal bila lebih dari satu yang tidak cocok dalam aktivitas yang sama.

    Gambar 1. Contoh cara dua modul UI yang didefinisikan oleh - fragmen bisa digabungkan ke dalam satu aktivitas untuk desain tablet, namun dipisahkan untuk + fragmen bisa digabungkan ke dalam satu aktivitas untuk desain tablet, namun dipisahkan untuk desain handset.

    Misalnya—untuk melanjutkan contoh aplikasi berita— aplikasi bisa menanamkan dua fragmen dalam Aktivitas A, saat berjalan pada perangkat berukuran tablet. Akan tetapi, pada -layar berukuran handset, ruang untuk kedua fragmen tidak cukup, sehingga Aktivitas A hanya -menyertakan fragmen untuk daftar artikel, dan saat pengguna memilih artikel, -Aktivitas B akan dimulai, termasuk fragmen kedua untuk membaca artikel. Sehingga, aplikasi mendukung +layar berukuran handset, ruang untuk kedua fragmen tidak cukup, sehingga Aktivitas A hanya +menyertakan fragmen untuk daftar artikel, dan saat pengguna memilih artikel, +Aktivitas B 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.

    -

    Untuk informasi selengkapnya tentang mendesain aplikasi menggunakan kombinasi fragmen berbeda +

    Untuk informasi selengkapnya tentang mendesain aplikasi menggunakan kombinasi fragmen berbeda untuk konfigurasi layar berbeda, lihat panduan untuk Mendukung Tablet dan Handset.

    @@ -131,26 +131,26 @@ untuk konfigurasi layar berbeda, lihat panduan untuk Menangani Daur Hidup Fragmen.

    @@ -171,15 +171,15 @@ android.app.Fragment}:

    {@link android.app.DialogFragment}
    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, +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.
    {@link android.app.ListFragment}
    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 +android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} untuk menangani kejadian klik.
    {@link android.preference.PreferenceFragment}
    @@ -196,7 +196,7 @@ layoutnya sendiri ke aktivitas.

    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 +bila tiba saatnya fragmen menggambar layoutnya. Implementasi Anda atas metode ini harus mengembalikan {@link android.view.View} yang menjadi akar layout fragmen.

    Catatan: Jika fragmen adalah subkelas {@link @@ -205,7 +205,7 @@ android.app.ListFragment}, implementasi default akan mengembalikan {@link androi

    Untuk mengembalikan layout dari {@link android.app.Fragment#onCreateView onCreateView()}, Anda bisa memekarkannya dari sumber daya layout yang didefinisikan di XML. Untuk -membantu melakukannya, {@link android.app.Fragment#onCreateView onCreateView()} menyediakan objek +membantu melakukannya, {@link android.app.Fragment#onCreateView onCreateView()} menyediakan objek {@link android.view.LayoutInflater}.

    Misalnya, ini adalah subkelas {@link android.app.Fragment} yang memuat layout dari file @@ -227,7 +227,7 @@ public static class ExampleFragment extends Fragment {

    Membuat layout

    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 +membuat layout di XML, lihat dokumentasi Antarmuka Pengguna.

    @@ -235,12 +235,12 @@ membuat layout di XML, lihat dokumentasi

    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 +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 Menangani Daur Hidup Fragmen).

    -

    Metode {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} membutuhkan +

    Metode {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} membutuhkan tiga argumen:

    • ID sumber daya layout yang ingin dimekarkan.
    • @@ -260,7 +260,7 @@ fragmen ke aktivitas.

      Menambahkan fragmen ke aktivitas

      -

      Biasanya, fragmen berkontribusi pada sebagian UI ke aktivitas host, yang ditanamkan sebagai +

      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:

      @@ -297,13 +297,13 @@ untuk mengambil setiap fragmen. Sistem akan menyisipkan {@link android.view.View

      Catatan: Setiap fragmen memerlukan identifier -unik yang bisa digunakan sistem untuk memulihkan fragmen jika aktivitas dimulai kembali (dan identifier yang bisa digunakan menangkap +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:

      • Memberikan atribut {@code android:id} bersama ID unik.
      • Memberikan atribut {@code android:tag} bersama string unik.
      • -
      • Jika Anda tidak memberikan dua hal tersebut, sistem akan menggunakan ID +
      • Jika Anda tidak memberikan dua hal tersebut, sistem akan menggunakan ID tampilan kontainer.
      @@ -354,15 +354,15 @@ android.app.FragmentTransaction#add(Fragment,String)} (dengan menyediakan string dalam layout aktivitas, ini tidak akan menerima panggilan ke {@link android.app.Fragment#onCreateView onCreateView()}. Jadi Anda tidak perlu mengimplementasikan metode itu.

      -

      Menyediakan tag string untuk fragmen tidak hanya untuk fragmen non-UI—Anda juga bisa +

      Menyediakan tag string untuk fragmen tidak hanya untuk fragmen non-UI—Anda juga bisa menyediakan tag string untuk fragmen yang memiliki UI—namun jika fragmen tidak memiliki UI -, maka tag string adalah satu-satunya cara untuk mengidentifikasinya. Jika Anda ingin mendapatkan fragmen dari +, 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()}.

      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 +FragmentRetainInstance.java}, yang disertakan dalam sampel SDK (tersedia melalui +Android SDK Manager) dan terletak di sistem Anda sebagai <sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java.

      @@ -378,7 +378,7 @@ mendapatkannya, panggil {@link android.app.Activity#getFragmentManager()} dari a
    • 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).
    • +findFragmentByTag()} (untuk fragmen yang menyediakan atau tidak menyediakan UI).
    • Tarik fragmen dari back-stack, dengan {@link android.app.FragmentManager#popBackStack()} (mensimulasikan perintah Back oleh pengguna).
    • Daftarkan listener untuk perubahan pada back-stack, dengan {@link @@ -395,7 +395,7 @@ menambah dan menghapus fragmen.

      Melakukan Transaksi Fragmen

      -

      Fitur menarik terkait penggunaan fragmen di aktivitas adalah kemampuan menambah, menghapus, mengganti, +

      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 @@ -423,7 +423,7 @@ android.app.FragmentTransaction#addToBackStack addToBackStack()}, untuk menambah ke back-stack dari transaksi fragmen. Back-stack ini dikelola oleh aktivitas dan memungkinkan pengguna kembali ke status fragmen sebelumnya, dengan menekan tombol Back.

      -

      Misalnya, berikut ini cara mengganti satu fragmen dengan yang fragmen yang lain, dan mempertahankan +

      Misalnya, berikut ini cara mengganti satu fragmen dengan yang fragmen yang lain, dan mempertahankan status sebelumnya di back-stack:

      @@ -442,18 +442,18 @@ transaction.commit();
       
       

      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 +android.app.FragmentTransaction#addToBackStack addToBackStack()}, transaksi yang diganti +disimpan ke back-stack sehingga pengguna bisa membalikkan transaksi dan mengembalikan fragmen sebelumnya dengan menekan tombol Back.

      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 +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 Back akan membalikannya semua.

      -

      Urutan menambahkan perubahan pada {@link android.app.FragmentTransaction} tidak berpengaruh, +

      Urutan menambahkan perubahan pada {@link android.app.FragmentTransaction} tidak berpengaruh, kecuali:

      • Anda harus memanggil {@link android.app.FragmentTransaction#commit()} paling akhir
      • @@ -462,9 +462,9 @@ urutan penambahannya akan menentukan urutan munculnya dalam hierarki tampilan

        Jika Anda tidak memanggil {@link android.app.FragmentTransaction#addToBackStack(String) -addToBackStack()} saat melakukan transaksi yang menghapus fragmen, maka fragmen itu +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 +Anda memanggil {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()} saat menghapus fragmen, maka fragmen itu akan dihentikan dan akan dilanjutkan jika pengguna mengarah kembali.

        @@ -473,9 +473,9 @@ transisi, dengan memanggil {@link android.app.FragmentTransaction#setTransition mengikatnya.

        Memanggil {@link android.app.FragmentTransaction#commit()} tidak akan langsung menjalankan -transaksi. Namun sebuah jadwal akan dibuat untuk dijalankan pada thread UI aktivitas (thread "utama") +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 +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.

        @@ -503,7 +503,7 @@ android.app.Fragment#getActivity()} dan dengan mudah melakukan tugas-tugas seper View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
      -

      Demikian pula, aktivitas Anda bisa memanggil metode di fragmen dengan meminta acuan ke +

      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:

      @@ -537,7 +537,7 @@ public static class FragmentA extends ListFragment {

      Selanjutnya aktivitas yang menjadi host fragmen akan mengimplementasikan antarmuka {@code OnArticleSelectedListener} - dan + 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 @@ -564,7 +564,7 @@ public static class FragmentA extends ListFragment {

      Jika aktivitas belum mengimplementasikan antarmuka, maka fragmen akan melontarkan {@link java.lang.ClassCastException}. -Jika berhasil, anggota {@code mListener} yang menyimpan acuan ke implementasi aktivitas +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 @@ -654,7 +654,7 @@ seluruh layar).

      Dihentikan
      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 +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.
      @@ -668,10 +668,10 @@ android.app.Fragment#onActivityCreated onActivityCreated()}. Untuk informasi sel status, lihat dokumen Aktivitas .

      -

      Perbedaan paling signifikan dalam daur hidup antara aktivitas dan fragmen ada +

      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 Back, seperti yang dibahas dalam Tugas dan Back-Stack). +ke aktivitas dengan tombol Back, seperti yang dibahas dalam Tugas dan Back-Stack). 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 @@ -736,7 +736,7 @@ melalui daur hidupnya oleh aktivitas.

      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, +daftar. Aktivitas ini juga menunjukkan cara menyediakan konfigurasi fragmen berbeda, berdasarkan konfigurasi layar.

      Catatan: Kode sumber lengkap untuk aktivitas ini tersedia di @@ -752,7 +752,7 @@ android.app.Activity#onCreate onCreate()}:

      {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} -

      Dengan layout ini, sistem akan membuat instance {@code TitlesFragment} (yang mencantumkan +

      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 @@ -769,14 +769,14 @@ tersimpan di {@code res/layout/fragment_layout.xml}:

      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, +daftar dalam konfigurasi ini, aplikasi akan memulai aktivitas baru untuk menampilkan rangkuman, sebagai ganti pemuatan fragmen kedua.

      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.

      -

      Saat Anda memeriksa kode ini, perhatikan bahwa ada dua kemungkinan perilaku saat pengguna mengklik +

      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).

      @@ -785,11 +785,11 @@ android.widget.FrameLayout}), atau memulai aktivitas baru (tempat fragmen ditamp

      Fragmen kedua, {@code DetailsFragment} menampilkan rangkuman pemutaran untuk item yang dipilih dari daftar dari {@code TitlesFragment}:

      - + {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}

      Ingatlah dari kelas {@code TitlesFragment}, bahwa, jika pengguna mengklik item daftar dan -layout saat ini tidak menyertakan tampilan {@code R.id.details} (yaitu tempat +layout saat ini tidak menyertakan tampilan {@code R.id.details} (yaitu tempat {@code DetailsFragment} berada), maka aplikasi memulai aktivitas {@code DetailsActivity} untuk menampilkan konten item.

      @@ -798,14 +798,14 @@ yang dipilih saat layar dalam orientasi tegak:

      {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details_activity} - +

      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).

      -

      Untuk contoh lainnya mengenai penggunaan fragmen (dan file sumber lengkap untuk contoh ini), +

      Untuk contoh lainnya mengenai penggunaan fragmen (dan file sumber lengkap untuk contoh ini), lihat aplikasi contoh Demo API yang tersedia di ApiDemos (bisa diunduh dari Komponen contoh SDK).

      diff --git a/docs/html-intl/intl/in/guide/components/fundamentals.jd b/docs/html-intl/intl/in/guide/components/fundamentals.jd index bd9a500f77a5c608557ab62134bc7400a24f241c..2c925e98edb0d3a6c70d54d3df44022448fe31f8 100644 --- a/docs/html-intl/intl/in/guide/components/fundamentals.jd +++ b/docs/html-intl/intl/in/guide/components/fundamentals.jd @@ -22,44 +22,44 @@ page.title=Dasar-Dasar Aplikasi
    -

    Aplikasi Android ditulis dalam bahasa pemrograman Java. Android SDK Tools mengkompilasi +

    Aplikasi Android ditulis dalam bahasa pemrograman Java. Android SDK Tools mengkompilasi kode Anda—bersama data dan file sumber daya —ke dalam APK: Paket Android, -yaitu file arsip berekstensi {@code .apk}. Satu file APK berisi semua konten +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.

    Setelah diinstal di perangkat, setiap aplikasi Android tinggal di sandbox keamanannya sendiri:

      -
    • Sistem operasi Android merupakan sistem Linux multi-pengguna yang di dalamnya setiap +
    • Sistem operasi Android merupakan sistem Linux multi-pengguna yang di dalamnya setiap aplikasi adalah pengguna berbeda.
    • 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.
    • -
    • Setiap proses memiliki mesin virtual (VM) sendiri, sehingga kode aplikasi yang berjalan secara terisolasi dari +
    • Setiap proses memiliki mesin virtual (VM) sendiri, sehingga kode aplikasi yang berjalan secara terisolasi dari aplikasi lainnya.
    • -
    • Secara default, setiap aplikasi berjalan dalam proses Linux-nya sendiri. Android memulai proses +
    • 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.
    -

    Dengan cara ini, sistem Android mengimplementasikan prinsip privilese minim. Ini berarti, +

    Dengan cara ini, sistem Android mengimplementasikan prinsip privilese minim. 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 +tidak lebih dari itu. Hal ini menghasilkan lingkungan yang sangat aman sehingga aplikasi tidak bisa mengakses bagian sistem bila tidak diberi izin.

    Akan tetapi, ada beberapa cara bagi aplikasi untuk berbagi data dengan aplikasi lain dan bagi aplikasi untuk mengakses layanan sistem:

      -
    • Dua aplikasi bisa diatur untuk menggunakan ID pengguna Linux yang sama, +
    • 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).
    • -
    • Aplikasi bisa meminta izin akses ke data perangkat seperti kontak -pengguna, pesan SMS, penyimpanan lepas-pasang (kartu SD), kamera, Bluetooth, dan lainnya. Semua +
    • 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.
    @@ -69,7 +69,7 @@ selanjutnya memperkenalkan Anda pada:

  • Komponen kerangka kerja inti yang mendefinisikan aplikasi.
  • File manifes tempat Anda mendeklarasikan komponen dan fitur yang diperlukan perangkat untuk aplikasi.
  • -
  • Sumber daya yang terpisah dari kode aplikasi dan memungkinkan +
  • Sumber daya yang terpisah dari kode aplikasi dan memungkinkan aplikasi mengoptimalkan perilakunya untuk beragam konfigurasi perangkat.
  • @@ -78,8 +78,8 @@ aplikasi mengoptimalkan perilakunya untuk beragam konfigurasi perangkat.

    Komponen Aplikasi

    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 +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—masing-masing merupakan blok pembangun unik yang mendefinisikan perilaku aplikasi secara keseluruhan.

    @@ -93,7 +93,7 @@ dan daur hidupnya sendiri yang mendefinisikan cara komponen dibuat dan dimusnahk
    Aktivitas
    Sebuah aktivitas mewakili satu layar dengan antarmuka pengguna. Misalnya, -aplikasi email mungkin memiliki satu aktivitas yang menampilkan daftar email +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 @@ -110,7 +110,7 @@ tentang hal ini dalam panduan pengembang Layanan.

    Sebuah penyedia konten 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 +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 @@ -137,7 +137,7 @@ penyedia konten untuk menyimpan catatan.

    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 +lain melakukan transaksi. Untuk informasi selengkapnya, lihat panduan pengembang Penyedia Konten.

    @@ -163,7 +163,7 @@ lihat kelas {@link android.content.BroadcastReceiver}.

    -

    Aspek unik dari desain sistem Android adalah aplikasi mana pun bisa memulai +

    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 @@ -175,7 +175,7 @@ kamera seakan menjadi bagian dari aplikasi Anda.

    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. +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()}).

    @@ -198,13 +198,13 @@ atau milik aplikasi lain.

    mengaktifkan komponen tertentu atau komponen tipe komponen tertentu—masing-masing intent bisa eksplisit atau implisit.

    -

    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 +

    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 +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—intent yang dikembalikan menyertakan URI yang +pengguna bisa memilih kontak pribadi dan memintanya dikembalikan kepada Anda—intent yang dikembalikan menyertakan URI yang menunjuk ke kontak yang dipilih).

    Untuk penerima siaran, intent hanya mendefinisikan @@ -213,18 +213,18 @@ hanya menyertakan string tindakan yang menunjukkan "baterai hampir habis").

    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 +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).

    Ada beberapa metode terpisah untuk mengaktifkan masing-masing tipe komponen:

      -
    • Anda bisa memulai aktivitas (atau memberinya pekerjaan baru) dengan +
    • 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).
    • -
    • Anda bisa memulai layanan (atau memberikan instruksi baru ke layanan yang sedang berlangsung) dengan +
    • 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()}.
    • @@ -237,7 +237,7 @@ android.content.ContentProvider#query query()} pada {@link android.content.Conte

    Untuk informasi selengkapnya tentang menggunakan intent, lihat dokumen Intent dan Filter - Intent. Informasi selengkapnya tentang mengaktifkan komponen + Intent. Informasi selengkapnya tentang mengaktifkan komponen tertentu juga tersedia dalam dokumen berikut: Aktivitas, Layanan, {@link android.content.BroadcastReceiver} dan Penyedia Konten.

    @@ -245,7 +245,7 @@ android.content.BroadcastReceiver} dan File Manifes

    Sebelum sistem Android bisa memulai komponen aplikasi, sistem harus mengetahui -keberadaan komponen dengan membaca file {@code AndroidManifest.xml} aplikasi (file +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.

    @@ -258,8 +258,8 @@ akses-baca ke kontak pengguna. minimum yang diperlukan aplikasi, berdasarkan API yang digunakan aplikasi.
  • Mendeklarasikan fitur perangkat keras dan perangkat lunak yang diperlukan aplikasi, seperti kamera, layanan Bluetooth, atau layar multisentuh.
  • -
  • Pustaka API aplikasi perlu ditautkan (selain -API kerangka kerja Android), seperti pustaka +
  • Pustaka API aplikasi perlu ditautkan (selain +API kerangka kerja Android), seperti pustaka Google Maps.
  • Dan lainnya
  • @@ -287,7 +287,7 @@ href="{@docRoot}guide/topics/manifest/application-element.html"><application& aplikasi.

    Dalam elemen <activity>, +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity>, 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.

    @@ -310,12 +310,12 @@ penyedia konten

    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 +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()}.

    -

    Untuk informasi selengkapnya tentang cara menstrukturkan file manifes untuk aplikasi Anda, +

    Untuk informasi selengkapnya tentang cara menstrukturkan file manifes untuk aplikasi Anda, lihat dokumentasi File AndroidManifest.xml.

    @@ -379,7 +379,7 @@ membacanya, namun layanan eksternal seperti Google Play akan membacanya untuk me penyaringan bagi pengguna saat mereka mencari aplikasi dari perangkat.

    Misalnya, jika aplikasi memerlukan kamera dan menggunakan API yang disediakan dalam Android 2.1 (API Level 7) -, Anda harus mendeklarasikannya sebagai kebutuhan dalam file manifes seperti ini:

    +, Anda harus mendeklarasikannya sebagai kebutuhan dalam file manifes seperti ini:

     <manifest ... >
    @@ -390,10 +390,10 @@ penyaringan bagi pengguna saat mereka mencari aplikasi dari perangkat.

    </manifest>
    -

    Sekarang, perangkat yang tidak memiliki kamera dan menggunakan +

    Sekarang, perangkat yang tidak memiliki kamera dan menggunakan Android versi lebih rendah dari 2.1 tidak bisa menginstal aplikasi Anda dari Google Play.

    -

    Akan tetapi, bisa juga mendeklarasikan bahwa aplikasi Anda menggunakan kamera, namun tidak +

    Akan tetapi, bisa juga mendeklarasikan bahwa aplikasi Anda menggunakan kamera, namun tidak mengharuskannya. Dalam hal itu, aplikasi Anda harus mengatur atribut {@code required} ke {@code "false"} dan memeriksa saat runtime apakah perangkat memiliki kamera dan menonaktifkan setiap fitur kamera yang sesuai.

    @@ -455,11 +455,11 @@ membuat sumber daya alternatif untuk konfigurasi perangkat berbeda, bacalah
    Aktivitas
    -
    Informasi tentang cara membuat instance kelas {@link android.app.Activity}, +
    Informasi tentang cara membuat instance kelas {@link android.app.Activity}, yang menyediakan layar tersendiri dalam aplikasi bersama antarmuka pengguna.
    Menyediakan Sumber Daya
    Informasi tentang cara aplikasi Android disusun untuk memisahkan sumber daya aplikasi dari -kode aplikasi, termasuk cara Anda bisa menyediakan sumber daya alternatif untuk +kode aplikasi, termasuk cara Anda bisa menyediakan sumber daya alternatif untuk konfigurasi perangkat tertentu.
    @@ -468,11 +468,11 @@ konfigurasi perangkat tertentu.

    Anda juga mungkin tertarik dengan:

    Kompatibilitas Perangkat
    -
    Informasi tentang cara kerja Android pada berbagai tipe perangkat dan +
    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.
    Izin Sistem
    -
    Informasi tentang cara Android membatasi akses aplikasi pada API tertentu dengan sistem izin +
    Informasi tentang cara Android membatasi akses aplikasi pada API tertentu dengan sistem izin yang mengharuskan persetujuan pengguna agar aplikasi dapat menggunakan API tersebut.
    diff --git a/docs/html-intl/intl/in/guide/components/index.jd b/docs/html-intl/intl/in/guide/components/index.jd index a8dd5f8820fcb038cc7577fb42e7cac5304bc8c8..de40b22d875ecfb24803a6211839b11ab2c51c4b 100644 --- a/docs/html-intl/intl/in/guide/components/index.jd +++ b/docs/html-intl/intl/in/guide/components/index.jd @@ -1,7 +1,7 @@ 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.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 @@ -11,7 +11,7 @@ page.image=images/develop/app_components.png

    Artikel Blog

    - +

    Menggunakan DialogFragments

    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.

    @@ -21,7 +21,7 @@ page.image=images/develop/app_components.png

    Fragmen Untuk Semua

    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.

    - +

    Multithreading untuk Kinerja

    Praktik yang baik dalam membuat aplikasi yang responsif adalah memastikan thread UI utama Anda @@ -32,7 +32,7 @@ ditangani di thread berbeda.

    Pelatihan

    - +

    Mengelola Daur Hidup Aktivitas

    Bagian ini menjelaskan pentingnya metode callback daur hidup yang diterima setiap instance Aktivitas diff --git a/docs/html-intl/intl/in/guide/components/loaders.jd b/docs/html-intl/intl/in/guide/components/loaders.jd index cd0379bf1cd99b5fc97325fad1e8749f07f991d5..88093cc258a4116fa4a9e2679e87d20eff5549fa 100644 --- a/docs/html-intl/intl/in/guide/components/loaders.jd +++ b/docs/html-intl/intl/in/guide/components/loaders.jd @@ -21,14 +21,14 @@ parent.link=activities.html - +

    Kelas-kelas utama

    1. {@link android.app.LoaderManager}
    2. {@link android.content.Loader}
    3. -
    - + +

    Contoh-contoh terkait

    1. @@ -51,7 +51,7 @@ konten berubah.
    2. dibuat kembali setelah perubahan konfigurasi. Karena itu, loader tidak perlu melakukan query ulang datanya. - +

      Rangkuman Loader API

      Ada beberapa kelas dan antarmuka yang mungkin dilibatkan dalam menggunakan @@ -64,11 +64,11 @@ loader pada aplikasi. Semuanya dirangkum dalam tabel ini:

      {@link android.app.LoaderManager} - Kelas abstrak yang dikaitkan dengan {@link android.app.Activity} atau + 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 +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.
      @@ -97,7 +97,7 @@ baru bila konten berubah. {@link android.content.CursorLoader} - Subkelas {@link android.content.AsyncTaskLoader} yang meng-query + 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, @@ -124,15 +124,15 @@ yang menggunakan loader biasanya berisi yang berikut ini:

    3. {@link android.app.Activity} atau {@link android.app.Fragment}.
    4. Instance {@link android.app.LoaderManager}.
    5. {@link android.content.CursorLoader} akan memuat data yang didukung oleh {@link -android.content.ContentProvider}. Atau, Anda dapat mengimplementasikan subkelas sendiri +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.
    6. Implementasi untuk {@link android.app.LoaderManager.LoaderCallbacks}. Di sinilah Anda membuat loader baru dan mengelola acuan bagi loader -yang ada.
    7. +yang ada.
    8. Cara menampilkan data loader, seperti {@link android.widget.SimpleCursorAdapter}.
    9. -
    10. Sumber data, seperti {@link android.content.ContentProvider}, saat menggunakan +
    11. Sumber data, seperti {@link android.content.ContentProvider}, saat menggunakan {@link android.content.CursorLoader}.
    12. Memulai Loader

      @@ -140,11 +140,11 @@ android.widget.SimpleCursorAdapter}.

      {@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.

      +android.app.LoaderManager} per aktivitas atau fragmen.

      Anda biasanya memulai {@link android.content.Loader} dalam metode {@link -android.app.Activity#onCreate onCreate()} aktivitas, atau dalam metode +android.app.Activity#onCreate onCreate()} aktivitas, atau dalam metode {@link android.app.Fragment#onActivityCreated onActivityCreated()} fragmen. Anda melakukannya dengan cara berikut ini:

      @@ -157,13 +157,13 @@ parameter berikut:

      • ID unik yang mengidentifikasi loader. Dalam contoh ini, ID-nya adalah 0.
      • Argumen opsional untuk dipasok ke loader -pada saat pembuatan (dalam contoh ini null).
      • +pada saat pembuatan (dalam contoh ini null).
      • 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}.
      • +ke dirinya sendiri, {@code this}.

      Panggilan {@link android.app.LoaderManager#initLoader initLoader()} memastikan bahwa loader telah dimulai dan aktif. Ia memiliki dua kemungkinan hasil:

      @@ -193,7 +193,7 @@ 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
      LoaderThrottle). +loader, lihat contoh LoaderThrottle). 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 Menggunakan Callback LoaderManager.

      @@ -245,7 +245,7 @@ Membuat instance dan mengembalikan {@link android.content.Loader} baru untuk ID — Dipanggil bila loader yang dibuat sebelumnya selesai dimuat.
        -
      • {@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} +
      • {@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} — Dipanggil bila loader yang dibuat sebelumnya sedang di-reset, sehingga datanya tidak tersedia.
      • @@ -322,7 +322,7 @@ data tersebut karena loader memilikinya dan akan menanganinya.

        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 +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:

        @@ -343,7 +343,7 @@ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

        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.  

        -

        Implementasi ini memanggil +

        Implementasi ini memanggil {@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()} dengan nilai null:

        @@ -366,7 +366,7 @@ public void onLoaderReset(Loader<Cursor> loader) { 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.

        - +

        Agar aplikasi dapat mengakses kontak pengguna, seperti yang ditampilkan dalam contoh ini, manifesnya harus menyertakan izin {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.

        diff --git a/docs/html-intl/intl/in/guide/components/processes-and-threads.jd b/docs/html-intl/intl/in/guide/components/processes-and-threads.jd index 44051bf492e0acf8eba217fc29d482a48cf90a73..cdab715bbca84f536ba375779cebc1b5556f6928 100644 --- a/docs/html-intl/intl/in/guide/components/processes-and-threads.jd +++ b/docs/html-intl/intl/in/guide/components/processes-and-threads.jd @@ -25,13 +25,13 @@ page.tags=daur hidup,latar belakang
    -

    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 +

    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.

    Dokumen ini membahas cara kerja proses dan thread di aplikasi Android.

    @@ -39,7 +39,7 @@ setiap proses.

    Proses

    -

    Secara default, semua komponen aplikasi yang sama berjalan dalam proses yang sama dan kebanyakan +

    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.

    @@ -47,54 +47,54 @@ komponen tertentu, Anda dapat melakukannya dalam file manifes.

    <activity>}, {@code <service>}, {@code <receiver>}, dan {@code -<provider>}—mendukung atribut {@code android:process} yang bisa menetapkan -dalam proses mana komponen harus dijalankan. Anda bisa mengatur atribut ini agar setiap komponen +<provider>}—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 -—sepanjang aplikasi menggunakan ID Linux yang sama dan ditandatangani +—sepanjang aplikasi menggunakan ID Linux yang sama dan ditandatangani dengan sertifikat yang sama.

    Elemen {@code -<application>} juga mendukung atribut {@code android:process}, untuk mengatur +<application>} juga mendukung atribut {@code android:process}, untuk mengatur nilai default yang berlaku bagi semua komponen.

    -

    Android bisa memutuskan untuk mematikan proses pada waktu tertentu, bila memori tinggal sedikit dan diperlukan oleh +

    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 +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.

    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 + 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.

    Daur hidup proses

    -

    Sistem Android mencoba mempertahankan proses aplikasi selama mungkin, namun +

    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 +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.

    -

    Ada lima tingkatan dalam hierarki prioritas. Daftar berikut berisi beberapa -tipe proses berdasarkan urutan prioritas (proses pertama adalah yang terpenting dan +

    Ada lima tingkatan dalam hierarki prioritas. Daftar berikut berisi beberapa +tipe proses berdasarkan urutan prioritas (proses pertama adalah yang terpenting dan dimatikan terakhir):

    1. Proses latar depan -

      Proses yang diperlukan untuk aktivitas yang sedang dilakukan pengguna. Proses +

      Proses yang diperlukan untuk aktivitas yang sedang dilakukan pengguna. Proses dianggap berada di latar depan jika salah satu kondisi berikut terpenuhi:

      • Proses menjadi host {@link android.app.Activity} yang berinteraksi dengan pengguna dengan metode ({@link -android.app.Activity}{@link android.app.Activity#onResume onResume()} telah +android.app.Activity}{@link android.app.Activity#onResume onResume()} telah dipanggil).
      • -
      • Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang sedang berinteraksi dengan +
      • Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang sedang berinteraksi dengan pengguna.
      • Proses menjadi host {@link android.app.Service} yang berjalan "di latar depan"— @@ -108,23 +108,23 @@ onStart()}, atau {@link android.app.Service#onDestroy onDestroy()}).
      • android.content.BroadcastReceiver#onReceive onReceive()}-nya.
      -

      Secara umum, hanya ada beberapa proses latar depan pada waktu yang diberikan. Proses dimatikan hanya sebagai -upaya terakhir— 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 +

      Secara umum, hanya ada beberapa proses latar depan pada waktu yang diberikan. Proses dimatikan hanya sebagai +upaya terakhir— 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.

    2. Proses yang terlihat -

      Proses yang tidak memiliki komponen latar depan, namun masih bisa -memengaruhi apa yang dilihat pengguna di layar. Proses dianggap terlihat jika salah satu kondisi +

      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:

      • 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 +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.
      • -
      • Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang terlihat (atau latar +
      • Proses menjadi host {@link android.app.Service} yang terikat dengan aktivitas yang terlihat (atau latar depan)
      @@ -134,53 +134,53 @@ diperlukan agar semua proses latar depan tetap berjalan.

    3. Proses layanan

      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 +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.

    4. Proses latar belakang -

      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 +

      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 + 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 Aktivitas untuk mendapatkan informasi tentang menyimpan dan memulihkan status.

    5. Proses kosong -

      Sebuah proses yang tidak berisi komponen aplikasi aktif apa pun. Alasan satu-satunya mempertahankan proses +

      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 +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.

    Android sebisa mungkin memeringkat proses setinggi -mungkin, berdasarkan prioritas komponen yang sedang aktif dalam proses. Misalnya, jika suatu proses menjadi host sebuah layanan dan +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.

    Selain itu, peringkat proses dapat meningkat karena adanya proses lain yang bergantung padanya -—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 +—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.

    -

    Karena proses yang menjalankan layanan diperingkat lebih tinggi daripada aktivitas latar belakang, -aktivitas yang memulai operasi yang berjalan lama mungkin lebih baik memulai layanan untuk operasi itu, daripada hanya +

    Karena proses yang menjalankan layanan diperingkat lebih tinggi daripada aktivitas latar belakang, +aktivitas yang memulai operasi yang berjalan lama mungkin lebih baik memulai layanan untuk operasi itu, daripada hanya membuat thread pekerja—khususnya jika operasi mungkin akan berlangsung lebih lama daripada aktivitas. - Misalnya, aktivitas yang mengunggah gambar ke situs web harus memulai layanan + 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 +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.

    @@ -188,35 +188,35 @@ menjalankan layanan daripada hanya menempatkan operasi yang menghabiskan waktu d

    Thread

    -

    Bila aplikasi diluncurkan, sistem akan membuat thread eksekusi untuk aplikasi tersebut, yang diberi nama, +

    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 +android.widget} dan {@link android.view}). Karena itu, thread 'main' juga terkadang disebut thread UI.

    -

    Sistem ini tidak 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 +

    Sistem ini tidak 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.

    -

    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 +

    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.

    -

    Saat aplikasi melakukan pekerjaan intensif sebagai respons terhadap interaksi pengguna, model +

    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 +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 "aplikasi tidak -merespons" (ANR) yang populer karena reputasi buruknya. Pengguna nanti bisa memutuskan untuk keluar dari aplikasi dan menghapus aplikasi +merespons" (ANR) yang populer karena reputasi buruknya. Pengguna nanti bisa memutuskan untuk keluar dari aplikasi dan menghapus aplikasi jika mereka tidak suka.

    -

    Selain itu, toolkit Android UI bukan thread-safe. Jadi, Anda tidak harus memanipulasi +

    Selain itu, toolkit Android UI bukan thread-safe. Jadi, Anda tidak harus memanipulasi UI dari thread pekerja—Anda harus melakukan semua manipulasi pada antarmuka pengguna dari thread UI. Sehingga hanya ada dua aturan untuk model thread tunggal Android:

    @@ -227,12 +227,12 @@ UI. Sehingga hanya ada dua aturan untuk model thread tunggal Android:

    Thread pekerja

    -

    Karena model thread tunggal yang dijelaskan di atas, Anda dilarang memblokir thread +

    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").

    -

    Misalnya, berikut ini beberapa kode untuk listener klik yang mengunduh gambar dari +

    Misalnya, berikut ini beberapa kode untuk listener klik yang mengunduh gambar dari thread terpisah dan menampilkannya dalam {@link android.widget.ImageView}:

    @@ -246,13 +246,13 @@ public void onClick(View v) {
     }
     
    -

    Awalnya hal ini tampak bekerja dengan baik, karena menciptakan thread baru untuk menangani +

    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: jangan mengakses toolkit Android UI dari luar thread UI—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.

    -

    Untuk memperbaiki masalah ini, Android menawarkan beberapa cara untuk mengakses thread UI dari +

    Untuk memperbaiki masalah ini, Android menawarkan beberapa cara untuk mengakses thread UI dari thread lainnya. Berikut ini daftar metode yang bisa membantu:

      @@ -284,10 +284,10 @@ public void onClick(View v) {

      Kini implementasi ini thread-safe: operasi jaringan dilakukan terpisah dari thread sementara {@link android.widget.ImageView} dimanipulasi dari thread UI.

      -

      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 +

      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}, + 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.

      @@ -298,10 +298,10 @@ pengguna. AsyncTask memblokir operasi di thread pekerja kemudian mempublikasikan di thread UI, tanpa mengharuskan Anda untuk menangani sendiri thread dan/atau handler sendiri.

      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 +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 +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.

      @@ -319,7 +319,7 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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) { @@ -328,16 +328,16 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { } -

      Kini UI aman dan kode jadi lebih sederhana, karena memisahkan pekerjaan ke +

      Kini UI aman dan kode jadi lebih sederhana, karena memisahkan pekerjaan ke dalam bagian-bagian yang harus dilakukan pada thread pekerja dan thread UI.

      -

      Anda harus membaca acuan {@link android.os.AsyncTask} untuk memahami sepenuhnya +

      Anda harus membaca acuan {@link android.os.AsyncTask} untuk memahami sepenuhnya cara menggunakan kelas ini, namun berikut ini ikhtisar singkat cara kerjanya:

      • Anda bisa menetapkan tipe parameter, nilai kemajuan, dan nilai akhir tugas, dengan menggunakan generik
      • -
      • Metode {@link android.os.AsyncTask#doInBackground doInBackground()} berjalan secara otomatis pada +
      • Metode {@link android.os.AsyncTask#doInBackground doInBackground()} berjalan secara otomatis pada thread pekerja
      • {@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link android.os.AsyncTask#onPostExecute onPostExecute()}, dan {@link @@ -352,23 +352,23 @@ android.os.AsyncTask#onProgressUpdate onProgressUpdate()} pada thread UI
      • Perhatian: Masalah lain yang mungkin Anda temui saat menggunakan thread pekerja adalah restart tak terduga dalam aktivitas karena perubahan konfigurasi runtime - (seperti saat pengguna mengubah orientasi layar), yang bisa memusnahkan thread pekerja. Untuk -melihat cara mempertahankan tugas selama restart ini dan cara membatalkan + (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 Shelves.

        Metode thread-safe

        -

        Dalam beberapa situasi, metode yang Anda implementasikan bisa dipanggil dari lebih dari satu thread, +

        Dalam beberapa situasi, metode yang Anda implementasikan bisa dipanggil dari lebih dari satu thread, dan karena itu harus ditulis agar menjadi thread-safe.

        -

        Ini terutama terjadi untuk metode yang bisa dipanggil dari jauh —seperti metode dalam layanan terikat. Bila sebuah panggilan pada -metode yang dijalankan dalam {@link android.os.IBinder} berasal dari proses yang sama di mana +

        Ini terutama terjadi untuk metode yang bisa dipanggil dari jauh —seperti metode dalam layanan terikat. 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 +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 @@ -382,19 +382,19 @@ android.content.ContentProvider} yang merespons permintaan itu—metode {@li 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()}— dipanggil dari pool thread pada proses penyedia konten, bukan thread UI -untuk proses tersebut. Mengingat metode ini bisa dipanggil dari thread mana pun +getType()}— 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.

        Komunikasi Antarproses

        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 + (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 +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.

        diff --git a/docs/html-intl/intl/in/guide/components/recents.jd b/docs/html-intl/intl/in/guide/components/recents.jd index dcfcda7a7d5f9d64e41b392a2eacf7607577f100..286fdc12732ebc74908f5c8a946df759517c60b3 100644 --- a/docs/html-intl/intl/in/guide/components/recents.jd +++ b/docs/html-intl/intl/in/guide/components/recents.jd @@ -60,23 +60,23 @@ layar ikhtisar. Selain itu, atribut Menambahkan Tugas ke Layar Ikhtisar

        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 +atas waktu dan cara dokumen dibuka atau dibuka kembali di layar ikhtisar. Bila menggunakan atribut <activity> -, Anda dapat memilih antara selalu membuka dokumen dalam tugas baru atau menggunakan kembali tugas +, Anda dapat memilih antara selalu membuka dokumen dalam tugas baru atau menggunakan kembali tugas yang ada untuk dokumen tersebut.

        Menggunakan flag Intent untuk menambahkan tugas

        -

        Bila membuat dokumen baru untuk aktivitas, Anda memanggil metode +

        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 + 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} +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.

        Catatan: Flag {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} -menggantikan flag {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET}, +menggantikan flag {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET}, yang tidak digunakan lagi pada Android 5.0 (API level 21).

        Jika Anda menetapkan flag {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} saat membuat @@ -169,18 +169,18 @@ bila pengguna membuka dokumen dengan aplikasi:

        "{@code none”}"
        Aktivitas ini tidak membuat tugas baru untuk dokumen. Layar ikhtisar memperlakukan - aktivitas seperti itu secara default: satu tugas ditampilkan untuk aplikasi, yang + aktivitas seperti itu secara default: satu tugas ditampilkan untuk aplikasi, yang dilanjutkan dari aktivitas apa pun yang terakhir dipanggil pengguna.
        "{@code never}"
        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 + 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.
        -

        Catatan: Untuk nilai selain {@code none} dan {@code never}, +

        Catatan: 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.

        @@ -219,8 +219,8 @@ public void onRemoveFromRecents(View view) {

        Catatan: Penggunaan metode -{@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()} -akan mengesampingkan penggunaan tag {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS}, seperti +{@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.

        Mempertahankan tugas yang telah selesai

        diff --git a/docs/html-intl/intl/in/guide/components/services.jd b/docs/html-intl/intl/in/guide/components/services.jd index 7ecd8cd38db9295c6d432de4a973dae6ef6e6877..b36e5656b0eaab3ce901a6465d68fa997b265a47 100644 --- a/docs/html-intl/intl/in/guide/components/services.jd +++ b/docs/html-intl/intl/in/guide/components/services.jd @@ -186,7 +186,7 @@ dari komponen aplikasi lain.

        aplikasi Anda.

        Untuk mendeklarasikan layanan Anda, tambahkan sebuah elemen {@code <service>} -sebagai anak +sebagai anak elemen {@code <application>}. Misalnya:

        @@ -539,7 +539,7 @@ layanan tersebut harus berhenti sendiri dengan memanggil {@link android.app.Serv
         komponen lain bisa menghentikannya dengan memanggil {@link android.content.Context#stopService stopService()}.

        Setelah diminta untuk berhenti dengan {@link android.app.Service#stopSelf stopSelf()} atau {@link -android.content.Context#stopService stopService()}, sistem akan menghapus layanan +android.content.Context#stopService stopService()}, sistem akan menghapus layanan secepatnya.

        Akan tetapi, bila layanan Anda menangani beberapa permintaan ke {@link diff --git a/docs/html-intl/intl/in/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/in/guide/components/tasks-and-back-stack.jd index 279442f2ab381e511ecedbd383718e71ddfdfb2f..4c344ae126aec338f5f1269b66e779418c8ee4e8 100644 --- a/docs/html-intl/intl/in/guide/components/tasks-and-back-stack.jd +++ b/docs/html-intl/intl/in/guide/components/tasks-and-back-stack.jd @@ -29,7 +29,7 @@ parent.link=activities.html

        1. Desain Android: Navigasi
        2. -
        3. Elemen manifes +
        4. Elemen manifes {@code <activity>}
        5. Layar Ikhtisar
        @@ -52,7 +52,7 @@ dikirim, aktivitas Anda akan dilanjutkan dan seolah-olah aktivitas email adalah aktivitas mungkin dari aplikasi yang berbeda, Android akan tetap mempertahankan pengalaman pengguna yang mulus dengan menjalankan kedua aktivitas dalam tugas yang sama.

        -

        Tugas adalah kumpulan aktivitas yang berinteraksi dengan pengguna +

        Tugas adalah kumpulan aktivitas yang berinteraksi dengan pengguna saat melakukan pekerjaan tertentu. Aktivitas tersebut diatur dalam tumpukan (back-stack), dalam urutan membuka setiap aktivitas.

        @@ -93,7 +93,7 @@ tidak pernah disusun ulang, hanya didorong dan dikeluarkan dari back-stack&mdash aktivitas saat ini dan dikeluarkan bila pengguna meninggalkannya menggunakan tombol Back. 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 +ini dengan jangka waktu yang menunjukkan kemajuan antar aktivitas beserta back-stack pada setiap waktu.

        @@ -148,7 +148,7 @@ pengguna untuk memulai aktivitas tertentu dari lebih dari satu aktivitas, instan 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 Back, setiap instance aktivitas ini akan ditampilkan dalam urutan saat +menggunakan tombol Back, 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 Mengelola Tugas.

        @@ -347,7 +347,7 @@ aktivitas apa pun yang dimulai dengan ini akan dibuka di tugas yang terpisah.{@code <activity>}. Ini berarti bahwa jika aplikasi Anda mengeluarkan intent untuk membuka Browser Android, aktivitasnya tidak akan ditempatkan dalam tugas -yang sama seperti aplikasi Anda. Sebagai gantinya, tugas baru akan dimulai untuk Browser atau, jika Browser +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.

        @@ -387,13 +387,13 @@ adalah:

        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()}. -

        Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTask"} {@code launchMode} +

        Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTask"} {@code launchMode} yang dibahas di bagian sebelumnya.

        {@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}
        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. -

        Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTop"} {@code launchMode} +

        Ini menghasilkan perilaku yang sama dengan nilai {@code "singleTop"} {@code launchMode} yang dibahas di bagian sebelumnya.

        {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}
        Jika aktivitas yang dimulai sudah berjalan dalam tugas saat ini, maka sebagai @@ -427,8 +427,8 @@ 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.

        -

        Anda bisa memodifikasi afinitas untuk setiap yang diberikan -dengan atribut {@code taskAffinity} +

        Anda bisa memodifikasi afinitas untuk setiap yang diberikan +dengan atribut {@code taskAffinity} elemen {@code <activity>}.

        Atribut {@code taskAffinity} @@ -444,7 +444,7 @@ tugas default untuk aplikasi.

        {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} . -

        Aktivitas baru, secara default, diluncurkan ke dalam tugas aktivitas +

        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()} @@ -473,7 +473,7 @@ dimilikinya, bila tugas tersebut di bawa ke latar depan.

        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, +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.

      @@ -497,7 +497,7 @@ apa yang mereka kerjakan sebelum dan kembali ke tugas itu untuk memulai sesuatu
      alwaysRetainTaskState
      -
      Jika atribut ini ditetapkan ke {@code "true"} dalam aktivitas akar tugas, +
      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.
      @@ -516,7 +516,7 @@ href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTask
      Atribut ini seperti {@code clearTaskOnLaunch}, 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"}, +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.
      @@ -552,14 +552,14 @@ pembuka yang menandai aktivitas selalu memulai tugas, {@code "singleTask"} d {@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 +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 Home. 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.

      -

      Untuk kasus-kasus di mana Anda tidak ingin pengguna bisa kembali ke aktivitas, atur dalam +

      Untuk kasus-kasus di mana Anda tidak ingin pengguna bisa kembali ke aktivitas, atur dalam <activity> - pada + pada {@code finishOnTaskLaunch} elemen ke {@code "true"} (lihat Menghapus back-stack).

      diff --git a/docs/html-intl/intl/in/guide/platform/j8-jack.jd b/docs/html-intl/intl/in/guide/platform/j8-jack.jd new file mode 100644 index 0000000000000000000000000000000000000000..4389184459029085ede569f99b8ba6b568fca8e9 --- /dev/null +++ b/docs/html-intl/intl/in/guide/platform/j8-jack.jd @@ -0,0 +1,197 @@ +page.title=Fitur Bahasa Java 8 +page.keywords="android N", "Java 8", "Jack" +@jd:body + + + +

      Android N memperkenalkan dukungan untuk fitur bahasa Java 8 + yang bisa Anda gunakan saat mengembangkan aplikasi yang menargetkan Android N. + Halaman ini menjelaskan fitur bahasa baru yang didukung dalam Android N + Preview, cara menyiapkan proyek Anda dengan benar untuk menggunakannya, dan setiap masalah + yang diketahui yang mungkin Anda temui. +

      + +

      Untuk mulai menggunakan fitur-fitur ini, Anda perlu mengunduh dan menyiapkan Android +Studio 2.1 dan Android N Preview SDK, yang menyertakan +Jack toolchain yang diperlukan dan Plugin Android untuk Gradle yang telah diperbarui. Jika Anda belum +memasang Android N Preview SDK, lihat Menyiapkan Pengembangan untuk Android N.

      + + + +

      + Catatan: Menggunakan fitur bahasa Java 8 yang baru bukanlah + persyaratan untuk mengembangkan aplikasi yang menargetkan platform Android N. Jika Anda + tidak ingin menulis kode dengan fitur bahasa Java 8, Anda bisa membiarkan nilai kompatibilitas + sumber dan target proyek disetel ke Java 7, namun Anda tetap harus + mengompilasi dengan JDK 8 untuk membangun pada platform Android N. +

      + +

      + API dan Fitur Bahasa Java 8 yang Didukung +

      + +

      + Saat ini tidak semua fitur bahasa Java 8 didukung Android. Akan tetapi, + fitur berikut sekarang tersedia saat mengembangkan aplikasi yang menargetkan + Android N Preview: +

      + + + +

      + Catatan: Untuk menguji ekspresi lambda dan referensi metode pada + Android versi sebelumnya, bukalah file {@code build.gradle} + Anda, serta setel {@code compileSdkVersion} dan {@code targetSdkVersion} ke 23 atau + yang lebih rendah. Anda tetap perlu mengaktifkan Jack + toolchain untuk menggunakan fitur Java 8 ini. +

      + +

      + Selain itu, API fitur bahasa Java 8 berikut ini sekarang tersedia: +

      + + + +

      + Mengaktifkan Fitur Java 8 dan Jack Toolchain +

      + +

      + Agar dapat menggunakan fitur bahasa Java 8 yang baru, Anda juga perlu menggunakan + Jack toolchain yang baru. Toolchain Android + yang baru ini mengompilasi sumber bahasa Java menjadi dex + bytecode yang bisa dibaca Android, memiliki format pustaka {@code .jack} sendiri, dan menyediakan sebagian besar fitur toolchain + sebagai bagian dari alat bantu tunggal: pengemasan ulang, penciutan, pengaburan, dan + multidex. +

      + +

      Inilah perbandingan dua toolchain yang digunakan untuk membangun file Android DEX:

      +
        +
      • Toolchain javac lawas:
        + javac ({@code .java} --> {@code .class}) --> dx ({@code + .class} --> {@code .dex}) +
      • + +
      • Jack Toolchain baru:
        + Jack ({@code .java} --> {@code .jack} --> {@code .dex}) +
      • +
      + +

      + Mengonfigurasi Gradle +

      + +

      + Untuk mengaktifkan fitur bahasa Java 8 dan Jack bagi proyek Anda, masukkan + yang berikut dalam file {@code build.gradle} level modul Anda: +

      + +
      +android {
      +  ...
      +  defaultConfig {
      +    ...
      +    jackOptions {
      +      enabled true
      +    }
      +  }
      +  compileOptions {
      +    sourceCompatibility JavaVersion.VERSION_1_8
      +    targetCompatibility JavaVersion.VERSION_1_8
      +  }
      +}
      +
      + +

      + Masalah yang Diketahui +

      + +

      + Instant + Run saat ini tidak berfungsi pada Jack dan akan dinonaktifkan saat menggunakan + toolchain baru. +

      + +

      Karena Jack tidak menghasilkan file kelas antara saat mengompilasi sebuah +aplikasi, alat yang bergantung pada file-file ini sekarang tidak berfungsi pada Jack. Beberapa +contoh alat ini adalah:

      + +
        +
      • Pendeteksi lint yang beroperasi pada file kelas +
      • + +
      • Alat dan pustaka yang mewajibkan file kelas aplikasi (misalnya +pengujian instrumentasi dengan JaCoCo) +
      • +
      + +

      Jika Anda menemukan masalah lain saat menggunakan Jack, laporkan bug.

      \ No newline at end of file diff --git a/docs/html-intl/intl/in/guide/topics/manifest/manifest-intro.jd b/docs/html-intl/intl/in/guide/topics/manifest/manifest-intro.jd index 6d6a3ad252db41075c066ae1caf082cf34b2a17c..050abf47da02b5993f6a02f90415b66f04943fd5 100644 --- a/docs/html-intl/intl/in/guide/topics/manifest/manifest-intro.jd +++ b/docs/html-intl/intl/in/guide/topics/manifest/manifest-intro.jd @@ -23,7 +23,7 @@ page.title=Manifes Aplikasi Setiap aplikasi harus memiliki file AndroidManifest.xml (bernama persis seperti ini) di direktori akar. File manifes menyediakan informasi penting tentang aplikasi ke sistem Android, - informasi yang harus dimiliki sistem agar bisa menjalankan setiap kode + informasi yang harus dimiliki sistem agar bisa menjalankan setiap kode aplikasi. Di antaranya, manifes melakukan hal berikut ini:

      @@ -32,26 +32,26 @@ aplikasi. Di antaranya, manifes melakukan hal berikut ini: Nama paket berfungsi sebagai identifier unik untuk aplikasi.
    • Menjelaskan berbagai komponen aplikasi—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 + 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.
    • -
    • Menentukan proses yang akan menjadi host komponen aplikasi.
    • +
    • Menentukan proses yang akan menjadi host komponen aplikasi.
    • -
    • Mendeklarasikan izin aplikasi mana yang harus dimiliki untuk -mengakses bagian yang dilindungi pada API dan berinteraksi dengan aplikasi lain.
    • +
    • Mendeklarasikan izin aplikasi mana yang harus dimiliki untuk +mengakses bagian yang dilindungi pada API dan berinteraksi dengan aplikasi lain.
    • -
    • Juga mendeklarasikan izin lain yang harus dimiliki untuk +
    • Juga mendeklarasikan izin lain yang harus dimiliki untuk untuk berinteraksi dengan komponen aplikasi.
    • -
    • Mencantumkan daftar kelas {@link android.app.Instrumentation} yang memberikan -profil dan informasi lain saat aplikasi berjalan. Deklarasi ini +
    • 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.
    • -
    • Mendeklarasikan tingkat minimum API Android yang diperlukan +
    • Mendeklarasikan tingkat minimum API Android yang diperlukan aplikasi.
    • Mencantumkan daftar pustaka yang harus ditautkan aplikasi.
    • @@ -61,12 +61,12 @@ aplikasi.

      Struktur File Manifes

      -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. +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.

      @@ -126,9 +126,9 @@ elemen lainnya.
       

      -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. +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.

      @@ -158,74 +158,74 @@ menambahkan elemen atau atribut sendiri.

      - +

      Konvensi File

      -Sebagian konvensi dan aturan berlaku secara umum untuk semua elemen +Sebagian konvensi dan aturan berlaku secara umum untuk semua elemen dan atribut di manifes:

      Elemen
      -
      Hanya elemen +
      Hanya elemen <manifest> dan -<application> -yang diwajibkan, masing-masing harus ada dan hanya boleh terjadi sekali. -Umumnya elemen lain bisa terjadi berkali-kali atau sama sekali tidak terjadi — meskipun -setidaknya sebagian dari elemen itu harus ada untuk agar manifes mencapai sesuatu yang +<application> +yang diwajibkan, masing-masing harus ada dan hanya boleh terjadi sekali. +Umumnya elemen lain bisa terjadi berkali-kali atau sama sekali tidak terjadi — meskipun +setidaknya sebagian dari elemen itu harus ada untuk agar manifes mencapai sesuatu yang berarti.

      -Jika elemen tidak berisi apa pun, berarti elemen itu berisi elemen lain. +Jika elemen tidak berisi apa pun, berarti elemen itu berisi elemen lain. Semua nilai diatur melalui atribut, bukan sebagai data karakter dalam elemen.

      -Elemen yang sama tingkatan umumnya tidak diurutkan. Misalnya, elemen -<activity>, -<provider>, dan -<service> -bisa dicampur dalam urutan apa pun. (Elemen +Elemen yang sama tingkatan umumnya tidak diurutkan. Misalnya, elemen +<activity>, +<provider>, dan +<service> +bisa dicampur dalam urutan apa pun. (Elemen <activity-alias> - merupakan eksepsi untuk aturan ini: Elemen ini harus mengikuti -<activity> + merupakan eksepsi untuk aturan ini: Elemen ini harus mengikuti +<activity> ini aliasnya.)

      Atribut
      -
      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 +
      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. -

      Selain untuk beberapa atribut elemen akar +

      Selain untuk beberapa atribut elemen akar <manifest>, - semua nama atribut dimulai dengan awalan {@code android:} — -misalnya, {@code android:alwaysRetainTaskState}. Karena awalan ini universal, dokumentasi umumnya meniadakannya saat mengacu atribut + semua nama atribut dimulai dengan awalan {@code android:} — +misalnya, {@code android:alwaysRetainTaskState}. Karena awalan ini universal, dokumentasi umumnya meniadakannya saat mengacu atribut dengan nama.

      Mendeklarasikan nama kelas
      -
      Banyak elemen berhubungan dengan objek Java, termasuk elemen -aplikasi itu sendiri (elemen -<application> -) dan aktivitas komponen — utamanya -(<activity>), -layanan -(<service>), -penerima siaran -(<receiver>), -dan penyedia konten -(<provider>). +
      Banyak elemen berhubungan dengan objek Java, termasuk elemen +aplikasi itu sendiri (elemen +<application> +) dan aktivitas komponen — utamanya +(<activity>), +layanan +(<service>), +penerima siaran +(<receiver>), +dan penyedia konten +(<provider>).

      -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. +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:

      @@ -239,12 +239,12 @@ Misalnya, subkelas {@link android.app.Service} mungkin dideklarasikan sebagai be </manifest>

      -Akan tetapi, sebagai shorthand, jika karakter pertama string adalah titik, -string akan ditambahkan ke nama paket aplikasi (seperti yang ditetapkan dalam elemen -<manifest> - melalui atribut +Akan tetapi, sebagai shorthand, jika karakter pertama string adalah titik, +string akan ditambahkan ke nama paket aplikasi (seperti yang ditetapkan dalam elemen +<manifest> + melalui atribut package -). Penetapan berikut sama dengan di atas: +). Penetapan berikut sama dengan di atas:

      <manifest package="com.example.project" . . . >
      @@ -257,13 +257,13 @@ string akan ditambahkan ke nama paket aplikasi (seperti yang ditetapkan dalam el
       </manifest>

      -Saat memulai komponen, Android akan membuat instance subkelas yang diberi nama. +Saat memulai komponen, Android akan membuat instance subkelas yang diberi nama. Jika subkelas tidak ditetapkan, maka akak dibuat instance kelas dasar.

      Banyak nilai
      -
      Jika lebih dari satu nilai yang dapat ditetapkan, elemen ini hampir selalu -diulangi, bukan menampilkan daftar banyak nilai dalam satu elemen. +
      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:
      <intent-filter . . . >
      @@ -275,23 +275,23 @@ Misalnya, filter intent dapat mencantumkan beberapa tindakan:
       
       
      Nilai sumber daya
      Beberapa atribut memiliki nilai yang bisa ditampilkan kepada pengguna — misalnya -, label dan ikon aktivitas. Nilai atribut ini -harus dilokalkan dan karenanya ditetapkan dari sumber daya atau tema. Nilai sumber +, label dan ikon aktivitas. Nilai atribut ini +harus dilokalkan dan karenanya ditetapkan dari sumber daya atau tema. Nilai sumber daya dinyatakan dalam format berikut,

      {@code @[package:]type:name}

      -dalam hal ini nama package boleh dihilangkan jika sumber daya ada dalam paket yang sama dengan -dengan aplikasi, type adalah tipe sumber daya — seperti "string" atau -"drawable" — dan name adalah nama yang mengidentifikasi sumber daya tertentu. +dalam hal ini nama package boleh dihilangkan jika sumber daya ada dalam paket yang sama dengan +dengan aplikasi, type adalah tipe sumber daya — seperti "string" atau +"drawable" — dan name adalah nama yang mengidentifikasi sumber daya tertentu. Misalnya:

      <activity android:icon="@drawable/smallPic" . . . >

      -Nilai tema diekspresikan dengan cara yang sama, namun dengan awal '{@code ?}' +Nilai tema diekspresikan dengan cara yang sama, namun dengan awal '{@code ?}' dan bukan '{@code @}':

      @@ -299,8 +299,8 @@ dan bukan '{@code @}':

      Nilai-nilai string
      -
      Bila nilai atribut adalah string, dua garis miring kiri ('{@code \\}') -harus digunakan untuk meninggalkan karakter — misalnya, '{@code \\n}' untuk +
      Bila nilai atribut adalah string, dua garis miring kiri ('{@code \\}') +harus digunakan untuk meninggalkan karakter — misalnya, '{@code \\n}' untuk baris baru atau '{@code \\uxxxx}' untuk karakter Unicode.
      @@ -308,7 +308,7 @@ baris baru atau '{@code \\uxxxx}' untuk karakter Unicode.

      Fitur File

      -Bagian berikut menjelaskan cara menerapkan sebagian fitur Android +Bagian berikut menjelaskan cara menerapkan sebagian fitur Android dalam file manifest.

      @@ -316,37 +316,37 @@ dalam file manifest.

      Filter Intent

      -Komponen inti dari aplikasi (aktivitasnya, layanannya, dan penerima -siaran) diaktifkan oleh intent. Intent adalah -sekumpulan informasi (objek {@link android.content.Intent}) yang menjelaskan -tindakan yang diinginkan — 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 +Komponen inti dari aplikasi (aktivitasnya, layanannya, dan penerima +siaran) diaktifkan oleh intent. Intent adalah +sekumpulan informasi (objek {@link android.content.Intent}) yang menjelaskan +tindakan yang diinginkan — 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.

      -Komponen mengiklankan kemampuannya — jenis intent yang bisa diresponsnya - — melalui filter intent. Karena sistem Android -harus mempelajari intent yang dapat ditangani komponen sebelum meluncurkan komponen, -filter intent ditetapkan dalam manifes sebagai elemen +Komponen mengiklankan kemampuannya — jenis intent yang bisa diresponsnya + — melalui filter intent. Karena sistem Android +harus mempelajari intent yang dapat ditangani komponen sebelum meluncurkan komponen, +filter intent ditetapkan dalam manifes sebagai elemen <intent-filter> -. Sebuah komponen dapat memiliki filter dalam jumlah berapa saja, masing-masing menjelaskan +. Sebuah komponen dapat memiliki filter dalam jumlah berapa saja, masing-masing menjelaskan kemampuan yang berbeda.

      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 +filter tidak berperan. Namun intent yang tidak menetapkan target +dengan nama dapat mengaktifkan komponen hanya jika dapat melewati salah satu filter komponen.

      -Untuk informasi tentang cara objek Intent diuji terhadap filter intent, -lihat dokumen terpisah, -Intent +Untuk informasi tentang cara objek Intent diuji terhadap filter intent, +lihat dokumen terpisah, +Intent dan Filter Intent.

      @@ -354,42 +354,42 @@ dan Filter Intent.

      Ikon dan Label

      -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 +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 <permission> - 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 + 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.

      -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 -<application> -adalah ikon dan label default untuk setiap komponen aplikasi. -Demikian pula, ikon dan label yang ditetapkan untuk komponen — misalnya, elemen -<activity> -— adalah pengaturan default untuk setiap elemen komponen +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 +<application> +adalah ikon dan label default untuk setiap komponen aplikasi. +Demikian pula, ikon dan label yang ditetapkan untuk komponen — misalnya, elemen +<activity> +— adalah pengaturan default untuk setiap elemen komponen <intent-filter> -. Jika elemen -<application> -menetapkan label, namun suatu aktivitas dan filter intent-nya tidak menetapkan label, -maka label aplikasi akan dianggap sama-sama sebagai label aktvitas dan +. Jika elemen +<application> +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.

      -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—, yaitu -sebagai salah satu aktivitas yang harus ditampilkan dalam launcher aplikasi. Ikon dan label yang +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—, 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.

      @@ -397,14 +397,14 @@ diatur dalam filter karenanya adalah ikon dan label yang ditampilkan dalam launc

      Izin

      -Sebuah izin 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. +Sebuah izin 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.

      -Setiap izin diidentifikasi melalui label yang unik. Sering kali, label menunjukkan -tindakan yang dibatasi. Misalnya, berikut ini adalah beberapa izin yang didefinisikan +Setiap izin diidentifikasi melalui label yang unik. Sering kali, label menunjukkan +tindakan yang dibatasi. Misalnya, berikut ini adalah beberapa izin yang didefinisikan oleh Android:

      @@ -418,25 +418,25 @@ Sebuah fitur bisa dilindungi paling banyak oleh satu izin.

      -Jika aplikasi memerlukan akses ke fitur yang dilindungi oleh izin, -aplikasi harus mendeklarasikan bahwa aplikasi memerlukan izin itu dengan elemen +Jika aplikasi memerlukan akses ke fitur yang dilindungi oleh izin, +aplikasi harus mendeklarasikan bahwa aplikasi memerlukan izin itu dengan elemen <uses-permission> - 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. + 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.

      -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 +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 <permission> . Misalnya, aktivitas dapat dilindungi sebagai berikut:

      @@ -457,43 +457,43 @@ dengan elemen

      -Perhatikan, dalam contoh ini izin {@code DEBIT_ACCT} tidak hanya -dideklarasikan dengan elemen +Perhatikan, dalam contoh ini izin {@code DEBIT_ACCT} tidak hanya +dideklarasikan dengan elemen <permission> -, penggunaannya juga diminta dengan elemen +, penggunaannya juga diminta dengan elemen <uses-permission> -. Penggunaannya harus diminta agar komponen -aplikasi lainnya bisa menjalankan aktivitas yang dilindungi, meskipun perlindungan itu -diberlakukan oleh aplikasi itu sendiri. +. Penggunaannya harus diminta agar komponen +aplikasi lainnya bisa menjalankan aktivitas yang dilindungi, meskipun perlindungan itu +diberlakukan oleh aplikasi itu sendiri.

      -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 +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 <permission> -. Akan tetapi, penggunaannya masih perlu dengan -<uses-permission>. +. Akan tetapi, penggunaannya masih perlu dengan +<uses-permission>.

      -Elemen -<permission-tree> -mendeklarasikan namespace untuk grup izin yang akan didefinisikan dalam -kode. Dan +Elemen +<permission-tree> +mendeklarasikan namespace untuk grup izin yang akan didefinisikan dalam +kode. Dan <permission-group> -mendefinisikan label untuk seperangkat izin (yang sama-sama dideklarasikan dalam manifes dengan elemen -<permission> -dan yang dideklarasikan di tempat lain). Ini hanya memengaruhi cara izin -dikelompokkan saat ditampilkan kepada pengguna. Elemen +mendefinisikan label untuk seperangkat izin (yang sama-sama dideklarasikan dalam manifes dengan elemen +<permission> +dan yang dideklarasikan di tempat lain). Ini hanya memengaruhi cara izin +dikelompokkan saat ditampilkan kepada pengguna. Elemen <permission-group> - tidak menetapkan izin mana dimiliki grup; + tidak menetapkan izin mana dimiliki grup; elemen hanya memberi nama grup. Izin ditempatkan dalam grup -dengan memberikan nama grup ke elemen -<permission> - melalui atribut -permissionGroup +dengan memberikan nama grup ke elemen +<permission> + melalui atribut +permissionGroup .

      @@ -501,17 +501,17 @@ dengan memberikan nama grup ke elemen

      Pustaka

      -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, +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).

      -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 -<uses-library> yang -terpisah untuk menamai setiap pustaka. (Nama pustaka bisa ditemukan +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 +<uses-library> yang +terpisah untuk menamai setiap pustaka. (Nama pustaka bisa ditemukan dalam dokumentasi paket.)

      diff --git a/docs/html-intl/intl/in/guide/topics/providers/calendar-provider.jd b/docs/html-intl/intl/in/guide/topics/providers/calendar-provider.jd index 76bc9915cbd7658f9af80cdb9a94220cfad93e3c..3058815368584613271ce3e57f78055602469619 100644 --- a/docs/html-intl/intl/in/guide/topics/providers/calendar-provider.jd +++ b/docs/html-intl/intl/in/guide/topics/providers/calendar-provider.jd @@ -42,7 +42,7 @@ page.title=Penyedia Kalender
    • Menggunakan intent untuk menampilkan data kalender
    • - +
    • Adaptor Sinkronisasi
    • @@ -63,8 +63,8 @@ pada kalender, kejadian, peserta, pengingat, dan seterusnya.

      API Penyedia Kalender bisa digunakan oleh aplikasi dan adaptor sinkronisasi. Aturannya bervariasi menurut tipe program yang membuat panggilan. Dokumen ini -terutama berfokus pada penggunaan API Penyedia Kalender sebagai sebuah aplikasi. Untuk -pembahasan ragam adaptor sinkronisasi, lihat +terutama berfokus pada penggunaan API Penyedia Kalender sebagai sebuah aplikasi. Untuk +pembahasan ragam adaptor sinkronisasi, lihat Adaptor Sinkronisasi.

      @@ -89,7 +89,7 @@ data kalender seorang pengguna.

      Setiap penyedia konten membuka sebuah URI publik (yang dibungkus sebagai objek {@link android.net.Uri} ) yang mengidentifikasikan set datanya secara unik. Penyedia konten yang mengontrol - beberapa set data (beberapa tabel) mengekspos URI terpisah untuk tiap set. Semua + beberapa set data (beberapa tabel) mengekspos URI terpisah untuk tiap set. Semua URI untuk penyedia diawali dengan string "content://". String ini mengidentifikasi data sebagai dikontrol oleh penyedia konten. Penyedia Kalender mendefinisikan konstanta untuk URI masing-masing kelas (tabel). URI ini @@ -113,26 +113,26 @@ tabel dan bidang utama yang saling berkaitan.

      {@link android.provider.CalendarContract.Calendars}

      - - Tabel ini menyimpan + + Tabel ini menyimpan informasi khusus kalender. Tiap baris dalam tabel ini berisi data untuk satu kalender, seperti nama, warna, informasi sinkronisasi, dan seterusnya. {@link android.provider.CalendarContract.Events} - + Tabel ini menyimpan informasi khusus kejadian. Tiap baris dalam tabel ini berisi informasi untuk satu kejadian—misalnya, judul kejadian, lokasi, waktu mulai, waktu selesai, dan seterusnya. Kejadian bisa terjadi satu kali atau bisa berulang beberapa kali. Peserta, -pengingat, dan properti perluasan disimpan dalam tabel terpisah. -Masing-masing memiliki sebuah {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} +pengingat, dan properti perluasan disimpan dalam tabel terpisah. +Masing-masing memiliki sebuah {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang mengacu {@link android.provider.BaseColumns#_ID} dalam tabel Events. {@link android.provider.CalendarContract.Instances} - + Tabel ini menyimpan waktu mulai dan waktu selesai setiap bentuk kejadian. Tiap baris dalam tabel ini mewakili satu bentuk kejadian. Untuk kejadian satu kali ada pemetaan 1:1 @@ -141,7 +141,7 @@ secara otomatis yang sesuai dengan beberapa kejadian itu. {@link android.provider.CalendarContract.Attendees} - + Tabel ini menyimpan informasi peserta (tamu) kejadian. Tiap baris mewakili satu tamu kejadian. Ini menetapkan tipe tamu dan respons kehadiran tamu @@ -149,17 +149,17 @@ untuk kejadian. {@link android.provider.CalendarContract.Reminders} - + Tabel ini menyimpan data peringatan/pemberitahuan. Tiap baris mewakili satu peringatan untuk sebuah kejadian. Sebuah kejadian bisa memiliki beberapa pengingat. Jumlah maksimum pengingat per kejadian -ditetapkan dalam -{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}, +ditetapkan dalam +{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}, yang diatur oleh adaptor sinkronisasi yang memiliki kalender yang diberikan. Pengingat ditetapkan dalam menit sebelum kejadian dan memiliki metode yang menentukan cara pengguna akan diperingatkan. - +

      API Penyedia Kalender didesain agar luwes dan tangguh. Sementara itu @@ -178,9 +178,9 @@ Kalender.

    • Adaptor sinkronisasi. Adaptor sinkronisasi menyinkronkan data kalender -pada perangkat pengguna dengan server atau sumber data lain. Dalam tabel +pada perangkat pengguna dengan server atau sumber data lain. Dalam tabel {@link android.provider.CalendarContract.Calendars} dan -{@link android.provider.CalendarContract.Events}, +{@link android.provider.CalendarContract.Events}, ada kolom yang dicadangkan untuk digunakan adaptor sinkronisasi. Penyedia dan aplikasi tidak boleh memodifikasinya. Sebenarnya, tabel-tabel itu tidak terlihat kecuali jika diakses sebagai adaptor sinkronisasi. Untuk informasi selengkapnya tentang @@ -211,7 +211,7 @@ untuk menghapus, menyisipkan, atau memperbarui data kalender:

      Tabel {@link android.provider.CalendarContract.Calendars} berisi data untuk tiap kalender. Kolom-kolom -berikut ini bisa ditulisi oleh aplikasi maupun adaptor sinkronisasi. +berikut ini bisa ditulisi oleh aplikasi maupun adaptor sinkronisasi. Untuk mengetahui daftar lengkap bidang-bidang yang didukung, lihat acuan {@link android.provider.CalendarContract.Calendars}.

      @@ -229,7 +229,7 @@ acuan {@link android.provider.CalendarContract.Calendars}.

      - + - +

      Berikut ini adalah contoh yang menampilkan cara mendapatkan kalender yang dimiliki oleh pengguna tertentu. Untuk memudahkan, dalam contoh ini, operasi query ditampilkan dalam thread antarmuka pengguna ("thread utama"). Dalam praktiknya, hal ini harus dilakukan dalam -thread asinkron, sebagai ganti pada thread utama. Untuk diskusi selengkapnya, lihat -Loader. Jika Anda tidak sekadar +thread asinkron, sebagai ganti pada thread utama. Untuk diskusi selengkapnya, lihat +Loader. Jika Anda tidak sekadar membaca data melainkan memodifikasinya, lihat {@link android.content.AsyncQueryHandler}.

      @@ -268,18 +268,18 @@ public static final String[] EVENT_PROJECTION = new String[] { Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3; - + +disinkronkan.

      Di bagian berikutnya pada contoh ini, Anda akan membuat query. Pemilihan @@ -301,59 +301,59 @@ kalender yang memiliki ACCOUNT_NAME telah ditampilkan pengguna, bukan hanya kalender yang dimiliki pengguna, hilangkan OWNER_ACCOUNT. Query tersebut akan menghasilkan objek {@link android.database.Cursor} yang bisa Anda gunakan untuk menyusuri set hasil yang dikembalikan oleh -query database. Untuk diskusi selengkapnya tentang penggunaan query dalam penyedia konten, +query database. Untuk diskusi selengkapnya tentang penggunaan query dalam penyedia konten, lihat Penyedia Kalender.

      // Run query
       Cursor cur = null;
       ContentResolver cr = getContentResolver();
      -Uri uri = Calendars.CONTENT_URI;   
      -String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
      +Uri uri = Calendars.CONTENT_URI;
      +String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                               + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                               + Calendars.OWNER_ACCOUNT + " = ?))";
       String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
      -        "sampleuser@gmail.com"}; 
      -// Submit the query and get a Cursor object back. 
      +        "sampleuser@gmail.com"};
      +// Submit the query and get a Cursor object back.
       cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

      Bagian berikutnya ini menggunakan kursor untuk merunut set hasil. Bagian ini menggunakan konstanta yang disiapkan pada awal contoh ini untuk menghasilkan nilai-nilai bagi tiap bidang.

      - +
      // Use the cursor to step through the returned records
       while (cur.moveToNext()) {
           long calID = 0;
           String displayName = null;
           String accountName = null;
           String ownerName = null;
      -      
      +
           // Get the field values
           calID = cur.getLong(PROJECTION_ID_INDEX);
           displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
           accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
           ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
      -              
      +
           // Do something with the values...
       
          ...
       }
       
      - +

      Memodifikasi kalender

      Untuk melakukan pembaruan kalender, Anda bisa menyediakan {@link android.provider.BaseColumns#_ID} kalender itu baik sebagai ID yang ditambahkan ke -URI +URI -({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) +({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) atau sebagai item pemilihan pertama. Pemilihan harus diawali dengan "_id=?", dan selectionArg pertama harus berupa {@link -android.provider.BaseColumns#_ID} kalender. +android.provider.BaseColumns#_ID} kalender. Anda juga bisa melakukan pembaruan dengan menuliskan kode ID dalam URI. Contoh ini mengubah -nama tampilan kalender dengan pendekatan -({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) +nama tampilan kalender dengan pendekatan +({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) :

      private static final String DEBUG_TAG = "MyActivity";
      @@ -375,7 +375,7 @@ perlu membuat sebuah kalender lokal, aplikasi bisa melakukannya dengan melakukan
       penyisipan kalender sebagai adaptor sinkronisasi, menggunakan {@link
       android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} dari {@link
       android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}.
      -{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} 
      +{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}
       adalah sebuah tipe akun khusus untuk kalender yang tidak
       terkait dengan akun perangkat. Kalender tipe ini tidak disinkronkan dengan server. Untuk
       diskusi tentang adaptor sinkronisasi, lihat Adaptor Sinkronisasi.

      @@ -434,7 +434,7 @@ android.provider.CalendarContract.Events}.

      - + - + - + - - + + - + - + - + - - + - - - + @@ -514,11 +514,11 @@ java.util.TimeZone#getAvailableIDs()}. Perhatikan bahwa aturan ini tidak berlaku Anda menyisipkan kejadian melalui Intent {@link android.content.Intent#ACTION_INSERT INSERT}, yang dijelaskan dalam Menggunakan intent untuk menyisipkan kejadian—dalam skenario itu, sebuah zona waktu default akan diberikan. - +
    • Untuk kejadian tidak-berulang, Anda harus menyertakan {@link android.provider.CalendarContract.EventsColumns#DTEND}.
    • - - + +
    • Untuk kejadian berulang, Anda harus menyertakan sebuah {@link android.provider.CalendarContract.EventsColumns#DURATION} selain {@link android.provider.CalendarContract.EventsColumns#RRULE} atau {@link @@ -526,9 +526,9 @@ android.provider.CalendarContract.EventsColumns#RDATE}. Perhatikan bahwa aturan Anda menyisipkan kejadian melalui Intent {@link android.content.Intent#ACTION_INSERT INSERT}, yang dijelaskan dalam Menggunakan intent untuk menyisipkan kejadian—dalam skenario itu, Anda bisa menggunakan {@link -android.provider.CalendarContract.EventsColumns#RRULE} bersama {@link android.provider.CalendarContract.EventsColumns#DTSTART} dan {@link android.provider.CalendarContract.EventsColumns#DTEND}, dan aplikasi Calendar +android.provider.CalendarContract.EventsColumns#RRULE} bersama {@link android.provider.CalendarContract.EventsColumns#DTSTART} dan {@link android.provider.CalendarContract.EventsColumns#DTEND}, dan aplikasi Calendar akan mengubahnya menjadi durasi secara otomatis.
    • - +

      Berikut ini adalah contoh penyisipan kejadian. Penyisipan ini dilakukan dalam thread UI @@ -539,8 +539,8 @@ informasi selengkapnya, lihat {@link android.content.AsyncQueryHandler}.

       long calID = 3;
      -long startMillis = 0; 
      -long endMillis = 0;     
      +long startMillis = 0;
      +long endMillis = 0;
       Calendar beginTime = Calendar.getInstance();
       beginTime.set(2012, 9, 14, 7, 30);
       startMillis = beginTime.getTimeInMillis();
      @@ -561,7 +561,7 @@ Uri uri = cr.insert(Events.CONTENT_URI, values);
       
       // get the event ID that is the last element in the Uri
       long eventID = Long.parseLong(uri.getLastPathSegment());
      -// 
      +//
       // ... do something with event ID
       //
       //
      @@ -578,14 +578,14 @@ peserta atau pengingat ke kejadian.

      gunakan Intent {@link android.content.Intent#ACTION_EDIT EDIT}, seperti dijelaskan dalam Menggunakan intent untuk mengedit kejadian. Akan tetapi, jika perlu, Anda bisa mengedit kejadian secara langsung. Untuk melakukan pembaruan -suatu kejadian, Anda bisa memberikan _ID +suatu kejadian, Anda bisa memberikan _ID kejadian itu sebagai ID yang ditambahkan ke URI ({@link -android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) -atau sebagai item pemilihan pertama. +android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) +atau sebagai item pemilihan pertama. Pemilihan harus dimulai dengan "_id=?", dan selectionArg yang pertama harus berupa _ID kejadian. Anda juga bisa melakukan pembaruan dengan menggunakan pemilihan tanpa ID. Berikut ini adalah contoh pembaruan -kejadian. Contoh ini mengubah judul kejadian dengan pendekatan +kejadian. Contoh ini mengubah judul kejadian dengan pendekatan {@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()} :

      @@ -598,7 +598,7 @@ ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event -values.put(Events.TITLE, "Kickboxing"); +values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows); @@ -625,22 +625,22 @@ ContentValues values = new ContentValues(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().delete(deleteUri, null, null); -Log.i(DEBUG_TAG, "Rows deleted: " + rows); +Log.i(DEBUG_TAG, "Rows deleted: " + rows);

      Tabel Peserta

      Tiap baris tabel {@link android.provider.CalendarContract.Attendees} -mewakili satu peserta atau tamu dari sebuah kejadian. Memanggil -{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} +mewakili satu peserta atau tamu dari sebuah kejadian. Memanggil +{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} akan menghasilkan daftar peserta untuk -kejadian dengan {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang diberikan. -{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} ini +kejadian dengan {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang diberikan. +{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} ini harus cocok dengan {@link -android.provider.BaseColumns#_ID} kejadian tertentu.

      +android.provider.BaseColumns#_ID} kejadian tertentu.

      Tabel berikut mencantumkan -bidang-bidang yang bisa ditulis. Saat menyisipkan peserta baru, Anda harus menyertakan semuanya +bidang-bidang yang bisa ditulis. Saat menyisipkan peserta baru, Anda harus menyertakan semuanya kecuali ATTENDEE_NAME.

      @@ -698,7 +698,7 @@ kecuali ATTENDEE_NAME.

      Menambahkan Peserta

      Berikut ini adalah contoh yang menambahkan satu peserta ke kejadian. Perhatikan bahwa -{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} +{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} diperlukan:

      @@ -718,17 +718,17 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values);
       

      Tabel Pengingat

      Tiap baris tabel {@link android.provider.CalendarContract.Reminders} -mewakili satu pengingat untuk sebuah kejadian. Memanggil +mewakili satu pengingat untuk sebuah kejadian. Memanggil {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} akan menghasilkan daftar pengingat untuk -kejadian dengan +kejadian dengan {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} yang diberikan.

      Tabel berikut mencantumkan bidang-bidang yang bisa ditulis untuk pengingat. Semua bidang harus disertakan saat menyisipkan pengingat baru. Perhatikan bahwa adaptor sinkronisasi menetapkan tipe pengingat yang didukungnya dalam tabel {@link -android.provider.CalendarContract.Calendars}. Lihat -{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} +android.provider.CalendarContract.Calendars}. Lihat +{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} untuk detailnya.

      @@ -773,16 +773,16 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values);

      Tabel Instances

      -

      Tabel +

      Tabel {@link android.provider.CalendarContract.Instances} menyimpan waktu mulai dan waktu selesai kejadian. Tiap baris dalam tabel ini mewakili satu bentuk kejadian. Tabel instance tidak bisa ditulis dan hanya menyediakan sebuah cara untuk membuat query kejadian.

      -

      Tabel berikut mencantumkan beberapa bidang yang bisa Anda query untuk suatu instance. Perhatikan -bahwa zona waktu didefinisikan oleh -{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} -dan +

      Tabel berikut mencantumkan beberapa bidang yang bisa Anda query untuk suatu instance. Perhatikan +bahwa zona waktu didefinisikan oleh +{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} +dan {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}.

      @@ -801,18 +801,18 @@ dan - + - + - + @@ -820,16 +820,16 @@ Kalender. - - + - +
      {@link android.provider.CalendarContract.Calendars#VISIBLE}Sebuah boolean yang menunjukkan apakah kalender dipilih untuk ditampilkan. Nilai 0 menunjukkan bahwa kejadian yang terkait dengan kalender ini tidak boleh ditampilkan. Nilai 1 menunjukkan bahwa kejadian yang terkait dengan kalender ini harus @@ -240,7 +240,7 @@ android.provider.CalendarContract.Instances}.
      {@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}Sebuah boolean yang menunjukkan apakah kalender harus disinkronkan dan apakah kejadiannya harus disimpan pada perangkat. Nilai 0 berarti jangan menyinkronkan kalender ini atau simpan kejadiannya pada perangkat. Nilai 1 berarti menyinkronkan kejadian untuk kalender ini @@ -253,8 +253,8 @@ dan simpan kejadiannya pada perangkat.
      {@link android.provider.CalendarContract.EventsColumns#DURATION}Durasi kejadian dalam format RFC5545. Misalnya, nilai "PT1H" menyatakan bahwa kejadian akan berlangsung satu jam, dan nilai "P2W" menunjukkan @@ -444,39 +444,39 @@ durasi 2 minggu.
      {@link android.provider.CalendarContract.EventsColumns#ALL_DAY}Nilai 1 menunjukkan kejadian ini memakan waktu sehari penuh, seperti yang didefinisikan oleh zona waktu lokal. Nilai 0 menunjukkan kejadian adalah kejadian biasa yang mungkin dimulai dan selesai pada sembarang waktu selama suatu hari.
      {@link android.provider.CalendarContract.EventsColumns#RRULE}Aturan perulangan untuk format kejadian. Misalnya, "FREQ=WEEKLY;COUNT=10;WKST=SU". Anda bisa menemukan contoh selengkapnya di sini.
      {@link android.provider.CalendarContract.EventsColumns#RDATE}Tanggal perulangan kejadian. - Anda biasanya menggunakan {@link android.provider.CalendarContract.EventsColumns#RDATE} - bersama dengan {@link android.provider.CalendarContract.EventsColumns#RRULE} + Tanggal perulangan kejadian. + Anda biasanya menggunakan {@link android.provider.CalendarContract.EventsColumns#RDATE} + bersama dengan {@link android.provider.CalendarContract.EventsColumns#RRULE} untuk mendefinisikan satu set agregat kejadian berulang. Untuk diskusi selengkapnya, lihat Spesifikasi RFC5545.
      {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}Jika kejadian ini dihitung sebagai waktu sibuk atau waktu bebas yang bisa + + Jika kejadian ini dihitung sebagai waktu sibuk atau waktu bebas yang bisa dijadwalkan.
      {@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}
      {@link android.provider.CalendarContract.Instances#END_DAY}Hari selesai Julian dari instance, relatif terhadap -zona waktu Kalender. - +zona waktu Kalender. +
      {@link android.provider.CalendarContract.Instances#END_MINUTE}Menit selesai dari instance yang diukur dari tengah malam di zona waktu Kalender.
      {@link android.provider.CalendarContract.Instances#EVENT_ID}
      {@link android.provider.CalendarContract.Instances#START_DAY}Hari mulai Julian dari instance, relatif terhadap zona waktu Kalender. + Hari mulai Julian dari instance, relatif terhadap zona waktu Kalender.
      {@link android.provider.CalendarContract.Instances#START_MINUTE}Menit mulai dari instance yang diukur dari tengah malam, relatif terhadap -zona waktu Kalender. +zona waktu Kalender.
      @@ -840,7 +840,7 @@ zona waktu Kalender. dalam URI. Dalam contoh ini, {@link android.provider.CalendarContract.Instances} mendapatkan akses ke bidang {@link android.provider.CalendarContract.EventsColumns#TITLE} melalui -implementasi antarmuka {@link android.provider.CalendarContract.EventsColumns}-nya. +implementasi antarmuka {@link android.provider.CalendarContract.EventsColumns}-nya. Dengan kata lain, {@link android.provider.CalendarContract.EventsColumns#TITLE} dihasilkan melalui tampilan database, bukan melalui query terhadap tabel {@link @@ -853,7 +853,7 @@ public static final String[] INSTANCE_PROJECTION = new String[] { Instances.BEGIN, // 1 Instances.TITLE // 2 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; @@ -868,7 +868,7 @@ long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); - + Cursor cur = null; ContentResolver cr = getContentResolver(); @@ -883,28 +883,28 @@ ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query -cur = cr.query(builder.build(), - INSTANCE_PROJECTION, - selection, - selectionArgs, +cur = cr.query(builder.build(), + INSTANCE_PROJECTION, + selection, + selectionArgs, null); - + while (cur.moveToNext()) { String title = null; long eventID = 0; - long beginVal = 0; - + long beginVal = 0; + // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); - - // Do something with the values. - Log.i(DEBUG_TAG, "Event: " + title); + + // Do something with the values. + Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(beginVal); + calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); + Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } } @@ -922,9 +922,9 @@ while (cur.moveToNext()) {
      {@link android.content.Intent#ACTION_VIEW VIEW}

      content://com.android.calendar/time/<ms_since_epoch>

      - Anda juga bisa mengacu ke URI dengan -{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. -Untuk contoh yang menggunakan intent ini, lihat Menggunakan intent untuk menampilkan data kalender. + Anda juga bisa mengacu ke URI dengan +{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. +Untuk contoh yang menggunakan intent ini, lihat Menggunakan intent untuk menampilkan data kalender. Membuka kalender pada waktu yang ditetapkan oleh <ms_since_epoch>. @@ -935,11 +935,11 @@ Untuk contoh yang menggunakan intent ini, lihat Menggunakan intent untuk menampilkan data kalender. - + Menampilkan kejadian yang ditetapkan oleh <event_id>. @@ -952,12 +952,12 @@ Untuk contoh yang menggunakan intent ini, lihat Menggunakan intent untuk mengedit kejadian. - - + + Mengedit kejadian yang ditetapkan oleh <event_id>. @@ -972,11 +972,11 @@ Untuk contoh penggunaan intent ini, lihat Menggunakan intent untuk menyisipkan kejadian. - + Membuat sebuah kejadian. @@ -996,7 +996,7 @@ Untuk contoh penggunaan intent ini, lihat file manifesnya.

      - +

      Bila pengguna menjalankan aplikasi yang menggunakan pendekatan ini, aplikasi akan mengirim izin ke Kalender untuk menyelesaikan penambahan kejadian. Intent {@link android.content.Intent#ACTION_INSERT INSERT} menggunakan bidang-bidang ekstra untuk mengisi formulir lebih dahulu dengan detail kejadian dalam Kalender. Pengguna nanti bisa membatalkan kejadian, mengedit formulir sebagaimana diperlukan, atau menyimpan kejadian ke kalender mereka.

      - +

      Berikut ini adalah cuplikan kode yang menjadwalkan kejadian pada tanggal 19 Januari 2012, yang berjalan dari 7:30 pagi hingga 8:30 pagi Perhatikan hal-hal berikut tentang cuplikan kode ini:

        -
      • Cuplikan kode ini menetapkan {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} +
      • Cuplikan kode ini menetapkan {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} sebagai URI-nya.
      • - +
      • Cuplikan kode ini menggunakan bidang-bidang ekstra {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} dan {@link @@ -1083,10 +1083,10 @@ android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} untuk mengisi dahulu formulir dengan waktu kejadian. Nilai-nilai untuk waktu ini harus dalam milidetik UTC sejak waktu patokan.
      • - +
      • Cuplikan kode ini menggunakan bidang ekstra {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL} untuk memberikan daftar undangan yang dipisah koma, yang ditetapkan melalui alamat email.
      • - +
       Calendar beginTime = Calendar.getInstance();
      @@ -1158,18 +1158,18 @@ mengakses Penyedia Kalender:

      • Adaptor sinkronisasi perlu menetapkan bahwa dirinya sebuah adaptor sinkronisasi dengan mengatur {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} ke true.
      • - - + +
      • Adaptor sinkronisasi perlu memberikan {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} dan {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} sebagai parameter query dalam URI.
      • - +
      • Adaptor sinkronisasi memiliki akses tulis ke lebih banyak kolom daripada aplikasi atau widget. - Misalnya, aplikasi hanya bisa mengubah sedikit karakteristik kalender, + Misalnya, aplikasi hanya bisa mengubah sedikit karakteristik kalender, misalnya nama, nama tampilan, pengaturan visibilitas, dan apakah kalender disinkronkan atau tidak. Sebagai perbandingan, adaptor sinkronisasi bisa mengakses bukan hanya kolom-kolom itu, namun banyak kolom lainnya, misalnya warna kalender, zona waktu, tingkat akses, lokasi, dan seterusnya. -Akan tetapi, adaptor sinkronisasi dibatasi pada ACCOUNT_NAME dan +Akan tetapi, adaptor sinkronisasi dibatasi pada ACCOUNT_NAME dan ACCOUNT_TYPE yang ditetapkannya.

      Berikut ini adalah metode pembantu yang bisa Anda gunakan untuk menghasilkan URI bagi penggunaan dengan adaptor sinkronisasi:

      @@ -1180,5 +1180,5 @@ Akan tetapi, adaptor sinkronisasi dibatasi pada ACCOUNT_NAME dan .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }
      -

      Untuk contoh implementasi adaptor sinkronisasi (yang tidak terkait secara khusus dengan Kalender), lihat +

      Untuk contoh implementasi adaptor sinkronisasi (yang tidak terkait secara khusus dengan Kalender), lihat SampleSyncAdapter. diff --git a/docs/html-intl/intl/in/guide/topics/providers/content-provider-basics.jd b/docs/html-intl/intl/in/guide/topics/providers/content-provider-basics.jd index c4003caba88f3c589462e5a49ff3fab1f00f2524..4af92771f7e1ce7a4638651d30a550abbadb1538 100644 --- a/docs/html-intl/intl/in/guide/topics/providers/content-provider-basics.jd +++ b/docs/html-intl/intl/in/guide/topics/providers/content-provider-basics.jd @@ -236,7 +236,7 @@ page.title=Dasar-Dasar Penyedia Konten Misalnya, untuk mendapatkan daftar kata dan lokalnya dari Penyedia Kamus Pengguna, Anda memanggil {@link android.content.ContentResolver#query ContentResolver.query()}. Metode {@link android.content.ContentResolver#query query()} memanggil - metode {@link android.content.ContentProvider#query ContentProvider.query()} yang didefinisikan oleh + metode {@link android.content.ContentProvider#query ContentProvider.query()} yang didefinisikan oleh Penyedia Kamus Pengguna. Baris-baris kode berikut menunjukkan sebuah panggilan {@link android.content.ContentResolver#query ContentResolver.query()}:

      @@ -251,7 +251,7 @@ mCursor = getContentResolver().query(

      Tabel 2 menampilkan cara argumen untuk - {@link android.content.ContentResolver#query + {@link android.content.ContentResolver#query query(Uri,projection,selection,selectionArgs,sortOrder)} cocok dengan sebuah pernyataan SELECT di SQL:

      @@ -310,7 +310,7 @@ mCursor = getContentResolver().query( {@link android.provider.UserDictionary.Words#CONTENT_URI} mengandung URI konten dari tabel "words" kamus pengguna. Objek {@link android.content.ContentResolver} akan mengurai otoritas URI, dan menggunakannya untuk "mengetahui" penyedia dengan - membandingkan otoritas tersebut dengan sebuah tabel sistem berisi penyedia yang dikenal. + membandingkan otoritas tersebut dengan sebuah tabel sistem berisi penyedia yang dikenal. {@link android.content.ContentResolver} kemudian bisa mengirim argumen query ke penyedia yang benar.

      @@ -343,8 +343,8 @@ Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4); salah satunya.

      - Catatan: Kelas-kelas {@link android.net.Uri} dan {@link android.net.Uri.Builder} - berisi metode praktis untuk membangun objek dari string URI yang tersusun dengan baik. + Catatan: Kelas-kelas {@link android.net.Uri} dan {@link android.net.Uri.Builder} + berisi metode praktis untuk membangun objek dari string URI yang tersusun dengan baik. {@link android.content.ContentUris} berisi metode praktis untuk menambahkan nilai ID ke URI. Cuplikan kode sebelumnya menggunakan {@link android.content.ContentUris#withAppendedId withAppendedId()} untuk menambahkan id ke URI konten User Dictionary. @@ -359,8 +359,8 @@ Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

      Demi kejelasan, cuplikan kode di bagian ini memanggil - {@link android.content.ContentResolver#query ContentResolver.query()} pada "UI thread"". Akan tetapi, dalam - kode sesungguhnya, Anda harus melakukan query secara asinkron pada sebuah thread terpisah. Satu cara melakukannya + {@link android.content.ContentResolver#query ContentResolver.query()} pada "UI thread"". Akan tetapi, dalam + kode sesungguhnya, Anda harus melakukan query secara asinkron pada sebuah thread terpisah. Satu cara melakukannya adalah menggunakan kelas {@link android.content.CursorLoader}, yang dijelaskan lebih detail dalam panduan Loader. Juga, baris-baris kode tersebut hanyalah cuplikan; tidak menunjukkan sebuah aplikasi @@ -428,7 +428,7 @@ String[] mSelectionArgs = {""};

      Cuplikan berikutnya menampilkan cara menggunakan {@link android.content.ContentResolver#query ContentResolver.query()}, dengan menggunakan Penyedia Kamus Pengguna - sebagai contoh. Query klien penyedia serupa dengan query SQL, dan berisi satu + sebagai contoh. Query klien penyedia serupa dengan query SQL, dan berisi satu set kolom yang akan dihasilkan, satu set kriteria pemilihan, dan urutan sortir.

      @@ -438,8 +438,8 @@ String[] mSelectionArgs = {""};

      Ekspresi yang menetapkan baris yang harus diambil dipecah menjadi klausa pemilihan dan argumen pemilihan. Klausa pemilihan adalah kombinasi ekspresi logis dan boolean, - nama kolom, dan nilai (variabel mSelectionClause). Jika Anda menetapkan - parameter ? yang bisa diganti, sebagai ganti nilai, metode query akan mengambil nilai + nama kolom, dan nilai (variabel mSelectionClause). Jika Anda menetapkan + parameter ? yang bisa diganti, sebagai ganti nilai, metode query akan mengambil nilai dari larik argumen pemilihan (variabel mSelectionArgs).

      @@ -558,21 +558,21 @@ String[] selectionArgs = {""}; selectionArgs[0] = mUserInput;

      - Sebuah klausa pemilihan yang menggunakan ? sebagai parameter yang bisa diganti dan sebuah larik + Sebuah klausa pemilihan yang menggunakan ? sebagai parameter yang bisa diganti dan sebuah larik argumen pemilihan adalah cara yang lebih disukai untuk menyebutkan pemilihan, sekalipun penyedia tidak dibuat berdasarkan database SQL.

      Menampilkan hasil query

      - Metode klien {@link android.content.ContentResolver#query ContentResolver.query()} selalu - menghasilkan {@link android.database.Cursor} berisi kolom-kolom yang ditetapkan oleh + Metode klien {@link android.content.ContentResolver#query ContentResolver.query()} selalu + menghasilkan {@link android.database.Cursor} berisi kolom-kolom yang ditetapkan oleh proyeksi query untuk baris yang cocok dengan kriteria pemilihan query. Objek - {@link android.database.Cursor} menyediakan akses baca acak ke baris dan kolom yang - dimuatnya. Dengan metode {@link android.database.Cursor}, Anda bisa mengulang baris-baris dalam + {@link android.database.Cursor} menyediakan akses baca acak ke baris dan kolom yang + dimuatnya. Dengan metode {@link android.database.Cursor}, Anda bisa mengulang baris-baris dalam hasil, menentukan tipe data tiap kolom, mengambil data dari kolom, dan memeriksa - properti lain dari hasil. Beberapa implementasi {@link android.database.Cursor} - akan memperbarui objek secara otomatis bila data penyedia berubah, atau memicu metode dalam objek pengamat + properti lain dari hasil. Beberapa implementasi {@link android.database.Cursor} + akan memperbarui objek secara otomatis bila data penyedia berubah, atau memicu metode dalam objek pengamat bila {@link android.database.Cursor} berubah, atau keduanya.

      @@ -703,14 +703,14 @@ if (mCursor != null) {

      Untuk mendapatkan izin yang diperlukan untuk mengakses penyedia, aplikasi memintanya dengan elemen <uses-permission> - dalam file manifesnya. Bila Android Package Manager memasang aplikasi, pengguna - harus menyetujui semua izin yang diminta aplikasi. Jika pengguna menyetujui semuanya, + dalam file manifesnya. Bila Android Package Manager memasang aplikasi, pengguna + harus menyetujui semua izin yang diminta aplikasi. Jika pengguna menyetujui semuanya, Package Manager akan melanjutkan instalasi; jika pengguna tidak menyetujui, Package Manager akan membatalkan instalasi.

      Elemen -<uses-permission> +<uses-permission> berikut meminta akses baca ke Penyedia Kamus Pengguna:

      @@ -793,8 +793,8 @@ content://user_dictionary/words/<id_value>
           Untuk memperbarui sebuah baris, gunakan objek {@link android.content.ContentValues} dengan
           nilai-nilai yang diperbarui, persis seperti yang Anda lakukan pada penyisipan, dan kriteria pemilihan persis seperti yang Anda lakukan pada query.
           Metode klien yang Anda gunakan adalah
      -    {@link android.content.ContentResolver#update ContentResolver.update()}. Anda hanya perlu menambahkan 
      -    nilai-nilai ke objek {@link android.content.ContentValues} untuk kolom yang sedang Anda perbarui. Jika Anda 
      +    {@link android.content.ContentResolver#update ContentResolver.update()}. Anda hanya perlu menambahkan
      +    nilai-nilai ke objek {@link android.content.ContentValues} untuk kolom yang sedang Anda perbarui. Jika Anda
           ingin membersihkan konten kolom, aturlah nilai ke null.
       

      @@ -828,7 +828,7 @@ mRowsUpdated = getContentResolver().update(

      Anda juga harus membersihkan input pengguna bila memanggil - {@link android.content.ContentResolver#update ContentResolver.update()}. Untuk mengetahui selengkapnya tentang + {@link android.content.ContentResolver#update ContentResolver.update()}. Untuk mengetahui selengkapnya tentang hal ini, bacalah bagian Melindungi dari input merusak.

      Menghapus data

      @@ -858,7 +858,7 @@ mRowsDeleted = getContentResolver().delete(

      Anda juga harus membersihkan input pengguna bila memanggil - {@link android.content.ContentResolver#delete ContentResolver.delete()}. Untuk mengetahui selengkapnya tentang + {@link android.content.ContentResolver#delete ContentResolver.delete()}. Untuk mengetahui selengkapnya tentang hal ini, bacalah bagian Melindungi dari input merusak.

      @@ -883,7 +883,7 @@ mRowsDeleted = getContentResolver().delete(

    Tipe data lain yang sering digunakan penyedia adalah Binary Large OBject (BLOB) yang diimplementasikan sebagai - larik byte 64 KB. Anda bisa melihat tipe data yang tersedia dengan memperhatikan metode "get" + larik byte 64 KB. Anda bisa melihat tipe data yang tersedia dengan memperhatikan metode "get" kelas {@link android.database.Cursor}.

    @@ -905,7 +905,7 @@ mRowsDeleted = getContentResolver().delete( {@link android.content.ContentResolver#getType ContentResolver.getType()}.

    - Bagian Acuan Tipe MIME menerangkan + Bagian Acuan Tipe MIME menerangkan sintaks tipe MIME baik yang standar maupun custom.

    @@ -946,9 +946,9 @@ mRowsDeleted = getContentResolver().delete( Untuk mengakses penyedia dalam "mode batch", buat satu larik objek {@link android.content.ContentProviderOperation}, kemudian kirim larik itu ke penyedia konten dengan - {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Anda meneruskan - otoritas penyedia konten ke metode ini, daripada URI konten tertentu. - Ini memungkinkan tiap objek {@link android.content.ContentProviderOperation} dalam larik untuk bekerja + {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Anda meneruskan + otoritas penyedia konten ke metode ini, daripada URI konten tertentu. + Ini memungkinkan tiap objek {@link android.content.ContentProviderOperation} dalam larik untuk bekerja terhadap tabel yang berbeda. Panggilan ke {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()} menghasilkan satu larik hasil.

    @@ -1011,7 +1011,7 @@ mRowsDeleted = getContentResolver().delete(

    Penyedia mendefinisikan izin URI untuk URI konten dalam manifesnya, dengan menggunakan atribut android:grantUriPermission - dari elemen + dari elemen <provider> , serta elemen anak <grant-uri-permission> @@ -1184,7 +1184,7 @@ content://com.example.trains/Line2/5 vnd.android.cursor.item/vnd.example.line2

    - Kebanyakan penyedia konten mendefinisikan konstanta kelas kontrak untuk tipe MIME yang digunakannya. Kelas kontrak + Kebanyakan penyedia konten mendefinisikan konstanta kelas kontrak untuk tipe MIME yang digunakannya. Kelas kontrak {@link android.provider.ContactsContract.RawContacts} pada Penyedia Kontak misalnya, mendefinisikan konstanta {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} untuk tipe MIME diff --git a/docs/html-intl/intl/in/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/in/guide/topics/providers/content-provider-creating.jd index fefce703c2c8c8af1bdaad0dc4a8ded1212a093e..7fbc613ff79c9a1e0570d87c9509fe377193350f 100644 --- a/docs/html-intl/intl/in/guide/topics/providers/content-provider-creating.jd +++ b/docs/html-intl/intl/in/guide/topics/providers/content-provider-creating.jd @@ -1171,7 +1171,7 @@ metadata lain yang melekat ke penyedia. Kelas

  • android:label: Label informatif yang menjelaskan penyedia atau - datanya, atau keduanya. Label ini muncul dalam daftar aplikasi di + datanya, atau keduanya. Label ini muncul dalam daftar aplikasi di Settings > Apps > All.
  • @@ -1189,7 +1189,7 @@ metadata lain yang melekat ke penyedia. Kelas Aplikasi bisa mengakses penyedia konten secara tidak langsung dengan sebuah {@link android.content.Intent}. Aplikasi tidak memanggil satu pun dari metode-metode {@link android.content.ContentResolver} atau {@link android.content.ContentProvider}. Sebagai gantinya, aplikasi mengirim intent yang memulai aktivitas, - yang sering kali merupakan bagian dari aplikasi penyedia sendiri. Aktivitas tujuan bertugas + yang sering kali merupakan bagian dari aplikasi penyedia sendiri. Aktivitas tujuan bertugas mengambil dan menampilkan data dalam UI-nya. Bergantung pada tindakan dalam intent, aktivitas tujuan juga bisa meminta pengguna untuk membuat modifikasi pada data penyedia. Intent juga bisa berisi data "ekstra" yang menampilkan aktivitas tujuan diff --git a/docs/html-intl/intl/in/guide/topics/providers/content-providers.jd b/docs/html-intl/intl/in/guide/topics/providers/content-providers.jd index fc6f12b6f569cb31c7187a6133d9b7cb6ef5eecc..2dcd55e8fc29e875410cc49ecce6303fcaf221af 100644 --- a/docs/html-intl/intl/in/guide/topics/providers/content-providers.jd +++ b/docs/html-intl/intl/in/guide/topics/providers/content-providers.jd @@ -69,7 +69,7 @@ menempelkan data atau file yang kompleks dari aplikasi Anda ke aplikasi lain.

    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 + acuan untuk paket android.provider . Dengan beberapa batasan, semua penyedia ini bisa diakses oleh aplikasi Android apa saja. diff --git a/docs/html-intl/intl/in/guide/topics/providers/document-provider.jd b/docs/html-intl/intl/in/guide/topics/providers/document-provider.jd index c066e85b283d4d87b0f93e5c5141631e3a8bc0d6..f85746753c01508522b8cc7c8b3ffa9918694dfa 100644 --- a/docs/html-intl/intl/in/guide/topics/providers/document-provider.jd +++ b/docs/html-intl/intl/in/guide/topics/providers/document-provider.jd @@ -96,7 +96,7 @@ walaupun cara penyedia dokumen Anda secara fisik menyimpan data adalah terserah Platform Android terdiri dari beberapa penyedia dokumen bawaan, seperti Downloads, Images, dan Videos. -

  • Aplikasi klien—Aplikasi custom yang memanggil intent +
  • Aplikasi klien—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.
  • @@ -446,7 +446,7 @@ bisa terus menulis ke dokumen itu.

    Menghapus dokumen

    -

    Jika Anda memiliki URI dokumen dan +

    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}, diff --git a/docs/html-intl/intl/in/guide/topics/resources/accessing-resources.jd b/docs/html-intl/intl/in/guide/topics/resources/accessing-resources.jd index e4a0bea1e36ab36ad6cd83d4fe8c66786da897b3..6774557b9e62eb557ef67feb0d64ebba5b5e6520 100644 --- a/docs/html-intl/intl/in/guide/topics/resources/accessing-resources.jd +++ b/docs/html-intl/intl/in/guide/topics/resources/accessing-resources.jd @@ -60,7 +60,7 @@ melihat ke sana untuk menemukan ID sumber daya. ID sumber daya selalu terdiri da string}, {@code drawable}, dan {@code layout}. Untuk mengetahui selengkapnya tentang berbagai tipe, lihat Tipe Sumber Daya.

  • Nama sumber daya, bisa berupa: nama file, -tidak termasuk ekstensi; atau nilai dalam atribut {@code android:name} XML, jika +tidak termasuk ekstensi; atau nilai dalam atribut {@code android:name} XML, jika sumber daya itu sebuah nilai sederhana (misalnya sebuah string).
  • @@ -259,8 +259,8 @@ mengacu sumber daya sistem, Anda perlu memasukkan nama paketnya. Misalnya:

    android:text="@string/hello" /> -

    Catatan: Anda harus menggunakan sumber daya string sepanjang -waktu, sehingga aplikasi Anda bisa dilokalkan untuk bahasa lain. +

    Catatan: 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 Menyediakan Sumber Daya Alternatif . Untuk panduan lengkap melokalkan aplikasi Anda ke bahasa lain, @@ -332,6 +332,6 @@ android.widget.ArrayAdapter}<String>(this, android.R.layout.simple

    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 +layout sendiri untuk item daftar. Untuk informasi selengkapnya, lihat panduan pengembang List View.

    diff --git a/docs/html-intl/intl/in/guide/topics/resources/overview.jd b/docs/html-intl/intl/in/guide/topics/resources/overview.jd index 966800cf7daa52b0a9478683f8b06cafeaae1764..def4932f4af4652f647ca4579c4f334e7a06d219 100644 --- a/docs/html-intl/intl/in/guide/topics/resources/overview.jd +++ b/docs/html-intl/intl/in/guide/topics/resources/overview.jd @@ -24,7 +24,7 @@ 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 +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.

    @@ -46,7 +46,7 @@ ukuran layar berbeda.

    alternatif untuk aplikasi Anda:

    • Sumber daya default adalah sumber daya yang harus digunakan apa pun -konfigurasi perangkatnya atau jika tidak ada sumber daya alternatif yang sesuai +konfigurasi perangkatnya atau jika tidak ada sumber daya alternatif yang sesuai dengan konfigurasi saat ini.
    • 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, diff --git a/docs/html-intl/intl/in/guide/topics/resources/providing-resources.jd b/docs/html-intl/intl/in/guide/topics/resources/providing-resources.jd index d6bbfc58d91136555aaf4196893e37f67a7b1ff5..9bccd24e643ad990175a9cb2879fedca02e173ac 100644 --- a/docs/html-intl/intl/in/guide/topics/resources/providing-resources.jd +++ b/docs/html-intl/intl/in/guide/topics/resources/providing-resources.jd @@ -176,7 +176,7 @@ string.
    • styles.xml untuk gaya.

    Lihat Sumber Daya String, - Sumber Daya Gaya, dan + Sumber Daya Gaya, dan Tipe Sumber Daya Lainnya.

    @@ -289,7 +289,7 @@ qualifier konfigurasi.

    dari kartu SIM dalam perangkat. Misalnya, mcc310 adalah AS untuk operator mana saja, mcc310-mnc004 adalah AS untuk Verizon, dan mcc208-mnc00 Prancis untuk Orange.

    -

    Jika perangkat menggunakan koneksi radio (ponsel GSM), nilai-nilai MCC dan MNC berasal +

    Jika perangkat menggunakan koneksi radio (ponsel GSM), nilai-nilai MCC dan MNC berasal dari kartu SIM.

    Anda juga dapat menggunakan MNC saja (misalnya, untuk menyertakan sumber daya legal spesifik untuk negara itu di aplikasi Anda). Jika Anda perlu menetapkan hanya berdasarkan bahasa, maka gunakan qualifier @@ -312,7 +312,7 @@ dan kode jaringan seluler.

    dll.

    Bahasa didefinisikan oleh kode bahasa dua huruf ISO -639-1, bisa juga diikuti dengan kode wilayah +639-1, bisa juga diikuti dengan kode wilayah dua huruf ISO 3166-1-alpha-2 (diawali dengan huruf kecil "{@code r}").

    @@ -428,8 +428,8 @@ berubah antara lanskap dan potret agar cocok dengan lebar sebenarnya saat ini.Bila aplikasi Anda menyediakan beberapa direktori sumber daya dengan nilai yang berbeda untuk konfigurasi ini, sistem akan menggunakan nilai terdekat dengan (tanpa melebihi) lebar layar perangkat saat ini. Nilai -di sini memperhitungkan dekorasi layar akun, jadi jika perangkat memiliki beberapa -elemen UI persisten di tepi kiri atau kanan, layar +di sini memperhitungkan dekorasi layar akun, jadi jika perangkat memiliki beberapa +elemen UI persisten di tepi kiri atau kanan, layar menggunakan nilai lebar yang lebih kecil daripada ukuran layar sebenarnya, yang memperhitungkan elemen UI ini dan mengurangi ruang aplikasi yang tersedia.

    Ditambahkan dalam API level 13.

    @@ -455,14 +455,14 @@ sumber daya —bersama nilai yang didefinisikan oleh <N>. berubah antara lanskap dan potret agar cocok dengan tinggi sebenarnya saat ini.

    Bila aplikasi menyediakan beberapa direktori sumber daya dengan nilai yang berbeda untuk konfigurasi ini, sistem akan menggunakan nilai yang terdekat dengan (tanpa melebihi) - tinggi layar perangkat saat ini. Nilai + tinggi layar perangkat saat ini. Nilai di sini memperhitungkan dekorasi layar akun, jadi jika perangkat memiliki beberapa elemen UI persisten di tepi atas atau bawah, layar akan menggunakan nilai tinggi yang lebih kecil daripada ukuran layar sebenarnya, memperhitungkan -elemen UI ini dan mengurangi ruang aplikasi yang tersedia. Dekorasi -layar yang tidak tetap (misalnya baris status (status-bar) telepon yang bisa -disembunyikan saat layar penuh) di sini tidak diperhitungkan, demikian pula -dekorasi jendela seperti baris judul (title-bar)atau baris tindakan (action-bar), jadi aplikasi harus disiapkan +elemen UI ini dan mengurangi ruang aplikasi yang tersedia. Dekorasi +layar yang tidak tetap (misalnya baris status (status-bar) telepon yang bisa +disembunyikan saat layar penuh) di sini tidak diperhitungkan, demikian pula +dekorasi jendela seperti baris judul (title-bar)atau baris tindakan (action-bar), jadi aplikasi harus disiapkan untuk menangani ruang yang agak lebih kecil daripada yang ditetapkan.

    Ditambahkan dalam API level 13.

    Lihat juga bidang konfigurasi {@link android.content.res.Configuration#screenHeightDp} @@ -482,35 +482,35 @@ Multi Layar.

      -
    • {@code small}: Layar yang berukuran serupa dengan -layar QVGA densitas rendah. Ukuran layout minimum untuk layar kecil -adalah sekitar 320x426 satuan dp. Misalnya QVGA densitas rendah +
    • {@code small}: Layar yang berukuran serupa dengan +layar QVGA densitas rendah. Ukuran layout minimum untuk layar kecil +adalah sekitar 320x426 satuan dp. Misalnya QVGA densitas rendah dan VGA densitas tinggi.
    • -
    • {@code normal}: Layar yang berukuran serupa dengan +
    • {@code normal}: Layar yang berukuran serupa dengan layar HVGA densitas sedang. Ukuran layout minimum untuk -layar normal adalah sekitar 320x470 satuan dp. Contoh layar seperti itu adalah +layar normal adalah sekitar 320x470 satuan dp. Contoh layar seperti itu adalah WQVGA densitas rendah, HVGA densitas sedang, WVGA densitas tinggi.
    • -
    • {@code large}: Layar yang berukuran serupa dengan +
    • {@code large}: Layar yang berukuran serupa dengan layar VGA densitas sedang. Ukuran layout minimum untuk layar besar adalah sekitar 480x640 satuan dp. Misalnya layar VGA dan WVGA densitas sedang.
    • -
    • {@code xlarge}: Layar yang jauh lebih besar dari layar HVGA -densitas sedang tradisional. Ukuran layout minimum untuk -layar ekstra besar adalah sekitar 720x960 satuan dp. Perangkat dengan layar ekstra besar +
    • {@code xlarge}: Layar yang jauh lebih besar dari layar HVGA +densitas sedang tradisional. Ukuran layout minimum untuk +layar ekstra besar adalah sekitar 720x960 satuan dp. Perangkat dengan layar ekstra besar seringkali terlalu besar untuk dibawa dalam saku dan kemungkinan besar berupa perangkat bergaya tablet. Ditambahkan dalam API level 9.
    -

    Catatan: Menggunakan qualifier ukuran tidak berarti bahwa +

    Catatan: Menggunakan qualifier ukuran tidak berarti bahwa sumber daya hanya untuk layar ukuran itu saja. Jika Anda tidak menyediakan sumber daya alternatif dengan qualifier yang lebih cocok dengan konfigurasi perangkat saat ini, sistem dapat menggunakan sumber daya mana saja yang paling cocok.

    -

    Perhatian: Jika semua sumber daya Anda menggunakan -qualifier yang berukuran lebih besar daripada layar saat ini, sistem tidak akan menggunakannya dan aplikasi +

    Perhatian: Jika semua sumber daya Anda menggunakan +qualifier yang berukuran lebih besar daripada layar saat ini, sistem tidak akan menggunakannya dan aplikasi Anda akan crash saat runtime (misalnya, jika semua sumber daya layout ditandai dengan qualifier {@code xlarge}, namun perangkat memiliki ukuran layar normal).

    Ditambahkan dalam API level 4.

    - +

    Lihat Mendukung Beberapa Layar untuk informasi selengkapnya.

    Lihat juga bidang konfigurasi {@link android.content.res.Configuration#screenLayout}, @@ -552,7 +552,7 @@ tidak ada kaitannya dengan orientasi layar.

    Ini bisa berubah selama masa pakai aplikasi Anda jika pengguna memutar layar. Lihat Menangani Perubahan Runtime untuk informasi tentang bagaimana hal ini memengaruhi aplikasi Anda selama runtime.

    -

    Lihat juga bidang konfigurasi {@link android.content.res.Configuration#orientation}, +

    Lihat juga bidang konfigurasi {@link android.content.res.Configuration#orientation}, yang menunjukkan orientasi perangkat saat ini.

    @@ -569,19 +569,19 @@ yang menunjukkan orientasi perangkat saat ini.

    • {@code car}: Perangkat sedang menampilkan di dudukan perangkat di mobil
    • {@code desk}: Perangkat sedang menampilkan di dudukan perangkat di meja
    • -
    • {@code television}: Perangkat sedang menampilkan di televisi, yang menyediakan +
    • {@code television}: Perangkat sedang menampilkan di televisi, yang menyediakan pengalaman "sepuluh kaki" dengan UI-nya pada layar besar yang berada jauh dari pengguna, -terutama diorientasikan seputar DPAD atau +terutama diorientasikan seputar DPAD atau interaksi non-pointer lainnya
    • -
    • {@code appliance}: Perangkat berlaku sebagai +
    • {@code appliance}: Perangkat berlaku sebagai alat, tanpa tampilan
    • {@code watch}: Perangkat memiliki tampilan dan dikenakan di pergelangan tangan

    Ditambahkan dalam API level 8, televisi ditambahkan dalam API 13, jam ditambahkan dalam API 20.

    -

    Untuk informasi tentang cara aplikasi merespons saat perangkat dimasukkan +

    Untuk informasi tentang cara aplikasi merespons saat perangkat dimasukkan ke dalam atau dilepaskan dari dudukannya, bacalah Menentukan dan Memantau Kondisi dan Tipe Dudukan.

    -

    Ini bisa berubah selama masa pakai aplikasi jika pengguna menempatkan perangkat di +

    Ini bisa berubah selama masa pakai aplikasi jika pengguna menempatkan perangkat di dudukannya. Anda dapat mengaktifkan atau menonaktifkan sebagian mode ini menggunakan {@link android.app.UiModeManager}. Lihat Menangani Perubahan Runtime untuk informasi tentang bagaimana hal ini memengaruhi aplikasi Anda selama runtime.

    @@ -601,7 +601,7 @@ informasi tentang bagaimana hal ini memengaruhi aplikasi Anda selama runtime.

    Ditambahkan dalam API level 8.

    Ini bisa berubah selama masa pakai aplikasi jika mode malam dibiarkan dalam mode otomatis (default), dalam hal ini perubahan mode berdasarkan pada waktu hari. Anda dapat mengaktifkan -atau menonaktifkan mode ini menggunakan {@link android.app.UiModeManager}. Lihat Menangani Perubahan Runtime untuk informasi tentang bagaimana hal ini memengaruhi +atau menonaktifkan mode ini menggunakan {@link android.app.UiModeManager}. Lihat Menangani Perubahan Runtime untuk informasi tentang bagaimana hal ini memengaruhi aplikasi Anda selama runtime.

    @@ -627,8 +627,8 @@ aplikasi Anda selama runtime.

    Level 8.
  • {@code xxhdpi}: Layar densitas ekstra-ekstra-tinggi; sekitar 480 dpi. Ditambahkan dalam API Level 16.
  • -
  • {@code xxxhdpi}: Densitas ekstra-ekstra-ekstra-tinggi (hanya ikon launcher, -lihat catatan +
  • {@code xxxhdpi}: Densitas ekstra-ekstra-ekstra-tinggi (hanya ikon launcher, +lihat catatan dalam Mendukung Beberapa Layar); sekitar 640 dpi. Ditambahkan dalam API Level 18.
  • {@code nodpi}: Ini bisa digunakan untuk sumber daya bitmap yang tidak ingin Anda @@ -696,7 +696,7 @@ fisik. Lihat Menangani Perubahan Runtime untu hal ini memengaruhi aplikasi Anda selama runtime.

    Lihat juga bidang konfigurasi {@link android.content.res.Configuration#hardKeyboardHidden} dan {@link -android.content.res.Configuration#keyboardHidden}, yang menunjukkan visibilitas +android.content.res.Configuration#keyboardHidden}, yang menunjukkan visibilitas keyboard fisik dan visibilitas segala jenis keyboard (termasuk keyboard perangkat lunak), masing-masing.

    @@ -716,7 +716,7 @@ pengguna
  • {@code 12key}: Perangkat memiliki keyboard fisik 12 tombol, baik terlihat maupun tidak pada pengguna.
  • -

    Lihat juga bidang konfigurasi {@link android.content.res.Configuration#keyboard}, +

    Lihat juga bidang konfigurasi {@link android.content.res.Configuration#keyboard}, yang menunjukkan metode utama input teks yang tersedia.

    @@ -810,7 +810,7 @@ Sumber Daya.

  • Anda bisa menetapkan beberapa qualifier untuk satu set sumber daya, yang dipisahkan dengan tanda hubung. Misalnya, drawable-en-rUS-land berlaku untuk perangkat bahasa Inggris-AS dalam orientasi lanskap.
  • -
  • Qualifier harus dalam urutan seperti yang tercantum dalam tabel 2. +
  • Qualifier harus dalam urutan seperti yang tercantum dalam tabel 2. Misalnya:
    • Salah: drawable-hdpi-port/
    • @@ -947,7 +947,7 @@ layout-land/} untuk lanskap dan {@code layout-port/} untuk potret, biarkan salah {@code layout/} untuk lanskap dan {@code layout-port/} untuk potret.

      Sumber daya default perlu disediakan bukan hanya karena aplikasi mungkin berjalan pada -konfigurasi yang belum Anda antisipasi, namun juga karena versi baru Android terkadang menambahkan +konfigurasi yang belum Anda antisipasi, namun juga karena versi baru Android terkadang menambahkan qualifier konfigurasi yang tidak didukung oleh versi lama. Jika Anda menggunakan qualifier sumber daya baru, namun mempertahankan kompatibilitas kode dengan versi Android yang lebih lama, maka saat versi lama Android menjalankan aplikasi, aplikasi itu akan crash jika Anda tidak menyediakan sumber daya default, aplikasi @@ -1058,7 +1058,7 @@ Layar.

    • Kembali dan ulangi langkah 2, 3, dan 4 hingga tersisa satu direktori. Dalam contoh ini, orientasi -layar adalah qualifier berikutnya yang memiliki kecocokan. +layar adalah qualifier berikutnya yang memiliki kecocokan. Jadi, sumber daya yang tidak menetapkan orientasi layar akan dihapus:
       drawable-en/
      diff --git a/docs/html-intl/intl/in/guide/topics/resources/runtime-changes.jd b/docs/html-intl/intl/in/guide/topics/resources/runtime-changes.jd
      index c9a5ead63c77d4b1e36e5f2429bffd361746fbe0..09ad60c369ff1a10364a53dcf0a1f4830a080e18 100644
      --- a/docs/html-intl/intl/in/guide/topics/resources/runtime-changes.jd
      +++ b/docs/html-intl/intl/in/guide/topics/resources/runtime-changes.jd
      @@ -82,12 +82,12 @@ aktivitas untuk mempertahankan objek stateful.

      Untuk mempertahankan objek stateful dalam fragmen selama perubahan konfigurasi runtime:

        -
      1. Perluas kelas {@link android.app.Fragment} dan deklarasikan referensi ke objek stateful +
      2. Perluas kelas {@link android.app.Fragment} dan deklarasikan referensi ke objek stateful Anda.
      3. Panggil {@link android.app.Fragment#setRetainInstance(boolean)} saat fragmen dibuat.
      4. Tambahkan fragmen ke aktivitas.
      5. -
      6. Gunakan {@link android.app.FragmentManager} untuk mengambil fragmen saat aktivitas +
      7. Gunakan {@link android.app.FragmentManager} untuk mengambil fragmen saat aktivitas di-restart.
      @@ -125,8 +125,8 @@ membocorkan semua tampilan dan sumber daya instance aktivitas semula. (Sumber da berarti bahwa aplikasi Anda tetap menyimpannya dan tidak bisa dijadikan kumpulan sampah, sehingga bisa banyak memori yang hilang.)

      -

      Selanjutnya gunakan {@link android.app.FragmentManager} untuk menambahkan fragmen ke aktivitas. -Anda bisa memperoleh objek data dari fragmen saat aktivitas memulai kembali selama perubahan +

      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:

      diff --git a/docs/html-intl/intl/in/guide/topics/ui/controls.jd b/docs/html-intl/intl/in/guide/topics/ui/controls.jd
      index 7ee2957980a898008c8d5df15d821184e356a249..3ebf48b5c9d4cd261313ec9911c3a78bb3815411 100644
      --- a/docs/html-intl/intl/in/guide/topics/ui/controls.jd
      +++ b/docs/html-intl/intl/in/guide/topics/ui/controls.jd
      @@ -69,7 +69,7 @@ semacam kontrol input tertentu, Anda bisa membangun Tombol radio
               Mirip dengan kotak cek, hanya saja cuma satu opsi yang bisa dipilih dalam kumpulan tersebut.
      -	{@link android.widget.RadioGroup RadioGroup} 
      +	{@link android.widget.RadioGroup RadioGroup}
       	
      {@link android.widget.RadioButton RadioButton} diff --git a/docs/html-intl/intl/in/guide/topics/ui/declaring-layout.jd b/docs/html-intl/intl/in/guide/topics/ui/declaring-layout.jd index 83ff7461e7ac0bf0100abe1524ea6751fb6f58a0..1c8a0d6eccaa7dad039feebe8002db4c70fa4b91 100644 --- a/docs/html-intl/intl/in/guide/topics/ui/declaring-layout.jd +++ b/docs/html-intl/intl/in/guide/topics/ui/declaring-layout.jd @@ -74,7 +74,7 @@ tertarik dalam membuat instance objek View saat runtime, lihat referensi kelas { EditText.setText().

      Tip: Ketahui selengkapnya berbagai tipe layout dalam Objek -Layout Umum. Ada juga sekumpulan tutorial tentang cara membangun berbagai layout dalam panduan tutorial +Layout Umum. Ada juga sekumpulan tutorial tentang cara membangun berbagai layout dalam panduan tutorial Hello Views.

      Tulis XML

      @@ -107,7 +107,7 @@ dalam direktori res/layout/ proyek Android, sehingga nanti bisa dik

      Muat Sumber Daya XML

      -

      Saat mengompilasi aplikasi, masing-masing file layout XML akan dikompilasi dalam sebuah sumber daya +

      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 {@link android.app.Activity#setContentView(int) setContentView()}, @@ -367,8 +367,8 @@ kiri anak B) atau terhadap induk (disejajarkan dengan atas induknya).

      Membangun Layout dengan Adaptor

      -

      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. +

      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}—{@link android.widget.Adapter} @@ -445,7 +445,7 @@ 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 +android.database.Cursor} yang Anda inginkan dalam layout untuk setiap hasil dan larik integer yang menentukan tampilan yang sesuai untuk menempatkan masing-masing kolom:

       String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
      diff --git a/docs/html-intl/intl/in/guide/topics/ui/dialogs.jd b/docs/html-intl/intl/in/guide/topics/ui/dialogs.jd
      index 65714a9e4c4dfd1387b2be5f93d25362ed1fdffe..06a25ac5bcd3de44e470f10032a29d62d7e4a66a 100644
      --- a/docs/html-intl/intl/in/guide/topics/ui/dialogs.jd
      +++ b/docs/html-intl/intl/in/guide/topics/ui/dialogs.jd
      @@ -32,7 +32,7 @@ page.tags=alertdialog,dialogfragment
             
    • {@link android.app.DialogFragment}
    • {@link android.app.AlertDialog}
    • - +

      Lihat juga

      1. Panduan desain dialog
      2. @@ -89,7 +89,7 @@ pada layar besar dan kecil).

        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 +. Jika Anda ingin membuat picker tanggal atau waktu, Anda harus membaca panduan Picker.

        Catatan: @@ -235,8 +235,8 @@ AlertDialog dialog = builder.create();

      Metode set...Button() mengharuskan adanya judul bagi tombol (disediakan -oleh suatu sumber daya string) dan -{@link android.content.DialogInterface.OnClickListener} yang mendefinisikan tindakan yang diambil +oleh suatu sumber daya string) dan +{@link android.content.DialogInterface.OnClickListener} yang mendefinisikan tindakan yang diambil bila pengguna menekan tombol.

      Ada tiga macam tombol tindakan yang Anda bisa tambahkan:

      @@ -247,8 +247,8 @@ bila pengguna menekan tombol.

      Anda harus menggunakan tipe ini untuk membatalkan tindakan.
      Netral
      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".
      + namun tidak ingin membatalkan. Tipe ini muncul antara tombol positif dan +tombol negatif. Misalnya, tindakan bisa berupa "Ingatkan saya nanti".

      Anda hanya bisa menambahkan salah satu tipe tombol ke {@link @@ -271,7 +271,7 @@ Dialog dengan satu judul dan daftar.

    • Daftar pilihan ganda persisten (kotak cek)
    -

    Untuk membuat daftar pilihan tunggal seperti dalam gambar 3, +

    Untuk membuat daftar pilihan tunggal seperti dalam gambar 3, gunakan metode {@link android.app.AlertDialog.Builder#setItems setItems()}:

    @@ -291,7 +291,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
     
     

    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()}. +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 @@ -300,7 +300,7 @@ dengan data dinamis (seperti dari database) dengan menggunakan {@link android.wi

    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 +secara asinkron. Hal ini dijelaskan lebih jauh dalam panduan Membuat Layout dengan Adaptor dan Loader .

    @@ -317,11 +317,11 @@ Daftar item pilihan ganda.

    Menambahkan daftar pilihan ganda atau pilihan tunggal persisten

    -

    Untuk menambahkan daftar item pilihan ganda (kotak cek) atau -item pilihan tunggal (tombol radio), gunakan masing-masing metode +

    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) +DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()}, atau +{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()}.

    Misalnya, berikut ini cara membuat daftar pilihan ganda seperti @@ -346,7 +346,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // 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 + // Else, if the item is already in the array, remove it mSelectedItems.remove(Integer.valueOf(which)); } } @@ -373,7 +373,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

    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) +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.

    @@ -442,7 +442,7 @@ Anda harus mengubah keluarga font ke {@code "sans-serif"} sehingga kedua bidang gaya font yang cocok.

    Untuk memekarkan layout dalam {@link android.support.v4.app.DialogFragment} Anda, -ambillah {@link android.view.LayoutInflater} dengan +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. @@ -470,7 +470,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { public void onClick(DialogInterface dialog, int id) { LoginDialogFragment.this.getDialog().cancel(); } - }); + }); return builder.create(); }

    @@ -505,7 +505,7 @@ antarmuka yang akan digunakan untuk mengirim kembali suatu kejadian ke aktivitas
     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. */
    @@ -513,10 +513,10 @@ public class NoticeDialogFragment extends DialogFragment {
             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
         @Override
         public void onAttach(Activity activity) {
    @@ -543,7 +543,7 @@ melalui implementasi antarmuka {@code NoticeDialogListener}:

    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(); @@ -638,12 +638,12 @@ android.support.v4.app.Fragment} yang bisa ditanamkan.

    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} +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()}.

    -

    Berikut ini adalah contoh {@link android.support.v4.app.DialogFragment} yang bisa muncul sebagai +

    Berikut ini adalah contoh {@link android.support.v4.app.DialogFragment} yang bisa muncul sebagai dialog maupun fragmen yang bisa ditanamkan (menggunakan layout bernama purchase_items.xml):

    @@ -656,7 +656,7 @@ public class CustomDialogFragment extends DialogFragment {
             // 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. */
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
    @@ -678,7 +678,7 @@ atau UI layar penuh, berdasarkan ukuran layar:

    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"); @@ -776,7 +776,7 @@ android.support.v4.app.DialogFragment#onDismiss onDismiss()} dalam {@link android.support.v4.app.DialogFragment} Anda.

    Anda juga bisa membatalkan dialog. Ini merupakan kejadian khusus yang menunjukkan bahwa pengguna -secara eksplisit meninggalkan dialog tanpa menyelesaikan tugas. Hal ini terjadi jika pengguna menekan tombol +secara eksplisit meninggalkan dialog tanpa menyelesaikan tugas. Hal ini terjadi jika pengguna menekan tombol Back, 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).

    diff --git a/docs/html-intl/intl/in/guide/topics/ui/menus.jd b/docs/html-intl/intl/in/guide/topics/ui/menus.jd index 2cd3e6a33aa5ed330072ce116e9a0b91b4df6eb7..1ee0244c1a9af3355980c1d82078b83c2f4d4c6a 100644 --- a/docs/html-intl/intl/in/guide/topics/ui/menus.jd +++ b/docs/html-intl/intl/in/guide/topics/ui/menus.jd @@ -60,7 +60,7 @@ dan konsisten, Anda harus menggunakan API {@link android.view.Menu} untuk menyaj tindakan dan opsi lain dalam aktivitas kepada pengguna.

    Mulai dengan Android 3.0 (API level 11), perangkat berbasis Android tidak perlu lagi -menyediakan tombol Menu tersendiri. Dengan perubahan ini, aplikasi Android harus bermigrasi dari +menyediakan tombol Menu tersendiri. Dengan perubahan ini, aplikasi Android harus bermigrasi dari dependensi pada panel menu 6 item biasa, dan sebagai ganti menyediakan action-bar untuk menyajikan berbagai tindakan pengguna yang lazim.

    @@ -83,9 +83,9 @@ tidak memilikinya), sehingga Anda harus bermigrasi ke penggunaan action-bar untu opsi lainnya.

    Lihat bagian tentang Membuat Menu Opsi.

    - +
    Menu konteks dan mode tindakan kontekstual
    - +
    Menu konteks adalah menu mengambang yang muncul saat pengguna mengklik lama pada suatu elemen. Menu ini menyediakan tindakan yang memengaruhi konten atau bingkai konteks yang dipilih. @@ -94,7 +94,7 @@ item tindakan yang memengaruhi konten yang dipilih dalam baris di bagian atas la memilih beberapa item sekaligus.

    Lihat bagian tentang Membuat Menu Kontekstual.

    - +
    Menu popup
    Menu popup menampilkan daftar item secara vertikal yang dipasang pada tampilan yang memanggil menu. Ini cocok untuk menyediakan kelebihan tindakan yang terkait dengan konten tertentu atau @@ -128,14 +128,14 @@ ukuran layar, dan konfigurasi lainnya dengan memanfaatkan kerangka kerja
    <menu>
    -
    Mendefinisikan {@link android.view.Menu}, yang merupakan sebuah kontainer untuk item menu. Elemen +
    Mendefinisikan {@link android.view.Menu}, yang merupakan sebuah kontainer untuk item menu. Elemen <menu> harus menjadi simpul akar untuk file dan bisa menampung salah satu atau beberapa dari elemen <item> dan <group>.
    <item>
    Membuat {@link android.view.MenuItem}, yang mewakili satu item menu. Elemen ini bisa berisi elemen <menu> tersarang guna untuk membuat submenu.
    - +
    <group>
    Kontainer opsional tak terlihat untuk elemen-elemen {@code <item>}. Kontainer ini memungkinkan Anda mengelompokkan item menu untuk berbagi properti seperti status aktif dan visibilitas. Untuk informasi @@ -253,7 +253,7 @@ aktivitas. Jika perlu, Anda bisa menyusun ulang item menu dengan atribut {@code dalam setiap {@code <item>} yang perlu Anda pindahkan.

    Untuk menetapkan menu opsi suatu aktivitas, kesampingkan {@link -android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} (fragmen-fragmen menyediakan +android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} (fragmen-fragmen menyediakan callback {@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()} sendiri). Dalam metode ini , Anda bisa memekarkan sumber daya menu (yang didefinisikan dalam XML) menjadi {@link android.view.Menu} yang disediakan dalam callback. Misalnya:

    @@ -273,7 +273,7 @@ dengan API {@link android.view.MenuItem}.

    Jika Anda mengembangkan aplikasi untuk Android 2.3.x dan yang lebih rendah, sistem akan memanggil {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} untuk membuat menu opsi -bila pengguna membuka menu untuk pertama kali. Jika Anda mengembangkan aplikasi untuk Android 3.0 dan yang lebih tinggi, +bila pengguna membuka menu untuk pertama kali. Jika Anda mengembangkan aplikasi untuk Android 3.0 dan yang lebih tinggi, sistem akan memanggil {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} saat memulai aktivitas, untuk menampilkan item menu pada action-bar.

    @@ -285,7 +285,7 @@ memulai aktivitas, untuk menampilkan item menu pada action-bar.

    sistem akan memanggil metode {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} aktivitas Anda. Metode ini meneruskan {@link android.view.MenuItem} yang dipilih. Anda bisa mengidentifikasi item dengan memanggil {@link android.view.MenuItem#getItemId()}, yang menghasilkan -ID unik untuk item menu itu (yang didefinisikan oleh atribut {@code android:id} dalam sumber daya menu atau dengan +ID unik untuk item menu itu (yang didefinisikan oleh atribut {@code android:id} dalam sumber daya menu atau dengan integer yang diberikan ke metode {@link android.view.Menu#add(int,int,int,int) add()}). Anda bisa mencocokkan ID ini dengan item menu yang diketahui untuk melakukan tindakan yang sesuai. Misalnya:

    @@ -317,7 +317,7 @@ untuk setiap fragmen (sesuai dengan urutan penambahan fragmen) hingga satu fragm {@code true} atau semua fragmen telah dipanggil.

    Tip: Android 3.0 menambahkan kemampuan mendefinisikan perilaku on-click -untuk item menu dalam XML, dengan menggunakan atribut {@code android:onClick}. Nilai atribut +untuk item menu dalam XML, dengan menggunakan atribut {@code android:onClick}. Nilai atribut harus berupa nama metode yang didefinisikan aktivitas dengan menggunakan menu. Metode harus bersifat publik dan menerima satu parameter {@link android.view.MenuItem}—bila sistem memanggilnya, metode ini akan meneruskan item menu yang dipilih. Untuk informasi selengkapnya dan contoh, lihat dokumen Sumber Daya Menu.

    @@ -346,7 +346,7 @@ lagi kecuali menu diinvalidkan karena suatu alasan. Akan tetapi, Anda harus meng android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} hanya untuk membuat status menu awal dan tidak untuk membuat perubahan selama daur hidup aktivitas.

    -

    Jika Anda ingin mengubah menu opsi berdasarkan +

    Jika Anda ingin mengubah menu opsi berdasarkan kejadian yang terjadi selama daur hidup aktivitas, Anda bisa melakukannya dalam metode {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}. Metode ini meneruskan objek {@link android.view.Menu} sebagaimana adanya saat ini sehingga Anda bisa mengubahnya, @@ -363,7 +363,7 @@ ditampilkan pada action-bar. Bila ada kejadian dan Anda ingin melakukan pembarua memanggil {@link android.app.Activity#invalidateOptionsMenu invalidateOptionsMenu()} untuk meminta sistem memanggil {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}.

    -

    Catatan: +

    Catatan: Anda tidak boleh mengubah item dalam menu opsi berdasarkan {@link android.view.View} yang saat ini difokus. Saat dalam mode sentuh (bila pengguna tidak sedang menggunakan trackball atau d-pad), tampilan tidak bisa mengambil fokus, sehingga Anda tidak boleh menggunakan fokus sebagai dasar untuk mengubah @@ -419,7 +419,7 @@ android.app.Activity#registerForContextMenu(View) registerForContextMenu()}.

  • Implementasikan metode {@link -android.view.View.OnCreateContextMenuListener#onCreateContextMenu onCreateContextMenu()} +android.view.View.OnCreateContextMenuListener#onCreateContextMenu onCreateContextMenu()} dalam {@link android.app.Activity} atau {@link android.app.Fragment} Anda.

    Bila tampilan yang terdaftar menerima kejadian klik-lama, sistem akan memanggil metode {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu onCreateContextMenu()} @@ -445,7 +445,7 @@ dimekarkan.

  • Implementasikan {@link android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()}. -

    Bila pengguna memilih item menu, sistem akan memanggil metode ini sehingga Anda bisa melakukan +

    Bila pengguna memilih item menu, sistem akan memanggil metode ini sehingga Anda bisa melakukan tindakan yang sesuai. Misalnya:

    @@ -609,7 +609,7 @@ someView.setOnLongClickListener(new View.OnLongClickListener() {
     
     

    Bila Anda memanggil {@link android.app.Activity#startActionMode startActionMode()}, sistem akan mengembalikan {@link android.view.ActionMode} yang dibuat. Dengan menyimpannya dalam variabel anggota, Anda bisa -membuat perubahan ke action-bar kontekstual sebagai respons terhadap kejadian lainnya. Dalam contoh di atas, +membuat perubahan ke action-bar kontekstual sebagai respons terhadap kejadian lainnya. Dalam contoh di atas, {@link android.view.ActionMode} digunakan untuk memastikan bahwa instance {@link android.view.ActionMode} tidak dibuat kembali jika sudah aktif, dengan memeriksa apakah anggota bernilai nol sebelum memulai mode tindakan.

    @@ -742,8 +742,8 @@ yang menampilkan menu popup:

     <ImageButton
    -    android:layout_width="wrap_content" 
    -    android:layout_height="wrap_content" 
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
         android:src="@drawable/ic_overflow_holo_dark"
         android:contentDescription="@string/descr_overflow_button"
         android:onClick="showPopup" />
    @@ -1010,7 +1010,7 @@ pertama.

    Anda juga bisa menawarkan layanan aktivitas Anda pada aplikasi lainnya, sehingga aplikasi Anda bisa disertakan dalam menu aplikasi lain (membalik peran yang dijelaskan di atas).

    -

    Agar bisa dimasukkan dalam menu aplikasi lain, Anda perlu mendefinisikan +

    Agar bisa dimasukkan dalam menu aplikasi lain, Anda perlu mendefinisikan filter intent seperti biasa, tetapi pastikan menyertakan nilai-nilai {@link android.content.Intent#CATEGORY_ALTERNATIVE} dan/atau {@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} untuk kategori filter intent. Misalnya:

    @@ -1026,6 +1026,6 @@ kategori filter intent. Misalnya:

    Baca selengkapnya tentang penulisan filter intent dalam dokumen Intent dan Filter Intent.

    -

    Untuk contoh aplikasi yang menggunakan teknik ini, lihat contoh kode +

    Untuk contoh aplikasi yang menggunakan teknik ini, lihat contoh kode Note Pad.

    diff --git a/docs/html-intl/intl/in/guide/topics/ui/multi-window.jd b/docs/html-intl/intl/in/guide/topics/ui/multi-window.jd new file mode 100644 index 0000000000000000000000000000000000000000..5e7b3d927202fe12820c1e067155a899a473a470 --- /dev/null +++ b/docs/html-intl/intl/in/guide/topics/ui/multi-window.jd @@ -0,0 +1,589 @@ +page.title=Dukungan Multi-Jendela +page.metaDescription=Dukungan baru di Android N untuk menampilkan lebih dari satu aplikasi sekaligus. +page.keywords="multi-window", "android N", "split screen", "free-form" + +@jd:body + + + +

    + Android N menambahkan dukungan untuk menampilkan lebih dari satu aplikasi + sekaligus. Pada perangkat genggam, dua aplikasi bisa berjalan berdampingan atau + atas-bawah dalam mode layar terbagi. Pada perangkat TV, aplikasi bisa + menggunakan mode gambar-dalam-gambar untuk melanjutkan pemutaran video selagi pengguna + berinteraksi dengan aplikasi lain. +

    + +

    + Jika Anda membangun aplikasi Anda dengan N Preview SDK, Anda bisa mengonfigurasi cara aplikasi + menangani tampilan multi-jendela. Misalnya, Anda bisa menetapkan dimensi + minimum yang diizinkan aktivitas Anda. Anda juga bisa menonaktifkan tampilan multi-jendela untuk + aplikasi, sehingga memastikan sistem hanya menampilkan aplikasi Anda dalam mode + layar penuh. +

    + +

    Ringkasan

    + +

    + Android N memungkinkan beberapa aplikasi berbagi layar sekaligus. Misalnya, + pengguna bisa membagi layar, melihat halaman web di sisi kiri + sambil menulis email di sisi kanan. Pengalaman pengguna bergantung pada + perangkat: +

    + +
      +
    • Perangkat genggam yang menjalankan Android N menawarkan mode + layar terbagi. Di mode ini, sistem mengisi layar dengan dua aplikasi, menampilkannya secara + berdampingan atau atas-bawah. Pengguna bisa menyeret garis pembagi + yang memisahkan keduanya untuk membuat satu aplikasi lebih besar dan yang lainnya lebih kecil. +
    • + +
    • Pada Nexus Player yang menjalankan Android N, aplikasi bisa menempatkan diri + dalam mode gambar-dalam-gambar, yang memungkinkannya + untuk terus menampilkan materi selagi pengguna menjelajahi atau berinteraksi dengan + aplikasi lain. +
    • + +
    • Produsen perangkat berukuran lebih besar bisa memilih untuk mengaktifkan mode + bentuk bebas, di mana pengguna bisa bebas mengubah ukuran setiap aktivitas. Jika + produsen mengaktifkan fitur ini, perangkat akan menawarkan mode bentuk bebas sebagai tambahan + untuk mode layar terbagi. +
    • +
    + + +

    + Gambar 1. Dua aplikasi berjalan berdampingan dalam mode layar terbagi. +

    + +

    + Pengguna bisa beralih ke mode multi-jendela dengan cara berikut: +

    + +
      +
    • Jika pengguna membuka layar + Ringkasan dan menekan lama pada + judul aktivitas, mereka bisa menyeret aktivitas itu ke bagian yang disorot pada layar + untuk menempatkan aktivitas dalam mode multi-jendela. +
    • + +
    • Jika pengguna menekan lama pada tombol Ringkasan, perangkat akan menempatkan + aktivitas saat ini dalam mode multi-jendela, dan membuka layar Ringkasan guna + memungkinkan pengguna memilih aktivitas lain untuk berbagi layar. +
    • +
    + +

    + Pengguna bisa seret dan + lepas data dari aktivitas satu ke aktivitas lain sewaktu aktivitas berbagi + layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam aktivitas + tunggal.) +

    + +

    Daur Hidup Multi-Jendela

    + +

    + Mode multi-jendela tidak mengubah daur hidup + aktivitas. +

    + +

    + Dalam mode multi-jendela, hanya aktivitas yang paling sering digunakan pengguna + yang akan aktif pada waktu tertentu. Aktivitas ini dianggap teratas. + Semua aktivitas lainnya dalam keadaan berhenti sementara, sekalipun terlihat. + Akan tetapi, sistem memberikan aktivitas, yang berhenti-sementara-namun-terlihat ini, prioritas lebih tinggi + daripada aktivitas yang tidak terlihat. Jika pengguna berinteraksi dengan salah satu + aktivitas yang berhenti sementara, aktivitas tersebut akan dilanjutkan kembali, dan aktivitas + teratas sebelumnya akan dihentikan sementara. +

    + +

    + Catatan: Dalam mode multi-jendela, aplikasi bisa berada dalam keadaan berhenti sementara + dan masih terlihat oleh pengguna. Sebuah aplikasi mungkin perlu melanjutkan aktivitasnya + bahkan saat berhenti sementara. Misalnya, aplikasi pemutar video yang ada dalam + mode berhenti sementara namun terlihat harus tetap menampilkan videonya. Karena alasan + ini, kami menyarankan aktivitas yang memutar video tidak menghentikan sementara video + dalam handler {@link android.app.Activity#onPause onPause()} mereka. + Sebagai gantinya, aktivitas itu harus menghentikan sementara video di {@link android.app.Activity#onStop + onStop()}, dan melanjutkan pemutaran di {@link android.app.Activity#onStart + onStart()}. +

    + +

    + Bila pengguna menempatkan aplikasi dalam mode multi-jendela, sistem akan memberi tahu + aktivitas tersebut mengenai perubahan konfigurasi, sebagaimana ditetapkan dalam Menangani Perubahan + Waktu Proses. Hal ini juga terjadi ketika pengguna mengubah skala aplikasi, atau menempatkan kembali aplikasi + ke mode layar penuh. + Pada dasarnya, perubahan ini memiliki implikasi daur hidup aktivitas yang sama + seperti saat sistem memberi tahu aplikasi bahwa perangkat telah beralih + dari mode potret ke mode lanskap, kecuali dimensi perangkat + telah berubah sebagai ganti bertukar posisi. Seperti yang dibahas di Menangani Perubahan + Waktu Proses, aktivitas Anda bisa menangani perubahan konfigurasi itu sendiri, atau + mengizinkan sistem memusnahkan aktivitas dan membuatnya kembali dengan dimensi + baru. +

    + +

    + Jika pengguna mengubah ukuran jendela dan membuat dimensinya lebih besar, sistem + akan mengubah ukuran aktivitas untuk menyesuaikan dengan tindakan pengguna dan mengeluarkan perubahan waktu proses + bila diperlukan. Jika aplikasi tertinggal dibandingkan gambar di area yang baru diekspos, + sistem untuk sementara mengisi area tersebut dengan warna yang ditetapkan oleh atribut {@link + android.R.attr#windowBackground windowBackground} atau dengan atribut gaya + windowBackgroundFallback secara default. +

    + +

    Mengonfigurasi Aplikasi Anda untuk Mode Multi-Jendela

    + +

    + Jika aplikasi Anda menargetkan Android N, Anda bisa mengonfigurasi bagaimana dan + apakah aktivitas aplikasi Anda mendukung tampilan multi-jendela. Anda bisa menyetel + atribut dalam manifes untuk mengontrol ukuran dan layoutnya. + Setelan atribut aktivitas root berlaku pada semua aktivitas + dalam tumpukan tugasnya. Misalnya, jika aktivitas root memiliki + android:resizeableActivity yang disetel ke true, maka semua aktivitas + dalam tumpukan tugas bisa diubah ukurannya. +

    + +

    + Catatan: Jika Anda membangun aplikasi multi-orientasi dengan versi + SDK lebih rendah dari Android N, dan pengguna menggunakan aplikasi + dalam mode multi-jendela, sistem akan mengubah ukuran aplikasi secara paksa. Sistem akan menampilkan kotak + dialog yang memperingatkan pengguna bahwa aplikasi mungkin berperilaku tidak terduga. Sistem + tidak mengubah ukuran aplikasi yang berorientasi tetap; jika + pengguna berusaha membuka aplikasi berorientasi tetap saat mode multi-jendela, + aplikasi akan menggunakan seluruh layar. +

    + +

    android:resizeableActivity

    +

    + Setel atribut ini dalam manifes <activity> Anda atau simpul + <application> untuk mengaktifkan atau menonaktifkan tampilan + multi-jendela: +

    + +
    +android:resizeableActivity=["true" | "false"]
    +
    + +

    + Jika atribut ini disetel ke true, aktivitas bisa dijalankan di + mode layar terbagi dan mode bentuk bebas. Jika atribut ini disetel ke false, aktivitas + tidak akan mendukung mode multi-jendela. Jika nilai ini false, dan pengguna + berusaha memulai aktivitas dalam mode multi-jendela, aktivitas akan menggunakan + layar penuh. +

    + +

    + Jika aplikasi Anda menargetkan Android N, namun Anda tidak menetapkan nilai + untuk atribut ini, nilai atribut default adalah true. +

    + +

    android:supportsPictureInPicture

    + +

    + Setel atribut ini dalam simpul <activity> manifes Anda untuk + menunjukkan apakah aktivitas mendukung tampilan gambar-dalam-gambar. Atribut ini + diabaikan jika android:resizeableActivity bernilai false. +

    + +
    +android:supportsPictureInPicture=["true" | "false"]
    +
    + +

    Atribut layout

    + +

    + Dengan Android N, elemen manifes <layout> + mendukung beberapa atribut yang memengaruhi cara aktivitas berperilaku dalam + mode multi-jendela: +

    + +
    +
    + android:defaultWidth +
    + +
    + Lebar default aktivitas saat dijalankan dalam mode bentuk bebas. +
    + +
    + android:defaultHeight +
    + +
    + Tinggi default aktivitas saat dijalankan dalam mode bentuk bebas. +
    + +
    + android:gravity +
    + +
    + Penempatan awal dari aktivitas saat dibuka dalam mode bentuk bebas. Lihat referensi + {@link android.view.Gravity} untuk mengetahui nilai yang cocok. +
    + +
    + android:minimalHeight, android:minimalWidth +
    + +
    + Tinggi dan lebar minimum untuk aktivitas dalam mode layar terbagi + dan mode bentuk bebas. Jika pengguna memindahkan pembagi dalam mode layar terbagi + untuk membuat aktivitas lebih kecil dari minimum yang ditetapkan, sistem akan memangkas + aktivitas sesuai dengan ukuran yang diminta pengguna. +
    +
    + +

    + Misalnya, kode berikut menampilkan cara menetapkan ukuran dan lokasi default + aktivitas, dan ukuran minimumnya, bila aktivitas ditampilkan dalam + mode bentuk bebas: +

    + +
    +<activity android:name=".MyActivity">
    +    <layout android:defaultHeight="500dp"
    +          android:defaultWidth="600dp"
    +          android:gravity="top|end"
    +          android:minimalHeight="450dp"
    +          android:minimalWidth="300dp" />
    +</activity>
    +
    + +

    Menjalankan Aplikasi Anda dalam Mode Multi-Jendela

    + +

    + Android N menawarkan fungsionalitas baru untuk mendukung aplikasi yang bisa berjalan + dalam mode multi-jendela. +

    + +

    Fitur yang dinonaktifkan dalam mode multi-jendela

    + +

    + Fitur tertentu akan dinonaktifkan atau diabaikan bila perangkat berada dalam mode + multi-jendela, karena dianggap tidak logis bagi suatu aktivitas yang mungkin berbagi + layar perangkat dengan aktivitas atau aplikasi lainnya. Fitur tersebut meliputi: + +

      +
    • Beberapa opsi penyesuaian di System UI + dinonaktifkan; misalnya, aplikasi tidak bisa menyembunyikan bilah status + jika tidak berjalan dalam mode layar penuh. +
    • + +
    • Sistem akan mengabaikan perubahan pada atribut android:screenOrientation. +
    • +
    + +

    Pemberitahuan perubahan multi-jendela dan melakukan kueri

    + +

    + Metode baru berikut telah ditambahkan ke kelas {@link android.app.Activity} + untuk mendukung tampilan multi-jendela. Untuk mengetahui detail tentang setiap + metode, lihat Referensi N + Preview SDK. +

    + +
    +
    + Activity.isInMultiWindowMode() +
    + +
    + Panggil untuk mengetahui apakah aktivitas berada dalam mode multi-jendela. +
    + +
    + Activity.isInPictureInPictureMode() +
    + +
    + Panggil untuk mengetahui apakah aktivitas berada dalam mode gambar-dalam-gambar. + +

    + Catatan: Mode gambar-dalam-gambar adalah kasus khusus pada + mode multi-jendela. Jika myActivity.isInPictureInPictureMode() + mengembalikan nilai true, maka myActivity.isInMultiWindowMode() juga + mengembalikan nilai true. +

    +
    + +
    + Activity.onMultiWindowModeChanged() +
    + +
    + Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari + mode multi-jendela. Sistem akan meneruskan ke metode sebuah nilai true jika + aktivitas tersebut memasuki mode multi-jendela, dan nilai false jika aktivitas + tersebut meninggalkan mode multi-jendela. +
    + +
    + Activity.onPictureInPictureModeChanged() +
    + +
    + Sistem akan memanggil metode ini bila aktivitas masuk atau keluar dari + mode gambar-dalam-gambar. Sistem akan meneruskan ke metode sebuah nilai true jika + aktivitas tersebut memasuki mode gambar-dalam-gambar, dan nilai false jika aktivitas + tersebut meninggalkan mode gambar-dalam-gambar. +
    +
    + +

    + Ada juga versi {@link android.app.Fragment} untuk setiap + metode ini, misalnya Fragment.isInMultiWindowMode(). +

    + +

    Memasuki mode gambar-dalam-gambar

    + +

    + Untuk menempatkan aktivitas dalam mode gambar-dalam-gambar, panggil metode baru + Activity.enterPictureInPictureMode(). Metode ini tidak berpengaruh jika + perangkat tidak mendukung mode gambar-dalam-gambar. Untuk informasi selengkapnya, + lihat dokumentasi Gambar-dalam-Gambar. +

    + +

    Meluncurkan Aktivitas Baru dalam Mode Multi-Jendela

    + +

    + Bila meluncurkan aktivitas baru, Anda bisa memberi petunjuk pada sistem bahwa aktivitas + baru harus ditampilkan bersebelahan dengan aktivitas yang sedang aktif, jika memungkinkan. Caranya, + gunakan flag + Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT. Meneruskan + flag ini akan meminta perilaku berikut: +

    + +
      +
    • Jika perangkat berada dalam mode layar terbagi, sistem akan berupaya membuat + aktivitas baru di sebelah aktivitas yang meluncurkannya, sehingga kedua aktivitas tersebut + berbagi layar. Tidak ada jaminan sistem mampu melakukannya, namun sistem akan + membuat aktivitas bersebelahan jika memungkinkan. +
    • + +
    • Jika perangkat tidak berada dalam mode layar terbagi, flag ini tidak akan berpengaruh. +
    • +
    + +

    + Jika perangkat dalam mode bentuk bebas dan Anda menjalankan aktivitas baru, Anda bisa + menetapkan dimensi aktivitas baru dan lokasi layar dengan memanggil + ActivityOptions.setLaunchBounds(). Metode ini tidak berpengaruh jika + perangkat tidak berada dalam mode multi-jendela. +

    + +

    + Catatan: Jika Anda meluncurkan aktivitas dalam tumpukan tugas, aktivitas + tersebut akan menggantikan aktivitas pada layar, dengan mewarisi semua + properti multi-jendelanya. Jika Anda ingin meluncurkan aktivitas baru sebagai jendela + terpisah dalam mode multi-jendela, Anda harus meluncurkannya dalam tumpukan tugas baru. +

    + +

    Mendukung seret dan lepas

    + +

    + Pengguna bisa menyeret dan + melepas data dari satu aktivitas ke aktivitas yang lain selagi kedua aktivitas + berbagi layar. (Sebelumnya, pengguna hanya bisa menyeret dan melepas data dalam + aktivitas tunggal.) Karena alasan ini, Anda mungkin perlu menambahkan fungsionalitas + seret dan lepas ke aplikasi jika aplikasi saat ini belum mendukungnya. +

    + +

    + N Preview SDK menambahkan paket android.view + untuk mendukung seret dan lepas lintas-aplikasi. Untuk mengetahui detail tentang kelas dan metode + berikut, lihat Referensi N + Preview SDK. +

    + +
    +
    + android.view.DropPermissions +
    + +
    + Objek token bertanggung jawab menetapkan izin yang diberikan kepada aplikasi + yang menerima pelepasan tersebut. +
    + +
    + View.startDragAndDrop() +
    + +
    + Alias baru untuk {@link android.view.View#startDrag View.startDrag()}. Untuk + mengaktifkan seret dan lepas lintas-aktivitas, teruskan flag baru + View.DRAG_FLAG_GLOBAL. Jika Anda perlu memberikan izin URI ke + aktivitas penerima, teruskan flag baru, + View.DRAG_FLAG_GLOBAL_URI_READ atau + View.DRAG_FLAG_GLOBAL_URI_WRITE, sebagaimana mestinya. +
    + +
    + View.cancelDragAndDrop() +
    + +
    + Membatalkan operasi seret yang sedang berlangsung. Hanya bisa dipanggil oleh + aplikasi yang menghasilkan operasi seret. +
    + +
    + View.updateDragShadow() +
    + +
    + Menggantikan bayangan penyeretan untuk operasi seret yang sedang berlangsung. Hanya + bisa dipanggil oleh aplikasi yang menghasilkan operasi seret. +
    + +
    + Activity.requestDropPermissions() +
    + +
    + Meminta izin untuk URI materi yang diteruskan dengan {@link + android.content.ClipData} yang terdapat dalam {@link android.view.DragEvent}. +
    +
    + +

    Menguji Dukungan Multi-Jendela Aplikasi Anda

    + +

    + Apakah Anda memperbarui aplikasi untuk Android N atau tidak, Anda harus + verifikasi bagaimana perilakunya di mode multi-jendela saat pengguna mencoba untuk menjalankannya + dalam mode multi-jendela pada perangkat yang menjalankan Android N. +

    + +

    Mengonfigurasi Perangkat Pengujian

    + +

    + Jika Anda pasang Android N pada perangkat, mode + layar terbagi secara otomatis didukung. +

    + +

    Jika aplikasi Anda tidak dibangun dengan N Preview SDK

    + +

    + Jika Anda tidak membangun aplikasi dengan N Preview SDK dan pengguna berupaya menggunakan + aplikasi dalam mode multi-jendela, sistem secara paksa akan mengubah ukuran aplikasi kecuali jika aplikasi + mendeklarasikan orientasi tetap. +

    + +

    + Jika aplikasi Anda tidak mendeklarasikan orientasi tetap, Anda harus meluncurkan aplikasi + pada perangkat yang menjalankan Android N dan berupaya menempatkan aplikasi tersebut dalam + mode layar terbagi. Verifikasi pengalaman pengguna + bisa diterima bila aplikasi secara paksa diubah ukurannya. +

    + +

    + Jika aplikasi mendeklarasikan orientasi tetap, Anda harus berupaya menempatkan aplikasi dalam + mode multi-jendela. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam + mode layar penuh. +

    + +

    Jika Anda mendukung mode multi-jendela

    + +

    + Jika Anda membuat aplikasi Anda dengan N Preview SDK dan belum menonaktifkan + dukungan multi-jendela, verifikasi perilaku berikut dalam mode layar terbagi + dan mode bentuk bebas. +

    + +
      +
    • Luncurkan aplikasi dalam mode layar penuh, kemudian beralih ke mode multi-jendela dengan + menekan lama pada tombol Ringkasan. Verifikasi apakah aplikasi beralih dengan benar. +
    • + +
    • Jalankan aplikasi secara langsung dalam mode multi-jendela, dan verifikasi aplikasi + diluncurkan dengan benar. Anda bisa meluncurkan aplikasi dalam mode multi-jendela dengan menekan + tombol Ringkasan, kemudian menekan lama baris judul pada aplikasi Anda dan menyeretnya + ke salah satu area yang disorot di layar. +
    • + +
    • Ubah ukuran aplikasi Anda dalam mode layar terbagi dengan menyeret garis pembagi. + Verifikasi apakah aplikasi mengubah ukuran tanpa mogok, dan apakah elemen UI yang diperlukan + terlihat. +
    • + +
    • Jika Anda telah menetapkan dimensi minimum aplikasi, cobalah untuk mengubah ukuran + aplikasi di bawah dimensi tersebut. Verifikasi apakah Anda tidak bisa mengubah ukuran aplikasi menjadi + lebih kecil dari minimum yang ditetapkan. +
    • + +
    • Melalui semua pengujian, verifikasi apakah kinerja aplikasi Anda bisa diterima. Misalnya, + verifikasi apakah tidak ada jeda yang terlalu lama untuk memperbarui UI setelah + aplikasi diubah ukurannya. +
    • +
    + +

    Daftar periksa pengujian

    + +

    + Untuk verifikasi kinerja aplikasi Anda dalam mode multi-jendela, cobalah operasi + berikut. Anda harus mencoba semua operasi ini dalam mode layar terbagi dan + dan mode multi-jendela, kecuali jika dinyatakan berbeda. +

    + +
      +
    • Masuki dan tinggalkan mode multi-jendela. +
    • + +
    • Beralih dari aplikasi Anda ke aplikasi lain, dan verifikasi apakah aplikasi berperilaku + sebagaimana mestinya saat terlihat namun tidak aktif. Misalnya, jika aplikasi Anda + sedang memutar video, verifikasi apakah video terus diputar selagi pengguna + berinteraksi dengan aplikasi lain. +
    • + +
    • Dalam mode layar terbagi, cobalah menggeser garis pembagi untuk membuat aplikasi + Anda menjadi lebih besar dan lebih kecil. Coba operasi ini dalam konfigurasi berdampingan dan + atas-bawah. Verifikasi apakah aplikasi tidak mogok, + fungsionalitas penting bisa terlihat, dan operasi mengubah ukuran tidak memakan waktu terlalu + lama. +
    • + +
    • Lakukan beberapa operasi ubah ukuran berturut-turut dalam waktu cepat. Verifikasi apakah + aplikasi Anda tidak mogok atau mengalami kebocoran memori. Untuk informasi tentang memeriksa penggunaan memori + aplikasi Anda, lihat + Menyelidiki Penggunaan RAM Anda. +
    • + +
    • Gunakan aplikasi secara normal di sejumlah konfigurasi jendela yang berbeda, dan + verifikasi apakah aplikasi berperilaku sebagaimana mestinya. Verifikasi apakah teks terbaca, dan apakah + elemen UI tidak terlalu kecil untuk interaksi. +
    • +
    + +

    Jika Anda telah menonaktifkan dukungan multi-jendela

    + +

    + Jika Anda menonaktifkan dukungan multi-jendela dengan menyetel + android:resizableActivity="false", Anda harus menjalankan aplikasi pada + perangkat yang menjalankan Android N dan berusaha menempatkan aplikasi dalam + mode bentuk bebas dan mode layar terbagi. Verifikasi apakah saat Anda melakukannya, aplikasi tetap berada dalam + mode layar penuh. +

    diff --git a/docs/html-intl/intl/in/guide/topics/ui/notifiers/notifications.jd b/docs/html-intl/intl/in/guide/topics/ui/notifiers/notifications.jd index 9033b9f744f3ec34d46dc4ca5d6b180c92e55b5a..bb48b80a0bcc6dfc4c145fc7d95fa1645ade683f 100644 --- a/docs/html-intl/intl/in/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html-intl/intl/in/guide/topics/ui/notifiers/notifications.jd @@ -147,7 +147,7 @@ pemberitahuan, Anda meneruskan objek {@link android.app.Notification} ke sistem

    Dalam {@link android.app.Notification}, tindakan itu sendiri didefinisikan oleh - {@link android.app.PendingIntent} berisi + {@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 @@ -174,12 +174,12 @@ pemberitahuan, Anda meneruskan objek {@link android.app.Notification} ke sistem 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, + android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); jika tidak diatur, prioritas default akan ditetapkan {@link android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0).

    Untuk informasi tentang mengatur level prioritas, lihat "Mengatur - dan mengelola prioritas pemberitahuan dengan benar" dalam panduan + dan mengelola prioritas pemberitahuan dengan benar" dalam panduan Desain Pemberitahuan.

    @@ -310,7 +310,7 @@ mBuilder.setStyle(inBoxStyle);

    Mengelola Pemberitahuan

    - Bila perlu mengeluarkan pemberitahuan beberapa kali untuk tipe kejadian yang sama, + 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.

    @@ -506,7 +506,7 @@ numMessages = 0; TaskStackBuilder.create()}.
  • - Tambahkan back-stack ke stack-builder dengan memanggil + 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 @@ -933,7 +933,7 @@ untuk informasi selengkapnya tentang API baru untuk mengelola sesi media dan men tampilan normal dibatasi hingga 64 dp, dan layout tampilan yang diperluas dibatasi hingga 256 dp.

    - Untuk mendefinisikan layout pemberitahuan custom, mulailah dengan membuat instance + 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()}, diff --git a/docs/html-intl/intl/in/guide/topics/ui/overview.jd b/docs/html-intl/intl/in/guide/topics/ui/overview.jd index a0b2b0645a900aa1fd20cfaf49f011e33c0352c7..ca8b42085ac27135703c2bbb58bf4a313369b764 100644 --- a/docs/html-intl/intl/in/guide/topics/ui/overview.jd +++ b/docs/html-intl/intl/in/guide/topics/ui/overview.jd @@ -39,7 +39,7 @@ dan elemen <LinearLayout> membuat kelompok tampilan {@link an

     <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -              android:layout_width="fill_parent" 
    +              android:layout_width="fill_parent"
                   android:layout_height="fill_parent"
                   android:orientation="vertical" >
         <TextView android:id="@+id/text"
    @@ -60,7 +60,7 @@ layout.

    Untuk mendapatkan panduan lengkap mengenai pembuatan layout UI, lihat Layout XML. - +

    Komponen Antarmuka Pengguna

    Anda tidak harus membuat semua UI menggunakan objek {@link android.view.View} dan {link diff --git a/docs/html-intl/intl/in/guide/topics/ui/settings.jd b/docs/html-intl/intl/in/guide/topics/ui/settings.jd index 5ac61f928c19e9993b52b99aff77720543584e53..89be52fc2a73a9a213752a635725ac0d0fe2b19a 100644 --- a/docs/html-intl/intl/in/guide/topics/ui/settings.jd +++ b/docs/html-intl/intl/in/guide/topics/ui/settings.jd @@ -82,7 +82,7 @@ cara membangun pengaturan aplikasi Anda menggunakan API {@link android.preferenc

    Gambar 1. Cuplikan layar dari pengaturan -aplikasi Messaging Android. Memilih item yang didefinisikan oleh {@link android.preference.Preference} +aplikasi Messaging Android. Memilih item yang didefinisikan oleh {@link android.preference.Preference} akan membuka antarmuka untuk mengubah pengaturan.

    @@ -163,7 +163,7 @@ tersimpan bisa berupa tipe nilai apa pun yang didukung (tercantum di atas). java.lang.String}. -

    Lihat kelas {@link android.preference.Preference} untuk mengetahui daftar subkelas lain dan +

    Lihat kelas {@link android.preference.Preference} untuk mengetahui daftar subkelas lain dan propertinya.

    Tentu saja, kelas bawaan tidak mengakomodasi setiap kebutuhan dan aplikasi Anda mungkin memerlukan @@ -226,7 +226,7 @@ android.preference.ListPreference}. Kedua item tersebut menyertakan tiga atribut

    {@code android:key}
    Atribut ini diperlukan untuk preferensi yang mempertahankan nilai data. Ini menetapkan kunci unik (string) yang digunakan sistem saat menyimpan nilai pengaturan ini dalam {@link -android.content.SharedPreferences}. +android.content.SharedPreferences}.

    Instance satu-satunya di mana atribut ini tidak diperlukan adalah bila preferensi berupa {@link android.preference.PreferenceCategory} atau {@link android.preference.PreferenceScreen}, atau preferensi menetapkan {@link android.content.Intent} untuk dipanggil (dengan elemen {@code <intent>}) atau {@link android.app.Fragment} untuk ditampilkan (dengan atribut {@code @@ -285,7 +285,7 @@ android.preference.PreferenceCategory}.

     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    -    <PreferenceCategory 
    +    <PreferenceCategory
             android:title="@string/pref_sms_storage_title"
             android:key="pref_key_storage_settings">
             <CheckBoxPreference
    @@ -293,12 +293,12 @@ android.preference.PreferenceCategory}.

    android:summary="@string/pref_summary_auto_delete" android:title="@string/pref_title_auto_delete" android:defaultValue="false"... /> - <Preference + <Preference android:key="pref_key_sms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_sms_delete"... /> - <Preference + <Preference android:key="pref_key_mms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" @@ -370,12 +370,12 @@ sebagai anak dari elemen {@code <Preference>} yang bersangkutan.

    {@code android:action}
    -
    Tindakan yang akan ditetapkan, sesuai metode +
    Tindakan yang akan ditetapkan, sesuai metode {@link android.content.Intent#setAction setAction()}.
    {@code android:data}
    Data yang akan ditetapkan, sesuai metode {@link android.content.Intent#setData setData()}.
    {@code android:mimeType}
    -
    Tipe MIME yang akan ditetapkan, sesuai metode +
    Tipe MIME yang akan ditetapkan, sesuai metode {@link android.content.Intent#setType setType()}.
    {@code android:targetClass}
    Bagian kelas dari nama komponen, sesuai metode {@link android.content.Intent#setComponent @@ -588,11 +588,11 @@ tunggal dalam elemen {@code <preference-headers>} akar. Misalnya:

     <?xml version="1.0" encoding="utf-8"?>
     <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one" />
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" >
    @@ -672,15 +672,15 @@ android.preference.Preference <Preference>} mengirimkan {@link android.con
     akan dimuat.

    Misalnya, ini adalah file XML untuk header preferensi yang menggunakan Android 3.0 -dan yang lebih tinggi ({@code res/xml/preference_headers.xml}):

    +dan yang lebih tinggi ({@code res/xml/preference_headers.xml}):

     <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsFragmentOne"
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one" />
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsFragmentTwo"
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" />
    @@ -692,18 +692,18 @@ Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):

     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    -    <Preference 
    +    <Preference
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one"  >
    -        <intent 
    +        <intent
                 android:targetPackage="com.example.prefs"
                 android:targetClass="com.example.prefs.SettingsActivity"
                 android:action="com.example.prefs.PREFS_ONE" />
         </Preference>
    -    <Preference 
    +    <Preference
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" >
    -        <intent 
    +        <intent
                 android:targetPackage="com.example.prefs"
                 android:targetClass="com.example.prefs.SettingsActivity"
                 android:action="com.example.prefs.PREFS_TWO" />
    @@ -879,7 +879,7 @@ prefs.registerOnSharedPreferenceChangeListener(
     });
     
    -

    Sebagai gantinya, simpan referensi ke listener dalam bidang data instance +

    Sebagai gantinya, simpan referensi ke listener dalam bidang data instance objek yang akan ada selama listener dibutuhkan:

    @@ -975,11 +975,11 @@ negatif dan positif default:

    public class NumberPickerPreference extends DialogPreference { public NumberPickerPreference(Context context, AttributeSet attrs) { super(context, attrs); - + setDialogLayoutResource(R.layout.numberpicker_dialog); setPositiveButtonText(android.R.string.ok); setNegativeButtonText(android.R.string.cancel); - + setDialogIcon(null); } ... @@ -1194,7 +1194,7 @@ protected void onRestoreInstanceState(Parcelable state) { // Cast state to custom BaseSavedState and pass to superclass SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); - + // Set this Preference's widget to reflect the restored state mNumberPicker.setValue(myState.value); } diff --git a/docs/html-intl/intl/in/guide/topics/ui/ui-events.jd b/docs/html-intl/intl/in/guide/topics/ui/ui-events.jd index 5068176fccaefce46166e9b4aceb85e35cfef955..0307b34a85c1e8616a0976afbf35049a70b66807 100644 --- a/docs/html-intl/intl/in/guide/topics/ui/ui-events.jd +++ b/docs/html-intl/intl/in/guide/topics/ui/ui-events.jd @@ -26,11 +26,11 @@ tindakan terjadi pada objek itu. Misalnya, bila View (seperti Button/Tombol) dis metode onTouchEvent() 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, +sekumpulan antarmuka tersarang dengan callback yang jauh lebih mudah didefinisikan. Antarmuka ini, yang disebut
    event listener, merupakan tiket Anda untuk menangkap interaksi pengguna dengan UI.

    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 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 event handler.

    @@ -46,28 +46,28 @@ telah didaftarkan dengan listener dipicu oleh interaksi pengguna dengan item dal
    onClick()
    -
    Dari {@link android.view.View.OnClickListener}. +
    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.
    onLongClick()
    -
    Dari {@link android.view.View.OnLongClickListener}. - Ini dipanggil baik saat pengguna menyentuh dan menahan item (bila dalam mode sentuh), +
    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).
    onFocusChange()
    -
    Dari {@link android.view.View.OnFocusChangeListener}. +
    Dari {@link android.view.View.OnFocusChangeListener}. Ini dipanggil saat pengguna menyusuri ke atau dari item, dengan menggunakan tombol navigasi atau trackball.
    onKey()
    -
    Dari {@link android.view.View.OnKeyListener}. +
    Dari {@link android.view.View.OnKeyListener}. Ini dipanggil saat pengguna memfokuskan pada item dan menekan atau melepas tombol fisik pada perangkat.
    onTouch()
    -
    Dari {@link android.view.View.OnTouchListener}. +
    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).
    onCreateContextMenu()
    -
    Dari {@link android.view.View.OnCreateContextMenuListener}. - Ini dipanggil saat Menu Konteks sedang dibuat (akibat "klik lama" terus-menerus). Lihat diskusi +
    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 Menu.
    @@ -75,8 +75,8 @@ tentang menu konteks di panduan pengembang Catatan: Android akan memanggil event handler terlebih dahulu kemudian handler -default yang sesuai dari definisi kelas. Karena itu, mengembalikan benar dari event listener ini akan menghentikan -penyebaran kejadian ke event listener lain dan juga akan memblokir callback ke +default yang sesuai dari definisi kelas. Karena itu, mengembalikan benar 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 true.

    Event Handler

    -

    Jika Anda membuat komponen custom dari View, maka Anda dapat mendefinisikan penggunaan beberapa +

    Jika Anda membuat komponen custom dari View, maka Anda dapat mendefinisikan penggunaan beberapa metode callback sebagai event handler default. Dalam dokumen tentang Komponen Custom, Anda akan melihat penggunaan beberapa callback umum untuk penanganan kejadian, @@ -176,19 +176,19 @@ termasuk:

  • {@link android.view.View#onTouchEvent} - Dipanggil bila terjadi kejadian gerakan layar sentuh.
  • {@link android.view.View#onFocusChanged} - Dipanggil bila View memperoleh atau kehilangan fokus.
  • -

    Ada beberapa metode lain yang harus Anda ketahui, yang bukan bagian dari kelas View, +

    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:

    • {@link android.app.Activity#dispatchTouchEvent(MotionEvent) - Activity.dispatchTouchEvent(MotionEvent)} - Ini memungkinkan {@link + Activity.dispatchTouchEvent(MotionEvent)} - Ini memungkinkan {@link android.app.Activity} Anda mencegat semua kejadian sentuh sebelum dikirim ke jendela.
    • {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent) ViewGroup.onInterceptTouchEvent(MotionEvent)} - Ini memungkinkan {@link android.view.ViewGroup} memantau kejadian saat dikirim ke View anak.
    • {@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) ViewParent.requestDisallowInterceptTouchEvent(boolean)} - Panggil ini - pada View induk untuk menunjukan larangan mencegat kejadian sentuh dengan {@link + pada View induk untuk menunjukan larangan mencegat kejadian sentuh dengan {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}.
    @@ -199,11 +199,11 @@ perlu memberikan fokus pada item tindakan (seperti tombol) agar pengguna bisa me 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". +untuk interaksi yang bernama "mode sentuh".

    Untuk perangkat berkemampuan sentuh, setelah pengguna menyentuh layar, perangkat -akan masuk ke mode sentuh. Dari sini dan selanjutnya, hanya View dengan +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. @@ -214,7 +214,7 @@ keluar dari mode sentuh, dan mencari tampilan untuk difokuskan. Kini pengguna bi dengan antarmuka pengguna tanpa menyentuh layar.

    -Status mode sentuh dipertahankan di seluruh sistem (semua jendela dan aktivitas). +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.

    @@ -257,7 +257,7 @@ mana pun, tidak pula akan menyusuri ke bawah dari Button kedua. Karena sekarang mendefinisikan Button bawah sebagai nextFocusUp (dan sebaliknya), fokus navigasi akan silih berganti dari atas ke bawah dan bawah ke atas.

    -

    Jika Anda ingin mendeklarasikan View sebagai dapat difokus dalam UI (bila biasanya tidak dapat difokus), +

    Jika Anda ingin mendeklarasikan View sebagai dapat difokus dalam UI (bila biasanya tidak dapat difokus), tambahkan atribut XML android:focusable ke View, dalam deklarasi layout Anda. Atur nilai true. Anda juga bisa mendeklarasikan View sebagai dapat difokus saat dalam Mode Sentuh dengan android:focusableInTouchMode.

    @@ -282,7 +282,7 @@ sebagai dapat difokus saat dalam Mode Sentuh dengan android:focusableInTou the framework will take care of measuring, laying out, and drawing the tree as appropriate.
  • - +

    Note: 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 diff --git a/docs/html-intl/intl/in/preview/_book.yaml b/docs/html-intl/intl/in/preview/_book.yaml deleted file mode 100644 index 88d6c715666d03431b592d085fa15d4a5ed18969..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/_book.yaml +++ /dev/null @@ -1,342 +0,0 @@ -toc: -- title: Ringkasan Program - path: /preview/overview.html - path_attributes: - - name: es-lang - value: Información general del programa - - name: in-lang - value: Ringkasan Program - - name: ja-lang - value: プログラム概要 - - name: ko-lang - value: 프로그램 개요 - - name: pt-br-lang - value: Visão geral do programa - - name: ru-lang - value: Обзор программы - - name: vi-lang - value: Tổng quan về Chương trình - - name: zh-cn-lang - value: 计划概览 - - name: zh-tw-lang - value: 程式總覽 - -- title: Dukungan dan Catatan Rilis - path: /preview/support.html - -- title: Menyiapkan Pratinjau - path: /preview/setup-sdk.html - path_attributes: - - name: es-lang - value: Configurar el SDK de la versión preliminar - - name: in-lang - value: Menyiapkan Pratinjau - - name: ja-lang - value: Preview SDK のセットアップ - - name: ko-lang - value: 미리 보기 SDK 설정하기 - - name: pt-br-lang - value: Configuração do Preview SDK - - name: ru-lang - value: Настройка пакета SDK Preview - - name: vi-lang - value: Kiểm thử trên Thiết bị - - name: zh-cn-lang - value: 设置预览版 SDK - - name: zh-tw-lang - value: 設定預覽版 SDK - -- title: Menguji pada Perangkat - path: /preview/download.html - path_attributes: - - name: es-lang - value: Pruebe en un dispositivo - - name: in-lang - value: Menguji pada Perangkat - - name: ja-lang - value: デバイス上でテストする - - name: ko-lang - value: 기기에서 테스트 - - name: pt-br-lang - value: Testar em um dispositivo - - name: ru-lang - value: Тестирование на устройстве - - name: vi-lang - value: Kiểm thử trên Thiết bị - - name: zh-cn-lang - value: 在设备上测试 - - name: zh-tw-lang - value: 在裝置上測試 - -- title: Perubahan Perilaku - path: /preview/behavior-changes.html - path_attributes: - - name: es-lang - value: Cambios en los comportamientos - - name: in-lang - value: Perubahan Perilaku - - name: ja-lang - value: 動作の変更点 - - name: ko-lang - value: 동작 변경 - - name: pt-br-lang - value: Mudanças de comportamento - - name: ru-lang - value: Изменения в работе - - name: vi-lang - value: Các thay đổi Hành vi - - name: zh-cn-lang - value: 行为变更 - - name: zh-tw-lang - value: 行為變更 - section: - - title: Optimalisasi Latar Belakang - path: /preview/features/background-optimization.html - path_attributes: - - name: es-lang - value: Optimizaciones en segundo plano - - name: in-lang - value: Optimisasi Latar Belakang - - name: ja-lang - value: バックグラウンド処理の最適化 - - name: ko-lang - value: 백그라운드 최적화 - - name: pt-br-lang - value: Otimizações em segundo plano - - name: ru-lang - value: Оптимизация фоновых процессов - - name: vi-lang - value: Tối ưu hóa Chạy ngầm - - name: zh-cn-lang - value: 后台优化 - - name: zh-tw-lang - value: 背景最佳化 - - title: Bahasa dan Lokal - path: /preview/features/multilingual-support.html - path_attributes: - - name: es-lang - value: Idioma y configuración regional - - name: in-lang - value: Bahasa dan Lokal - - name: ja-lang - value: 言語とロケール - - name: ko-lang - value: 언어 및 로케일 - - name: pt-br-lang - value: Idioma e localidade - - name: ru-lang - value: Язык и языковой стандарт - - name: vi-lang - value: Ngôn ngữ và Bản địa - - name: zh-cn-lang - value: 语言和区域设置 - - name: zh-tw-lang - value: 語言和地區設定 - -- title: Android N for Developers - path: /preview/api-overview.html - path_attributes: - - name: es-lang - value: Información general de la API - - name: in-lang - value: Android N untuk Pengembang - - name: ja-lang - value: API の概要 - - name: ko-lang - value: API 개요 - - name: pt-br-lang - value: Visão geral da API - - name: ru-lang - value: Обзор API-интерфейсов - - name: vi-lang - value: Android N cho Nhà phát triển - - name: zh-cn-lang - value: API 概览 - - name: zh-tw-lang - value: API 總覽 - section: - - title: Dukungan Multi-Jendela - path: /preview/features/multi-window.html - path_attributes: - - name: es-lang - value: Compatibilidad con ventanas múltiples - - name: in-lang - value: Dukungan Multi-Jendela - - name: ja-lang - value: マルチ ウィンドウのサポート - - name: ko-lang - value: 다중 창 지원 - - name: pt-br-lang - value: Suporte a várias janelas - - name: ru-lang - value: Поддержка многооконного режима - - name: vi-lang - value: Hỗ trợ đa cửa sổ - - name: zh-cn-lang - value: 多窗口支持 - - name: zh-tw-lang - value: 多視窗支援 - - title: Pemberitahuan - path: /preview/features/notification-updates.html - path_attributes: - - name: es-lang - value: Notificaciones - - name: in-lang - value: Pemberitahuan - - name: ja-lang - value: 通知 - - name: ko-lang - value: 알림 - - name: pt-br-lang - value: Notificações - - name: ru-lang - value: Уведомления - - name: vi-lang - value: Thông báo - - name: zh-cn-lang - value: 通知 - - name: zh-tw-lang - value: 通知 - - title: Data Saver - path: /preview/features/data-saver.html - - title: Perekaman TV - path: /preview/features/tv-recording-api.html - path_attributes: - - name: es-lang - value: Grabación de TV - - name: in-lang - value: Perekaman TV - - name: ja-lang - value: TV の録画 - - name: ko-lang - value: TV 녹화 - - name: pt-br-lang - value: Gravação para TV - - name: ru-lang - value: Запись ТВ - - name: vi-lang - value: Ghi lại TV - - name: zh-cn-lang - value: TV 录制 - - name: zh-tw-lang - value: 電視錄製 - - title: Konfigurasi Keamanan Jaringan - path: /preview/features/security-config.html - path_attributes: - - name: es-lang - value: Configuración de seguridad de la red - - name: ja-lang - value: ネットワーク セキュリティ構成 - - name: ko-lang - value: 네트워크 보안 구성 - - name: pt-br-lang - value: Configurações de segurança de rede - - name: ru-lang - value: Конфигурация сетевой безопасности - - name: vi-lang - value: Cấu hình Bảo mật mạng - - name: zh-cn-lang - value: 网络安全配置 - - name: zh-tw-lang - value: 網路安全性設定 - - title: Dukungan ICU4J - path: /preview/features/icu4j-framework.html - path_attributes: - - name: es-lang - value: API de ICU4J del framework de Android - - name: in-lang - value: ICU4J Android Framework API - - name: ja-lang - value: ICU4J Android フレームワーク API - - name: ko-lang - value: ICU4J Android 프레임워크 API - - name: pt-br-lang - value: APIs de estrutura do Android para ICU4J - - name: ru-lang - value: API-интерфейсы ICU4J в платформе Android - - name: vi-lang - value: API Khuôn khổ Android ICU4J - - name: zh-cn-lang - value: ICU4J Android 框架 API - - name: zh-tw-lang - value: ICU4J Android 架構 API - - title: Fitur Bahasa Java 8 - path: /preview/j8-jack.html - path_attributes: - - name: es-lang - value: Funciones del lenguaje Java 8 - - name: in-lang - value: Fitur Bahasa Java 8 - - name: ja-lang - value: Java 8 の機能 - - name: ko-lang - value: Java 8 언어 기능 - - name: pt-br-lang - value: Recursos de linguagem do Java 8 - - name: ru-lang - value: Возможности языка Java 8 - - name: vi-lang - value: Tính năng của Ngôn ngữ Java 8 - - name: zh-cn-lang - value: Java 8 语言功能 - - name: zh-tw-lang - value: Java 8 語言功能 - - title: Pembaruan Android for Work - path: /preview/features/afw.html - - title: Scoped Directory Access - path: /preview/features/scoped-folder-access.html - path_attributes: - - name: es-lang - value: Acceso a directorios determinados - - name: ja-lang - value: 特定のディレクトリへのアクセス - - name: ko-lang - value: 범위가 지정된 디렉터리 액세스 - - name: pt-br-lang - value: Acesso a diretórios com escopo - - name: ru-lang - value: Доступ к выделенным каталогам - - name: vi-lang - value: Truy cập Thư mục theo Phạm vi - - name: zh-cn-lang - value: 作用域目录访问 - - name: zh-tw-lang - value: 限定範圍目錄存取 - -- title: Contoh - path: /preview/samples.html - path_attributes: - - name: es-lang - value: Ejemplos - - name: in-lang - value: Contoh - - name: ja-lang - value: サンプル - - name: ko-lang - value: 샘플 - - name: pt-br-lang - value: Exemplos - - name: ru-lang - value: Примеры - - name: zh-cn-lang - value: 示例 - - name: zh-tw-lang - value: 範例 - -- title: Perjanjian Lisensi - path: /preview/license.html - path_attributes: - - name: es-lang - value: Contrato de licencia - - name: ja-lang - value: 使用許諾契約 - - name: ko-lang - value: 라이선스 계약 - - name: pt-br-lang - value: Contrato de licença - - name: ru-lang - value: Лицензионное соглашение - - name: zh-cn-lang - value: 许可协议 - - name: zh-tw-lang - value: 授權協議 diff --git a/docs/html-intl/intl/in/preview/download-ota.jd b/docs/html-intl/intl/in/preview/download-ota.jd deleted file mode 100644 index 1efe9b72815c3bfb54593bd72fc16699bf0a76a0..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/download-ota.jd +++ /dev/null @@ -1,324 +0,0 @@ -page.title=Menerapkan Citra OTA Perangkat - -@jd:body - -

    - - - - -
    - -

    - Halaman ini menyediakan tautan ke citra perangkat lewat jaringan seluler (OTA) dan menjelaskan - cara menerapkan pembaruan OTA secara manual ke suatu perangkat. Prosedur ini berguna - untuk memulihkan perangkat yang menerima pembaruan OTA melalui Android Beta - Program dan tidak jalan setelah pembaruan dipasang. -

    - -

    Memasang Citra OTA

    - -

    - -

    Untuk pasang OTA pada perangkat:

    - -
      -
    1. Unduh citra perangkat OTA dari tabel di bawah.
    2. -
    3. Boot ulang perangkat ke dalam mode Recovery. Untuk informasi selengkapnya mengenai cara masuk ke mode ini - di perangkat Nexus, lihat - Setel ulang perangkat Nexus - Anda ke setelan pabrik. -
    4. -
    5. Pada perangkat, pilih ADB sideload.
    6. -
    7. Hubungkan perangkat ke komputer dengan lingkungan pengembangan Android - yang telah dimuat dan alat Android Debug Bridge (adb) yang telah dipasang.
    8. -
    9. Jalankan perintah berikut: -
      adb sideload <ota-package>
      -
    10. -
    - - - -

    Citra OTA Perangkat

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PerangkatUnduhan / Checksum
    Nexus 5X
    "bullhead"
    bullhead-ota-npd35k-b8cfbd80.zip
    - MD5: 15fe2eba9b01737374196bdf0a792fe9
    - SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283 -
    Nexus 6
    "shamu"
    shamu-ota-npd35k-078e6fa5.zip
    - MD5: e8b12f7721c53af9a450f7058928a5fc
    - SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a -
    Nexus 6P
    "angler"
    angler-ota-npd35k-88457699.zip
    - MD5: 3fac09fef759dde26e57cb80b20b6477
    - SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c -
    Nexus 9
    "volantis"
    volantis-ota-npd35k-51dbae76.zip
    - MD5: 58312c4a5971818ef5c77a3f446003da
    - SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921 -
    Nexus 9G
    "volantisg"
    volantisg-ota-npd35k-834f047f.zip
    - MD5: 92b7d1fa252f7394e70f957c72d4aac8
    - SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361 -
    Nexus Player
    "fugu"
    fugu-ota-npd35k-6ac91298.zip
    - MD5: 1461622ad53ea842b2722fa7b49b8172
    - SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931 -
    Pixel C
    "ryu"
    ryu-ota-npd35k-a0b2347f.zip
    - MD5: c60117f3640cc6db12386fd632289c7d
    - SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3 -
    General Mobile 4G (Android One)
    "seed"
    seed_l8150-ota-npd35k-09897a1d.zip
    - MD5: a55cf94f7cce0393ec6c0b35041766b7
    - SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a -
    - - -
    - -
    - - - - diff --git a/docs/html-intl/intl/in/preview/download.jd b/docs/html-intl/intl/in/preview/download.jd deleted file mode 100644 index a759a11c007ff5e9f9f5e41173a37bdbc6712b69..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/download.jd +++ /dev/null @@ -1,543 +0,0 @@ -page.title=Menguji pada Perangkat -meta.tags="preview", "nexus","system image" -page.tags="preview", "androidn" -page.image=images/cards/card-n-downloads_2x.png - -@jd:body - -
    - - - - -
    - - - -

    - Untuk menjalankan dan menguji aplikasi Anda pada platform baru, Anda perlu menyiapkan lingkungan waktu proses - Android N. Anda bisa melakukannya dengan salah satu cara ini: -

    - -
      -
    • Pasang Android N pada perangkat keras yang didukung, atau
    • -
    • Siapkan emulator Android yang menjalankan Android N
    • -
    - -

    - Jika Anda ingin lingkungan untuk pengujian kompatibilitas dasar aplikasi Anda pada - platform baru, maka Anda hanya perlu APK saat ini dan perangkat keras atau - emulator. Anda tidak perlu memperbarui lingkungan - pengembangan penuh untuk melakukan pengujian dasar. -

    - -

    - Jika Anda ingin memodifikasi aplikasi untuk menargetkan Android N atau menggunakan Android N API baru, - Anda perlu menyiapkan lingkungan pengembangan yang telah diperbarui untuk mendukung - Android N. Menyiapkan Pengembangan - Android N berisi detail mengenai hal ini. -

    - - -

    Menyiapkan perangkat keras

    - -

    - N Developer Preview menawarkan pembaruan sistem untuk berbagai jenis perangkat keras - yang bisa Anda gunakan untuk menguji aplikasi Anda, dari ponsel hingga tablet dan TV. -

    - -

    - Jika Anda memiliki akses ke perangkat yang didukung, Anda bisa memperbaruinya ke build tahapan pencapaian Developer - Preview dengan salah satu cara berikut: -

    - -
      -
    • Daftarkan perangkat dalam pembaruan sistem OTA otomatis melalui - Android Beta Program. Setelah didaftarkan, perangkat Anda akan secara teratur menerima - pembaruan lewat jaringan seluler (OTA) untuk semua build tahapan pencapaian dalam N Developer Preview. Pendekatan - ini disarankan karena akan membantu Anda melakukan transisi secara mulus dari lingkungan saat ini - ke berbagai rilis N Developer Preview.
    • -
    • Unduh citra sistem Developer Preview dan flash perangkat. - Pembaruan OTA tidak disediakan secara otomatis untuk perangkat yang Anda flash secara manual, namun - Anda bisa mendaftarkan perangkat tersebut dalam Android Beta Program untuk memperoleh pembaruan OTA.
    • -
    - -

    Daftarkan perangkat dalam pembaruan OTA otomatis

    - -

    - Jika Anda memiliki akses ke perangkat yang didukung (lihat daftar dalam tabel - Unduhan), Anda bisa menerima pembaruan lewat jaringan seluler ke versi pratinjau Android - dengan mendaftarkan perangkat itu ke Android Beta Program. Pembaruan ini - secara otomatis akan diunduh dan memperbarui perangkat Anda seperti - pembaruan sistem resmi. -

    - -

    - Anda bisa membatalkan pendaftaran perangkat kapan saja. Perangkat akan menerima pembaruan OTA - ke versi produksi terbaru Android yang tersedia untuk perangkat itu - (misalnya, Android 6.0 Marshmallow). Pembaruan mengharuskan penyetelan ulang - perangkat secara penuh, jadi data pengguna pada perangkat itu akan dibuang. Pastikan mencadangkan - data penting sebelum membatalkan pendaftaran perangkat. -

    - -

    - Untuk informasi selengkapnya dan untuk mendaftarkan perangkat Anda, lihat - situs web Android Beta Program. -

    - -

    Catatan: - Membatalkan pendaftaran mengharuskan penyetelan ulang perangkat secara penuh. Cadangkan - data penting terlebih dahulu. -

    - -

    Mem-flash perangkat secara manual

    - -

    - Anda bisa mengunduh citra sistem Developer Preview terbaru dan - mem-flash-nya secara manual ke perangkat Anda kapan saja. Lihat tabel di bawah untuk mengunduh citra - sistem perangkat pengujian Anda. Mem-flash perangkat secara manual berguna jika Anda harus - mengontrol secara persis lingkungan pengujian tersebut atau harus memasang ulang secara rutin, - misalnya untuk pengujian otomatis. -

    - -

    - Memasang citra sistem pada perangkat akan membuang semua data dari - perangkat, karena itu Anda harus mencadangkan data terlebih dahulu. -

    - -

    - Setelah Anda mencadangkan data perangkat dan mengunduh citra sistem di bawah ini yang - sesuai dengan perangkat Anda, ikuti petunjuk di developers.google.com/android - untuk mem-flash citra ini ke perangkat Anda. -

    - -

    - Citra sistem yang di-flash secara manual tidak secara otomatis akan - menerima pembaruan OTA ke build tahapan pencapaian Developer Preview - terbaru. Pastikan lingkungan Anda selalu diperbarui dan lakukan flash - citra sistem yang baru di setiap tahapan pencapaian Developer Preview. -

    - -

    - Jika Anda memutuskan ingin mendapatkan pembaruan OTA setelah mem-flash perangkat secara manual, - Anda tinggal mendaftarkan perangkat dalam - Android Beta Program. Anda bisa mendaftarkan perangkat kapan saja untuk menerima pembaruan Pratinjau - berikutnya lewat jaringan seluler. -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PerangkatUnduhan / Checksum
    Nexus 5X
    "bullhead"
    bullhead-npd35k-factory-5ba40535.tgz
    - MD5: b6c5d79a21815ee21db41822dcf61e9f
    - SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c -
    Nexus 6
    "shamu"
    shamu-npd35k-factory-a33bf20c.tgz
    - MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab
    - SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c -
    Nexus 6P
    "angler"
    angler-npd35k-factory-81c341d5.tgz
    - MD5: e93de7949433339856124c3729c15ebb
    - SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd -
    Nexus 9
    "volantis"
    volantis-npd35k-factory-2b50e19d.tgz
    - MD5: 565be87ebb2d5937e2abe1a42645864b
    - SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1 -
    Nexus 9G
    "volantisg"
    volantisg-npd35k-factory-2e89ebe6.tgz
    - MD5: a8464e15c6683fe2afa378a63e205fda
    - SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678 -
    Nexus Player
    "fugu"
    fugu-npd35k-factory-1de74874.tgz
    - MD5: c0dbb7db671f61b2785da5001cedefcb
    - SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873 -
    Pixel C
    "ryu"
    ryu-npd35k-factory-b4eed85d.tgz
    - MD5: bdcb6f770e753668b5fadff2a6678e0d
    - SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2 -
    General Mobile 4G (Android One)
    "seed"
    seed_l8150-npd35k-factory-5ab1212b.tgz
    - MD5: 7d34a9774fdd6e025d485ce6cfc23c4c
    - SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5 -
    Sony Xperia Z3
    (D6603 dan D6653)
    Unduh: Xperia Companion
    - Untuk informasi selengkapnya, lihatCoba Android N Developer Preview untuk Xperia Z3. -
    - -

    Mencopot pemasangan Pratinjau dari perangkat

    - -

    - Jika Anda ingin mencopot pemasangan Pratinjau dari perangkat, Anda bisa melakukannya dengan salah satu cara - ini:

    -
      -
    • Dapatkan citra sistem sesuai spesifikasi pabrik kemudian flash - secara manual ke perangkat. -
        -
      • Untuk perangkat Nexus dan Pixel C, lihat halaman - Citra Pabrik - untuk Perangkat Nexus untuk mengunduhnya.
      • -
      • Untuk perangkat lainnya, hubungi produsen perangkat - secara langsung. Atau, jika perangkat didukung - dalam Android Beta Program, Anda bisa mendaftarkan perangkat dalam - program kemudian membatalkan pendaftarannya (lihat di bawah).
      • -
      -
    • -
    • Batalkan pendaftaran perangkat dari Android Beta Program. Jika - perangkat telah terdaftar dalam Android Beta - Program, apa pun perangkatnya, Anda cukup membatalkan pendaftarannya dari program tersebut. -

      - Perangkat akan menerima pembaruan OTA ke versi produksi terbaru - Android yang tersedia untuk perangkat itu (misalnya, Android 6.0 Marshmallow). - Pembaruan mengharuskan penyetelan ulang perangkat secara penuh, jadi data pengguna pada perangkat itu akan - dibuang. Pastikan Anda mencadangkan data penting sebelum - membatalkan pendaftaran perangkat. -

      -
    • -
    - -

    Catatan: - Mencopot pemasangan citra sistem Developer Preview sebelum - program berakhir mengharuskan penyetelan ulang perangkat secara penuh dan membuang semua data pengguna - pada perangkat. -

    - - -

    Menyiapkan emulator

    - -

    Untuk menggunakan Android Emulator guna menjalankan Android N Preview, Anda perlu -mengunduh Android N Preview SDK dan membuat perangkat maya untuk -emulator.

    - -

    Pertama, unduh Android N Preview SDK sebagai berikut (jika Anda -sudah memperolehnya saat menyiapkan -pengembangan Android N, Anda bisa lewati bagian ini): - -

      -
    1. Di Android Studio, buka dialog Settings - (File > Settings pada Windows/Linux, atau - Android Studio > Preferences pada Mac). Di panel - kiri, pilih Appearance & Behavior > - System Settings > Android SDK. - -
    2. Klik tab SDK Platforms, kemudian pilih kotak centang - Android N Preview.
    3. - -
    4. Klik tab SDK Tools, kemudian pilih - kotak centang Android SDK Build Tools, Android SDK - Platform-Tools, dan Android SDK Tools. - -
    5. - -
    6. Klik OK, dan terima - perjanjian lisensi untuk setiap paket yang akan dipasang. -
    7. -
    - -

    Sekarang Anda seharusnya telah memiliki Android SDK Built-Tools 24.0 0 rc1, -Platform-Tools 24.0.0 rc1, dan SDK Tools -25.0.9. Jika Anda tidak memperbarui SDK Tools ke 25.0.9, maka Anda tidak akan -dapat menjalankan citra sistem x86_64 untuk Android N.

    - - -

    Sekarang buatlah perangkat maya dengan citra sistem Android N:

    - -
      -
    1. Buka AVD Manager dengan memilih Tools > Android > - AVD Manager.
    2. -
    3. Klik Create Virtual Device.
    4. -
    5. Pilih perangkat misalnya Nexus 5X, Nexus 6P, Nexus 9, atau Android TV, - kemudian klik Next.
    6. -
    7. Pilih citra sistem N (dengan - x86 ABI), kemudian klik Next. - (Hanya citra sistem x86 yang saat ini didukung dengan Android Emulator -untuk Android N Preview.) -
    8. Selesaikan konfigurasi AVD selanjutnya dan klik - Finish.
    9. -
    - -

    Anda sekarang bisa meluncurkan Android Emulator dengan Android N Preview AVD.

    - -

    -Untuk mendapatkan pengalaman terbaik di Android Emulator, pastikan Anda menggunakan -Android Studio 2.1 atau yang lebih tinggi, yang mendukung Android Emulator 2.0 -dengan kinerja jauh lebih cepat dibandingkan Emulator di -Android Studio 1.5.

    - -

    Untuk informasi selengkapnya tentang membuat perangkat maya, lihat Mengelola Perangkat Maya. -

    - - - - - - - - - - - - - - -
    - -
    - - - - diff --git a/docs/html-intl/intl/in/preview/features/afw.jd b/docs/html-intl/intl/in/preview/features/afw.jd deleted file mode 100644 index 643fab2a8b38e46f70bc4e6a858487de917ccd6a..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/features/afw.jd +++ /dev/null @@ -1,552 +0,0 @@ -page.title=Pembaruan Android for Work -page.metaDescription=API dan fitur baru Android for Work di Android N. -page.keywords="android for work", "android N", "enterprise", "QR code" - -@jd:body - - - -

    Dokumen ini menjelaskan fitur baru Android for Work yang disediakan di -Android N.

    - -

    Penyediaan Kode QR

    - -

    - Android for Work kini mendukung penggunaan kode QR untuk penyediaan perangkat - milik perusahaan. Wizard persiapan kini memungkinkan Anda memindai kode QR untuk penyediaan - perangkat. -

    - -

    Pertanyaan Keamanan Profil Kerja

    - -

    - Pemilik profil bisa mengharuskan pengguna menetapkan pertanyaan keamanan untuk aplikasi - yang berjalan dalam profil kerja. Sistem akan menampilkan pertanyaan keamanan bila - pengguna mencoba membuka aplikasi kerja apa pun. Jika pengguna berhasil menyelesaikan - pertanyaan keamanan, sistem akan membuat profil kerja dan mendekripsinya - jika diperlukan. -

    - -

    - Jika pemilik profil mengirim intent {@link - android.app.admin.DevicePolicyManager#ACTION_SET_NEW_PASSWORD} , sistem - akan menampilkan pertanyaan keamanan kepada pengguna. Pemilik profil juga dapat - mengirim intent ACTION_SET_NEW_PARENT_PROFILE_PASSWORD untuk - meminta pengguna menyetel kunci perangkat. -

    - -

    - Pemilik profil dapat memilih untuk menyetel kebijakan sandi untuk pertanyaan pekerjaan - yang berbeda dari kebijakan sandi perangkat lainnya. Misalnya, panjang minimum - jawaban pertanyaan perangkat bisa berbeda dari panjang - yang diperlukan untuk sandi lainnya. Pemilik profil menyetel kebijakan pertanyaan - menggunakan metode{@link android.app.admin.DevicePolicyManager} - biasa, seperti {@link - android.app.admin.DevicePolicyManager#setPasswordQuality - setPasswordQuality()} dan {@link - android.app.admin.DevicePolicyManager#setPasswordMinimumLength - setPasswordMinimumLength()}. Pemilik profil juga bisa menyetel penguncian perangkat, - dengan menggunakan instance {@link android.app.admin.DevicePolicyManager} yang dikembalikan secara langsung - oleh metode DevicePolicyManager.getParentProfileInstance() - baru. Selain itu, pemilik profil dapat menyesuaikan layar kredensial untuk - pertanyaan kerja menggunakan kelas {@link android.app.admin.DevicePolicyManager} - dengan metode setOrganizationColor() dan - setOrganizationName() baru. -

    - -

    - Untuk mengetahui detail tentang kelas dan metode berikut, lihat halaman referensi - DevicePolicyManager di Referensi N Preview SDK. -

    - -

    Menonaktifkan Akses ke Aplikasi

    - -

    - Pemilik perangkat dan pemilik profil bisa menangguhkan akses untuk sementara ke paket - dengan memanggil metode DevicePolicyManager.setPackagesSuspended() - baru. Pemilik bisa menggunakan metode yang sama untuk mengaktifkan kembali paket tersebut. -

    - -

    - Selagi paket ditangguhkan, maka tidak bisa memulai aktivitas, pemberitahuan ke - paket akan disembunyikan, dan entri aplikasi dalam layar ringkasan akan disembunyikan. - Paket yang ditangguhkan tidak muncul di layar ringkasan, dan - tidak bisa menampilkan dialog (termasuk toast dan snackbar). Juga tidak bisa memutar - audio atau menggetarkan perangkat. -

    - -

    - Launcher harus menerapkan UI berbeda pada aplikasi yang ditangguhkan untuk menunjukkan - aplikasi saat ini tidak tersedia; misalnya, bisa merender ikon aplikasi - dalam warna abu-abu. Launcher bisa mengetahui apakah aplikasi ditangguhkan dengan memanggil metode - DevicePolicyManager.getPackageSuspended() baru. -

    - -

    Beralih Mode Kerja

    - -

    - Pada perangkat dua-profil, pengguna bisa mengaktifkan dan menonaktifkan mode kerja. Selagi mode - kerja dinonaktifkan, profil yang dikelola akan dinonaktifkan untuk sementara. Aplikasi Profil Kerja, - sinkronisasi latar belakang, dan pemberitahuan semuanya dinonaktifkan, termasuk - aplikasi pemilik profil. Selagi profil kerja dinonaktifkan, sistem - akan menampilkan ikon status tetap untuk mengingatkan pengguna bahwa mereka tidak bisa meluncurkan aplikasi - kerja. Peluncur sistem menunjukkan bahwa aplikasi kerja dan widget tidak bisa - diakses. -

    - -

    Always-On VPN

    - -

    - Pemilik perangkat dan pemilik profil bisa mengharuskan aplikasi kerja selalu terhubung - ke jaringan melalui VPN yang ditetapkan. Jika pemilik menyetel persyaratan ini, - perangkat secara otomatis akan memulai VPN itu saat booting. -

    - -

    - Pemilik bisa menggunakan VPN dengan memanggil metode - DevicePolicyManager.setAlwaysOnVpnPackage() baru. Untuk mengetahui - apakah pemilik telah menyetel persyaratan VPN, panggil metode - DevicePolicyManager.GetAlwaysOnVpnPackage() baru. -

    - -

    - Karena sistem bisa secara langsung mengikat layanan VPN tanpa interaksi aplikasi, - klien VPN perlu menangani titik masuk baru untuk Always-On VPN. Seperti sebelumnya, - Anda bisa menemukan layanan aktif dengan menggunakan filter intent yang cocok dengan tindakan - {@link android.net.VpnService android.net.VpnService}. -

    - -

    - Pengguna bisa secara manual menyetel klien Always-On VPN yang mengimplementasikan {@link - android.net.VpnService} dengan menggunakan layar Settings > More > - VPN. -

    - -

    Integrasi Kontak dengan Profil Kerja

    - -

    - Pemilik profil bisa mengizinkan penelusuran lokal dan pencarian direktori kontak kerja - dari pengguna utama. Misalnya, seorang pengguna bisa mengakses kontak direktori pribadi dan pekerjaan - dari telepon pribadi atau aplikasi kontak mereka (jika - diizinkan oleh administrator profil mereka). -

    - -

    - Pengembang yang memanfaatkan Contact Provider bisa menggunakan Enterprise Contacts - API untuk mengakses entri direktori profil kerja dari pengguna utama jika diizinkan - oleh kebijakan: -

    - -
      -
    • ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Phone.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Email.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Callable.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Directory.ENTERPRISE_CONTENT_URI -
    • - -
    • ContactsContract.Directory.isEntepriseDirectoryId() -
    • -
    - -

    - Pemilik profil bisa mengendalikan visibilitas kontak kerja di - pengguna utama menggunakan metode baru berikut: -

    - -
      -
    • - DevicePolicyManager.setCrossProfileContactsSearchDisabled() -
    • - -
    • - DevicePolicyManager.getCrossProfileContactsSearchDisabled() -
    • -
    - -

    Boot Ulang Jarak Jauh

    - -

    - Pemilik perangkat bisa mem-boot ulang perangkat dari jarak jauh. Di beberapa kasus, perangkat yang diluncurkan di - tempat umum dalam pembatas bisa mencegah akses ke tombol daya. Jika - perangkat perlu di-boot ulang, administrator bisa melakukannya dengan metode - DevicePolicyManager.reboot() baru. -

    - -

    Menonaktifkan Roaming Data

    - -

    - Pemilik perangkat bisa menonaktifkan roaming data menggunakan pembatasan pengguna {@link - android.os.UserManager} DISALLOW_DATA_ROAMING baru. -

    - -

    Pencatatan Proses Enterprise

    - -

    - Pemilik perangkat bisa mengenali aktivitas mencurigakan dengan melacak perangkat dari jarak jauh, - termasuk peluncuran aplikasi, aktivitas adb, dan pembukaan kunci layar. Log proses - tidak memerlukan persetujuan pengguna. Untuk mengambil log, pemilik perangkat mengaktifkan - pencatatan perangkat menggunakan DevicePolicyManager.setSecurityLoggingEnabled(). -

    - -

    - Perubahan API meliputi: -

    - -
      - -
    • - Kelas android.app.admin.SecurityLog baru dan - metodenya -
    • - -
    • - void DevicePolicyManager.setSecurityLoggingEnabled() -
    • - -
    • - boolean DevicePolicyManager.isSecurityLoggingEnabled() -
    • - -
    • - List<SecurityEvent> - DevicePolicyManager.retrieveSecurityLogs() -
    • - -
    • - List<SecurityEvent> - DevicePolicyManager.retrievePreRebootSecurityLogs() -
    • - -
    • - void DeviceAdminReceiver.onSecurityLogsAvailable() -
    • -
    - -

    Laporan Bug Jarak Jauh

    - -

    - Pemilik perangkat bisa memicu dari jarak jauh dan mengambil laporan bug yang berisi - file dump status perangkat, yang memungkinkan penyelidikan forensik atas - kesalahan yang diketahui atau perangkat yang telah diutak-atik. Dikarenakan sifat detail laporan bug, - maka diperlukan persetujuan pengguna. -

    - -

    - Android N menyertakan tambahan API berikut untuk mendukung fitur ini. Untuk detailnya, lihat - Referensi - N Preview SDK. -

    - -
      -
    • - DevicePolicyManager.requestBugreport() -
    • - -
    • - DeviceAdminReceiver.onBugreportFailed() -
    • - -
    • - DeviceAdminReceiver.onBugreportShared() -
    • - -
    • - DeviceAdminReceiver.onBugreportSharingDeclined() -
    • - -
    • - DeviceAdminReceiver.BUGREPORT_FAILURE_FAILED_COMPLETING -
    • - -
    • - DeviceAdminReceiver.BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE -
    • -
    - -

    Membuang Sertifikat Klien

    - -

    - Pemilik profil dan pemilik perangkat kini bisa membuang sertifikat klien yang telah dipasang melalui - {@link android.app.admin.DevicePolicyManager#installKeyPair - installKeyPair()} dengan memanggil metode baru - DevicePolicyManager.removeKeyPair(). -

    - -

    Memberi Akses ke Sertifikat Klien - saat Pemasangan

    - -

    - Jika pemilik profil dan pemilik perangkat memberikan kemampuan kepada aplikasi pihak ketiga untuk - mengelola sertifikat, aplikasi bisa memberikan akses pada dirinya sendiri ke sertifikat - yang dipasangnya tanpa intervensi dari pemilik. -

    - -

    - API yang sudah ada untuk mengelola sertifikat diperluas untuk mencakup: -

    - -
      -
    • DevicePolicyManager.installKeyPair() -
    • -
    - -

    Transparansi Kebijakan UI Sistem

    - -

    - Kebijakan yang memengaruhi pengalaman pengguna atau membatasi Settings pengguna sepenuhnya - diungkapkan kepada pengguna, serta pemilik profil dan pemilik perangkat bisa memberlakukan - kebijakannya kepada departemen TI perusahaan mereka. Selain pesan “Action - not allowed” yang konsisten di Settings, administrator TI bisa menyetel - pesan dukungan khusus-organisasi di setelan perangkat dengan metode - {@link android.app.admin.DevicePolicyManager} baru berikut: -

    - -
      -
    • - DevicePolicyManager.setShortSupportMessage() -
    • - -
    • - DevicePolicyManager.setLongSupportMessage() -
    • -
    - -

    Penyempurnaan Manajemen Pembatasan Aplikasi

    - -

    - Pemilik perangkat atau profil bisa mengaktifkan aplikasi lain untuk mengelola - pembatasan aplikasi melalui metode - DevicePolicyManager.setApplicationRestrictionsManagingPackage() - baru. Aplikasi yang dipilih bisa memeriksa apakah izin ini telah - diberikan dengan memanggil - DevicePolicyManager.isCallerApplicationRestrictionsManagingPackage(). -

    - -

    - Aplikasi yang dipilih untuk mengelola pembatasan aplikasi bisa memanggil {@link - android.app.admin.DevicePolicyManager#setApplicationRestrictions - setApplicationRestrictions()} dan {@link - android.app.admin.DevicePolicyManager#getApplicationRestrictions - getApplicationRestrictions()} untuk paket apa pun di pengguna atau profil itu. -

    - -

    Tombol Lokasi Nonaktif

    - -

    - Pengguna bisa menonaktifkan izin lokasi untuk aplikasi kerja sambil melanjutkan - akses informasi lokasi di aplikasi pribadi mereka. Tombol akses - lokasi yang terpisah di Location Settings memungkinkan pengguna untuk menolak pembaruan lokasi atau - kueri lokasi terakhir untuk aplikasi yang berjalan di profil kerja. -

    - -

    - Tombol lokasi nonaktif level teratas menonaktifkan akses lokasi untuk - profil utama dan profil yang dikelola. -

    - -

    Penyediaan yang Disesuaikan

    - -

    - Aplikasi bisa menyesuaikan alur penyediaan pemilik profil dan pemilik perangkat - dengan warna dan logo perusahaan. -

    - -
    -
    - DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR -
    - -
    - Menyesuaikan warna alur. -
    - -
    - DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI -
    - -
    - Menyesuaikan alur dengan logo perusahaan. -
    -
    - -

    Multi-Sertifikat CA Wi-Fi

    - -

    - Pemilik profil dan pemilik perangkat bisa menyetel beberapa sertifikat CA sekaligus untuk - konfigurasi Wi-Fi yang diberikan. Bila jaringan Wi-Fi perusahaan memiliki CA terpisah untuk - titik akses yang terpisah dengan SSID yang sama, administrator TI bisa menyertakan semua - CA yang relevan dalam konfigurasi Wi-Fi menggunakan metode - setCaCertificates() baru. -

    - -

    - API yang ditambah adalah: -

    - -
      -
    • - WifiEnterpriseConfig.setCaCertificates() -
    • - -
    • - WifiEnterpriseConfig.getCaCertificates() -
    • -
    - -

    Pesan Layar Terkunci yang Disesuaikan

    - -

    - Pemilik perangkat bisa menyediakan informasi pemilik agar ditampilkan di layar kunci. - Informasi ini lebih diprioritaskan dari pesan layar kunci pengguna (jika sudah ada - yang disetel). Metode {@link android.app.admin.DevicePolicyManager} baru adalah: -

    - -
      -
    • - setDeviceOwnerLockScreenInfo() -
    • - -
    • - getDeviceOwnerLockScreenInfo() -
    • -
    - -

    ConnectionService Profil Kerja

    - -

    - Pemilik profil bisa menetapkan aplikasi telepon kerja yang menggunakan - {@link android.telecom.ConnectionService} khusus-kerja untuk - backend panggilan (akun panggilan). Telepon kerja hanya menyimpan log panggilan kerja - dan hanya mengandalkan kontak kerja. Pengguna memiliki pengalaman UI - saat-panggilan yang konsisten, apa pun aplikasi panggilannya. Panggilan telepon kerja yang masuk ke akun panggilan kerja - dibedakan dari telepon pribadi yang masuk - ke akun panggilan pribadi. -

    - -

    - Penelepon harus memeriksa tanda baru - android.telecom.Call.PROPERTY_WORK_CALL untuk menentukan apakah telepon tersebut merupakan - telepon kerja. Jika merupakan telepon kerja, penelepon harus menunjukkannya, - misalnya dengan menambahkan lencana kerja. -

    - -

    Mengunci Wallpaper

    - -

    - Pembatasan pengguna baru (DISALLOW_SET_WALLPAPER) mencegah - pengguna mengubah wallpaper mereka. Pemilik perangkat atau pemilik profil tetap bisa - mengubah wallpaper, namun mereka hanya bisa mengubah wallpaper - untuk pengguna atau profil yang mereka kontrol. Misalnya, pemilik profil tidak bisa mengubah - wallpaper pengguna induk, namun pemilik profil utama di profil utama atau - pemilik perangkat bisa melakukannya. Pemilik profil atau pemilik perangkat yang ingin mengubah - wallpapernya harus memeriksa apakah pengguna atau profil - yang mereka kelola memiliki wallpaper ({@link android.app.WallpaperManager#isWallpaperSupported - isWallpaperSupported()}) dan apakah mereka diperbolehkan untuk mengubahnya (dengan metode - baruWallpaperManager.isWallpaperSettingAllowed()) -

    - -

    Mengunci Ikon Pengguna

    - -

    - Pembatasan pengguna baru (DISALLOW_SET_USER_ICON) mencegah - pengguna mengubah ikon pengguna mereka. Pemilik perangkat atau pemilik profil pengguna - tetap bisa mengubah ikon. Akan tetapi, pemilik profil hanya bisa mengubah ikon - pengguna untuk profil yang dikontrolnya. -

    - -

    Pemantauan Kesehatan Perangkat

    - -

    - Pemilik perangkat atau pemilik profil bisa menggunakan antarmuka - HardwarePropertiesManager baru untuk mengambil informasi - tentang kesehatan perangkat, seperti suhu CPU atau GPU dan penggunaan CPU. Antarmuka pemantauan - baru ini khususnya berguna untuk memantau berjalannya perangkat yang tidak diawasi - di lokasi yang jauh. -

    diff --git a/docs/html-intl/intl/in/preview/features/background-optimization.jd b/docs/html-intl/intl/in/preview/features/background-optimization.jd deleted file mode 100644 index 5712ab671059d50a7b9bb244c84b08e99c5368e0..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/features/background-optimization.jd +++ /dev/null @@ -1,391 +0,0 @@ -page.title=Optimalisasi Latar Belakang -page.metaDescription=Pembatasan baru pada siaran implisit. -page.keywords="android N", "implicit broadcasts", "job scheduler" -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

    - Proses latar belakang bisa menguras memori dan baterai. Misalnya, sebuah - siaran implisit dapat memulai banyak proses latar belakang yang telah didaftarkan - untuk mendengarkannya, sekalipun proses-proses itu mungkin tidak melakukan banyak pekerjaan. Hal ini bisa - berdampak besar pada kinerja perangkat dan pengalaman pengguna. -

    - -

    - Untuk meringankan masalah ini, Android N menerapkan pembatasan - berikut: -

    - -
      -
    • Aplikasi yang menargetkan Pratinjau tidak menerima siaran {@link - android.net.ConnectivityManager#CONNECTIVITY_ACTION} jika mereka - mendaftar untuk menerimanya dalam manifes mereka. Aplikasi yang berjalan tetap - bisa mendengarkan {@code CONNECTIVITY_CHANGE} pada thread utama mereka dengan mendaftarkan - {@link android.content.BroadcastReceiver} pada {@link - android.content.Context#registerReceiver Context.registerReceiver()}. -
    • - -
    • Aplikasi tidak bisa mengirim atau menerima siaran {@link - android.hardware.Camera#ACTION_NEW_PICTURE} atau {@link - android.hardware.Camera#ACTION_NEW_VIDEO}. Optimalisasi ini - memengaruhi semua aplikasi, tidak hanya aplikasi yang menargetkan Pratinjau. -
    • -
    - -

    - Jika aplikasi Anda menggunakan intent ini, Anda harus membuang dependensi padanya - secepat mungkin agar Anda bisa menargetkan perangkat Android N dengan benar. - Kerangka kerja Android menyediakan beberapa solusi untuk mengurangi kebutuhan akan - siaran implisit ini. Misalnya, {@link android.app.job.JobScheduler} - dan - {@code GcmNetworkManager} menyediakan mekanisme yang tangguh untuk menjadwalkan operasi - jaringan bila kondisi yang ditetapkan, seperti koneksi ke jaringan - berbiaya tetap, terpenuhi. Anda sekarang juga bisa menggunakan {@link android.app.job.JobScheduler} - untuk bereaksi terhadap perubahan penyedia materi. Objek {@link android.app.job.JobInfo} - membungkus parameter yang digunakan {@link android.app.job.JobScheduler} - untuk menjadwalkan pekerjaan Anda. Bila syarat-syarat pekerjaan sudah terpenuhi, sistem - akan mengeksekusi pekerjaan ini pada {@link android.app.job.JobService} aplikasi Anda. -

    - -

    - Dalam dokumen ini, kita akan mempelajari cara menggunakan metode alternatif, seperti - {@link android.app.job.JobScheduler}, untuk menyesuaikan aplikasi Anda dengan pembatasan - yang baru. -

    - -

    - Pembatasan pada CONNECTIVITY_ACTION -

    - -

    - Aplikasi yang menargetkan Android N tidak menerima siaran {@link - android.net.ConnectivityManager#CONNECTIVITY_ACTION} jika mereka - mendaftar untuk menerimanya dalam manifes mereka, dan proses yang bergantung pada siaran - ini tidak akan dimulai. Hal ini bisa menimbulkan masalah bagi aplikasi yang ingin - memantau perubahan jaringan atau melakukan aktivitas jaringan dalam jumlah besar bila perangkat - menghubungkan ke jaringan berbiaya tetap. Beberapa solusi untuk menyiasati pembatasan - ini sudah ada dalam kerangka kerja Android, namun pemilihan solusi - yang tepat bergantung pada apa yang ingin dicapai oleh aplikasi Anda. -

    - -

    - Catatan: Sebuah {@link android.content.BroadcastReceiver} yang mendaftar pada - {@link android.content.Context#registerReceiver Context.registerReceiver()} - akan terus menerima siaran ini saat aplikasi berjalan. -

    - -

    - Menjadwalkan Pekerjaan Jaringan pada Koneksi Berbiaya Tetap -

    - -

    - Saat menggunakan kelas {@link android.app.job.JobInfo.Builder JobInfo.Builder} - untuk membangun objek {@link android.app.job.JobInfo} Anda, terapkan metode {@link - android.app.job.JobInfo.Builder#setRequiredNetworkType - setRequiredNetworkType()} dan teruskan {@link android.app.job.JobInfo - JobInfo.NETWORK_TYPE_UNMETERED} sebagai parameter pekerjaan. Contoh kode berikut - menjadwalkan layanan yang akan dijalankan ketika perangkat terhubung ke jaringan - berbiaya tetap dan dikenai biaya: -

    - -
    -public static final int MY_BACKGROUND_JOB = 0;
    -...
    -public static void scheduleJob(Context context) {
    -  JobScheduler js =
    -      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    -  JobInfo job = new JobInfo.Builder(
    -    MY_BACKGROUND_JOB,
    -    new ComponentName(context, MyJobService.class))
    -      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
    -      .setRequiresCharging(true)
    -      .build();
    -  js.schedule(job);
    -}
    -
    - -

    - Bila syarat untuk pekerjaan Anda terpenuhi, aplikasi Anda akan menerima callback untuk menjalankan - metode {@link android.app.job.JobService#onStartJob onStartJob()} dalam - {@code JobService.class} yang ditetapkan. Untuk melihat contoh selengkapnya mengenai implementasi {@link - android.app.job.JobScheduler}, lihat aplikasi contoh JobScheduler. -

    - -

    - Aplikasi yang menggunakan layanan GMSCore, dan menargetkan Android 5.0 (API level 21) - atau yang lebih rendah, bisa menggunakan - {@code GcmNetworkManager} dan menetapkan {@code Task.NETWORK_STATE_UNMETERED}. -

    - -

    - Memantau Konektivitas Jaringan Saat Aplikasi Dijalankan -

    - -

    - Aplikasi yang berjalan tetap bisa memantau {@code CONNECTIVITY_CHANGE} dengan - {@link android.content.BroadcastReceiver} yang telah didaftarkan. Akan tetapi, {@link - android.net.ConnectivityManager} API menyediakan metode yang lebih tangguh untuk meminta - callback hanya bila persyaratan jaringan yang ditetapkan terpenuhi. -

    - -

    - Objek {@link android.net.NetworkRequest} mendefinisikan parameter - callback jaringan dari segi {@link android.net.NetworkCapabilities}. Anda - membuat objek {@link android.net.NetworkRequest} dengan kelas {@link - android.net.NetworkRequest.Builder NetworkRequest.Builder}. {@link - android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, - android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()} - kemudian meneruskan objek {@link android.net.NetworkRequest} ke sistem. Bila - syarat jaringan terpenuhi, aplikasi akan menerima callback untuk mengeksekusi - metode {@link android.net.ConnectivityManager.NetworkCallback#onAvailable - onAvailable()} yang didefinisikan dalam kelas {@link - android.net.ConnectivityManager.NetworkCallback}. -

    - -

    - Aplikasi akan terus menerima callback hingga aplikasi keluar atau memanggil - {@link android.net.ConnectivityManager#unregisterNetworkCallback - unregisterNetworkCallback()}. -

    - -

    - Pembatasan pada NEW_PICTURE dan NEW_VIDEO -

    - -

    - Di Android N, aplikasi tidak bisa mengirim atau menerima siaran {@link - android.hardware.Camera#ACTION_NEW_PICTURE} atau {@link - android.hardware.Camera#ACTION_NEW_VIDEO}. Pembatasan ini membantu - meringankan dampak terhadap kinerja dan pengalaman pengguna bila beberapa aplikasi harus - aktif untuk memproses gambar atau video baru. Android N - memperluas {@link android.app.job.JobInfo} dan {@link - android.app.job.JobParameters} untuk menyediakan solusi alternatif. -

    - -

    - Metode JobInfo baru -

    - -

    - Untuk memicu pekerjaan saat perubahan URI materi, Android N memperluas - {@link android.app.job.JobInfo} API dengan metode berikut: -

    - -
    -
    - {@code JobInfo.TriggerContentUri()} -
    - -
    - Membungkus parameter yang diperlukan untuk memicu pekerjaan saat perubahan URI materi. -
    - -
    - {@code JobInfo.Builder.addTriggerContentUri()} -
    - -
    - Meneruskan objek {@code TriggerContentUri} ke {@link - android.app.job.JobInfo}. Sebuah {@link android.database.ContentObserver} - akan memantau URI materi yang dibungkus. Jika terdapat beberapa objek {@code - TriggerContentUri} yang berhubungan dengan pekerjaan, sistem memberikan sebuah - callback bahkan jika itu hanya melaporkan perubahan pada salah satu URI materi. -
    - -
    - Tambahkan flag {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} untuk - memicu pekerjaan jika ada turunan dari perubahan URI yang diberikan. Flag ini - berkaitan dengan parameter {@code notifyForDescendants} yang diteruskan ke {@link - android.content.ContentResolver#registerContentObserver - registerContentObserver()}. -
    -
    - -

    - Catatan: {@code TriggerContentUri()} tidak bisa digunakan - bersama-sama dengan {@link android.app.job.JobInfo.Builder#setPeriodic - setPeriodic()} atau {@link android.app.job.JobInfo.Builder#setPersisted - setPersisted()}. Untuk terus memantau perubahan materi, jadwalkan - {@link android.app.job.JobInfo} baru sebelum {@link - android.app.job.JobService} aplikasi selesai menangani callback terbaru. -

    - -

    - Kode contoh berikut menjadwalkan pekerjaan yang akan dipicu bila sistem melaporkan - perubahan ke URI materi, {@code MEDIA_URI}: -

    - -
    -public static final int MY_BACKGROUND_JOB = 0;
    -...
    -public static void scheduleJob(Context context) {
    -  JobScheduler js =
    -          (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    -  JobInfo.Builder builder = new JobInfo.Builder(
    -          MY_BACKGROUND_JOB,
    -          new ComponentName(context, MediaContentJob.class));
    -  builder.addTriggerContentUri(
    -          new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    -          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
    -  js.schedule(builder.build());
    -}
    -
    -

    - Bila sistem melaporkan perubahan dalam URI materi yang ditetapkan, aplikasi Anda - akan menerima callback dan objek {@link android.app.job.JobParameters} - akan diteruskan ke metode {@link android.app.job.JobService#onStartJob onStartJob()} - dalam {@code MediaContentJob.class}. -

    - -

    - Metode JobParameter Baru -

    - -

    - Android N juga memperluas {@link android.app.job.JobParameters} untuk - memungkinkan aplikasi Anda menerima informasi yang berguna tentang otoritas materi - dan URI yang memicu pekerjaan: -

    - -
    -
    - {@code Uri[] getTriggeredContentUris()} -
    - -
    - Mengembalikan larik URL yang telah memicu pekerjaan. Ini akan berupa {@code - null} jika tidak ada URI yang memicu pekerjaan (misalnya, pekerjaan - dipicu karena batas waktu atau alasan lainnya), atau jumlah - URI yang berubah lebih dari 50. -
    - -
    - {@code String[] getTriggeredContentAuthorities()} -
    - -
    - Mengembalikan larik string otoritas materi yang telah memicu pekerjaan. - Jika larik yang dikembalikan bukan {@code null}, gunakan {@code getTriggeredContentUris()} - untuk mengambil detail URI yang telah berubah. -
    -
    - -

    - Kode contoh berikut mengganti metode {@link - android.app.job.JobService#onStartJob JobService.onStartJob()} dan - mencatat otoritas materi serta URI yang telah memicu pekerjaan: -

    - -
    -@Override
    -public boolean onStartJob(JobParameters params) {
    -  StringBuilder sb = new StringBuilder();
    -  sb.append("Media content has changed:\n");
    -  if (params.getTriggeredContentAuthorities() != null) {
    -      sb.append("Authorities: ");
    -      boolean first = true;
    -      for (String auth :
    -          params.getTriggeredContentAuthorities()) {
    -          if (first) {
    -              first = false;
    -          } else {
    -             sb.append(", ");
    -          }
    -           sb.append(auth);
    -      }
    -      if (params.getTriggeredContentUris() != null) {
    -          for (Uri uri : params.getTriggeredContentUris()) {
    -              sb.append("\n");
    -              sb.append(uri);
    -          }
    -      }
    -  } else {
    -      sb.append("(No content)");
    -  }
    -  Log.i(TAG, sb.toString());
    -  return true;
    -}
    -
    - -

    - Mengoptimalkan Aplikasi Anda Lebih Jauh -

    - -

    - Mengoptimalkan aplikasi Anda untuk berjalan pada perangkat yang mempunyai memori rendah, atau dalam kondisi - memori rendah, dapat meningkatkan kinerja dan pengalaman pengguna. Membuang - dependensi pada layanan latar belakang dan penerima siaran - implisit yang terdaftar secara statis bisa membantu aplikasi Anda berjalan lebih baik pada perangkat demikian. Meskipun - Android N telah mengambil langkah-langkah untuk mengurangi sebagian masalah ini, Anda disarankan - agar mengoptimalkan aplikasi untuk berjalan tanpa menggunakan - proses latar belakang ini sama sekali. -

    - -

    - Android N memperkenalkan beberapa tambahan perintah Android Debug Bridge (ADB) yang - bisa Anda gunakan untuk menguji perilaku aplikasi dengan proses latar belakang dinonaktifkan: -

    - -
      -
    • Untuk mensimulasikan kondisi saat siaran implisit dan layanan latar belakang - tidak tersedia, masukkan perintah berikut: -
    • - -
    • -
      -{@code $ adb shell cmd appops set <package> RUN_IN_BACKGROUND ignore}
      -
      -
    • - -
    • Untuk mengaktifkan kembali siaran implisit dan layanan latar belakang, masukkan - perintah berikut: -
    • - -
    • -
      -{@code $ adb shell cmd appops set <package> RUN_IN_BACKGROUND allow}
      -
      -
    • -
    diff --git a/docs/html-intl/intl/in/preview/features/icu4j-framework.jd b/docs/html-intl/intl/in/preview/features/icu4j-framework.jd deleted file mode 100644 index 1d97623146fc6bdd4827ceebb68df8932bd6b67e..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/features/icu4j-framework.jd +++ /dev/null @@ -1,159 +0,0 @@ -page.title=ICU4J Android Framework API -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

    - ICU4J merupakan serangkaian pustaka Java sumber terbuka yang banyak digunakan dan menyediakan Unicode - serta dukungan globalisasi untuk aplikasi perangkat lunak. Android N - mengekspos subset ICU4J API dalam kerangka kerja Android bagi pengembang aplikasi - untuk digunakan pada paket {@code android.icu}. API ini menggunakan - data pelokalan yang ada pada perangkat. Hasilnya, Anda bisa mengurangi footprint - APK dengan tidak mengompilasi pustaka ICU4J ke APK Anda; sebagai gantinya, - cukup memanggilnya dalam kerangka kerja. (Dalam hal ini, Anda mungkin perlu menyediakan - beberapa versi - APK Anda, sehingga pengguna yang menjalankan versi Android lebih rendah dari Android N - bisa mengunduh versi aplikasi yang berisi pustaka ICU4J.) -

    - -

    - Dokumen ini diawali dengan menyediakan beberapa informasi dasar tentang level Android API - minimum yang diperlukan untuk mendukung pustaka-pustaka ini. Kemudian dijelaskan tentang apa - yang perlu Anda ketahui tentang implementasi ICU4J spesifik Android. Terakhir, - Anda akan diberi tahu cara menggunakan ICU4J API dalam kerangka kerja Android. -

    - -

    Hubungan dengan ICU4J

    - -

    - Android N mengekspos subset ICU4J API lewat - paket android.icu, bukannya com.ibm.icu. Kerangka kerja - Android dapat memilih untuk tidak - mengekspos ICU4J API karena berbagai alasan; misalnya, Android N tidak mengekspos - beberapa API yang tidak digunakan lagi atau yang dinyatakan belum - stabil oleh tim ICU. Karena tim ICU tidak lagi menggunakan API di masa mendatang, Android juga akan menandainya - sebagai tidak digunakan lagi namun akan terus menyertakannya. -

    - -

    Tabel 1. Versi ICU dan CLDR yang digunakan - di Android N.

    - - - - - - - - - - - -
    Level Android APIVersi ICUVersi CLDR
    Android N5628
    - -

    Inilah beberapa hal penting yang harus diperhatikan:

    - -
      -
    • ICU4J Android Framework API tidak menyertakan semua ICU4J API.
    • -
    • Pengembang NDK harus mengetahui bahwa Android ICU4C tidak didukung.
    • -
    • API dalam kerangka kerja Android tidak menggantikan dukungan Android untuk -melokalkan dengan -sumber daya.
    • -
    - -

    Migrasi ke paket android.icu dari com.ibm.icu

    - -

    - Jika Anda sudah menggunakan ICU4J API dalam aplikasi, dan - android.icu API memenuhi persyaratan Anda, maka migrasi ke - API kerangka kerja mengharuskan Anda untuk mengubah impor Java - dari com.ibm.icu ke android.icu. Kemudian Anda bisa - membuang salinan file ICU4J dari APK. -

    - -

    - Catatan: API kerangka kerja ICU4J menggunakan ruang nama {@code android.icu} - sebagai ganti {@code com.ibm.icu}. Hal ini untuk menghindari konflik - ruang nama di APK yang berisi pustaka {@code com.ibm.icu} sendiri. -

    - -

    - Migrasi ke API android.icu dari Android SDK API lainnya -

    - -

    - Beberapa kelas dalam paket java dan android memiliki - padanannya dengan yang ditemukan di ICU4J. Akan tetapi, ICU4J seringkali menyediakan dukungan - yang lebih luas untuk standar dan bahasa. -

    -

    Inilah beberapa contoh untuk membantu Anda memulai:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    KelasAlternatif
    java.lang.Character android.icu.lang.UCharacter
    java.text.BreakIterator android.icu.text.BreakIterator
    java.text.DecimalFormat android.icu.text.DecimalFormat
    java.util.Calendar -android.icu.util.Calendar
    android.text.BidiFormatter - android.icu.text.Bidi -
    android.text.format.DateFormat - android.icu.text.DateFormat -
    android.text.format.DateUtils android.icu.text.DateFormat -android.icu.text.RelativeDateTimeFormatter -
    - -

    Lisensi

    - -

    - ICU4J dirilis dengan lisensi ICU. Untuk detailnya, lihat Panduan Pengguna - ICU. -

    diff --git a/docs/html-intl/intl/in/preview/features/multilingual-support.jd b/docs/html-intl/intl/in/preview/features/multilingual-support.jd deleted file mode 100644 index 29104cb4da7c5e2cc5e44c2428a421964b17d294..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/features/multilingual-support.jd +++ /dev/null @@ -1,221 +0,0 @@ -page.title=Bahasa dan Lokal -page.tags=androidn -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

    Android N memberikan dukungan yang disempurnakan untuk pengguna multibahasa, -yang memungkinkan mereka memilih beberapa lokal dalam setelan. Android N -menyediakan kemampuan ini dengan memperbanyak jumlah lokal yang didukung -dan mengubah cara sistem mengatasi masalah sumber daya. Metode baru mengatasi -masalah sumber daya ini lebih tangguh dan didesain agar kompatibel dengan APK yang ada, namun -Anda harus ekstra hati-hati terhadap perilaku tak terduga. Misalnya, Anda -harus menguji untuk memastikan aplikasi Anda secara default diatur ke bahasa yang diinginkan. Juga, -jika aplikasi Anda mendukung beberapa bahasa, Anda harus memastikan dukungan ini berfungsi -sebagaimana diinginkan. Terakhir, Anda harus mencoba memastikan aplikasi Anda dengan lancar menangani -bahasa yang tidak secara eksplisit Anda dukung dalam desain.

    - -

    Dokumen ini diawali dengan menjelaskan strategi resolusi sumber daya sebelum -Android N. Berikutnya, akan dijelaskan strategi -resolusi sumber daya Android N yang telah ditingkatkan. Terakhir, akan djelaskan cara memanfaatkan -jumlah lokal yang telah diperbanyak untuk mendukung lebih banyak pengguna multibahasa.

    - -

    Tantangan dalam Mengatasi Masalah Sumber Daya Bahasa

    - -

    Sebelum Android N, Android tidak selalu - berhasil mencocokkan lokal aplikasi dan lokal sistem.

    - -

    Misalnya, anggaplah Anda menghadapi situasi berikut:

    -
      -
    • Bahasa default aplikasi Anda adalah {@code en_US} (US English), dan aplikasi juga - berisi string bahasa Spanyol yang telah dilokalkan di file sumber daya {@code es_ES}. -
    • -
    • Perangkat telah disetel ke {@code es_MX}
    • - -

      Bila kode Java Anda merujuk ke string, sistem akan memuat -string dari file sumber daya default ({@code en_US}), sekalipun aplikasi memiliki -sumber daya bahasa Spanyol yang dilokalkan pada {@code es_ES}. Hal ini karena bila sistem - tidak bisa menemukan hasil yang persis, sistem akan terus mencari sumber daya dengan menghilangkan - kode negara dari lokal tersebut. Akhirnya, jika tidak ada hasil yang ditemukan, sistem akan mengembalikan - ke default, yakni {@code en_US}.

      - - -

      Sistem juga akan default ke {@code en_US} jika pengguna memilih -bahasa yang sama sekali tidak didukung oleh aplikasi, seperti bahasa Prancis. Misalnya:

      - -

      -Tabel 1. Resolusi sumber daya tanpa lokal yang persis sama. -

      - - - - - - - - - - - - - -
      Setelan PenggunaSumber Daya AplikasiResolusi Sumber Daya
      fr_CH -default (en)
      -de_DE
      -es_ES
      -fr_FR
      -it_IT
      -
      -Coba fr_CH => Gagal
      -Coba fr => Gagal
      -Gunakan default (en) -
      - - -

      Dalam contoh ini, sistem menampilkan string bahasa Inggris -tanpa mengetahui apakah pengguna memahami bahasa Inggris. Perilaku ini sudah sangat umum -sekarang. Android N harus mengurangi frekuensi -hasil seperti ini secara substansial.

      - -

      Peningkatan pada Strategi Resolusi Sumber Daya

      -

      Android N menghadirkan resolusi sumber daya yang lebih handal, dan -secara otomatis menemukan solusi yang lebih baik. Akan tetapi, untuk mempercepat resolusi dan meningkatkan -kemudahan pemeliharaan, Anda harus menyimpan sumber daya dalam dialek induk yang paling umum. - Misalnya, jika sebelumnya Anda telah menyimpan sumber daya bahasa Spanyol di direktori {@code es-US} -, pindahkan ke direktori {@code es-419}, yang berisi bahasa Spanyol Amerika Latin. - Demikian pula, jika Anda memiliki string sumber daya dalam folder bernama {@code en-GB}, ganti nama - folder itu menjadi {@code en-001} (bahasa Inggris internasional), karena induk yang paling umum - untuk string en-GB adalah {@code en-001}. - Contoh berikut menjelaskan mengapa praktik-praktik ini meningkatkan kinerja dan -reliabilitas resolusi sumber daya.

      - -

      Contoh resolusi sumber daya

      - -

      Dengan Android N, kasus yang dijelaskan dalam Tabel 1 diatasi -secara berbeda:

      - -

      -Tabel 2. Strategi resolusi yang ditingkatkan bila tidak ada -lokal yang sama persis.

      - - - - - - - - - - - - -
      Setelan PenggunaSumber Daya AplikasiResolusi Sumber Daya
        -
      1. fr_CH
      2. -
      -
      -default (en)
      -de_DE
      -es_ES
      -fr_FR
      -it_IT
      -
      -Coba fr_CH => Gagal
      -Coba fr => Gagal
      -Coba anak dari fr => fr_FR
      -Gunakan fr_FR -
      - - -

      Sekarang pengguna mendapatkan sumber daya bahasa Prancis sebagai ganti bahasa Inggris. Contoh ini juga menunjukkan - mengapa Anda harus menyimpan string bahasa Prancis di {@code fr} bukan pada {@code fr_FR} - untuk Android N. Arah aksi di sini adalah untuk mencocokkan dengan induk dialek terdekat, - membuat resolusi lebih cepat dan lebih dapat diprediksi.

      - -

      Selain logika resolusi yang diperbaiki ini, Android sekarang menawarkan lebih banyak -pilihan bahasa untuk pengguna. Mari kita coba lagi contoh di atas dengan menetapkan bahasa Italia - sebagai bahasa pengguna tambahan, tetapi tanpa dukungan aplikasi untuk bahasa Prancis.

      - -

      -Tabel 3. Resolusi sumber daya bila aplikasi hanya mencocokkan -setelan lokal yang disukai kedua oleh pengguna.

      - - - - - - - - - - - - - - -
      Setelan PenggunaSumber Daya AplikasiResolusi Sumber Daya
        -
      1. fr_CH
      2. -
      3. it_CH
      4. -
      -
      -default (en)
      -de_DE
      -es_ES
      -it_IT
      -
      -Coba fr_CH => Gagal
      -Coba fr => Gagal
      -Coba anak dari fr => Gagal
      -Coba it_CH => Gagal
      -Coba it => Gagal
      -Coba anak dari it => it_IT
      -Gunakan it_IT -
      -

      Pengguna tetap mendapatkan bahasa yang mereka pahami, meskipun aplikasi tidak -mendukung bahasa Prancis.

      - - -

      Mendesain Aplikasi Anda untuk Mendukung Lokal Tambahan

      -

      LocaleList API

      - -

      Android N menambahkan API baru {@code LocaleList.getDefault()} -yang memungkinkan aplikasi langsung kueri daftar bahasa yang telah ditetapkan pengguna. API ini -memungkinkan Anda membuat - perilaku aplikasi yang lebih canggih dan tampilan materi yang lebih optimal. Misalnya, Telusur - bisa menampilkan hasil dalam beberapa bahasa berdasarkan setelan pengguna. Aplikasi browser - bisa menghindari penawaran menerjemahkan halaman dalam bahasa yang sudah diketahui pengguna, - dan aplikasi keyboard bisa mengaktifkan otomatis semua layout yang sesuai.

      - -

      Formatter

      - -

      Hingga Android 6.0 (API level 23), Android hanya mendukung satu atau dua lokal - untuk banyak bahasa umum -(en, es, ar, fr, ru). Karena hanya ada beberapa varian dari setiap bahasa, -aplikasi bisa menghindar dengan menyimpan beberapa nomor dan tanggal sebagai string hard-code -dalam file sumber daya. Akan tetapi, dengan perluasan set lokal yang didukung Android, -maka akan ada -perbedaan format yang signifikan untuk tanggal, waktu, mata uang, dan informasi -serupa bahkan dalam lokal tunggal. Menjadikan format Anda sebagai hard-code bisa menghasilkan -pengalaman yang membingungkan bagi pengguna akhir. Karena itu, saat mengembangkan untuk Android N -pastikan menggunakan formatter sebagai ganti menjadikan string angka dan tanggal sebagai hard-code.

      - -

      Contoh terbaik adalah bahasa Arab, yang mendukung Android N berkembang dari -satu {@code ar_EG} menjadi 27 lokal bahasa Arab. Bahasa lokal ini bisa berbagi hampir semua sumber daya, -namun sebagian lebih memilih digit ASCII, sementara yang lain memilih digit asli. Misalnya, -bila Anda ingin membuat kalimat dengan variabel digit, seperti -"Pilih PIN 4 digit", gunakan formatter seperti yang ditampilkan di bawah ini:

      - -
       format(locale, "Choose a %d-digit PIN", 4)
      diff --git a/docs/html-intl/intl/in/preview/features/notification-updates.jd b/docs/html-intl/intl/in/preview/features/notification-updates.jd deleted file mode 100644 index 0ad2770a4c4875f1f7db7dae47358c5ba1ff6cd6..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/features/notification-updates.jd +++ /dev/null @@ -1,393 +0,0 @@ -page.title=Pemberitahuan -page.tags=pemberitahuan -helpoutsWidget=true -page.image=/preview/images/notifications-card.png - -trainingnavtop=true - -@jd:body - -
      -
      - - -

      Dokumen ini berisi

      -
        -
      1. Balasan Langsung
      2. -
      3. Bundel Pemberitahuan
      4. -
      5. Tampilan Khusus
      6. -
      7. Gaya Pesan
      8. -
      - -
      -
      - -

      Android N memperkenalkan beberapa API baru yang memungkinkan aplikasi untuk mengeposkan -pemberitahuan yang sangat mudah terlihat dan interaktif.

      - -

      Android N menambahkan API pemberitahuan{@link android.support.v4.app.RemoteInput} -yang ada untuk mendukung balasan inline pada handset. Fitur ini memungkinkan pengguna - merespons dengan cepat dari bayangan pemberitahuan tanpa mengunjungi aplikasi Anda.

      - -

      - Android N juga memungkinkan Anda menggabungkan pemberitahuan yang serupa agar - muncul sebagai satu pemberitahuan. Untuk memungkinkan hal ini, Android N menggunakan metode {@link - android.support.v4.app.NotificationCompat.Builder#setGroup - NotificationCompat.Builder.setGroup()} yang sudah ada. Pengguna bisa memperluas setiap - pemberitahuan, dan melakukan tindakan seperti membalas dan menutup setiap - pemberitahuan, satu per satu dari bayangan pemberitahuan. -

      - -

      Terakhir, Android N juga menambahkan API baru yang memungkinkan Anda untuk memanfaatkan dekorasi -sistem dalam tampilan pemberitahuan yang disesuaikan untuk aplikasi Anda. API ini membantu -memastikan semua tampilan pemberitahuan sama-sama menggunakan penyajian yang konsisten dengan -template standar.

      - -

      Dokumen ini menyoroti beberapa perubahan penting yang harus Anda - perhitungkan saat menggunakan fitur pemberitahuan baru dalam aplikasi Anda.

      - -

      Balasan Langsung

      - -

      Dengan fitur Balasan Langsung di Android N, pengguna bisa dengan cepat -merespons pesan teks atau memperbarui daftar tugas secara langsung dalam antarmuka -pemberitahuan. Pada perangkat genggam, tindakan balasan inline muncul sebagai tombol tambahan - yang dilampirkan pada pemberitahuan. Bila pengguna membalas lewat keyboard, sistem akan melampirkan - respons teks ke intent - yang telah Anda tetapkan untuk tindakan pemberitahuan dan mengirimkan intent ke - aplikasi perangkat genggam Anda. - - - -

      - Gambar 1. Android N menambahkan tombol tindakan Reply. - -

      - -

      Menambahkan tindakan balasan inline

      - -

      Untuk membuat tindakan pemberitahuan yang mendukung balasan langsung: -

      - -
        -
      1. Buat instance {@link android.support.v4.app.RemoteInput.Builder} - yang bisa Anda tambahkan ke tindakan -pemberitahuan. Konstruktor kelas ini akan menerima string bahwa sistem menggunakannya sebagai kunci - untuk masukan teks. Kemudian, aplikasi perangkat genggam Anda akan menggunakan kunci itu untuk mengambil teks - masukan tersebut. - -
        -// Key for the string that's delivered in the action's intent.
        -private static final String KEY_TEXT_REPLY = "key_text_reply";
        -String replyLabel = getResources().getString(R.string.reply_label);
        -RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
        -        .setLabel(replyLabel)
        -        .build();
        -
        -
      2. -
      3. Lampirkan objek {@link android.support.v4.app.RemoteInput} - pada tindakan dengan menggunakan addRemoteInput(). - -
        -// Create the reply action and add the remote input.
        -Notification.Action action =
        -        new Notification.Action.Builder(R.drawable.ic_reply_icon,
        -                getString(R.string.label), replyPendingIntent)
        -                .addRemoteInput(remoteInput)
        -                .build();
        -
        -
      4. - -
      5. Terapkan tindakan pada pemberitahuan dan keluarkan pemberitahuan. - -
        -// Build the notification and add the action.
        -Notification newMessageNotification =
        -        new Notification.Builder(mContext)
        -                .setSmallIcon(R.drawable.ic_message)
        -                .setContentTitle(getString(R.string.title))
        -                .setContentText(getString(R.string.content))
        -                .addAction(action))
        -                .build();
        -
        -// Issue the notification.
        -NotificationManager notificationManager =
        -        NotificationManager.from(mContext);
        -notificationManager.notify(notificationId, newMessageNotification);
        -
        -
        -
      6. - -
      - - -

      Sistem akan meminta pengguna memasukkan respons bila mereka memicu -tindakan pemberitahuan.

      - - -

      - Gambar 2. Pengguna memasukkan teks dari bayangan pemberitahuan. -

      - -

      - Mengambil masukan pengguna dari balasan inline -

      - -

      - Untuk menerima masukan pengguna dari antarmuka pemberitahuan ke aktivitas yang Anda -deklarasikan dalam intent tindakan balasan: -

      - -
        -
      1. Panggil {@link android.support.v4.app.RemoteInput#getResultsFromIntent - getResultsFromIntent()} dengan meneruskan intent tindakan pemberitahuan sebagai - parameter masukan. Metode ini mengembalikan {@link android.os.Bundle} yang - berisi respons teks. - -
        -Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        -
        -
      2. - -
      3. Lakukan kueri pada bundel menggunakan kunci hasil (diberikan ke konstruktor {@link - android.support.v4.app.RemoteInput.Builder}). Anda bisa menyelesaikan - proses ini dan mengambil teks masukan dengan membuat sebuah metode, seperti dalam - cuplikan kode berikut: - -
        -// Obtain the intent that started this activity by calling
        -// Activity.getIntent() and pass it into this method to
        -// get the associated string.
        -
        -private CharSequence getMessageText(Intent intent) {
        -    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        -    if (remoteInput != null) {
        -        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
        -    }
        -    return null;
        - }
        -
        -
      4. - -
      5. Kompilasilah dan keluarkan pemberitahuan lain, menggunakan ID pemberitahuan yang sama dengan - yang Anda berikan untuk pemberitahuan sebelumnya. Indikator kemajuan - menghilang dari antarmuka pemberitahuan untuk memberi tahu pengguna mengenai balasan - yang berhasil. Saat menangani pemberitahuan baru ini, gunakan konteks yang - diteruskan ke metode {@code onReceive()} penerima. - -
        -// Build a new notification, which informs the user that the system
        -// handled their interaction with the previous notification.
        -Notification repliedNotification =
        -        new Notification.Builder(context)
        -                .setSmallIcon(R.drawable.ic_message)
        -                .setContentText(getString(R.string.replied))
        -                .build();
        -
        -// Issue the new notification.
        -NotificationManager notificationManager =
        -        NotificationManager.from(context);
        -notificationManager.notify(notificationId, repliedNotification);
        -
        -
      6. -
      - -

      - Untuk aplikasi interaktif, seperti chat, akan berguna bila menyertakan - konteks tambahan saat menangani teks yang diambil. Misalnya, aplikasi ini bisa menampilkan - beberapa baris riwayat chat sekaligus. Bila pengguna merespons melalui {@link - android.support.v4.app.RemoteInput}, Anda bisa memperbarui riwayat balasan - menggunakan metode {@code setRemoteInputHistory()}. -

      - -

      - Pemberitahuan harus diperbarui atau dibatalkan setelah aplikasi - menerima masukan jarak jauh. Bila pengguna membalas ke pembaruan jarak jauh - menggunakan Balasan Langsung, - jangan batalkan pemberitahuan. Melainkan, perbarui pemberitahuan untuk menampilkan balasan pengguna. -Untuk pemberitahuan yang menggunakan {@code MessagingStyle}, Anda harus menambahkan -balasannya sebagai pesan terbaru. Saat menggunakan template lain, Anda bisa -menambahkan balasan pengguna ke riwayat masukan jarak jauh. -

      - -

      Bundel Pemberitahuan

      - -

      Android N membekali pengembang dengan sebuah cara baru untuk menyatakan - antrean pemberitahuan: bundel pemberitahuan. Ini mirip dengan fitur - Tumpukan - Pemberitahuan dalam Android Wear. Misalnya, jika aplikasi Anda membuat pemberitahuan - untuk pesan yang diterima, bila lebih dari satu pesan diterima, pemberitahuan tersebut akan - dibundel sebagai satu grup. Anda bisa - menggunakan metode {@link android.support.v4.app.NotificationCompat.Builder#setGroup -Builder.setGroup()} yang ada untuk membundel pemberitahuan yang sama.

      - -

      - Grup pemberitahuan menerapkan hierarki pada pemberitahuan yang ada di dalamnya. - Di bagian teratas hierarki adalah pemberitahuan induk yang menampilkan informasi - rangkuman untuk grup tersebut. Pengguna secara bertahap bisa - memperbesar grup pemberitahuan, dan sistem akan menampilkan informasi lebih banyak saat - pengguna menggali lebih dalam. Bila pengguna memperbesar bundel, sistem akan memperlihatkan informasi lebih - banyak untuk semua pemberitahuan anak; bila pengguna - memperbesar salah satu pemberitahuan tersebut, sistem akan memperlihatkan seluruh isinya. -

      - - -

      - Gambar 3. Pengguna secara bertahap bisa memperluas grup - pemberitahuan. -

      - -

      - Catatan: Jika aplikasi yang sama mengirim empat atau beberapa pemberitahuan - dan tidak menetapkan pengelompokan, - sistem secara otomatis akan mengelompokannya. -

      - -

      Untuk mengetahui cara menambahkan pemberitahuan ke grup, lihat -Menambahkan -Setiap Pemberitahuan ke Grup.

      - - -

      Praktik terbaik untuk bundel pemberitahuan

      -

      Bagian ini memberikan panduan tentang kapan menggunakan grup pemberitahuan sebagai ganti -pemberitahuan {@link android.app.Notification.InboxStyle InboxStyle} -yang telah tersedia di -platform Android versi sebelumnya.

      - -

      Kapan menggunakan bundel pemberitahuan

      - -

      Anda harus menggunakan grup pemberitahuan hanya jika semua kondisi berikut ini -bernilai benar untuk kasus penggunaan Anda:

      - -
        -
      • Pemberitahuan anak adalah pemberitahuan lengkap dan bisa ditampilkan - masing-masing tanpa perlu rangkuman grup.
      • -
      • Ada untungnya memunculkan pemberitahuan anak satu per satu. Misalnya: - -
      • -
          -
        • Mereka dapat diaplikasikan, dengan tindakan khusus untuk masing-masing anak.
        • -
        • Ada lebih banyak informasi pada anak yang ingin dibaca oleh pengguna.
        • -
        -
      - -

      Contoh kasus penggunaan yang baik untuk grup pemberitahuan antara lain: aplikasi perpesanan -yang menampilkan daftar pesan yang masuk, atau aplikasi email yang menampilkan daftar email -yang diterima.

      - -

      -Contoh kasus penggunaan saat pemberitahuan tunggal lebih disukai - meliputi pesan pribadi dari satu orang, atau representasi daftar dari - item teks baris tunggal. Anda bisa menggunakan -({@link android.app.Notification.InboxStyle InboxStyle} atau -{@link android.app.Notification.BigTextStyle BigTextStyle}) untuk mencapai -hal ini. -

      - -

      Menampilkan bundel pemberitahuan

      - -

      - Aplikasi ini harus selalu mengeposkan rangkuman grup, sekalipun grup hanya berisi - satu anak. Sistem akan menyembunyikan rangkuman dan langsung menampilkan - pemberitahuan anak jika hanya berisi pemberitahuan tunggal. Hal ini akan memastikan - sistem bisa memberikan pengalaman yang konsisten saat pengguna menggeser - anak grup. -

      - -

      - Catatan: Versi Android N ini tidak menyembunyikan - rangkuman untuk grup pemberitahuan yang berisi satu anak. Fungsionalitas - ini akan ditambahkan dalam Android N versi berikutnya. -

      - -

      Mengintip pemberitahuan

      - -

      Walaupun sistem biasanya menampilkan pemberitahuan anak sebagai sebuah grup, Anda bisa menyetelnya - agar muncul untuk sementara muncul sebagai - - pemberitahuan pendahuluan. Fitur ini khususnya berguna karena memungkinkan - akses langsung ke pemberitahuan anak terbaru dan tindakan yang dikaitkan dengannya. -

      - - -

      Kompatibilitas mundur

      - -

      - Baik grup pemberitahuan maupun masukan jauh telah menjadi bagian dari {@link - android.app.Notification} API sejak Android 5.0 (API level 21) untuk mendukung - perangkat Android Wear. Jika Anda sudah membuat pemberitahuan dengan API ini, - satu-satunya tindakan yang harus Anda ambil adalah memverifikasi apakah perilaku aplikasi sesuai dengan panduan yang - dijelaskan di atas, dan mempertimbangkan implementasi {@code - setRemoteInputHistory()}. -

      - -

      - Untuk mendukung kompatibilitas mundur, tersedia API yang sama bersama - kelas {@link android.support.v4.app.NotificationCompat} - pustaka dukungan, yang memungkinkan Anda untuk membuat pemberitahuan yang bekerja pada versi Android - sebelumnya. Pada perangkat genggam dan tablet, pengguna hanya melihat pemberitahuan rangkuman, - sehingga aplikasi masih memiliki model inbox atau pemberitahuan sama yang - mewakili seluruh materi informasi grup. Karena perangkat Android - Wear memungkinkan pengguna melihat semua pemberitahuan anak bahkan pada level platform - yang lebih lama, maka Anda harus membangun pemberitahuan anak dengan mengabaikan level - API. -

      - -

      Tampilan Khusus

      -

      Mulai dari Android N, Anda bisa menyesuaikan tampilan pemberitahuan dan -tetap mendapatkan dekorasi sistem seperti header pemberitahuan, tindakan, dan -layout yang bisa diperluas.

      - -

      Untuk mengaktifkan kemampuan ini, Android N menambahkan API berikut untuk menata gaya - tampilan khusus Anda:

      - -
      -
      -{@code DecoratedCustomViewStyle()}
      -
      Menata gaya pemberitahuan selain pemberitahuan -media.
      -
      -{@code DecoratedMediaCustomViewStyle()}
      -
      Menata gaya pemberitahuan media.
      -
      - -

      Untuk menggunakan API baru ini, panggil metode {@code setStyle()}, dengan meneruskan -gaya tampilan khusus yang diinginkan padanya.

      - -

      Cuplikan ini menampilkan cara membuat objek pemberitahuan khusus dengan metode -{@code DecoratedCustomViewStyle()}.

      - -
      -Notification notification = new Notification.Builder()
      -           .setSmallIcon(R.drawable.ic_stat_player)
      -           .setLargeIcon(albumArtBitmap))
      -           .setCustomContentView(contentView);
      -           .setStyle(new Notification.DecoratedCustomViewStyle())
      -           .build();
      -
      -
      - -

      Gaya Perpesanan

      -

      - Android N memperkenalkan API baru untuk menyesuaikan gaya pemberitahuan. - Dengan menggunakan kelas MessageStyle, Anda bisa mengubah beberapa - label yang ditampilkan pada pemberitahuan, termasuk judul percakapan, - pesan tambahan, dan tampilan materi untuk pemberitahuannya. -

      - -

      - Cuplikan kode berikut memperagakan cara menyesuaikan sebuah - gaya pemberitahuan menggunakan kelas MessageStyle. -

      - -
      -  Notification notification = new Notification.Builder()
      -             .setStyle(new Notification.MessagingStyle("Me")
      -                 .setConversationTitle("Team lunch")
      -                 .addMessage("Hi", timestamp1, null) // Pass in null for user.
      -                 .addMessage("What's up?", timestamp2, "Coworker")
      -                 .addMessage("Not much", timestamp3, null)
      -                 .addMessage("How about lunch?", timestamp4, "Coworker"));
      -
      diff --git a/docs/html-intl/intl/in/preview/index.jd b/docs/html-intl/intl/in/preview/index.jd deleted file mode 100644 index a8f61ebb547b03e798a05fafc0dcc4f0c81290e1..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/index.jd +++ /dev/null @@ -1,131 +0,0 @@ -page.title=Android N Developer Preview -page.tags="preview","developer" -meta.tags="preview", "android" -fullpage=true -forcelocalnav=true -header.hide=1 -footer.hide=1 -@jd:body - - - -
      -
      -
      - -
      -

      Android N Developer Preview

      -

      - Bersiaplah menyambut Android N! - Uji aplikasi Anda pada perangkat Nexus dan perangkat lainnya. Dukung perilaku sistem - baru untuk menghemat daya dan memori. - Tambah aplikasi Anda dengan UI multi-jendela, - pemberitahuan balasan langsung dan lainnya. -

      - - - - Mulai - -
      -
      - -
      -
      -
      -
      -
      -
      -
      - - - - - -
      -

      Terbaru

      -
      -
      - -
      -

      Sumber Daya

      -
      - Informasi penting guna membantu mempersiapkan aplikasi untuk Android N. -
      - -
      - -
      -
      - diff --git a/docs/html-intl/intl/in/preview/license.jd b/docs/html-intl/intl/in/preview/license.jd deleted file mode 100644 index 56ae58a05fe949ffcc9407c63365c29746f4939d..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/license.jd +++ /dev/null @@ -1,145 +0,0 @@ -page.title=Perjanjian Lisensi - -@jd:body - -

      -Untuk mulai Android SDK Preview, Anda harus menyetujui ketentuan dan persyaratan berikut. -Seperti dijelaskan di bawah ini, perhatikan bahwa ini adalah versi pratinjau Android SDK, bisa saja berubah, yang Anda gunakan dengan risiko sendiri. Android SDK Preview bukan rilis stabil, dan mungkin berisi kesalahan serta cacat yang bisa mengakibatkan kerusakan serius pada sistem komputer, perangkat dan data Anda. -

      - -

      -Ini adalah Perjanjian Lisensi Android SDK Preview ("Perjanjian Lisensi"). -

      -
      -1. Pengantar - -1.1 Android SDK Preview (dalam Perjanjian Lisensi ini disebut "Pratinjau" dan secara spesifik termasuk file sistem Android, paket API, dan file pustaka Pratinjau, jika disediakan) diberikan lisensinya kepada Anda sesuai dengan ketentuan Perjanjian Lisensi. Perjanjian Lisensi ini merupakan kontrak yang mengikat secara hukum antara Anda dan Google dalam kaitannya dengan penggunaan Pratinjau oleh Anda. - -1.2 "Android" berarti tumpukan perangkat lunak Android untuk perangkat, seperti yang tersedia di Android Open Source Project, yang ada di URL berikut: http://source.android.com/, yang selalu diperbarui. - -1.3 “Kompatibel dengan Android” berarti segala implementasi Android yang (i) sesuai dengan Android Compatibility Definition Document, yang bisa ditemukan di situs web kompatibilitas Android (http://source.android.com/compatibility) dan yang selalu diperbarui; serta (ii) berhasil lulus Android Compatibility Test Suite (CTS). - -1.4 "Google" berarti Google Inc., perusahaan asal Delaware dengan kantor bisnis utama di 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States. - -2. Menerima Perjanjian Lisensi - -2.1 Agar bisa menggunakan Pratinjau, Anda terlebih dahulu harus menyetujui Perjanjian Lisensi ini. Anda tidak boleh menggunakan Pratinjau jika tidak menerima Perjanjian Lisensi. - -2.2 Dengan mengklik untuk menerima dan/atau menggunakan Pratinjau, berarti Anda menyetujui ketentuan Perjanjian Lisensi. - -2.3 Anda tidak boleh menggunakan Pratinjau dan tidak boleh menerima Perjanjian Lisensi jika Anda adalah orang yang dilarang menerima Pratinjau berdasarkan hukum Amerika Serikat atau negara lainnya termasuk negara di mana Anda tinggal atau dari mana Anda menggunakan Pratinjau. - -2.4 Jika Anda akan menggunakan Pratinjau di lingkungan perusahaan atau organisasi Anda, berarti Anda setuju untuk terikat oleh Perjanjian Lisensi atas nama perusahaan Anda atau entitas lainnya, serta Anda mewakili dan menjamin bahwa Anda memiliki kewenangan hukum penuh untuk mengikat perusahaan Anda atau entitas tersebut pada Perjanjian Lisensi ini. Jika Anda tidak memiliki kewenangan yang disyaratkan, Anda tidak boleh menerima Perjanjian Lisensi atau menggunakan Pratinjau atas nama perusahaan Anda atau entitas lainnya. - -3. Lisensi Pratinjau dari Google - -3.1 Sesuai dengan ketentuan Perjanjian Lisensi ini, Google memberi Anda lisensi yang tidak bisa disublisensikan, non-eksklusif, tidak bisa dialihkan, bebas royalti, bersifat global dan terbatas dalam menggunakan Pratinjau hanya untuk keperluan pengembangan aplikasi yang kompatibel untuk diimplementasikan pada Android. - -3.2 Anda tidak boleh menggunakan Pratinjau ini untuk mengembangkan aplikasi platform lain (termasuk implementasi yang tidak kompatibel pada Android) atau untuk mengembangkan SDK lain. Anda tentu saja bebas mengembangkan aplikasi untuk platform lain, termasuk implementasi yang tidak kompatibel pada Android, karena Pratinjau ini tidak digunakan untuk tujuan tersebut. - -3.3 Anda setuju bahwa Google atau pihak ketiga memiliki semua hak, kuasa dan kepentingan hukum dalam dan pada Pratinjau, termasuk Hak Kekayaan Intelektual yang terdapat dalam Pratinjau. "Hak Kekayaan Intelektual" berarti setiap dan semua hak yang berdasarkan pada hukum paten, hukum hak cipta, hukum rahasia dagang, hukum merek dagang, dan setiap dan semua hak kepemilikan lainnya. Google memiliki semua hak yang tidak secara tersurat diberikan kepada Anda. - -3.4 Anda tidak boleh menggunakan Pratinjau untuk tujuan apa pun yang tidak secara tersurat diizinkan dalam Perjanjian Lisensi ini. Kecuali sejauh yang diperlukan oleh lisensi pihak ketiga yang berlaku, Anda tidak boleh: (a) menyalin (kecuali untuk keperluan pencadangan), memodifikasi, mengadaptasi, mendistribusikan kembali, mendekompilasi, merekayasa balik, membongkar atau membuat karya turunan dari Pratinjau atau bagian apa pun dari Pratinjau; atau (b) memuat bagian apa pun dari Pratinjau ke sebuah handset ponsel atau perangkat keras selain komputer pribadi, menggabungkan suatu bagian dari Pratinjau dengan perangkat lunak lain, atau mendistribusikan perangkat lunak atau perangkat yang menggabungkan suatu bagian dari Pratinjau. - -3.5 Penggunaan, reproduksi dan distribusi komponen Pratinjau yang berlisensi perangkat lunak sumber terbuka diatur semata-mata oleh ketentuan lisensi perangkat lunak sumber terbuka tersebut dan bukan oleh Perjanjian Lisensi ini. Anda menyetujui bagian selebihnya dari lisensi dengan maksud baik sehubungan dengan lisensi perangkat lunak sumber terbuka tersebut sesuai dengan semua hak yang diberikan dan untuk menahan diri dari segala tindakan yang mungkin akan mengakhiri, menangguhkan, atau melanggar hak tersebut. - -3.6 Anda setuju bahwa bentuk dan sifat Pratinjau yang disediakan oleh Google dapat berubah tanpa pemberitahuan sebelumnya kepada Anda dan bahwa versi Pratinjau mendatang mungkin tidak kompatibel dengan aplikasi yang dikembangkan di versi Pratinjau sebelumnya. Anda setuju bahwa Google boleh menghentikan (secara permanen atau sementara) penyediaan Pratinjau (atau fitur apa pun dalam Pratinjau) kepada Anda atau pengguna pada umumnya atas kebijakan Google semata, tanpa pemberitahuan sebelumnya kepada Anda. - -3.7 Perjanjian Lisensi ini tidak memberi Anda hak untuk menggunakan nama dagang, merek dagang, merek layanan, logo, nama domain, atau fitur merek khas Google lainnya. - -3.8 Anda setuju bahwa Anda tidak akan membuang, mengaburkan, atau mengubah pernyataan hak kepemilikan apa pun (termasuk pemberitahuan hak cipta dan merek dagang) yang terlampir atau termuat dalam Pratinjau. - -4. Penggunaan Pratinjau oleh Anda - -4.1 Google setuju bahwa Perjanjian Lisensi ini tidak memberi Google hak, kuasa, dan kepentingan hukum dari Anda (atau pemberi lisensi Anda) dalam atau pada aplikasi perangkat lunak apa pun yang Anda kembangkan menggunakan Pratinjau ini, termasuk kekayaan intelektual yang ada dalam aplikasi tersebut. - -4.2 Anda setuju untuk menggunakan Pratinjau dan menulis aplikasi hanya untuk tujuan yang diizinkan oleh (a) Perjanjian Lisensi, dan (b) hukum yang berlaku, peraturan atau praktik yang diterima secara umum atau panduan dalam yurisdiksi terkait (termasuk hukum mengenai ekspor data atau perangkat lunak ke dan dari Amerika Serikat atau negara lain yang terkait). - -4.3 Anda setuju jika Anda menggunakan Pratinjau untuk mengembangkan aplikasi, Anda akan melindungi hak privasi dan hak hukum pengguna. Jika pengguna memberikan nama pengguna, sandi, atau informasi login atau informasi pribadinya, Anda harus membuat pengguna tersebut menyadari bahwa informasi yang diberikannya akan bisa digunakan oleh aplikasi Anda, dan Anda harus memberikan perlindungan dan pemberitahuan privasi yang memadai secara hukum bagi pengguna tersebut. Jika aplikasi Anda menyimpan informasi pribadi atau sensitif yang diberikan oleh pengguna, aplikasi Anda harus melakukannya dengan aman. Jika pengguna memberikan informasi Akun Google, aplikasi Anda hanya boleh menggunakan informasi tersebut untuk mengakses Akun Google pengguna saat, dan untuk tujuan terbatas di mana, pengguna tersebut telah memberikan izin kepada Anda untuk melakukannya. - -4.4 Anda setuju bahwa Anda tidak akan terlibat dalam aktivitas apa pun dengan Pratinjau, termasuk pengembangan atau distribusi aplikasi yang mengganggu, mengacaukan, merusak, atau mengakses secara tidak sah server, jaringan atau properti layanan Google atau pihak ketiga lainnya. - -4.5 Anda setuju bertanggung jawab penuh untuk (dan bahwa Google tidak bertanggung jawab terhadap Anda atau pihak ketiga lainnya untuk) data, materi, atau sumber daya apa pun yang Anda buat, kirimkan atau tampilkan melalui Android dan/atau aplikasi untuk Android, dan terhadap konsekuensi tindakan Anda (termasuk kerugian atau kerusakan apa pun yang mungkin dialami Google). - -4.6 Anda setuju bertanggung jawab penuh terhadap (dan bahwa Google tidak bertanggung jawab terhadap Anda atau pihak ketiga lainnya untuk) pelanggaran kewajiban Anda berdasarkan Perjanjian Lisensi ini, kontrak pihak ketiga yang berlaku atau Ketentuan Layanan, atau hukum atau peraturan yang berlaku, dan terhadap konsekuensi (termasuk kerugian atau kerusakan yang mungkin dialami Google atau pihak ketiga lainnya) akibat pelanggaran tersebut. - -4.7 Pratinjau ini dalam tahap pengembangan, dan pengujian serta masukan Anda merupakan bagian penting dalam proses pengembangan. Dengan menggunakan Pratinjau, Anda mengakui bahwa implementasi beberapa fitur masih dalam tahap pengembangan dan bahwa Anda tidak seharusnya mengandalkan Pratinjau berfungsi sepenuhnya sebagaimana pada rilis stabil. Anda setuju untuk tidak mendistribusikan atau mengirimkan untuk umum penggunaan aplikasi menggunakan Pratinjau karena Pratinjau ini tidak akan lagi didukung setelah Android SDK dirilis secara resmi. - -5. Kredensial Pengembang Anda - -5.1 Anda setuju bertanggung jawab untuk menjaga kerahasiaan semua kredensial pengembang yang mungkin diberikan Google kepada Anda atau yang mungkin Anda pilih sendiri dan bahwa Anda akan bertanggung jawab penuh terhadap semua aplikasi yang dikembangkan dengan kredensial pengembang Anda. - -6. Privasi dan Informasi - -6.1 Untuk terus berinovasi dan meningkatkan Pratinjau, Google boleh mengumpulkan statistik penggunaan tertentu dari perangkat lunak termasuk namun tidak terbatas pada identifier unik, alamat IP terkait, nomor versi perangkat lunak, dan informasi yang menjadi tempat penggunaan alat dan/atau layanan dalam Pratinjau dan cara penggunaannya. Sebelum informasi ini dikumpulkan, Pratinjau akan memberi tahu dan meminta persetujuan Anda. Jika Anda tidak memberikan persetujuan, informasi tersebut tidak akan dikumpulkan. - -6.2 Data yang dikumpulkan akan diperiksa secara agregat untuk meningkatkan Pratinjau dan dikelola sesuai dengan Kebijakan Privasi Google yang terdapat di http://www.google.com/policies/privacy. - -7. Aplikasi Pihak Ketiga - -7.1 Jika Anda menggunakan Pratinjau untuk menjalankan aplikasi yang dikembangkan oleh pihak ketiga atau yang mengakses data, materi atau sumber daya yang disediakan oleh pihak ketiga, Anda setuju bahwa Google tidak bertanggung jawab terhadap aplikasi, data, materi atau sumber daya tersebut. Anda memahami bahwa semua data, materi atau sumber daya yang mungkin Anda akses melalui aplikasi pihak ketiga merupakan tanggung jawab penuh dari pihak yang menjadi asal data tersebut dan Google tidak bertanggung jawab terhadap kerugian atau kerusakan apa pun yang mungkin Anda alami sebagai akibat menggunakan atau mengakses aplikasi, data, materi, atau sumber daya pihak ketiga tersebut. - -7.2 Anda harus menyadari bahwa data, materi dan sumber daya yang diberikan kepada Anda melalui aplikasi pihak ketiga mungkin dilindungi oleh hak kekayaan intelektual yang dimiliki oleh penyedia (atau oleh orang lain atau perusahaan atas nama mereka). Anda tidak boleh memodifikasi, menyewakan, menyewabelikan, meminjamkan, menjual, mendistribusikan atau membuat karya turunan berdasarkan data, materi, atau sumber daya ini (baik secara keseluruhan atau sebagian) kecuali Anda secara khusus diberikan izin untuk melakukannya oleh pemilik yang bersangkutan. - -7.3 Anda mengakui bahwa penggunaan Anda atas aplikasi, data, materi, atau sumber daya pihak ketiga semacam itu tunduk pada ketentuan terpisah antara Anda dan pihak ketiga yang bersangkutan. - -8. Menggunakan Google API - -8.1 Google API - -8.1.1 Jika Anda menggunakan API (Antarmuka Pemrograman Aplikasi) untuk mengambil data dari Google, Anda mengakui bahwa data tersebut dilindungi hak kekayaan intelektual yang dimiliki Google atau pihak-pihak yang menyediakan data (atau oleh orang lain atau perusahaan atas nama mereka). Penggunaan API oleh Anda tunduk pada Ketentuan Layanan tambahan. Anda tidak boleh memodifikasi, menyewakan, menyewabelikan, meminjamkan, menjual, mendistribusikan atau membuat karya turunan berdasarkan data ini (baik secara keseluruhan atau sebagian) kecuali diizinkan oleh Ketentuan Layanan yang bersangkutan. - -8.1.2 Jika Anda menggunakan API dalam bentuk apa pun untuk mengambil data pengguna dari Google, Anda mengakui dan menyetujui bahwa Anda akan mengambil data hanya dengan persetujuan yang jelas dari pengguna dan hanya bila, dan sebatas keperluan yang diizinkan oleh pengguna tersebut untuk Anda lakukan. - -9. Mengakhiri Perjanjian Lisensi - -9.1 Perjanjian Lisensi ini akan terus berlaku hingga diakhiri oleh Anda atau Google sebagaimana diatur di bawah ini. - -9.2 Jika Anda ingin mengakhiri Perjanjian Lisensi ini, Anda boleh melakukannya dengan menghentikan penggunaan Pratinjau dan kredensial pengembang yang relevan. - -9.3 Google boleh mengakhiri Perjanjian Lisensi ini dengan Anda kapan saja, dengan atau tanpa sebab, setelah memberi tahu Anda. - -9.4 Perjanjian Lisensi akan berakhir secara otomatis tanpa pemberitahuan atau tindakan lainnya bila, mana saja yang lebih dahulu: -(A) Google berhenti menyediakan Pratinjau atau bagian Pratinjau tertentu kepada pengguna di negara tempat Anda tinggal atau negara tempat asal Anda menggunakan layanan; dan -(B) Google mengeluarkan versi rilis final dari Android SDK. - -9.5 Bila Perjanjian Lisensi berakhir, lisensi yang telah diberikan kepada Anda dalam Perjanjian Lisensi akan berakhir pula, Anda akan segera menghentikan semua penggunaan Pratinjau, dan ketetapan paragraf 10, 11, 12, dan 14 akan terus berlaku secara tak terbatas. - -10. SANGGAHAN - -10.1 ANDA SEPENUHNYA MEMAHAMI DAN MENYETUJUI BAHWA PENGGUNAAN PRATINJAU OLEH ANDA MERUPAKAN RISIKO ANDA SENDIRI DAN BAHWA PRATINJAU INI DISEDIAKAN "APA ADANYA" DAN "SEBAGAIMANA TERSEDIA" TANPA JAMINAN DALAM BENTUK APA PUN DARI GOOGLE. - -10.2 PENGGUNAAN PRATINJAU DAN MATERI APA PUN YANG DIUNDUH ATAU DIPEROLEH MELALUI PENGGUNAAN PRATINJAU OLEH ANDA ADALAH ATAS KEHENDAK DAN RISIKO ANDA SENDIRI DAN ANDA BERTANGGUNG JAWAB PENUH TERHADAP KERUSAKAN PADA SISTEM KOMPUTER ATAU PERANGKAT LAIN ATAU HILANGNYA DATA AKIBAT PENGGUNAAN TERSEBUT. TANPA MEMBATASI HAL TERSEBUT, ANDA MEMAHAMI BAHWA PRATINJAU BUKANLAH RILIS STABIL DAN MUNGKIN BERISI KESALAHAN, CACAT, DAN RISIKO KEAMANAN YANG BISA MENGAKIBATKAN KERUSAKAN SIGNIFIKAN, TERMASUK KEHILANGAN PENGGUNAAN ATAS SISTEM KOMPUTER ANDA ATAU PERANGKAT LAIN DENGAN SEPENUHNYA DAN TIDAK BISA DIPULIHKAN LAGI. - -10.3 GOOGLE LEBIH LANJUT MENYANGGAH SEMUA JAMINAN DAN PERSYARATAN APA PUN, BAIK TERSURAT MAUPUN TERSIRAT, TERMASUK NAMUN TIDAK TERBATAS PADA JAMINAN TERSIRAT DAN PERSYARATAN MENGENAI DAYA JUAL, KESESUAIAN DENGAN TUJUAN TERTENTU, DAN NON-PELANGGARAN. - -11. PEMBATASAN KEWAJIBAN - -11.1 ANDA SEPENUHNYA MEMAHAMI DAN MENYETUJUI BAHWA GOOGLE, ANAK PERUSAHAAN DAN AFILIASINYA, DAN PEMBERI LISENSINYA TIDAK AKAN BERTANGGUNG JAWAB KEPADA ANDA BERDASARKAN TEORI KEWAJIBAN TERHADAP SEGALA KERUGIAN LANGSUNG, TIDAK LANGSUNG, INSIDENTAL, KHUSUS, JANGKA PANJANG ATAU GANTI RUGI YANG DIAKIBATKAN OLEH ANDA, TERMASUK HILANGNYA DATA, WALAUPUN GOOGLE ATAU PERWAKILANNYA TELAH DIBERI TAHU ATAU SEHARUSNYA MENGETAHUI KEMUNGKINAN TIMBULNYA KEHILANGAN TERSEBUT. - -12. Penggantian Kerugian - -12.1 Sejauh maksimum yang diizinkan oleh hukum, Anda setuju untuk membela, mengganti kerugian dan melepaskan tanggung jawab Google, afiliasinya beserta direksi, petugas, karyawan dan agennya dari dan terhadap setiap dan semua klaim, tindakan, gugatan, proses hukum, serta setiap dan semua kehilangan, kewajiban, kerusakan, biaya dan pengeluaran (termasuk biaya pengacara yang sewajarnya) yang timbul atau diakibatkan dari (a) penggunaan Pratinjau oleh Anda, (b) aplikasi apa pun yang Anda kembangkan dari Pratinjau yang melanggar Hak Kekayaan Intelektual seseorang atau mencemarkan nama baik seseorang atau melanggar hak mereka berkaitan dengan publisitas atau privasi, dan (c) ketidakpatuhan Anda terhadap Perjanjian Lisensi ini. - -13. Perubahan pada Perjanjian Lisensi - -13.1 Google boleh membuat perubahan pada Perjanjian Lisensi saat mendistribusikan versi baru Pratinjau. Saat perubahan tersebut dibuat, Google akan menyediakan versi baru Perjanjian Lisensi di situs web penyediaan Pratinjau. - -14. Ketentuan Hukum Umum - -14.1 Perjanjian Lisensi ini merupakan perjanjian hukum antara Anda dan Google dan mengatur penggunaan Pratinjau oleh Anda (tidak termasuk layanan apa pun yang mungkin disediakan Google untuk Anda dalam perjanjian tertulis terpisah), dan sepenuhnya menggantikan perjanjian sebelumnya antara Anda dan Google dalam kaitannya dengan Pratinjau. - -14.2 Anda setuju bahwa jika Google tidak menjalankan atau menerapkan hak atau upaya hukum yang terkandung dalam Perjanjian Lisensi ini (atau bila Google memiliki kewenangan berdasarkan hukum yang berlaku), tindakan ini tidak akan dianggap sebagai pelepasan hak secara resmi oleh Google dan bahwa hak atau upaya hukum tersebut akan tetap bisa digunakan oleh Google. - -14.3 Jika persidangan hukum yang berwenang untuk memutuskan perkara ini menetapkan bahwa ada ketetapan Perjanjian Lisensi ini yang tidak valid, maka ketetapan tersebut akan dihapus dari Perjanjian Lisensi tanpa memengaruhi bagian selebihnya dari Perjanjian Lisensi ini. Ketetapan selebihnya dari Perjanjian Lisensi ini akan tetap sah dan berlaku. - -14.4 Anda mengakui dan menyetujui bahwa setiap anggota dari kelompok perusahaan yang diinduki oleh Google akan menjadi pihak ketiga penerima manfaat dari Perjanjian Lisensi ini dan bahwa perusahaan tersebut berhak untuk secara langsung memberlakukan, dan bergantung pada, ketetapan yang dimuat dalam Perjanjian Lisensi ini yang memberikan manfaat (atau hak yang mendukung) kepada mereka. Selain yang telah disebutkan di atas, tidak ada orang atau perusahaan lain yang akan menjadi pihak ketiga penerima manfaat dari Perjanjian Lisensi ini - -14.5 PEMBATASAN EKSPOR. PRATINJAU TUNDUK PADA HUKUM DAN PERATURAN EKSPOR AMERIKA SERIKAT. ANDA HARUS MEMATUHI SEMUA HUKUM DAN PERATURAN NASIONAL DAN INTERNASIONAL YANG BERLAKU PADA PRATINJAU. HUKUM INI MENYERTAKAN PEMBATASAN ATAS TUJUAN, PENGGUNA AKHIR DAN PENGGUNAAN AKHIR - -14.6 Perjanjian Lisensi ini tidak boleh diberikan atau dialihkan baik oleh Anda tanpa persetujuan tertulis sebelumnya dari Google, dan upaya apa pun untuk mengalihkannya tanpa persetujuan akan menjadi tidak sah. Anda tidak boleh mendelegasikan tanggung jawab atau kewajiban berdasarkan Perjanjian Lisensi ini tanpa persetujuan tertulis sebelumnya dari pihak lain. - -14.7 Perjanjian Lisensi ini, dan hubungan Anda dengan Google berdasarkan Perjanjian Lisensi ini, akan diatur oleh hukum Negara Bagian California tanpa mengindahkan pertentangan ketetapan hukumnya. Anda dan Google setuju untuk tunduk pada yurisdiksi eksklusif pengadilan yang berlokasi di county Santa Clara, California untuk menyelesaikan segala masalah hukum yang timbul dari Perjanjian Lisensi ini. Meski demikian, Anda setuju bahwa Google akan tetap diizinkan untuk mengajukan upaya hukum (atau tipe keringanan hukum setara yang mendesak) dalam yurisdiksi apa pun. - - -
      \ No newline at end of file diff --git a/docs/html-intl/intl/in/preview/overview.jd b/docs/html-intl/intl/in/preview/overview.jd deleted file mode 100644 index c1fc0b5dabe420295c011d90412d4c7de06c1c08..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/overview.jd +++ /dev/null @@ -1,440 +0,0 @@ -page.title=Ringkasan Program -page.metaDescription=Persiapkan aplikasi Anda untuk versi Android berikutnya -page.image=images/cards/card-n-overview_2x.png -meta.tags="preview", "developer", "android" -page.tags="preview", "developer", "android" - -@jd:body - - -

      - Selamat datang di Android N Developer Preview, program yang - akan memberi apa saja yang Anda butuhkan untuk menguji dan mengoptimalkan aplikasi untuk versi - Android berikutnya. Program ini tersedia gratis, dan Anda bisa langsung mulai hanya dengan - mengunduh alat bantu N Developer Preview. -

      - - - - - - - -
      -
      -
      -
      -
      - Gambar perangkat keras dan emulator -
      - -

      - Jalankan dan uji aplikasi Anda pada berbagai perangkat atau pada emulator. - -

      -
      - -
      -
      - Kode platform terbaru -
      - -

      - Kami akan menyediakan pembaruan setiap bulan selama Pratinjau, agar Anda bisa menguji perubahan platform terbaru. -

      -
      - -
      -
      - Prioritas untuk masalah pengembang -
      - -

      - Selama beberapa minggu pertama, kami akan memberikan prioritas pada masalah-masalah - yang dilaporkan pengembang, jadi ujilah dan berikan masukan sesegera mungkin. -

      -
      - -
      - -
      - - -
      -
      - Kemampuan dan perilaku baru -
      - -

      - Mulailah pekerjaan lebih awal untuk mendukung perilaku platform baru dan kembangkan dengan fitur-fitur baru. -

      -
      - -
      -
      - Pembaruan dikirim melalui OTA -
      - -

      - Pembaruan lewat jaringan seluler tanpa kendala untuk setiap perangkat yang didukung melalui - Android Beta Program. Flashing tidak diperlukan. -

      -
      - -
      -
      - Masukan dan dukungan -
      - -

      - Laporkan masalah dan berikan masukan kepada kami dengan menggunakan - Issue Tracker kami. Hubungkan dengan - pengembang lain di - N Developer Community. -

      -
      -
      -
      -
      - - - -

      Kronologi dan pembaruan

      - - -

      - N Developer Preview berjalan dari 9 Maret 2016 hingga rilis resmi Android N - final ke AOSP dan OEM, yang direncanakan selama Kuartal 3 2016. -

      - -

      - Pada tahapan pencapaian pengembangan yang penting kami akan mengirimkan pembaruan untuk lingkungan pengujian dan - pengembangan Anda. Pada umumnya Anda diharapkan sudah memperoleh pembaruan setiap bulan (dengan interval 4 sampai 6 - minggu). Tahapan pencapaian tersebut tercantum di bawah ini. -

      - -
        -
      • Pratinjau 1 (rilis pertama, alfa)
      • -
      • Pratinjau 2 (pembaruan bertahap, alfa)
      • -
      • Pratinjau 3 (pembaruan bertahap, beta)
      • -
      • Pratinjau 4 (API final dan SDK resmi, publikasi di Play)
      • -
      • Pratinjau 5 (citra sistem hampir final untuk pengujian akhir)
      • -
      • Rilis Final ke AOSP dan ekosistem
      • -
      - -

      - Setiap pembaruan menyertakan SDK Tools, citra sistem pratinjau, emulator, dokumentasi - referensi, dan diff API. -

      - -

      - Tiga tahapan pencapaian pratinjau pertama memberikan ujian - pertama dan lingkungan pengembangan yang membantu Anda mengidentifikasi - masalah kompatibilitas dalam aplikasi Anda saat ini dan merencanakan migrasi atau menampilkan pekerjaan - yang diperlukan untuk menargetkan platform baru. Ini adalah periode prioritas yang akan - memberi kami masukan dari Anda tentang fitur dan API serta masalah kompatibilitas file - — untuk semua ini, gunakan Issue - Tracker. Anda bisa mengharapkan beberapa perubahan API dalam pembaruan ini. -

      - -

      - Pada pratinjau 4 dan 5 Anda akan memiliki akses ke - API dan SDK N final untuk digunakan dalam pengembangan, serta citra sistem hampir-final - untuk menguji perilaku dan fitur sistem. Android N akan memberikan level API - standar pada saat ini. Anda bisa memulai pengujian kompatibilitas final dari aplikasi - lawas dan menyaring setiap kode baru yang menggunakan API atau fitur N. -

      - -

      - Juga, mulai pratinjau 4, Anda akan bisa mempublikasikan aplikasi ke - perangkat yang menjalankan Android N pada level API resmi, seperti - perangkat konsumen yang telah mengikuti program Android Beta. Anda bisa - mempublikasikan ke saluran alfa dan beta Google Play terlebih dahulu, agar Anda bisa menguji - aplikasi pada konsumen Android Beta sebelum mendistribusikan secara luas di - toko. -

      - -

      - Saat Anda menguji dan mengembangkan di Android N, kami sangat menyarankanterus memperbarui - lingkungan pengembangan saat pembaruan pratinjau - dirilis. Untuk mempermudah prosesnya, Anda bisa mendaftarkan perangkat pengujian di - program Android Beta dan mendapatkan pembaruan lewat jaringan seluler (OTA) - pada setiap tahapan pencapaian. Sebagai alternatif, citra pratinjau terbaru telah tersedia agar Anda - bisa mengunduh dan mem-flash secara manual. -

      - -

      - Kami akan memberi tahu Anda bila pembaruan pratinjau telah tersedia lewat Android Developers Blog serta - situs ini dan Android - N Developer Community. -

      - - -

      Apa yang ada di N Developer Preview?

      - -

      - N Developer Preview menyertakan apa saja yang Anda perlukan untuk menguji aplikasi - yang ada pada berbagai ukuran layar, teknologi jaringan, chipset CPU/GPU, - dan arsitektur perangkat keras. -

      - -

      SDK Tools

      - -

      Anda bisa mengunduh komponen-komponen ini melalui SDK Manager di Android Studio:

      - -
        -
      • SDK dan alat N Developer Preview -
      • Citra sistem emulator N Developer Preview (32-bit & 64-bit) -
      • Citra sistem emulator N Developer Preview untuk Android TV (32-bit) -
      • N Developer Preview mendukung pustaka (untuk template aplikasi baru) -
      - -

      - Kami akan menyediakan pembaruan untuk alat pengembangan ini di setiap tahapan pencapaian jika diperlukan. -

      - -

      Citra sistem perangkat keras

      - -

      - N Developer Preview menyertakan citra sistem Nexus dan perangkat keras lainnya yang bisa Anda gunakan saat - menguji dan mengembangkan pada perangkat fisik. Lihat halaman Citra Perangkat untuk melihat daftar lengkap - citra perangkat keras. -

      - -

      - Kami akan mengirimkan citra sistem terbaru untuk perangkat ini pada setiap tahapan pencapaian. Anda - bisa mengunduh dan mem-flash citra sistem yang diperbarui untuk perangkat pengujian - secara manual, sesering yang Anda perlukan. Ini terutama berguna untuk lingkungan pengujian - otomatis bila Anda mungkin perlu mem-flash ulang perangkat beberapa - kali. -

      - -

      Catatan: - Perangkat yang di-flash secara manual tidak akan mendapatkan pembaruan OTA seperti di - pratinjau tahun lalu. Tahun ini, Anda bisa memperoleh OTA dengan mendaftarkan perangkat dalam - Android Beta Program — lihat detailnya di bagian berikutnya. -

      - -

      Pembaruan OTA melalui Android Beta Program

      - -

      - Yang baru untuk Android N adalah program pembaruan lewat jaringan seluler (OTA) yang secara otomatis - mengirim pembaruan pratinjau terbaru Android N secara langsung ke perangkat yang telah mendaftar - di program ini. Program ini gratis dan terbuka bagi siapa saja yang memiliki - perangkat yang didukung dan telah didaftarkan ke akun Google mereka. -

      - -

      - Untuk mendaftar dalam program ini, kunjungi situs Android - Beta Program. Anda akan - melihat semua perangkat yang telah didaftarkan ke akun Anda yang memenuhi syarat untuk mendaftar - dalam Android Beta. -

      - -
        -
      1. Pilih perangkat yang Anda inginkan untuk menerima pembaruan Android N -
      2. Klik Enroll, baca dan setujui ketentuan layanan, kemudian klik OK -
      - -

      - Setelah terdaftar, perangkat Anda akan segera menerima pembaruan. Umumnya - Anda tidak perlu penyetelan ulang penuh atas data untuk beralih ke Android N, namun - Anda disarankan mencadangkan setiap data yang tidak ingin hilang sebelum - mendaftarkan perangkat. -

      - -

      - Saat pembaruan dikirim ke perangkat Anda, kami menyarankan Anda untuk segera mengunduh dan - memasangnya. Anda perlu terus mengikuti perubahan terbaru - dalam UI sistem, perilaku, API, dan fitur. -

      - -

      - Di akhir periode Developer Preview, perangkat Anda yang telah didaftarkan akan - menerima pembaruan ke rilis resmi Android N. -

      - -

      - Anda bisa membatalkan pendaftaran perangkat dari program Android Beta kapan saja dari - situs Android Beta. Sebelum membatalkan pendaftaran, pastikan Anda telah mencadangkan data pada - perangkat. -

      - -

      Catatan: - Bila membatalkan pendaftaran, perangkat Anda akan dikembalikan ke setelan pabrik - ke versi terbaru - Android 6.0 Marshmallow (tidak harus ke versi yang telah Anda - pasang sebelum mendaftarkan perangkat). Untuk memastikan pemasangan yang bersih, - data Anda akan dihapus dari perangkat, termasuk kontak, pesan, - foto, dan seterusnya. -

      - -

      Dokumentasi dan kode contoh

      - -

      - Sumber daya dokumentasi ini tersedia pada situs Developer Preview untuk - membantu Anda mempelajari tentang Android N: -

      - -
        -
      • Menyiapkan Pengembangan untuk -Android N memiliki - petunjuk langkah demi langkah untuk memulai.
      • -
      • Perubahan - Perilaku akan menunjukkan kepada Anda bidang-bidang utama untuk diuji.
      • -
      • Dokumentasi API baru, termasuk Ringkasan API, - Referensi - API yang bisa diunduh, dan panduan pengembang detail mengenai fitur-fitur utama seperti - dukungan multi-jendela, bundel pemberitahuan, dukungan multilokal, dan lainnya. -
      • Kode contoh yang - memperagakan cara mendukung izin dan fitur baru lainnya. -
      • Catatan rilis - untuk versi N Developer Preview saat ini, termasuk catatan perubahan dan - laporan diff. -
      - -

      Referensi API yang Bisa Diunduh

      - -

      - Selama pembaruan pratinjau awal, Anda bisa mengunduh - Referensi API - untuk platform Android N sebagai arsip zip terpisah. Unduhan - referensi juga menyertakan laporan diff yang akan membantu Anda mengenali perubahan API dari - API 23 dan pembaruan sebelumnya. -

      - -

      - Bila API Android N sudah final dan API level resmi telah ditetapkan, - kami akan menyediakan referensi API kepada Anda secara online di https://developer.android.com. -

      - -

      - Sumber daya dukungan -

      - -

      - Saat Anda menguji dan mengembangkan N Developer Preview, gunakan saluran - ini untuk melaporkan masalah dan memberikan masukan. -

      - -
        -
      • N Developer Preview Issue - Tracker adalah saluran masukan Anda. Anda bisa melaporkan bug, masalah - kinerja, dan masukan umum melalui Issue Tracker. Anda juga bisa memeriksa -masalah yang diketahui dan - mencari langkah-langkah solusinya. Kami akan terus mengabari Anda mengenai masalah tersebut bila telah disortir dan dikirimkan ke - tim teknis Android untuk ditinjau.
      • -
      • Android N Developer Community adalah - sebuah komunitas Google+ tempat Anda bisa terhubung dengan pengembang lain yang menggunakan - Android N. Anda bisa menyampaikan pengamatan atau ide atau menemukan jawaban atas - pertanyaan-pertanyaan mengenai Android N. Kami akan memoderasi komunitas ini dan memberikan jawaban serta - panduan jika diperlukan.
      • -
      - -

      Menargetkan, API pratinjau, dan mempublikasikan

      - -

      - N Developer Preview menyediakan sistem pengembangan saja dan pustaka - Android yang tidak memiliki API level standar. Jika Anda tidak ingin - mengikuti perilaku kompatibilitas untuk menguji aplikasi (yang sangat - disarankan), Anda bisa menargetkan versi pratinjau Android N dengan menyetel - targetSdkVersion - aplikasi Anda ke “N”. -

      - -

      - Android N Developer Preview menghasilkan API pratinjau - — API ini tidak akan resmi hingga SDK final dirilis, - yang saat ini direncanakan untuk kuartal ketiga 2016. Berarti Anda bisa - mengharapkan ada banyak perubahan kecil pada API selama waktu ini, terutama selama - minggu-minggu awal program. Kami akan menyediakan rangkuman perubahan kepada Anda bersama - setiap pembaruan Android N Developer Preview. -

      - -

      - Catatan: Meskipun API pratinjau mungkin berubah, perilaku dasar - sistem sudah stabil dan siap diuji. - -

      - -

      - Google Play mencegah publikasi aplikasi yang menargetkan N Developer - Preview. Bila Android N final SDK tersedia, Anda akan bisa - menargetkan level API Android N resmi dan mempublikasikan aplikasi ke Google - Play lewat saluran rilis alfa dan beta. Sementara itu, jika Anda ingin - mendistribusikan aplikasi yang menargetkan Android N kepada penguji, Anda bisa melakukannya lewat email atau - dengan mengunduh langsung dari situs Anda. -

      - -

      - Saat rilis penuh Android N ke AOSP dan OEM, yang direncanakan pada Kuartal 3 2016, - Anda akan bisa mempublikasikan aplikasi yang menargetkan Android N ke saluran - rilis resmi di Google Play. -

      - - -

      Cara mulai

      - -

      - Untuk mulai menguji aplikasi Anda dengan Android N: -

      - -
        -
      1. Tinjau Ringkasan API - dan Perubahan Perilaku untuk - mendapatkan gambaran mengenai apa saja yang baru dan bagaimana pengaruhnya pada aplikasi Anda. Khususnya, - pelajari tentang fitur baru pemberitahuan dan - dukungan multi-jendela.
      2. -
      3. Siapkan lingkungan Anda dengan mengikuti petunjuk berikut untuk Menyiapkan SDK Pratinjau - dan mengonfigurasi perangkat pengujian.
      4. -
      5. Ikuti petunjuk - flashing untuk mem-flash citra sistem Android N terbaru ke perangkat Anda.
      6. -
      7. Tinjau Referensi API - dan contoh Android N untuk mendapatkan wawasan - lebih luas mengenai fitur-futur API yang baru dan cara menggunakannya dalam aplikasi Anda. -
      8. Bergabunglah dengan Android N - Developer Community untuk mendapatkan berita terbaru dan terhubung dengan pengembang - lainnya yang menggunakan platform baru ini.
      9. -
      - -

      - Terima kasih atas partisipasi Anda dalam program Android N Developer Preview! -

      diff --git a/docs/html-intl/intl/in/preview/preview_toc.cs b/docs/html-intl/intl/in/preview/preview_toc.cs deleted file mode 100644 index 5868e4d741a436d7f4b5eaaad6ba4183ca2096f0..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/preview_toc.cs +++ /dev/null @@ -1,75 +0,0 @@ - \ No newline at end of file diff --git a/docs/html-intl/intl/in/preview/setup-sdk.jd b/docs/html-intl/intl/in/preview/setup-sdk.jd deleted file mode 100644 index 999970563db31991bf8df26b30b8008d68027d61..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/setup-sdk.jd +++ /dev/null @@ -1,187 +0,0 @@ -page.title=Menyiapkan Pratinjau -meta.keywords="preview", "android" -page.tags="preview", "developer preview" -page.image=images/cards/card-n-sdk_2x.png - -@jd:body - - - - -

      Untuk mengembangkan aplikasi bagi Android N Preview, Anda perlu membuat beberapa pembaruan -pada lingkungan pengembang, seperti dijelaskan pada halaman ini.

      - -

      Untuk sekedar menguji kompatibilitas aplikasi Anda pada -citra sistem Android N, ikuti panduan untuk Menguji pada Perangkat Android N.

      - - - - -

      Dapatkan Android Studio 2.1

      - -

      Platform Android N menambahkan dukungan untuk fitur bahasa Java 8, -yang memerlukan compiler baru bernama Jack. Jack versi terbaru -saat ini hanya didukung di Android Studio 2.1. Jadi, jika Anda ingin -menggunakan fitur bahasa Java 8, Anda harus menggunakan Android Studio 2.1 untuk -membangun aplikasi. Jika tidak, Anda tidak perlu menggunakan compiler Jack, namun Anda -tetap harus memperbarui JDK 8 untuk mengompilasi pada platform Android N, -seperti dijelaskan di bawah ini.

      - -

      Jika sudah memasang Android Studio, pastikan Anda memiliki Android -Studio 2.1 atau yang lebih tinggi dengan mengklik Help > Check for Update -(pada Mac, Android Studio > Check for Updates).

      - -

      Jika Anda tidak memilikinya, unduh Android Studio -2.1 di sini.

      - - -

      Dapatkan N Preview SDK

      - -

      Untuk mulai mengembangkan dengan Android N API, Anda perlu pasang -Android N Preview SDK di Android Studio sebagai berikut:

      - -
        -
      1. Buka SDK Manager dengan mengklik Tools > Android > - SDK Manager.
      2. - -
      3. Di tab SDK Platforms pilih -kotak centang Android N Preview.
      4. - -
      5. Klik tab SDK Tools, kemudian pilih - kotak centang Android SDK Build Tools, Android SDK - Platform-Tools, dan Android SDK Tools. - -
      6. - -
      7. Klik OK, kemudian terima - perjanjian lisensi untuk setiap paket yang perlu dipasang. -
      8. -
      - -

      Dapatkan dokumentasi referensi N Preview

      - -

      - Informasi detail tentang Android N API tersedia dalam dokumentasi referensi N Preview, - yang bisa Anda unduh dari tabel berikut. - Paket ini berisi versi offline situs web pengembang Android yang disederhanakan, - dan termasuk referensi API yang diperbarui untuk Android N API serta - laporan perbedaan API. -

      - - - - - - - - - - -
      DokumentasiChecksum
      - n-preview-3-docs.zip - MD5: 19bcfd057a1f9dd01ffbb3d8ff7b8d81
      - SHA-1: 9224bd4445cd7f653c4c294d362ccb195a2101e7 -
      - - - -

      Dapatkan Java 8 JDK

      - -

      Untuk mengompilasi aplikasi Anda pada platform Android N dan menggunakan beberapa alat bersama -Android Studio 2.1, Anda perlu pasang Java 8 Developer Kit (JDK 8). Jadi, jika -Anda belum mempunyai versi terbaru, unduh JDK 8 sekarang.

      - -

      Kemudian, setel versi JDK di Android Studio sebagai berikut:

      - -
        -
      1. Buka proyek Android di Android Studio, kemudian buka - dialog Project Structure dengan memilih File > - Project Structure. (Atau, Anda bisa menyetel default - untuk semua proyek dengan memilih File > Other Settings > - Default Project Structure.) -
      2. -
      3. Di panel kiri dialog, klik SDK Location. -
      4. -
      5. Dalam bidang JDK Location, masukkan lokasi - Java 8 JDK (klik tombol di sebelah kanan - untuk menjelajah file Anda), kemudian klik OK. -
      6. -
      - - - - -

      Perbarui atau Buat sebuah Proyek

      - -

      - Untuk menggunakan Android N API, proyek Anda harus dikonfigurasi dengan benar. -

      - -

      Jika Anda berencana menggunakan fitur bahasa Java 8, Anda juga harus membaca -Fitur Bahasa Java 8 -untuk informasi tentang fitur Java 8 yang didukung dan -cara mengonfigurasi proyek Anda dengan Jack compiler.

      - - -

      Perbarui proyek yang ada

      - -

      Buka file - build.gradle untuk modul Anda dan perbarui nilainya sebagai - berikut: -

      - -
      -android {
      -  compileSdkVersion 'android-N'
      -  buildToolsVersion '24.0.0-rc3'
      -  ...
      -
      -  defaultConfig {
      -     minSdkVersion 'N'
      -     targetSdkVersion 'N'
      -     ...
      -  }
      -  ...
      -}
      - - -

      Buat proyek baru

      - - -

      Untuk membuat proyek baru bagi pengembangan dengan Android N Preview SDK:

      - -
        -
      1. Klik File > New Project, dan ikuti langkah-langkahnya hingga - Anda tiba di halaman Target Android Devices. -
      2. -
      3. Pada halaman ini, pilih opsi Phone and Tablet.
      4. -
      5. Pada opsi Phone and Tablet, dalam daftar opsi Minimum - SDK, pilih - N: Android API 23, N Preview (Pratinjau).
      6. -
      - - -

      Langkah Berikutnya

      - - - diff --git a/docs/html-intl/intl/in/preview/support.jd b/docs/html-intl/intl/in/preview/support.jd deleted file mode 100644 index 5571b11610f6d35e55c2ccd61f5e087b1f068667..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/in/preview/support.jd +++ /dev/null @@ -1,1188 +0,0 @@ -page.title=Dukungan dan Catatan Rilis -meta.keywords="preview", "android" -page.tags="preview", "developer preview" -page.image=images/cards/card-n-support_2x.png - -@jd:body - - - - -

      - Dua saluran dukungan utama tersedia untuk Anda saat mengembangkan dan menguji - dengan Android N Developer Preview: Laporkan bug di https://developer.android.com/preview/bug untuk - bug perangkat tertentu, sistem, dan Google App. Untuk masalah di aplikasi lain, - hubungi pengembang secara langsung. -

      - -

      Untuk mendiskusikan masalah atau gagasan dengan pengembang lain yang menangani Android N, bergabunglah dengan -komunitas Google+ untuk Developer Preview.

      - -

      Developer Preview 3

      - -
      -
      -
      -

      - Tanggal: Mei 2016
      - Build: NPD35K
      - Dukungan emulator: x86 & ARM (32/64-bit)
      - Google Play Services: 8.4
      -

      -
      -
      -
      - -

      Saran umum

      - -

      - Rilis Developer Preview ini adalah untuk pengembang aplikasi dan pengguna - awal lainnya serta tersedia untuk penggunaan sehari-hari, pengembangan, atau - pengujian kompatibilitas. Harap perhatikan catatan umum tentang - rilis ini: -

      - -
        -
      • Rilis ini mungkin memiliki berbagai masalah stabilitas pada - perangkat yang didukung. Pengguna mungkin mengalami ketidakstabilan sistem, seperti kernel - yang panik dan mogok. -
      • - -
      • Beberapa aplikasi mungkin tidak berfungsi seperti yang diharapkan pada versi - platform baru. Hal ini termasuk aplikasi Google serta aplikasi lainnya. -
      • - -
      • Developer Preview 3 adalah Compatibility Test Suite (CTS) - yang disetujui pada perangkat ini: Nexus 5X, Nexus 6, Nexus 6P, dan Pixel - C. Aplikasi yang bergantung pada build yang disetujui CTS seharusnya - berfungsi secara normal pada perangkat ini (Android Pay misalnya). -
      • - -
      • Developer Preview 3 tersedia pada semua perangkat - yang didukung: Nexus 5X, Nexus 6, Nexus 6P, Nexus 9, Nexus Player, Pixel - C, General Mobile 4G (Android One), serta Sony Xperia Z3 (model D6603 dan - D6653). - -
      • -
      - - -

      Yang baru di DP3

      - -

      VR Mode untuk Android

      - -

      - Android N menambahkan dukungan platform dan optimalisasi untuk VR Mode baru yang memungkinkan - pengembang membuat pengalaman VR berkualitas tinggi di seluler bagi para pengguna. Ada - banyak penyempurnaan kinerja, termasuk akses ke inti CPU yang eksklusif - untuk aplikasi VR. Dalam aplikasi, Anda bisa memanfaatkan pemantauan kepala - yang cerdas, dan pemberitahuan stereo yang bekerja untuk VR. Yang terpenting, - Android N memberikan grafis latensi sangat rendah. -

      - -

      - Untuk informasi selengkapnya, lihat Google VR SDK untuk Android. -

      - -

      Mode kinerja kontinu

      - -

      - Android N menyertakan dukungan opsional untuk mode - kinerja kontinu, yang memungkinkan OEM memberikan petunjuk mengenai kapabilitas kinerja - perangkat untuk aplikasi yang berjalan dalam waktu lama. Pengembang aplikasi nanti bisa menggunakan - petunjuk ini untuk menyesuaikan aplikasi agar kinerja - perangkat bisa diprediksi pada level yang konsisten dalam jangka waktu lama. Pengembang aplikasi bisa mencoba API - baru ini dalam Developer Preview pada perangkat Nexus 6P saja. -

      - -

      Multiprocess WebView

      - -

      - Mulai versi 51 di Android N, WebView akan menjalankan materi web dalam - proses sandbox terpisah bila opsi pengembang "Multiprocess Webview" - diaktifkan. Tim WebView menunggu masukan mengenai kompatibilitas dan - kinerja waktu proses di N sebelum mengaktifkan Multiprocess WebView di versi Android - yang akan datang. Dalam versi ini, diharapkan adanya regresi waktu startup, penggunaan - memori total dan kinerja render perangkat lunak. -

      - -

      - Jika Anda menemukan masalah yang tidak diharapkan dalam mode multiproses, kami ingin - mengetahuinya. Hubungi tim WebView dengan - melaporkan bug. -

      - -

      Keyboard Shortcuts Helper

      - -

      - Android N memungkinkan pengguna menekan Meta+/ untuk memunculkan layar Keyboard - Shortcuts yang menampilkan semua pintasan yang tersedia baik dari - sistem maupun dari aplikasi yang sedang mendapatkan fokus. Pengembang bisa menambahkan pintasan sendiri atau - memunculkan layar Shortcuts dari aplikasi mereka. Lihat Keyboard - Shortcuts Helper untuk detailnya. -

      - -

      FrameMetrics API

      - -

      - DP3 memperkenalkan FrameMetrics API - baru yang memungkinkan aplikasi memantau kinerja render UI dengan mengekspos - streaming pubsub API untuk mentransfer informasi frame-timing jendela aplikasi - saat ini. FrameMetricsListener bisa digunakan untuk mengukur - kinerja UI level interaksi di produksi dengan tingkat kejelasan yang lebih tinggi dan - tidak memerlukan koneksi USB. -

      - -

      Fitur dan perubahan API

      - -
      -
      - Pintasan Peluncur dan Launcher Shortcuts API -
      - -
      - Kami memutuskan untuk menunda fitur ini pada rilis Android yang akan datang. Kami berencana - membuang Launcher Shortcuts API (ShortcutManager dan lainnya) dari - Android N API publik mulai dalam Developer Preview berikutnya. -
      - -
      - WebView Javascript berjalan sebelum halaman dimuat -
      - -
      - Mulai dengan aplikasi yang menargetkan Android N, konteks Javascript disetel ulang - saat halaman baru telah dimuat. Saat ini, konteks tersebut dibawa untuk - halaman pertama yang dimuat di instance {@link android.webkit.WebView} yang baru. - Pengembang yang ingin menginjeksikan Javascript ke dalam {@link -android.webkit.WebView} harus mengeksekusi skrip setelah halaman - mulai dimuat. -
      - -
      - WebView Geolocation pada sumber yang tidak aman -
      - -
      - Mulai dengan aplikasi yang menargetkan Android N, API geolokasi hanya akan - diizinkan pada sumber yang aman (melalui HTTPS). Kebijakan ini didesain untuk melindungi - informasi privat pengguna saat mereka menggunakan koneksi yang tidak aman. -
      - -
      - Data Saver -
      - -
      - Mulai di Developer Preview 3, aplikasi bisa menggunakan intent untuk menampilkan - dialog sistem yang memungkinkan pengguna menambahkan aplikasi secara langsung ke daftar putih pengecualian - Data Saver. Lihat dokumentasi - Data Saver untuk detailnya. -
      - -
      - Pemblokiran nomor -
      - -
      - Jika pengguna yang tidak diizinkan berusaha memblokir atau membuka blokir suatu nomor, operasi - tersebut kini akan gagal dengan {@link java.lang.SecurityException}. (Sebelumnya, - operasi tersebut akan melontarkan {@link java.lang.UnsupportedOperationException}.) -
      - -
      - Quick Settings Tile - API -
      - -
      - Sistem kini menggunakan metadata aktivitas untuk memutuskan mode petak. - (Sebelumnya, mode petak ditentukan oleh nilai hasil - TileService.onTileAdded().) Untuk informasi selengkapnya, lihat - TileService.META_DATA_ACTIVE_TILE dalam Referensi API yang bisa diunduh. -
      -
      - -

      Perbaikan untuk masalah yang dilaporkan oleh pengembang

      - -

      - Banyak masalah yang dilaporkan oleh pengembang telah diperbaiki, termasuk: -

      - -
        -
      • Pemutaran Bluetooth Audio yang terputus setelah 1 lagu (bug 206889) -
      • - -
      • Pixel C Terus Mengalami Mogok (bug 206962) -
      • - -
      • Masalah pemberitahuan Jam dan Toast (bug 203094) -
      • - -
      • Pixel C melakukan boot ulang saat dihubungkan ke MacBook Pro lewat Kabel USB C (bug - 205432) -
      • - -
      • Kalender selisih satu hari (bug 203002) -
      • - -
      • TelephonyManager.getAllCellInfo menghasilkan data tidak valid (bug 203022) -
      • - -
      • Nexus 6p, Bluetooth terputus terus-menerus (bug 208062) -
      • -
      - -

      Untuk daftar lengkap masalah yang telah diperbaiki, lihat Issue -Tracker.

      - -

      Masalah yang Diketahui

      - -

      Aksesibilitas

      - -
        -
      • Tidak bisa memantau output TTS saat pitch disetel mendekati level maksimum. -
      • - -
      • Fitur dan setelan aksesibilitas bisa terganggu bila pengguna menambahkan - sebuah profil kerja, termasuk isyarat perbesaran dan setelan. Kondisi - aksesibilitas dipulihkan bila pengguna menyentuh setelan terkait. -
      • -
      - -

      Kamera

      - -
        -
      • Aplikasi Kamera telah menunjukkan ketidakstabilan; aplikasi ini bisa mogok dalam berbagai - keadaan, seperti saat diluncurkan dalam mode multi-jendela. -
      • - -
      • Menekan rana terus-menerus dalam mode panorama dapat menyebabkan aplikasi - Kamera mogok. -
      • -
      - -

      Audio

      -
        -
      • Masalah pemutar audio platform mencegah beberapa aplikasi berfungsi - secara normal. Misalnya, Skype dan aplikasi lain terpengaruh oleh masalah ini. -
      • -
      - -

      Konektivitas

      - - -
        -
      • Bila perangkat peran periferal Bluetooth Low Energy (BLE) mengiklankan suatu - layanan dan perangkat peran sentral BLE menghubungkan, perangkat peran periferal - akan terputus dengan sangat cepat. -
      • - -
      • Koneksi Wi-Fi dapat melemah bila layar mati. -
      • - -
      • Koneksi RFCOMM tidak stabil serta dapat mengakibatkan kerusakan data dan - koneksi yang menggantung. -
      • - -
      • Kondisi jaringan aktif ({@link android.net.NetworkInfo#getState - NetworkInfo.getState()} dan {@link android.net.NetworkInfo#getDetailedState - NetworkInfo.getDetailedState()}) mungkin mengembalikan nilai yang tidak benar selama beberapa - skenario latar belakang terbatas. -
      • -
      - - -

      - Peluncur -

      - -
        -
      • Baki All Apps peluncur default mungkin menjadi tidak responsif setelah - layar dimatikan/dihidupkan berulang-ulang. Kembali ke layar beranda dan meluncurkan kembali - baki All Apps mungkin akan mengatasi masalah ini. -
      • -
      - -

      - Keyboard -

      - -
        -
      • Saat memperbarui perangkat yang menjalankan Android 6.0 atau yang sebelum versi N Developer - Preview, Keyboard Google tidak menyimpan data preferensi seperti emoji - terbaru dan setelan suara. -
      • - -
      • Google Indic Managed Keyboard mungkin menjadi tidak stabil. -
      • - -
      • Saat memasukkan teks dalam bidang sandi, pengguna bisa memilih bahasa Rusia sebagai - bahasa masukan, namun keyboard tetap dalam bahasa Inggris. Hal ini mencegah - pengguna memasukkan sandi berbahasa Rusia. -
      • -
      - -

      - Lokal dan bahasa -

      - -
        -
      • Saat menggunakan lokal kanan-ke-kiri (RTL), sistem mungkin secara tidak diharapkan - beralih ke presentasi kiri-ke-kanan (LTR) setelah menghidupkan ulang perangkat. -
      • -
      - -

      Media

      - -
        -
      • Pemutaran media mungkin tidak bisa diandalkan pada Nexus 9 dan Nexus Player, termasuk - masalah pemutaran video HD. -
      • -
      - -

      - Mode multi-jendela -

      - -
        -
      • Perangkat mungkin macet saat mengubah orientasi dalam mode multi-jendela. -
      • - -
      • Beberapa aplikasi saat ini memiliki masalah dengan mode multi-jendela: -
          -
        • UI sistem bisa mogok saat mengubah Settings > Display > - Screen brightness ke multi-jendela. -
        • - -
        • Aplikasi Kamera mungkin mogok bila diluncurkan dalam mode multi-jendela. -
        • - -
        • YouTube mungkin mogok bila diluncurkan dalam mode multi-jendela. Untuk memperbaiki - masalah ini, Anda bisa mengosongkan data aplikasi YouTube di Storage > Apps > - YouTube. -
        • -
        -
      • -
      - -

      - Google Play Services -

      - -
        -
      • Aplikasi yang menggunakan Google Cast melalui Google Play Services mungkin menjadi tidak stabil bila - pengguna memilih lokal sistem yang menggunakan huruf serta angka di luar - rentang ASCII. -
      • -
      - -

      - Kebijakan Perangkat Android for Work dan Google Apps -

      - -
        -
      • Aplikasi Device Policy mungkin mogok bila pengguna membuka kunci perangkat dengan - layar "status kebijakan perangkat" disematkan. -
      • - -
      • Setelah menyiapkan profil kerja dengan enkripsi berbasis file diaktifkan - kemudian menonaktifkan Work, pengguna harus membuka kunci layar profil utama untuk sekali - lagi mengakses aplikasi Work. -
      • - -
      • Perangkat dihidupkan ulang saat membuang kunci pola keamanan dan membuka aplikasi - kerja/aplikasi pribadi di multi-jendela. -
      • - -
      • Menyetel DISALLOW_VPN_CONFIG menyebabkan dialog persetujuan muncul di - always-on-vpn yang disetel oleh Device Policy Client. -
      • - -
      • Lalu lintas tidak dikunci hingga VPN terhubung dalam mode always-on-vpn. -
      • -
      - -

      - Penyimpanan eksternal -

      - -
        -
      • Aplikasi mungkin menjadi tidak stabil bila pengguna memindahkannya dari penyimpanan internal - ke penyimpanan eksternal lepas-pasang (ini termasuk kartu SD atau perangkat yang dihubungkan - melalui USB). -
      • -
      - -

      - Perbesaran layar dan multi-APK dalam Google Play -

      - -
        -
      • Pada perangkat yang menjalankan Android N, Google Play Services 9.0.83 salah melaporkan - kepadatan layar saat ini dibandingkan dengan kepadatan layar stabil. Saat perbesaran - layar diaktifkan pada perangkat, hal ini bisa menyebabkan Google Play memilih - versi aplikasi multi-APK yang didesain untuk layar yang lebih kecil. Masalah ini - telah diperbaiki dalam Google Play Services versi berikutnya dan akan disertakan dalam - rilis Developer Preview mendatang. -
      • - -
      • Pada perangkat yang menjalankan Android N, Google Play Services 9.0.83 saat ini melaporkan - dukungan Vulkan, namun bukan versi Vulkan. Hal ini bisa mengakibatkan Google Play memilih - versi aplikasi multi-APK yang didesain untuk mendukung Vulkan yang lebih rendah pada - perangkat dengan dukungan versi yang lebih tinggi. Saat ini, Google Play Store tidak - menerima unggahan aplikasi yang menggunakan penargetan versi Vulkan. Dukungan ini - akan ditambahkan pada Google Play Store di masa mendatang dan diperbaiki dalam - Google Play Services versi berikutnya (akan disertakan dalam rilis Developer Preview - mendatang). Perangkat N yang menggunakan Google Play Services 9.0.83 akan - tetap menerima versi Aplikasi yang menargetkan dukungan Vulkan dasar. -
      • -
      - -

      Pemberitahuan

      - -
        -
      • MessagingStyle tidak menampilkan pemberitahuan dengan pengirim "null" (sendiri). -
      • -
      - -

      Alat Pengembang

      - -
        -
      • - adb mungkin kadang-kadang terputus saat menggunakan debug JDWP. -
      • -
      - - - - - - - - - - - -

      Developer Preview 2

      - -
      -
      -
      -

      - Tanggal: April 2016
      - Build: NPC91K, NPC91O
      - Dukungan emulator: x86 & ARM (32/64-bit)
      - Google Play Services: 8.4
      -

      -
      -
      -
      - -

      Yang baru di DP2

      - -
        -
      • Dukungan platform untuk Vulkan, API rendering 3D baru yang menyediakan - kontrol GPU (Graphics Processor Unit) eksplisit dan overhead yang rendah serta menawarkan - peningkatan kinerja untuk aplikasi draw-call yang berat. Untuk detailnya, lihat - dokumentasi. -
      • - -
      • Emoji orang yang baru dengan dukungan untuk warna kulit, dan glyph Unicode 9 baru. - Warna kulit dan emoji baru tidak akan muncul hingga keyboard membangun dukungan untuknya - di palet. Aplikasi tidak perlu melakukan tindakan apa pun untuk memanfaatkan - emoji baru ini, kecuali jika aplikasi menggunakan font nonsistem. Pengembang - IME perlu menyertakan dukungan untuk emoji baru. -
      • - -
      • - Launcher - Shortcuts API: Aplikasi bisa menggunakan ShortcutManager untuk mengirim - pintasan ke titik awal dalam aplikasi itu sendiri ke peluncur. -
      • - -
      • - Multi-Jendela: - Anda kini bisa menetapkan tinggi minimum dan lebar minimum secara terpisah untuk suatu - aktivitas. Selain itu, beberapa nama API sedikit berubah. -
      • -
      - -

      Perbaikan untuk masalah yang dilaporkan oleh pengembang

      - -

      - Banyak masalah yang dilaporkan oleh pengembang telah diperbaiki, termasuk: -

      - -
        -
      • Tidak bisa menghubungkan ke SSID tersembunyi atau Wi-Fi yang tidak disiarkan. (bug 203116) -
      • - -
      • Keadaan mikrofon nonaktif terjadi selama aktivitas. (bug 205922) -
      • - -
      • Mengubah fokus multi-jendela akan menghentikan YouTube untuk sementara. (bug 203424) -
      • - -
      • Balasan Langsung mungkin menutup aktivitas yang telah dibuka. (bug 204411) -
      • - -
      • Berbagai perbaikan stabilitas. -
      • -
      - -

      Saran umum

      - -

      - Rilis Developer Preview ini adalah untuk pengembang aplikasi saja - dan didesain untuk digunakan dalam pengujian kompatibilitas serta pengembangan awal saja. - Harap perhatikan catatan umum tentang rilis ini: -

      - -
        - -
      • Komponen alat pengembangan dan pustaka dukungan telah diperbarui - untuk rilis DP2. Pastikan memperbarui lingkungan pengembangan pratinjau Anda - sebelum mengembangkan untuk DP2. Untuk petunjuk mengenai persiapan lingkungan - pengembangan Anda, lihat - Menyiapkan Pratinjau. -
      • - -
      • Rilis ini memiliki berbagai masalah stabilitas dan kinerja pada semua perangkat - yang membuatnya tidak cocok untuk penggunaan sehari-hari pada ponsel atau tablet, - terutama untuk selain pengembang. -
      • - -
      • Daya tahan dan kinerja baterai belum dioptimalkan pada rilis - ini: - -
          -
        • Kinerja sistem dan aplikasi diketahui lambat/ - melempem pada waktu-waktu tertentu, dan perangkat kadang-kadang tidak responsif. Masalah-masalah - ini bisa menjadi lebih akut pada penggunaan yang lama. -
        • - -
        • Daya tahan baterai mungkin melemah dalam rilis ini untuk kasus penggunaan layar hidup dan - layar mati. -
        • -
        -
      • - -
      • Beberapa aplikasi mungkin tidak berfungsi dengan normal pada Developer Preview - 2. Termasuk aplikasi Google serta aplikasi lainnya. -
      • - -
      • Build awal ini bukan Compatibility Test Suite (CTS) - yang disetujui. Aplikasi yang bergantung pada build yang disetujui CTS tidak akan berfungsi - (Android Pay misalnya). -
      • - -
      • Rilis pratinjau ini mendukung perangkat berikut: Nexus 5X, Nexus 6, - Nexus 6P, Nexus 9, dan Pixel C, serta General Mobile 4G - (Android One). Dukungan untuk Nexus Player segera hadir. -
      • - - -
      • TestDPC telah - diperbarui untuk menangani perubahan API antara DP1 dan DP2. -
      • -
      - -

      Masalah yang Diketahui

      - -

      Kinerja dan baterai

      - -
        -
      • Kinerja sistem dan aplikasi diketahui lambat/ - melempem pada waktu-waktu tertentu, dan perangkat kadang-kadang tidak responsif. Masalah-masalah - ini bisa menjadi lebih akut pada penggunaan yang lama. -
      • -
      - -

      Akun Google

      - -
        -
      • Dalam beberapa situasi, bisa jadi ada masalah dengan - AccountManagerService yang mencegah masuk ke akun Google -
      • -
      - -

      Pemutakhiran sistem

      - -
        -
      • Perangkat mungkin langsung dihidupkan ulang setelah memperbarui ke DP2. -
      • -
      - -

      Aksesibilitas

      - -
        -
      • Ada masalah dalam mendengarkan keluaran teks-ke-suara (TTS) bila pitch disetel - mendekati level maksimum. -
      • -
      - -

      Bluetooth

      - -
        -
      • Karakteristik Bluetooth Low Energy (LE) GATT menggunakan tipe tulisan - yang salah dan tidak akan dikirim ke perangkat jauh. Karena itu, misalnya, beberapa perangkat - kebugaran tidak akan berfungsi. -
      • -
      - -

      Wizard persiapan

      - -
        -
      • Opsi untuk memulihkan data pada perangkat baru (atau perangkat yang baru disetel ulang) dari - "Your Google Account" tidak dapat digunakan dari wizard persiapan. Anda harus memulihkan - data dari perangkat yang ada dengan memilih "another Android device" dalam - wizard persiapan, atau siapkan sebagai perangkat baru. -
      • -
      - -

      Buka kunci OEM

      - -
        -
      • Pada beberapa perangkat, Enable OEM unlock dalam "Developer Options", berwarna abu-abu - saat menjalankan DP2.
        - Solusi: Ikuti - Android Beta Program (jika Anda belum mengikuti) dengan mengunjungi - www.google.com/android/beta. Kemudian, keluar dan terima - OTA turunkan versi. Keluar dari program akan menyebabkan perangkat turun versi ke Android 6.0. Anda - seharusnya sekarang bisa memilih Enable OEM unlock dalam - "Developer Options". Data pribadi akan dihapus bila Anda turunkan versi - perangkat; akan tetapi, membuka kunci bootloader akan menghapus data ini. -
      • -
      - -

      Android for Work

      - -
        -
      • Work Security Challenge -
          -
        • Setelah migrasi ke N, atau setelah pengguna membuat profil kerja, profil - kerja tidak bisa membuat kunci-kunci dalam keystore hingga pengguna mengubah pola, - PIN, atau sandi mereka, atau menyiapkan Work Challenge. -
        • - -
        • Dalam mode Direct Boot, menerapkan batasan kode sandi pada perangkat - menyebabkan profil kerja tidak terkunci, meskipun perangkat terkunci. - Hal ini membuat profil kerja bisa diakses meskipun seharusnya dilindungi - oleh layar kunci perangkat. -
        • -
        -
      • - -
      • Always-On VPN -
          -
        • Jika mode Always-On VPN diaktifkan, namun VPN tidak tersedia, aplikasi - akan menghubungkan melalui jaringan biasa. Aplikasi seharusnya offline jika tidak - tersedia koneksi VPN. -
        • - -
        • Bila mode Always-On aktif, koneksi VPN tidak akan dibuat setelah - perangkat dihidupkan ulang ke dalam mode Direct Boot, bahkan setelah pengguna membuka kunci - layar kunci aman. -
        • -
        -
      • - -
      • Paket Ditangguhkan -
          -
        • Admin perangkat bisa menangguhkan paket sistem penting, yang dapat menyebabkan - perilaku yang tidak diharapkan, seperti melakukan panggilan meskipun dialog "Telephone - disabled" sedang ditampilkan. -
        • -
        -
      • - -
      • Lainnya -
          -
        • Aplikasi Settings akan mogok saat dibuka jika {@link - android.os.UserManager#DISALLOW_MOUNT_PHYSICAL_MEDIA} disetel ke true bila - pengguna memasukkan media fisik seperti kartu SD. -
        • - -
        • Proses masuk pertama ke Profil Kerja membutuhkan waktu - beberapa menit. -
        • -
        -
      • -
      - -

      Vulkan

      - -
        -
      • Nexus 5X/6P
      • -
          -
        • Selisih antara angka-angka yang mengikat dan selain nol - sebagai angka pengikat pertama menyebabkan {@code vkCreateGraphicsPipeline()} gagal.
        • -
        • Vulkan menunjukkan perilaku sampling yang salah pada koordinat tekstur yang diproyeksikan.
        • -
        • dalam contoh multithreadCmdBuffer, {@code vkCmdClearColorImage()} mengalami mogok bila - dijalankan dengan driver N-DP2.
        • -
        • Nilai kembalian dari {@code vkGetPhysicalDeviceFormatProperties()} tidak menyetel nilai - untuk {@code VkFormatProperties::linearTilingFeatures}, yang mengambil nilai 0 sebagai - hasil.
        • -
        • Lampiran buffer bingkai titik ambang Vulkan tidak ditangani dengan benar.
        • -
        -
      • Nexus Player
      • -
          -
        • SPIR-V shader mungkin memicu pernyataan driver.
        • -
        • Beberapa konfigurasi pipeline mungkin menyebabkan {@code vkCreateGraphicsPipeline()} - mogok.
        • -
        -
      - -

      Masalah perangkat tertentu

      - -
      -
      - Android One -
      - -
      - Koneksi data gagal bila perangkat dipindah dari slot 1 SIM ke slot 2 SIM. -
      - -
      - Pixel C -
      - -
      - Tidak bisa mengubah opsi "Always On" untuk Voice Search. -
      - -
      - Nexus 6 -
      - -
      - Gambar kamera dalam orientasi potret rusak, kecuali untuk foto - HDR+. -
      - -
      - Nexus Player -
      - -
      - Pemutaran materi HD Netflix mungkin gagal pada Nexus Player. -
      - -
      - Aplikasi yang bergantung pada perubahan resolusi video dinamis mungkin gagal pada - Nexus Player. -
      - -
      - Aplikasi yang menggunakan codec video VP9 mungkin gagal pada Nexus Player. -
      -
      - - - -

      Developer Preview 1

      - -
      -
      -
      -

      - Tanggal: Maret 2016
      - Build: NPC56P, NPC56R, diperbarui: NPC56W, NPC56X
      - Dukungan emulator: x86 & ARM (32/64-bit)
      - Google Play Services: 8.4
      -

      -
      -
      -
      - -

      Saran umum

      - -

      - Rilis Developer Preview ini adalah untuk pengembang aplikasi saja dan didesain untuk - digunakan dalam pengujian kompatibilitas serta pengembangan awal saja. Harap perhatikan - catatan umum tentang rilis ini: -

      -
        -
      • Rilis ini memiliki berbagai masalah stabilitas dan kinerja pada semua perangkat - yang membuatnya tidak cocok untuk penggunaan sehari-hari pada ponsel atau tablet, - terutama untuk selain pengembang. -
      • - -
      • Kinerja sistem dan aplikasi diketahui lambat/ - melempem pada waktu-waktu tertentu, dan perangkat kadang-kadang tidak responsif. Masalah-masalah - ini bisa menjadi lebih akut pada penggunaan yang lama. -
      • - -
      • Daya tahan baterai mungkin melemah dalam rilis ini untuk kasus penggunaan layar hidup dan - layar mati. -
      • - -
      • Beberapa aplikasi mungkin tidak berfungsi dengan normal pada Developer Preview 1. - Termasuk aplikasi Google serta aplikasi lainnya. -
      • - -
      • Build awal ini bukan Compatibility Test Suite (CTS) yang disetujui. Aplikasi - yang bergantung pada build yang disetujui CTS tidak akan berfungsi (Android Pay misalnya). -
      • - -
      • Rilis pratinjau ini mendukung perangkat berikut: Nexus 5X, Nexus 6, - Nexus 6P, Nexus 9, Nexus Player, dan Pixel C, serta General Mobile 4G - (Android One). -
      • -
      - -

      Masalah Platform

      - -

      Kinerja dan baterai

      - -
        -
      • Kinerja sistem dan aplikasi diketahui lambat/ - melempem pada waktu-waktu tertentu, dan perangkat kadang-kadang tidak responsif. Masalah-masalah - ini bisa menjadi lebih akut pada penggunaan yang lama. -
      • - -
      • Daya tahan baterai mungkin melemah dalam rilis ini untuk kasus penggunaan layar hidup dan - layar mati. -
      • -
      -

      Telepon

      - -
        -
      • Aplikasi telepon tidak mendukung Direct Boot. Hal ini nanti akan ditangani dalam - N Developer Preview. -
      • - -
      • Pemutaran pesan suara tidak berfungsi. -
      • -
      - -

      Mikrofon

      - -
        -
      • Sistem mungkin keliru mempertahankan mikrofon dalam keadaan nonaktif di semua aplikasi dan saat menghidupkan ulang. Jika Anda menonaktifkan mikrofon di aplikasi dan kondisi ini terus bertahan, buka aplikasi apa saja yang memiliki kontrol untuk menonaktifkan mikrofon dan aktifkan mikrofon.
      • -
      - -

      UI sistem

      - -
        -
      • Beberapa string baru atau yang dimodifikasi dalam UI sistem tidak diterjemahkan ke semua - bahasa. -
      • - -
      • UI ringkasan masih dalam pengembangan, dan masih mungkin berubah. Misalnya, - kami bermaksud membuang timer yang muncul bila pengguna beralih - aplikasi. -
      • - -
      • Kontrol setelan dan peralihannya mungkin menjadi lambat atau tampak tidak responsif. -
      • - -
      • Desain visual pemberitahuan masih bisa berubah. -
      • - -
      • Dalam aplikasi Gmail, pengarsipan email secara langsung yang disertakan dalam bundel - pemberitahuan tidak berfungsi dengan benar. -
      • -
      - -

      Android for Work

      - -
        -
      • Work Security Challenge -
          -
        • Setelah migrasi ke N, atau setelah pengguna membuat profil kerja, profil - kerja tidak bisa membuat kunci-kunci dalam keystore hingga pengguna mengubah pola, - PIN, atau sandi mereka, atau menyiapkan Work Challenge. -
        • - -
        • Dalam mode Direct Boot, menerapkan batasan kode sandi pada perangkat - menyebabkan profil kerja tidak terkunci, meskipun perangkat terkunci. - Hal ini membuat profil kerja bisa diakses meskipun seharusnya dilindungi - oleh layar kunci perangkat. -
        • - -
        • Bila pengguna memasukkan sandi dan pin yang salah, sistem tidak akan - menampilkan pesan informasi; sistem hanya mengosongkan bidang - masukan. Masalah ini tidak memengaruhi masukan pola atau sidik jari. -
        • - -
        • Pada tablet, latar belakang yang ditampilkan bersama pertanyaan kerja - berukuran kecil dan tidak proporsional. -
        • - -
        • Versi - Google Apps Device Policy yang dibundel bersama N Developer Preview - belum mendukung fitur Pertanyaan Keamanan Profil Kerja. - Pengembang seharusnya menggunakan TestDPC - untuk menguji fitur ini. -
        • -
        -
      • - -
      • Always-On VPN -
          -
        • Jika mode Always-On VPN diaktifkan, namun VPN tidak tersedia, aplikasi - yang tidak dinyatakan sebagai pengecualian pada kebijakan Always On akan menghubungkan melalui - jaringan biasa. Kecuali jika ditetapkan sebagai pengecualian pada kebijakan Always-On VPN, - aplikasi seharusnya offline jika tidak tersedia koneksi VPN. -
            -
          • Bila mode Always On aktif, koneksi VPN tidak akan dibuat - setelah perangkat dihidupkan ulang ke dalam mode Direct Boot, bahkan - setelah pengguna membuka kunci layar kunci aman. -
          • -
          -
        • -
        -
      • - -
      • Kontak yang Ditingkatkan -
          -
        • Perangkat Bluetooth PBAP/MAP tidak menampilkan nomor penelepon untuk kontak - kerja. Rilis Pratinjau berikutnya akan mengatasi masalah ini. -
        • -
        -
      • - -
      • Mode Kerja -
          -
        • Peluncur Google Now tidak menampilkan apakah Mode Kerja aktif atau - nonaktif. Peluncur juga tidak menunjukkan kondisi penangguhan aplikasi. -
        • - -
        • Setelah pengguna menonaktifkan lalu mengaktifkan Mode Kerja, sistem tidak lagi menampilkan - widget aplikasi Profil Kerja, seperti Kalender. -
        • -
        -
      • - -
      • Paket Ditangguhkan -
      • - -
      • Admin perangkat bisa menangguhkan paket sistem penting, yang dapat menyebabkan - perilaku yang tidak diharapkan, seperti melakukan panggilan meskipun dialog Telephone - disabled sedang ditampilkan. -
      • - -
      • Lainnya -
          -
        • Aplikasi Settings akan mogok saat dibuka jika {@link - android.os.UserManager#DISALLOW_MOUNT_PHYSICAL_MEDIA} disetel ke true bila - pengguna memasukkan media fisik seperti kartu SD. -
        • - -
        • Keadaan {@code DPM.setPackagesSuspended} tidak akan bertahan bila - pengguna mencopot pemasangan kemudian memasang kembali aplikasi tersebut. Aplikasi harus tetap - ditangguhkan setelah mencopot pemasangan/pemasangan ulang, atau aplikasi tidak boleh - dicopot pemasangannya -
        • - -
        • Proses masuk pertama ke Profil Kerja membutuhkan waktu - beberapa menit. Hal ini dapat menyebabkan perangkat membutuhkan waktu lebih lama dari biasanya untuk - terlihat di Play EMM API. -
        • - -
        • Pemberitahuan dari aplikasi Profil Kerja tidak tampak bagi listener - pemberitahuan yang terpasang di profil pribadi. Akibatnya, sistem tidak - menampilkan Pemberitahuan seperti yang diharapkan. -
        • - -
        -
      • -
      - -

      Keyboard

      - -
        -
      • Penyandingan Bluetooth antara keyboard dan perangkat Android mungkin menjadi tidak stabil. -
      • -
      - -

      Video

      - -
        -
      • Pemutaran video mungkin mengalami selisih waktu dan menunjukkan interupsi.
      • -
      - -

      Wi-Fi

      - -
        -
      • Wi-Fi telah menjalani beberapa optimalisasi yang mungkin mengubah perilaku kasus patologis - API. Khususnya, aplikasi yang berusaha menghubungkan ke jaringan - tertentu, atau berusaha menghubungkan kembali ke jaringan harus mengulang pengujian. -
      • - -
      • Klien DHCP lawas telah dibuang dari platform. Satu-satunya klien DHCP - yang didukung platform adalah klien DHCP yang diperkenalkan di M. -
      • -
      - -

      Direct Boot

      - -
        -
      • NFC tidak berfungsi hingga pembukaan kunci pertama. -
          -
        • Bila telepon berkemampuan Bluetooth dihidupkan ulang, Bluetooth tidak akan - aktif secara otomatis. Anda harus mengaktifkan kembali Bluetooth secara manual. -
        • - -
        • Dalam beberapa situasi, nada dering default mungkin tidak terdengar untuk - panggilan telepon dan pesan. Perilaku ini telah diperbaiki dalam rilis N Preview berikutnya, - dengan satu pengecualian (dan solusi): -
        • - -
        • Pada perangkat yang bukan baru dikosongkan--perangkat yang telah booting setidaknya - sekali sejak disetel ke mode Direct Boot--nada dering pemberitahuan - default tidak berbunyi. Pengguna bisa mengatasi masalah ini dengan - memilih nada dering dari Settings secara manual. -
        • - -
        • Direct Boot tidak diaktifkan secara default pada perangkat yang menjalankan build N - Developer Preview. Untuk mengaktifkan Direct Boot untuk pengujian dan - pengembangan, masuklah ke Developer Option dan ketuk Convert to File Encryption. - Dalam Developer Preview ini perlu penyetelan ulang pabrik untuk membagi ulang dan - memformat ulang perangkat Anda bagi File-based Encryption. -
        • -
        -
      • -
      - -

      Gambar-dalam-gambar untuk Android TV

      - -
        -
      • Integrasi PIP dalam Recents UI belum final, dan masih bisa - berubah. -
          -
        • Animasi jendela PIP belum halus. Rilis Pratinjau - mendatang akan memperbaiki hal ini. -
        • -
        -
      • - -
      • Rilis Pratinjau mendatang akan memperbaiki - desain visual dan perapian layout PIP. -
      • -
      - -

      Laporan bug

      - -
        -
      • Laporan bug tidak selalu berhasil diselesaikan (seperti solusi, - kadang-kadang masih bisa diakses melalui penyedia dokumen laporan bug - di penyimpanan internal). -
      • -
      - -

      Layar terbagi Multi-jendela

      - -
        -
      • Aplikasi bisa mengalami mogok dan perilaku UI yang tidak diharapkan bila ditempatkan dalam - mode layar terbagi. Ini adalah masalah aplikasi yang harus diperbaiki oleh pengembang - aplikasi. -
      • - -
      • Bila aplikasi menargetkan versi platform Android sebelum N, maka - aplikasi mungkin tidak berfungsi pada layar terbagi dan toast mungkin muncul berkali-kali. -
      • - -
      • Menekan lama tombol Ringkasan saat menggunakan aplikasi dengan orientasi - tetap mungkin menghasilkan perilaku aplikasi yang tidak diharapkan. -
      • - -
      • Aplikasi mungkin berkedip saat mengubah ukurannya. -
      • - -
      • Animasi belum final. -
      • -
      - -

      Metode masukan

      - -
        -
      • Google Keyboard secara tidak diharapkan kembali ke keyboard Google generik - bila menggunakan bahasa sistem, namun Google Keyboard tidak mendukung - bahasa yang dipilih dalam preferensi bahasa sistem. Ia akan kembali - ke American English. -

        - Anda bisa mengatasi masalah ini dengan menambahkan setidaknya satu bahasa yang didukung - Keyboard Google. -

        -
      • -
      - -

      Aksesibilitas

      - -
        -
      • TalkBack menunjukkan masalah pada beberapa fitur termasuk Pemberitahuan, petak - Quick Settings dan tampilan Multi-jendela yang mungkin menyebabkan sistem mogok atau - tidak ada masukan lisan dari TalkBack. Rilis pratinjau mendatang akan - menangani masalah ini. -
      • -
      - -

      Masalah dan Catatan untuk Perangkat Tertentu

      - -

      Nexus Player

      -
        -
      • Pemutaran video, kompatibilitas aplikasi, dan masalah stabilitas telah antisipasi pada - Nexus Player dalam rilis Pratinjau ini. -
      • -
      - -

      Pixel C

      -
        -
      • Mengubah ukuran multi-jendela bisa menyebabkan mogok.
      • -
      - -

      Nexus 9

      -
        -
      • Perangkat Nexus 9 mungkin tidak jalan setelah menerima pembaruan lewat jaringan seluler (OTA) - via Android Beta Program. Untuk memulihkan dari masalah ini, Anda bisa mencoba - pasang citra OTA secara manual. Untuk informasi selengkapnya, lihat - Menerapkan Citra OTA Perangkat. -
      • -
      - diff --git a/docs/html-intl/intl/in/training/articles/direct-boot.jd b/docs/html-intl/intl/in/training/articles/direct-boot.jd new file mode 100644 index 0000000000000000000000000000000000000000..a7e3cf3cad7741efc2ec99ac24d5cce5b2e08168 --- /dev/null +++ b/docs/html-intl/intl/in/training/articles/direct-boot.jd @@ -0,0 +1,181 @@ +page.title=Direct Boot +page.keywords=pratinjau,sdk,direct boot +page.tags=androidn +page.image=images/cards/card-nyc_2x.jpg + +@jd:body + + + +

      Android N berjalan dalam mode Direct Boot yang aman +bila perangkat telah dihidupkan namun pengguna tidak membuka +kunci perangkat. Untuk mendukung hal ini, sistem menyediakan dua lokasi penyimpanan untuk data:

      + +
        +
      • Penyimpanan yang dienkripsi dengan kredensial, yang merupakan lokasi penyimpanan default +dan hanya tersedia setelah pengguna membuka kunci perangkat.
      • +
      • Penyimpanan yang dienkripsi dengan perangkat, yang merupakan lokasi penyimpanan yang tersedia +selama mode Direct Boot dan setelah pengguna membuka kunci perangkat.
      • +
      + +

      Secara default, aplikasi tidak berjalan selama mode Direct Boot. +Jika aplikasi Anda perlu melakukan tindakan selama mode Direct Boot, Anda bisa mendaftarkan +komponen aplikasi yang harus dijalankan selama mode ini. Beberapa kasus penggunaan umum +untuk aplikasi yang perlu dijalankan selama mode Direct Boot antara lain:

      + +
        +
      • Aplikasi yang telah menjadwalkan pemberitahuan, seperti aplikasi +beker.
      • +
      • Aplikasi yang menyediakan pemberitahuan pengguna yang penting, seperti aplikasi SMS.
      • +
      • Aplikasi yang menyediakan layanan aksesibilitas, seperti TalkBack.
      • +
      + +

      Jika aplikasi Anda perlu mengakses data saat dijalankan dalam mode Direct Boot, gunakan +penyimpanan yang dienkripsi dengan perangkat. Penyimpanan yang dienkripsi dengan perangkat berisi data +yang dienkripsi dengan kunci yang hanya tersedia setelah perangkat melakukan +booting yang berhasil diverifikasi.

      + +

      Untuk data yang harus dienkripsi dengan kunci yang dikaitkan dengan kredensial +pengguna, seperti PIN atau kata sandi, gunakan penyimpanan yang dienkripsi dengan kredensial. +Penyimpanan yang dienkripsi dengan kredensial hanya tersedia setelah pengguna berhasil +membuka kunci perangkat, hingga saat pengguna menghidupkan ulang perangkat lagi. Jika +pengguna mengaktifkan layar kunci setelah membuka kunci perangkat, hal ini tidak akan mengunci +penyimpanan yang dienkripsi dengan kredensial.

      + +

      Meminta Akses untuk Berjalan Selama Direct Boot

      + +

      Aplikasi harus mendaftarkan komponennya pada sistem agar +bisa berjalan selama mode Direct Boot atau mengakses +penyimpanan yang dienkripsi dengan perangkat. Aplikasi mendaftar pada sistem dengan menandai komponen sebagai +peka enkripsi. Untuk menandai komponen Anda sebagai peka enkripsi, setel atribut +android:directBootAware ke true dalam manifes Anda.

      + +

      Komponen yang peka enkripsi bisa mendaftar untuk menerima pesan siaran +LOCKED_BOOT_COMPLETED dari +sistem bila perangkat telah dihidupkan ulang. Pada tahap ini +penyimpanan yang dienkripsi dengan perangkat akan tersedia, dan komponen Anda bisa mengeksekusi tugas-tugas yang perlu +dijalankan selama mode Direct Boot, seperti memicu alarm yang terjadwal.

      + +

      Cuplikan kode berikut adalah contoh cara mendaftarkan +{@link android.content.BroadcastReceiver} sebagai peka enkripsi, dan menambahkan sebuah +filter intent untuk LOCKED_BOOT_COMPLETED, dalam manifes aplikasi:

      + +
      +<receiver
      +  android:directBootAware="true" >
      +  ...
      +  <intent-filter>
      +    <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
      +  </intent-filter>
      +</receiver>
      +
      + +

      Setelah pengguna membuka kunci perangkat, semua komponen bisa mengakses +penyimpanan yang dienkripsi dengan perangkat serta penyimpanan yang dienkripsi dengan kredensial.

      + +

      Mengakses Penyimpanan yang Dienkripsi dengan Perangkat

      + +

      Untuk mengakses penyimpanan yang dienkripsi dengan perangkat, buat instance +{@link android.content.Context} kedua dengan memanggil +Context.createDeviceProtectedStorageContext(). Semua panggilan +API penyimpanan yang dibuat menggunakan konteks ini mengakses penyimpanan yang dienkripsi dengan perangkat. Contoh +berikut mengakses penyimpanan yang dienkripsi dengan perangkat dan membuka file data aplikasi +yang ada:

      + +
      +Context directBootContext = appContext.createDeviceProtectedStorageContext();
      +// Access appDataFilename that lives in device encrypted storage
      +FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
      +// Use inStream to read content...
      +
      + +

      Gunakan penyimpanan yang dienkripsi dengan perangkat hanya untuk +informasi yang harus bisa diakses selama mode Direct Boot. +Jangan gunakan penyimpanan yang dienkripsi dengan perangkat sebagai penyimpanan terenkripsi serba guna. +Untuk informasi pengguna yang bersifat pribadi, atau data terenkripsi yang tidak diperlukan selama +mode Direct Boot, gunakan penyimpanan yang dienkripsi dengan kredensial.

      + +

      Mendapatkan Pemberitahuan saat Pengguna Membuka Kunci

      + +

      Setelah pengguna membuka kunci perangkat setelah restart, aplikasi Anda bisa beralih untuk +mengakses penyimpanan yang dienkripsi dengan kredensial dan menggunakan layanan sistem biasa yang +bergantung pada kredensial pengguna.

      + +

      Agar diberi tahu bila pengguna membuka kunci perangkat setelah boot ulang, +daftarkan {@link android.content.BroadcastReceiver} dari komponen yang berjalan +untuk mendengarkan pesan ACTION_USER_UNLOCKED. Atau, Anda bisa +menerima pesan {@link android.content.Intent#ACTION_BOOT_COMPLETED +ACTION_BOOT_COMPLETED} yang ada, yang sekarang menunjukkan bahwa perangkat telah dihidupkan dan +pengguna telah membuka kunci perangkat.

      + +

      Anda bisa langsung kueri apakah pengguna telah membuka kunci perangkat dengan memanggil +UserManager.isUserUnlocked().

      + +

      Migrasi Data yang Ada

      + +

      Jika pengguna memperbarui perangkat mereka untuk menggunakan mode Direct Boot, +data Anda yang ada mungkin perlu dipindahkan ke penyimpanan yang dienkripsi dengan perangkat. Gunakan +Context.moveSharedPreferencesFrom() dan +Context.moveDatabaseFrom() untuk memindahkan data preferensi dan +basis data antara penyimpanan yang dienkripsi dengan kredensial dan penyimpanan yang dienkripsi dengan perangkat.

      + +

      Pertimbangkan dengan baik saat memutuskan data apa yang akan dipindahkan dari +penyimpanan yang dienkripsi dengan kredensial ke penyimpanan yang dienkripsi dengan perangkat. Anda sebaiknya tidak memindahkan +informasi pengguna yang bersifat rahasia, seperti kata sandi atau token otorisasi, ke +penyimpanan yang dienkripsi dengan perangkat. Dalam beberapa skenario, Anda mungkin perlu mengelola +set data terpisah pada dua tempat penyimpanan yang dienkripsi.

      + +

      Menguji Aplikasi Peka Enkripsi Anda

      + +

      Uji aplikasi peka enkripsi Anda menggunakan mode Direct Boot baru. Ada +dua cara untuk mengaktifkan Direct Boot.

      + +

      Perhatian: Mengaktifkan Direct Boot +akan menghapus semua data pengguna pada perangkat.

      + +

      Pada perangkat yang didukung dengan Android N terpasang, aktifkan +Direct Boot dengan melakukan salah satu hal berikut:

      + +
        +
      • Pada perangkat, aktifkan Developer options jika Anda belum melakukannya dengan +masuk ke Settings > About phone, dan menyentuh Build number +tujuh kali. Setelah layar Developer options terbuka, masuk ke +Settings > Developer options dan pilih +Convert to file encryption.
      • +
      • Gunakan perintah shell adb berikut untuk mengaktifkan mode Direct Boot: +
        +$ adb reboot-bootloader
        +$ fastboot --wipe-and-use-fbe
        +
        +
      • +
      + +

      Mode emulasi Direct Boot juga tersedia, jika Anda perlu mengganti +mode pada perangkat pengujian. Mode emulasi sebaiknya hanya digunakan selama +pengembangan dan bisa menyebabkan kehilangan data. Untuk mengaktifkan mode emulasi Direct Boot, +setel pola kunci pada perangkat, pilih "No thanks" jika ditanya mengenai +layar start-up aman saat menetapkan pola kunci, kemudian gunakan +perintah shell adb berikut:

      + +
      +$ adb shell sm set-emulate-fbe true
      +
      + +

      Untuk menonaktifkan mode emulasi Direct Boot, gunakan perintah berikut:

      + +
      +$ adb shell sm set-emulate-fbe false
      +
      + +

      Menggunakan perintah ini akan menyebabkan perangkat melakukan boot ulang.

      diff --git a/docs/html-intl/intl/in/training/articles/scoped-directory-access.jd b/docs/html-intl/intl/in/training/articles/scoped-directory-access.jd new file mode 100644 index 0000000000000000000000000000000000000000..30aed6fbb2a46e4397eaea6a2559adaff2ee90be --- /dev/null +++ b/docs/html-intl/intl/in/training/articles/scoped-directory-access.jd @@ -0,0 +1,148 @@ +page.title=Scoped Directory Access +page.keywords=pratinjau,sdk,scoped directory access +page.tags=androidn + +@jd:body + + + +

      Aplikasi seperti aplikasi foto biasanya hanya memerlukan akses ke direktori tertentu dalam +penyimpanan eksternal, seperti direktori Pictures. Pendekatan +yang ada dalam mengakses penyimpanan eksternal tidak didesain untuk memberi kemudahan +akses direktori tertarget untuk tipe aplikasi ini. Misalnya:

      + +
        +
      • Meminta {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} +atau {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} dalam manifes Anda +akan memungkinkan akses ke semua direktori publik pada penyimpanan eksternal, yang mungkin +lebih banyak akses dari yang dibutuhkan aplikasi Anda.
      • +
      • Menggunakan +Storage +Access Framework biasanya membuat pengguna Anda memilih direktori +melalui UI sistem, yang tidak diperlukan jika aplikasi Anda selalu mengakses +direktori eksternal yang sama.
      • +
      + +

      Android N menyediakan API baru yang disederhanakan untuk mengakses +direktori penyimpanan eksternal umum.

      + +

      Mengakses Direktori Penyimpanan Eksternal

      + +

      Gunakan kelas StorageManager untuk mendapatkan instance +StorageVolume yang tepat. Kemudian, buat intent dengan memanggil metode +StorageVolume.createAccessIntent() dari instance itu. +Gunakan intent ini untuk mengakses direktori penyimpanan eksternal. Untuk mendapatkan daftar +semua volume yang tersedia, termasuk volume media lepas-pasang, gunakan +StorageManager.getVolumesList().

      + +

      Jika Anda memiliki informasi tentang file spesifik, gunakan +StorageManager.getStorageVolume(File) untuk mendapatkan +StorageVolume yang berisi file tersebut. Panggil +createAccessIntent() pada StorageVolume ini untuk mengakses +direktori penyimpanan eksternal untuk file tersebut.

      + +

      +Di volume kedua, seperti kartu SD eksternal, teruskan null saat memanggil +StorageVolume.createAccessIntent() untuk meminta akses ke seluruh +volume, sebagai ganti direktori spesifik. +StorageVolume.createAccessIntent() akan mengembalikan null jika Anda meneruskan +null ke volume utama, atau jika Anda meneruskan nama direktori yang tidak valid. +

      + +

      Cuplikan kode berikut adalah contoh cara membuka direktori +Pictures dalam penyimpanan bersama utama:

      + +
      +StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
      +StorageVolume volume = sm.getPrimaryVolume();
      +Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
      +startActivityForResult(intent, request_code);
      +
      + +

      Sistem ini mencoba untuk memberikan akses ke direktori eksternal, dan jika +diperlukan mengonfirmasi akses dengan pengguna menggunakan UI yang disederhanakan:

      + + +

      Gambar 1. Sebuah aplikasi yang meminta +akses ke direktori Pictures.

      + +

      Jika pengguna memberi akses, sistem akan memanggil penggantian +onActivityResult() Anda dengan kode hasil +Activity.RESULT_OK, dan data intent yang berisi URI. Gunakan +URI yang disediakan untuk mengakses informasi direktori, serupa dengan menggunakan URI +yang dikembalikan oleh +Storage +Access Framework.

      + +

      Jika pengguna tidak memberi akses, sistem akan memanggil penggantian +onActivityResult() Anda dengan kode hasil +Activity.RESULT_CANCELED, dan data intent nol.

      + +

      Catatan: Mendapatkan akses ke direktori eksternal tertentu +juga akan memperoleh akses ke subdirektori dalam direktori tersebut.

      + +

      Mengakses Direktori pada Media Lepas-Pasang

      + +

      Untuk menggunakan Scoped Directory Access guna mengakses direktori pada media lepas-pasang, +pertama tambahkan {@link android.content.BroadcastReceiver} yang akan mendengarkan pemberitahuan +{@link android.os.Environment#MEDIA_MOUNTED}, misalnya:

      + +
      +<receiver
      +    android:name=".MediaMountedReceiver"
      +    android:enabled="true"
      +    android:exported="true" >
      +    <intent-filter>
      +        <action android:name="android.intent.action.MEDIA_MOUNTED" />
      +        <data android:scheme="file" />
      +    </intent-filter>
      +</receiver>
      +
      + +

      Bila pengguna memasang media lepas-pasang, seperti kartu SD, sistem akan mengirimkan pemberitahuan +{@link android.os.Environment#MEDIA_MOUNTED}. Pemberitahuan ini +memberikan sebuah objek StorageVolume dalam data intent yang bisa +Anda gunakan untuk mengakses direktori pada media lepas-pasang. Contoh berikut +mengakses direktori Pictures pada media lepas-pasang:

      + +
      +// BroadcastReceiver has already cached the MEDIA_MOUNTED
      +// notification Intent in mediaMountedIntent
      +StorageVolume volume = (StorageVolume)
      +    mediaMountedIntent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
      +volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
      +startActivityForResult(intent, request_code);
      +
      + +

      Praktik Terbaik

      + +

      Bila memungkinkan, pertahankan URI akses direktori eksternal sehingga Anda tidak perlu +berulang kali meminta akses ke pengguna. Setelah pengguna memberikan akses, panggil +getContentResolver().takePersistableUriPermssion() bersama +URI akses direktori. Sistem akan mempertahankan URI dan permintaan +akses berikutnya akan mengembalikan RESULT_OK dan tidak menampilkan UI konfirmasi kepada +pengguna.

      + +

      Jika pengguna menolak akses ke direktori eksternal, jangan langsung +meminta akses lagi. Berulang kali meminta akses akan menghasilkan pengalaman +pengguna yang buruk. Jika permintaan ditolak oleh pengguna, dan aplikasi meminta akses +lagi, UI akan menampilkan kotak centang Don't ask again:

      + + +

      Gambar 1. Sebuah aplikasi membuat +permintaan kedua untuk mengakses media lepas-pasang.

      + +

      Jika pengguna memilih Don't ask again dan menolak permintaan, +semua permintaan berikutnya untuk direktori yang diberikan dari aplikasi +Anda secara otomatis akan ditolak, dan tidak ada UI permintaan yang akan ditampilkan ke pengguna.

      \ No newline at end of file diff --git a/docs/html-intl/intl/in/training/articles/security-config.jd b/docs/html-intl/intl/in/training/articles/security-config.jd new file mode 100644 index 0000000000000000000000000000000000000000..e13429dec04e44b3263d2b70b9f3bf01a82c32b6 --- /dev/null +++ b/docs/html-intl/intl/in/training/articles/security-config.jd @@ -0,0 +1,747 @@ +page.title=Konfigurasi Keamanan Jaringan +page.keywords=androidn,keamanan,jaringan +page.image=images/cards/card-nyc_2x.jpg + +@jd:body + + + + +

      + Android N menyertakan fitur + Network Security Configuration yang memungkinkan aplikasi menyesuaikan setelan keamanan jaringan mereka dalam + file konfigurasi deklaratif yang aman tanpa memodifikasi kode aplikasi. Setelan ini bisa + dikonfigurasi untuk domain dan aplikasi tertentu. Kemampuan + utama fitur ini adalah sebagai berikut: +

      + +
        +
      • + Trust-anchor khusus: Menyesuaikan Certificate Authorities (CA) mana + yang dipercaya untuk koneksi aman aplikasi. Misalnya, + mempercayai sertifikat tertentu yang ditandatangani sendiri atau membatasi + set CA umum yang dipercaya aplikasi. +
      • + +
      • + Penggantian hanya-debug: Men-debug secara aman koneksi aman dalam aplikasi + tanpa menambahkan risiko pada basis yang telah dipasang. +
      • + +
      • + Berhenti dari lalu lintas cleartext: Melindungi aplikasi dari + penggunaan lalu lintas cleartext secara tidak sengaja. +
      • + +
      • + Penyematan sertifikat: Membatasi koneksi aman aplikasi ke + sertifikat tertentu. +
      • +
      + + +

      Menambahkan File Konfigurasi Keamanan

      + +

      + Fitur Network Security Configuration menggunakan file XML tempat Anda menetapkan + setelan untuk aplikasi. Anda harus menyertakan sebuah entri dalam manifes aplikasi + untuk menunjuk ke file ini. Kutipan kode berikut dari sebuah manifes + yang memperagakan cara membuat entri ini: +

      + +
      +<?xml version="1.0" encoding="utf-8"?>
      +<manifest ... >
      +  <application ... >
      +    <meta-data android:name="android.security.net.config"
      +               android:resource="@xml/network_security_config" />
      +    ...
      +  </application>
      +</manifest>
      +
      + +

      Menyesuaikan CA Tepercaya

      + +

      + Aplikasi mungkin perlu mempercayai set CA khusus sebagai ganti default + platform. Alasannya yang paling umum adalah: +

      + +
        +
      • Menghubungkan ke host dengan otoritas sertifikat khusus (ditandatangani sendiri, + dikeluarkan oleh CA internal, dll). +
      • + +
      • Membatasi set CA hanya untuk CA yang Anda percaya sebagai ganti setiap CA + yang sudah terpasang. +
      • + +
      • Mempercayai CA tambahan yang tidak disertakan dalam sistem. +
      • +
      + +

      + Secara default koneksi (mis. TLS, HTTPS) aman dari semua aplikasi mempercayai + CA yang telah dipasang oleh sistem, dan aplikasi yang menargetkan API level 23 + (Android M) ke bawah, juga mempercayai penyimpanan CA yang ditambahkan pengguna secara default. Aplikasi + bisa menyesuaikan koneksinya menggunakan {@code base-config} (untuk + penyesuaian lebar-aplikasi) atau {@code domain-config} (untuk penyesuaian + per-domain). +

      + + +

      Mengonfigurasi CA Khusus

      + +

      + Anggaplah Anda ingin menghubungkan ke host Anda yang menggunakan sertifikat + SSL yang ditandatangani sendiri atau ke host yang sertifikat SSL-nya dikeluarkan oleh CA non-publik + yang Anda percaya, seperti CA internal perusahaan Anda. +

      + +

      + res/xml/network_security_config.xml: +

      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <domain-config>
      +        <domain includeSubdomains="true">example.com</domain>
      +        <trust-anchors>
      +            <certificates src="@raw/my_ca"/>
      +        </trust-anchors>
      +    </domain-config>
      +</network-security-config>
      +
      +

      + +

      + Menambahkan sertifikat CA yang ditandatangani sendiri atau sertifikat CA non-publik, dalam format PEM atau DER, ke + {@code res/raw/my_ca}. +

      + + +

      Membatasi Set CA Tepercaya

      + +

      + Aplikasi yang tidak ingin mempercayai semua CA yang dipercaya oleh sistem + sebagai gantinya bisa menetapkan set CA sendiri yang telah dikurangi untuk dipercaya. Ini akan melindungi + aplikasi dari sertifikat palsu yang dikeluarkan oleh selain CA. +

      + +

      + Konfigurasi untuk membatasi set CA tepercaya mirip dengan mempercayai CA khusus untuk domain tertentu selain + beberapa CA disediakan dalam sumber daya. +

      + +

      +res/xml/network_security_config.xml: +

      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <domain-config>
      +        <domain includeSubdomains="true">secure.example.com</domain>
      +        <domain includeSubdomains="true">cdn.example.com</domain>
      +        <trust-anchors>
      +            <certificates src="@raw/trusted_roots"/>
      +        </trust-anchors>
      +    </domain-config>
      +</network-security-config>
      +
      +

      + +

      + Menambahkan CA tepercaya, dalam format PEM atau DER, ke {@code res/raw/trusted_roots}. + Perhatikan, jika menggunakan format PEM, file hanya boleh berisi data PEM + dan tidak ada teks tambahan. Anda juga bisa menyediakan beberapa elemen + <certificates> +sebagai ganti satu elemen. +

      + + +

      + Mempercayai CA Tambahan +

      + +

      + Sebuah aplikasi mungkin perlu mempercayai CA tambahan yang tidak dipercaya oleh sistem, + hal ini bisa disebabkan karena sistem belum menyertakan CA atau CA tidak + memenuhi persyaratan untuk memasukkan ke dalam sistem Android. Aplikasi + bisa melakukannya dengan menetapkan beberapa sumber sertifikat untuk + konfigurasi. +

      +

      +res/xml/network_security_config.xml: +

      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <base-config>
      +        <trust-anchors>
      +            <certificates src="@raw/extracas"/>
      +            <certificates src="system"/>
      +        </trust-anchors>
      +    </base-config>
      +</network-security-config>
      +
      +

      + + +

      Mengonfigurasi CA untuk Debug

      + +

      + Saat men-debug aplikasi yang terhubung melalui HTTPS, Anda mungkin perlu + menghubungkan ke server pengembangan lokal, yang tidak memiliki sertifikat + SSL untuk server produksi Anda. Untuk mendukungnya tanpa + memodifikasi kode aplikasi, Anda bisa menetapkan CA hanya-debug + yang hanya dipercaya bila +android:debuggable + adalah {@code true} dengan menggunakan {@code debug-overrides}. Biasanya IDE dan alat + build menyetel flag ini secara otomatis untuk build non-rilis. +

      + +

      + Ini lebih aman daripada kode kondisional biasa karena, sebagai tindakan + pencegahan keamanan, toko aplikasi tidak menerima aplikasi yang ditandai + bisa-di-debug. +

      + +

      +res/xml/network_security_config.xml: +

      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <debug-overrides>
      +        <trust-anchors>
      +            <certificates src="@raw/debug_cas"/>
      +        </trust-anchors>
      +    </debug-overrides>
      +</network-security-config>
      +
      +

      + + +

      Berhenti dari Lalu Lintas Cleartext

      + +

      + Aplikasi bermaksud menyambung ke tujuan hanya menggunakan koneksi + aman dapat memilih keluar dari dukungan cleartext (menggunakan protokol + HTTP yang tidak terenkripsi sebagai ganti HTTPS) ke tujuan tersebut. Opsi ini akan membantu mencegah + regresi tidak disengaja dalam aplikasi karena perubahan dalam URL yang disediakan oleh sumber-sumber + eksternal seperti server backend. + Lihat {@link android.security.NetworkSecurityPolicy#isCleartextTrafficPermitted + NetworkSecurityPolicy.isCleartextTrafficPermitted()} untuk detail selengkapnya. +

      + +

      + Misalnya, aplikasi mungkin ingin memastikan semua koneksi ke {@code + secure.example.com} selalu dilakukan melalui HTTPS untuk melindungi lalu lintas sensitif + dari jaringan yang berbahaya. +

      + +

      +res/xml/network_security_config.xml: +

      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <domain-config usesCleartextTraffic="false">
      +        <domain includeSubdomains="true">secure.example.com</domain>
      +    </domain-config>
      +</network-security-config>
      +
      +

      + + +

      Menyematkan Sertifikat

      + +

      + Biasanya aplikasi mempercayai semua CA yang telah terpasang. Jika salah satu dari CA ini + mengeluarkan sertifikat palsu, aplikasi akan berisiko terkena serangan + MiTM. Beberapa aplikasi memilih untuk membatasi set sertifikat yang mereka terima + baik dengan membatasi set CA yang mereka percaya atau dengan menyematkan sertifikat. +

      + +

      + Penyematan sertifikat dilakukan dengan memberikan seperangkat sertifikat dengan hash + kunci publik (SubjectPublicKeyInfo pada sertifikat X.509). Rantai + sertifikat nanti hanya berlaku jika rantai sertifikat berisi setidaknya salah satu + dari kunci publik yang disematkan. +

      + +

      + Perhatikan, saat menggunakan penyematan sertifikat, Anda harus selalu menyertakan kunci + cadangan sehingga jika Anda terpaksa beralih ke kunci baru, atau mengubah CA (saat + menyematkan ke sertifikat CA atau perantara CA tersebut), konektivitas + aplikasi Anda tidak terpengaruh. Jika tidak, Anda harus mendorong + pembaruan ke aplikasi tersebut untuk memulihkan konektivitas. +

      + +

      + Selain itu dimungkinkan juga menyetel waktu habis masa berlaku untuk pin setelah + penyematan tidak dilakukan. Hal ini membantu mencegah masalah konektivitas dalam + aplikasi yang belum diperbarui. Akan tetapi, menyetel waktu kedaluwarsa + pada pin mungkin akan membuat penyematan bisa diabaikan. +

      + +

      +res/xml/network_security_config.xml: +

      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <domain-config>
      +        <domain includeSubdomains="true">example.com</domain>
      +        <pin-set expiration="2018-01-01">
      +            <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
      +            <!-- backup pin -->
      +            <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPDcf3UKgO/04cDM1oE=</pin>
      +        </pin-set>
      +    </domain-config>
      +</network-security-config>
      +
      +

      + + +

      Perilaku Pewarisan Konfigurasi

      + +

      + Nilai yang tidak disetel dalam konfigurasi tertentu akan diwariskan. Perilaku ini memungkinkan konfigurasi + yang lebih kompleks sambil menjaga file konfigurasi tetap terbaca. +

      + +

      + Jika nilai tidak disetel dalam entri tertentu maka nilai dari entri berikutnya yang lebih + umum akan digunakan. Nilai yang tidak disetel dalam {@code domain-config} akan + diambil dari {@code domain-config} induk, jika tersarang, atau dari {@code + base-config} jika tidak. Nilai yang tidak disetel dalam {@code base-config} akan menggunakan + nilai default platform. +

      + +

      + Misalnya pertimbangkan, bila semua koneksi ke subdomain {@code + example.com} harus menggunakan set CA khusus. Selain itu, lalu lintas cleartext ke + domain ini diizinkan kecuali saat menghubungkan ke {@code + secure.example.com}. Dengan menyarangkan konfigurasi untuk {@code + secure.example.com} dalam konfigurasi untuk {@code example.com}, + {@code trust-anchors} tidak perlu digandakan. +

      + +

      +res/xml/network_security_config.xml: +

      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <domain-config>
      +        <domain includeSubdomains="true">example.com</domain>
      +        <trust-anchors>
      +            <certificates src="@raw/my_ca"/>
      +        </trust-anchors>
      +        <domain-config cleartextTrafficPermitted="false">
      +            <domain includeSubdomains="true">secure.example.com</domain>
      +        </domain-config>
      +    </domain-config>
      +</network-security-config>
      +
      +

      + + +

      Format File Konfigurasi

      + +

      + Fitur Network Security Configuration menggunakan format file XML. + Struktur keseluruhan file ditampilkan dalam contoh kode berikut: +

      + +
      +<?xml version="1.0" encoding="utf-8"?>
      +<network-security-config>
      +    <base-config>
      +        <trust-anchors>
      +            <certificates src="..."/>
      +            ...
      +        </trust-anchors>
      +    </base-config>
      +
      +    <domain-config>
      +        <domain>android.com</domain>
      +        ...
      +        <trust-anchors>
      +            <certificates src="..."/>
      +            ...
      +        </trust-anchors>
      +        <pin-set>
      +            <pin digest="...">...</pin>
      +            ...
      +        </pin-set>
      +    </domain-config>
      +    ...
      +    <debug-overrides>
      +        <trust-anchors>
      +            <certificates src="..."/>
      +            ...
      +        </trust-anchors>
      +    </debug-overrides>
      +</network-security-config>
      +
      + +

      + Bagian berikut menjelaskan sintaks dan detail lainnya dari format + file. +

      + +

      + <network-security-config> +

      + +
      +
      + bisa berisi: +
      + +
      + 0 atau 1 <base-config>
      + Sejumlah <domain-config>
      + 0 atau 1 <debug-overrides> +
      +
      + +

      + <base-config> +

      + +
      +
      + sintaks: +
      +
      + +
      +<base-config usesCleartextTraffic=["true" | "false"]>
      +    ...
      +</base-config>
      +
      +
      +
      + bisa berisi: +
      + +
      + <trust-anchors> +
      + +
      + keterangan: +
      + +
      + Konfigurasi default yang digunakan oleh semua koneksi yang tujuannya tidak + tercakup oleh domain-config. + +

      + Nilai yang tidak disetel akan menggunakan nilai default platform. Konfigurasi + default untuk aplikasi yang menargetkan API level 24 ke atas: +

      + +
      +<base-config usesCleartextTraffic="true">
      +    <trust-anchors>
      +        <certificates src="system" />
      +    </trust-anchors>
      +</base-config>
      +
      +Konfigurasi default untuk aplikasi yang menargetkan API level 23 ke bawah: +
      +<base-config usesCleartextTraffic="true">
      +    <trust-anchors>
      +        <certificates src="system" />
      +        <certificates src="user" />
      +    </trust-anchors>
      +</base-config>
      +
      + +
      +
      + +

      <domain-config>

      +
      +
      sintaks:
      +
      +
      <domain-config usesCleartextTraffic=["true" | "false"]>
      +    ...
      +</domain-config>
      +
      + +
      Bisa Berisi:
      + +
      +1 atau beberapa <domain> +
      0 atau 1 <trust-anchors> +
      0 atau 1 <pin-set> +
      Sejumlah <domain-config> tersarang
      + +
      Keterangan
      +
      Konfigurasi yang digunakan untuk koneksi ke tujuan tertentu seperti didefinisikan oleh elemen {@code domain}. + +

      Perhatikan, jika beberapa elemen {@code domain-config} mencakup suatu tujuan, konfigurasi dengan aturan domain paling spesifik (terpanjang) yang cocok +akan digunakan.

      +
      + + +

      <domain>

      + +
      +
      + sintaks: +
      + +
      +
      +<domain includeSubdomains=["true" | "false"]>example.com</domain>
      +
      +
      + +
      + Atribut: +
      + +
      +
      +
      + {@code includeSubdomains} +
      + +
      + Jika {@code "true"} maka aturan domain ini akan dicocokkan dengan domain dan semua + subdomain, termasuk subdomain dari subdomain, jika tidak peraturan hanya + diterapkan pada kecocokan yang persis tepat. +
      +
      +
      + +
      + Keterangan: +
      +
      + +

      <debug-overrides>

      + +
      +
      + sintaks: +
      + +
      +
      +<debug-overrides>
      +    ...
      +</debug-overrides>
      +
      +
      + +
      + Bisa Berisi: +
      + +
      + 0 atau 1 <trust-anchors> +
      + +
      + Keterangan: +
      + +
      + Pengesampingan yang akan diterapkan bila android:debuggable + adalah {@code "true"} yang biasanya terjadi untuk build non-rilis + yang dihasilkan oleh alat IDE dan build. Trust-anchor yang ditetapkan dalam {@code + debug-overrides} akan ditambahkan ke semua konfigurasi lainnya dan penyematan + sertifikat tidak dilakukan bila rantai sertifikat server menggunakan satu dari + trust-anchor hanya-debug ini. Jika android:debuggable + adalah {@code "false"} maka bagian ini akan diabaikan sepenuhnya. +
      +
      + +

      <trust-anchors>

      +
      +
      + sintaks: +
      + +
      +
      +<trust-anchors>
      +...
      +</trust-anchors>
      +
      +
      + +
      + Bisa Berisi: +
      + +
      + Sejumlah <certificates> +
      + +
      + Keterangan: +
      + +
      + Set trust-anchor untuk koneksi aman. +
      +
      + + +

      <certificates>

      +
      +
      sintaks:
      +
      <certificates src=["system" | "user" | "raw resource"]
      +              overridePins=["true" | "false"] />
      +
      +
      keterangan:
      +
      Set sertifikat X.509 untuk elemen {@code trust-anchors}.
      + +
      atribut:
      +
      +
      {@code src}
      +
      +Sumber sertifikat CA, bisa salah satu dari +
        +
      • ID sumber daya mentah yang menunjuk ke file berisi sertifikat X.509. + Sertifikat harus dikodekan dalam format DER atau PEM. Dalam hal sertifikat + PEM, file tidak boleh berisi data tambahan non-PEM seperti + komentar. +
      • + +
      • {@code "system"} untuk sertifikat CA sistem yang telah terpasang. +
      • + +
      • {@code "user"} untuk sertifikat CA yang ditambahkan pengguna. +
      • +
      +
      + +
      {@code overridePins}
      +
      +

      + Menetapkan apakah CA dari sumber akan mengabaikan penyematan sertifikat. Jika {@code + "true"} kemudian rangkaian sertifikat melalui salah satu CA dari + sumber ini maka tidak dilakukan penyematan. Hal ini bisa berguna untuk debug CA + atau untuk mendukung dengan memungkinkan pengguna melakukan MiTM atas lalu lintas aman aplikasi Anda. +

      + +

      + Default-nya adalah {@code "false"} kecuali jika ditetapkan dalam elemen {@code debug-overrides}, + dalam hal demikian default-nya adalah {@code "true"}. +

      +
      +
      +
      + + +

      <pin-set>

      + +
      +
      + sintaks: +
      + +
      +
      +<pin-set expiration="date">
      +...
      +</pin-set>
      +
      +
      + +
      + Bisa Berisi: +
      + +
      + Sejumlah <pin> +
      + +
      + Keterangan: +
      + +
      + Satu set pin kunci publik. Agar koneksi aman bisa dipercaya, salah satu + kunci publik dalam rantai kepercayaan harus berada dalam set pin. Lihat + <pin> untuk mengetahui format pin. +
      + +
      + Atribut: +
      + +
      +
      +
      + {@code expiration} +
      + +
      + Tanggal, dalam format {@code yyyy-MM-dd}, pada saat dan setelah pin + kedaluwarsa, sehingga menonaktifkan penyematan. Jika atribut tidak disetel maka + pin tidak kedaluwarsa. +

      + Tanggal kedaluwarsa membantu mencegah masalah konektivitas di aplikasi yang + tidak mengambil pembaruan untuk set pin mereka, misalnya karena pengguna + menonaktifkan pembaruan aplikasi. +

      +
      +
      +
      +
      + +

      <pin>

      +
      +
      + sintaks: +
      + +
      +
      +<pin digest=["SHA-256"]>base64 encoded digest of X.509
      +    SubjectPublicKeyInfo (SPKI)</pin>
      +
      +
      + +
      + Atribut: +
      + +
      +
      +
      + {@code digest} +
      + +
      + Algoritme intisari yang digunakan untuk menghasilkan pin. Saat ini, hanya + {@code "SHA-256"} yang didukung. +
      +
      +
      +
      diff --git a/docs/html-intl/intl/in/training/basics/network-ops/data-saver.jd b/docs/html-intl/intl/in/training/basics/network-ops/data-saver.jd new file mode 100644 index 0000000000000000000000000000000000000000..abd4e4391dfa281a73d924272b3bd8203731ec83 --- /dev/null +++ b/docs/html-intl/intl/in/training/basics/network-ops/data-saver.jd @@ -0,0 +1,234 @@ +page.title=Data Saver +metaDescription=Optimalisasi penggunaan data yang diaktifkan pengguna. +page.keywords="android N", "data usage", "metered network" +page.image=images/cards/card-nyc_2x.jpg +@jd:body + + + +

      + Selama penggunaan ponsel cerdas, biaya paket data seluler bisa saja + melebihi harga perangkat itu sendiri. Di N Developer Preview, pengguna bisa + mengaktifkan Data Saver berdasarkan lingkup perangkat untuk menghemat data, baik saat + roaming, mendekati akhir siklus penagihan, atau pada paket data prabayar kecil. +

      + +

      + Bila pengguna mengaktifkan Data Saver di Settings dan perangkat + berada dalam jaringan berkuota, sistem akan memblokir penggunaan data latar belakang dan memberi tahu + aplikasi untuk menghemat penggunaan data latar depan bila memungkinkan. Pengguna bisa + memasukkan aplikasi tertentu ke daftar putih untuk memungkinkan penggunaan data berkuota bila Data + Saver diaktifkan. +

      + +

      + N Developer Preview memperluas {@link android.net.ConnectivityManager} + API untuk menyediakan cara pada aplikasi untuk menerima preferensi Data Saver + pengguna dan memantau perubahan + preferensi. Hal ini dianggap praktik terbaik bagi aplikasi untuk memeriksa apakah + pengguna telah mengaktifkan DataSaver dan berusaha membatasi penggunaan data latar depan dan + data latar belakang. +

      + +

      + Memeriksa Preferensi Data Saver +

      + +

      + Di N Developer Preview, aplikasi bisa menggunakan {@link + android.net.ConnectivityManager} API untuk menentukan pembatasan penggunaan data + apa yang sedang diterapkan. Metode {@code getRestrictBackgroundStatus()} + akan mengembalikan salah satu dari nilai berikut: +

      + +
      +
      + {@code RESTRICT_BACKGROUND_STATUS_DISABLED} +
      + +
      + Data Saver dinonaktifkan. +
      + +
      + {@code RESTRICT_BACKGROUND_STATUS_ENABLED} +
      + +
      + Pengguna telah mengaktifkan Data Saver untuk aplikasi ini. Aplikasi harus berusaha membatasi + penggunaan data di latar depan dan dengan halus menangani pembatasan penggunaan + data latar belakang. +
      + +
      + {@code RESTRICT_BACKGROUND_STATUS_WHITELISTED} +
      + +
      + Pengguna telah mengaktifkan Data Saver namun aplikasi telah dimasukkan dalam daftar putih. Aplikasi harus + tetap berusaha membatasi penggunaan data latar belakang dan latar depan. +
      +
      + +

      + Hal ini dianggap praktik terbaik untuk membatasi penggunaan data bila perangkat + terhubung ke jaringan berkuota, meskipun Data Saver telah dinonaktifkan atau aplikasi + telah dimasukkan dalam daftar putih. Kode contoh berikut menggunakan {@link + android.net.ConnectivityManager#isActiveNetworkMetered + ConnectivityManager.isActiveNetworkMetered()} dan {@code + ConnectivityManager.getRestrictBackgroundStatus()} untuk menentukan berapa banyak data + yang harus digunakan aplikasi: +

      + +
      +ConnectivityManager connMgr = (ConnectivityManager)
      +        getSystemService(Context.CONNECTIVITY_SERVICE);
      +// Checks if the device is on a metered network
      +if (connMgr.isActiveNetworkMetered()) {
      +  // Checks user’s Data Saver settings.
      +  switch (connMgr.getRestrictBackgroundStatus()) {
      +    case RESTRICT_BACKGROUND_STATUS_ENABLED:
      +    // Background data usage is blocked for this app. Wherever possible,
      +    // the app should also use less data in the foreground.
      +
      +    case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
      +    // The app is whitelisted. Wherever possible,
      +    // the app should use less data in the foreground and background.
      +
      +    case RESTRICT_BACKGROUND_STATUS_DISABLED:
      +    // Data Saver is disabled. Since the device is connected to a
      +    // metered network, the app should use less data wherever possible.
      +  }
      +} else {
      +  // The device is not on a metered network.
      +  // Use data as required to perform syncs, downloads, and updates.
      +}
      +
      + +

      + Meminta izin daftar putih +

      + +

      + Jika aplikasi Anda perlu menggunakan data di latar belakang, aplikasi bisa meminta izin + daftar putih dengan mengirim + Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS + yang mengandung URI dari nama paket aplikasi Anda: misalnya, + package:MY_APP_ID. +

      + +

      + Mengirim intent dan URI akan membuka aplikasi Settings dan + menampilkan setelan penggunaan data untuk aplikasi Anda. Pengguna nanti bisa memutuskan apakah akan + mengaktifkan data latar belakang untuk aplikasi Anda. Sebelum Anda mengirim intent ini, sebaiknya + tanyakan kepada pengguna terlebih dahulu apakah mereka ingin membuka aplikasi + Settings untuk keperluan mengaktifkan penggunaan + data latar belakang. +

      + +

      + Memantau Perubahan pada Preferensi Data Saver +

      + +

      + Aplikasi bisa memantau perubahan pada preferensi Data Saver dengan membuat {@link + android.content.BroadcastReceiver} untuk memantau {@code + ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED} dan secara dinamis + mendaftarkan penerima pada {@link android.content.Context#registerReceiver + Context.registerReceiver()}. Bila menerima siaran ini, aplikasi harus + memeriksa apakah preferensi Data Saver baru memengaruhi + izinnya dengan memanggil {@code + ConnectivityManager.getRestrictBackgroundStatus()}. +

      + +

      + Catatan: Sistem hanya mengirim siaran ini ke aplikasi yang + secara dinamis mendaftar padanya dengan {@link + android.content.Context#registerReceiver Context.registerReceiver()}. Aplikasi + yang mendaftar untuk menerima siaran ini dalam manifes mereka + tidak akan menerimanya. +

      + +

      + Menguji dengan Perintah Android Debug Bridge +

      + +Android Debug Bridge (ADB) +menyediakan beberapa perintah yang bisa Anda gunakan untuk memeriksa dan +mengonfigurasi izin jaringan: + +
      +
      + $ adb shell dumpsys netpolicy +
      + +
      + Menghasilkan laporan berisi setelan pembatasan jaringan latar belakang + global saat ini, UID paket saat ini di daftar putih, dan izin jaringan + untuk paket yang diketahui lainnya. +
      + +
      + $ adb shell cmd netpolicy +
      + +
      + Menampilkan daftar lengkap dari perintah Network Policy Manager (netpolicy). +
      + +
      + $ adb shell cmd netpolicy set restrict-background + <boolean> +
      + +
      + Mengaktifkan atau menonaktifkan mode Data Saver saat meneruskan true atau + false, masing-masing. +
      + +
      + $ adb shell cmd netpolicy add restrict-background-whitelist + <UID> +
      + +
      + Menambahkan UID paket tertentu ke daftar putih untuk mengizinkan penggunaan data berkuota + di latar belakang. +
      + +
      + $ adb shell cmd netpolicy remove restrict-background-whitelist + <UID> +
      + +
      + Membuang UID paket tertentu dari daftar putih untuk memblokir + penggunaan data berkuota di latar belakang saat Data Saver diaktifkan. +
      +
      diff --git a/docs/html-intl/intl/in/training/material/drawables.jd b/docs/html-intl/intl/in/training/material/drawables.jd index 56fd17fc684b915d832a0c63454106864af42e5b..493abd46bebdfaf0c9bf56e98d74883149e26cbe 100644 --- a/docs/html-intl/intl/in/training/material/drawables.jd +++ b/docs/html-intl/intl/in/training/material/drawables.jd @@ -66,7 +66,7 @@ sediakan listener sebagai gantinya.

      Anda bisa mengambil warna mencolok dari gambar dengan metode getter di kelas Palette, misalnya Palette.getVibrantColor.

      -

      Untuk menggunakan kelas {@link android.support.v7.graphics.Palette} dalam proyek Anda, tambahkan +

      Untuk menggunakan kelas {@link android.support.v7.graphics.Palette} dalam proyek Anda, tambahkan dependensi Gradle berikut ke modul aplikasi Anda:

      diff --git a/docs/html-intl/intl/in/training/material/lists-cards.jd b/docs/html-intl/intl/in/training/material/lists-cards.jd index 358f1d17d9e24f7ce38c9c1a3eb702a500ba035a..46dd19afc4e1aea8c415e49077322b66ff231680 100644 --- a/docs/html-intl/intl/in/training/material/lists-cards.jd +++ b/docs/html-intl/intl/in/training/material/lists-cards.jd @@ -83,7 +83,7 @@ android.support.v7.widget.RecyclerView.LayoutManager RecyclerView.LayoutManager}

      Animasi

      Animasi untuk menambahkan dan menghapus item diaktifkan secara default di {@link -android.support.v7.widget.RecyclerView}. Untuk menyesuaikan animasi ini, perluas kelas +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()}.

      @@ -253,7 +253,7 @@ dalam layout:

      Widget {@link android.support.v7.widget.RecyclerView} dan {@link android.support.v7.widget.CardView} adalah bagian dari v7 Support -Library. Untuk menggunakan widget dalam proyek Anda, tambahkan +Library. Untuk menggunakan widget dalam proyek Anda, tambahkan dependensi Gradle ini ke modul aplikasi Anda:

      diff --git a/docs/html-intl/intl/in/training/tv/playback/picture-in-picture.jd b/docs/html-intl/intl/in/training/tv/playback/picture-in-picture.jd new file mode 100644 index 0000000000000000000000000000000000000000..41af6de9772386d4f2e269c816c2c62ee01c27ec --- /dev/null +++ b/docs/html-intl/intl/in/training/tv/playback/picture-in-picture.jd @@ -0,0 +1,213 @@ +page.title=Gambar-dalam-gambar +page.keywords=pratinjau,sdk,PIP,Gambar-dalam-gambar +page.tags=androidn + +@jd:body + + + +

      Di Android N, pengguna Android TV sekarang bisa menonton video +dalam jendela yang disematkan di sudut layar saat menyusuri +aplikasi. Mode gambar-dalam-gambar (PIP) memungkinkan aplikasi menjalankan aktivitas +video dalam jendela yang disematkan selagi aktivitas lain tetap berjalan di +latar belakang. Jendela PIP memungkinkan pengguna melakukan multitasking saat menggunakan aplikasi Anda, yang +membantu pengguna menjadi lebih produktif.

      + +

      Aplikasi Anda bisa memutuskan kapan memicu mode PIP. Inilah beberapa contoh +kapan memasuki mode PIP:

      + +
        +
      • Aplikasi Anda bisa memindahkan video ke dalam mode PIP bila pengguna mengarah +mundur dari video untuk menjelajah materi lainnya.
      • +
      • Aplikasi Anda bisa mengalihkan video ke dalam mode PIP selagi pengguna menonton akhir episode +dari materi. Layar utama menampilkan informasi +promosi atau rangkuman tentang episode berikutnya dalam seri tersebut.
      • +
      • Aplikasi Anda bisa menyediakan suatu cara bagi pengguna untuk mengantre materi tambahan selagi +mereka menonton video. Video terus dimainkan dalam mode PIP selagi layar +utama menampilkan aktivitas pemilihan materi.
      • +
      + +

      Jendela PIP memiliki luas 240x135 dp dan ditampilkan di layer paling atas pada salah satu +dari empat sudut layar, yang dipilih oleh sistem. Pengguna bisa memunculkan +menu PIP yang memungkinkan mereka untuk beralih mode dari jendela PIP ke layar penuh, atau menutup jendela +PIP, dengan menekan dan menahan tombol Beranda pada remote. Jika video +lain mulai diputar pada layar utama, jendela PIP secara otomatis +ditutup. Pengguna juga bisa menutup jendela PIP melalui Recents.

      + + +

      Gambar 1. Video +Gambar-dalam-gambar terlihat di sudut layar selagi pengguna menjelajahi materi pada layar +utama.

      + +

      PIP memanfaatkan API multi-jendela yang tersedia di Android N untuk +menyediakan jendela hamparan video yang disematkan. Untuk menambahkan PIP ke aplikasi, Anda harus +mendaftarkan aktivitas yang mendukung PIP, mengalihkan aktivitas Anda ke mode PIP bila +diperlukan, serta memastikan elemen UI disembunyikan dan pemutaran video berlanjut bila +aktivitas dalam mode PIP.

      + +

      Mendeklarasikan Bahwa Aktivitas Anda Mendukung Gambar-dalam-gambar

      + +

      Secara default, sistem tidak secara otomatis mendukung PIP untuk aplikasi. +Jika Anda ingin mendukung PIP dalam aplikasi, daftarkan aktivitas +video Anda dalam manifes dengan menyetel +android:supportsPictureInPicture dan +android:resizeableActivity ke true. Juga, tetapkan +bahwa aktivitas Anda menangani perubahan konfigurasi layout sehingga aktivitas +Anda tidak diluncurkan ulang saat terjadi perubahan layout selama transisi mode PIP.

      + +
      +<activity android:name="VideoActivity"
      +    android:resizeableActivity="true"
      +    android:supportsPictureInPicture="true"
      +    android:configChanges=
      +        "screenSize|smallestScreenSize|screenLayout|orientation"
      +    ...
      +
      + +

      Saat mendaftarkan aktivitas Anda, ingatlah bahwa dalam mode PIP aktivitas +Anda akan ditampilkan pada jendela hamparan kecil pada layar TV. Aktivitas +pemutaran video dengan UI minimal akan memberikan pengalaman pengguna terbaik. Aktivitas yang +mengandung elemen UI kecil mungkin tidak memberikan pengalaman pengguna yang baik +ketika beralih ke mode PIP, karena pengguna tidak dapat melihat elemen UI secara jelas +di jendela PIP.

      + +

      Mengalihkan Aktivitas Anda ke Gambar-dalam-gambar

      + +Bila Anda perlu untuk mengalihkan aktivitas ke mode PIP, panggil +Activity.enterPictureInPictureMode(). Contoh berikut mengalihkan +ke mode PIP bila pengguna memilih tombol PIP khusus pada baris +kontrol media:

      + +
      +@Override
      +public void onActionClicked(Action action) {
      +    if (action.getId() == R.id.lb_control_picture_in_picture) {
      +        getActivity().enterPictureInPictureMode();
      +        return;
      +    }
      +    ...
      +
      + +

      Menambahkan tombol PIP ke baris kontrol media Anda akan memungkinkan pengguna dengan mudah beralih +ke mode PIP selagi mengontrol pemutaran video.

      + + +

      Gambar 1. Tombol +gambar-dalam-gambar pada baris kontrol media.

      + +

      Android N menyertakan kelas +PlaybackControlsRow.PictureInPictureAction baru yang mendefinisikan +tindakan PIP baris kontrol dan menggunakan ikon PIP.

      + +

      Menangani UI Selama Gambar-dalam-gambar

      + +

      Bila aktivitas memasuki mode PIP, aktivitas Anda seharusnya hanya menampilkan pemutaran +video. Buang elemen UI sebelum aktivitas Anda memasuki PIP, +dan pulihkan elemen ini bila aktivitas Anda beralih ke layar penuh lagi. +Ganti Activity.onPictureInPictureModeChanged() atau +Fragment.onPictureInPictureModeChanged() dan aktifkan atau +nonaktifkan elemen UI saat diperlukan, misalnya:

      + +
      +@Override
      +public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
      +    if (isInPictureInPictureMode) {
      +        // Hide the controls in picture-in-picture mode.
      +        ...
      +    } else {
      +        // Restore the playback UI based on the playback status.
      +        ...
      +    }
      +}
      +
      + +

      Melanjutkan Pemutaran Video Saat dalam +Gambar-dalam-gambar

      + +

      Bila aktivitas Anda beralih ke PIP, sistem akan menganggap aktivitas tersebut berada dalam +keadaan berhenti sementara, dan akan memanggil metode onPause() aktivitas Anda. Pemutaran +video tidak boleh berhenti sementara dan harus terus diputar jika aktivitas tersebut +berhenti sementara karena mode PIP. Periksa PIP dalam metode +onPause() aktivitas Anda dan tangani pemutaran dengan tepat, +misalnya:

      + +
      +@Override
      +public void onPause() {
      +    // If called while in PIP mode, do not pause playback
      +    if (isInPictureInPictureMode()) {
      +        // Continue playback
      +        ...
      +    }
      +    // If paused but not in PIP, pause playback if necessary
      +    ...
      +}
      +
      + +

      Bila aktivitas meninggalkan mode PIP dan kembali ke mode layar penuh, sistem +akan melanjutkan aktivitas Anda dan memanggil metode onResume().

      + +

      Menggunakan Aktivitas Pemutaran Tunggal untuk + Gambar-dalam-gambar

      + +

      Di aplikasi Anda, seorang pengguna bisa memilih video baru saat menyusuri materi di +layar utama, selagi aktivitas pemutaran video dalam mode PIP. Putar +video baru di aktivitas pemutaran yang ada dalam mode layar penuh, sebagai ganti +meluncurkan aktivitas baru yang dapat membingungkan pengguna.

      + +

      Guna memastikan aktivitas tunggal digunakan untuk permintaan pemutaran video dan +beralih ke atau dari mode PIP bila dibutuhkan, setel +android:launchMode aktivitas ke singleTask dalam manifes Anda: +

      + +
      +<activity android:name="VideoActivity"
      +    ...
      +    android:supportsPictureInPicture="true"
      +    android:launchMode="singleTask"
      +    ...
      +
      + +

      Di aktivitas Anda, ganti {@link android.app.Activity#onNewIntent +Activity.onNewIntent()} dan tangani video baru, yang akan menghentikan pemutaran video +jika diperlukan.

      + +

      Praktik Terbaik

      + +

      PIP ditujukan untuk aktivitas yang memutar video layar penuh. Saat mengalihkan +aktivitas Anda ke mode PIP, hindari menampilkan apa pun selain materi video. +Pantau saat aktivitas Anda memasuki mode PIP dan sembunyikan elemen UI, seperti dijelaskan +dalam Menangani UI Selama Gambar-dalam-gambar.

      + +

      Karena jendela PIP ditampilkan sebagai jendela mengambang di sudut +layar, Anda harus menghindari menampilkan informasi penting di layar utama +di area mana saja yang bisa terhalang oleh jendela PIP.

      + +

      Bila aktivitas ada berada dalam mode PIP, secara default aktivitas itu tidak mendapatkan fokus masukan. Untuk +menerima kejadian masukan saat dalam mode PIP, gunakan +MediaSession.setMediaButtonReceiver().

      diff --git a/docs/html-intl/intl/in/training/tv/tif/content-recording.jd b/docs/html-intl/intl/in/training/tv/tif/content-recording.jd new file mode 100644 index 0000000000000000000000000000000000000000..3389dbf84cbfdbe2d4b15c7fddea4b20b6cb1b4a --- /dev/null +++ b/docs/html-intl/intl/in/training/tv/tif/content-recording.jd @@ -0,0 +1,142 @@ +page.title=Perekaman TV +page.keywords=pratinjau,sdk,tv,perekaman +page.tags=androidn +page.image=images/cards/card-nyc_2x.jpg + +@jd:body + + + +

      Layanan masukan TV memungkinkan pengguna menghentikan sementara dan melanjutkan pemutaran saluran melalui +API perekaman. Android N telah berkembang hingga ke perekaman +dengan memungkinkan pengguna menyimpan beberapa sesi rekaman.

      + +

      Pengguna bisa menjadwalkan rekaman terlebih dahulu, atau memulai rekaman sambil menonton +suatu acara. Setelah sistem menyimpan rekaman, pengguna bisa menjelajah, menata, +dan memutar kembali rekaman tersebut menggunakan aplikasi TV di sistem.

      + +

      Jika Anda ingin menyediakan fungsi perekaman untuk layanan masukan TV, +Anda harus menunjukkan pada sistem bahwa aplikasi Anda mendukung perekaman, mengimplementasikan +kemampuan merekam program, menangani dan mengomunikasikan kesalahan yang muncul +selama perekaman, dan mengelola sesi perekaman Anda.

      + +

      Catatan: Aplikasi Live Channels belum +menyediakan cara bagi pengguna untuk membuat atau mengakses perekaman. Hingga dibuat perubahan +di aplikasi Live Channels, mungkin sulit menguji sepenuhnya pengalaman +perekaman untuk layanan masukan TV Anda.

      + +

      Menunjukkan Dukungan untuk Perekaman

      + +

      Untuk memberi tahu sistem bahwa layanan masukan TV Anda mendukung perekaman, setel +atribut android:canRecord di file XML metadata layanan Anda +ke true: +

      + +
      +<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
      +  android:canRecord="true"
      +  android:setupActivity="com.example.sampletvinput.SampleTvInputSetupActivity" />
      +
      + +

      Untuk informasi selengkapnya mengenai layanan file metadata, lihat +Mendeklarasikan Layanan Masukan TV Anda +di Manifes. +

      + +

      Atau, Anda bisa menunjukkan dukungan perekaman dalam kode Anda menggunakan +langkah-langkah ini:

      + +
        +
      1. Dalam metode TvInputService.onCreate() Anda, buat objek +TvInputInfo baru menggunakan kelas TvInputInfo.Builder. +
      2. +
      3. Saat membuat objek TvInputInfo baru, panggil +setCanRecord(true) sebelum memanggil build() untuk + menunjukkan layanan Anda mendukung perekaman.
      4. +
      5. Daftarkan objek TvInputInfo Anda pada sistem dengan memanggil +TvInputManager.updateTvInputInfo().
      6. +
      + +

      Merekam Sesi

      + +

      Setelah layanan masukan TV Anda mendaftar bahwa mendukung fungsionalitas +perekaman, sistem akan memanggil +TvInputService.onCreateRecordingSession() bila perlu untuk mengakses +implementasi perekaman aplikasi Anda. Implementasikan subkelas +TvInputService.RecordingSession Anda sendiri dan kembalikan +bila callback onCreateRecordingSession() dipicu. + Subkelas ini bertanggung jawab mengalihkan ke saluran data yang benar, +merekam data yang diminta, dan memberitahukan status perekaman serta kesalahan ke +sistem.

      + +

      Bila sistem memanggil RecordingSession.onTune(), dengan meneruskan +URI saluran, setel ke saluran yang ditetapkan URI. Beri tahu sistem bahwa +aplikasi Anda telah disetel ke saluran yang diinginkan dengan memanggil notifyTuned(), +atau, jika aplikasi Anda tidak bisa disetel ke saluran yang tepat, panggil +notifyError().

      + +

      Sistem berikutnya akan memanggil callback RecordingSession.onStartRecording(). + Aplikasi Anda harus segera mulai merekam. Bila sistem memanggil +callback ini, sistem mungkin akan memberikan URI yang berisi informasi tentang program +yang akan direkam. Bila perekaman selesai, Anda perlu menyalin data +ini ke tabel data RecordedPrograms.

      + +

      Terakhir, sistem akan memanggil RecordingSession.onStopRecording(). +Pada tahap ini, aplikasi Anda harus segera berhenti merekam. Anda juga perlu +membuat entri dalam tabel RecordedPrograms. Entri ini harus +menyertakan URI data sesi yang direkam dalam kolom +RecordedPrograms.COLUMN_RECORDING_DATA_URI, dan informasi +program yang diberikan sistem dalam panggilan awal ke +onStartRecording().

      + +

      Untuk detail selengkapnya tentang cara mengakses tabel RecordedPrograms +lihat Mengelola Sesi yang Direkam.

      + +

      Menangani Kesalahan Perekaman

      + +

      Jika terjadi kesalahan selama perekaman, yang menghasilkan data terekam yang tidak bisa digunakan, +beri tahu sistem dengan memanggil RecordingSession.notifyError(). +Begitu juga, Anda bisa memanggil notifyError() setelah sesi rekaman dibuat +agar sistem mengetahui bahwa aplikasi Anda tidak bisa lagi merekam sesi.

      + +

      Jika terjadi kesalahan selama perekaman, namun Anda ingin menyediakan rekaman parsial +yang bisa digunakan pengguna untuk pemutaran, panggil +RecordingSession.notifyRecordingStopped() untuk memungkinkan sistem +menggunakan sesi parsial.

      + +

      Mengelola Sesi yang Direkam

      + +

      Sistem menyimpan informasi untuk semua sesi yang direkam dari semua +aplikasi saluran yang mampu merekam dalam tabel penyedia materi TvContract.RecordedPrograms. + Informasi ini bisa diakses lewat URI materi +RecordedPrograms.Uri. Gunakan API penyedia materi untuk +membaca, menambahkan, dan menghapus entri dari tabel ini.

      + +

      Untuk informasi selengkapnya tentang menangani data penyedia materi, lihat + +Dasar-Dasar Penyedia Materi.

      + +

      Praktik Terbaik

      + +

      Perangkat TV mungkin memiliki penyimpanan terbatas, jadi pertimbangkan sebaik mungkin saat +mengalokasikan penyimpanan untuk menyimpan sesi rekaman. Gunakan +RecordingCallback.onError(RECORDING_ERROR_INSUFFICIENT_SPACE) bila +tidak cukup ruang untuk menyimpan sesi rekaman.

      + +

      Bila pengguna memulai perekaman, Anda harus memulai perekaman data +secepatnya. Untuk memfasilitasinya, selesaikan setiap tugas yang memakan waktu di awal, +seperti mengakses dan mengalokasikan ruang penyimpanan, saat sistem memanggil callback +onCreateRecordingSession(). Hal ini akan memungkinkan Anda memulai +perekaman dengan segera bila callback onStartRecording() +dipicu.

      diff --git a/docs/html-intl/intl/ja/preview/guide.jd b/docs/html-intl/intl/ja/about/versions/marshmallow/android-6.0-testing.jd similarity index 99% rename from docs/html-intl/intl/ja/preview/guide.jd rename to docs/html-intl/intl/ja/about/versions/marshmallow/android-6.0-testing.jd index f56fc668d39487508ca004dcad345084f4f44e20..9f034120c7762bb4ef97012186e833be65e9e2c9 100644 --- a/docs/html-intl/intl/ja/preview/guide.jd +++ b/docs/html-intl/intl/ja/about/versions/marshmallow/android-6.0-testing.jd @@ -5,8 +5,8 @@ page.tags="preview", "developer preview" @jd:body -
      -
      +
      +

      このドキュメントの内容

      1. パーミッションをテストする
      2. diff --git a/docs/html-intl/intl/ja/preview/behavior-changes.jd b/docs/html-intl/intl/ja/about/versions/nougat/android-7.0-changes.jd similarity index 98% rename from docs/html-intl/intl/ja/preview/behavior-changes.jd rename to docs/html-intl/intl/ja/about/versions/nougat/android-7.0-changes.jd index c112504c5d9dc0ba1d884948b9bb795c8046ccd0..0fd941263913950d619c86830c031c4819d95d18 100644 --- a/docs/html-intl/intl/ja/preview/behavior-changes.jd +++ b/docs/html-intl/intl/ja/about/versions/nougat/android-7.0-changes.jd @@ -6,8 +6,8 @@ page.image=images/cards/card-n-changes_2x.png @jd:body -
        -
        +
        +

        このドキュメントの内容

        @@ -77,7 +77,7 @@ Android N では、Doze が改良されています。端末を電源と接続

        - +

        図 1. Doze が第 1 レベルのシステム アクティビティ制限を適用して、電池寿命を改善 @@ -96,7 +96,7 @@ Android N では、Doze が改良されています。端末を電源と接続

        - +

        図 2. 端末がしばらくの間静止状態になると、Doze が第 2 レベルのシステム アクティビティ制限を適用する @@ -282,10 +282,10 @@ Android N 向けのアプリでは、Android フレームワークにより、

        - +
        - +
        diff --git a/docs/html-intl/intl/ja/preview/samples.jd b/docs/html-intl/intl/ja/about/versions/nougat/android-7.0-samples.jd similarity index 80% rename from docs/html-intl/intl/ja/preview/samples.jd rename to docs/html-intl/intl/ja/about/versions/nougat/android-7.0-samples.jd index ec3f9f7d4c2e1629923fcc3d91df51d5dc751da3..9a50ff7c2fedadc433d7e7a3e6b3640e3575ef61 100644 --- a/docs/html-intl/intl/ja/preview/samples.jd +++ b/docs/html-intl/intl/ja/about/versions/nougat/android-7.0-samples.jd @@ -16,7 +16,7 @@ page.image=images/cards/card-n-samples_2x.png

        マルチ ウィンドウ Playground

        - +

        このサンプルでは、自身のアプリでマルチ ウィンドウのユーザー インターフェースを使用する方法をご確認いただけます。 @@ -28,7 +28,7 @@ page.image=images/cards/card-n-samples_2x.png

        アクティブ通知

        - +

        NotificationCompat を使用して通知を送信するシンプルなサービスをご確認いただける既存のサンプルです。 ユーザーからの未読メッセージは、それぞれ別の通知として送信されます。 @@ -45,7 +45,7 @@ page.image=images/cards/card-n-samples_2x.png

        メッセージ サービス

        - +

        1 つのアプリで表示している通知の件数を NotificationManager で取得する方法をご確認いただける既存のサンプルです。 @@ -62,7 +62,7 @@ page.image=images/cards/card-n-samples_2x.png

        ダイレクト ブート

        - +

        このサンプルでは、端末の暗号化ストレージ内のデータにアクセスしたり、データを保存したりする方法をご確認いただけます。この機能は端末が起動している間は常に有効です。 @@ -74,7 +74,7 @@ page.image=images/cards/card-n-samples_2x.png

        特定のディレクトリへのアクセス

        - +

        このサンプルでは、より少ないパーミッションで、特定のディレクトリに対するデータの読み出しや書き込みを行う方法をご確認いただけます。 @@ -82,4 +82,4 @@ page.image=images/cards/card-n-samples_2x.png

        GitHub でサンプルを入手 -

        \ No newline at end of file +

        diff --git a/docs/html-intl/intl/ja/preview/api-overview.jd b/docs/html-intl/intl/ja/about/versions/nougat/android-7.0.jd similarity index 98% rename from docs/html-intl/intl/ja/preview/api-overview.jd rename to docs/html-intl/intl/ja/about/versions/nougat/android-7.0.jd index d967a67bb9a417f5bb297380395d438e0220b6e5..732b014d047dedbdd13163a05dad3c99283647a6 100644 --- a/docs/html-intl/intl/ja/preview/api-overview.jd +++ b/docs/html-intl/intl/ja/about/versions/nougat/android-7.0.jd @@ -7,8 +7,8 @@ page.image=images/cards/card-n-apis_2x.png -
        -
        +
        +

        主なデベロッパー機能

            @@ -78,7 +78,7 @@ page.image=images/cards/card-n-apis_2x.png
          - +

          図 1. 分割画面モードで実行されているアプリ

          @@ -142,15 +142,15 @@ Android Wear 向けの通知を実装したことがある場合は、このモ
          - +
          - +
          - +
          @@ -277,7 +277,7 @@ JobScheduler はシンプルな制御を提供するため、すべてのアプ

          データセーバー

          - +

          図 4. [Settings] でのデータセーバー @@ -357,7 +357,7 @@ Vulkan を可能な限りより多くの端末に導入するためにパート

          - +

          図 5. 通知シェードにあるクイック設定タイル diff --git a/docs/html-intl/intl/ja/about/versions/nougat/index.jd b/docs/html-intl/intl/ja/about/versions/nougat/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..7c5fe5df786be650c120f06102fb92ac1740b286 --- /dev/null +++ b/docs/html-intl/intl/ja/about/versions/nougat/index.jd @@ -0,0 +1,110 @@ +page.title=Android 7.0 Nougat +page.tags="androidn","versions" +meta.tags="android n", "nougat", "android 7.0" +fullpage=true +forcelocalnav=true +header.hide=1 +footer.hide=1 +@jd:body + +

          + +
          + + + + +
          +

          新着

          +
          +
          + +
          +

          Videos

          +
          + New Android capabilities and the right way to use them in your apps. +
          + +
          +
          +
          + +
          +

          リソース

          +
          + Android Nougat 向けにアプリを開発する上で役立つ必須情報をご提供します。 +
          + +
          +
          +
          \ No newline at end of file diff --git a/docs/html-intl/intl/ja/design/patterns/notifications.jd b/docs/html-intl/intl/ja/design/patterns/notifications.jd deleted file mode 100644 index 8c5b6babd0853567fa8eddab78afdfe0341d225b..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ja/design/patterns/notifications.jd +++ /dev/null @@ -1,872 +0,0 @@ -page.title=通知 -page.tags="notifications","design","L" -@jd:body - - -
          -

          デベロッパー文書

          -

          ユーザーに通知する

          -
          -
          - - -
          -

          Android 4.4 以前での通知

          -
          -
          - - - -
          -

          ビデオ

          -

          DevBytes:Notifications in the Android L Developer Preview

          -
          -
          - - - -

          通知システムを使用すると、ユーザーは友人からの新しいチャット メッセージやカレンダー イベントなど、自分に関係のあるタイムリーなイベントについてアプリで常に通知を受けることができます。通知は、重要な出来事が起こるとすぐに知らせてくれるニュース チャンネルであり、ユーザーが意識していない間に出来事を時系列的に記録するログであると捉えることができます — さらに、すべての Android 端末で適宜同期されます。 - - - - - -

          - -

          Android 5.0 での新機能

          - -

          Android 5.0 において、通知は構造的に、視覚的に、機能的に重要なアップデートを受信します。 -

          - -
            -
          • 通知は、新しいマテリアル デザインのテーマにあわせて外観が変更されているところす。 -
          • -
          • 端末のロック画面で通知を利用できるようになりましたが、機密性の高いコンテンツはこれからも非表示にできます。 - -
          • -
          • 端末の使用中に受信した高優先度の通知において、ヘッドアップ通知と呼ばれる新しい形式が使用されるようになりました。 -
          • -
          • クラウド同期通知: 所有する Android 端末のどれかで通知を却下すると、他でも却下されます。 - -
          • -
          - -

          : このバージョンの Android での通知設計は、従来のバージョンから大きく変わっています。 - -これまでのバージョンの通知設計について詳しくは、Android 4.4 以前での通知をご覧ください。 -

          - -

          通知の仕組み

          - -

          このセクションでは、通知の基本パーツと各種端末における通知の表示について詳しく説明します。 -

          - -

          基本レイアウト

          - -

          あらゆる通知の最低限の基本レイアウトは次のようになっています。

          - -
            -
          • 通知のアイコン。このアイコンは通知元のアプリを示します。複数タイプの通知を生成するアプリでは、通知のタイプを示すことがあります。 - - -
          • -
          • 通知のタイトルと追加テキストメッセージ。 -
          • -
          • タイムスタンプ
          • -
          - -

          従来のプラットフォーム バージョンの {@link android.app.Notification.Builder Notification.Builder} で作成された通知は、Android 5.0 でも同じように表示され、機能します。スタイルにいくらかの違いがありますが、システムが対処します。 - - -従来のバージョンの Android での通知について詳しくは、Android 4.4 以前での通知をご覧ください。 - -

          - - - - - -
          -

          - ユーザー フォトと通知アイコンを使用した、携帯端末での通知(左)と Wear での同じ通知(右) - -

          -
          - -

          展開レイアウト

          - - -

          通知にどこまでの詳細を表示するかを選択できます。 -メッセージの最初の数行を表示したり、大きな画像プレビューを表示したりできます。 -追加情報はユーザーにより多くのコンテキストを提供し、—場合によっては—メッセージ全体が表示されることもあります。 - - -ユーザーは、ピンチ ズームまたは 1 本指のスワイプで、コンパクトなレイアウトと展開されたレイアウトを切り替えることができます。 - - - 1 つのイベントに関する通知に対し、Android では 3 種類の展開レイアウト(テキスト、受信トレイ、画像)をアプリケーションで使用できるようにしています。 - -次の図に、1 つのイベントに関する通知が携帯端末(左)とウェアラブル(右)でどのように見えるかを示します。 - -

          - - - - - -

          アクション

          - -

          Android では、通知の最下部に表示されるオプションのアクションをサポートしています。ここに示されるアクションを使用することで、ユーザーは特定の通知に対するほとんどの一般的なタスクを通知シェードで処理でき、通知元のアプリケーションを開く必要はありません。これによりやり取りがスピードアップし、スワイプで却下もできることから、ユーザーは自分に関係のある通知に集中しやすくなります。 - - - - - -

          - - - - - - -

          通知に含めるアクションの数はほどほどに抑えることをお勧めします。 -含めるアクションを増やすほど、わかりにくくなるからです。 -もっとも差し迫った意味のある重要なアクションだけにして、アクションの数を最小限に抑えてください。 - - -

          - -

          通知に対するアクションとして好ましい候補は次のとおりです。

          - -
            -
          • 表示するコンテンツ タイプに欠かせず、よく使われ、典型的である - -
          • ユーザーがタスクを手早く完了できる -
          - -

          次のようなアクションは避けてください。

          - -
            -
          • あいまいである -
          • 通知のデフォルト アクションと同じである(「読む」や「開く」など) - -
          - - - -

          アクションは 3 つまで指定でき、それぞれにアクションのアイコンと名前が付きます。 - - シンプルな基本レイアウトにアクションを追加すると、展開レイアウトがない場合でも、通知は展開可能になります。 - -アクションは展開可能な通知にのみ表示され、それ以外では非表示になることから、ユーザーが通知から起動できるどのアクションについても、関連アプリケーションからも利用できるようにしてください。 - - - - -

          - -

          ヘッドアップ通知

          -
          - -

          - イマーシブ アプリの最上部に表示されたヘッドアップ通知の例(電話の着信、高優先度) - - -

          -
          - -

          優先度の高い通知が作成されると(右図)、その展開レイアウトが可能なアクションとともに短時間表示されます。 - -

          -

          この時間が過ぎると、通知は通知シェードに戻ります。 -通知の優先度を示すフラグが高、最大、全画面の場合は、ヘッドアップ通知になります。 -

          - -

          ヘッドアップ通知にふさわしい例

          - -
            -
          • 端末使用中の電話の着信
          • -
          • 端末使用中のアラーム
          • -
          • 新しい SMS メッセージ
          • -
          • 低バッテリ残量
          • -
          - -

          ガイドライン

          - - -

          パーソナルにする

          - -

          他人から送信されたアイテム(メッセージ、ステータス アップデートなど)の通知には、{@link android.app.Notification.Builder#setLargeIcon setLargeIcon()} を使用して相手の画像を含めます。 - -また、通知のメタデータに相手に関する情報を添付します({@link android.app.Notification#EXTRA_PEOPLE} を参照)。 -

          - -

          通知のメインアイコンは表示され続けるため、ユーザーはそれをステータスバーに表示されるアイコンと関連付けることができます。 - -

          - - - -

          - 通知をトリガーした人と送信内容が表示された通知。 -

          - - - - -

          ユーザーが通知の本体(アクション ボタン以外)をタップしたら、アプリが開き、通知に表示されているデータの表示や操作ができる画面へ移動するようにします。 - - -ほとんどの場合、移動先はメッセージのような 1 つのデータアイテムの詳細表示になりますが、通知がスタックされている場合は概要ビューにすることも考えられます。 - -アプリがユーザーをアプリの最上位レベルより下のどこかに移動する場合は、アプリのバックスタックにナビゲーションを挿入して、ユーザーがシステムの Back ボタンを押すと最上位レベルに戻れるようにします。 - -詳しくは、ナビゲーションデザイン パターンのホーム画面ウィジェットと通知を経由するアプリへのナビゲーションをご覧ください。 - -

          - -

          通知優先度の適切な設定と管理 - -

          - -

          Android では、通知用の優先度フラグをサポートしています。このフラグを使用すると、通知の表示位置に他の通知との相対関係として影響を及ぼして、ユーザーが常に最重要の通知を真っ先に目にするようにできます。 - - -通知を投稿する際には、優先度を次の中から選べます。 - -

          -
      - - - - - - - - - - - - - - - - - - - - - - - - -
      -

      優先度

      -
      -

      用途

      -
      -

      MAX

      -
      -

      重大で切迫した通知に対して使用します。緊急を要する状況、または特定のタスクを続ける前に解決する必要がある状況であることをユーザーに通告します。 - - -

      -
      -

      HIGH

      -
      -

      主に重要な情報に対して使用します。ユーザーが特に関心を持ちそうなメッセージ イベントやチャット イベントなどが該当します。通知の優先度を高く設定すると、ヘッドアップ通知を表示できます。 - -

      -
      -

      DEFAULT

      -
      -

      ここで説明している他の優先度のどれにも該当しないすべての通知に対して使用します。

      -
      -

      LOW

      -
      -

      ユーザーに知らせたいがそれほど緊急ではない通知に対して使用します。 -低優先度の通知は一般にリストの末尾に表示され、公の、または間接的なソーシャル アップデートなどに適しています。 - -ユーザーがこうした通知の設定をしていても、急を要するコミュニケーションや直接的なコミュニケーションより優先されないようにする必要があります。 - - -

      -
      -

      MIN

      -
      -

      天気予報や周辺位置情報のようなコンテキスト的またはバックグラウンド的な情報に対して使用します。最小優先度の通知はステータスバーに表示されません。 - -ユーザーは通知シェードを展開したときにその存在に気づきます。 -

      -
      - - -

      適切な優先度の選び方 - -

      - -

      DEFAULTHIGHMAX は中断を伴う優先度レベルで、ユーザーによるアクティビティに割り込むリスクがあります。 - -アプリのユーザーに不快に思われないようにするため、割り込みを伴う優先度レベルの通知は次のような場合に限定してください。 -

      - -
        -
      • 他人が絡む
      • -
      • 急を要する
      • -
      • 実世界におけるユーザーの行動が直ちに変わりうる
      • -
      - -

      LOWMIN に設定されている通知も、ユーザーにとって価値がある可能性はあります。 -ほとんどとは言わないまでも、多くの通知は、ユーザーの注意を直ちに引く、またはユーザーの手首に振動を与える必要はありませんが、ユーザーがその通知を見ることにしたときに価値があると気づくような情報が含まれている必要があります。 - - -優先度が LOWMIN の通知の条件は以下のとおりです。 -

      - -
        -
      • 他人が絡まない
      • -
      • 急を要さない
      • -
      • ユーザーが興味を持ちうる内容が含まれているが、手が空いたときに参照することにして問題ない -
      • -
      - - - - - -

      通知カテゴリの設定 -

      - -

      通知が、あらかじめ定義されているカテゴリ(下を参照)のどれかに該当する場合は、それに沿って割り当てます。 - -通知シェード(やその他の通知リスナー)などの各種システム UI は、評価やフィルタリングの判断にこの情報を使用することがあります。 - -

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -

      CATEGORY_CALL

      -
      -

      電話(ビデオまたは音声)の着信またはそれに類する同期通信の要求 -

      -
      -

      CATEGORY_MESSAGE

      -
      -

      直接メッセージ(SMS、インスタントメッセージなど)の受信

      -
      -

      CATEGORY_EMAIL

      -
      -

      非同期バルク メッセージ(メール)

      -
      -

      CATEGORY_EVENT

      -
      -

      カレンダー イベント

      -
      -

      CATEGORY_PROMO

      -
      -

      販促または広告

      -
      -

      CATEGORY_ALARM

      -
      -

      アラームまたはタイマー

      -
      -

      CATEGORY_PROGRESS

      -
      -

      長時間実行のバックグラウンド処理の進捗

      -
      -

      CATEGORY_SOCIAL

      -
      -

      ソーシャル ネットワークまたは共有アップデート

      -
      -

      CATEGORY_ERROR

      -
      -

      バックグラウンド処理または認証ステータスにおけるエラー

      -
      -

      CATEGORY_TRANSPORT

      -
      -

      再生のためのメディア転送コントロール

      -
      -

      CATEGORY_SYSTEM

      -
      -

      システムまたは端末のステータス アップデート。システム用に予約済み。

      -
      -

      CATEGORY_SERVICE

      -
      -

      バックグラウンド サービス実行中の表示。

      -
      -

      CATEGORY_RECOMMENDATION

      -
      -

      1 つの事項に対する具体的でタイムリーな推奨。たとえば、ニュースアプリがユーザーが次に読みたいのではないかと予想した記事を推奨するなど。 - -

      -
      -

      CATEGORY_STATUS

      -
      -

      端末やコンテキスト ステータスに関する進行中情報。

      -
      - -

      通知の概要

      - -

      アプリで特定の新しい通知を送信しようとしたときに同じタイプの通知が既に保留されていた場合は、それらを統合してそのアプリに対する 1 つの概要通知にします。新しいオブジェクトは作成しないでください。 - -

      - -

      概要通知は概要説明を作成し、特定タイプの通知がいくつ保留になっているのかがユーザーにわかるようにします。 - -

      - -
      - -

      非推奨

      - -
      - -
      -

      推奨

      - - -
      - -

      概要を構成している個々の通知に関する詳細は、展開ダイジェスト レイアウトを使用して提示できます。 - -このアプローチにより、ユーザーはどの通知が保留中か、そして関連アプリで詳しく読もうと思うほどそれらに興味があるかを把握しやすくなります。 - - - -

      -
      - -

      - 通知の展開された概要と折りたたまれた概要(InboxStyle を使用) -

      -
      - -

      通知をオプションにする -

      - -

      ユーザーは常に通知を制御できる必要があります。アプリケーションの設定に通知設定アイテムを追加して、ユーザーがアプリの通知を無効にしたり、警告音や振動を使用するかどうかなどのアラート設定を変更したりできるようにしてください。 - - - -

      - -

      見分けやすいアイコンにする

      -

      現在保留になっているのがどのタイプの通知なのか、ユーザーが通知エリアを一目で見分けられることが必要です。 - -

      - -
      - -
      - -

      推奨

      -

      Android アプリが既に提供している通知アイコンを見ながら、独自アプリ用に見かけの十分異なるアイコンを作成する。 - -

      - -

      推奨

      -

      小さなアイコン用の適切な通知アイコン スタイルと、アクション アイコン用の Material Light アクションバー アイコンスタイルを使う。 - - - -

      -

      推奨

      -

      アイコンの見た目はシンプルに保ち、細かくしすぎて見にくくならないようにする。 -

      - -

      非推奨

      -

      なんらかの追加アルファ(暗転やフェード)を小さなアイコンやアクション アイコンに配置する。エッジはアンチ エイリアス処理できますが、Android ではこれらのアイコンをマークとして使用するため(つまり、アルファ チャンネルのみ使用)、画像は概して完全不透明で描画されます。 - - - - -

      - -
      -

      非推奨

      - -

      アプリを他と色で区別する。通知アイコンは、背景が透明な白に限定してください。 -

      - - -

      通知 LED を適切に点灯させる -

      - -

      多くの Android 端末には通知 LED が用意されており、スクリーンがオフのときでもユーザーに引き続きイベントを通知するために使用されます。 - -優先度が MAXHIGHDEFAULT の通知を LED 点灯するようにし、優先度の低い通知(LOWMIN)は点灯しないようにしてください。 - - -

      - -

      ユーザーによる通知の制御が LED にも及ぶようにしてください。DEFAULT_LIGHTS を使用すると、LED が白く点灯します。 - -ユーザーが明示的にカスタマイズしない限り、通知では別の色を使用しないでください。 - -

      - -

      ユーザーが気にする通知の作成 -

      - -

      ユーザーに愛されるアプリを開発するためには、通知を入念にデザインすることが重要です。通知はアプリの声を体現するものであり、アプリの個性の一部です。 - - -望まれない通知や重要ではない通知がユーザーの邪魔になったり、アプリへの注目を集める意図が逆にユーザーに不快に思われたりしかねませんので、通知は適切に使用してください。 - - -

      - -

      通知を表示すべきケース

      - -

      ユーザーが楽しんで使えるアプリケーションを開発するには、ユーザーの注目や関心は保護すべきリソースであるという認識が重要です。 - -Android の通知システムは、ユーザーの注意に対する通知のインパクトを最小限に抑える設計になっていますが、通知がユーザーのタスクフローに割り込むという事実を意識することがやはり重要です。通知を盛り込む予定の場合は、それが割り込みに値するほど重要かどうかを自問してください。 - - - - - - -確信が持てない場合は、ユーザーがアプリの通知設定を使用して通知をコントロールできるようにするか、通知のフラグを LOWMIN に設定してユーザーがしている別のことを邪魔しないようにします。 - - - -

      - - -

      - 急を要する通知の例 -

      - -

      概して、適切に振る舞うアプリは話しかけられたときだけ口を開きますが、求められていない通知でユーザーの作業に割り込むことにメリットがあるケースもいくつか存在します。 -

      - -

      通知は主に急を要するイベントで、特に他人が絡む同期イベントで使用します。 -たとえば、受信チャットはリアルタイムの同期コミュニケーションです。 - -他人が応答を能動的に待っています。 -カレンダー イベントも、通知でユーザーの注目を引くタイミングに関する好例です。なぜなら、そうしたイベントは差し迫っており、往々にして他人が絡みます。 - - -

      - -

      通知を表示すべきでないケース -

      - -
      - -
      - -

      以上を除く多くの場合、通知の使用は適切ではありません。

      - -
        -
      • 明示的にユーザー宛てではない情報や、それほど急を要さない情報は、ユーザーへの通知を避けます。 - -たとえば、ソーシャル ネットワーク経由で流れてくる非同期の間接的なアップデートは、概してリアルタイムの割り込みにふさわしくありません。 - - -それらに本当に関心のあるユーザーが選択できるようにします。 -
      • -
      • 関連する新しい情報が現在画面に表示されている場合は、通知を作成しないようにします。 -その代わり、アプリケーションそのものの UI を使用して、ユーザーに情報をコンテキスト内で直接通知します。 - - - たとえば、チャット アプリケーションは、ユーザーが他のユーザーとチャットしている最中にシステム通知を作成しないようにします。 -
      • -
      • 情報の保存や同期、アプリケーションのアップデートなど、低レベルの技術的な通知については、アプリやシステムがユーザーの介入なしに問題を解決できる場合は割り込まないようにします。 - -
      • -
      • アプリケーションがユーザーの介入なしにエラーから復旧できる場合は、そのようなエラーの通知で割り込まないでください。 - -
      • -
      • 通知にふさわしい内容がなく、アプリを宣伝するだけの通知は、作成しないようにします。通知は、有益でタイムリーな新しい情報を提供するものであり、アプリを起動するためだけには使用しないでください。 - - - -
      • -
      • ブランドをユーザーの目の前に提示するだけの表面的な通知を作成しないようにします。 - - そうした通知はユーザーにフラストレーションを与え、アプリが使われなくなります。アップデートされた情報を少しだけ提供し、ユーザーをアプリにつなぎ止める最適な方法は、ホームスクリーンに配置できるウィジェットを開発することです。 - - - - -
      • -
      - -

      通知の操作 -

      - -

      通知はステータスバーにアイコンとして示され、通知ドロワーを開いてアクセスできます。 - -

      - -

      通知をタップすると関連アプリが開き、その通知に対応する詳細なコンテンツに移動します。通知上で左か右にスワイプされた通知は、ドロワーから削除されます。 - -

      - -

      進行中通知

      -
      - -

      - 音楽再生の進行中通知 -

      -
      -

      進行中通知は、バックグラウンドで進行中の処理に関する情報をユーザーに伝えます。たとえば、音楽プレイヤーは通知システムで現在再生中のトラックを示し、ユーザーが再生を停止するまで通知を継続します。 - - - -進行中通知には、ファイルのダウンロードやビデオのエンコードなど、時間のかかるタスクに対するフィードバックをユーザーに示すこともできます。 - -ユーザーは、進行中通知を通知ドロワーから手動では削除できません。 -

      - -

      メディア再生

      -

      Android 5.0 では、廃止された {@link android.media.RemoteControlClient} クラスの転送コントロールがロック画面に表示されません。 -ただし、通知が表示されるため、ユーザーがロック状態から再生をコントロールするための主な手段は、現状では各アプリの再生通知です。 - -この動作により、アプリは表示するボタンとその表示形態についてより多くをコントロールでき、画面がロックされているかどうかによらない一貫した操作感をユーザーに提供できます。 - - -

      - -

      ダイアログとトースト -

      - -

      アプリが画面上に表示されていないときにダイアログやトーストを作成しないようにしてください。 -ダイアログやトーストの表示は、アプリでのアクションに対するユーザーへの即座の応答のみにします。ダイアログやトーストの使用の目安については、確認と通知をご覧ください。 - - - -

      - -

      評価と並べ替え

      - -

      通知はニュースであるため、基本的には新しい順に表示され、アプリが通知に指定した優先度に基づき特別な配慮がなされます。 - - -

      - -

      通知はロック画面の重要な一部であり、端末のディスプレイがオンになるたび前面に出ます。 - -ロック画面のスペースは限られているため、もっとも緊急か重要な通知を識別することが何より重要になります。 - -この理由から、Android では洗練された通知並べ替えアルゴリズムを採用しており、その中で以下を考慮しています。 - -

      - -
        -
      • タイムスタンプと、アプリが指定した優先度。
      • -
      • その通知が最近ユーザーに音または振動で配信されたかどうか。 -(つまり、電話が音を立てるだけの場合、ユーザーが「何が起こったのか」を知りたくなったら、ロック画面はそれに一目でわかる答えを示すべきです)。 - - -
      • -
      • {@link android.app.Notification#EXTRA_PEOPLE} を使用して通知に添付された人、特にその人が「お気に入り」の連絡先かどうか。 -
      • -
      - -

      この並べ替え機能を最大限に生かすには、リストにおける特定の位置付けを狙うのではなく、ユーザーの操作感に注目します。 - -

      - - - -

      Gmail 通知の優先度はデフォルトであり、そのため Hangouts などのインスタントメッセージ アプリからのメッセージの下に並びますが、新しいメッセージが来たときは一時的にそれより先に表示されます。 - - - - -

      - - -

      ロック画面上

      - -

      通知はロック画面に表示されるため、ユーザーのプライバシーはとりわけ重要な考慮対象です。 - -通知には機密性の高い情報が含まれることが多く、端末を手に取ってディスプレイをオンにした誰にでも見られるようにすべきではありません。 - -

      - -
        -
      • セキュリティ保護されたロック画面(PIN、パターン、パスワードなど)を持つ端末の場合、インターフェースには公開部分と秘密部分があります。 -公開インターフェースはセキュリティ保護されたロック画面に表示でき、誰でも見られます。 -秘密インターフェースはロック画面の背後にある世界で、ユーザーが端末にサインインして初めて表示されます。 -
      • -
      - -

      セキュリティ保護されたロック画面に表示される情報のユーザー コントロール

      -
      - -

      - ロック画面上の通知。コンテンツはユーザーが端末をロック解除した後に表示されます。 -

      -
      - -

      セキュリティ保護されたロック画面をセットアップする際、ユーザーはセキュリティ保護されたロック画面には表示しない機密性の高い情報を選ぶことができます。 -その場合、システム UI は通知の可視性レベルを考慮して、表示しても問題ない情報を識別します。 - -

      -

      可視性レベルをコントロールするには、Notification.Builder.setVisibility() を呼び出し、次の値のどれかを指定します。 - -

      - -
        -
      • VISIBILITY_PUBLIC。通知の内容がすべて表示されます。 - - 可視性レベルが指定されていない場合は、これがシステム デフォルトです。
      • -
      • VISIBILITY_PRIVATE。ロック画面に、その通知の存在に関する基本情報、たとえば通知のアイコンやそれを提示したアプリ名などを表示します。 - -通知のその他の詳細は表示されません。いくつか留意すべき点があります。 - -
          -
        • システムがセキュリティ保護されたロック画面に表示するためとして公開バージョンの通知を別に提供する場合は、Notification.publicVersion フィールドに代替 Notification オブジェクトを用意します。 - - - -
        • この設定により、アプリは利便性はあるが個人情報は明かさない編集されたバージョンのコンテンツを作成できるようになります。 -SMS アプリを例に考えて見ましょう。通知には SMS のテキストメッセージ、送信者の名前、連絡先アイコンが含まれています。この通知は VISIBILITY_PRIVATE であるべきですが、publicVersion にも "3 件の新しいメッセージ" のような個人を特定する詳細なしでも利便性のある情報を盛り込めます。 - - - - -
        -
      • -
      • Notification.VISIBILITY_SECRET。必要最小限の情報のみ表示し、通知のアイコンさえありません。 -
      • -
      -

      Android Wear での通知 -

      - -

      通知とそのアクションは、デフォルトで Wear 端末にブリッジされます。デベロッパーは、どの通知が電話から腕時計へ、またはその逆へブリッジするかを制御できます。 - - -また、どのアクションがブリッジするかも制御できます。タップ 1 回では完了しないアクションがアプリに含まれている場合は、そうしたアクションを Wear 通知では隠すか Wear アプリに接続することを検討してください。いずれにしても、ユーザーがアクションを腕時計で完了できるようにします。 - - - - - -

      - -

      通知とアクションのブリッジ

      - -

      電話のような接続状態の端末は、通知を Wear 端末にブリッジして、通知が腕時計に表示されるようにできます。 -同様に、アクションもブリッジして、ユーザーが通知に Wear 端末で直接対処できるようにできます。 -

      - -

      ブリッジする

      - -
        -
      • 新しいインスタントメッセージ
      • -
      • +1、いいね、心拍数のようなタップ 1 回のアクション
      • -
      - - - -

      ブリッジしない

      - -
        -
      • 新着ポッドキャストの通知
      • -
      • 腕時計ではできない機能にマップされたアクション
      • -
      - - - -

      Wear 専用に定義されたアクション

      - -

      Wear でのみできるアクションがいくつかあります。次に例を挙げます。

      - -
        -
      • 「Be right back」 のような定形応答のクイックリスト
      • -
      • 携帯電話で開く
      • -
      • 音声入力画面を起動する 「Comment」 アクションや 「Reply」 アクション
      • -
      • Wear 専用アプリを起動するアクション
      • -
      - - diff --git a/docs/html-intl/intl/ja/distribute/googleplay/about.jd b/docs/html-intl/intl/ja/distribute/googleplay/about.jd index 56eaf2c6d0a7a50edcfcdcd0419d6c1cd3a76e39..6a58cf60e6b663abff9ca13f5b78b89efdfce114 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/about.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/about.jd @@ -6,7 +6,7 @@ page.image=/distribute/images/about-play.jpg @jd:body -
      +

      Google Play について

        diff --git a/docs/html-intl/intl/ja/distribute/googleplay/auto.jd b/docs/html-intl/intl/ja/distribute/googleplay/auto.jd index 0cbf8b1310725f8ad942f212ea1db112d22ff977..bc5a01f8d0da8725369870c1f9ac3283ddcb747c 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/auto.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/auto.jd @@ -160,4 +160,4 @@ page.metaDescription=アプリとコンテンツを Android Auto に配布しま data-query="collection:autolanding" data-cardSizes="9x6, 6x3x2" data-maxResults="6"> -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/developer-console.jd b/docs/html-intl/intl/ja/distribute/googleplay/developer-console.jd index 8dd562d79a16a0809da8f1371a78b5ea9b8357c7..29e4145a7d37d92cb4e03af3d296f06594353e58 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/developer-console.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/developer-console.jd @@ -5,7 +5,7 @@ Xnonavpage=true @jd:body -
      +

      公開機能

        diff --git a/docs/html-intl/intl/ja/distribute/googleplay/families/about.jd b/docs/html-intl/intl/ja/distribute/googleplay/families/about.jd index 53258de6419cea9f18096999d0101016ddae0d20..54c4f34da34ba099647ae7402257edcca0fb7d17 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/families/about.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/families/about.jd @@ -36,4 +36,4 @@ page.tags="families" \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/families/faq.jd b/docs/html-intl/intl/ja/distribute/googleplay/families/faq.jd index 206429c654427825db0137966be3ca953d33ac6e..da877f9a219126b99345b0c5d12f6012b8689744 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/families/faq.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/families/faq.jd @@ -10,7 +10,7 @@ page.metaDescription=Designed for Families に関する質問と回答 font-weight:bold; } - +

        本書の内容

        @@ -106,7 +106,7 @@ page.metaDescription=Designed for Families に関する質問と回答
        - Designed for Families プログラムにオプトインすると、Google Play はアプリを審査し、ファミリー層に適切かどうか確認します。アプリがすべてのプログラム要件に準拠している場合、公開までの時間は通常よりも長くかかることはないはずです。ただし、Designed for Families 審査で却下された場合、アプリの公開が遅れる可能性があります。 + Designed for Families プログラムにオプトインすると、Google Play はアプリを審査し、ファミリー層に適切かどうか確認します。アプリがすべてのプログラム要件に準拠している場合、公開までの時間は通常よりも長くかかることはないはずです。ただし、Designed for Families 審査で却下された場合、アプリの公開が遅れる可能性があります。
        diff --git a/docs/html-intl/intl/ja/distribute/googleplay/families/start.jd b/docs/html-intl/intl/ja/distribute/googleplay/families/start.jd index e8e9ee59af41b3286782f9a74452eb134a39fa50..023e2c17e06d15953a47f56c5715e17551df35e6 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/families/start.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/families/start.jd @@ -51,7 +51,7 @@ page.metaDescription=ほんの数ステップで Designed for Families に参加

        - 注: Designed for Families プログラムで公開されたアプリは Google Play ですべてのユーザーも利用できます。 + 注: Designed for Families プログラムで公開されたアプリは Google Play ですべてのユーザーも利用できます。

        @@ -67,4 +67,4 @@ page.metaDescription=ほんの数ステップで Designed for Families に参加

        \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/guide.jd b/docs/html-intl/intl/ja/distribute/googleplay/guide.jd index 137c63f6cbe470fe34efb59267da84170e3bc74f..1655017efa03250a0da6b5bf470c47b2e85de013 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/guide.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/guide.jd @@ -54,4 +54,4 @@ page.image=distribute/images/play_dev_guide.png data-query="collection:play_dev_guide" data-cardSizes="9x6" data-maxResults="1"> -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/quality/auto.jd b/docs/html-intl/intl/ja/distribute/googleplay/quality/auto.jd index eda7297741cc1752d77598051e5bb6eab4d6ef8f..2870153fe2d93e91ce334bbbdf862cbe95411ef3 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/quality/auto.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/quality/auto.jd @@ -431,4 +431,4 @@ data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">

      重要: この制限のため、Auto サポートのプロトタイプの作成に、実働 APK を使用してはなりません。 -

      \ No newline at end of file +

      \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/quality/core.jd b/docs/html-intl/intl/ja/distribute/googleplay/quality/core.jd index 5229aa7c829fc531913c73cc4eaa3bfa4149b139..ddf41155b082b1f4cb7f534c15593b1a249f232e 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/quality/core.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/quality/core.jd @@ -13,7 +13,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
    • Google Play
    • - +

      テスト

      1. テスト環境の設定
      2. @@ -25,7 +25,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
      3. タブレットのアプリ品質
      4. アプリを最適化する
      - +
      @@ -70,7 +70,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg ID - + 説明 @@ -1011,4 +1011,4 @@ data-cardsizes="6x3,6x3,6x3,6x3,6x3,6x3" data-maxresults="6">

      {@link android.os.StrictMode.ThreadPolicy.Builder#penaltyFlashScreen() penaltyFlashScreen()} を使用してThreadPolicy に対するポリシー違反の視覚通知を有効にします。 -

      \ No newline at end of file +

      \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/quality/tablets.jd b/docs/html-intl/intl/ja/distribute/googleplay/quality/tablets.jd index f0cc133c8bda7da06912ac93888ab5692ccd0c63..dbdabc21d57eccf413f1f0c08aea942b834b8c51 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/quality/tablets.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/quality/tablets.jd @@ -46,7 +46,7 @@ Xnonavpage=true

      1.タブレット アプリの基本的な品質テスト

      -

      タブレット アプリの優れたエクスペリエンスを提供する最初のステップは、アプリがターゲットとしているすべてのデバイスとフォーム ファクタに対して、アプリの中核品質基準に適合していることを確認することです。詳細については、アプリの中核品質に関するガイドラインを参照してください。 +

      タブレット アプリの優れたエクスペリエンスを提供する最初のステップは、アプリがターゲットとしているすべてのデバイスとフォーム ファクタに対して、アプリの中核品質基準に適合していることを確認することです。詳細については、アプリの中核品質に関するガイドラインを参照してください。

      diff --git a/docs/html-intl/intl/ja/distribute/googleplay/quality/wear.jd b/docs/html-intl/intl/ja/distribute/googleplay/quality/wear.jd index 9fa4439900115889f9450800fc747b103e4e366c..1d92d8c4050b08f4fcae1ee664130373a34a4540 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/quality/wear.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/quality/wear.jd @@ -395,4 +395,4 @@ data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">

      はい。上記の要件は、アプリが Google Play で Android Wear アプリとして識別され、Android Wear ユーザーが発見しやすくなるかどうかのみを判断するものです。アプリが Wear アプリとして承認されなくても、電話やタブレットなどの他のデバイス タイプで利用可能です。ウェアラブル端末へのインストールも可能です。 -

      \ No newline at end of file +

      \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/start.jd b/docs/html-intl/intl/ja/distribute/googleplay/start.jd index 3c5e548624aee0f454491ab6ac414e686f197e67..93aee136da0588a14d5441d6a7cdbb10da77395f 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/start.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/start.jd @@ -134,4 +134,4 @@ href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=e data-query="collection:distribute/googleplay/gettingstarted" data-sortOrder="-timestamp" data-cardSizes="9x3" - data-maxResults="6">
    \ No newline at end of file + data-maxResults="6">
    \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/googleplay/tv.jd b/docs/html-intl/intl/ja/distribute/googleplay/tv.jd index 1a7558de28abfc4f0d41d11fa7751d6d27a5129b..9532bf4277e3d7b73931924f788df1c469dce469 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/tv.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/tv.jd @@ -173,7 +173,7 @@ page.metaDescription=アプリ、ゲーム、コンテンツを Android TV に

    5.審査と承認をトラッキングする

    - アプリが上述の Android TV 向けの技術上の基準と品質基準に適合すると、ユーザーはそのアプリを Android TV で活用できるようになります。アプリが基準を満たしていない場合、デベロッパー アカウント アドレスに送られた通知メールを受け取ります。このメールには対処が必要な領域の要約が記載されています。必要な調整を行ったら、デベロッパー コンソールにアプリの新規バージョンをアップロードできます。 + アプリが上述の Android TV 向けの技術上の基準と品質基準に適合すると、ユーザーはそのアプリを Android TV で活用できるようになります。アプリが基準を満たしていない場合、デベロッパー アカウント アドレスに送られた通知メールを受け取ります。このメールには対処が必要な領域の要約が記載されています。必要な調整を行ったら、デベロッパー コンソールにアプリの新規バージョンをアップロードできます。

    @@ -190,7 +190,7 @@ page.metaDescription=アプリ、ゲーム、コンテンツを Android TV に

  • - 承認 — アプリが審査され、承認されました。アプリは Android TV ユーザーが直接利用できるようになります。 + 承認 — アプリが審査され、承認されました。アプリは Android TV ユーザーが直接利用できるようになります。
  • @@ -207,4 +207,4 @@ page.metaDescription=アプリ、ゲーム、コンテンツを Android TV に data-query="collection:tvlanding" data-cardSizes="9x6, 6x3x2" data-maxResults="6"> - + diff --git a/docs/html-intl/intl/ja/distribute/googleplay/wear.jd b/docs/html-intl/intl/ja/distribute/googleplay/wear.jd index 4e0196e8a80571d6e91c46d72d0a132d5c996a6e..85cffca6d97fcec8fbebab858c2a62e0331e0dc1 100644 --- a/docs/html-intl/intl/ja/distribute/googleplay/wear.jd +++ b/docs/html-intl/intl/ja/distribute/googleplay/wear.jd @@ -196,4 +196,4 @@ page.metaDescription=アプリ、ゲーム、コンテンツを Android Wear に data-query="collection:wearlanding" data-cardSizes="6x2" data-maxResults="3"> - \ No newline at end of file + \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/tools/launch-checklist.jd b/docs/html-intl/intl/ja/distribute/tools/launch-checklist.jd index b1394f8c950eb3a147460a3723e7f9dc00da100c..a6f1a7f8b6f23507b7441b6627c91318e12b9d12 100644 --- a/docs/html-intl/intl/ja/distribute/tools/launch-checklist.jd +++ b/docs/html-intl/intl/ja/distribute/tools/launch-checklist.jd @@ -789,4 +789,4 @@ data-maxresults="6"> data-query="collection:distribute/toolsreference/launchchecklist/afterlaunch" data-sortOrder="-timestamp" data-cardSizes="9x3,9x3,9x3,9x3,9x3,9x3" - data-maxResults="6"> \ No newline at end of file + data-maxResults="6"> \ No newline at end of file diff --git a/docs/html-intl/intl/ja/distribute/tools/localization-checklist.jd b/docs/html-intl/intl/ja/distribute/tools/localization-checklist.jd index b2c797b437ab5b5f80fced0fddbe5e15b877c3de..5bb9fe0359a6baf4339e81fef2177b92b388f64e 100644 --- a/docs/html-intl/intl/ja/distribute/tools/localization-checklist.jd +++ b/docs/html-intl/intl/ja/distribute/tools/localization-checklist.jd @@ -2,7 +2,7 @@ page.title=ローカライズのチェックリスト page.metaDescription=Android と Google Play から提供される世界中のユーザーを活用します。このチェックリストを読んで、お客様の製品を世界中のマーケットに提供する方法の概要を把握してください。 meta.tags="localizing, publishing, disttools" page.tags="local, l10n, translation, language" -page.image=/distribute/images/localization-checklist.jpg +page.image=/distribute/images/localization-checklist.jpg @jd:body @@ -713,4 +713,4 @@ data-maxresults="6"> data-query="collection:distribute/toolsreference/localizationchecklist/supportlaunch" data-sortOrder="-timestamp" data-cardSizes="9x3,9x3,6x3,9x3,9x3,9x3" - data-maxResults="6"> \ No newline at end of file + data-maxResults="6"> \ No newline at end of file diff --git a/docs/html-intl/intl/ja/google/play/filters.jd b/docs/html-intl/intl/ja/google/play/filters.jd index 5ab6336eac65b393e85949dd9b17a2f2a496c06f..eed069f74b9795b69a06cd0e809a50fbe19de1a6 100644 --- a/docs/html-intl/intl/ja/google/play/filters.jd +++ b/docs/html-intl/intl/ja/google/play/filters.jd @@ -263,4 +263,4 @@ href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-featur

    警告: 同じアプリに複数の APK を公開することは拡張機能とみなされます。大部分のアプリは、広範囲のデバイス設定をサポートする APK を 1 つだけ公開すべきです。複数の APK を公開する場合、フィルタ固有のルールに従う必要があります。また、設定ごとに適切なアップデート パスを確保するため、各 APK のバージョン コードに特別な注意を払う必要があります。

    -

    Google Play で複数の APK を公開する方法について詳しくは、複数の APK サポート(Multiple APK Support)をご覧ください。

    \ No newline at end of file +

    Google Play で複数の APK を公開する方法について詳しくは、複数の APK サポート(Multiple APK Support)をご覧ください。

    \ No newline at end of file diff --git a/docs/html-intl/intl/ja/guide/components/activities.jd b/docs/html-intl/intl/ja/guide/components/activities.jd index 9b06d2c838bbc93e2a1cc7f94b962aaedcfafc55..227f7f4b4083859c2bcce1437a1ea9fd579d39ef 100644 --- a/docs/html-intl/intl/ja/guide/components/activities.jd +++ b/docs/html-intl/intl/ja/guide/components/activities.jd @@ -53,7 +53,7 @@ page.tags=activity,intent

    通常、アプリケーションは複数のアクティビティで構成されており、各アプリケーションはそれぞれ緩やかにつながっています。 一般的には、アプリケーションの 1 つのアクティビティが「メイン」アクティビティとして指定され、ユーザーが初めてアプリケーションを起動したときに表示されるのがこのアクティビティになります。 その後、各アクティビティで別のアクティビティを開始して別の操作を実行できます。 -新しいアクティビティの開始時には、前のアクティビティは停止しますが、そのアクティビティはシステムによってスタック(「バックスタック」)に維持されます +新しいアクティビティの開始時には、前のアクティビティは停止しますが、そのアクティビティはシステムによってスタック(「バックスタック」)に維持されます 新しいアクティビティが開始すると、それがバックスタックに入ってユーザーに表示されます。 バックスタックは「後入れ先出し」の基本的なスタック メカニズムを順守するため、ユーザーが現在のアクティビティを完了して [戻る] ボタンを押すと、そのアクティビティはスタックから消え(破棄され)、前のアクティビティが再開します。 diff --git a/docs/html-intl/intl/ja/guide/components/fragments.jd b/docs/html-intl/intl/ja/guide/components/fragments.jd index 31fb7f5020b22bdf40a70f8a8ec871c5ccebe218..7f9096393eda7588c5ba2a2582f5d6e62eb7788d 100644 --- a/docs/html-intl/intl/ja/guide/components/fragments.jd +++ b/docs/html-intl/intl/ja/guide/components/fragments.jd @@ -36,7 +36,7 @@ parent.link=activities.html

  • {@link android.app.FragmentManager}
  • {@link android.app.FragmentTransaction}
  • - +

    関連ドキュメント

    1. Building a Dynamic UI with Fragments
    2. @@ -332,7 +332,7 @@ fragmentTransaction.add(R.id.fragment_container, fragment); fragmentTransaction.commit(); -

      {@link android.app.FragmentTransaction#add(int,Fragment) add()} に渡される最初の引数はフラグメントを配置する {@link android.view.ViewGroup} でリソース ID で指定されており、2 つ目のパラメータは追加するフラグメントです。 +

      {@link android.app.FragmentTransaction#add(int,Fragment) add()} に渡される最初の引数はフラグメントを配置する {@link android.view.ViewGroup} でリソース ID で指定されており、2 つ目のパラメータは追加するフラグメントです。

      {@link android.app.FragmentTransaction} で変更を加えたら、{@link android.app.FragmentTransaction#commit} を呼び出して変更を適用する必要があります。 @@ -378,7 +378,7 @@ FragmentRetainInstance.java} のサンプルでシステムに <sdk_roo

    3. {@link android.app.FragmentManager#findFragmentById findFragmentById()}(アクティビティ レイアウトで UI を提供するフラグメントの場合)や {@link android.app.FragmentManager#findFragmentByTag findFragmentByTag()}(UI を提供しないフラグメントの場合)を使用して、アクティビティにあるフラグメントを取得する。 -
    4. +
    5. {@link android.app.FragmentManager#popBackStack()} を使用してフラグメントをバックスタックから取り出す(ユーザーによる [戻る] コマンドをシミュレートする)。
    6. {@link @@ -785,7 +785,7 @@ android.widget.FrameLayout} にフラグメントを追加する)、新しい

      2 つ目のフラグメントである {@code DetailsFragment} は、{@code TitlesFragment} のリストで選択された劇のあらすじを表示します。

      - + {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}

      {@code TitlesFragment} クラスで説明したように、ユーザーがリストアイテムをクリックしたときに、現在のレイアウトに{@code R.id.details} ビュー({@code DetailsFragment} が属する場所)が含まれていない場合、アプリケーションは {@code DetailsActivity} のアクティビティを開始してアイテムのコンテンツを表示します。 @@ -798,7 +798,7 @@ android.widget.FrameLayout} にフラグメントを追加する)、新しい {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details_activity} - +

      構成が横方向の場合はアクティビティは自ら終了するため、メイン アクティビティが引き継いで {@code DetailsFragment} を {@code TitlesFragment} の横に表示できます。これは、ユーザーが縦方向のときに {@code DetailsActivity} を開始し、その後横方向に回転した(ここで現在のアクティビティが再開される)ときに起こることがあります。 diff --git a/docs/html-intl/intl/ja/guide/components/fundamentals.jd b/docs/html-intl/intl/ja/guide/components/fundamentals.jd index 46e98689a3ecc23aa6955577a8811ade1acedd0b..e1a26cd9c577694c5013dc7f5624bbf66bc4c5b1 100644 --- a/docs/html-intl/intl/ja/guide/components/fundamentals.jd +++ b/docs/html-intl/intl/ja/guide/components/fundamentals.jd @@ -379,7 +379,7 @@ startActivity()} に渡す場合、ユーザーがメールを下書きして送

      たとえば、アプリでカメラを使用する必要があり、Android 2.1 で採用された API(API レベル 7)を使用する場合、次のようにマニフェスト ファイルでそれを要件として宣言する必要があります。 -

      +

       <manifest ... >
      diff --git a/docs/html-intl/intl/ja/guide/components/index.jd b/docs/html-intl/intl/ja/guide/components/index.jd
      index 803f99b2ebd213303c925f71be5d3c3d1d6a95d3..f4801c945970160cabf2227ad447d0e1bc784b09 100644
      --- a/docs/html-intl/intl/ja/guide/components/index.jd
      +++ b/docs/html-intl/intl/ja/guide/components/index.jd
      @@ -11,7 +11,7 @@ page.image=images/develop/app_components.png
       
         

      ブログの記事

      - +

      DialogFragments の使用

      この投稿では、DialogFragments を v4 サポート ライブラリで使用して(Honeycomb 以前の端末での下方互換性のため)ダイアログを編集したり、インターフェースを使用して呼び出し元の Activity に結果を返したりする方法について説明します。

      @@ -21,7 +21,7 @@ page.image=images/develop/app_components.png

      すべてに Fragments を

      本日、同じ Fragments API を利用できる静的なライブラリが公開され、Android 1.6 以降でもフラグメントを使用してタブレット対応のユーザー インターフェースを作成できるようになりました。

      - +

      マルチスレッドでパフォーマンス向上

      応答の速いアプリケーションを作成する上で重要なのは、メイン UI スレッドが最小限の作業を行うようにすることです。 @@ -32,7 +32,7 @@ page.image=images/develop/app_components.png

    - +

    キークラス

    1. {@link android.app.LoaderManager}
    2. {@link android.content.Loader}
    3. -
    - + +

    関連サンプル

    1. @@ -51,7 +51,7 @@ android.app.Fragment} で使用できる。
    2. 再度データを問い合わせる必要がない。 - +

      Loader API の概要

      アプリケーションでローダを使用するのに必要になりそうなクラスやインターフェースは複数あります。 @@ -129,7 +129,7 @@ android.content.ContentProvider} でサポートされているデータをロ

    3. {@link android.app.LoaderManager.LoaderCallbacks} の実装。ここで、新しいローダを作成して既存のローダへの参照を管理します。 -
    4. +
    5. {@link android.widget.SimpleCursorAdapter} などのローダのデータを表示する方法。
    6. {@link android.content.CursorLoader} を使用するときの、{@link android.content.ContentProvider} などのデータ ソース。 @@ -140,7 +140,7 @@ android.widget.SimpleCursorAdapter} などのローダのデータを表示す

      {@link android.app.LoaderManager} は 1 つ以上の {@link android.content.Loader} インスタンスを {@link android.app.Activity} や {@link android.app.Fragment} 内で管理します。 1 つのアクティビティやフラグメントごとに、{@link -android.app.LoaderManager} は 1 つだけ存在します。

      +android.app.LoaderManager} は 1 つだけ存在します。

      通常は、アクティビティの {@link android.app.Activity#onCreate onCreate()} メソッドか、フラグメントの {@link android.app.Fragment#onActivityCreated onActivityCreated()} メソッド内で {@link android.content.Loader} を初期化します。 @@ -157,13 +157,13 @@ getLoaderManager().initLoader(0, null, this);

      • ローダを識別する一意の ID。この例では、ID は 0 です。
      • ローダの構築時に提供する任意の引数(この例では null)。 -
      • +
      • {@link android.app.LoaderManager} がローダのイベントを報告する際に呼び出す {@link android.app.LoaderManager.LoaderCallbacks} の実装。 この例では、ローカルクラスが {@link android.app.LoaderManager.LoaderCallbacks} インターフェースを実装するため、自身の {@code this} に参照を渡します。 -
      • +

      {@link android.app.LoaderManager#initLoader initLoader()} の呼び出しによって、ローダが初期化され、アクティブになります。 結果には次の 2 つの可能性があります。

      @@ -366,7 +366,7 @@ public void onLoaderReset(Loader<Cursor> loader) { android.app.Fragment} の完全な実装の例です。 {@link android.content.CursorLoader} を使用してプロバイダへのクエリを管理しています。

      - +

      この例にあるように、アプリケーションがユーザーの連絡先にアクセスするには、マニフェストに {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS} の許可を含める必要があります。

      diff --git a/docs/html-intl/intl/ja/guide/components/processes-and-threads.jd b/docs/html-intl/intl/ja/guide/components/processes-and-threads.jd index 691a5f4718801cce755f073b570a3fd273cf6cfb..ae364113e1e685fbf81f97146b142241377625a2 100644 --- a/docs/html-intl/intl/ja/guide/components/processes-and-threads.jd +++ b/docs/html-intl/intl/ja/guide/components/processes-and-threads.jd @@ -319,7 +319,7 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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) { diff --git a/docs/html-intl/intl/ja/preview/j8-jack.jd b/docs/html-intl/intl/ja/guide/platform/j8-jack.jd similarity index 100% rename from docs/html-intl/intl/ja/preview/j8-jack.jd rename to docs/html-intl/intl/ja/guide/platform/j8-jack.jd diff --git a/docs/html-intl/intl/ja/guide/publishing/app-signing.jd b/docs/html-intl/intl/ja/guide/publishing/app-signing.jd index 2d2acfa2f8c3c156e3c6067ecd08d9dbd86c69c3..efe66f453c9f25bef07375e1c3096a6530ffec06 100644 --- a/docs/html-intl/intl/ja/guide/publishing/app-signing.jd +++ b/docs/html-intl/intl/ja/guide/publishing/app-signing.jd @@ -53,7 +53,7 @@ page.title=アプリケーションへの署名
    - +
  • 同期アダプタ
  • @@ -113,14 +113,14 @@ URI の形式は <class>.CONTENT_URI です。

    {@link android.provider.CalendarContract.Calendars}

    - + このテーブルは、該当するカレンダー固有の情報を保持します。 各行には、名前、色、同期情報など、1 つのカレンダーに関する詳細が格納されます。 {@link android.provider.CalendarContract.Events} - + このテーブルは、該当するイベント固有の情報を保持します。 各行には、1 つのイベントに関する情報が格納されます—イベントのタイトル、場所、開始時刻、終了時刻などが該当します。 @@ -132,7 +132,7 @@ URI の形式は <class>.CONTENT_URI です。 {@link android.provider.CalendarContract.Instances} - + このテーブルは、あるイベントの発生ごとの開始時刻と終了時刻を保持します。 各行は、イベントの発生 1 回を表します。 単発イベントには、イベントのインスタンスが 1 対 1 で対応します。 @@ -141,7 +141,7 @@ URI の形式は <class>.CONTENT_URI です。 {@link android.provider.CalendarContract.Attendees} - + このテーブルは、イベントの参加者(ゲスト)の情報を保持します。 各行は、1 回のイベントの 1 人のゲストを表します。 ゲストのタイプと、ゲストのイベントへの出欠の回答を指定します。 @@ -149,7 +149,7 @@ URI の形式は <class>.CONTENT_URI です。 {@link android.provider.CalendarContract.Reminders} - + このテーブルは、アラートや通知のデータを保持します。 各行は、1 回のイベントの 1 つのアラートを表します。1 つのイベントが複数のリマインダーを持つことができます。 1 イベントあたりの最大リマインダー数は {@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS} で指定され、指定されたカレンダーを所有する同期アダプタによって設定されます。 @@ -159,7 +159,7 @@ URI の形式は <class>.CONTENT_URI です。 リマインダーは、イベント開始前の分単位で指定され、ユーザーに注意喚起する手段を示す情報を保持します。 - +

    カレンダー プロバイダ API は、柔軟で効果的な設計になっています。ですが同時に、エンドユーザーにとって使いやすくすることや、カレンダーとそのデータの整合性を保護することが重要です。 @@ -229,7 +229,7 @@ URI の形式は <class>.CONTENT_URI です。 {@link android.provider.CalendarContract.Calendars#VISIBLE} - + カレンダーが表示対象として選択されているかどうかを示すブール値。値 0 は、このカレンダーに関連付けられているイベントを表示しないことを示します。 値 1 は、このカレンダーに関連付けられているイベントを表示することを示します。 @@ -240,7 +240,7 @@ URI の形式は <class>.CONTENT_URI です。 {@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS} - + カレンダーを同期してそのイベントを端末に格納するかどうかを示すブール値。 値 0 は、このカレンダーを同期せず、イベントを端末に格納しないことを指定します。 値 1 は、このカレンダーのイベントを同期し、イベントを端末に格納することを指定します。 @@ -268,13 +268,13 @@ public static final String[] EVENT_PROJECTION = new String[] { Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3; - +

    +

    この例の次の部分では、クエリを作成します。クエリの条件は selection に指定しています。 @@ -308,38 +308,38 @@ private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;

    // Run query
     Cursor cur = null;
     ContentResolver cr = getContentResolver();
    -Uri uri = Calendars.CONTENT_URI;   
    -String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    +Uri uri = Calendars.CONTENT_URI;
    +String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                             + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                             + Calendars.OWNER_ACCOUNT + " = ?))";
     String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
    -        "sampleuser@gmail.com"}; 
    -// Submit the query and get a Cursor object back. 
    +        "sampleuser@gmail.com"};
    +// Submit the query and get a Cursor object back.
     cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

    次のセクションでは、カーソルを使用して結果セットをステップ単位で移動します。例の冒頭で設定した定数を使用して各フィールドの値を返します。

    - +
    // Use the cursor to step through the returned records
     while (cur.moveToNext()) {
         long calID = 0;
         String displayName = null;
         String accountName = null;
         String ownerName = null;
    -      
    +
         // Get the field values
         calID = cur.getLong(PROJECTION_ID_INDEX);
         displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
         accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
         ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
    -              
    +
         // Do something with the values...
     
        ...
     }
     
    - +

    カレンダーの変更

    カレンダーのアップデートを実行する場合、カレンダーの {@link android.provider.BaseColumns#_ID} を、URI({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})の末尾に追加された ID として、または最初の selection 項目として指定できます。 @@ -434,7 +434,7 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows); {@link android.provider.CalendarContract.EventsColumns#DURATION} - + RFC5545 形式でのイベントの期間。たとえば、"PT1H" という値はイベントが 1 時間であること、"P2W" という値は期間が 2 週間であることを示します。 @@ -444,24 +444,24 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows); {@link android.provider.CalendarContract.EventsColumns#ALL_DAY} - + 値 1 は、そのイベントがローカルのタイムゾーンで定義された終日を占めることを示します。 値 0 は、1 日のどこかで始まって終わる定例のイベントであることを示します。 - + - - + + {@link android.provider.CalendarContract.EventsColumns#RRULE} - + イベント形式の繰り返し発生ルール。たとえば、"FREQ=WEEKLY;COUNT=10;WKST=SU" のようになります。 その他の例については、こちらをご覧ください。 - + - + {@link android.provider.CalendarContract.EventsColumns#RDATE} イベントの繰り返し発生日。通常、{@link android.provider.CalendarContract.EventsColumns#RDATE} は {@link android.provider.CalendarContract.EventsColumns#RRULE} と組み合わせて、繰り返し発生全体を定義するのに使用します。 @@ -470,13 +470,13 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows); 詳細については、RFC5545 の仕様をご覧ください。 - + {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY} - + このイベントを埋まっている時間に数えるか、それともスケジュールのやり直しが利く空き時間とみなすか。 - + {@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY} @@ -514,11 +514,11 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows); - +

  • 繰り返されないイベントには、{@link android.provider.CalendarContract.EventsColumns#DTEND} を含める必要があります。
  • - - + +
  • 繰り返されるイベントには、{@link android.provider.CalendarContract.EventsColumns#RRULE} と {@link android.provider.CalendarContract.EventsColumns#RDATE} に加えて {@link android.provider.CalendarContract.EventsColumns#DURATION} を含める必要があります。 @@ -528,7 +528,7 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows);
  • - +

    イベントの挿入の例を次に示します。簡潔にするため、この例は UI スレッドで実行されています。 @@ -539,8 +539,8 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows);

     long calID = 3;
    -long startMillis = 0; 
    -long endMillis = 0;     
    +long startMillis = 0;
    +long endMillis = 0;
     Calendar beginTime = Calendar.getInstance();
     beginTime.set(2012, 9, 14, 7, 30);
     startMillis = beginTime.getTimeInMillis();
    @@ -561,7 +561,7 @@ Uri uri = cr.insert(Events.CONTENT_URI, values);
     
     // get the event ID that is the last element in the Uri
     long eventID = Long.parseLong(uri.getLastPathSegment());
    -// 
    +//
     // ... do something with event ID
     //
     //
    @@ -598,7 +598,7 @@ ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event -values.put(Events.TITLE, "Kickboxing"); +values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows); @@ -625,7 +625,7 @@ ContentValues values = new ContentValues(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().delete(deleteUri, null, null); -Log.i(DEBUG_TAG, "Rows deleted: " + rows); +Log.i(DEBUG_TAG, "Rows deleted: " + rows);

    Attendees テーブル

    @@ -637,7 +637,7 @@ Log.i(DEBUG_TAG, "Rows deleted: " + rows); この {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} は特定のイベントの {@link android.provider.BaseColumns#_ID} と一致している必要があります。 -

    +

    次の表に、書き込み可能なフィールドを示します。 新しい参加者を挿入する際には、ATTENDEE_NAME を除くすべてを含める必要があります。 @@ -801,18 +801,18 @@ Instances テーブルは書き込みできません。イベントの発生を {@link android.provider.CalendarContract.Instances#END_DAY} - + インスタンスの、カレンダーのタイムゾーンにおけるユリウス暦での終了日。 - - + + {@link android.provider.CalendarContract.Instances#END_MINUTE} - + カレンダーのタイムゾーンにおける午前零時を基準にしたインスタンスの終了分。 - + {@link android.provider.CalendarContract.Instances#EVENT_ID} @@ -820,16 +820,16 @@ Instances テーブルは書き込みできません。イベントの発生を {@link android.provider.CalendarContract.Instances#START_DAY} - インスタンスの、カレンダーのタイムゾーンにおけるユリウス暦での開始日。 + インスタンスの、カレンダーのタイムゾーンにおけるユリウス暦での開始日。 {@link android.provider.CalendarContract.Instances#START_MINUTE} - + カレンダーのタイムゾーンにおける午前零時を基準にしたインスタンスの開始分。 - + - + @@ -853,7 +853,7 @@ public static final String[] INSTANCE_PROJECTION = new String[] { Instances.BEGIN, // 1 Instances.TITLE // 2 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; @@ -868,7 +868,7 @@ long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); - + Cursor cur = null; ContentResolver cr = getContentResolver(); @@ -883,28 +883,28 @@ ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query -cur = cr.query(builder.build(), - INSTANCE_PROJECTION, - selection, - selectionArgs, +cur = cr.query(builder.build(), + INSTANCE_PROJECTION, + selection, + selectionArgs, null); - + while (cur.moveToNext()) { String title = null; long eventID = 0; - long beginVal = 0; - + long beginVal = 0; + // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); - - // Do something with the values. - Log.i(DEBUG_TAG, "Event: " + title); + + // Do something with the values. + Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(beginVal); + calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); + Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } } @@ -924,7 +924,7 @@ while (cur.moveToNext()) {

    content://com.android.calendar/time/<ms_since_epoch>

    URI は、{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI} を使用しても参照できます。 このインテントの使用例については、インテントを使用したカレンダー データの参照をご覧ください。 - + <ms_since_epoch> に指定された時刻でカレンダーを開きます。 @@ -935,11 +935,11 @@ while (cur.moveToNext()) {

    content://com.android.calendar/events/<event_id>

    - + URI は、{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} を使用しても参照できます。 このインテントの使用例については、インテントを使用したカレンダー データの参照をご覧ください。 - + <event_id> で指定されたイベントを参照します。 @@ -952,12 +952,12 @@ while (cur.moveToNext()) { {@link android.content.Intent#ACTION_EDIT EDIT}

    content://com.android.calendar/events/<event_id>

    - + URI は、{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} を使用しても参照できます。 このインテントの使用例については、インテントを使用したカレンダー データの編集をご覧ください。 - - + + <event_id> で指定されたイベントを編集します。 @@ -972,11 +972,11 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_INSERT INSERT}

    content://com.android.calendar/events

    - + URI は、{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} を使用しても参照できます。 このインテントの使用例については、インテントを使用したカレンダー データの挿入をご覧ください。 - + イベントを作成します。 @@ -996,7 +996,7 @@ while (cur.moveToNext()) { イベントの名前。 - + {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} イベントの開始時刻(エポックからのミリ秒単位)。 @@ -1004,25 +1004,25 @@ while (cur.moveToNext()) { {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} - + イベントの終了時刻(エポックからのミリ秒単位)。 {@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY CalendarContract.EXTRA_EVENT_ALL_DAY} - + イベントが終日かどうかを示すブール値。使用できる値は true または false です。 {@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION Events.EVENT_LOCATION} - + イベントの場所。 {@link android.provider.CalendarContract.EventsColumns#DESCRIPTION Events.DESCRIPTION} - + イベントの説明。 @@ -1039,16 +1039,16 @@ while (cur.moveToNext()) { {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL Events.ACCESS_LEVEL} - + イベントが公開か非公開か。 {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY Events.AVAILABILITY} - + このイベントを埋まっている時間に数えるか、それともスケジュールのやり直しが利く空き時間とみなすか。 - - + +

    次のセクションでは、これらのインテント使用方法を説明します。

    @@ -1059,14 +1059,14 @@ while (cur.moveToNext()) {

    - +

    このアプローチのアプリケーションをユーザーが実行すると、アプリケーションによってユーザーがカレンダーに誘導されイベントを追加できるようになります。 {@link android.content.Intent#ACTION_INSERT INSERT} インテントは、追加フィールドを使用して、カレンダーに格納されている詳細情報をフォームに自動入力します。 それに対して、ユーザーはイベントのキャンセル、必要に応じたイベントの編集、イベントのカレンダーへの保存ができます。

    - +

    次に示すのは、2012 年 1 月 19 日の午前 7:30 から 午前 8:30 までのイベントをスケジュールするコード スニペットです。 @@ -1075,7 +1075,7 @@ while (cur.moveToNext()) {

    • URI として {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} を指定しています。
    • - +
    • {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} と {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} の各エクストラ フィールドを使用して、イベントの時間をフォームに自動入力しています。 @@ -1083,10 +1083,10 @@ while (cur.moveToNext()) { これらの値は、エポックからの UTC ミリ秒単位であることが必要です。
    • - +
    • {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL} エクストラ フィールドを使用して、参加者をメールアドレスで示したコンマ区切りリストを指定しています。
    • - +
     Calendar beginTime = Calendar.getInstance();
    @@ -1158,12 +1158,12 @@ startActivity(intent);
     
     
    • 同期アダプタは、{@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} を true に設定して、それが同期アダプタであることを示す必要があります。
    • - - + +
    • 同期アダプタは、{@link android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} と {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} をクエリ パラメータとして URI に指定する必要があります。
    • - +
    • 同期アダプタは、アプリケーションやウィジェットより多くの列に書き込みアクセスできます。 たとえば、アプリケーションで変更できるのは、名前、表示名、可視性の設定、カレンダーが同期対象かどうかなど、カレンダーの特性の一部のみです。 diff --git a/docs/html-intl/intl/ja/guide/topics/providers/contacts-provider.jd b/docs/html-intl/intl/ja/guide/topics/providers/contacts-provider.jd index e12b62f222c535c2c9cb4b0aecd4d6c7999eafda..09bc249543db4b6d3c239cc629c2602f05dfcbf7 100644 --- a/docs/html-intl/intl/ja/guide/topics/providers/contacts-provider.jd +++ b/docs/html-intl/intl/ja/guide/topics/providers/contacts-provider.jd @@ -2146,19 +2146,19 @@ startActivity(insertIntent); viewStreamItemPhotoActivity="viewphotostream_activity_name">

    - 含まれているファイル: + 含まれているファイル:

    res/xml/contacts.xml

    - 含めることのできる要素: + 含めることのできる要素:

    <ContactsDataKind>

    - 説明: + 説明:

    ユーザーが連絡先の 1 人をソーシャル ネットワーキングに招待できるようにしたり、ソーシャル ネットワーキング ストリームのどれかがアップデートされたらユーザーに通知したりするための、Android コンポーネントや UI ラベルを宣言します。 @@ -2170,7 +2170,7 @@ startActivity(insertIntent);

    - 属性: + 属性:

    {@code inviteContactActivity}
    @@ -2248,11 +2248,11 @@ Google+ サークルのどれかをクリックすると、そのサークルに android:detailColumn="column_name">

    - 含まれているファイル: + 含まれているファイル:

    <ContactsAccountType>

    - 説明: + 説明:

    この要素は、カスタムデータ行のコンテンツを未加工連絡先の詳細の一部として連絡先アプリケーションに表示させるために使用します。 @@ -2263,7 +2263,7 @@ Google+ サークルのどれかをクリックすると、そのサークルに

    - 属性: + 属性:

    {@code android:mimeType}
    diff --git a/docs/html-intl/intl/ja/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/ja/guide/topics/providers/content-provider-creating.jd index af2181482d33925bfd7bb69e0eade3525b1fee51..b14174fa37c4678d26c6e5559928b33501bd74fd 100644 --- a/docs/html-intl/intl/ja/guide/topics/providers/content-provider-creating.jd +++ b/docs/html-intl/intl/ja/guide/topics/providers/content-provider-creating.jd @@ -377,7 +377,7 @@ BLOB 列内のデータの内容は、MIME タイプ列の値によって示さ プロバイダの任意のコンテンツ URI に一致します。
    - content://com.example.app.provider/table2/*: + content://com.example.app.provider/table2/*:
    テーブル dataset1dataset2 のコンテンツ URI に一致しますが、table1table3 のコンテンツ URI には一致しません。 @@ -791,7 +791,7 @@ protected static final class MainDatabaseHelper extends SQLiteOpenHelper { タイプ部分: vnd
  • - サブタイプ部分: + サブタイプ部分:
    • URI パターンが 1 つの行の場合: android.cursor.item/ diff --git a/docs/html-intl/intl/ja/guide/topics/resources/providing-resources.jd b/docs/html-intl/intl/ja/guide/topics/resources/providing-resources.jd index 6729e8b6ee8a0f5a698bd21af230a51db958427c..2024d5d0bdae99cedd1efdcfcfe758c14aba9f70 100644 --- a/docs/html-intl/intl/ja/guide/topics/resources/providing-resources.jd +++ b/docs/html-intl/intl/ja/guide/topics/resources/providing-resources.jd @@ -110,7 +110,7 @@ MyProject/ drawable/ -

      ビットマップ ファイル({@code .png}、{@code .9.png}、{@code .jpg}、{@code .gif})または次のドローアブル リソース サブタイプにコンパイルされる XML ファイル: +

      ビットマップ ファイル({@code .png}、{@code .9.png}、{@code .jpg}、{@code .gif})または次のドローアブル リソース サブタイプにコンパイルされる XML ファイル:

      • ビットマップ ファイル
      • @@ -510,7 +510,7 @@ xlarge} 識別子のタグが付いているが、端末は通常サイズの画

        API レベル 4 で追加。

        - +

        詳細については、「Supporting Multiple Screens」をご覧ください。

        さらに、{@link android.content.res.Configuration#screenLayout} 設定フィールドもご覧ください。これは、画面のサイズが小、中、大のいずれかであるかを表します。 diff --git a/docs/html-intl/intl/ja/guide/topics/ui/controls.jd b/docs/html-intl/intl/ja/guide/topics/ui/controls.jd index 0bc2063764bb65397992166cad2a9d4343ae2591..c76771fc00bc271b14580c3e70891b8b6314306b 100644 --- a/docs/html-intl/intl/ja/guide/topics/ui/controls.jd +++ b/docs/html-intl/intl/ja/guide/topics/ui/controls.jd @@ -69,7 +69,7 @@ parent.link=index.html ラジオボタン グループで選択できるオプションは 1 つのみであることを除き、チェックボックスと同様です。 - {@link android.widget.RadioGroup RadioGroup} + {@link android.widget.RadioGroup RadioGroup}
        {@link android.widget.RadioButton RadioButton} diff --git a/docs/html-intl/intl/ja/guide/topics/ui/dialogs.jd b/docs/html-intl/intl/ja/guide/topics/ui/dialogs.jd index 358fc304f60ab861614ec8ea969f918a8a90ec66..006dc99962968bcd26180313cb80cdd99d3ee981 100644 --- a/docs/html-intl/intl/ja/guide/topics/ui/dialogs.jd +++ b/docs/html-intl/intl/ja/guide/topics/ui/dialogs.jd @@ -32,7 +32,7 @@ page.tags=alertdialog,dialogfragment

      • {@link android.app.DialogFragment}
      • {@link android.app.AlertDialog}
      • - +

        関連ドキュメント

        1. ダイアログ デザインのガイド
        2. @@ -142,7 +142,7 @@ public class FireMissilesDialogFragment extends DialogFragment {
          -

          図 1 +

          図 1 メッセージと 2 つのアクション ボタンを含むダイアログ

          @@ -248,7 +248,7 @@ AlertDialog dialog = builder.create();
          Neutral
          ユーザーがアクションを続けたくない可能性があり、キャンセルしたいとは限らない場合に使います。 ポジティブ ボタンとネガティブ ボタンの間に表示されます。 -たとえば、「後で通知する」のようなアクションの場合です。
          +たとえば、「後で通知する」のようなアクションの場合です。
  • 各ボタンタイプのいずれか 1 つのみを {@link @@ -258,7 +258,7 @@ android.app.AlertDialog} に追加できます。つまり、2 つ以上の「

    -

    図 3 +

    図 3 タイトルとリストを含むダイアログ

    @@ -318,7 +318,7 @@ android.app.AlertDialog.Builder#setAdapter setAdapter()} を使ってリスト

    固定の複数選択または排他的選択リストを追加する

    複数選択アイテム(チェックボックス)または排他的選択アイテム(ラジオボタン)のリストを追加するには、{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, -DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} または {@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} または {@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} メソッドをそれぞれ使用します。 @@ -346,7 +346,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // 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 + // Else, if the item is already in the array, remove it mSelectedItems.remove(Integer.valueOf(which)); } } @@ -372,7 +372,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

    従来のリストとラジオボタンを含むリストでは、「排他的選択」アクションが提供されますが、ユーザーの選択を固定させたい場合は、{@link -android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} を使用してください。つまり、ダイアログを後でもう一度開く場合は、ユーザーの現在の選択を表示し、ラジオボタンを含むリストを作成します。 @@ -470,7 +470,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { public void onClick(DialogInterface dialog, int id) { LoginDialogFragment.this.getDialog().cancel(); } - }); + }); return builder.create(); } @@ -505,7 +505,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

     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. */
    @@ -513,10 +513,10 @@ public class NoticeDialogFragment extends DialogFragment {
             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
         @Override
         public void onAttach(Activity activity) {
    @@ -543,7 +543,7 @@ public class NoticeDialogFragment extends DialogFragment {
     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();
    @@ -656,7 +656,7 @@ public class CustomDialogFragment extends DialogFragment {
             // 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. */
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
    @@ -678,7 +678,7 @@ public class CustomDialogFragment extends DialogFragment {
     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");
    diff --git a/docs/html-intl/intl/ja/guide/topics/ui/menus.jd b/docs/html-intl/intl/ja/guide/topics/ui/menus.jd
    index 7d8090e7a0ad616101036c53a2f87b5548df786f..53142a1b3e5820a31735afd85e340d72687afbd2 100644
    --- a/docs/html-intl/intl/ja/guide/topics/ui/menus.jd
    +++ b/docs/html-intl/intl/ja/guide/topics/ui/menus.jd
    @@ -83,9 +83,9 @@ Android 3.0 からは、Menu ボタンが廃止されたため(一部
     

    オプション メニューの作成のセクションをご覧ください。

    - +
    コンテキスト メニューとコンテキスト アクション モード
    - +
    コンテキスト メニューは、ユーザーが要素を長押しクリックするときに表示されるフローティング メニューです。 ここでは、選択したコンテンツやコンテキスト フレームに影響するアクションが提供されます。 @@ -94,7 +94,7 @@ Android 3.0 からは、Menu ボタンが廃止されたため(一部

    コンテキスト メニューの作成のセクションをご覧ください。

    - +
    ポップアップ メニュー
    ポップアップ メニューでは、メニューを呼び出すビューに固定された縦方向のリストでアイテムが表示されます。 特定のコンテンツに関連するアクションの概要を表示したり、コマンドの 2 番目の部分のオプションを表示したりする場合に適しています。 @@ -135,7 +135,7 @@ Android 3.0 からは、Menu ボタンが廃止されたため(一部
    <item>
    メニューで 1 つのアイテムを表示する {@link android.view.MenuItem} を作成します。この要素には、サブメニューを作成するために、ネストされた <menu> 要素を含めることができます。
    - +
    <group>
    省略可能な {@code <item>} 要素の非表示コンテナ。メニュー アイテムでアクティブ状態や可視性のようなプロパティを共有できるよう、メニュー アイテムを分類できます。 詳細については、メニュー グループの作成のセクションをご覧ください。 @@ -742,8 +742,8 @@ android.view.Menu} オブジェクトにメニュー リソースをインフレ
     <ImageButton
    -    android:layout_width="wrap_content" 
    -    android:layout_height="wrap_content" 
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
         android:src="@drawable/ic_overflow_holo_dark"
         android:contentDescription="@string/descr_overflow_button"
         android:onClick="showPopup" />
    diff --git a/docs/html-intl/intl/ja/preview/features/multi-window.jd b/docs/html-intl/intl/ja/guide/topics/ui/multi-window.jd
    similarity index 98%
    rename from docs/html-intl/intl/ja/preview/features/multi-window.jd
    rename to docs/html-intl/intl/ja/guide/topics/ui/multi-window.jd
    index 4ad3d940f38ccd33d7820e44e946458492c69cda..a8df89d9c9b31416d11793e04cb316fe75e52e11 100644
    --- a/docs/html-intl/intl/ja/preview/features/multi-window.jd
    +++ b/docs/html-intl/intl/ja/guide/topics/ui/multi-window.jd
    @@ -4,8 +4,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form"
     
     @jd:body
     
    -
    -
    +
    +

    このドキュメントの内容

    1. 概要
    2. @@ -69,8 +69,8 @@ TV 端末で、アプリがピクチャ イン ピクチャ モードで動画 - +

      図 1. 分割画面モードで並べて実行されている 2 つのアプリ。

      @@ -146,7 +146,7 @@ TV 端末で、アプリがピクチャ イン ピクチャ モードで動画 ユーザーがウィンドウのサイズを変更して、高さや幅を拡大した場合、ユーザー操作に一致するようにアクティビティのサイズが変更され、必要に応じて、実行時の変更が発行されます。 アプリで新しく表示された領域を描画するまでに時間がかかる場合、{@link - android.R.attr#windowBackground windowBackground} 属性またはデフォルトの + android.R.attr#windowBackground windowBackground} 属性またはデフォルトの windowBackgroundFallback システム属性によって指定された色でこれらの領域が一時的に塗りつぶされます。

      @@ -158,7 +158,7 @@ TV 端末で、アプリがピクチャ イン ピクチャ モードで動画 サイズとレイアウトを制御するための属性をマニフェストに設定できます。 ルート アクティビティ属性の設定は、タスクスタック内のすべてのアクティビティに適用されます。 -たとえば、ルート アクティビティにより +たとえば、ルート アクティビティにより android:resizeableActivity が true に設定されると、タスク スタック内のすべてのアクティビティのサイズを変更できるようになります。

      @@ -175,7 +175,7 @@ TV 端末で、アプリがピクチャ イン ピクチャ モードで動画

      android:resizeableActivity

      - マルチ ウィンドウ ディスプレイを有効または無効にするには、この属性をマニフェストの <activity> ノードまたは + マルチ ウィンドウ ディスプレイを有効または無効にするには、この属性をマニフェストの <activity> ノードまたは <application> ノードに設定します。

      @@ -361,7 +361,7 @@ android:supportsPictureInPicture=["true" | "false"]

      ピクチャ イン ピクチャ モードにする

      - アクティビティをピクチャ イン ピクチャ モードにするには、新しいメソッド + アクティビティをピクチャ イン ピクチャ モードにするには、新しいメソッド Activity.enterPictureInPictureMode() を呼び出します。端末がピクチャ イン ピクチャ モードをサポートしない場合、このメソッドの効果はありません。 詳細については、ピクチャ イン ピクチャに関するドキュメントをご覧ください。 @@ -371,7 +371,7 @@ android:supportsPictureInPicture=["true" | "false"]

      新しいアクティビティを起動するときに、可能であれば、新しいアクティビティを現在のアクティビティの隣に表示する必用があるかどうかをシステムに示すことができます。 -そうするには、フラグ +そうするには、フラグ Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT を使用します。 このフラグを渡すと、次の動作がリクエストされます。 @@ -434,10 +434,10 @@ android:supportsPictureInPicture=["true" | "false"]

      - {@link android.view.View#startDrag View.startDrag()} の新しいエイリアスです。異なるアクティビティ間のドラッグ&ドロップを有効にするには、新しいフラグ + {@link android.view.View#startDrag View.startDrag()} の新しいエイリアスです。異なるアクティビティ間のドラッグ&ドロップを有効にするには、新しいフラグ View.DRAG_FLAG_GLOBAL を渡します。 -URI パーミッションを受け取る側のアクティビティに付与する必要がある場合、必要に応じて、新しいフラグ -View.DRAG_FLAG_GLOBAL_URI_READ または +URI パーミッションを受け取る側のアクティビティに付与する必要がある場合、必要に応じて、新しいフラグ +View.DRAG_FLAG_GLOBAL_URI_READ または View.DRAG_FLAG_GLOBAL_URI_WRITE を渡します。
      @@ -581,7 +581,7 @@ URI パーミッションを受け取る側のアクティビティに付与す

      マルチ ウィンドウのサポートを無効にしている場合

      - + android:resizableActivity="false" を設定して、マルチ ウィンドウのサポートを無効にした場合は、Android N を実行している端末でアプリを起動し、アプリをフリーフォーム モードおよび分割画面モードにすることを試みる必要があります。 アプリをマルチ ウィンドウ モードにすることを試みたとき、アプリが全画面モードのままであることを確認してください。 diff --git a/docs/html-intl/intl/ja/guide/topics/ui/notifiers/notifications.jd b/docs/html-intl/intl/ja/guide/topics/ui/notifiers/notifications.jd index f341256a3225be22b136bff83747f143f65165a6..d0f1f72f626a25e5db4465c04ef8ea69ef45218c 100644 --- a/docs/html-intl/intl/ja/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html-intl/intl/ja/guide/topics/ui/notifiers/notifications.jd @@ -531,7 +531,7 @@ numMessages = 0;

    3. 必要に応じて、{@link android.support.v4.app.TaskStackBuilder#editIntentAt TaskStackBuilder.editIntentAt()} を呼び出し、スタック上の {@link android.content.Intent} オブジェクトに引数を追加します。 -これは、場合によっては、ターゲット {@link android.app.Activity} に、ユーザーが +これは、場合によっては、ターゲット {@link android.app.Activity} に、ユーザーが [戻る] を使って移動したときに、適切なデータが表示されるようにするために必要です。
    4. diff --git a/docs/html-intl/intl/ja/guide/topics/ui/overview.jd b/docs/html-intl/intl/ja/guide/topics/ui/overview.jd index 08d93560cb4e0bb0cce656da5fdaafece6adce5b..7bc49f4f12fc6e1e9ef16943eef29e862f9fe237 100644 --- a/docs/html-intl/intl/ja/guide/topics/ui/overview.jd +++ b/docs/html-intl/intl/ja/guide/topics/ui/overview.jd @@ -39,7 +39,7 @@ android.view.View} と {@link android.view.ViewGroup} オブジェクトの階
       <?xml version="1.0" encoding="utf-8"?>
       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -              android:layout_width="fill_parent" 
      +              android:layout_width="fill_parent"
                     android:layout_height="fill_parent"
                     android:orientation="vertical" >
           <TextView android:id="@+id/text"
      @@ -60,7 +60,7 @@ android.view.View} と {@link android.view.ViewGroup} オブジェクトの階
       

      UI レイアウト作成のガイドについては、XML レイアウトをご覧ください。 - +

      ユーザー インターフェース コンポーネント

      {@link android.view.View} と {@link android.view.ViewGroup} オブジェクトを使用してすべての UI をビルドする必要はありません。 diff --git a/docs/html-intl/intl/ja/guide/topics/ui/settings.jd b/docs/html-intl/intl/ja/guide/topics/ui/settings.jd index 9e6bb9d04169c0bc5b6d0de07450bee32f2e154e..c36a01c898feca17ea553f56f32f537375092e12 100644 --- a/docs/html-intl/intl/ja/guide/topics/ui/settings.jd +++ b/docs/html-intl/intl/ja/guide/topics/ui/settings.jd @@ -226,7 +226,7 @@ XML ファイルは更新が容易な簡単に読むことができる構造を

      {@code android:key}
      この属性は、データ値を保持するプリファレンスで必要です。設定の値を {@link android.content.SharedPreferences} に保存するときにシステムが使用する一意のキー(文字列)を指定します。 - +

      プリファレンスが {@link android.preference.PreferenceCategory} または{@link android.preference.PreferenceScreen} の場合、またはプリファレンスが {@link android.content.Intent} の呼び出しを指定している場合({@code <intent>} 要素を使用)、または {@link android.app.Fragment} の表示を指定している場合({@code android:fragment} 属性を使用)のみ、インスタンスでこの属性は必要ありません。 @@ -285,7 +285,7 @@ XML ファイルは更新が容易な簡単に読むことができる構造を

       <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
      -    <PreferenceCategory 
      +    <PreferenceCategory
               android:title="@string/pref_sms_storage_title"
               android:key="pref_key_storage_settings">
               <CheckBoxPreference
      @@ -293,12 +293,12 @@ XML ファイルは更新が容易な簡単に読むことができる構造を
                   android:summary="@string/pref_summary_auto_delete"
                   android:title="@string/pref_title_auto_delete"
                   android:defaultValue="false"... />
      -        <Preference 
      +        <Preference
                   android:key="pref_key_sms_delete_limit"
                   android:dependency="pref_key_auto_delete"
                   android:summary="@string/pref_summary_delete_limit"
                   android:title="@string/pref_title_sms_delete"... />
      -        <Preference 
      +        <Preference
                   android:key="pref_key_mms_delete_limit"
                   android:dependency="pref_key_auto_delete"
                   android:summary="@string/pref_summary_delete_limit"
      @@ -588,11 +588,11 @@ PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
       
       <?xml version="1.0" encoding="utf-8"?>
       <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
               android:title="@string/prefs_category_one"
               android:summary="@string/prefs_summ_category_one" />
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
               android:title="@string/prefs_category_two"
               android:summary="@string/prefs_summ_category_two" >
      @@ -672,15 +672,15 @@ public class SettingsActivity extends PreferenceActivity {
       

      たとえば、以下は Android 3.0 以降で使用されるプリファレンス ヘッダーの XML ファイル({@code res/xml/preference_headers.xml})です。 -

      +

       <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsFragmentOne"
               android:title="@string/prefs_category_one"
               android:summary="@string/prefs_summ_category_one" />
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsFragmentTwo"
               android:title="@string/prefs_category_two"
               android:summary="@string/prefs_summ_category_two" />
      @@ -692,18 +692,18 @@ public class SettingsActivity extends PreferenceActivity {
       
       
       <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
      -    <Preference 
      +    <Preference
               android:title="@string/prefs_category_one"
               android:summary="@string/prefs_summ_category_one"  >
      -        <intent 
      +        <intent
                   android:targetPackage="com.example.prefs"
                   android:targetClass="com.example.prefs.SettingsActivity"
                   android:action="com.example.prefs.PREFS_ONE" />
           </Preference>
      -    <Preference 
      +    <Preference
               android:title="@string/prefs_category_two"
               android:summary="@string/prefs_summ_category_two" >
      -        <intent 
      +        <intent
                   android:targetPackage="com.example.prefs"
                   android:targetClass="com.example.prefs.SettingsActivity"
                   android:action="com.example.prefs.PREFS_TWO" />
      @@ -975,11 +975,11 @@ prefs.registerOnSharedPreferenceChangeListener(listener);
       public class NumberPickerPreference extends DialogPreference {
           public NumberPickerPreference(Context context, AttributeSet attrs) {
               super(context, attrs);
      -        
      +
               setDialogLayoutResource(R.layout.numberpicker_dialog);
               setPositiveButtonText(android.R.string.ok);
               setNegativeButtonText(android.R.string.cancel);
      -        
      +
               setDialogIcon(null);
           }
           ...
      @@ -1194,7 +1194,7 @@ protected void onRestoreInstanceState(Parcelable state) {
           // Cast state to custom BaseSavedState and pass to superclass
           SavedState myState = (SavedState) state;
           super.onRestoreInstanceState(myState.getSuperState());
      -    
      +
           // Set this Preference's widget to reflect the restored state
           mNumberPicker.setValue(myState.value);
       }
      diff --git a/docs/html-intl/intl/ja/guide/topics/ui/ui-events.jd b/docs/html-intl/intl/ja/guide/topics/ui/ui-events.jd
      index 1cff3f62d0229041aa5008bd48c540c97edd8c3d..b4b3766e768a6ee9743a25cce90e177033385730 100644
      --- a/docs/html-intl/intl/ja/guide/topics/ui/ui-events.jd
      +++ b/docs/html-intl/intl/ja/guide/topics/ui/ui-events.jd
      @@ -187,7 +187,7 @@ dispatchKeyEvent()} メソッドを介して伝わっていると判断
           ViewGroup.onInterceptTouchEvent(MotionEvent)} - {@link android.view.ViewGroup} が、イベントが子ビューにディスパッチされたときにイベントを監視できるようにします。
       
         
    5. {@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) - ViewParent.requestDisallowInterceptTouchEvent(boolean)} - このメソッドを親ビュー上で呼び出すことで、{@link + ViewParent.requestDisallowInterceptTouchEvent(boolean)} - このメソッドを親ビュー上で呼び出すことで、{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)} による親ビューのタップイベントのインターセプトを許可しないことを示すことができます。
    6. @@ -199,7 +199,7 @@ dispatchKeyEvent()} メソッドを介して伝わっていると判断 ただし、端末にタッチ機能がある場合は、ユーザーはタップでインターフェースの操作を開始するため、アイテムをハイライトすることや、特定のビューにフォーカスを与えることは必要ではなくなりました。 そのため、「タッチモード」と名付けられた操作モードが存在します。 - +

      タッチ可能な端末では、ユーザーが画面をタップすると、端末がタッチモードになります。 @@ -233,7 +233,7 @@ dispatchKeyEvent()} メソッドを介して伝わっていると判断

      フォーカスの移動は、所定の方向で最も近くにあるアイテムを見つけるアルゴリズムに基づきますが、 まれに、デフォルトのアルゴリズムが開発者の意図する動作と一致しない場合もあります。 -この場合、レイアウト ファイルの +この場合、レイアウト ファイルの nextFocusDownnextFocusLeftnextFocusRightnextFocusUp の各 XML 属性を明示的にオーバーライドできます。これらの属性のいずれかを、フォーカスの移動のビューに追加します。 @@ -253,11 +253,11 @@ dispatchKeyEvent()} メソッドを介して伝わっていると判断

      本来、上記の縦方向のレイアウトでは、1 番上のボタンから上に移動しようとしても、2 番目のボタンから下に移動しようしても、どこにもフォーカスが移動しないはずでしたが、上記の処理により、 -1 番上のボタンによって 1 番下のボタンが +1 番上のボタンによって 1 番下のボタンが nextFocusUp として定義され(逆の場合も同様)、フォーカスが、上から下と下から上に順番に移動するようになります。

      -

      UI でビューをフォーカス可能にする場合は(従来は、ビューはフォーカス可能ではありません)、レイアウトの宣言で android:focusable XML 属性をビューに追加し、値を +

      UI でビューをフォーカス可能にする場合は(従来は、ビューはフォーカス可能ではありません)、レイアウトの宣言で android:focusable XML 属性をビューに追加し、値を true に設定します。また、android:focusableInTouchMode を使用して、タッチモードのときにビューをフォーカス可能にすることもできます。

      @@ -282,7 +282,7 @@ dispatchKeyEvent()} メソッドを介して伝わっていると判断 the framework will take care of measuring, laying out, and drawing the tree as appropriate.
    - +

    Note: 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 diff --git a/docs/html-intl/intl/ja/index.jd b/docs/html-intl/intl/ja/index.jd index 755ec6205bfe48bbd3ec0d6ae1bf3562c0edc39f..3220f19443673290a0cc4f21790725026fac7c19 100644 --- a/docs/html-intl/intl/ja/index.jd +++ b/docs/html-intl/intl/ja/index.jd @@ -5,49 +5,36 @@ page.customHeadTag= - -

    -
    -
    - -

    Android N Developer Preview

    -

    - Get ready for the next version of Android! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. +

    +
    -
    @@ -163,7 +163,7 @@ Designed for Families에 대한 질문과page.metaDescription= 대답
    앱을 게시한 후에 Designed for Families 프로그램 요구사항을 준수하지 않는 것으로 확인되면 어떻게 됩니까? - +
    @@ -185,7 +185,7 @@ Designed for Families에 대한 질문과page.metaDescription= 대답
    Designed for Families 프로그램에서 승인된 앱을 업데이트하면 어떻게 됩니까? - +
    @@ -265,7 +265,7 @@ Designed for Families에 대한 질문과page.metaDescription= 대답 인앱 광고를 포함한 전반적인 사용자 경험이 Designed for Families 프로그램 요구사항을 충족하도록 보장하는 것은 개발자의 책임입니다. - +
    @@ -297,7 +297,7 @@ Designed for Families에 대한 질문과page.metaDescription= 대답
    - 당사는 부모와 보호자가 Google Play 스토어에서 신뢰할 수 있는 브랜드와 개발자가 제작한 우수한 아동 및 가족용 앱을 찾을 수 있도록 하는 것을 목표로 합니다. + 당사는 부모와 보호자가 Google Play 스토어에서 신뢰할 수 있는 브랜드와 개발자가 제작한 우수한 아동 및 가족용 앱을 찾을 수 있도록 하는 것을 목표로 합니다.
    diff --git a/docs/html-intl/intl/ko/distribute/googleplay/families/start.jd b/docs/html-intl/intl/ko/distribute/googleplay/families/start.jd index 06f76b5c45892fe85e2ba3b32f8693863e1e0ac3..4a93b564ec2e670ff22701b2e5b6f1654f83fdf0 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/families/start.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/families/start.jd @@ -78,7 +78,7 @@ page.metaDescription=간단한 몇 단계로 Designed for Families에 가입합

    참고: Designed for Families 프로그램에 게시된 앱은 Google Play의 모든 사용자도 사용할 수 있습니다. - +

    diff --git a/docs/html-intl/intl/ko/distribute/googleplay/guide.jd b/docs/html-intl/intl/ko/distribute/googleplay/guide.jd index e8d25ff2a3d6eaac0f1c5dc9651b1850bb4cce12..2a622b728cd4aa64a676f453ae01a13c9eb714c7 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/guide.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/guide.jd @@ -34,7 +34,7 @@ page.image=distribute/images/play_dev_guide.png

  • 사용자 확보 및 유지 — 앱을 설치한 사람을 실제 사용자로 확보하고 해당 사용자를 효율적으로 유지하는 방법을 안내합니다. - +
  • diff --git a/docs/html-intl/intl/ko/distribute/googleplay/quality/core.jd b/docs/html-intl/intl/ko/distribute/googleplay/quality/core.jd index c914aab02de120bca514ce8237b5016bce4e310e..cec3dc6730bc5d488330d7f12b9a77718c22c7c9 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/quality/core.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/quality/core.jd @@ -12,7 +12,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
  • Google Play
  • - +

    테스트

    1. 테스트 환경 설정
    2. @@ -24,7 +24,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
    3. 태블릿 앱 품질
    4. 앱 최적화
    - + @@ -59,7 +59,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg - +

    @@ -84,7 +84,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg ID - + 설명 @@ -166,7 +166,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg 어디서든지 홈 버튼을 누르면 장치의 홈 화면으로 이동합니다. - + CR-1 @@ -292,7 +292,7 @@ data-maxresults="6"> 앱이 핵심 기능과 관련되지 않은 경우 사용자가 비용을 지불할 수 있는 서비스(예: 전화 걸기 또는 SMS) 또는 민감한 데이터(예: 연락처 또는 시스템 로그)에 대한 액세스 권한을 요청하지 않습니다. - +

    @@ -594,7 +594,7 @@ data-sortorder="-timestamp" data-cardsizes="6x3" data-maxresults="6"> 정상적인 앱 사용 및 로드 시 음악 및 동영상 재생이 매끄럽고 잔금, 버벅거림 또는 기타 아티팩트가 없습니다. - + CR-all, SD-1, HA-1 diff --git a/docs/html-intl/intl/ko/distribute/googleplay/quality/tablets.jd b/docs/html-intl/intl/ko/distribute/googleplay/quality/tablets.jd index 6cf38c3371a17c53da97cf1b76d1afeaef07a016..23ddbcb128b92f36ba1659845e35cd0e61cfa4cb 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/quality/tablets.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/quality/tablets.jd @@ -56,7 +56,7 @@ Xnonavpage=true

    뛰어난 태블릿 앱 경험을 제공하는 첫 번째 단계는 앱이 대상으로 삼은 모든 장치 및 폼 팩터에 대한 핵심 앱 품질 기준을 충족하는지 확인하는 것입니다. - 자세한 내용은 핵심 앱 품질 가이드라인을 참조하십시오. + 자세한 내용은 핵심 앱 품질 가이드라인을 참조하십시오.

    diff --git a/docs/html-intl/intl/ko/distribute/googleplay/quality/wear.jd b/docs/html-intl/intl/ko/distribute/googleplay/quality/wear.jd index 7ab936731b023f0313334372aa95775aebe7ce8a..e35e566f267d394e41f4c51722c128cd312b6f9c 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/quality/wear.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/quality/wear.jd @@ -331,7 +331,7 @@ data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">

    - 앱이 필요한 경우 확인 애니메이션을 표시합니다. + 앱이 필요한 경우 확인 애니메이션을 표시합니다. (방법 알아보기)

    diff --git a/docs/html-intl/intl/ko/distribute/googleplay/start.jd b/docs/html-intl/intl/ko/distribute/googleplay/start.jd index f5dd1b3fd51065e5c1dbe8b549e2d7fc75c2de6b..495df80c513f90e701bc21cc23cc09467a2aacf0 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/start.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/start.jd @@ -75,7 +75,7 @@ page.image=/distribute/images/getting-started.jpg
  • 해당 국가 또는 지역의 개발자 배포 계약을 읽고 동의합니다. Google Play에 게시하는 앱 및 스토어 목록은 개발자 프로그램 정책 및 미국 수출 법규를 준수해야 합니다. - +
  • Google Wallet을 사용하여 등록 수수료로 미화 25달러를 지불합니다. Google Wallet 계정이 없는 경우 프로세스 진행 중에 계정을 설정할 수 있습니다. diff --git a/docs/html-intl/intl/ko/distribute/googleplay/tv.jd b/docs/html-intl/intl/ko/distribute/googleplay/tv.jd index 58f4c2e01ee441aa3dc6baaf8f613285e5d2fa21..3efa93bdbaf12156e1a9d3f2be9c80d08c6a969b 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/tv.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/tv.jd @@ -261,7 +261,7 @@ page.metaDescription=앱, 게임 및 콘텐츠를 Android TV에 배포합니다. 필요한 조정을 거친 후에 새로운 앱 버전을 개발자 콘솔에 업로드할 수 있습니다. - +

    @@ -282,7 +282,7 @@ page.metaDescription=앱, 게임 및 콘텐츠를 Android TV에 배포합니다.

  • 승인됨 — 앱이 검토 후에 승인되었습니다. Android TV 사용자가 앱을 바로 사용할 수 있습니다. - +
  • diff --git a/docs/html-intl/intl/ko/distribute/googleplay/wear.jd b/docs/html-intl/intl/ko/distribute/googleplay/wear.jd index 864f668ecd3d8748c634e4891c92336d516274ee..1f916c2f08a95add8a9542703e037bd997bcde11 100644 --- a/docs/html-intl/intl/ko/distribute/googleplay/wear.jd +++ b/docs/html-intl/intl/ko/distribute/googleplay/wear.jd @@ -121,7 +121,7 @@ page.metaDescription=Android Wear에 앱, 게임 및 콘텐츠를 배포합니 Wear 앱은 잘 작동하고 Android Wear에서 멋있게 보이고 최고의 사용자 경험을 제공하도록 디자인해야 합니다. Google Play는 사용자가 쉽게 검색할 수 있도록 선정된 고품질 Wear 앱을 소개합니다. 다음과 같은 방법으로 참여하여 사용자에게 멋진 Android Wear 앱을 제공할 수 있습니다. - +

      diff --git a/docs/html-intl/intl/ko/distribute/tools/launch-checklist.jd b/docs/html-intl/intl/ko/distribute/tools/launch-checklist.jd index a8a2dcdc0bd6d44a1355be20ea92ba3a39101c07..623c129fcba87756afb38c6a2eb8567304eeb5fa 100644 --- a/docs/html-intl/intl/ko/distribute/tools/launch-checklist.jd +++ b/docs/html-intl/intl/ko/distribute/tools/launch-checklist.jd @@ -197,7 +197,7 @@ data-maxresults="6">

      Android 장치에서 Android 사용자는 검색에 사용할 완성도를 설정할 수 있습니다. Google Play는 설정에 따라 앱을 필터링하므로 선택한 콘텐츠 등급은 사용자에게 앱을 배포하는 데 영향을 줄 수 있습니다. - 앱 바이너리를 변경할 필요 없이 개발자 콘솔에서 앱의 콘텐츠 등급을 할당(또는 변경)할 수 있습니다. + 앱 바이너리를 변경할 필요 없이 개발자 콘솔에서 앱의 콘텐츠 등급을 할당(또는 변경)할 수 있습니다.

      @@ -764,7 +764,7 @@ See how you can facilitate testing with Google Play.

      개발자 콘솔에서 앱의 대상 지역을 설정한 후에 지원하는 모든 언어에 대해 현지화된 스토어 목록, 홍보 그래픽 등을 추가하십시오. - +

      diff --git a/docs/html-intl/intl/ko/distribute/tools/localization-checklist.jd b/docs/html-intl/intl/ko/distribute/tools/localization-checklist.jd index cf4648183a6f7d58440de0b7cc09e96ee26fe862..4cc9735421179c15608593e858483ec10ed946fa 100644 --- a/docs/html-intl/intl/ko/distribute/tools/localization-checklist.jd +++ b/docs/html-intl/intl/ko/distribute/tools/localization-checklist.jd @@ -187,7 +187,7 @@ data-sortorder="-timestamp" data-cardsizes="9x3," data-maxresults="6"> - +

      diff --git a/docs/html-intl/intl/ko/guide/components/activities.jd b/docs/html-intl/intl/ko/guide/components/activities.jd index 001982f6f63c5f9fe437615fd0fc82774471ec32..255a11119e96c5f81c4d2ec729efba24249cf06a 100644 --- a/docs/html-intl/intl/ko/guide/components/activities.jd +++ b/docs/html-intl/intl/ko/guide/components/activities.jd @@ -44,31 +44,31 @@ page.tags=activity,intent -

      {@link android.app.Activity}는 일종의 애플리케이션 구성 요소로서, -사용자와 상호작용할 수 있는 화면을 제공하여 전화 걸기, 사진 찍기, 이메일 보내기 또는 지도 보기 등의 일을 할 수 -있습니다. 액티비티마다 창이 하나씩 주어져 이곳에 사용자 인터페이스를 끌어올 수 있습니다. 이 창은 -일반적으로 화면을 가득 채우지만, 작은 창으로 만들어 다른 창 위에 띄울 수도 +

      {@link android.app.Activity}는 일종의 애플리케이션 구성 요소로서, +사용자와 상호작용할 수 있는 화면을 제공하여 전화 걸기, 사진 찍기, 이메일 보내기 또는 지도 보기 등의 일을 할 수 +있습니다. 액티비티마다 창이 하나씩 주어져 이곳에 사용자 인터페이스를 끌어올 수 있습니다. 이 창은 +일반적으로 화면을 가득 채우지만, 작은 창으로 만들어 다른 창 위에 띄울 수도 있습니다.

      -

      하나의 애플리케이션은 보통 여러 개의 액티비티가 느슨하게 서로 묶여 있는 형태로 -구성됩니다. 통상 한 애플리케이션 내에서 하나의 액티비티가 "주요" 액티비티로 지정되며, -사용자가 이 애플리케이션을 처음 실행할 때 이 액티비티가 사용자에게 표시됩니다. 그런 후 +

      하나의 애플리케이션은 보통 여러 개의 액티비티가 느슨하게 서로 묶여 있는 형태로 +구성됩니다. 통상 한 애플리케이션 내에서 하나의 액티비티가 "주요" 액티비티로 지정되며, +사용자가 이 애플리케이션을 처음 실행할 때 이 액티비티가 사용자에게 표시됩니다. 그런 후 각각의 액티비티는 여러 가지 작업을 수행하기 위해 또 다른 액티비티를 시작할 수 있습니다. 새로운 액티비티가 시작될 때마다 이전 액티비티는 중단되지만 시스템은 해당 액티비티를 -스택("백 스택")에 보존합니다. 새로운 액티비티가 시작되면, 이것이 백 스택 위로 밀려와 사용자의 -시선을 끕니다. 백 스택은 기본적인 "후입선출" 방식을 지키므로, -사용자가 현재 액티비티를 끝내고 뒤로 버튼을 누르면 해당 액티비티가 +스택("백 스택")에 보존합니다. 새로운 액티비티가 시작되면, 이것이 백 스택 위로 밀려와 사용자의 +시선을 끕니다. 백 스택은 기본적인 "후입선출" 방식을 지키므로, +사용자가 현재 액티비티를 끝내고 뒤로 버튼을 누르면 해당 액티비티가 스택에서 튀어나와(소멸되고) 이전 액티비티를 재개합니다 (백 스택은 작업 및 백 스택 문서에서 상세하게 논의합니다).

      한 액티비티가 새로운 액티비티의 시작으로 인해 중단된 경우, 이 상태 변경은 -액티비티의 수명 주기 콜백 메서드를 통해 알려집니다. +액티비티의 수명 주기 콜백 메서드를 통해 알려집니다. 액티비티가 시스템 액티비티를 생성, 중단, 재시작, 제거하는 등의 상태 변화로 인해 받을 수 있는 콜백 메서드는 여러 가지가 있습니다. 각 콜백은 상태 변화에 알맞은 특정 작업을 수행할 기회를 제공합니다. - 예를 들어 액티비티가 중단되면 네트워크 또는 데이터베이스 연결과 같이 -큰 개체는 모두 해제해야 합니다. 액티비티가 재개되면, 필요한 리소스를 + 예를 들어 액티비티가 중단되면 네트워크 또는 데이터베이스 연결과 같이 +큰 개체는 모두 해제해야 합니다. 액티비티가 재개되면, 필요한 리소스를 다시 획득하여 중단된 작업을 재개할 수 있습니다. 이러한 상태 전환은 모두 액티비티 수명 주기의 일부입니다.

      @@ -83,52 +83,52 @@ page.tags=activity,intent

      액티비티를 생성하려면 {@link android.app.Activity}의 하위 클래스(또는 이의 기존 하위 클래스)를 생성해야 합니다. 하위 클래스에서는 액티비티 생성, 중단, 재개, 소멸 시기 등과 같은 -수명 주기의 다양한 상태 간 액티비티가 전환될 때 시스템이 호출하는 콜백 메서드를 구현해야 합니다. 가장 중요한 두 가지 콜백 메서드는 +수명 주기의 다양한 상태 간 액티비티가 전환될 때 시스템이 호출하는 콜백 메서드를 구현해야 합니다. 가장 중요한 두 가지 콜백 메서드는 다음과 같습니다.

      {@link android.app.Activity#onCreate onCreate()}
      이 메서드는 반드시 구현해야 합니다. 시스템은 액티비티를 생성할 때 이것을 호출합니다. - 구현하는 중에 액티비티의 필수 구성 요소를 초기화해야 + 구현하는 중에 액티비티의 필수 구성 요소를 초기화해야 합니다. 무엇보다도 중요한 점은, 바로 여기서 {@link android.app.Activity#setContentView setContentView()}를 호출해야 액티비티의 사용자 인터페이스 레이아웃을 정의할 수 있다는 점입니다.
      {@link android.app.Activity#onPause onPause()}
      -
      시스템이 이 메서드를 호출하는 것은 사용자가 액티비티를 떠난다는 -첫 번째 신호입니다(다만 이것이 항상 액티비티가 소멸 중이라는 뜻은 아닙니다). 현재 사용자 세션을 넘어서 -지속되어야 하는 변경 사항을 커밋하려면 보통 이곳에서 해아 합니다(사용자가 +
      시스템이 이 메서드를 호출하는 것은 사용자가 액티비티를 떠난다는 +첫 번째 신호입니다(다만 이것이 항상 액티비티가 소멸 중이라는 뜻은 아닙니다). 현재 사용자 세션을 넘어서 +지속되어야 하는 변경 사항을 커밋하려면 보통 이곳에서 해아 합니다(사용자가 돌아오지 않을 수 있기 때문입니다).
      -

      여러 액티비티 사이에서 원활한 사용자 경험을 제공하고, 액티비티 중단이나 심지어 -소멸을 초래할 수도 있는 예상치 못한 간섭을 처리하기 위해 사용해야 하는 다른 수명 주기 -콜백 메서드도 여러 가지 있습니다. 모든 수명 주기 콜백 메서드는 나중에 +

      여러 액티비티 사이에서 원활한 사용자 경험을 제공하고, 액티비티 중단이나 심지어 +소멸을 초래할 수도 있는 예상치 못한 간섭을 처리하기 위해 사용해야 하는 다른 수명 주기 +콜백 메서드도 여러 가지 있습니다. 모든 수명 주기 콜백 메서드는 나중에 액티비티 수명 주기 관리 섹션에서 자세히 논의할 것입니다.

      사용자 인터페이스 구현하기

      -

      한 액티비티에 대한 사용자 인터페이스는 보기 계층—즉, +

      한 액티비티에 대한 사용자 인터페이스는 보기 계층—즉, {@link android.view.View} 클래스에서 파생된 개체가 제공합니다. 각 보기는 액티비티 창 안의 특정한 직사각형 공간을 - 제어하며 사용자 상호 작용에 대응할 수 있습니다. 예를 들어, 어떤 보기는 사용자가 터치하면 + 제어하며 사용자 상호 작용에 대응할 수 있습니다. 예를 들어, 어떤 보기는 사용자가 터치하면 작업을 시작하는 버튼일 수 있습니다.

      -

      Android는 레이아웃을 디자인하고 정리하는 데 사용할 수 있도록 여러 가지 보기를 미리 만들어 -제공합니다. "위젯"이란 화면에 시각적(이자 대화형) 요소를 제공하는 보기입니다. 예를 들어 +

      Android는 레이아웃을 디자인하고 정리하는 데 사용할 수 있도록 여러 가지 보기를 미리 만들어 +제공합니다. "위젯"이란 화면에 시각적(이자 대화형) 요소를 제공하는 보기입니다. 예를 들어 버튼, 텍스트 필드, 확인란이나 그저 하나의 이미지일 수도 있습니다. "레이아웃"은 선형 레이아웃, 격자형 레이아웃, 상대적 레이아웃과 같이 하위 레이아웃에 대해 독특한 레이아웃 모델을 제공하는 {@link android.view.ViewGroup}에서 파생된 보기입니다. 또한, {@link android.view.View}와 {@link android.view.ViewGroup} 클래스(또는 기존 하위 클래스)의 아래로 내려가서 위젯과 레이아웃을 생성하고 이를 액티비티 레이아웃에 적용할 수 있습니다.

      -

      보기를 사용하여 레이아웃을 정의하는 가장 보편적인 방식은 애플리케이션 리소스에 저장된 +

      보기를 사용하여 레이아웃을 정의하는 가장 보편적인 방식은 애플리케이션 리소스에 저장된 XML 레이아웃 파일을 사용하는 것입니다. 이렇게 하면 액티비티의 동작을 정의하는 -소스 코드와 별개로 사용자 인터페이스 디자인을 유지할 수 있습니다. +소스 코드와 별개로 사용자 인터페이스 디자인을 유지할 수 있습니다. {@link android.app.Activity#setContentView(int) setContentView()}로 액티비티의 UI로서 레이아웃을 설정하고, 해당 레이아웃의 리소스 ID를 전달할 수 있습니다. 그러나 액티비티 코드에 새로운 {@link android.view.View}를 생성하고 새로운 {@link -android.view.View}를 {@link android.view.ViewGroup}에 삽입하여 보기 계층을 구축한 뒤 루트 +android.view.View}를 {@link android.view.ViewGroup}에 삽입하여 보기 계층을 구축한 뒤 루트 {@link android.view.ViewGroup}을 {@link android.app.Activity#setContentView(View) setContentView()}에 전달해도 해당 레이아웃을 사용할 수 있습니다.

      @@ -138,7 +138,7 @@ setContentView()}에 전달해도 해당 레이아웃을 사용할 수 있습니

      매니페스트에서 액티비티 선언하기

      -

      시스템에서 액티비티에 액세스할 수 있게 하려면 이를 매니페스트 파일에서 +

      시스템에서 액티비티에 액세스할 수 있게 하려면 이를 매니페스트 파일에서 선언해야만 합니다. 액티비티를 선언하려면 매니페스트 파일을 열고 {@code <activity>} 요소를 {@code <application>} 요소의 하위 항목으로 추가합니다. 예:

      @@ -169,12 +169,12 @@ setContentView()}에 전달해도 해당 레이아웃을 사용할 수 있습니

      {@code <activity>} 요소 또한 여러 가지 인텐트 필터를 지정할 수 있습니다. 다른 애플리케이션 구성 요소가 이를 활성화하는 방법을 선언하기 위해 {@code -<intent-filter>}를 사용하는 +<intent-filter>}를 사용하는 것입니다.

      -

      Android SDK 도구를 사용하여 새 애플리케이션을 생성하는 경우, 개발자를 위해 -생성되어 있는 스텁 액티비티에 자동으로 인텐트 필터가 포함되어 있어 "주요" 동작에 -응답하는 액티비티를 선언하며, 이는 "시작 관리자" 범주에 배치해야 합니다. 인텐트 필터는 다음과 +

      Android SDK 도구를 사용하여 새 애플리케이션을 생성하는 경우, 개발자를 위해 +생성되어 있는 스텁 액티비티에 자동으로 인텐트 필터가 포함되어 있어 "주요" 동작에 +응답하는 액티비티를 선언하며, 이는 "시작 관리자" 범주에 배치해야 합니다. 인텐트 필터는 다음과 같은 형태를 띱니다.

      @@ -188,23 +188,23 @@ setContentView()}에 전달해도 해당 레이아웃을 사용할 수 있습니
       
       

      {@code <action>} 요소는 이것이 애플리케이션으로 가는 "주요" 진입 지점이라는 것을 나타냅니다. {@code -<category>} 요소는 이 액티비티가 시스템의 +<category>} 요소는 이 액티비티가 시스템의 애플리케이션 시작 관리자에 목록으로 나열되어야 한다는 것을 나타냅니다(사용자가 이 액티비티를 시작할 수 있도록 해줌).

      -

      애플리케이션이 자체 포함 방식이기를 원하고 다른 애플리케이션이 이 -애플리케이션의 액티비티를 활성화하도록 허용하지 않고자 하면, 달리 인텐트 필터가 더 필요하지 않습니다. "주요" 동작과 "시작 관리자" 범주가 있는 -액티비티는 하나뿐이어야 합니다(이전 예시 참조). 다른 애플리케이션에서 -사용할 수 없게 하고자 하는 액티비티에는 인텐트 필터가 있으면 안 됩니다. +

      애플리케이션이 자체 포함 방식이기를 원하고 다른 애플리케이션이 이 +애플리케이션의 액티비티를 활성화하도록 허용하지 않고자 하면, 달리 인텐트 필터가 더 필요하지 않습니다. "주요" 동작과 "시작 관리자" 범주가 있는 +액티비티는 하나뿐이어야 합니다(이전 예시 참조). 다른 애플리케이션에서 +사용할 수 없게 하고자 하는 액티비티에는 인텐트 필터가 있으면 안 됩니다. 이러한 액티비티는 명시적인 인텐트를 사용해 직접 시작할 수 있습니다(이 내용은 다음 섹션에서 논의).

      -

      그러나, 액티비티가 다른 애플리케이션(및 본인의 애플리케이션)에서 -전달된 암시적 인텐트에 응답하도록 하려면 액티비티에 추가로 인텐트 필터를 정의해야만 -합니다. 응답하게 하고자 하는 각 인텐트 유형별로 +

      그러나, 액티비티가 다른 애플리케이션(및 본인의 애플리케이션)에서 +전달된 암시적 인텐트에 응답하도록 하려면 액티비티에 추가로 인텐트 필터를 정의해야만 +합니다. 응답하게 하고자 하는 각 인텐트 유형별로 {@code <action>} 요소를 포함하는 {@code <intent-filter>}를 하나씩 포함시켜야 하며, 선택 사항으로 {@code <category>} 요소 및/또는 {@code -<data>} 요소를 포함시킬 수 있습니다. 이와 같은 요소는 액티비티가 응답할 수 있는 인텐트의 유형을 +<data>} 요소를 포함시킬 수 있습니다. 이와 같은 요소는 액티비티가 응답할 수 있는 인텐트의 유형을 나타냅니다.

      액티비티가 인텐트에 응답하는 방식에 관한 자세한 정보는 인텐트 및 인텐트 필터 @@ -215,15 +215,15 @@ setContentView()}에 전달해도 해당 레이아웃을 사용할 수 있습니

      액티비티 시작하기

      다른 액티비티를 시작하려면 {@link android.app.Activity#startActivity - startActivity()}를 호출한 다음 이에 시작하고자 하는 액티비티를 설명하는 {@link android.content.Intent}를 -전달하면 됩니다. 인텐트는 시작하고자 하는 액티비티를 정확히 나타내거나, 수행하고자 하는 작업의 -유형을 설명하는 것입니다(시스템이 적절한 액티비티를 선택하며, + startActivity()}를 호출한 다음 이에 시작하고자 하는 액티비티를 설명하는 {@link android.content.Intent}를 +전달하면 됩니다. 인텐트는 시작하고자 하는 액티비티를 정확히 나타내거나, 수행하고자 하는 작업의 +유형을 설명하는 것입니다(시스템이 적절한 액티비티를 선택하며, 이는 다른 애플리케이션에서 가져온 것일 수도 있습니다). 인텐트는 소량의 데이터를 운반하여 시작된 액티비티에서 사용할 수 있습니다.

      본인의 애플리케이션 안에서 작업하는 경우에는, 알려진 액티비티를 시작하기만 하면 되는 경우가 잦습니다. - 이렇게 하려면 시작하고자 하는 액티비티를 명시적으로 정의하는 인텐트를 클래스 이름을 + 이렇게 하려면 시작하고자 하는 액티비티를 명시적으로 정의하는 인텐트를 클래스 이름을 사용하여 생성하면 됩니다. 예를 들어, 다음은 한 액티비티가 {@code SignInActivity}라는 이름의 다른 액티비티를 시작하는 방법입니다.

      @@ -232,15 +232,15 @@ Intent intent = new Intent(this, SignInActivity.class); startActivity(intent);
      -

      그러나, 애플리케이션이 다른 몇 가지 동작을 수행하고자 할 수도 있습니다. 예를 들어 이메일 보내기, 문자 -메시지 보내기 또는 상태 업데이트 등을 액티비티의 데이터를 사용하여 수행하는 것입니다. 이 경우, 본인의 애플리케이션에 -그러한 동작을 수행할 자체 액티비티가 없을 수도 있습니다. 따라서 기기에 있는 다른 애플리케이션이 -제공하는 액티비티를 대신 활용하여 동작을 수행하도록 할 수 있습니다. 바로 이 부분에서 -인텐트의 진가가 발휘됩니다. 수행하고자 하는 동작을 설명하는 인텐트를 생성하면 +

      그러나, 애플리케이션이 다른 몇 가지 동작을 수행하고자 할 수도 있습니다. 예를 들어 이메일 보내기, 문자 +메시지 보내기 또는 상태 업데이트 등을 액티비티의 데이터를 사용하여 수행하는 것입니다. 이 경우, 본인의 애플리케이션에 +그러한 동작을 수행할 자체 액티비티가 없을 수도 있습니다. 따라서 기기에 있는 다른 애플리케이션이 +제공하는 액티비티를 대신 활용하여 동작을 수행하도록 할 수 있습니다. 바로 이 부분에서 +인텐트의 진가가 발휘됩니다. 수행하고자 하는 동작을 설명하는 인텐트를 생성하면 시스템이 적절한 액티비티를 다른 애플리케이션에서 시작하는 것입니다. 해당 인텐트를 처리할 수 있는 액티비티가 여러 개 있는 경우, 사용자가 어느 것을 사용할지 선택합니다. 예를 - 들어 사용자가 이메일 메시지를 보낼 수 있게 하려면, 다음과 같은 인텐트를 + 들어 사용자가 이메일 메시지를 보낼 수 있게 하려면, 다음과 같은 인텐트를 생성하면 됩니다.

      @@ -250,7 +250,7 @@ startActivity(intent);
       

      인텐트에 추가된 {@link android.content.Intent#EXTRA_EMAIL} 추가 사항은 이메일이 전송되어야 할 이메일 주소의 - 문자열 배열입니다. 이메일 애플리케이션이 이 인텐트에 + 문자열 배열입니다. 이메일 애플리케이션이 이 인텐트에 응답하면, 애플리케이션은 추가 사항이 제공한 문자열 배열을 읽어낸 다음 이를 이메일 작성 양식의 "수신" 필드에 배치합니다. 이 상황에서 이메일 애플리케이션의 액티비티가 시작되고 사용자가 작업을 끝내면 본인의 액티비티가 재개되는 것입니다.

      @@ -263,14 +263,14 @@ startActivity(intent);

      때로는 시작한 액티비티에서 결과를 받고 싶을 수도 있습니다. 그런 경우, ({@link android.app.Activity#startActivity startActivity()} 대신) {@link android.app.Activity#startActivityForResult - startActivityForResult()}를 호출해서 액티비티를 시작합니다. 그런 다음 후속 액티비티에서 결과를 + startActivityForResult()}를 호출해서 액티비티를 시작합니다. 그런 다음 후속 액티비티에서 결과를 받으려면, {@link android.app.Activity#onActivityResult onActivityResult()} 콜백 메서드를 구현합니다. 해당 후속 액티비티가 완료되면, 이것이 {@link android.content.Intent} 형식으로 결과를 {@link android.app.Activity#onActivityResult onActivityResult()} 메서드에 반환합니다.

      -

      예를 들어 사용자가 연락처 중에서 하나를 고를 수 있도록 하고 싶을 수 있습니다. -즉 여러분의 액티비티가 해당 연락처의 정보로 무언가 할 수 있도록 하는 것입니다. 그와 같은 인텐트를 생성하고 결과를 처리하려면 +

      예를 들어 사용자가 연락처 중에서 하나를 고를 수 있도록 하고 싶을 수 있습니다. +즉 여러분의 액티비티가 해당 연락처의 정보로 무언가 할 수 있도록 하는 것입니다. 그와 같은 인텐트를 생성하고 결과를 처리하려면 다음과 같이 하면 됩니다.

      @@ -299,7 +299,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       

      이 예시는 액티비티 결과를 처리하기 위해 {@link android.app.Activity#onActivityResult onActivityResult()} 메서드에서 사용해야 할 기본 논리를 나타낸 것입니다. 첫 번째 조건은 요청이 성공적인지 확인합니다. 요청에 성공했다면 -{@code resultCode}가 {@link android.app.Activity#RESULT_OK}가 됩니다. 또한, 이 결과가 응답하는 요청이 +{@code resultCode}가 {@link android.app.Activity#RESULT_OK}가 됩니다. 또한, 이 결과가 응답하는 요청이 알려져 있는지도 확인합니다. 이 경우에는 {@code requestCode}가 {@link android.app.Activity#startActivityForResult startActivityForResult()}와 함께 전송된 두 번째 매개변수와 일치합니다. 여기서부터 코드가 @@ -317,58 +317,58 @@ android.content.ContentResolver}가 콘텐츠 제공자에 대한 쿼리를 수

      액티비티 종료하기

      액티비티를 종료하려면 해당 액티비티의 {@link android.app.Activity#finish -finish()} 메서드를 호출하면 됩니다. +finish()} 메서드를 호출하면 됩니다. {@link android.app.Activity#finishActivity finishActivity()}를 호출하여 이전에 시작한 별도의 액티비티를 종료할 수도 있습니다.

      -

      참고: 대부분의 경우, 이와 같은 메서드를 사용하여 액티비티를 명시적으로 -종료해서는 안 됩니다. 다음 섹션에서 액티비티 수명 주기에 관해 논의한 바와 같이, -Android 시스템이 액티비티의 수명을 대신 관리해주므로 직접 액티비티를 종료하지 -않아도 됩니다. 이와 같은 메서드를 호출하면 예상되는 사용자 -환경에 부정적인 영향을 미칠 수 있으며, 따라서 사용자가 액티비티의 이 인스턴스에 돌아오는 것을 절대 바라지 않는 경우에만 +

      참고: 대부분의 경우, 이와 같은 메서드를 사용하여 액티비티를 명시적으로 +종료해서는 안 됩니다. 다음 섹션에서 액티비티 수명 주기에 관해 논의한 바와 같이, +Android 시스템이 액티비티의 수명을 대신 관리해주므로 직접 액티비티를 종료하지 +않아도 됩니다. 이와 같은 메서드를 호출하면 예상되는 사용자 +환경에 부정적인 영향을 미칠 수 있으며, 따라서 사용자가 액티비티의 이 인스턴스에 돌아오는 것을 절대 바라지 않는 경우에만 사용해야 합니다.

      액티비티 수명 주기 관리하기

      -

      콜백 메서드를 구현하여 액티비티의 수명 주기를 관리하는 것은 -강력하고 유연한 애플리케이션 개발에 -대단히 중요한 역할을 합니다. 액티비티의 수명 주기는 다른 액티비티와의 관계, +

      콜백 메서드를 구현하여 액티비티의 수명 주기를 관리하는 것은 +강력하고 유연한 애플리케이션 개발에 +대단히 중요한 역할을 합니다. 액티비티의 수명 주기는 다른 액티비티와의 관계, 액티비티의 작업과 백 스택 등에 직접적으로 영향을 받습니다.

      액티비티는 기본적으로 세 가지 상태로 존재할 수 있습니다.

      재개됨
      -
      액티비티가 화면 전경에 있으며 사용자의 초점이 맞춰져 있습니다 (이 상태를 때로는 +
      액티비티가 화면 전경에 있으며 사용자의 초점이 맞춰져 있습니다 (이 상태를 때로는 "실행 중"이라고 일컫기도 합니다).
      일시정지됨
      다른 액티비티가 전경에 나와 있고 사용자의 시선을 집중시키고 있지만, 이 액티비티도 여전히 표시되어 있습니다. 다시 말해, -다른 액티비티가 이 액티비티 위에 표시되어 있으며 해당 액티비티는 부분적으로 투명하거나 +다른 액티비티가 이 액티비티 위에 표시되어 있으며 해당 액티비티는 부분적으로 투명하거나 전체 화면을 덮지 않는 상태라는 뜻입니다. 일시정지된 액티비티는 완전히 살아있지만({@link android.app.Activity} -개체가 메모리에 보관되어 있고, 모든 상태 및 구성원 정보를 유지하며, +개체가 메모리에 보관되어 있고, 모든 상태 및 구성원 정보를 유지하며, 창 관리자에 붙어 있는 상태로 유지됨), 메모리가 극히 부족한 경우 시스템이 중단시킬 수 있습니다.
      정지됨
      -
      이 액티비티가 다른 액티비티에 완전히 가려진 상태입니다(액티비티가 이제 +
      이 액티비티가 다른 액티비티에 완전히 가려진 상태입니다(액티비티가 이제 "배경"에 위치함). 중단된 액티비티도 여전히 살아 있기는 마찬가지입니다({@link android.app.Activity} 개체가 메모리에 보관되어 있고, 모든 상태와 구성원 정보를 유지하시만 창 관리자에 붙어 있지 않음 -). 그러나, 이는 더 이상 사용자에게 표시되지 않으며 +). 그러나, 이는 더 이상 사용자에게 표시되지 않으며 다른 곳에 메모리가 필요하면 시스템이 종료시킬 수 있습니다.
      -

      액티비티가 일시정지 또는 중단된 상태이면, 시스템이 이를 메모리에서 삭제할 수 있습니다. 이러기 위해서는 -종료를 요청하거나({@link android.app.Activity#finish finish()} 메서드를 호출) 단순히 이 액티비티의 프로세스를 중단시키면 -됩니다. 액티비티가 다시 열릴 때에는(종료 또는 중단된 후에) 처음부터 다시 생성해야 +

      액티비티가 일시정지 또는 중단된 상태이면, 시스템이 이를 메모리에서 삭제할 수 있습니다. 이러기 위해서는 +종료를 요청하거나({@link android.app.Activity#finish finish()} 메서드를 호출) 단순히 이 액티비티의 프로세스를 중단시키면 +됩니다. 액티비티가 다시 열릴 때에는(종료 또는 중단된 후에) 처음부터 다시 생성해야 합니다.

      수명 주기 콜백 구현하기

      -

      위에서 설명한 바와 같이 액티비티가 여러 가지 상태를 오가며 전환되면, 이와 같은 내용이 -여러 가지 콜백 메서드를 통해 통지됩니다. 콜백 메서드는 모두 후크로서, -액티비티 상태가 변경될 때 적절한 작업을 하기 위해 이를 재정의할 수 있습니다. 다음의 골격 +

      위에서 설명한 바와 같이 액티비티가 여러 가지 상태를 오가며 전환되면, 이와 같은 내용이 +여러 가지 콜백 메서드를 통해 통지됩니다. 콜백 메서드는 모두 후크로서, +액티비티 상태가 변경될 때 적절한 작업을 하기 위해 이를 재정의할 수 있습니다. 다음의 골격 액티비티에는 기본 수명 주기 메서드가 각각 하나씩 포함되어 있습니다.

      @@ -410,51 +410,51 @@ public class ExampleActivity extends Activity {

      참고: 이와 같은 수명 주기 메서드를 구현하려면, 항상 슈퍼클래스 구현을 호출한 다음에만 다른 작업을 시작할 수 있습니다(위의 예시 참조).

      -

      이와 같은 메서드를 모두 합쳐 한 액티비티의 수명 주기 전체를 정의합니다. 이러한 메서드를 구현함으로써 +

      이와 같은 메서드를 모두 합쳐 한 액티비티의 수명 주기 전체를 정의합니다. 이러한 메서드를 구현함으로써 액티비티 수명 주기 내의 세 가지 중첩된 루프를 모니터링할 수 있습니다.

      • 한 액티비티의 전체 수명은 {@link android.app.Activity#onCreate onCreate()} 호출과 {@link -android.app.Activity#onDestroy} 호출 사이를 말합니다. 액티비티는 {@link android.app.Activity#onCreate onCreate()}에서 -"전체" 상태(레이아웃 정의 등)의 설정을 수행한 다음 나머지 리소스를 -모두 {@link android.app.Activity#onDestroy}에 해제해야 합니다. 예를 들어, -액티비티에 네트워크에서 데이터를 다운로드하기 위해 배경에서 실행 중인 스레드가 있는 경우, 이는 +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}에서 그 스레드를 중단할 수 있습니다.
      • 액티비티의 가시적 수명은 {@link android.app.Activity#onStart onStart()} 호출에서 {@link -android.app.Activity#onStop onStop()} 호출 사이를 말합니다. 이 기간 중에는 사용자가 액티비티를 화면에서 보고 이와 +android.app.Activity#onStop onStop()} 호출 사이를 말합니다. 이 기간 중에는 사용자가 액티비티를 화면에서 보고 이와 상호작용할 수 있습니다. 예컨대 {@link android.app.Activity#onStop onStop()}이 호출되어 - 새 액티비티가 시작되면 이 액티비티는 더 이상 표시되지 않게 됩니다. 이와 같은 두 가지 메서드 중에서 + 새 액티비티가 시작되면 이 액티비티는 더 이상 표시되지 않게 됩니다. 이와 같은 두 가지 메서드 중에서 사용자에게 액티비티를 표시하는 데 필요한 리소스를 유지하면 됩니다. 예를 들어, {@link android.app.Activity#onStart onStart()}에서 {@link android.content.BroadcastReceiver}를 등록하고 UI에 영향을 미치는 변화를 모니터링하고 -{@link android.app.Activity#onStop onStop()}에서 등록을 해제하면 사용자는 여러분이 무엇을 표시하고 있는지 더 이상 볼 수 +{@link android.app.Activity#onStop onStop()}에서 등록을 해제하면 사용자는 여러분이 무엇을 표시하고 있는지 더 이상 볼 수 없게 됩니다. 시스템은 액티비티의 전체 수명 내내 {@link android.app.Activity#onStart onStart()} 및 {@link -android.app.Activity#onStop onStop()}을 여러 번 호출할 수 있으며, 이때 +android.app.Activity#onStop onStop()}을 여러 번 호출할 수 있으며, 이때 액티비티는 사용자에게 표시되었다 숨겨지는 상태를 오가게 됩니다.

      • 액티비티의 전경 수명은 {@link android.app.Activity#onResume onResume()} 호출에서 {@link android.app.Activity#onPause -onPause()} 호출 사이를 말합니다. 이 기간 중에는 이 액티비티가 화면에서 다른 모든 액티비티 앞에 표시되며 사용자 입력도 +onPause()} 호출 사이를 말합니다. 이 기간 중에는 이 액티비티가 화면에서 다른 모든 액티비티 앞에 표시되며 사용자 입력도 여기에 집중됩니다. 액티비티는 전경에 나타났다 숨겨지는 전환을 자주 반복할 수 있습니다. 예를 들어 -, 기기가 절전 모드에 들어가거나 대화 상자가 -나타나면 {@link android.app.Activity#onPause onPause()}가 호출됩니다. 이 상태는 자주 전환될 수 있으므로, 이 두 가지 메서드의 코드는 +, 기기가 절전 모드에 들어가거나 대화 상자가 +나타나면 {@link android.app.Activity#onPause onPause()}가 호출됩니다. 이 상태는 자주 전환될 수 있으므로, 이 두 가지 메서드의 코드는 상당히 가벼워야 합니다. 그래야 전환이 느려 사용자를 기다리게 하는 일을 피할 수 있습니다.

      그림 1은 액티비티가 상태 사이에서 취할 수 있는 이와 같은 루프와 경로를 나타낸 것입니다. -직사각형이 액티비티가 여러 상태 사이를 전환할 때 작업을 수행하도록 +직사각형이 액티비티가 여러 상태 사이를 전환할 때 작업을 수행하도록 구현할 수 있는 콜백 메서드를 나타냅니다.

      그림 1. 액티비티 수명 주기입니다.

      -

      같은 수명 주기 콜백 메서드가 표 1에 나열되어 있으며, 이 표는 각 콜백 -메서드를 더욱 상세하게 설명하며 액티비티의 전반적인 -수명 주기 내에서 각 메서드의 위치를 나타내기도 합니다. 여기에는 콜백 메서드가 완료된 다음 +

      같은 수명 주기 콜백 메서드가 표 1에 나열되어 있으며, 이 표는 각 콜백 +메서드를 더욱 상세하게 설명하며 액티비티의 전반적인 +수명 주기 내에서 각 메서드의 위치를 나타내기도 합니다. 여기에는 콜백 메서드가 완료된 다음 시스템이 액티비티를 중단시킬 수 있는지 여부도 포함되어 있습니다.

      표 1. 액티비티 수명 주기 @@ -474,9 +474,9 @@ onPause()} 호출 사이를 말합니다. 이 기간 중에는 이 액티비티 {@link android.app.Activity#onCreate onCreate()} 액티비티가 처음 생성되었을 때 호출됩니다. - 이곳에서 일반적인 정적 설정을 모두 수행해야 합니다. -즉 보기 생성, 목록에 데이터 바인딩하기 등을 말합니다. 이 메서드에는 -액티비티의 이전 상태가 캡처된 경우 해당 상태를 포함한 + 이곳에서 일반적인 정적 설정을 모두 수행해야 합니다. +즉 보기 생성, 목록에 데이터 바인딩하기 등을 말합니다. 이 메서드에는 +액티비티의 이전 상태가 캡처된 경우 해당 상태를 포함한 번들 개체가 전달됩니다(이 문서 나중에 나오는 액티비티 상태 저장하기를 참조하십시오 ).

      이 뒤에는 항상 {@code onStart()}가 따라옵니다.

      @@ -508,7 +508,7 @@ onRestart()}      {@link android.app.Activity#onResume onResume()} 액티비티가 시작되고 사용자와 상호 작용하기 직전에 -호출됩니다. 이 시점에서 액티비티는 액티비티 +호출됩니다. 이 시점에서 액티비티는 액티비티 스택의 맨 위에 있으며, 사용자 입력이 입력되고 있습니다.

      이 뒤에는 항상 {@code onPause()}가 따라옵니다.

      아니요 @@ -517,10 +517,10 @@ onRestart()} {@link android.app.Activity#onPause onPause()} - 시스템이 다른 액티비티를 재개하기 직전에 -호출됩니다. 이 메서드는 일반적으로 데이터를 유지하기 위해 저장되지 않은 변경 사항을 -커밋하는 데, 애니메이션을 비롯하여 CPU를 소모하는 기타 작업을 중단하는 등 -여러 가지 용도에 사용됩니다. 이 메서드는 무슨 일을 하든 매우 빨리 끝내야 합니다. + 시스템이 다른 액티비티를 재개하기 직전에 +호출됩니다. 이 메서드는 일반적으로 데이터를 유지하기 위해 저장되지 않은 변경 사항을 +커밋하는 데, 애니메이션을 비롯하여 CPU를 소모하는 기타 작업을 중단하는 등 +여러 가지 용도에 사용됩니다. 이 메서드는 무슨 일을 하든 매우 빨리 끝내야 합니다. 이것이 반환될 때까지 다음 액티비티가 재개되지 않기 때문입니다.

      액티비티가 다시 전경으로 돌아오면 {@code onResume()}이 뒤에 따라오고 액티비티가 사용자에게 보이지 않게 되면{@code onStop()}이 뒤에 따라옵니다. @@ -544,11 +544,11 @@ onRestart()} {@link android.app.Activity#onDestroy onDestroy()} - 액티비티가 소멸되기 전에 호출됩니다. 이것이 액티비티가 받는 -마지막 호출입니다. 이것이 호출될 수 있는 경우는 액티비티가 + 액티비티가 소멸되기 전에 호출됩니다. 이것이 액티비티가 받는 +마지막 호출입니다. 이것이 호출될 수 있는 경우는 액티비티가 완료되는 중이라서(누군가가 여기에 {@link android.app.Activity#finish - finish()}를 호출해서)일 수도 있고, 시스템이 공간을 절약하기 위해 액티비티의 이 인스턴스를 일시적으로 소멸시키는 -중이기 때문일 수도 있습니다. 이와 같은 + finish()}를 호출해서)일 수도 있고, 시스템이 공간을 절약하기 위해 액티비티의 이 인스턴스를 일시적으로 소멸시키는 +중이기 때문일 수도 있습니다. 이와 같은 두 가지 시나리오는 {@link android.app.Activity#isFinishing isFinishing()} 메서드로 구분할 수 있습니다. @@ -558,49 +558,49 @@ onDestroy()}

      "완료 후 중단 가능?"이라는 레이블이 붙은 열은 - 시스템이 메서드가 반환된 후 액티비티 코드의 다른 줄을 실행하지 않고도 + 시스템이 메서드가 반환된 후 액티비티 코드의 다른 줄을 실행하지 않고도 언제든 이 액티비티를 호스팅하는 프로세스를 중단시킬 수 있는지 여부를 나타냅니다. 다음 세 가지 메서드가 "예"로 표시되어 있습니다({@link android.app.Activity#onPause onPause()}, {@link android.app.Activity#onStop onStop()} 및 {@link android.app.Activity#onDestroy onDestroy()}). {@link android.app.Activity#onPause onPause()}가 세 가지 메서드 중에서 첫 번째이므로, 액티비티가 생성되면 {@link android.app.Activity#onPause onPause()}는 프로세스가 지워지기 전에 -반드시 호출되는 마지막 메서드입니다. +반드시 호출되는 마지막 메서드입니다. 시스템이 비상 시에 메모리를 복구해야 할 경우, {@link android.app.Activity#onStop onStop()}와 {@link android.app.Activity#onDestroy onDestroy()}는 -호출되지 않을 수도 있습니다. 따라서, 중요한 영구적 데이터(사용자 편집 등)를 보관하기 위해 작성하는 경우에는 {@link android.app.Activity#onPause onPause()}를 사용해야 -합니다. 그러나, {@link android.app.Activity#onPause onPause()} 중에 -어느 정보를 유지해야 할지는 조심해서 선택해야 합니다. 이 메서드에 차단 절차가 있으면 -다음 액티비티로의 전환을 차단하고 사용자 경험을 느려지게 할 수 있기 +호출되지 않을 수도 있습니다. 따라서, 중요한 영구적 데이터(사용자 편집 등)를 보관하기 위해 작성하는 경우에는 {@link android.app.Activity#onPause onPause()}를 사용해야 +합니다. 그러나, {@link android.app.Activity#onPause onPause()} 중에 +어느 정보를 유지해야 할지는 조심해서 선택해야 합니다. 이 메서드에 차단 절차가 있으면 +다음 액티비티로의 전환을 차단하고 사용자 경험을 느려지게 할 수 있기 때문입니다.

      -

      중단 가능한 열에 "아니요"로 표시된 메서드는 액티비티를 호스팅하는 프로세스를 -보호하여 호출된 즉시 중단되지 않도록 방지합니다. 따라서 액티비티는 -{@link android.app.Activity#onPause onPause()}가 반환되는 시기부터 -{@link android.app.Activity#onResume onResume()}이 호출되는 시기 사이에 중단시킬 수 있습니다. 다시 중단시킬 수 있는 상태가 되려면 +

      중단 가능한 열에 "아니요"로 표시된 메서드는 액티비티를 호스팅하는 프로세스를 +보호하여 호출된 즉시 중단되지 않도록 방지합니다. 따라서 액티비티는 +{@link android.app.Activity#onPause onPause()}가 반환되는 시기부터 +{@link android.app.Activity#onResume onResume()}이 호출되는 시기 사이에 중단시킬 수 있습니다. 다시 중단시킬 수 있는 상태가 되려면 {@link android.app.Activity#onPause onPause()}가 다시 호출되어 반환되어야 합니다.

      -

      참고: 표 1에 나타난 이런 정의에 -따르면 엄밀히 말해 "중단 가능한" 것이 아닌 액티비티라도 시스템이 중단시킬 수는 있습니다. 다만 이것은 다른 리소스가 없는 -극단적인 상황에서만 발생합니다. 액티비티가 중단될 수 있는 시기가 +

      참고: 표 1에 나타난 이런 정의에 +따르면 엄밀히 말해 "중단 가능한" 것이 아닌 액티비티라도 시스템이 중단시킬 수는 있습니다. 다만 이것은 다른 리소스가 없는 +극단적인 상황에서만 발생합니다. 액티비티가 중단될 수 있는 시기가 언제인지는 프로세스 및 스레딩 문서에서 보다 자세히 논의합니다.

      액티비티 상태 저장하기

      -

      액티비티 수명 주기 관리하기 도입부에서는 액티비티가 -일시중지되거나 -중단되었더라도 액티비티의 상태는 그대로 유지된다고 잠시 언급한 바 있습니다. 이것은 -{@link android.app.Activity} 개체가 일시중지되거나 중단된 경우에도 -메모리 안에 그대로 보관되었기 때문에 가능합니다. 즉 이 액티비티의 구성원과 현재 상태에 대한 모든 정보가 아직 살아 있다는 뜻입니다. 따라서, 사용자가 -액티비티 내에서 변경한 모든 내용도 그대로 유지되어 액티비티가 전경으로 +

      액티비티 수명 주기 관리하기 도입부에서는 액티비티가 +일시중지되거나 +중단되었더라도 액티비티의 상태는 그대로 유지된다고 잠시 언급한 바 있습니다. 이것은 +{@link android.app.Activity} 개체가 일시중지되거나 중단된 경우에도 +메모리 안에 그대로 보관되었기 때문에 가능합니다. 즉 이 액티비티의 구성원과 현재 상태에 대한 모든 정보가 아직 살아 있다는 뜻입니다. 따라서, 사용자가 +액티비티 내에서 변경한 모든 내용도 그대로 유지되어 액티비티가 전경으로 돌아갈 때("재개"될 때) 그와 같은 변경 사항도 그대로 존재하게 됩니다.

      그러나 시스템이 메모리를 복구하기 위해 액티비티를 소멸시키는 경우에는 {@link -android.app.Activity} 개체가 소멸되므로 시스템이 액티비티의 상태를 온전히 유지한 채로 간단하게 재개할 수 없게 -됩니다. 대신, 사용자가 다시 이 액티비티로 이동해 오면 시스템이 {@link android.app.Activity} 개체를 -다시 생성해야 합니다. 하지만, 사용자는 시스템이 -해당 액티비티를 소멸시켰다가 다시 생성했다는 것을 모릅니다. +android.app.Activity} 개체가 소멸되므로 시스템이 액티비티의 상태를 온전히 유지한 채로 간단하게 재개할 수 없게 +됩니다. 대신, 사용자가 다시 이 액티비티로 이동해 오면 시스템이 {@link android.app.Activity} 개체를 +다시 생성해야 합니다. 하지만, 사용자는 시스템이 +해당 액티비티를 소멸시켰다가 다시 생성했다는 것을 모릅니다. 따라서 액티비티가 예전과 똑같을 것이라고 예상할 것입니다. 이런 상황에서는 액티비티 상태에 관한 정보를 저장할 수 있는 추가 콜백 메서드 {@link @@ -617,19 +617,19 @@ android.os.Bundle#putInt putInt()} 같은 메서드를 사용하여, 이 메서 android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}에게 전달합니다. 이들 메서드 중 하나를 사용하여 {@link android.os.Bundle}에서 저장된 상태를 추출하고 액티비티 상태 를 복원할 수 있습니다. 복구할 상태 정보가 없는 경우, 여러분에게 전달되는 {@link -android.os.Bundle}은 null입니다(액티비티가 처음 생성되었을 때 이런 경우가 +android.os.Bundle}은 null입니다(액티비티가 처음 생성되었을 때 이런 경우가 발생합니다).

      -

      그림 2. 액티비티의 상태가 온전한 채로 사용자의 -초점에 다시 돌아오는 데에는 두 가지 방식이 있습니다. 하나는 액티비티가 소멸되었다가 다시 생성되어 액티비티가 -이전에 저장된 상태를 복구해야 하는 경우, 다른 하나는 액티비티가 중단되었다가 재개되었으며 +

      그림 2. 액티비티의 상태가 온전한 채로 사용자의 +초점에 다시 돌아오는 데에는 두 가지 방식이 있습니다. 하나는 액티비티가 소멸되었다가 다시 생성되어 액티비티가 +이전에 저장된 상태를 복구해야 하는 경우, 다른 하나는 액티비티가 중단되었다가 재개되었으며 액티비티 상태가 온전히 유지된 경우입니다.

      참고: 상태를 저장할 필요가 없는 경우도 있으므로 액티비티가 소멸되기 전에 {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}가 호출된다는 보장은 없습니다 -(예컨대 사용자가 +(예컨대 사용자가 명시적으로 액티비티를 닫기 위해 뒤로 버튼을 눌러서 액티비티를 떠날 때가 이에 해당합니다). 시스템이 {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}를 호출하는 경우, {@link @@ -642,9 +642,9 @@ android.app.Activity#onSaveInstanceState onSaveInstanceState()}를 구현하지 android.app.Activity#onSaveInstanceState onSaveInstanceState()}가 일부 액티비티 상태를 복구합니다. 특히, 기본 구현은 레이아웃에서 {@link android.view.View}가 나올 때마다 해당하는 {@link -android.view.View#onSaveInstanceState onSaveInstanceState()} 메서드를 호출하고, 이 때문에 각 보기가 저장해야 하는 자체 관련 정보를 제공할 수 -있게 해줍니다. Android 프레임워크를 사용하는 위젯은 거의 대부분 이 메서드를 -필요에 따라 구현하므로, UI에 눈에 보이는 변경이 있으면 모두 자동으로 저장되며 액티비티를 다시 +android.view.View#onSaveInstanceState onSaveInstanceState()} 메서드를 호출하고, 이 때문에 각 보기가 저장해야 하는 자체 관련 정보를 제공할 수 +있게 해줍니다. Android 프레임워크를 사용하는 위젯은 거의 대부분 이 메서드를 +필요에 따라 구현하므로, UI에 눈에 보이는 변경이 있으면 모두 자동으로 저장되며 액티비티를 다시 생성하면 복구됩니다. 예를 들어, {@link android.widget.EditText} 위젯은 사용자가 입력한 모든 텍스트 를 저장하고 {@link android.widget.CheckBox} 위젯은 확인 여부를 저장합니다. 여러분이 해야 할 유일한 작업은 상태를 저장하고자 하는 각 위젯에 고유 ID({@code android:id} @@ -653,9 +653,9 @@ android.view.View#onSaveInstanceState onSaveInstanceState()} 메서드를 호출

      @@ -668,25 +668,25 @@ UI에서 복구된 값과 상관관계가 있을 수 있지만 이런 UI 값을 ).

      {@link -android.app.Activity#onSaveInstanceState onSaveInstanceState()}의 기본 구현이 UI 상태를 저장하는 데 도움이 되기 때문에, -추가 상태 정보를 저장하기 위해 이 메서드를 재정의하려면 +android.app.Activity#onSaveInstanceState onSaveInstanceState()}의 기본 구현이 UI 상태를 저장하는 데 도움이 되기 때문에, +추가 상태 정보를 저장하기 위해 이 메서드를 재정의하려면 작업을 하기 전에 항상{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}의 슈퍼클래스 구현 을 호출해야 합니다. 이와 마찬가지로 {@link -android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}를 재정의하는 경우, 이것의 슈퍼클래스 구현을 호출해야 하기도 합니다. +android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}를 재정의하는 경우, 이것의 슈퍼클래스 구현을 호출해야 하기도 합니다. 이렇게 해야 기본 구현이 보기 상태를 복구할 수 있습니다.

      참고: {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}의 호출이 보장되지 않으므로 이것은 액티비티의 일시적 상태(UI의 상태 -)를 기록하는 데에만 사용하고, 영구 데이터를 보관하는 데 사용해서는 안 됩니다. 대신, 사용자가 액티비티를 떠날 때 영구적인 데이터(데이터베이스에 저장되어야 +)를 기록하는 데에만 사용하고, 영구 데이터를 보관하는 데 사용해서는 안 됩니다. 대신, 사용자가 액티비티를 떠날 때 영구적인 데이터(데이터베이스에 저장되어야 하는 데이터 등)를 저장하려면 {@link android.app.Activity#onPause onPause()}를 사용해야 합니다.

      애플리케이션의 상태 저장 기능을 시험하는 좋은 방법은 기기를 회전해보고 화면 방향이 -바뀌는지 확인하는 것입니다. 화면 방향이 바뀌면 시스템은 액티비티를 -소멸시켰다가 다시 생성하여 새 화면 구성에서 이용할 수 있을지 모르는 대체 -리소스를 적용합니다. 이 이유 하나만으로도 액티비티가 다시 생성되었을 때 상태를 -완전히 복구할 수 있어야 한다는 점이 대단히 중요합니다. 사용자는 애플리케이션을 사용하면서 화면을 +바뀌는지 확인하는 것입니다. 화면 방향이 바뀌면 시스템은 액티비티를 +소멸시켰다가 다시 생성하여 새 화면 구성에서 이용할 수 있을지 모르는 대체 +리소스를 적용합니다. 이 이유 하나만으로도 액티비티가 다시 생성되었을 때 상태를 +완전히 복구할 수 있어야 한다는 점이 대단히 중요합니다. 사용자는 애플리케이션을 사용하면서 화면을 자주 돌리기 때문입니다.

      @@ -700,8 +700,8 @@ android.app.Activity#onCreate onCreate()}를 호출합니다). 이런 동작은 설계되었습니다 (예: 다양한 화면 방향과 크기에 대한 다양한 레이아웃).

      -

      액티비티를 적절히 설계하여 화면 방향 변경으로 인한 재시작을 감당할 수 있으며 -위에 설명한 것처럼 액티비티 상태를 복구할 수 있도록 하면, 애플리케이션이 액티비티 수명 주기에서 +

      액티비티를 적절히 설계하여 화면 방향 변경으로 인한 재시작을 감당할 수 있으며 +위에 설명한 것처럼 액티비티 상태를 복구할 수 있도록 하면, 애플리케이션이 액티비티 수명 주기에서 예기치 못한 이벤트가 일어나도 더욱 탄력적으로 복구될 수 있습니다.

      이러한 재시작을 처리하는 가장 좋은 방법은 이전 섹션에서 논의한 바와 같이 @@ -710,22 +710,22 @@ android.app.Activity#onCreate onCreate()}를 호출합니다). 이런 동작은 android.app.Activity#onRestoreInstanceState onRestoreInstanceState()}(또는 {@link android.app.Activity#onCreate onCreate()})를 사용하여 액티비티 상태를 저장하고 복구하는 것입니다.

      -

      런타임에 발생하는 구성 변경과 그 처리 방법에 대한 자세한 정보는 -런타임 변경 +

      런타임에 발생하는 구성 변경과 그 처리 방법에 대한 자세한 정보는 +런타임 변경 처리하기에 대한 가이드를 읽어보십시오.

      액티비티 조정하기

      -

      한 액티비티가 다른 액티비티를 시작하면, 둘 모두 수명 주기 전환을 겪습니다. 첫 번째 액티비티는 -일시중지하고 중단되는 반면(배경에서 계속 보이는 경우에는 중단되지 않습니다만), 다른 액티비티는 -생성되는 것입니다. 이와 같은 액티비티가 디스크 또는 다른 속에 저장된 데이터를 공유하는 경우, -첫 번째 액티비티는 두 번째 액티비티가 생성되기 전에 완전히 중단되지 않는다는 점을 이해하는 것이 중요합니다. +

      한 액티비티가 다른 액티비티를 시작하면, 둘 모두 수명 주기 전환을 겪습니다. 첫 번째 액티비티는 +일시중지하고 중단되는 반면(배경에서 계속 보이는 경우에는 중단되지 않습니다만), 다른 액티비티는 +생성되는 것입니다. 이와 같은 액티비티가 디스크 또는 다른 속에 저장된 데이터를 공유하는 경우, +첫 번째 액티비티는 두 번째 액티비티가 생성되기 전에 완전히 중단되지 않는다는 점을 이해하는 것이 중요합니다. 그렇다기보다는, 두 번째 액티비티의 시작 과정이 첫 번째 액티비티 중단 과정과 겹쳐 일어납니다.

      -

      수명 주기 콜백은 분명히 정의된 순서가 있으며 특히 두 개의 액티비티가 +

      수명 주기 콜백은 분명히 정의된 순서가 있으며 특히 두 개의 액티비티가 같은 프로세스 안에 있으면서 하나가 다른 하나를 시작하는 경우 순서가 더욱 확실합니다. 다음은 액티비티 A가 액티비티 B를 시작할 때 발생하는 작업 순서입니다.

      @@ -741,8 +741,8 @@ android.app.Activity#onStop onStop()} 메서드가 실행됩니다.

      이처럼 수명 주기 콜백의 순서를 예측할 수 있기 때문에 한 액티비티에서 다른 액티비티로 전환되는 - 정보를 관리할 수 있습니다. 예를 들어 첫 번째 액티비티가 중단될 때 데이터베이스에 -내용을 작성해서 다음 액티비티가 그 내용을 읽을 수 있도록 하려면, 데이터베이스에는 + 정보를 관리할 수 있습니다. 예를 들어 첫 번째 액티비티가 중단될 때 데이터베이스에 +내용을 작성해서 다음 액티비티가 그 내용을 읽을 수 있도록 하려면, 데이터베이스에는 {@link android.app.Activity#onPause onPause()} 중에({@link android.app.Activity#onStop onStop()} 중이 아니라) 쓰기 작업을 해야 합니다.

      diff --git a/docs/html-intl/intl/ko/guide/components/bound-services.jd b/docs/html-intl/intl/ko/guide/components/bound-services.jd index bf97b260a7dad1c70405dd18841529086a47707f..276ff24111bb61bd78c36dae789fbfc2518473fb 100644 --- a/docs/html-intl/intl/ko/guide/components/bound-services.jd +++ b/docs/html-intl/intl/ko/guide/components/bound-services.jd @@ -41,22 +41,22 @@ parent.link=services.html
  • -

    바인딩된 서비스란 클라이언트 서버 인터페이스 안의 서버를 말합니다. 바인딩된 서비스를 사용하면 구성 요소(활동 등)를 -서비스에 바인딩되게 하거나, 요청을 보내고 응답을 수신하며 심지어는 +

    바인딩된 서비스란 클라이언트 서버 인터페이스 안의 서버를 말합니다. 바인딩된 서비스를 사용하면 구성 요소(활동 등)를 +서비스에 바인딩되게 하거나, 요청을 보내고 응답을 수신하며 심지어는 프로세스간 통신(IPC)까지 수행할 수 있게 됩니다. 일반적으로 바인딩된 서비스는 다른 애플리케이션 구성 요소를 도울 때까지만 살고 배경에서 무한히 실행되지 않습니다.

    이 문서는 다른 애플리케이션 구성 요소의 -서비스에 바인딩하는 방법을 포함하여 바인딩된 서비스를 만드는 방법을 보여줍니다. 하지만 일반적인 서비스에 관한 정보도 알아두는 것이 좋습니다. -서비스에서 알림을 전달하는 방법이나 서비스를 전경에서 실행되도록 설정하는 방법 등 여러 가지 +서비스에 바인딩하는 방법을 포함하여 바인딩된 서비스를 만드는 방법을 보여줍니다. 하지만 일반적인 서비스에 관한 정보도 알아두는 것이 좋습니다. +서비스에서 알림을 전달하는 방법이나 서비스를 전경에서 실행되도록 설정하는 방법 등 여러 가지 추가 정보를 알아보려면 서비스 문서를 참조하십시오.

    기본 정보

    -

    바인딩된 서비스란 일종의 {@link android.app.Service} 클래스 구현으로, -이를 통해 다른 애플리케이션이 이 서비스에 바인딩하여 상호 작용할 수 있도록 해주는 것입니다. 한 서비스에 대한 바인딩을 제공하려면, -{@link android.app.Service#onBind onBind()} 콜백 메서드를 구현해야 합니다. +

    바인딩된 서비스란 일종의 {@link android.app.Service} 클래스 구현으로, +이를 통해 다른 애플리케이션이 이 서비스에 바인딩하여 상호 작용할 수 있도록 해주는 것입니다. 한 서비스에 대한 바인딩을 제공하려면, +{@link android.app.Service#onBind onBind()} 콜백 메서드를 구현해야 합니다. 이 메서드는 클라이언트가 서비스와 상호 작용하는 데 사용하는 프로그래밍 인터페이스를 정의하는 {@link android.os.IBinder} 개체를 반환합니다.

    @@ -65,24 +65,24 @@ parent.link=services.html

    시작된 서비스에 바인딩

    서비스 -문서에서 논의된 바와 같이, 시작되었으면서도 바인딩된 서비스를 만들 수 있습니다. 다시 말해, -{@link android.content.Context#startService startService()}를 호출하여 서비스를 시작할 수 있으며 +문서에서 논의된 바와 같이, 시작되었으면서도 바인딩된 서비스를 만들 수 있습니다. 다시 말해, +{@link android.content.Context#startService startService()}를 호출하여 서비스를 시작할 수 있으며 이를 통해 서비스가 무한히 실행되도록 할 수 있으며, {@link android.content.Context#bindService bindService()}를 호출하면 클라이언트가 해당 서비스에 바인딩되도록 할 수 있다는 것입니다. -

    서비스를 시작되고 바인딩되도록 허용한 다음 서비스가 시작되면 -시스템은 클라이언트가 모두 바인딩을 해제해도 서비스를 소멸시키지 않습니다. 대신, +

    서비스를 시작되고 바인딩되도록 허용한 다음 서비스가 시작되면 +시스템은 클라이언트가 모두 바인딩을 해제해도 서비스를 소멸시키지 않습니다. 대신, 직접 서비스를 확실히 중단시켜야 합니다. 그러려면 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link android.content.Context#stopService stopService()}를 호출하면 됩니다.

    보통은 {@link android.app.Service#onBind onBind()} 또는 {@link android.app.Service#onStartCommand onStartCommand()} -중 한 가지만 구현하지만, 둘 모두 구현해야 할 때도 있습니다. 예를 들어, 음악 플레이어의 경우 서비스를 무한히 실행하면서 -바인딩도 제공하도록 허용하는 것이 유용하다는 결론을 내릴 수 있습니다. 이렇게 하면, 한 액티비티가 서비스로 하여금 음악을 재생하도록 -시작한 다음 사용자가 애플리케이션을 떠나더라도 음악을 계속 재생하도록 할 수 있습니다. 그런 다음, 사용자가 애플리케이션으로 +중 한 가지만 구현하지만, 둘 모두 구현해야 할 때도 있습니다. 예를 들어, 음악 플레이어의 경우 서비스를 무한히 실행하면서 +바인딩도 제공하도록 허용하는 것이 유용하다는 결론을 내릴 수 있습니다. 이렇게 하면, 한 액티비티가 서비스로 하여금 음악을 재생하도록 +시작한 다음 사용자가 애플리케이션을 떠나더라도 음악을 계속 재생하도록 할 수 있습니다. 그런 다음, 사용자가 애플리케이션으로 다시 돌아오면 이 액티비티가 서비스를 바인딩하여 재생 제어권을 다시 획득할 수 있습니다.

    바인딩된 서비스 수명 주기 관리 - 관련 섹션을 꼭 읽어보십시오. 시작된 서비스에 바인딩을 + 관련 섹션을 꼭 읽어보십시오. 시작된 서비스에 바인딩을 추가할 때 서비스 수명 주기에 관한 자세한 정보를 얻을 수 있습니다.

    @@ -90,23 +90,23 @@ android.content.Context#stopService stopService()}를 호출하면 됩니다.

    클라이언트가 서비스에 바인딩하려면 {@link android.content.Context#bindService bindService()}를 호출하면 됩니다. 이 때, 반드시 {@link android.content.ServiceConnection}의 구현을 제공해야 하며 이것이 서비스와의 연결을 모니터링합니다. {@link -android.content.Context#bindService bindService()} 메서드는 값 없이 즉시 반환됩니다. -그러나 Android 시스템이 클라이언트와 서비스 사이의 +android.content.Context#bindService bindService()} 메서드는 값 없이 즉시 반환됩니다. +그러나 Android 시스템이 클라이언트와 서비스 사이의 연결을 만드는 경우, 시스템은 {@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}를 {@link -android.content.ServiceConnection}에서 호출하여 클라이언트가 서비스와 통신하는 데 사용할 수 있도록 {@link android.os.IBinder}를 +android.content.ServiceConnection}에서 호출하여 클라이언트가 서비스와 통신하는 데 사용할 수 있도록 {@link android.os.IBinder}를 전달하게 됩니다.

    -

    여러 클라이언트가 한 번에 서비스에 연결될 수 있습니다. 그러나, 시스템이 서비스의 -{@link android.app.Service#onBind onBind()} 메서드를 호출하여 {@link android.os.IBinder}를 검색하는 경우는 첫 번째 클라이언트가 -바인딩되는 경우뿐입니다. 시스템은 그 후 같은 {@link android.os.IBinder}를 바인딩되는 추가 +

    여러 클라이언트가 한 번에 서비스에 연결될 수 있습니다. 그러나, 시스템이 서비스의 +{@link android.app.Service#onBind onBind()} 메서드를 호출하여 {@link android.os.IBinder}를 검색하는 경우는 첫 번째 클라이언트가 +바인딩되는 경우뿐입니다. 시스템은 그 후 같은 {@link android.os.IBinder}를 바인딩되는 추가 클라이언트 모두에 전달하며 이때는 {@link android.app.Service#onBind onBind()}를 다시 호출하지 않습니다.

    마지막 클라이언트가 서비스에서 바인딩을 해제하면 시스템은 서비스를 소멸시킵니다( {@link android.content.Context#startService startService()}가 서비스를 시작했을 경우 제외).

    바인딩된 서비스를 구현할 때 가장 중요한 부분은 -{@link android.app.Service#onBind onBind()} 콜백 메서드가 반환하는 인터페이스를 정의하는 것입니다. +{@link android.app.Service#onBind onBind()} 콜백 메서드가 반환하는 인터페이스를 정의하는 것입니다. 서비스의 {@link android.os.IBinder} 인터페이스를 정의하는 방법에는 몇 가지가 있고, 다음 섹션에서는 각 기법에 관해 논의합니다.

    @@ -115,42 +115,42 @@ android.content.ServiceConnection}에서 호출하여 클라이언트가 서비

    바인딩된 서비스 생성

    바인딩을 제공하는 서비스를 생성할 때는 클라이언트가 서비스와 상호 작용하는 데 사용할 수 있는 프로그래밍 인터페이스를 제공하는 {@link android.os.IBinder} -를 제공해야 합니다. +를 제공해야 합니다. 인터페이스를 정의하는 방법은 세 가지가 있습니다.

    바인더 클래스 확장
    -
    서비스가 본인의 애플리케이션 전용이며 클라이언트와 같은 과정으로 실행되는 +
    서비스가 본인의 애플리케이션 전용이며 클라이언트와 같은 과정으로 실행되는 경우(이런 경우가 흔함), 인터페이스를 생성할 때 {@link android.os.Binder} 클래스를 - 확장하고 그 인스턴스를 -{@link android.app.Service#onBind onBind()}에서 반환하는 방식을 사용해야 합니다. 클라이언트가 {@link android.os.Binder}를 받으며, -이를 사용하여 {@link android.os.Binder} 구현 또는 심지어 {@link android.app.Service}에서 + 확장하고 그 인스턴스를 +{@link android.app.Service#onBind onBind()}에서 반환하는 방식을 사용해야 합니다. 클라이언트가 {@link android.os.Binder}를 받으며, +이를 사용하여 {@link android.os.Binder} 구현 또는 심지어 {@link android.app.Service}에서 사용할 수 있는 공개 메서드에 직접 액세스할 수 있습니다. -

    이것은 서비스가 본인의 애플리케이션을 위해 단순히 배경에서 작동하는 요소에 그치는 경우 -선호되는 기법입니다. 인터페이스를 생성할 때 이 방식을 사용하지 않는 유일한 이유는 +

    이것은 서비스가 본인의 애플리케이션을 위해 단순히 배경에서 작동하는 요소에 그치는 경우 +선호되는 기법입니다. 인터페이스를 생성할 때 이 방식을 사용하지 않는 유일한 이유는 서비스를 다른 애플리케이션에서나 별도의 프로세스에 걸쳐 사용하고 있는 경우뿐입니다.

    메신저 사용
    -
    인터페이스를 여러 프로세스에 걸쳐 적용되도록 해야 하는 경우, 서비스에 대한 -인터페이스를 {@link android.os.Messenger}로 생성할 수 있습니다. +
    인터페이스를 여러 프로세스에 걸쳐 적용되도록 해야 하는 경우, 서비스에 대한 +인터페이스를 {@link android.os.Messenger}로 생성할 수 있습니다. 이 방식을 사용하면 서비스가 여러 가지 유형의 {@link android.os.Message} 개체에 응답하는 {@link android.os.Handler}를 정의합니다. 이 {@link android.os.Handler} 가 {@link android.os.Messenger}의 기초이며, 이를 통해 클라이언트와 함께 {@link android.os.IBinder} 를 공유할 수 있게 되어 클라이언트가 {@link -android.os.Message} 개체를 사용해 서비스에 명령을 보낼 수 있게 해줍니다. 이외에도, 클라이언트가 자체적으로 {@link android.os.Messenger}를 +android.os.Message} 개체를 사용해 서비스에 명령을 보낼 수 있게 해줍니다. 이외에도, 클라이언트가 자체적으로 {@link android.os.Messenger}를 정의하여 서비스가 메시지를 돌려보낼 수 있도록 할 수도 있습니다.

    이것이 프로세스간 통신(IPC)을 수행하는 가장 간단한 방법입니다. {@link -android.os.Messenger}가 모든 요청을 단일 스레드에 대기하게 해서, 서비스를 스레드로부터 안전하게 +android.os.Messenger}가 모든 요청을 단일 스레드에 대기하게 해서, 서비스를 스레드로부터 안전하게 설계하지 않아도 되기 때문입니다.

    AIDL 사용하기
    -
    AIDL(Android Interface Definition Language)은 개체를 운영 체제가 이해할 수 있는 -원시 데이터로 구성 해제한 다음 여러 프로세스에 걸쳐 집결하여 IPC를 수행하기 위해 -필요한 모든 작업을 수행합니다. 이전 기법은 {@link android.os.Messenger}를 사용했는데, +
    AIDL(Android Interface Definition Language)은 개체를 운영 체제가 이해할 수 있는 +원시 데이터로 구성 해제한 다음 여러 프로세스에 걸쳐 집결하여 IPC를 수행하기 위해 +필요한 모든 작업을 수행합니다. 이전 기법은 {@link android.os.Messenger}를 사용했는데, 사실 그 기본 구조가 AIDL을 기반으로 하고 있는 것입니다. 위에서 언급한 바와 같이 {@link android.os.Messenger}는 단일 스레드에 모든 클라이언트 요청 -대기열을 생성하므로 서비스는 한 번에 요청을 하나씩 수신합니다. 그러나, -서비스가 동시에 여러 요청을 처리하도록 하고 싶은 경우에는 AIDL을 직접 사용해도 +대기열을 생성하므로 서비스는 한 번에 요청을 하나씩 수신합니다. 그러나, +서비스가 동시에 여러 요청을 처리하도록 하고 싶은 경우에는 AIDL을 직접 사용해도 됩니다. 이 경우, 서비스가 다중 스레딩을 할 수 있어야 하며 스레드로부터 안전하게 구축되었어야 합니다.

    AIDL을 직접 사용하려면 프로그래밍 인터페이스를 정의하는 {@code .aidl} 파일을 생성해야 합니다. Android SDK 도구는 @@ -159,10 +159,10 @@ android.os.Messenger}가 모든 요청을 단일 스레드에 대기하게 해

    -

    참고: 대부분의 애플리케이션의 경우, -바인딩된 서비스를 생성하기 위해 AIDL를 사용해서는 안 됩니다. -그러려면 다중 스레딩 기능이 필요할 수 있고, 따라서 더 복잡한 구현을 초래할 수 있기 때문입니다. 따라서 AIDL은 -대부분의 애플리케이션에 적합하지 않으므로 이 문서에서는 여러분의 서비스에 이를 이용하는 방법에 대해 다루지 않습니다. AIDL을 직접 사용해야 한다는 확신이 드는 경우, +

    참고: 대부분의 애플리케이션의 경우, +바인딩된 서비스를 생성하기 위해 AIDL를 사용해서는 안 됩니다. +그러려면 다중 스레딩 기능이 필요할 수 있고, 따라서 더 복잡한 구현을 초래할 수 있기 때문입니다. 따라서 AIDL은 +대부분의 애플리케이션에 적합하지 않으므로 이 문서에서는 여러분의 서비스에 이를 이용하는 방법에 대해 다루지 않습니다. AIDL을 직접 사용해야 한다는 확신이 드는 경우, AIDL 문서를 참조하십시오.

    @@ -172,12 +172,12 @@ android.os.Messenger}가 모든 요청을 단일 스레드에 대기하게 해

    바인더 클래스 확장

    서비스를 사용하는 것이 로컬 애플리케이션뿐이고 여러 프로세스에 걸쳐 작동할 필요가 없는 경우, -나름의 {@link android.os.Binder} 클래스를 구현하여 +나름의 {@link android.os.Binder} 클래스를 구현하여 클라이언트로 하여금 서비스 내의 공개 메서드에 직접 액세스할 수 있도록 할 수도 있습니다.

    -

    참고: 이것은 클라이언트와 서비스가 -같은 애플리케이션 및 프로세스에 있는 경우에만 통하며, 이 경우가 가장 보편적입니다. 이 방식이 잘 통하는 경우를 예로 들면, -음악 애플리케이션에서 자체 서비스에 액티비티를 바인딩하여 배경에서 음악을 재생하도록 해야 하는 +

    참고: 이것은 클라이언트와 서비스가 +같은 애플리케이션 및 프로세스에 있는 경우에만 통하며, 이 경우가 가장 보편적입니다. 이 방식이 잘 통하는 경우를 예로 들면, +음악 애플리케이션에서 자체 서비스에 액티비티를 바인딩하여 배경에서 음악을 재생하도록 해야 하는 경우가 있습니다.

    이렇게 설정하는 방법은 다음과 같습니다.

    @@ -185,7 +185,7 @@ android.os.Messenger}가 모든 요청을 단일 스레드에 대기하게 해
  • 서비스에서 다음 중 한 가지에 해당하는 {@link android.os.Binder}의 인스턴스를 생성합니다.
    • 클라이언트가 호출할 수 있는 공개 메서드 포함
    • -
    • 클라이언트가 호출할 수 있는 공개 메서드가 있는 현재{@link android.app.Service} +
    • 클라이언트가 호출할 수 있는 공개 메서드가 있는 현재{@link android.app.Service} 인스턴스를 반환
    • 클라이언트가 호출할 수 있는 공개 메서드가 포함된 서비스가 호스팅하는 다른 클래스의 인스턴스를 반환
    • @@ -193,16 +193,16 @@ android.os.Messenger}가 모든 요청을 단일 스레드에 대기하게 해
    • {@link android.app.Service#onBind onBind()} 콜백 메서드에서 이 {@link android.os.Binder}의 인스턴스를 반환합니다.
    • 클라이언트의 경우, {@link android.os.Binder}를 {@link -android.content.ServiceConnection#onServiceConnected onServiceConnected()} +android.content.ServiceConnection#onServiceConnected onServiceConnected()} 콜백 메서드에서 받아 제공된 메서드를 사용해 서비스를 바인딩하기 위해 호출합니다.
    • -

      참고: 서비스와 클라이언트가 같은 애플리케이션에 -있어야 하는 것은 그래야만 클라이언트가 반환된 개체를 캐스팅하여 해당 API를 적절하게 호출할 수 있기 때문입니다. 또한 -서비스와 클라이언트는 같은 프로세스에 있어야 하기도 합니다. 이 기법에서는 +

      참고: 서비스와 클라이언트가 같은 애플리케이션에 +있어야 하는 것은 그래야만 클라이언트가 반환된 개체를 캐스팅하여 해당 API를 적절하게 호출할 수 있기 때문입니다. 또한 +서비스와 클라이언트는 같은 프로세스에 있어야 하기도 합니다. 이 기법에서는 여러 프로세스에 걸친 집결 작업을 전혀 수행하지 않기 때문입니다.

      -

      예컨대, 어떤 서비스가 클라이언트에게 {@link android.os.Binder} 구현을 통해 서비스 내의 +

      예컨대, 어떤 서비스가 클라이언트에게 {@link android.os.Binder} 구현을 통해 서비스 내의 메서드에 액세스할 수 있도록 한다고 합시다.

      @@ -303,12 +303,12 @@ public class BindingActivity extends Activity {
       }
       
      -

      위 예시는 클라이언트가 +

      위 예시는 클라이언트가 {@link android.content.ServiceConnection} 구현과 {@link -android.content.ServiceConnection#onServiceConnected onServiceConnected()} 콜백을 사용하여 서비스에 바인딩하는 방법을 보여줍니다. 다음 +android.content.ServiceConnection#onServiceConnected onServiceConnected()} 콜백을 사용하여 서비스에 바인딩하는 방법을 보여줍니다. 다음 섹션에서는 서비스에 바인딩하는 이러한 과정에 대해 좀 더 자세한 정보를 제공합니다.

      -

      참고: 위 예시에서는 서비스에서 분명히 바인딩을 해제하지는 않습니다. +

      참고: 위 예시에서는 서비스에서 분명히 바인딩을 해제하지는 않습니다. 그러나 모든 클라이언트는 적절한 시점에 바인딩을 해제해야 합니다(액티비티가 일시 중지될 때 등).

      더 많은 샘플 코드를 보려면 ApiDemos에서 {@code @@ -326,26 +326,26 @@ LocalServiceActivities.java} 클래스를 참조하십시오.

      AIDL과 비교

      IPC를 수행해야 할 경우, 인터페이스에 대해 {@link android.os.Messenger}를 사용하는 것이 AIDL로 구현하는 것보다 간단합니다. 왜냐하면 {@link android.os.Messenger}는 -모든 호출을 서비스에 대기시키지만 순수한 AIDL 인터페이스는 +모든 호출을 서비스에 대기시키지만 순수한 AIDL 인터페이스는 서비스에 동시에 요청을 전송하여 다중 스레딩을 처리해야 하기 때문입니다.

      대부분의 애플리이션에서는 서비스가 다중 스레딩을 수행할 필요가 없으므로 {@link -android.os.Messenger}를 사용하면 호출을 한 번에 하나씩 처리할 수 있습니다. 서비스가 +android.os.Messenger}를 사용하면 호출을 한 번에 하나씩 처리할 수 있습니다. 서비스가 다중 스레딩되는 것이 중요한 경우, 인터페이스를 정의하는 데 AIDL을 사용해야 합니다.

      -

      서비스가 원격 프로세스와 통신해야 한다면 서비스에 인터페이스를 제공하는 데 -{@link android.os.Messenger}를 사용하면 됩니다. 이 기법을 사용하면 +

      서비스가 원격 프로세스와 통신해야 한다면 서비스에 인터페이스를 제공하는 데 +{@link android.os.Messenger}를 사용하면 됩니다. 이 기법을 사용하면 AIDL을 쓰지 않고도 프로세스간 통신(IPC)을 수행할 수 있게 해줍니다.

      다음은 {@link android.os.Messenger} 사용 방법을 간략하게 요약한 것입니다.

        -
      • 서비스가 클라이언트로부터 각 호출에 대해 콜백을 받는 {@link android.os.Handler}를 +
      • 서비스가 클라이언트로부터 각 호출에 대해 콜백을 받는 {@link android.os.Handler}를 구현합니다.
      • {@link android.os.Handler}를 사용하여 {@link android.os.Messenger} 개체를 생성합니다 (이것은 {@link android.os.Handler}에 대한 참조입니다).
      • -
      • {@link android.os.Messenger}가 {@link android.os.IBinder}를 생성하여 서비스가 +
      • {@link android.os.Messenger}가 {@link android.os.IBinder}를 생성하여 서비스가 {@link android.app.Service#onBind onBind()}로부터 클라이언트에게 반환하도록 합니다.
      • 클라이언트는 {@link android.os.IBinder}를 사용하여 {@link android.os.Messenger} (서비스의 {@link android.os.Handler}를 참조)를 인스턴트화하고, 이를 이용하여 @@ -356,8 +356,8 @@ handleMessage()} 메서드를 사용합니다.
      -

      이렇게 하면, 클라이언트가 서비스에서 호출할 "메서드"가 없습니다. 대신 클라이언트는 -"메시지"({@link android.os.Message} 개체)를 전달하여 서비스가 +

      이렇게 하면, 클라이언트가 서비스에서 호출할 "메서드"가 없습니다. 대신 클라이언트는 +"메시지"({@link android.os.Message} 개체)를 전달하여 서비스가 {@link android.os.Handler}로 받을 수 있도록 합니다.

      다음은 {@link android.os.Messenger} 인터페이스를 사용하는 간단한 예시 서비스입니다.

      @@ -406,7 +406,7 @@ public class MessengerService extends Service {

      클라이언트는 서비스가 반환한 {@link android.os.IBinder}에 기초하여 {@link android.os.Messenger}를 생성하고 {@link -android.os.Messenger#send send()}로 메시지를 전송하기만 하면 됩니다. 예를 들어, 다음은 +android.os.Messenger#send send()}로 메시지를 전송하기만 하면 됩니다. 예를 들어, 다음은 서비스에 바인딩하여 {@code MSG_SAY_HELLO} 메시지를 서비스에 전달하는 간단한 액티비티입니다.

      @@ -477,7 +477,7 @@ public class ActivityMessenger extends Activity {
       

      이 예시에는 서비스가 클라이언트에 응답하는 방식이 나타나 있지 않다는 것을 유념하십시오. 서비스가 응답하게 하려면 - 클라이언트에도 {@link android.os.Messenger}를 생성해야 합니다. + 클라이언트에도 {@link android.os.Messenger}를 생성해야 합니다. 클라이언트가 {@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} 콜백을 받으면 {@link android.os.Messenger#send send()}메서드의 {@link android.os.Message#replyTo} 매개변수에서 클라이언트의 {@link android.os.Messenger}를 포함하는 {@link android.os.Message}를 서비스에 전송합니다. @@ -493,7 +493,7 @@ MessengerServiceActivities.java}(클라이언트) 예시를 참조하십시

      서비스에 바인딩

      -

      애플리케이션 구성 요소(클라이언트)를 서비스에 바인딩하려면 +

      애플리케이션 구성 요소(클라이언트)를 서비스에 바인딩하려면 {@link android.content.Context#bindService bindService()}를 호출하면 됩니다. 그러면 Android system이 서비스의 {@link android.app.Service#onBind onBind()} 메서드를 호출하고, 이는 서비스와의 상호 작용을 위해 {@link android.os.IBinder}를 반환합니다.

      @@ -505,7 +505,7 @@ android.content.ServiceConnection}의 인스턴스를 생성하여 이를 {@link bindService()}에 전달해야 합니다. {@link android.content.ServiceConnection}에는 {@link android.os.IBinder}를 전달하기 위해 시스템이 호출하는 콜백 메서드가 포함됩니다.

      -

      참고: 서비스에 바인딩할 수 있는 것은 액티비티, 서비스 및 +

      참고: 서비스에 바인딩할 수 있는 것은 액티비티, 서비스 및 콘텐츠 제공자뿐입니다. 브로드캐스트 수신자로부터는 서비스에 바인딩할 수 없습니다.

      따라서, 클라이언트로부터 서비스에 바인딩하려면 다음과 같이 해야 합니다.

      @@ -514,12 +514,12 @@ bindService()}에 전달해야 합니다. {@link android.content.ServiceConnecti

      이 구현으로 두 가지 콜백 메서드를 재정의해야 합니다.

      {@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}
      -
      시스템이 이것을 호출하여 서비스의 +
      시스템이 이것을 호출하여 서비스의 {@link android.app.Service#onBind onBind()} 메서드가 반환한 {@link android.os.IBinder}를 전달합니다.
      {@link android.content.ServiceConnection#onServiceDisconnected onServiceDisconnected()}
      -
      Android 시스템이 이것을 호출하는 경우는 서비스로의 연결이 -예기치 못하게 끊어졌을 때, 즉 서비스가 충돌했거나 중단되었을 때 등입니다. +
      Android 시스템이 이것을 호출하는 경우는 서비스로의 연결이 +예기치 못하게 끊어졌을 때, 즉 서비스가 충돌했거나 중단되었을 때 등입니다. 클라이언트가 바인딩을 해제한다고 이것이 호출되지는 않습니다.
      @@ -527,19 +527,19 @@ onServiceDisconnected()} android.content.Context#bindService bindService()}를 호출하고 {@link android.content.ServiceConnection} 구현을 전달합니다.
    • 시스템이 {@link android.content.ServiceConnection#onServiceConnected -onServiceConnected()} 콜백 메서드를 호출하면, 인터페이스가 정의한 메서드를 사용하여 +onServiceConnected()} 콜백 메서드를 호출하면, 인터페이스가 정의한 메서드를 사용하여 서비스에 호출을 시작해도 됩니다.
    • 서비스로부터 연결을 해제하려면 {@link android.content.Context#unbindService unbindService()}를 호출합니다. -

      클라이언트가 소멸되면 이는 서비스에서 바인딩을 해제하게 되지만, -서비스와 상호 작용을 마쳤을 때 또는 액티비티가 일시 중지되었을 때에는 항상 바인딩을 해제해야 합니다. -이렇게 해야 서비스가 사용 중이 아닐 때에는 중지할 수 있습니다 +

      클라이언트가 소멸되면 이는 서비스에서 바인딩을 해제하게 되지만, +서비스와 상호 작용을 마쳤을 때 또는 액티비티가 일시 중지되었을 때에는 항상 바인딩을 해제해야 합니다. +이렇게 해야 서비스가 사용 중이 아닐 때에는 중지할 수 있습니다 (바인딩과 바인딩 해제의 적절한 시기는 아래에서 좀 더 논의합니다).

    • -

      예를 들어, 다음 코드 조각은 위와 같이 -바인더 클래스를 확장해서 생성한 서비스와 클라이언트를 연결합니다. 그러므로 이것이 해야 하는 일은 반환된 +

      예를 들어, 다음 코드 조각은 위와 같이 +바인더 클래스를 확장해서 생성한 서비스와 클라이언트를 연결합니다. 그러므로 이것이 해야 하는 일은 반환된 {@link android.os.IBinder}를 {@code LocalService} 클래스에 캐스팅하고 {@code LocalService} 인스턴스를 요청하는 것뿐입니다.

      @@ -564,7 +564,7 @@ private ServiceConnection mConnection = new ServiceConnection() { };
  • -

    이 {@link android.content.ServiceConnection}이 있으면 클라이언트는 +

    이 {@link android.content.ServiceConnection}이 있으면 클라이언트는 이것을 {@link android.content.Context#bindService bindService()}에 전달하여 서비스에 바인딩할 수 있습니다. 예:

    @@ -573,12 +573,12 @@ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
     
      -
    • {@link android.content.Context#bindService bindService()}의 첫 번째 매개변수는 바인딩할 서비스를 명시적으로 명명하는 -{@link android.content.Intent}입니다(인텐트는 +
    • {@link android.content.Context#bindService bindService()}의 첫 번째 매개변수는 바인딩할 서비스를 명시적으로 명명하는 +{@link android.content.Intent}입니다(인텐트는 암시적일 수 있음).
    • 두 번째 매개변수는 {@link android.content.ServiceConnection} 개체입니다.
    • 세 번째 매개변수는 바인딩 옵션을 나타내는 플래그입니다. 서비스를 생성하기 위해 보통은 {@link -android.content.Context#BIND_AUTO_CREATE}를 사용합니다(이미 살아 있는 상태가 아닌 경우). +android.content.Context#BIND_AUTO_CREATE}를 사용합니다(이미 살아 있는 상태가 아닌 경우). 가능한 기타 값은 {@link android.content.Context#BIND_DEBUG_UNBIND} 및 {@link android.content.Context#BIND_NOT_FOREGROUND}, 또는 값이 없는 경우 {@code 0}입니다.
    @@ -588,27 +588,27 @@ android.content.Context#BIND_AUTO_CREATE}를 사용합니다(이미 살아 있

    다음은 서비스에 바인딩하는 데 관한 몇 가지 중요한 참고 사항입니다.

      -
    • 항상 {@link android.os.DeadObjectException} 예외를 트래핑해야 합니다. +
    • 항상 {@link android.os.DeadObjectException} 예외를 트래핑해야 합니다. 이것은 연결이 끊어지면 발생합니다. 원격 메서드에 의해 발생하는 예외는 이것뿐입니다.
    • 개체는 여러 프로세스에 걸쳐 감안된 참조입니다.
    • 일반적으로, 클라이언트의 수명 주기를 결합하고 분해하는 순간을 일치시키면서 바인딩과 바인딩 해제를 페어링해야 합니다. 예:
        -
      • 액티비티가 눈에 보이는 동안에만 서비스와 상호 작용해야 한다면 +
      • 액티비티가 눈에 보이는 동안에만 서비스와 상호 작용해야 한다면 {@link android.app.Activity#onStart onStart()}에는 바인딩하고 {@link android.app.Activity#onStop onStop()}에는 바인딩을 해제해야 합니다.
      • 배경에서 중단되었을 때도 액티비티가 응답을 받게 하고 싶다면 {@link android.app.Activity#onCreate onCreate()}에는 바인딩하고 -{@link android.app.Activity#onDestroy onDestroy()} 중에는 바인딩을 해제합니다. -이때, 사용자의 액티비티가 서비스가 실행되는 시간 전체에서(배경에서라도) 서비스를 사용한다는 것을 유념해야 합니다. +{@link android.app.Activity#onDestroy onDestroy()} 중에는 바인딩을 해제합니다. +이때, 사용자의 액티비티가 서비스가 실행되는 시간 전체에서(배경에서라도) 서비스를 사용한다는 것을 유념해야 합니다. 서비스가 다른 프로세스에 있을 경우, 사용자가 프로세스의 가중치를 높이면 시스템이 이를 중단할 가능성이 높아집니다.

      참고: 일반적으로는, 액티비티의 {@link android.app.Activity#onResume onResume()}와 {@link android.app.Activity#onPause onPause()}에는 바인딩하거나 바인딩을 해제하지 말아야 합니다. 이러한 콜백은 모든 수명 주기 전환에서 발생하고 이런 전환에서 발생하는 처리는 -최소한으로 유지해야 하기 때문입니다. 또한, -사용자 애플리케이션의 여러 액티비티가 동일한 서비스에 바인딩되었고 +최소한으로 유지해야 하기 때문입니다. 또한, +사용자 애플리케이션의 여러 액티비티가 동일한 서비스에 바인딩되었고 두 액티비티 사이에 전환이 있을 경우, 현재 액티비티의 바인딩이 해제된 후(일시중지 중) 다음 액티비티가 바인딩하기 전(재개 중)에 서비스가 제거되었다가 다시 생성될 수 있습니다 (수명 주기를 조절하기 위한 이러한 액티비티 전환은 액티비티 @@ -624,8 +624,8 @@ RemoteService.java} 클래스를 참조하십시오.

      바인딩된 서비스 수명 주기 관리

      -

      서비스가 모든 클라이언트로부터 바인딩 해제되면, Android 시스템이 이를 소멸시킵니다(다만 -{@link android.app.Service#onStartCommand onStartCommand()}와도 함께 시작된 경우는 예외). +

      서비스가 모든 클라이언트로부터 바인딩 해제되면, Android 시스템이 이를 소멸시킵니다(다만 +{@link android.app.Service#onStartCommand onStartCommand()}와도 함께 시작된 경우는 예외). 따라서, 서비스가 순전히 바인딩된 서비스일 경우에는 해당 서비스의 수명 주기를 관리하지 않아도 됩니다. 클라이언트에 바인딩되었는지를 근거로 Android 시스템이 대신 관리해주기 때문입니다.

      diff --git a/docs/html-intl/intl/ko/guide/components/fragments.jd b/docs/html-intl/intl/ko/guide/components/fragments.jd index a41250c38d9ffd2104331a936ad78fa29069a498..96bf7a197649d3d42d218106f655b01cba2ffe1f 100644 --- a/docs/html-intl/intl/ko/guide/components/fragments.jd +++ b/docs/html-intl/intl/ko/guide/components/fragments.jd @@ -36,7 +36,7 @@ parent.link=activities.html
    • {@link android.app.FragmentManager}
    • {@link android.app.FragmentTransaction}
    • - +

      참고 항목

      1. 프래그먼트로 동적 UI 구축하기
      2. @@ -46,79 +46,79 @@ parent.link=activities.html -

        {@link android.app.Fragment}는 동작 또는 -{@link android.app.Activity} 내에서 사용자 인터페이스의 일부를 나타냅니다. 여러 개의 프래그먼트를 하나의 액티비티에 -조합하여 창이 여러 개인 UI를 구축할 수 있으며, 하나의 프래그먼트를 여러 액티비티에서 재사용할 수 있습니다. 프래그먼트는 자체 수명 주기를 가지고, 자체 입력 이벤트를 받으며, -액티비티 실행 중에 추가 및 제거가 가능한 액티비티의 모듈식 섹션이라고 -생각하면 됩니다(다른 액티비티에 +

        {@link android.app.Fragment}는 동작 또는 +{@link android.app.Activity} 내에서 사용자 인터페이스의 일부를 나타냅니다. 여러 개의 프래그먼트를 하나의 액티비티에 +조합하여 창이 여러 개인 UI를 구축할 수 있으며, 하나의 프래그먼트를 여러 액티비티에서 재사용할 수 있습니다. 프래그먼트는 자체 수명 주기를 가지고, 자체 입력 이벤트를 받으며, +액티비티 실행 중에 추가 및 제거가 가능한 액티비티의 모듈식 섹션이라고 +생각하면 됩니다(다른 액티비티에 재사용할 수 있는 "하위 액티비티"와 같은 개념).

        -

        프래그먼트는 항상 액티비티 내에 포함되어 있어야 하며 해당 프래그먼트의 수명 주기는 -호스트 액티비티의 수명 주기에 직접적으로 영향을 받습니다. 예를 들어 액티비티가 일시정지되는 경우, 그 안의 모든 프래그먼트도 -일시정지되며 액티비티가 소멸되면 모든 프래그먼트도 마찬가지로 소멸됩니다. 그러나 액티비티가 실행 중인 -동안에는(재개됨 수명 주기 상태에 있을 때를 말합니다) -각 프래그먼트를 추가 또는 제거하는 등 개별적으로 조작할 수 있습니다. 그와 같은 프래그먼트 트랜잭션을 -수행할 때에는 이를 액티비티가 관리하는 백 스택에도 -추가할 수 있습니다. 각 백 스택 항목이 발생한 프래그먼트 트랜잭션의 +

        프래그먼트는 항상 액티비티 내에 포함되어 있어야 하며 해당 프래그먼트의 수명 주기는 +호스트 액티비티의 수명 주기에 직접적으로 영향을 받습니다. 예를 들어 액티비티가 일시정지되는 경우, 그 안의 모든 프래그먼트도 +일시정지되며 액티비티가 소멸되면 모든 프래그먼트도 마찬가지로 소멸됩니다. 그러나 액티비티가 실행 중인 +동안에는(재개됨 수명 주기 상태에 있을 때를 말합니다) +각 프래그먼트를 추가 또는 제거하는 등 개별적으로 조작할 수 있습니다. 그와 같은 프래그먼트 트랜잭션을 +수행할 때에는 이를 액티비티가 관리하는 백 스택에도 +추가할 수 있습니다. 각 백 스택 항목이 발생한 프래그먼트 트랜잭션의 기록이 됩니다. 이 백 스택을 사용하면 사용자가 프래그먼트 트랜잭션을 거꾸로 돌릴 수 있습니다(뒤로 이동). 이때 뒤로 버튼을 누르면 됩니다.

        프래그먼트를 액티비티 레이아웃의 일부로 추가하는 경우, 이는 액티비티의 보기 계층 내부의 {@link -android.view.ViewGroup} 안에 살며, 해당 프래그먼트가 자신의 보기 +android.view.ViewGroup} 안에 살며, 해당 프래그먼트가 자신의 보기 레이아웃을 정의합니다. -프래그먼트를 액티비티 레이아웃에 삽입하려면 해당 프래그먼트를 -액티비티의 레이아웃 파일에서 {@code <fragment>} 요소로 선언하거나, 애플리케이션 코드에서 이를 -기존의 {@link android.view.ViewGroup}에 추가하면 됩니다. 그러나 프래그먼트가 -액티비티 레이아웃의 일부분이어야만 하는 것은 아닙니다. 나름의 UI가 없는 프래그먼트도 액티비티를 위한 +프래그먼트를 액티비티 레이아웃에 삽입하려면 해당 프래그먼트를 +액티비티의 레이아웃 파일에서 {@code <fragment>} 요소로 선언하거나, 애플리케이션 코드에서 이를 +기존의 {@link android.view.ViewGroup}에 추가하면 됩니다. 그러나 프래그먼트가 +액티비티 레이아웃의 일부분이어야만 하는 것은 아닙니다. 나름의 UI가 없는 프래그먼트도 액티비티를 위한 보이지 않는 작업자로 사용할 수 있습니다.

        -

        이 문서에서는 프래그먼트를 사용하도록 애플리케이션을 구축하는 법을 -설명합니다. 그중에는 프래그먼트를 액티비티의 백 스택에 추가했을 때 프래그먼트가 자신의 상태를 유지하는 방법, -액티비티 및 액티비티 내의 다른 프래그먼트와 이벤트를 공유하는 방법과 액티비티의 +

        이 문서에서는 프래그먼트를 사용하도록 애플리케이션을 구축하는 법을 +설명합니다. 그중에는 프래그먼트를 액티비티의 백 스택에 추가했을 때 프래그먼트가 자신의 상태를 유지하는 방법, +액티비티 및 액티비티 내의 다른 프래그먼트와 이벤트를 공유하는 방법과 액티비티의 작업 모음에 참가하는 법 등등 여러 가지가 포함됩니다.

        디자인 철학

        -

        Android가 프래그먼트를 처음 도입한 것은 Android 3.0(API 레벨 11)부터입니다. 기본적으로 -태블릿과 같은 큰 화면에서 보다 역동적이고 유연한 UI 디자인을 지원하는 것이 목적이었습니다. 태블릿의 화면은 -핸드셋 화면보다 훨씬 크기 때문에 UI 구성 요소를 조합하고 상호 교환할 공간이 -더 많습니다. 프래그먼트는 개발자가 보기 계층에 복잡한 변경 내용을 관리하지 않아도 -그러한 디자인을 사용할 수 있도록 해주는 것입니다. 한 액티비티의 레이아웃을 여러 프래그먼트로 나누면 -런타임에 액티비티의 외관을 수정할 수도 있고 그러한 변경 내용을 해당 액티비티가 관리하는 +

        Android가 프래그먼트를 처음 도입한 것은 Android 3.0(API 레벨 11)부터입니다. 기본적으로 +태블릿과 같은 큰 화면에서 보다 역동적이고 유연한 UI 디자인을 지원하는 것이 목적이었습니다. 태블릿의 화면은 +핸드셋 화면보다 훨씬 크기 때문에 UI 구성 요소를 조합하고 상호 교환할 공간이 +더 많습니다. 프래그먼트는 개발자가 보기 계층에 복잡한 변경 내용을 관리하지 않아도 +그러한 디자인을 사용할 수 있도록 해주는 것입니다. 한 액티비티의 레이아웃을 여러 프래그먼트로 나누면 +런타임에 액티비티의 외관을 수정할 수도 있고 그러한 변경 내용을 해당 액티비티가 관리하는 백 스택에 보존할 수도 있습니다.

        -

        예를 들어 뉴스 애플리케이션이라면 하나의 프래그먼트를 사용하여 -왼쪽에 기사 목록을 표시하도록 하고 또 다른 프래그먼트로 오른쪽에 기사 내용을 표시하도록 할 수 있습니다. 두 프래그먼트 모두 -한 액티비티에서 양쪽으로 나란히 나타나며, 각 프래그먼트에 나름의 수명 주기 콜백 메서드가 있고 -각자 사용자 입력 이벤트를 따로 처리하게 됩니다. 따라서, 사용자는 기사를 선택하는 데 한 액티비티를 쓰고 -기사를 읽는 데 또 다른 액티비티를 선택하는 대신에 같은 액티비티 안에서 기사를 선택하고 읽는 과정을 +

        예를 들어 뉴스 애플리케이션이라면 하나의 프래그먼트를 사용하여 +왼쪽에 기사 목록을 표시하도록 하고 또 다른 프래그먼트로 오른쪽에 기사 내용을 표시하도록 할 수 있습니다. 두 프래그먼트 모두 +한 액티비티에서 양쪽으로 나란히 나타나며, 각 프래그먼트에 나름의 수명 주기 콜백 메서드가 있고 +각자 사용자 입력 이벤트를 따로 처리하게 됩니다. 따라서, 사용자는 기사를 선택하는 데 한 액티비티를 쓰고 +기사를 읽는 데 또 다른 액티비티를 선택하는 대신에 같은 액티비티 안에서 기사를 선택하고 읽는 과정을 모두 끝낼 수 있는 것입니다. 이것은 그림 1에 나타낸 태블릿 레이아웃과 같습니다.

        -

        프래그먼트를 디자인할 때에는 각 프래그먼트를 모듈식이며 재사용 가능한 액티비티 구성 요소로 만들어야 합니다. -다시 말해, 각 프래그먼트가 나름의 레이아웃을 따로 정의하고 자기만의 수명 주기 콜백으로 자기 나름의 동작을 정의하기 때문에 -한 프래그먼트를 여러 액티비티에 포함시킬 수 있습니다. 그러므로 재사용을 염두에 두고 디자인하며 -한 프래그먼트를 또 다른 프래그먼트로부터 직접 조작하는 것은 삼가야 합니다. 이것은 특히 모듈식 프래그먼트를 사용하면 -프래그먼트 조합을 여러 가지 화면 크기에 맞춰 변경할 수 있도록 해주기 때문에 중요한 요점입니다. 태블릿과 핸드셋을 모두 지원하는 -애플리케이션을 디자인하는 경우, 사용 가능한 화면 공간을 토대로 사용자 경험을 최적화하도록 프래그먼트를 -여러 레이아웃 구성에 재사용할 수 있습니다. 예를 들어 핸드셋에서의 경우 -프래그먼트를 분리해서 단일 창 UI를 제공하도록 해야할 수 있습니다. 같은 액티비티 안에 하나 이상이 들어가지 않을 수 +

        프래그먼트를 디자인할 때에는 각 프래그먼트를 모듈식이며 재사용 가능한 액티비티 구성 요소로 만들어야 합니다. +다시 말해, 각 프래그먼트가 나름의 레이아웃을 따로 정의하고 자기만의 수명 주기 콜백으로 자기 나름의 동작을 정의하기 때문에 +한 프래그먼트를 여러 액티비티에 포함시킬 수 있습니다. 그러므로 재사용을 염두에 두고 디자인하며 +한 프래그먼트를 또 다른 프래그먼트로부터 직접 조작하는 것은 삼가야 합니다. 이것은 특히 모듈식 프래그먼트를 사용하면 +프래그먼트 조합을 여러 가지 화면 크기에 맞춰 변경할 수 있도록 해주기 때문에 중요한 요점입니다. 태블릿과 핸드셋을 모두 지원하는 +애플리케이션을 디자인하는 경우, 사용 가능한 화면 공간을 토대로 사용자 경험을 최적화하도록 프래그먼트를 +여러 레이아웃 구성에 재사용할 수 있습니다. 예를 들어 핸드셋에서의 경우 +프래그먼트를 분리해서 단일 창 UI를 제공하도록 해야할 수 있습니다. 같은 액티비티 안에 하나 이상이 들어가지 않을 수 있기 때문입니다.

        -

        그림 1. 프래그먼트가 정의한 두 가지 UI 모듈이 -태블릿 디자인에서는 하나의 액티비티로 조합될 수 있는 반면 핸드셋 디자인에서는 분리될 수 있다는 것을 +

        그림 1. 프래그먼트가 정의한 두 가지 UI 모듈이 +태블릿 디자인에서는 하나의 액티비티로 조합될 수 있는 반면 핸드셋 디자인에서는 분리될 수 있다는 것을 예시로 나타낸 것입니다.

        -

        예를 들어—뉴스 애플리케이션 예시를 계속 사용하겠습니다—이 애플리케이션을 태블릿 크기의 기기에서 실행하는 경우, -애플리케이션 내의 액티비티 A 안에 두 개의 프래그먼트를 포함시킬 수 있습니다. 그러나 -핸드셋 크기의 화면에서라면 두 프래그먼트를 모두 쓸 만큼 공간이 충분치 않습니다. -따라서 액티비티 A에는 기사 목록에 해당되는 프래그먼트만 포함하고, 사용자가 기사를 하나 선택하면 이것이 -액티비티 B를 시작합니다. 여기에 기사를 읽을 두 번째 프래그먼트가 포함되어 있습니다. 따라서 이 애플리케이션은 -서로 다른 조합으로 프래그먼트를 재사용함으로써 태블릿과 핸드셋을 둘 다 지원하는 +

        예를 들어—뉴스 애플리케이션 예시를 계속 사용하겠습니다—이 애플리케이션을 태블릿 크기의 기기에서 실행하는 경우, +애플리케이션 내의 액티비티 A 안에 두 개의 프래그먼트를 포함시킬 수 있습니다. 그러나 +핸드셋 크기의 화면에서라면 두 프래그먼트를 모두 쓸 만큼 공간이 충분치 않습니다. +따라서 액티비티 A에는 기사 목록에 해당되는 프래그먼트만 포함하고, 사용자가 기사를 하나 선택하면 이것이 +액티비티 B를 시작합니다. 여기에 기사를 읽을 두 번째 프래그먼트가 포함되어 있습니다. 따라서 이 애플리케이션은 +서로 다른 조합으로 프래그먼트를 재사용함으로써 태블릿과 핸드셋을 둘 다 지원하는 것입니다(그림 1 참조).

        -

        여러 가지 화면 구성에 맞게 여러 가지 프래그먼트 조합으로 애플리케이션을 디자인하는 법에 대한 자세한 정보는 +

        여러 가지 화면 구성에 맞게 여러 가지 프래그먼트 조합으로 애플리케이션을 디자인하는 법에 대한 자세한 정보는 태블릿 및 핸드셋 지원에 대한 가이드를 참조하십시오.

        @@ -132,36 +132,36 @@ android.view.ViewGroup} 안에 살며, 해당 프래그먼트가 자신의 보

        프래그먼트를 생성하려면 {@link android.app.Fragment}의 하위 클래스(또는 이의 기존 -하위 클래스)를 생성해야 합니다. {@link android.app.Fragment} 클래스에는 -{@link android.app.Activity}와 아주 유사해 보이는 코드가 있습니다. 여기에는 액티비티와 비슷한 콜백 메서드가 들어 있습니다. +하위 클래스)를 생성해야 합니다. {@link android.app.Fragment} 클래스에는 +{@link android.app.Activity}와 아주 유사해 보이는 코드가 있습니다. 여기에는 액티비티와 비슷한 콜백 메서드가 들어 있습니다. 예를 들어 {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onStart onStart()}, -{@link android.app.Fragment#onPause onPause()} 및 {@link android.app.Fragment#onStop onStop()} 등입니다. 사실, -기존 Android 애플리케이션을 변환하여 프래그먼트를 사용하도록 하려면 그저 -액티비티의 콜백 메서드에서 프래그먼트에 해당되는 콜백 메서드로 코드를 옮기기만 하면 +{@link android.app.Fragment#onPause onPause()} 및 {@link android.app.Fragment#onStop onStop()} 등입니다. 사실, +기존 Android 애플리케이션을 변환하여 프래그먼트를 사용하도록 하려면 그저 +액티비티의 콜백 메서드에서 프래그먼트에 해당되는 콜백 메서드로 코드를 옮기기만 하면 될 수도 있습니다.

        보통은 최소한 다음과 같은 수명 주기 메서드를 구현해야 합니다.

        {@link android.app.Fragment#onCreate onCreate()}
        -
        시스템은 프래그먼트를 생성할 때 이것을 호출합니다. 구현 내에서 프래그먼트의 기본 구성 요소 중 -프래그먼트가 일시정지되거나 중단되었다가 재개되었을 때 유지하고자 하는 것을 +
        시스템은 프래그먼트를 생성할 때 이것을 호출합니다. 구현 내에서 프래그먼트의 기본 구성 요소 중 +프래그먼트가 일시정지되거나 중단되었다가 재개되었을 때 유지하고자 하는 것을 초기화해야 합니다.
        {@link android.app.Fragment#onCreateView onCreateView()}
        -
        시스템은 프래그먼트가 자신의 사용자 인터페이스를 처음으로 그릴 시간이 되면 -이것을 호출합니다. 프래그먼트에 맞는 UI를 그리려면 메서드에서 {@link android.view.View}를 반환해야 합니다. -이 메서드는 프래그먼트 레이아웃의 루트입니다. 프래그먼트가 UI를 제공하지 않는 경우 null을 반환하면 +
        시스템은 프래그먼트가 자신의 사용자 인터페이스를 처음으로 그릴 시간이 되면 +이것을 호출합니다. 프래그먼트에 맞는 UI를 그리려면 메서드에서 {@link android.view.View}를 반환해야 합니다. +이 메서드는 프래그먼트 레이아웃의 루트입니다. 프래그먼트가 UI를 제공하지 않는 경우 null을 반환하면 됩니다.
        {@link android.app.Activity#onPause onPause()}
        -
        시스템이 이 메서드를 호출하는 것은 사용자가 프래그먼트를 떠난다는 -첫 번째 신호입니다(다만 이것이 항상 프래그먼트가 소멸 중이라는 뜻은 아닙니다). 현재 사용자 세션을 넘어서 -지속되어야 하는 변경 사항을 커밋하려면 보통 이곳에서 해아 합니다(사용자가 +
        시스템이 이 메서드를 호출하는 것은 사용자가 프래그먼트를 떠난다는 +첫 번째 신호입니다(다만 이것이 항상 프래그먼트가 소멸 중이라는 뜻은 아닙니다). 현재 사용자 세션을 넘어서 +지속되어야 하는 변경 사항을 커밋하려면 보통 이곳에서 해아 합니다(사용자가 돌아오지 않을 수 있기 때문입니다).
        -

        대부분의 애플리케이션은 각각의 프래그먼트에 이와 같은 메서드를 최소한 세 개씩 -구현해야 하지만, 프래그먼트 수명 주기의 여러 단계를 처리하려면 사용해야 하는 다른 콜백 메서드도 -많이 있습니다. 모든 수명 주기 콜백 메서드는 나중에 +

        대부분의 애플리케이션은 각각의 프래그먼트에 이와 같은 메서드를 최소한 세 개씩 +구현해야 하지만, 프래그먼트 수명 주기의 여러 단계를 처리하려면 사용해야 하는 다른 콜백 메서드도 +많이 있습니다. 모든 수명 주기 콜백 메서드는 나중에 프래그먼트 수명 주기 처리 섹션에서 더욱 상세히 논의할 것입니다.

        @@ -170,45 +170,45 @@ android.app.Fragment} 클래스 대신 확장하고자 하는 하위 클래스
        {@link android.app.DialogFragment}
        -
        부동 대화 창을 표시합니다. 이 클래스를 사용하여 대화를 생성하면 -{@link android.app.Activity} 클래스의 대화 도우미 메서드를 사용하는 것의 -좋은 대안책이 됩니다. 이렇게 하면 프래그먼트 대화를 액티비티가 관리하는 프래그먼트의 백 스택에 통합시킬 수 있어, +
        부동 대화 창을 표시합니다. 이 클래스를 사용하여 대화를 생성하면 +{@link android.app.Activity} 클래스의 대화 도우미 메서드를 사용하는 것의 +좋은 대안책이 됩니다. 이렇게 하면 프래그먼트 대화를 액티비티가 관리하는 프래그먼트의 백 스택에 통합시킬 수 있어, 사용자가 무시된 프래그먼트를 반환할 수 있도록 해주기 때문입니다.
        {@link android.app.ListFragment}
        어댑터가 관리하는 항목의 목록(예: {@link -android.widget.SimpleCursorAdapter})을 표시하며, {@link android.app.ListActivity}와 비슷합니다. +android.widget.SimpleCursorAdapter})을 표시하며, {@link android.app.ListActivity}와 비슷합니다. 이것은 목록 보기를 관리하는 데 쓰는 몇 가지 메서드를 제공합니다. 예를 들어 {@link -android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} 콜백을 +android.app.ListFragment#onListItemClick(ListView,View,int,long) onListItemClick()} 콜백을 제공하여 클릭 이벤트를 처리하는 것 등입니다.
        {@link android.preference.PreferenceFragment}
        -
        {@link android.preference.Preference} 객체의 계층을 목록으로 표시하며, -{@link android.preference.PreferenceActivity}와 비슷합니다. 이것은 +
        {@link android.preference.Preference} 객체의 계층을 목록으로 표시하며, +{@link android.preference.PreferenceActivity}와 비슷합니다. 이것은 애플리케이션에 대한 "설정" 액티비티를 생성할 때 유용합니다.

        사용자 인터페이스 추가하기

        -

        프래그먼트는 일반적으로 액티비티에 속한 사용자 인터페이스의 일부분으로 사용되며 +

        프래그먼트는 일반적으로 액티비티에 속한 사용자 인터페이스의 일부분으로 사용되며 자기 나름의 레이아웃으로 액티비티에 참가합니다.

        프래그먼트에 대해 레이아웃을 제공하려면 반드시 {@link -android.app.Fragment#onCreateView onCreateView()} 콜백 메서드를 구현해야 합니다. -이것은 프래그먼트가 자신의 레이아웃을 그릴 때가 되면 Android 시스템이 호출하는 것입니다. 이 메서드의 구현은 반드시 +android.app.Fragment#onCreateView onCreateView()} 콜백 메서드를 구현해야 합니다. +이것은 프래그먼트가 자신의 레이아웃을 그릴 때가 되면 Android 시스템이 호출하는 것입니다. 이 메서드의 구현은 반드시 {@link android.view.View}를 반환해야 합니다. 이것은 프래그먼트 레이아웃의 루트입니다.

        참고: 프래그먼트가 {@link -android.app.ListFragment}의 하위 클래스인 경우, 기본 구현이 +android.app.ListFragment}의 하위 클래스인 경우, 기본 구현이 {@link android.app.Fragment#onCreateView onCreateView()}로부터 {@link android.widget.ListView}를 반환하므로 이를 구현하지 않아도 됩니다.

        {@link -android.app.Fragment#onCreateView onCreateView()}로부터 레이아웃을 반환하려면 이를 XML에서 정의된 레이아웃 리소스로부터 팽창시키면 됩니다. 이를 돕기 위해 -{@link android.app.Fragment#onCreateView onCreateView()}가 +android.app.Fragment#onCreateView onCreateView()}로부터 레이아웃을 반환하려면 이를 XML에서 정의된 레이아웃 리소스로부터 팽창시키면 됩니다. 이를 돕기 위해 +{@link android.app.Fragment#onCreateView onCreateView()}가 {@link android.view.LayoutInflater} 객체를 제공합니다.

        -

        예를 들어 다음은 {@link android.app.Fragment}의 하위 클래스입니다. 이것이 +

        예를 들어 다음은 {@link android.app.Fragment}의 하위 클래스입니다. 이것이 {@code example_fragment.xml} 파일로부터 레이아웃을 로딩합니다.

        @@ -225,49 +225,49 @@ public static class ExampleFragment extends Fragment {
         
         
         

        {@link android.app.Fragment#onCreateView -onCreateView()}로 전달된 {@code container} 매개변수가 상위 {@link android.view.ViewGroup}이며(액티비티의 레이아웃으로부터), +onCreateView()}로 전달된 {@code container} 매개변수가 상위 {@link android.view.ViewGroup}이며(액티비티의 레이아웃으로부터), 이 안에 프래그먼트 레이아웃이 삽입됩니다. - {@code savedInstanceState} 매개변수는 일종의 {@link android.os.Bundle}로, -이것은 프래그먼트가 재개되는 중인 경우 프래그먼트의 이전 인스턴스에 대한 데이터를 -제공합니다(상태를 복원하는 것은 프래그먼트 수명 주기 + {@code savedInstanceState} 매개변수는 일종의 {@link android.os.Bundle}로, +이것은 프래그먼트가 재개되는 중인 경우 프래그먼트의 이전 인스턴스에 대한 데이터를 +제공합니다(상태를 복원하는 것은 프래그먼트 수명 주기 처리에서 좀 더 논의합니다).

        -

        {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} 메서드는 +

        {@link android.view.LayoutInflater#inflate(int,ViewGroup,boolean) inflate()} 메서드는 다음과 같은 세 개의 인수를 취합니다.

        • 팽창시키고자 하는 레이아웃의 리소스 ID.
        • 팽창된 레이아웃의 상위가 될 {@link android.view.ViewGroup}. {@code -container}를 전달해야 시스템이 레이아웃 매개변수를 팽창된 레이아웃의 루트 보기에 실행 중인 상위 보기에서 지정한 것과 같이 +container}를 전달해야 시스템이 레이아웃 매개변수를 팽창된 레이아웃의 루트 보기에 실행 중인 상위 보기에서 지정한 것과 같이 적용할 수 있으므로 이는 중요한 부분입니다.
        • 팽창된 레이아웃이 팽창 중에 {@link -android.view.ViewGroup}(두 번째 매개변수)에 첨부되어야 하는지를 나타내는 부울 값 (이 경우, +android.view.ViewGroup}(두 번째 매개변수)에 첨부되어야 하는지를 나타내는 부울 값 (이 경우, 이것은 거짓입니다. 시스템이 이미 팽창된 레이아웃을 {@code container} 안에 삽입하고 있기 때문입니다. 참을 전달하면 최종 레이아웃에 중복된 보기 그룹을 생성하게 됩니다).
        -

        이제 레이아웃을 제공하는 프래그먼트 생성하는 법을 알게 되셨습니다. 다음은 프래그먼트를 +

        이제 레이아웃을 제공하는 프래그먼트 생성하는 법을 알게 되셨습니다. 다음은 프래그먼트를 액티비티에 추가해야 합니다.

        액티비티에 프래그먼트 추가

        -

        프래그먼트는 보통 UI의 일부분으로 호스트 액티비티에 참가합니다. 이는 해당 액티비티의 -전반적인 보기 계층의 일부분으로 포함되게 됩니다. 프래그먼트를 액티비티 레이아웃에 추가하는 데에는 두 가지 방법이 +

        프래그먼트는 보통 UI의 일부분으로 호스트 액티비티에 참가합니다. 이는 해당 액티비티의 +전반적인 보기 계층의 일부분으로 포함되게 됩니다. 프래그먼트를 액티비티 레이아웃에 추가하는 데에는 두 가지 방법이 있습니다.

        • 프래그먼트를 액티비티의 레이아웃 파일 안에서 선언합니다. -

          이 경우, 프래그먼트에 대한 레이아웃 속성을 마치 -보기인 것처럼 나타낼 수 있습니다. 예를 들어 다음은 프래그먼트가 두 개 있는 +

          이 경우, 프래그먼트에 대한 레이아웃 속성을 마치 +보기인 것처럼 나타낼 수 있습니다. 예를 들어 다음은 프래그먼트가 두 개 있는 한 액티비티에 대한 레이아웃 파일을 나타낸 것입니다.

           <?xml version="1.0" encoding="utf-8"?>
          @@ -290,31 +290,31 @@ container} 안에 삽입하고 있기 때문입니다. 참을 전달하면 최
             

          {@code <fragment>} 안의 {@code android:name} 속성이 레이아웃 안에서 인스턴트화할 {@link android.app.Fragment} 클래스를 나타냅니다.

          -

          시스템은 이 액티비티 레이아웃을 생성할 때 레이아웃에서 지정된 각 프래그먼트를 인스턴트화하며 각각에 대해 -{@link android.app.Fragment#onCreateView onCreateView()} 메서드를 -호출하여 각 프래그먼트의 레이아웃을 검색합니다. 시스템은 프래그먼트가 반환한 {@link android.view.View}를 +

          시스템은 이 액티비티 레이아웃을 생성할 때 레이아웃에서 지정된 각 프래그먼트를 인스턴트화하며 각각에 대해 +{@link android.app.Fragment#onCreateView onCreateView()} 메서드를 +호출하여 각 프래그먼트의 레이아웃을 검색합니다. 시스템은 프래그먼트가 반환한 {@link android.view.View}를 {@code <fragment>} 요소 자리에 곧바로 삽입합니다.

          -

          참고: 각 프래그먼트에는 액티비티가 재시작되는 경우 -프래그먼트를 복구하기 위해 시스템이 사용할 수 있는 고유한 식별자가 필요합니다(그리고, 개발자는 이것을 사용하여 프래그먼트를 캡처해 -이를 제거하는 등 여러 가지 트랜잭션을 수행할 수 있습니다). 프래그먼트에 ID를 제공하는 데에는 +

          참고: 각 프래그먼트에는 액티비티가 재시작되는 경우 +프래그먼트를 복구하기 위해 시스템이 사용할 수 있는 고유한 식별자가 필요합니다(그리고, 개발자는 이것을 사용하여 프래그먼트를 캡처해 +이를 제거하는 등 여러 가지 트랜잭션을 수행할 수 있습니다). 프래그먼트에 ID를 제공하는 데에는 다음과 같은 세 가지 방법이 있습니다.

          • 고유한 ID와 함께 {@code android:id} 속성을 제공합니다.
          • 고유한 문자열과 함께 {@code android:tag} 속성을 제공합니다.
          • -
          • 위의 두 가지 중 어느 것도 제공하지 않으면, 시스템은 컨테이너 보기의 ID를 +
          • 위의 두 가지 중 어느 것도 제공하지 않으면, 시스템은 컨테이너 보기의 ID를 사용합니다.
        • 또는, 프로그래밍 방식으로 프래그먼트를 기존의 {@link android.view.ViewGroup}에 추가합니다. -

          액티비티가 실행 중인 동안에는 언제든 액티비티 레이아웃에 프래그먼트를 추가할 수 있습니다. 그저 프래그먼트를 배치할 +

          액티비티가 실행 중인 동안에는 언제든 액티비티 레이아웃에 프래그먼트를 추가할 수 있습니다. 그저 프래그먼트를 배치할 {@link android.view.ViewGroup}를 지정하기만 하면 됩니다.

          -

          액티비티 내에서 프래그먼트 트랜잭션을 수행하려면(프래그먼트 추가, 제거 또는 -교체 등), {@link android.app.FragmentTransaction}에서 가져온 API를 사용해야 합니다. +

          액티비티 내에서 프래그먼트 트랜잭션을 수행하려면(프래그먼트 추가, 제거 또는 +교체 등), {@link android.app.FragmentTransaction}에서 가져온 API를 사용해야 합니다. {@link android.app.FragmentTransaction}의 인스턴스를 {@link android.app.Activity}에서 가져오는 방법은 다음과 같습니다.

          @@ -323,7 +323,7 @@ FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.Fra
           

          그런 다음 {@link -android.app.FragmentTransaction#add(int,Fragment) add()} 메서드를 사용하여 프래그먼트를 추가하고, 추가할 프래그먼트와 이를 삽입할 +android.app.FragmentTransaction#add(int,Fragment) add()} 메서드를 사용하여 프래그먼트를 추가하고, 추가할 프래그먼트와 이를 삽입할 보기를 지정하면 됩니다. 예:

          @@ -332,11 +332,11 @@ fragmentTransaction.add(R.id.fragment_container, fragment);
           fragmentTransaction.commit();
           
          -

          {@link android.app.FragmentTransaction#add(int,Fragment) add()}에 -전달되는 첫 인수가 {@link android.view.ViewGroup}입니다. +

          {@link android.app.FragmentTransaction#add(int,Fragment) add()}에 +전달되는 첫 인수가 {@link android.view.ViewGroup}입니다. 여기에 프래그먼트가 리소스 ID가 지정한 바와 같이 배치되어야 하며, 두 번째 매개변수는 추가할 프래그먼트입니다.

          -{@link android.app.FragmentTransaction}을 변경하고 나면, 반드시 +{@link android.app.FragmentTransaction}을 변경하고 나면, 반드시 {@link android.app.FragmentTransaction#commit}을 호출해야 변경 내용이 적용됩니다.

        @@ -344,41 +344,41 @@ fragmentTransaction.commit();

        UI 없이 프래그먼트 추가

        -

        위의 예시에서는 UI를 제공하기 위해 프래그먼트를 액티비티에 추가하는 방법을 보여드렸습니다. 하지만 -추가로 UI를 제시하지 않고 액티비티에 대한 배경 동작을 제공하는 데에도 프래그먼트를 사용할 수 +

        위의 예시에서는 UI를 제공하기 위해 프래그먼트를 액티비티에 추가하는 방법을 보여드렸습니다. 하지만 +추가로 UI를 제시하지 않고 액티비티에 대한 배경 동작을 제공하는 데에도 프래그먼트를 사용할 수 있습니다.

        UI 없이 프래그먼트를 추가하려면 액티비티로부터 가져온 프래그먼트를 {@link -android.app.FragmentTransaction#add(Fragment,String)}을 사용하여 추가합니다(이때, 프래그먼트에 대해 -보기 ID보다는 고유한 문자열 "태그"를 제공합니다). 이렇게 하면 프래그먼트가 추가되지만, +android.app.FragmentTransaction#add(Fragment,String)}을 사용하여 추가합니다(이때, 프래그먼트에 대해 +보기 ID보다는 고유한 문자열 "태그"를 제공합니다). 이렇게 하면 프래그먼트가 추가되지만, 이것은 액티비티 레이아웃 안에 있는 보기와 연관되어 있지 않기 때문에 {@link android.app.Fragment#onCreateView onCreateView()}로의 호출은 받지 않습니다. 따라서 그 메서드는 구현하지 않아도 됩니다.

        -

        프래그먼트에 대해 문자열 태그를 제공하는 것은 엄밀히 말해 비 UI 프래그먼트에만 해당되는 것은 아닙니다. UI가 있는 -프래그먼트에도 문자열 태그를 제공할 수 있습니다. 하지만 프래그먼트에 -UI가 없는 경우라면 이를 식별할 방법은 문자열 태그뿐입니다. 액티비티에서 나중에 +

        프래그먼트에 대해 문자열 태그를 제공하는 것은 엄밀히 말해 비 UI 프래그먼트에만 해당되는 것은 아닙니다. UI가 있는 +프래그먼트에도 문자열 태그를 제공할 수 있습니다. 하지만 프래그먼트에 +UI가 없는 경우라면 이를 식별할 방법은 문자열 태그뿐입니다. 액티비티에서 나중에 프래그먼트를 가져오고자 하는 경우, {@link android.app.FragmentManager#findFragmentByTag findFragmentByTag()}를 사용해야 합니다.

        예를 들어 어떤 액티비티에서 UI 없이 프래그먼트를 배경 작업자로 사용한다고 가정해봅시다. 이것의 예로 {@code -FragmentRetainInstance.java} 샘플을 들 수 있으며 -이는 SDK 샘플에 포함되어 있고(Android SDK Manager를 통해 이용 가능), 시스템에는 +FragmentRetainInstance.java} 샘플을 들 수 있으며 +이는 SDK 샘플에 포함되어 있고(Android SDK Manager를 통해 이용 가능), 시스템에는 <sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java로 찾을 수 있습니다.

        프래그먼트 관리

        -

        액티비티 내의 프래그먼트를 관리하려면 {@link android.app.FragmentManager}를 사용해야 합니다. 이것을 +

        액티비티 내의 프래그먼트를 관리하려면 {@link android.app.FragmentManager}를 사용해야 합니다. 이것을 가져오려면 액티비티에서 {@link android.app.Activity#getFragmentManager()}를 호출하십시오.

        {@link android.app.FragmentManager}를 가지고 할 수 있는 여러 가지 일 중에 예를 들면 다음과 같습니다.

        • 액티비티 내에 존재하는 프래그먼트를 {@link -android.app.FragmentManager#findFragmentById findFragmentById()}로 가져오기(액티비티 레이아웃 내에서 +android.app.FragmentManager#findFragmentById findFragmentById()}로 가져오기(액티비티 레이아웃 내에서 UI를 제공하는 프래그먼트의 경우) 또는 {@link android.app.FragmentManager#findFragmentByTag -findFragmentByTag()}로 가져오기(UI를 제공하거나 하지 않는 프래그먼트의 경우).
        • +findFragmentByTag()}로 가져오기(UI를 제공하거나 하지 않는 프래그먼트의 경우).
        • 백 스택에서 프래그먼트를 {@link android.app.FragmentManager#popBackStack()}을 사용하여 튀어나오게 하기(사용자가 내린 뒤로 명령을 시뮬레이트함).
        • 백 스택에 변경 내용이 있는지 알아보기 위해 {@link @@ -388,18 +388,18 @@ android.app.FragmentManager#addOnBackStackChangedListener addOnBackStackChangedL

          이와 같은 메서드와 그 외 다른 메서드에 대한 자세한 정보는 {@link android.app.FragmentManager} 클래스 관련 문서를 참조하십시오.

          -

          이전 섹션에서 설명한 바와 같이 {@link android.app.FragmentManager}를 +

          이전 섹션에서 설명한 바와 같이 {@link android.app.FragmentManager}를 사용해서도 {@link android.app.FragmentTransaction} 을 열 수 있습니다. 이렇게 하면 프래그먼트 추가 및 제거 등 트랜잭션을 수행할 수 있게 해줍니다.

          프래그먼트 트랜잭션 수행

          -

          액티비티에서 프래그먼트를 사용하는 경우 특히 유용한 점은 사용자 상호 작용에 응답하여 추가, -제거, 교체 및 다른 작업을 수행할 수 있다는 것입니다. 액티비티에 적용한 +

          액티비티에서 프래그먼트를 사용하는 경우 특히 유용한 점은 사용자 상호 작용에 응답하여 추가, +제거, 교체 및 다른 작업을 수행할 수 있다는 것입니다. 액티비티에 적용한 변경 내용의 집합을 하나의 트랜잭션이라 칭합니다. 이것을 수행하려면 {@link -android.app.FragmentTransaction} 내의 API를 사용하면 됩니다. 해당 액티비티가 관리하는 백 스택에 행해진 각 트랜잭션을 -저장할 수도 있습니다. 이렇게 하면 사용자가 프래그먼트 변경 내역을 거쳐 뒤로 탐색할 수 있습니다(액티비티를 통과해 +android.app.FragmentTransaction} 내의 API를 사용하면 됩니다. 해당 액티비티가 관리하는 백 스택에 행해진 각 트랜잭션을 +저장할 수도 있습니다. 이렇게 하면 사용자가 프래그먼트 변경 내역을 거쳐 뒤로 탐색할 수 있습니다(액티비티를 통과해 뒤로 탐색하는 것과 비슷합니다).

          {@link android.app.FragmentTransaction}의 인스턴스를 {@link @@ -410,20 +410,20 @@ FragmentManager fragmentManager = {@link android.app.Activity#getFragmentManager FragmentTransaction fragmentTransaction = fragmentManager.{@link android.app.FragmentManager#beginTransaction()};

        -

        각 트랜잭션은 동시에 수행하고자 하는 여러 변경을 집합적으로 일컫는 말입니다. 주어진 +

        각 트랜잭션은 동시에 수행하고자 하는 여러 변경을 집합적으로 일컫는 말입니다. 주어진 트랜잭션에 대해 수행하고자 하는 모든 변경 사항을 설정하려면 {@link android.app.FragmentTransaction#add add()}, {@link android.app.FragmentTransaction#remove remove()}, -및 {@link android.app.FragmentTransaction#replace replace()}와 같은 메서드를 사용하면 됩니다. 그런 다음, +및 {@link android.app.FragmentTransaction#replace replace()}와 같은 메서드를 사용하면 됩니다. 그런 다음, 트랜잭션을 액티비티에 적용하려면 반드시 {@link android.app.FragmentTransaction#commit()}을 호출해야 합니다.

    하지만 {@link android.app.FragmentTransaction#commit()}을 호출하기 전에 먼저 호출해야 할 것이 있습니다. 바로 {@link -android.app.FragmentTransaction#addToBackStack addToBackStack()}입니다. -이렇게 해야 트랜잭션을 프래그먼트 트랜잭션의 백 스택에 추가할 수 있습니다. 이 백 스택을 액티비티가 관리하며, +android.app.FragmentTransaction#addToBackStack addToBackStack()}입니다. +이렇게 해야 트랜잭션을 프래그먼트 트랜잭션의 백 스택에 추가할 수 있습니다. 이 백 스택을 액티비티가 관리하며, 이를 통해 사용자가 이전 프래그먼트 상태로 되돌아갈 수 있습니다. 이때 뒤로 버튼을 누르면 됩니다.

    -

    예를 들어 다음은 한 프래그먼트를 다른 것으로 교체하고 이전 상태를 백 스택에 보존하는 법을 +

    예를 들어 다음은 한 프래그먼트를 다른 것으로 교체하고 이전 상태를 백 스택에 보존하는 법을 나타낸 것입니다.

    @@ -440,49 +440,49 @@ transaction.addToBackStack(null);
     transaction.commit();
     
    -

    이 예시에서 {@code newFragment}가 현재 레이아웃 컨테이너에 있는 +

    이 예시에서 {@code newFragment}가 현재 레이아웃 컨테이너에 있는 프래그먼트(있는 경우)를 교체합니다. 이는 {@code R.id.fragment_container} ID로 식별할 수 있습니다. {@link -android.app.FragmentTransaction#addToBackStack addToBackStack()}를 호출하면 교체 트랜잭션이 -백 스택에 저장되고, 따라서 사용자가 트랜잭션을 거꾸로 수행하여 +android.app.FragmentTransaction#addToBackStack addToBackStack()}를 호출하면 교체 트랜잭션이 +백 스택에 저장되고, 따라서 사용자가 트랜잭션을 거꾸로 수행하여 이전 프래그먼트를 도로 가져올 수 있습니다. 뒤로 버튼을 사용하면 됩니다.

    트랜잭션에 여러 개의 변경을 추가하고(예를 들어 또 다른 {@link android.app.FragmentTransaction#add add()} 또는 {@link android.app.FragmentTransaction#remove remove()}) {@link -android.app.FragmentTransaction#addToBackStack addToBackStack()}을 호출하면, {@link android.app.FragmentTransaction#commit commit()}을 호출하기 전에 적용된 모든 변경 내용이 -백 스택에 하나의 트랜잭션으로 추가되며, 뒤로 버튼을 누르면 +android.app.FragmentTransaction#addToBackStack addToBackStack()}을 호출하면, {@link android.app.FragmentTransaction#commit commit()}을 호출하기 전에 적용된 모든 변경 내용이 +백 스택에 하나의 트랜잭션으로 추가되며, 뒤로 버튼을 누르면 모두 한꺼번에 역행하게 됩니다.

    -

    {@link android.app.FragmentTransaction}에 변경 내용을 추가하는 순서는 중요하지 않습니다. +

    {@link android.app.FragmentTransaction}에 변경 내용을 추가하는 순서는 중요하지 않습니다. 다만 다음과 같은 예외가 있습니다.

    • {@link android.app.FragmentTransaction#commit()}을 마지막으로 호출해야만 합니다.
    • -
    • 같은 컨테이너에 여러 개의 프래그먼트를 추가하는 경우, 이를 추가하는 순서가 이들이 +
    • 같은 컨테이너에 여러 개의 프래그먼트를 추가하는 경우, 이를 추가하는 순서가 이들이 보기 계층에 나타나는 순서를 결정 짓습니다.

    프래그먼트를 제거하는 트랜잭션을 수행하면서 {@link android.app.FragmentTransaction#addToBackStack(String) -addToBackStack()}을 호출하지 않는 경우, -해당 프래그먼트는 트랜잭션이 적용되면 소멸되고 사용자가 이를 되짚어 탐색할 수 없게 됩니다. 반면에 -프래그먼트를 제거하면서 {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()}을 호출하면, -해당 프래그먼트는 중단되고 사용자가 뒤로 탐색하면 +addToBackStack()}을 호출하지 않는 경우, +해당 프래그먼트는 트랜잭션이 적용되면 소멸되고 사용자가 이를 되짚어 탐색할 수 없게 됩니다. 반면에 +프래그먼트를 제거하면서 {@link android.app.FragmentTransaction#addToBackStack(String) addToBackStack()}을 호출하면, +해당 프래그먼트는 중단되고 사용자가 뒤로 탐색하면 재개됩니다.

    -

    팁: 각 프래그먼트 트랜잭션에 대해 전환 애니메이션을 적용하려면 -커밋하기 전에 {@link android.app.FragmentTransaction#setTransition setTransition()}을 +

    팁: 각 프래그먼트 트랜잭션에 대해 전환 애니메이션을 적용하려면 +커밋하기 전에 {@link android.app.FragmentTransaction#setTransition setTransition()}을 호출하면 됩니다.

    -

    {@link android.app.FragmentTransaction#commit()}을 호출해도 그 즉시 트랜잭션을 수행하지는 -않습니다. 그보다는, 액티비티의 UI 스레드("주요" 스레드)를 스레드가 할 수 있는 한 빨리 +

    {@link android.app.FragmentTransaction#commit()}을 호출해도 그 즉시 트랜잭션을 수행하지는 +않습니다. 그보다는, 액티비티의 UI 스레드("주요" 스레드)를 스레드가 할 수 있는 한 빨리 이 트랜잭션을 수행하도록 일정을 예약하는 것에 가깝습니다. 하지만 필요한 경우 UI 스레드로부터 {@link -android.app.FragmentManager#executePendingTransactions()}를 호출하면 -{@link android.app.FragmentTransaction#commit()}이 제출한 트랜잭션을 즉시 실행할 수 있습니다. 트랜잭션이 +android.app.FragmentManager#executePendingTransactions()}를 호출하면 +{@link android.app.FragmentTransaction#commit()}이 제출한 트랜잭션을 즉시 실행할 수 있습니다. 트랜잭션이 다른 스레드의 작업에 대한 종속성이 아니라면 굳이 이렇게 해야만 하는 것은 아닙니다.

    주의: 트랜잭션을 적용할 때 {@link -android.app.FragmentTransaction#commit commit()}을 사용해도 되는 것은 액티비티가 그 상태를 -저장하기 전뿐입니다(사용자가 액티비티를 떠날 때). 그 시점 이후에 적용하려고 하면 예외가 -발생합니다. 이것은 액티비티를 복원해야 하는 경우 적용 이후의 상태가 손실될 수 +android.app.FragmentTransaction#commit commit()}을 사용해도 되는 것은 액티비티가 그 상태를 +저장하기 전뿐입니다(사용자가 액티비티를 떠날 때). 그 시점 이후에 적용하려고 하면 예외가 +발생합니다. 이것은 액티비티를 복원해야 하는 경우 적용 이후의 상태가 손실될 수 있기 때문입니다. 적용이 손실되어도 괜찮은 상황이라면, {@link android.app.FragmentTransaction#commitAllowingStateLoss()}를 사용하십시오.

    @@ -491,19 +491,19 @@ android.app.FragmentTransaction#commitAllowingStateLoss()}를 사용하십시오

    액티비티와 통신

    -

    {@link android.app.Fragment}는 -{@link android.app.Activity}로부터 독립적인 객체로 구현되었고 여러 개의 액티비티 안에서 사용할 수 있는 것이 사실이지만, +

    {@link android.app.Fragment}는 +{@link android.app.Activity}로부터 독립적인 객체로 구현되었고 여러 개의 액티비티 안에서 사용할 수 있는 것이 사실이지만, 프래그먼트의 주어진 인스턴스는 그것을 포함하고 있는 액티비티에 직접적으로 연결되어 있습니다.

    구체적으로 말하면, 이 프래그먼트는 {@link -android.app.Fragment#getActivity()}를 사용하여 {@link android.app.Activity} 인스턴스에 액세스하여 +android.app.Fragment#getActivity()}를 사용하여 {@link android.app.Activity} 인스턴스에 액세스하여 액티비티 레이아웃에서 보기를 찾는 것과 같은 작업을 손쉽게 수행할 수 있습니다.

     View listView = {@link android.app.Fragment#getActivity()}.{@link android.app.Activity#findViewById findViewById}(R.id.list);
     
    -

    이와 마찬가지로, 액티비티도 프래그먼트 안의 메서드를 호출할 수 있습니다. 그러려면 {@link android.app.FragmentManager}로부터의 +

    이와 마찬가지로, 액티비티도 프래그먼트 안의 메서드를 호출할 수 있습니다. 그러려면 {@link android.app.FragmentManager}로부터의 {@link android.app.Fragment}에 대한 참조를 가져와야 하며, 이때 {@link android.app.FragmentManager#findFragmentById findFragmentById()} 또는 {@link android.app.FragmentManager#findFragmentByTag findFragmentByTag()}를 사용합니다. 예:

    @@ -515,14 +515,14 @@ ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentBy

    액티비티로의 이벤트 콜백 생성

    -

    어떤 경우에는 프래그먼트로 하여금 액티비티와 이벤트를 공유하게 해야 할 수 있습니다. 이렇게 하기 위한 -한 가지 좋은 방법은 프래그먼트 내부의 콜백 인터페이스를 정의한 다음 해당 호스트 액티비티가 이를 구현하도록 -하는 것입니다. 액티비티가 인터페이스를 통해 콜백을 수신하면, 필요에 따라 그 정보를 레이아웃 내의 +

    어떤 경우에는 프래그먼트로 하여금 액티비티와 이벤트를 공유하게 해야 할 수 있습니다. 이렇게 하기 위한 +한 가지 좋은 방법은 프래그먼트 내부의 콜백 인터페이스를 정의한 다음 해당 호스트 액티비티가 이를 구현하도록 +하는 것입니다. 액티비티가 인터페이스를 통해 콜백을 수신하면, 필요에 따라 그 정보를 레이아웃 내의 다른 프래그먼트와 공유할 수 있습니다.

    -

    예를 들어 어떤 뉴스 애플리케이션에서 액티비티 하나에 프래그먼트가 두 개 있습니다. - 하나는 기사 목록을 표시(프래그먼트 A)하고 다른 하나는 기사 하나를 표시(프래그먼트 B)하는 경우 목록 항목이 선택되면 -프래그먼트 A가 액티비티에 알려야 프래그먼트 B에 해당 기사를 표시하라고 알릴 수 있습니다. 이 경우, +

    예를 들어 어떤 뉴스 애플리케이션에서 액티비티 하나에 프래그먼트가 두 개 있습니다. + 하나는 기사 목록을 표시(프래그먼트 A)하고 다른 하나는 기사 하나를 표시(프래그먼트 B)하는 경우 목록 항목이 선택되면 +프래그먼트 A가 액티비티에 알려야 프래그먼트 B에 해당 기사를 표시하라고 알릴 수 있습니다. 이 경우, {@code OnArticleSelectedListener} 인터페이스는 프래그먼트 A 내부에 선언됩니다.

    @@ -537,12 +537,12 @@ public static class FragmentA extends ListFragment {
     

    그러면 프래그먼트를 호스팅하는 액티비티가 {@code OnArticleSelectedListener} - 인터페이스를 -구현하고 {@code onArticleSelected()}를 재정의하여 프래그먼트 A로부터 일어난 이벤트를 -프래그먼트 B에 알립니다. 호스트 액티비티가 이 인터페이스를 구현하도록 + 인터페이스를 +구현하고 {@code onArticleSelected()}를 재정의하여 프래그먼트 A로부터 일어난 이벤트를 +프래그먼트 B에 알립니다. 호스트 액티비티가 이 인터페이스를 구현하도록 확실히 하려면 프래그먼트 A의 {@link android.app.Fragment#onAttach onAttach()} 콜백 메서드(프래그먼트를 액티비티에 추가할 때 시스템이 호출하는 것)가 {@code OnArticleSelectedListener}의 인스턴스를 인스턴트화해야 합니다. 이때 {@link android.app.Fragment#onAttach -onAttach()} 안으로 전달된 {@link android.app.Activity}를 +onAttach()} 안으로 전달된 {@link android.app.Activity}를 캐스팅하는 방법을 씁니다.

    @@ -562,14 +562,14 @@ public static class FragmentA extends ListFragment {
     }
     
    -

    액티비티가 인터페이스를 구현하지 않은 경우, 프래그먼트가 -{@link java.lang.ClassCastException}을 발생시킵니다. -성공 시, {@code mListener} 구성원이 액티비티의 -{@code OnArticleSelectedListener} 구현에 대한 참조를 보유하므로, 프래그먼트 A가 액티비티와 이벤트를 공유할 수 있습니다. -이때 {@code OnArticleSelectedListener} 인터페이스가 정의한 메서드를 호출하는 방법을 씁니다. 예를 들어 프래그먼트 A가 -{@link android.app.ListFragment}의 확장인 경우, +

    액티비티가 인터페이스를 구현하지 않은 경우, 프래그먼트가 +{@link java.lang.ClassCastException}을 발생시킵니다. +성공 시, {@code mListener} 구성원이 액티비티의 +{@code OnArticleSelectedListener} 구현에 대한 참조를 보유하므로, 프래그먼트 A가 액티비티와 이벤트를 공유할 수 있습니다. +이때 {@code OnArticleSelectedListener} 인터페이스가 정의한 메서드를 호출하는 방법을 씁니다. 예를 들어 프래그먼트 A가 +{@link android.app.ListFragment}의 확장인 경우, 사용자가 목록 항목을 클릭할 때마다 시스템이 프래그먼트 안의 {@link android.app.ListFragment#onListItemClick -onListItemClick()}을 호출하고, 그러면 이것이 {@code onArticleSelected()}를 호출하여 +onListItemClick()}을 호출하고, 그러면 이것이 {@code onArticleSelected()}를 호출하여 해당 이벤트를 액티비티와 공유하는 것입니다.

    @@ -588,42 +588,42 @@ public static class FragmentA extends ListFragment {
     

    {@link -android.app.ListFragment#onListItemClick onListItemClick()}에 전달된 {@code id} 매개변수가 클릭한 항목의 행 ID이며, +android.app.ListFragment#onListItemClick onListItemClick()}에 전달된 {@code id} 매개변수가 클릭한 항목의 행 ID이며, 액티비티(또는 다른 프래그먼트)가 이것을 사용해 애플리케이션의 {@link android.content.ContentProvider}에서 기사를 가져옵니다.

    콘텐츠 제공자 사용법에 대한 자세한 정보는 +href="{@docRoot}resources/samples/NotePad/index.html">NotePad sample. -->콘텐츠 제공자 사용법에 대한 자세한 정보는 콘텐츠 제공자 문서에서 이용하실 수 있습니다.

    작업 모음에 항목 추가

    -

    프래그먼트는 액티비티의 옵션 메뉴에(결과적으로 작업 모음에도) 메뉴 항목으로 참가할 수 있습니다. 이때 -{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}를 구현하는 방법을 씁니다. 이 메서드가 +

    프래그먼트는 액티비티의 옵션 메뉴에(결과적으로 작업 모음에도) 메뉴 항목으로 참가할 수 있습니다. 이때 +{@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}를 구현하는 방법을 씁니다. 이 메서드가 호출을 수신하도록 하려면, {@link android.app.Fragment#onCreate(Bundle) onCreate()} 중에 {@link -android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()}를 호출하여 프래그먼트가 -옵션 메뉴에 항목을 추가하고자 한다는 것을 나타내야 합니다(그렇지 않으면 해당 프래그먼트가 +android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()}를 호출하여 프래그먼트가 +옵션 메뉴에 항목을 추가하고자 한다는 것을 나타내야 합니다(그렇지 않으면 해당 프래그먼트가 {@link android.app.Fragment#onCreateOptionsMenu onCreateOptionsMenu()}로의 호출을 받지 못하게 됩니다).

    -

    그런 다음 프래그먼트로부터 옵션 메뉴에 추가하는 모든 항목은 기존의 메뉴 항목에 +

    그런 다음 프래그먼트로부터 옵션 메뉴에 추가하는 모든 항목은 기존의 메뉴 항목에 추가됩니다. 해당 프래그먼트는 메뉴 항목을 선택하면 {@link -android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}로의 콜백도 +android.app.Fragment#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}로의 콜백도 수신하게 됩니다.

    또한 프래그먼트 레이아웃에 보기를 등록하여 컨텍스트 메뉴를 제공하도록 할 수도 있습니다. 이때 {@link -android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}를 호출하면 됩니다. 사용자가 컨텍스트 메뉴를 열면, +android.app.Fragment#registerForContextMenu(View) registerForContextMenu()}를 호출하면 됩니다. 사용자가 컨텍스트 메뉴를 열면, 해당 프래그먼트가 {@link android.app.Fragment#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) onCreateContextMenu()}로의 호출을 받습니다. 사용자가 항목을 하나 선택하면, 해당 프래그먼트는 {@link android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}로의 호출을 받습니다.

    -

    참고: 프래그먼트는 추가한 각 메뉴 항목에 대해 '항목 선택됨' 콜백을 -하나씩 받게 되지만, 사용자가 메뉴 항목을 선택할 때 그에 상응하는 콜백을 가장 처음 받는 것은 -액티비티입니다. 액티비티가 구현한 '항목 선택됨' 콜백이 선택된 항목을 다루지 않는 경우, -해당 이벤트는 프래그먼트의 콜백으로 전달됩니다. 이것은 +

    참고: 프래그먼트는 추가한 각 메뉴 항목에 대해 '항목 선택됨' 콜백을 +하나씩 받게 되지만, 사용자가 메뉴 항목을 선택할 때 그에 상응하는 콜백을 가장 처음 받는 것은 +액티비티입니다. 액티비티가 구현한 '항목 선택됨' 콜백이 선택된 항목을 다루지 않는 경우, +해당 이벤트는 프래그먼트의 콜백으로 전달됩니다. 이것은 옵션 메뉴와 컨텍스트 메뉴에 모두 참입니다.

    메뉴에 대한 더 자세한 정보는 메뉴작업 모음 개발자 가이드를 참조하십시오.

    @@ -635,11 +635,11 @@ android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}로
    -

    그림 3. 액티비티 수명 주기가 프래그먼트 수명 주기에 미치는 +

    그림 3. 액티비티 수명 주기가 프래그먼트 수명 주기에 미치는 영향입니다.

    -

    프래그먼트의 수명 주기를 관리하는 것은 액티비티의 수명 주기를 관리하는 것과 매우 비슷합니다. 액티비티와 마찬가지로 +

    프래그먼트의 수명 주기를 관리하는 것은 액티비티의 수명 주기를 관리하는 것과 매우 비슷합니다. 액티비티와 마찬가지로 프래그먼트는 세 가지 상태로 존재할 수 있습니다.

    @@ -647,57 +647,57 @@ android.app.Fragment#onContextItemSelected(MenuItem) onContextItemSelected()}로
    프래그먼트가 실행 중인 액티비티에 표시됩니다.
    일시정지됨
    -
    또 다른 액티비티가 전경에 나와 있고 사용자가 이에 초점을 맞추고 있지만, -이 프래그먼트가 있는 액티비티도 여전히 표시되어 있습니다(전경의 액티비티가 부분적으로 투명하거나 +
    또 다른 액티비티가 전경에 나와 있고 사용자가 이에 초점을 맞추고 있지만, +이 프래그먼트가 있는 액티비티도 여전히 표시되어 있습니다(전경의 액티비티가 부분적으로 투명하거나 전체 화면을 뒤덮지 않습니다).
    정지됨
    -
    프래그먼트가 표시되지 않습니다. 호스트 액티비티가 정지되었거나 -프래그먼트가 액티비티에서 제거되었지만 백 스택에 추가되었습니다. 정지된 프래그먼트도 -여전히 표시는 됩니다(모든 상태 및 구성원 정보를 시스템이 보존합니다). 하지만, 사용자에게는 +
    프래그먼트가 표시되지 않습니다. 호스트 액티비티가 정지되었거나 +프래그먼트가 액티비티에서 제거되었지만 백 스택에 추가되었습니다. 정지된 프래그먼트도 +여전히 표시는 됩니다(모든 상태 및 구성원 정보를 시스템이 보존합니다). 하지만, 사용자에게는 더 이상 표시되지 않으며 액티비티를 종료하면 이것도 종료됩니다.

    이번에도 액티비티와 마찬가지로, 프래그먼트의 상태를 보존하려면 {@link -android.os.Bundle}을 사용합니다. 이는 혹시나 액티비티의 프로세스가 종료되고 액티비티를 +android.os.Bundle}을 사용합니다. 이는 혹시나 액티비티의 프로세스가 종료되고 액티비티를 다시 만들 때 해당 프래그먼트의 상태를 복구해야 할 필요가 있을 때를 대비하는 것입니다. 상태를 저장하려면 프래그먼트의 {@link -android.app.Fragment#onSaveInstanceState onSaveInstanceState()} 콜백 중에 저장할 수 있고, 복구는 +android.app.Fragment#onSaveInstanceState onSaveInstanceState()} 콜백 중에 저장할 수 있고, 복구는 {@link android.app.Fragment#onCreate onCreate()}, {@link android.app.Fragment#onCreateView onCreateView()} 또는 {@link -android.app.Fragment#onActivityCreated onActivityCreated()} 중 한 가지가 진행되는 동안 할 수 있습니다. 상태 저장에 관한 자세한 정보는 +android.app.Fragment#onActivityCreated onActivityCreated()} 중 한 가지가 진행되는 동안 할 수 있습니다. 상태 저장에 관한 자세한 정보는 액티비티 문서를 참조하십시오.

    -

    액티비티와 프래그먼트의 수명 주기에서 가장 중대한 차이점은 -해당되는 백 스택에 저장되는 방법입니다. 액티비티는 중단되었을 때 시스템이 관리하는 -액티비티 백 스택 안에 배치되는 것이 기본입니다(따라서 사용자가 뒤로 버튼을 사용하여 다시 이 액티비티로 -뒤로 탐색할 수 있습니다. 이 내용은 작업 및 백 스택에서 설명하였습니다). -하지만, 프래그먼트가 호스트 액티비티가 관리하는 백 스택 안에 배치되는 것은 해당 인스턴스를 저장하라고 명시적으로 요청하는 경우뿐입니다. +

    액티비티와 프래그먼트의 수명 주기에서 가장 중대한 차이점은 +해당되는 백 스택에 저장되는 방법입니다. 액티비티는 중단되었을 때 시스템이 관리하는 +액티비티 백 스택 안에 배치되는 것이 기본입니다(따라서 사용자가 뒤로 버튼을 사용하여 다시 이 액티비티로 +뒤로 탐색할 수 있습니다. 이 내용은 작업 및 백 스택에서 설명하였습니다). +하지만, 프래그먼트가 호스트 액티비티가 관리하는 백 스택 안에 배치되는 것은 해당 인스턴스를 저장하라고 명시적으로 요청하는 경우뿐입니다. 이때 프래그먼트를 제거하는 트랜잭션 중 {@link -android.app.FragmentTransaction#addToBackStack(String) addToBackStack()}을 +android.app.FragmentTransaction#addToBackStack(String) addToBackStack()}을 호출합니다.

    -

    이것만 제외하면, 프래그먼트 수명 주기를 관리하는 것은 액티비티의 수명 주기를 관리하는 것과 -아주 비슷합니다. 따라서, 액티비티 -수명 주기 관리에 쓰이는 실례가 프래그먼트에도 똑같이 적용되는 것입니다. 하지만 또 한 가지 이해해두어야 하는 것이 있습니다. 즉, +

    이것만 제외하면, 프래그먼트 수명 주기를 관리하는 것은 액티비티의 수명 주기를 관리하는 것과 +아주 비슷합니다. 따라서, 액티비티 +수명 주기 관리에 쓰이는 실례가 프래그먼트에도 똑같이 적용되는 것입니다. 하지만 또 한 가지 이해해두어야 하는 것이 있습니다. 즉, 액티비티의 수명이 프래그먼트의 수명에 어떤 영향을 미치는지를 알아두어야 합니다.

    -

    주의: {@link android.app.Fragment} 내에서 {@link android.content.Context} -객체가 필요한 경우, {@link android.app.Fragment#getActivity()}를 호출하면 됩니다. +

    주의: {@link android.app.Fragment} 내에서 {@link android.content.Context} +객체가 필요한 경우, {@link android.app.Fragment#getActivity()}를 호출하면 됩니다. 그러나 {@link android.app.Fragment#getActivity()}를 호출하는 것은 프래그먼트가 액티비티에 - 첨부되어 있는 경우뿐이니 유의하십시오. 프래그먼트가 아직 첨부되지 않았거나 수명 주기가 끝날 무렵 분리된 경우, + 첨부되어 있는 경우뿐이니 유의하십시오. 프래그먼트가 아직 첨부되지 않았거나 수명 주기가 끝날 무렵 분리된 경우, {@link android.app.Fragment#getActivity()}가 null을 반환합니다.

    액티비티 수명 주기와 조화

    -

    프래그먼트가 있는 액티비티의 수명 주기는 해당 프래그먼트의 수명 주기에 직접적인 -영향을 미칩니다. 따라서 액티비티에 대한 각 수명 주기 콜백이 각 프래그먼트에 대한 비슷한 콜백을 -유발합니다. 예를 들어 액티비티가 {@link android.app.Activity#onPause}를 받으면, +

    프래그먼트가 있는 액티비티의 수명 주기는 해당 프래그먼트의 수명 주기에 직접적인 +영향을 미칩니다. 따라서 액티비티에 대한 각 수명 주기 콜백이 각 프래그먼트에 대한 비슷한 콜백을 +유발합니다. 예를 들어 액티비티가 {@link android.app.Activity#onPause}를 받으면, 해당 액티비티 내의 각 프래그먼트가 {@link android.app.Fragment#onPause}를 받습니다.

    -

    하지만 프래그먼트에는 몇 가지 수명 주기 콜백이 더 있습니다. 이것은 액티비티와의 -고유한 상호 작용을 다루어 프래그먼트의 UI를 구축하고 소멸시키는 것과 같은 +

    하지만 프래그먼트에는 몇 가지 수명 주기 콜백이 더 있습니다. 이것은 액티비티와의 +고유한 상호 작용을 다루어 프래그먼트의 UI를 구축하고 소멸시키는 것과 같은 작업을 수행합니다. 이러한 추가적인 콜백 메서드를 예로 들면 다음과 같습니다.

    @@ -715,17 +715,17 @@ onCreate()} 메서드가 반환되면 호출됩니다.
    프래그먼트가 액티비티와 연결이 끊어지는 중일 때 호출됩니다.
    -

    호스트 액티비티의 영향을 받을 프래그먼트 수명 주기의 흐름은 그림 3에서 -확인하십시오. 이 그림을 보면 액티비티의 각 연속된 상태가 프래그먼트가 어느 +

    호스트 액티비티의 영향을 받을 프래그먼트 수명 주기의 흐름은 그림 3에서 +확인하십시오. 이 그림을 보면 액티비티의 각 연속된 상태가 프래그먼트가 어느 콜백 메서드를 받게 되는지 결정 짓는다는 것을 볼 수 있습니다. 예를 들어 액티비티가 자신의 {@link -android.app.Activity#onCreate onCreate()} 콜백을 받은 경우, 해당 액티비티 안에 있는 프래그먼트는 +android.app.Activity#onCreate onCreate()} 콜백을 받은 경우, 해당 액티비티 안에 있는 프래그먼트는 {@link android.app.Fragment#onActivityCreated onActivityCreated()} 콜백을 받을 뿐입니다.

    -

    액티비티가 재개된 상태에 도달하면 자유자재로 프래그먼트를 액티비티에 추가하거나 액티비티에서 -제거해도 됩니다. 따라서, 액티비티가 재개된 상태에 있는 동안에만 프래그먼트의 수명 주기를 +

    액티비티가 재개된 상태에 도달하면 자유자재로 프래그먼트를 액티비티에 추가하거나 액티비티에서 +제거해도 됩니다. 따라서, 액티비티가 재개된 상태에 있는 동안에만 프래그먼트의 수명 주기를 독립적으로 변경할 수 있는 것입니다.

    -

    그러나 액티비티가 재개된 상태를 떠나면 액티비티는 다시 프래그먼트를 그 수명 주기 안으로 +

    그러나 액티비티가 재개된 상태를 떠나면 액티비티는 다시 프래그먼트를 그 수명 주기 안으로 밀어넣습니다.

    @@ -733,13 +733,13 @@ android.app.Activity#onCreate onCreate()} 콜백을 받은 경우, 해당 액티

    -

    이 문서에서 논의한 모든 것을 한 번에 모아 보기 위해, 다음은 두 개의 프래그먼트를 사용하여 -창이 두 개인 레이아웃을 생성하는 액티비티를 예시로 나타낸 것입니다. 아래의 액티비티에 포함된 -한 프래그먼트는 셰익스피어 희곡 제목 목록을 표시하고, 또 다른 하나는 목록에서 선택했을 때 -해당 희곡의 요약을 표시합니다. 또한 화면 구성을 근거로 프래그먼트를 여러 가지로 구성하여 제공하는 방법도 +

    이 문서에서 논의한 모든 것을 한 번에 모아 보기 위해, 다음은 두 개의 프래그먼트를 사용하여 +창이 두 개인 레이아웃을 생성하는 액티비티를 예시로 나타낸 것입니다. 아래의 액티비티에 포함된 +한 프래그먼트는 셰익스피어 희곡 제목 목록을 표시하고, 또 다른 하나는 목록에서 선택했을 때 +해당 희곡의 요약을 표시합니다. 또한 화면 구성을 근거로 프래그먼트를 여러 가지로 구성하여 제공하는 방법도 보여줍니다.

    -

    참고: 이 액티비티에 대한 완전한 소스 코드는 +

    참고: 이 액티비티에 대한 완전한 소스 코드는 {@code FragmentLayout.java}에서 이용하실 수 있습니다.

    @@ -752,44 +752,44 @@ android.app.Activity#onCreate onCreate()} 중에 일반적인 방식으로 레 {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout} -

    시스템은 이 레이아웃을 사용하여 액티비티가 레이아웃을 로딩하자마자 {@code TitlesFragment}를 초기화합니다(이것이 희곡 제목을 +

    시스템은 이 레이아웃을 사용하여 액티비티가 레이아웃을 로딩하자마자 {@code TitlesFragment}를 초기화합니다(이것이 희곡 제목을 목록으로 나열합니다). 반면 {@link android.widget.FrameLayout} -(희곡 요약을 표시하는 프래그먼트가 배치될 곳)은 화면 오른쪽에 있는 -공간을 차지하기는 하지만 처음에는 텅 빈 상태로 유지됩니다. 아래에서 볼 수 있듯이, 사용자가 해당 목록에서 +(희곡 요약을 표시하는 프래그먼트가 배치될 곳)은 화면 오른쪽에 있는 +공간을 차지하기는 하지만 처음에는 텅 빈 상태로 유지됩니다. 아래에서 볼 수 있듯이, 사용자가 해당 목록에서 항목을 하나 선택해야만 프래그먼트가 {@link android.widget.FrameLayout} 안에 배치됩니다.

    -

    그러나 희곡 목록과 요약을 둘 다 나란히 표시할 만큼 너비가 넓지 않은 -화면 구성도 있습니다. 따라서 위의 레이아웃은 가로 방향 화면 구성에만 사용되며, +

    그러나 희곡 목록과 요약을 둘 다 나란히 표시할 만큼 너비가 넓지 않은 +화면 구성도 있습니다. 따라서 위의 레이아웃은 가로 방향 화면 구성에만 사용되며, 이를 {@code res/layout-land/fragment_layout.xml}에 저장하여 씁니다.

    -

    그러므로 화면이 세로 방향으로 구성된 경우, 시스템은 다음 레이아웃을 적용합니다. 이것은 +

    그러므로 화면이 세로 방향으로 구성된 경우, 시스템은 다음 레이아웃을 적용합니다. 이것은 {@code res/layout/fragment_layout.xml}에 저장되어 있습니다.

    {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout} -

    이 레이아웃에는 {@code TitlesFragment}만 포함되어 있습니다. 이는 다시 말해 기기가 세로 방향인 경우에는 -희곡 제목 목록만 표시된다는 뜻입니다. 따라서 사용자가 이 구성에서 목록 항목을 하나 클릭하면, -애플리케이션이 두 번째 프래그먼트를 로딩하는 대신 새 액티비티를 시작하여 요약을 +

    이 레이아웃에는 {@code TitlesFragment}만 포함되어 있습니다. 이는 다시 말해 기기가 세로 방향인 경우에는 +희곡 제목 목록만 표시된다는 뜻입니다. 따라서 사용자가 이 구성에서 목록 항목을 하나 클릭하면, +애플리케이션이 두 번째 프래그먼트를 로딩하는 대신 새 액티비티를 시작하여 요약을 표시하게 됩니다.

    다음으로, 프래그먼트 클래스에서 이것을 달성하는 방법을 보시겠습니다. 첫 번째가 {@code TitlesFragment}로, 셰익스피어 희곡 제목 목록을 표시하는 것입니다. 이 프래그먼트는 {@link android.app.ListFragment}를 확장하며 목록 보기 작업의 대부분을 처리하기 위해 여기에 의존합니다.

    -

    이 코드를 살펴보면서 사용자가 목록 항목을 클릭하면 일어날 수 있는 두 가지 동작이 -있다는 점을 눈여겨 보십시오. 두 레이아웃 중 어느 것이 활성화 상태인지에 따라 +

    이 코드를 살펴보면서 사용자가 목록 항목을 클릭하면 일어날 수 있는 두 가지 동작이 +있다는 점을 눈여겨 보십시오. 두 레이아웃 중 어느 것이 활성화 상태인지에 따라 같은 액티비티 내에서 세부 사항을 표시하기 위해 새 프래그먼트를 생성하거나 표시할 수도 있고(프래그먼트를 {@link android.widget.FrameLayout}에 추가함으로써), 새 액티비티를 시작할 수도 있습니다(프래그먼트를 표시할 수 있는 곳).

    {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java titles} -

    두 번째 프래그먼트인 {@code DetailsFragment}는 {@code TitlesFragment}에서 가져온 목록에서 선택한 항목에 대한 희곡 요약을 +

    두 번째 프래그먼트인 {@code DetailsFragment}는 {@code TitlesFragment}에서 가져온 목록에서 선택한 항목에 대한 희곡 요약을 표시하는 것입니다.

    - + {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details} -

    {@code TitlesFragment} 클래스에서 다룬 것을 되살려 보면, 사용자가 목록 항목을 클릭하고 -현재 레이아웃이 {@code R.id.details} 보기를 포함하지 않는 경우(이 보기가 +

    {@code TitlesFragment} 클래스에서 다룬 것을 되살려 보면, 사용자가 목록 항목을 클릭하고 +현재 레이아웃이 {@code R.id.details} 보기를 포함하지 않는 경우(이 보기가 {@code DetailsFragment}가 속하는 곳임), 애플리케이션은 항목의 내용을 표시하기 위해 {@code DetailsActivity} 액티비티를 시작하게 됩니다.

    @@ -798,14 +798,14 @@ android.widget.FrameLayout}에 추가함으로써), 새 액티비티를 시작 {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details_activity} - -

    이 액티비티는 구성이 가로 방향인 경우 알아서 종료한다는 점을 눈여겨 보십시오. 따라서 + +

    이 액티비티는 구성이 가로 방향인 경우 알아서 종료한다는 점을 눈여겨 보십시오. 따라서 주요 액티비티가 작업을 인계 받아 {@code DetailsFragment}를 {@code TitlesFragment}와 함께 표시할 수 있는 것입니다. -이것은 사용자가 세로 방향 구성에서 {@code DetailsActivity}를 시작했지만 +이것은 사용자가 세로 방향 구성에서 {@code DetailsActivity}를 시작했지만 그런 다음 가로 방향으로 돌리는 경우(현재 액티비티를 다시 시작함) 일어날 수 있습니다.

    -

    프래그먼트 사용에 대한 더 많은 샘플(및 이 예시에 대한 완전한 소스 파일)을 보시려면 +

    프래그먼트 사용에 대한 더 많은 샘플(및 이 예시에 대한 완전한 소스 파일)을 보시려면 ApiDemos에서 이용할 수 있는 API Demos 샘플 앱을 참조하십시오(샘플 SDK 구성 요소에서 다운로드할 수 있습니다).

    diff --git a/docs/html-intl/intl/ko/guide/components/fundamentals.jd b/docs/html-intl/intl/ko/guide/components/fundamentals.jd index 608b5a2cba1b9a9322a0e64bb07ca358e903f08e..6bb5a9f7ba556fe5bd4130cab673087f6658137b 100644 --- a/docs/html-intl/intl/ko/guide/components/fundamentals.jd +++ b/docs/html-intl/intl/ko/guide/components/fundamentals.jd @@ -22,54 +22,54 @@ page.title=애플리케이션 기본 항목 -

    Android 앱은 Java 프로그래밍 언어로 작성됩니다. Android SDK 도구는 +

    Android 앱은 Java 프로그래밍 언어로 작성됩니다. Android SDK 도구는 코드를 컴파일링하여 모든 데이터 및 리소스 파일과 함께 하나의 APK로 만듭니다. 이것은 즉, Android 패키지 -를 뜻하며, 이는 일종의 {@code .apk} 접미사가 있는 아카이브 파일입니다. 한 개의 APK 파일에는 +를 뜻하며, 이는 일종의 {@code .apk} 접미사가 있는 아카이브 파일입니다. 한 개의 APK 파일에는 Android 앱의 모든 콘텐츠가 들어 있으며 이 파일이 바로 Android로 구동하는 기기가 앱을 설치할 때 사용하는 파일입니다.

    Android 앱은 일단 기기에 설치되고 나면 각자 나름의 보안 샌드박스 안에 살게 됩니다.

      -
    • Android 운영 체제는 멀티 사용자 Linux 시스템으로, 여기서 각 앱은 각기 다른 사용자와 +
    • Android 운영 체제는 멀티 사용자 Linux 시스템으로, 여기서 각 앱은 각기 다른 사용자와 같습니다.
    • -
    • 기본적으로 시스템이 각 앱에 고유한 Linux ID를 할당합니다(이 ID는 시스템만 -사용할 수 있으며 앱은 이것을 알지 못합니다). 시스템은 앱 안의 모든 파일에 대해 권한을 설정하여 +
    • 기본적으로 시스템이 각 앱에 고유한 Linux ID를 할당합니다(이 ID는 시스템만 +사용할 수 있으며 앱은 이것을 알지 못합니다). 시스템은 앱 안의 모든 파일에 대해 권한을 설정하여 해당 앱에 할당된 사용자 ID만 이에 액세스할 수 있도록 합니다.
    • -
    • 각 프로세스에는 나름의 가상 머신(VM)이 있고, 그렇기 때문에 한 앱의 코드가 다른 여러 앱과는 격리된 상태로 +
    • 각 프로세스에는 나름의 가상 머신(VM)이 있고, 그렇기 때문에 한 앱의 코드가 다른 여러 앱과는 격리된 상태로 실행됩니다.
    • -
    • 기본적으로 모든 앱이 나름의 Linux 프로세스에서 실행됩니다. Android는 앱의 구성 요소 중 -어느 것이라도 실행해야 하는 경우 프로세스를 시작하고, 이것이 더 이상 필요 없어지거나 시스템이 다른 앱을 위해 +
    • 기본적으로 모든 앱이 나름의 Linux 프로세스에서 실행됩니다. Android는 앱의 구성 요소 중 +어느 것이라도 실행해야 하는 경우 프로세스를 시작하고, 이것이 더 이상 필요 없어지거나 시스템이 다른 앱을 위해 메모리를 회복해야 하는 경우 해당 프로세스를 종료합니다.
    -

    Android 시스템은 이런 방식으로 최소 특권의 원리를 구현하는 것입니다. 다시 말해, -각 앱은 기본적으로 자신의 작업을 수행하기 위해 필요한 구성 요소에만 액세스 권한을 가지고 -그 이상은 허용되지 않습니다. 이렇게 하면 대단히 안전한 환경이 만들어져 앱이 시스템에서 +

    Android 시스템은 이런 방식으로 최소 특권의 원리를 구현하는 것입니다. 다시 말해, +각 앱은 기본적으로 자신의 작업을 수행하기 위해 필요한 구성 요소에만 액세스 권한을 가지고 +그 이상은 허용되지 않습니다. 이렇게 하면 대단히 안전한 환경이 만들어져 앱이 시스템에서 자신이 권한을 부여 받지 못한 부분에는 액세스할 수 없게 됩니다.

    -

    그러나, 앱이 다른 여러 앱과 데이터를 공유하는 것과 앱이 시스템 서비스에 액세스하는 데에는 +

    그러나, 앱이 다른 여러 앱과 데이터를 공유하는 것과 앱이 시스템 서비스에 액세스하는 데에는 여러 가지 방법이 있습니다.

      -
    • 두 개의 앱이 같은 Linux 사용자 ID를 공유하도록 설정할 수도 있습니다. 이 경우 -두 앱은 서로의 파일에 액세스할 수 있게 됩니다. 시스템 리소스를 절약하려면, 같은 사용자 ID를 가진 앱이 -같은 Linux 프로세스에서 실행되도록 설정하고 같은 VM을 공유하도록 할 수도 있습니다(이들 앱은 같은 인증서로 +
    • 두 개의 앱이 같은 Linux 사용자 ID를 공유하도록 설정할 수도 있습니다. 이 경우 +두 앱은 서로의 파일에 액세스할 수 있게 됩니다. 시스템 리소스를 절약하려면, 같은 사용자 ID를 가진 앱이 +같은 Linux 프로세스에서 실행되도록 설정하고 같은 VM을 공유하도록 할 수도 있습니다(이들 앱은 같은 인증서로 서명해야 합니다).
    • -
    • 앱은 사용자의 연락처, SMS 메시지, 마운트 가능한 저장소(SD 카드), -카메라, Bluetooth를 비롯하여 이외에도 여러 가지 기기 데이터에 액세스할 권한을 요청할 수 있습니다. 모든 +
    • 앱은 사용자의 연락처, SMS 메시지, 마운트 가능한 저장소(SD 카드), +카메라, Bluetooth를 비롯하여 이외에도 여러 가지 기기 데이터에 액세스할 권한을 요청할 수 있습니다. 모든 앱 권한은 설치 시점에 사용자가 허용해야 합니다.
    -

    이렇게 해서 Android 앱이 시스템 내에 어떤 식으로 존재하는지 기본 정보를 알아보았습니다. 이 문서의 +

    이렇게 해서 Android 앱이 시스템 내에 어떤 식으로 존재하는지 기본 정보를 알아보았습니다. 이 문서의 나머지 부분에서 소개될 내용은 다음과 같습니다.

    • 앱을 정의하는 핵심 프레임워크 구성 요소.
    • -
    • 구성 요소를 선언하고 앱에 맞는 필수 기기 특징을 선언할 수 있는 매니페스트 +
    • 구성 요소를 선언하고 앱에 맞는 필수 기기 특징을 선언할 수 있는 매니페스트 파일.
    • -
    • 앱 코드로부터 별도로 분리되어 있으며 앱이 다양한 기기 구성에 맞게 자신의 행동을 +
    • 앱 코드로부터 별도로 분리되어 있으며 앱이 다양한 기기 구성에 맞게 자신의 행동을 안정적으로 최적화할 수 있도록 해주는 리소스.
    @@ -77,13 +77,13 @@ Android 앱의 모든 콘텐츠가 들어 있으며 이 파일이 바로 Android

    앱 구성 요소

    -

    앱 구성 요소는 Android 앱을 이루는 가장 기본적인 구성 단위입니다. 각 -구성 요소는 시스템이 앱으로 들어올 수 있는 각기 다른 통과 지점을 나타냅니다. 구성 요소 중에는 -실제 사용자가 쓸 수 있는 진입 지점이 아닌 것도 있고, 일부는 서로에게 의존하지만, -각각의 구성 요소는 따로 떨어진 엔티티로서 존재하며 각기 특정한 역할을 수행합니다. 즉 하나하나가 +

    앱 구성 요소는 Android 앱을 이루는 가장 기본적인 구성 단위입니다. 각 +구성 요소는 시스템이 앱으로 들어올 수 있는 각기 다른 통과 지점을 나타냅니다. 구성 요소 중에는 +실제 사용자가 쓸 수 있는 진입 지점이 아닌 것도 있고, 일부는 서로에게 의존하지만, +각각의 구성 요소는 따로 떨어진 엔티티로서 존재하며 각기 특정한 역할을 수행합니다. 즉 하나하나가 앱의 전반적인 행동을 정의하는 데 유용한 고유한 구성 단위인 것입니다.

    -

    앱 구성 요소에는 네 가지 서로 다른 유형이 있습니다. 각 유형이 뚜렷한 목적을 가지고 있으며 +

    앱 구성 요소에는 네 가지 서로 다른 유형이 있습니다. 각 유형이 뚜렷한 목적을 가지고 있으며 각자 나름의 수명 주기가 있어 구성 요소의 생성 및 소멸 방식을 정의합니다.

    다음은 네 가지 유형의 앱 구성 요소를 나타낸 것입니다.

    @@ -92,15 +92,15 @@ Android 앱의 모든 콘텐츠가 들어 있으며 이 파일이 바로 Android
    액티비티
    -
    통상 액티비티 라고 하면, 사용자 인터페이스가 있는 화면 하나를 나타냅니다. 예를 들어 -이메일 앱이라면 새 이메일 목록을 표시하는 액티비티가 하나 있고, -이메일을 작성하는 액티비티가 또 하나, 그리고 이메일을 읽는 데 쓰는 액티비티가 또 하나 있을 수 있습니다. 여러 -액티비티가 함께 작동하여 해당 이메일 앱에서 짜임새 있는 사용자 환경을 형성하는 것은 사실이지만, 각자 서로와는 -독립적인 형태입니다. 따라서, 다른 앱이 이와 같은 액티비티 중 어느 것이라도 하나만 -시작할 수 있습니다(이메일 앱이 그렇게 하도록 허용하는 경우). 예를 들어, 카메라 앱이라면 이메일 앱 안의 +
    통상 액티비티 라고 하면, 사용자 인터페이스가 있는 화면 하나를 나타냅니다. 예를 들어 +이메일 앱이라면 새 이메일 목록을 표시하는 액티비티가 하나 있고, +이메일을 작성하는 액티비티가 또 하나, 그리고 이메일을 읽는 데 쓰는 액티비티가 또 하나 있을 수 있습니다. 여러 +액티비티가 함께 작동하여 해당 이메일 앱에서 짜임새 있는 사용자 환경을 형성하는 것은 사실이지만, 각자 서로와는 +독립적인 형태입니다. 따라서, 다른 앱이 이와 같은 액티비티 중 어느 것이라도 하나만 +시작할 수 있습니다(이메일 앱이 그렇게 하도록 허용하는 경우). 예를 들어, 카메라 앱이라면 이메일 앱 안의 액티비티를 시작하여 새 메일을 작성하도록 해서 사용자가 사진을 공유하도록 할 수 있습니다. -

    액티비티는 {@link android.app.Activity}의 하위 클래스로 구현되며 이에 대한 더 자세한 내용은 +

    액티비티는 {@link android.app.Activity}의 하위 클래스로 구현되며 이에 대한 더 자세한 내용은 액티비티 개발자 가이드에서 확인하실 수 있습니다.

    @@ -108,14 +108,14 @@ Android 앱의 모든 콘텐츠가 들어 있으며 이 파일이 바로 Android
    서비스
    -
    통상 서비스 라고 하면 배경에서 실행되는 구성 요소로, 오랫동안 실행되는 -작업을 수행하거나 원격 프로세스를 위한 작업을 수행하는 것입니다. 서비스는 -사용자 인터페이스를 제공하지 않습니다. 예를 들어 서비스는 사용자가 다른 앱에 있는 동안에 배경에서 음악을 재생할 수도 있고, -아니면 사용자와 액티비티 사이의 상호 작용을 차단하지 않고 네트워크를 가로질러 -데이터를 가져올 수도 있습니다. 또 다른 구성 요소(예: 액티비티)가 서비스를 시작한 다음 +
    통상 서비스 라고 하면 배경에서 실행되는 구성 요소로, 오랫동안 실행되는 +작업을 수행하거나 원격 프로세스를 위한 작업을 수행하는 것입니다. 서비스는 +사용자 인터페이스를 제공하지 않습니다. 예를 들어 서비스는 사용자가 다른 앱에 있는 동안에 배경에서 음악을 재생할 수도 있고, +아니면 사용자와 액티비티 사이의 상호 작용을 차단하지 않고 네트워크를 가로질러 +데이터를 가져올 수도 있습니다. 또 다른 구성 요소(예: 액티비티)가 서비스를 시작한 다음 실행되도록 두거나 자신에게 바인딩하여 상호 작용하도록 할 수도 있습니다. -

    서비스는 {@link android.app.Service}의 하위 클래스로 구현되며 이에 대한 더 자세한 내용은 +

    서비스는 {@link android.app.Service}의 하위 클래스로 구현되며 이에 대한 더 자세한 내용은 서비스 개발자 가이드에서 확인하실 수 있습니다.

    @@ -123,20 +123,20 @@ Android 앱의 모든 콘텐츠가 들어 있으며 이 파일이 바로 Android
    콘텐츠 제공자
    -
    통상 콘텐츠 제공자 는 공유된 앱 데이터 집합을 관리합니다. 데이터는 파일 시스템이나 SQLite 데이터베이스, -또는 웹이나 기타 영구적인 저장소 위치 중 앱이 액세스할 수 있는 곳이라면 어디에든 저장할 수 -있습니다. 다른 여러 앱은 콘텐츠 제공자를 통해 해당 데이터를 쿼리하거나, 심지어는 수정할 수도 -있습니다(콘텐츠 제공자가 그렇게 하도록 허용하는 경우). 예를 들어, Android 시스템은 사용자의 연락처 정보를 -관리하는 콘텐츠 제공자를 제공합니다. 따라서, 적절한 권한을 가진 앱이라면 +
    통상 콘텐츠 제공자 는 공유된 앱 데이터 집합을 관리합니다. 데이터는 파일 시스템이나 SQLite 데이터베이스, +또는 웹이나 기타 영구적인 저장소 위치 중 앱이 액세스할 수 있는 곳이라면 어디에든 저장할 수 +있습니다. 다른 여러 앱은 콘텐츠 제공자를 통해 해당 데이터를 쿼리하거나, 심지어는 수정할 수도 +있습니다(콘텐츠 제공자가 그렇게 하도록 허용하는 경우). 예를 들어, Android 시스템은 사용자의 연락처 정보를 +관리하는 콘텐츠 제공자를 제공합니다. 따라서, 적절한 권한을 가진 앱이라면 어떤 것이든 해당 콘텐츠 제공자의 일부를 쿼리하여(예를 들어 {@link android.provider.ContactsContract.Data} 등) 특정한 사람에 대한 정보를 읽고 쓸 수 있습니다. -

    콘텐츠 제공자는 앱에서 비공개이며 공유되지 않는 데이터를 읽고 쓰는 데에도 -유용합니다. 예를 들어 메모장 샘플 앱은 메모한 내용을 저장하는 데 +

    콘텐츠 제공자는 앱에서 비공개이며 공유되지 않는 데이터를 읽고 쓰는 데에도 +유용합니다. 예를 들어 메모장 샘플 앱은 메모한 내용을 저장하는 데 콘텐츠 제공자를 사용합니다.

    콘텐츠 제공자는 {@link android.content.ContentProvider}의 -하위 클래스로 구현되며, 다른 앱이 트랜잭션을 수행할 수 있도록 활성화하는 표준 API 집합을 +하위 클래스로 구현되며, 다른 앱이 트랜잭션을 수행할 수 있도록 활성화하는 표준 API 집합을 구현해야 합니다. 자세한 내용은 콘텐츠 제공자 개발자 가이드를 참조하십시오.

    @@ -144,18 +144,18 @@ android.provider.ContactsContract.Data} 등) 특정한 사람에 대한 정보
    브로드캐스트 수신기
    -
    통상 브로드캐스트 수신기 는 시스템 전체에 대한 브로드캐스트 공지에 응답하는 구성 요소를 -말합니다. 대다수의 브로드캐스트는 시스템에서 시작합니다. 예를 들어, 화면이 꺼졌다거나 +
    통상 브로드캐스트 수신기 는 시스템 전체에 대한 브로드캐스트 공지에 응답하는 구성 요소를 +말합니다. 대다수의 브로드캐스트는 시스템에서 시작합니다. 예를 들어, 화면이 꺼졌다거나 배터리 잔량이 부족하다거나, 사진을 캡처했다는 것을 알리는 브로드캐스트가 있습니다. -앱도 브로드캐스트를 시작합니다. 예를 들어, 기기에 몇 가지 데이터를 다운로드하여 다른 앱도 사용할 수 있다는 -사실을 다른 여러 앱에게 알리는 것입니다. 브로드캐스트 수신기는 사용자 인터페이스를 표시하지 않지만, -상태 표시줄 알림을 생성하여 -사용자에게 브로드캐스트 이벤트가 발생했다고 알릴 수 있습니다. 다만 브로드캐스트 수신기는 -그저 다른 구성 요소로의 "게이트웨이"인 경우가 더 보편적이고, 극소량의 작업만 수행하도록 만들어진 경우가 많습니다. 예컨대 +앱도 브로드캐스트를 시작합니다. 예를 들어, 기기에 몇 가지 데이터를 다운로드하여 다른 앱도 사용할 수 있다는 +사실을 다른 여러 앱에게 알리는 것입니다. 브로드캐스트 수신기는 사용자 인터페이스를 표시하지 않지만, +상태 표시줄 알림을 생성하여 +사용자에게 브로드캐스트 이벤트가 발생했다고 알릴 수 있습니다. 다만 브로드캐스트 수신기는 +그저 다른 구성 요소로의 "게이트웨이"인 경우가 더 보편적이고, 극소량의 작업만 수행하도록 만들어진 경우가 많습니다. 예컨대 서비스를 시작하여 이벤트를 근거로 한 어떤 작업을 수행하도록 할 수 있습니다. -

    브로드캐스트 수신기는 {@link android.content.BroadcastReceiver}의 -하위 클래스로 구현되며 각 브로드캐스트는 {@link android.content.Intent} 객체로 전달됩니다. 자세한 정보는 +

    브로드캐스트 수신기는 {@link android.content.BroadcastReceiver}의 +하위 클래스로 구현되며 각 브로드캐스트는 {@link android.content.Intent} 객체로 전달됩니다. 자세한 정보는 {@link android.content.BroadcastReceiver} 클래스를 참조하십시오.

    @@ -163,72 +163,72 @@ android.provider.ContactsContract.Data} 등) 특정한 사람에 대한 정보 -

    Android 시스템 디자인의 독특한 점으로 어떤 앱이든 다른 앱의 구성 요소를 시작할 수 있다는 점을 -들 수 있습니다. 예를 들어 사용자가 기기 카메라로 사진을 캡처하기를 바라는 경우, -그런 작업을 수행하는 또 다른 앱이 있을 가능성이 높습니다. 그러면 사진을 캡처하는 액티비티를 직접 개발하는 대신 -여러분의 앱이 그 앱을 사용하도록 하면 됩니다. 카메라 앱에 +

    Android 시스템 디자인의 독특한 점으로 어떤 앱이든 다른 앱의 구성 요소를 시작할 수 있다는 점을 +들 수 있습니다. 예를 들어 사용자가 기기 카메라로 사진을 캡처하기를 바라는 경우, +그런 작업을 수행하는 또 다른 앱이 있을 가능성이 높습니다. 그러면 사진을 캡처하는 액티비티를 직접 개발하는 대신 +여러분의 앱이 그 앱을 사용하도록 하면 됩니다. 카메라 앱에 통합하기는커녕 카메라 앱의 코드에 연결시킬 필요조차도 없습니다. -그 대신, 그저 사진을 캡처하는 카메라 앱 안의 해당 액티비티를 시작하기만 하면 -됩니다. 작업이 완료되면 사진이 앱으로 반환되기까지 하여 바로 사용할 수 있습니다. 사용자에게는, +그 대신, 그저 사진을 캡처하는 카메라 앱 안의 해당 액티비티를 시작하기만 하면 +됩니다. 작업이 완료되면 사진이 앱으로 반환되기까지 하여 바로 사용할 수 있습니다. 사용자에게는, 마치 카메라가 여러분의 앱의 일부분인 것처럼 보입니다.

    -

    시스템이 구성 요소를 시작하는 경우, 그 앱에 대한 프로세스를 시작하는 것이며(이미 -실행 중이지 않은 경우), 해당 구성 요소에 필요한 클래스를 인스턴트화하는 것입니다. 예를 들어 여러분의 앱이 -카메라 앱 내에서 사진을 캡처하는 액티비티를 시작한다고 하면, 해당 액티비티는 -여러분 앱의 프로세스가 아니라 카메라 앱에 속한 프로세스에서 실행됩니다. -따라서 대부분의 다른 시스템에서와는 달리 Android 앱에는 단일한 진입 +

    시스템이 구성 요소를 시작하는 경우, 그 앱에 대한 프로세스를 시작하는 것이며(이미 +실행 중이지 않은 경우), 해당 구성 요소에 필요한 클래스를 인스턴트화하는 것입니다. 예를 들어 여러분의 앱이 +카메라 앱 내에서 사진을 캡처하는 액티비티를 시작한다고 하면, 해당 액티비티는 +여러분 앱의 프로세스가 아니라 카메라 앱에 속한 프로세스에서 실행됩니다. +따라서 대부분의 다른 시스템에서와는 달리 Android 앱에는 단일한 진입 지점이 없습니다(예를 들어 {@code main()} 기능이 없습니다).

    -

    시스템이 각 앱을 별도의 프로세스에서 실행하며 다른 앱에 대한 액세스를 제한하는 -파일 권한을 가지고 실행하기 때문에 여러분의 앱은 또 다른 앱에서 곧바로 구성 요소를 -활성화할 수는 없습니다. 하지만 Android 시스템은 할 수 있습니다. 그래서 또 다른 앱에 있는 -구성 요소를 활성화하려면 시스템에 메시지를 전달하여 특정 구성 요소를 시작하고자 하는 인텐트를 +

    시스템이 각 앱을 별도의 프로세스에서 실행하며 다른 앱에 대한 액세스를 제한하는 +파일 권한을 가지고 실행하기 때문에 여러분의 앱은 또 다른 앱에서 곧바로 구성 요소를 +활성화할 수는 없습니다. 하지만 Android 시스템은 할 수 있습니다. 그래서 또 다른 앱에 있는 +구성 요소를 활성화하려면 시스템에 메시지를 전달하여 특정 구성 요소를 시작하고자 하는 인텐트를 밝혀야 합니다. 그러면 시스템이 대신 해당 구성 요소를 활성화해줍니다.

    구성 요소 활성화

    -

    네 가지 구성 요소 중 세 가지—액티비티, 서비스 및 +

    네 가지 구성 요소 중 세 가지—액티비티, 서비스 및 브로드캐스트 수신기—는 일명 인텐트라고 하는 비동기식 메시지가 활성화합니다. -인텐트는 각각의 구성 요소를 런타임에 서로 바인딩하며(다른 구성 요소로부터 작업을 요청하는 -일종의 메신저로 생각하면 됩니다), 이는 구성 요소가 여러분의 앱에 속하든 아니든 +인텐트는 각각의 구성 요소를 런타임에 서로 바인딩하며(다른 구성 요소로부터 작업을 요청하는 +일종의 메신저로 생각하면 됩니다), 이는 구성 요소가 여러분의 앱에 속하든 아니든 무관합니다.

    -

    인텐트는 {@link android.content.Intent} 객체로 생성되며, 이것이 -특정 구성 요소를 활성화할지 아니면 구성 요소의 특정 유형을 활성화할지를 나타내는 메시지를 정의합니다. 인텐트는 +

    인텐트는 {@link android.content.Intent} 객체로 생성되며, 이것이 +특정 구성 요소를 활성화할지 아니면 구성 요소의 특정 유형을 활성화할지를 나타내는 메시지를 정의합니다. 인텐트는 각각 명시적이거나 암시적일 수 있습니다.

    -

    액티비티와 서비스의 경우, 인텐트는 수행할 작업을 정의하며(예를 들어 무언가를 '보기" 또는 -"보내기"), 작업을 수행할 데이터의 URI를 나타낼 수 있습니다(시작되는 구성 요소가 알아야 할 것은 -이외에도 많이 있습니다). 예를 들어, 인텐트는 액티비티에 이미지를 표시하거나 웹 페이지를 열라는 요청을 -전달할 수 있습니다. 어떤 경우에는 액티비티를 시작하여 -결과를 받아오도록 할 수 있습니다. 이런 경우 이 액티비티는 -{@link android.content.Intent}로 결과를 반환하기도 합니다(예를 들어, 사용자가 -개인적인 연락처를 선택하도록 한 다음 그것을 반환하도록 하는 인텐트를 발행할 수 있습니다—반환 인텐트에 +

    액티비티와 서비스의 경우, 인텐트는 수행할 작업을 정의하며(예를 들어 무언가를 '보기" 또는 +"보내기"), 작업을 수행할 데이터의 URI를 나타낼 수 있습니다(시작되는 구성 요소가 알아야 할 것은 +이외에도 많이 있습니다). 예를 들어, 인텐트는 액티비티에 이미지를 표시하거나 웹 페이지를 열라는 요청을 +전달할 수 있습니다. 어떤 경우에는 액티비티를 시작하여 +결과를 받아오도록 할 수 있습니다. 이런 경우 이 액티비티는 +{@link android.content.Intent}로 결과를 반환하기도 합니다(예를 들어, 사용자가 +개인적인 연락처를 선택하도록 한 다음 그것을 반환하도록 하는 인텐트를 발행할 수 있습니다—반환 인텐트에 선택한 연락처를 가리키는 URI가 포함됩니다).

    -

    브로드캐스트 수신기의 경우, 인텐트는 단순히 브로드캐스트될 알림을 -정의할 뿐입니다(예를 들어, 기기 배터리 잔량이 낮다는 것을 나타내는 브로드캐스트에는 +

    브로드캐스트 수신기의 경우, 인텐트는 단순히 브로드캐스트될 알림을 +정의할 뿐입니다(예를 들어, 기기 배터리 잔량이 낮다는 것을 나타내는 브로드캐스트에는 "배터리 부족"을 나타내는 알려진 작업 문자열만 포함됩니다).

    -

    남은 하나의 구성 요소 유형, 즉 콘텐츠 제공자는 인텐트가 활성화하지 않습니다. 그보다는 -{@link android.content.ContentResolver}로부터의 요청으로 지정되면 활성화됩니다. 콘텐츠 -확인자는 콘텐츠 제공자와의 모든 직접적인 트랜잭션을 처리하여 +

    남은 하나의 구성 요소 유형, 즉 콘텐츠 제공자는 인텐트가 활성화하지 않습니다. 그보다는 +{@link android.content.ContentResolver}로부터의 요청으로 지정되면 활성화됩니다. 콘텐츠 +확인자는 콘텐츠 제공자와의 모든 직접적인 트랜잭션을 처리하여 제공자와의 트랜잭션을 수행하는 구성 요소가 그런 일을 하지 않아도 되게 하고, 그 대신 {@link -android.content.ContentResolver} 객체에서 메서드를 호출합니다. 이렇게 되면 콘텐츠 제공자와 +android.content.ContentResolver} 객체에서 메서드를 호출합니다. 이렇게 되면 콘텐츠 제공자와 정보를 요청하는 구성 요소 사이에 추상화 계층이 하나 남습니다(보안 목적).

    각 유형의 구성 요소를 활성화하는 데에는 각기 별도의 메서드가 있습니다.

      -
    • 액티비티를 시작하려면(아니면 무언가 새로운 할 일을 주려면) +
    • 액티비티를 시작하려면(아니면 무언가 새로운 할 일을 주려면) {@link android.content.Intent}를 {@link android.content.Context#startActivity -startActivity()} 또는 {@link android.app.Activity#startActivityForResult startActivityForResult()}에 +startActivity()} 또는 {@link android.app.Activity#startActivityForResult startActivityForResult()}에 전달하면 됩니다(액티비티가 결과를 반환하기를 원하는 경우).
    • -
    • 서비스를 시작하려면(또는 진행 중인 서비스에 새로운 지침을 주려면) +
    • 서비스를 시작하려면(또는 진행 중인 서비스에 새로운 지침을 주려면) {@link android.content.Intent}를 {@link android.content.Context#startService -startService()}에 전달하면 됩니다. 아니면 {@link android.content.Intent}를 +startService()}에 전달하면 됩니다. 아니면 {@link android.content.Intent}를 {@link android.content.Context#bindService bindService()}에 전달하여 서비스에 바인딩할 수도 있습니다.
    • -
    • 브로드캐스트를 시작하려면 {@link android.content.Intent}를 +
    • 브로드캐스트를 시작하려면 {@link android.content.Intent}를 {@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}, {@link android.content.Context#sendOrderedBroadcast(Intent, String) sendOrderedBroadcast()} 또는 {@link android.content.Context#sendStickyBroadcast sendStickyBroadcast()}와 같은 메서드에 전달하면 됩니다.
    • @@ -236,29 +236,29 @@ android.content.Context#sendStickyBroadcast sendStickyBroadcast()}와 같은 메 android.content.ContentProvider#query query()}를 호출하면 됩니다.
    -

    인텐트 사용에 관한 자세한 정보는 인텐트 및 -인텐트 필터문서를 참조하십시오. 특정 구성 요소를 활성화하는 데 관한 자세한 정보 또한 다음 문서에 +

    인텐트 사용에 관한 자세한 정보는 인텐트 및 +인텐트 필터문서를 참조하십시오. 특정 구성 요소를 활성화하는 데 관한 자세한 정보 또한 다음 문서에 제공되어 있습니다. 액티비티, 서비스, {@link android.content.BroadcastReceiver} 및 콘텐츠 제공자.

    매니페스트 파일

    -

    Android 시스템이 앱 구성 요소를 시작하려면 시스템은 우선 해당 구성 요소가 +

    Android 시스템이 앱 구성 요소를 시작하려면 시스템은 우선 해당 구성 요소가 존재하는지 알아야 합니다. 그러기 위해 앱의 {@code AndroidManifest.xml} 파일을 읽습니다(즉 "매니페스트" -파일). 앱은 이 파일 안에 모든 구성 요소를 선언해야 하며, 이 파일은 앱 프로젝트 디렉터리의 루트에 +파일). 앱은 이 파일 안에 모든 구성 요소를 선언해야 하며, 이 파일은 앱 프로젝트 디렉터리의 루트에 있어야 합니다.

    매니페스트는 앱의 구성 요소를 선언하는 것 이외에도 수많은 역할을 합니다. 예를 들면 다음과 같습니다.

      -
    • 앱이 요구하는 모든 사용자 권한 식별(예: 인터넷 액세스 또는 사용자의 연락처로의 +
    • 앱이 요구하는 모든 사용자 권한 식별(예: 인터넷 액세스 또는 사용자의 연락처로의 읽기 액세스)
    • 앱이 어느 API를 사용하는지를 근거로 하여 앱에서 요구하는 최소 API 레벨 선언
    • -
    • 앱에서 사용하거나 필요로 하는 하드웨어 및 소프트웨어 기능 선언(예: 카메라, +
    • 앱에서 사용하거나 필요로 하는 하드웨어 및 소프트웨어 기능 선언(예: 카메라, 블루투스 서비스 또는 멀티터치 화면 등)
    • -
    • 앱이 링크되어야 하는 API 라이브러리(Android 프레임워크 +
    • 앱이 링크되어야 하는 API 라이브러리(Android 프레임워크 API 제외)(예: Google Maps 라이브러리)
    • 그 외 기타 등등
    • @@ -267,7 +267,7 @@ API 제외)(예: 구성 요소 선언 -

      매니페스트의 주요 작업은 시스템에 앱의 구성 요소에 대해 알리는 것입니다. 예를 들어 +

      매니페스트의 주요 작업은 시스템에 앱의 구성 요소에 대해 알리는 것입니다. 예를 들어 매니페스트 파일은 액티비티를 다음과 같이 선언할 수 있습니다.

      @@ -283,36 +283,36 @@ API 제외)(예: <application>
      -요소에서 {@code android:icon} 속성은 앱을 식별하는 아이콘에 대한 리소스를 
      +요소에서 {@code android:icon} 속성은 앱을 식별하는 아이콘에 대한 리소스를
       가리킵니다.

      <activity> 요소에서는, +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity> 요소에서는, {@code android:name} 속성이 {@link -android.app.Activity} 하위 클래스의 완전히 정규화된 클래스 이름을 나타내며 {@code android:label} 속성은 액티비티의 +android.app.Activity} 하위 클래스의 완전히 정규화된 클래스 이름을 나타내며 {@code android:label} 속성은 액티비티의 사용자에게 표시되는 레이블로 사용할 문자열을 나타냅니다.

      모든 앱 구성 요소를 이렇게 선언해야 합니다.

        -
      • 액티비티는 +
      • 액티비티는 <activity> 요소
      • -
      • 서비스는 +
      • 서비스는 <service> 요소
      • -
      • 브로드캐스트 수신기는 +
      • 브로드캐스트 수신기는 <receiver> 요소
      • -
      • 콘텐츠 제공자는 +
      • 콘텐츠 제공자는 <provider> 요소
      -

      액티비티, 서비스를 비롯하여 소스에는 포함시키지만 매니페스트에서는 선언하지 않는 -콘텐츠 제공자는 시스템에 표시되지 않으며, 따라서 실행될 수 없습니다. 그러나 +

      액티비티, 서비스를 비롯하여 소스에는 포함시키지만 매니페스트에서는 선언하지 않는 +콘텐츠 제공자는 시스템에 표시되지 않으며, 따라서 실행될 수 없습니다. 그러나 브로드캐스트 수신기는 매니페스트에서 선언해도 되고 코드를 사용해( -{@link android.content.BroadcastReceiver} 객체로) 동적으로 생성한 다음 시스템에 등록해도 됩니다. 이때 +{@link android.content.BroadcastReceiver} 객체로) 동적으로 생성한 다음 시스템에 등록해도 됩니다. 이때 {@link android.content.Context#registerReceiver registerReceiver()}를 호출하는 방법을 씁니다.

      앱에 맞는 매니페스트 파일을 구성하는 방법에 대한 자세한 내용은 AndroidManifest.xml 파일을 @@ -322,26 +322,26 @@ href="{@docRoot}guide/topics/manifest/provider-element.html"><provider>구성 요소 기능 선언 -

      위에서 논한 바와 같이, 활성화 상태의 구성 요소에서는 -{@link android.content.Intent}를 사용하여 액티비티, 서비스 및 브로드캐스트 수신기를 시작할 수 있습니다. 그렇게 하려면 -대상 구성 요소를 인텐트 내에서 명시적으로 명명하면 됩니다(구성 요소 클래스 이름을 사용). 그러나, -인텐트의 진정한 힘은 암시적 인텐트의 개념에서 발휘됩니다. 암시적 인텐트는 -그저 수행할 작업의 유형을 설명할 뿐이며(또한, 선택 사항으로, 해당 작업을 수행하고자 하는 -데이터 위치도) 시스템에 기기에서 작업을 수행할 수 있는 구성 요소를 찾아 -시작하도록 해줍니다. 인텐트가 설명한 작업을 수행할 수 있는 구성 요소가 여러 개인 경우, +

      위에서 논한 바와 같이, 활성화 상태의 구성 요소에서는 +{@link android.content.Intent}를 사용하여 액티비티, 서비스 및 브로드캐스트 수신기를 시작할 수 있습니다. 그렇게 하려면 +대상 구성 요소를 인텐트 내에서 명시적으로 명명하면 됩니다(구성 요소 클래스 이름을 사용). 그러나, +인텐트의 진정한 힘은 암시적 인텐트의 개념에서 발휘됩니다. 암시적 인텐트는 +그저 수행할 작업의 유형을 설명할 뿐이며(또한, 선택 사항으로, 해당 작업을 수행하고자 하는 +데이터 위치도) 시스템에 기기에서 작업을 수행할 수 있는 구성 요소를 찾아 +시작하도록 해줍니다. 인텐트가 설명한 작업을 수행할 수 있는 구성 요소가 여러 개인 경우, 어느 것을 사용할지 사용자가 선택합니다.

      -

      시스템이 인텐트에 응답할 수 있는 구성 요소를 식별하는 방법은 수신한 인텐트를 - 인텐트 필터 와 비교하는 것입니다. 이 인텐트 필터는 기기의 다른 여러 앱의 매니페스트 +

      시스템이 인텐트에 응답할 수 있는 구성 요소를 식별하는 방법은 수신한 인텐트를 + 인텐트 필터 와 비교하는 것입니다. 이 인텐트 필터는 기기의 다른 여러 앱의 매니페스트 파일이 제공합니다.

      -

      앱의 매니페스트에서 액티비티를 선언하는 경우, 선택 사항으로 -해당 액티비티의 기능을 선언하는 인텐트 필터를 포함시켜서 다른 앱으로부터의 인텐트에 -응답할 수 있도록 할 수 있습니다. 구성 요소에 대한 인텐트 필터를 선언하려면 +

      앱의 매니페스트에서 액티비티를 선언하는 경우, 선택 사항으로 +해당 액티비티의 기능을 선언하는 인텐트 필터를 포함시켜서 다른 앱으로부터의 인텐트에 +응답할 수 있도록 할 수 있습니다. 구성 요소에 대한 인텐트 필터를 선언하려면 {@code <intent-filter>} 요소를 해당 구성 요소의 선언 요소 하위로 추가하면 됩니다.

      -

      예를 들어, 새 이메일을 작성하는 데 쓰는 액티비티가 있는 이메일 앱을 구축했다고 가정합시다. 이때 "전송" 인텐트에 +

      예를 들어, 새 이메일을 작성하는 데 쓰는 액티비티가 있는 이메일 앱을 구축했다고 가정합시다. 이때 "전송" 인텐트에 응답하는 인텐트 필터를 선언하려면(새 이메일을 전송하기 위해) 다음과 같이 하면 됩니다.

       <manifest ... >
      @@ -360,7 +360,7 @@ href="{@docRoot}guide/topics/manifest/provider-element.html"><provider>그런 다음, 다른 앱이 {@link
       android.content.Intent#ACTION_SEND} 작업을 가진 인텐트를 생성하여 그것을 {@link android.app.Activity#startActivity
      -startActivity()}로 전달하면 시스템이 여러분의 액티비티를 시작하여 사용자가 이메일을 임시 보관하고 전송할 수 
      +startActivity()}로 전달하면 시스템이 여러분의 액티비티를 시작하여 사용자가 이메일을 임시 보관하고 전송할 수
       있습니다.

      인텐트 필터 생성에 관한 자세한 내용은 인텐트 및 인텐트 필터 문서를 참조하십시오. @@ -370,16 +370,16 @@ startActivity()}로 전달하면 시스템이 여러분의 액티비티를 시

      앱 요구 사항 선언

      -

      Android로 구동되는 기기는 수없이 많지만 모두 똑같은 특징을 갖고 같은 -기능을 제공하는 것은 아닙니다. 앱이 필요로 하는 기능이 부족한 기기에 앱을 설치하게 되는 불상사를 방지하려면, -앱이 지원하는 기기 유형에 대한 프로필을 명확하게 정의하는 것이 중요합니다. -그러려면 매니페스트 파일에 기기와 소프트웨어 요구 사항을 -선언하면 됩니다. 이와 같은 선언은 대부분 정보성일 뿐이며 시스템은 이를 읽지 않는 것이 일반적이지만, -Google Play와 같은 외부 서비스는 사용자가 본인의 기기에서 앱을 검색할 때 필터링을 제공하기 위해 +

      Android로 구동되는 기기는 수없이 많지만 모두 똑같은 특징을 갖고 같은 +기능을 제공하는 것은 아닙니다. 앱이 필요로 하는 기능이 부족한 기기에 앱을 설치하게 되는 불상사를 방지하려면, +앱이 지원하는 기기 유형에 대한 프로필을 명확하게 정의하는 것이 중요합니다. +그러려면 매니페스트 파일에 기기와 소프트웨어 요구 사항을 +선언하면 됩니다. 이와 같은 선언은 대부분 정보성일 뿐이며 시스템은 이를 읽지 않는 것이 일반적이지만, +Google Play와 같은 외부 서비스는 사용자가 본인의 기기에서 앱을 검색할 때 필터링을 제공하기 위해 이와 같은 선언도 읽습니다.

      -

      예를 들어, 앱에 카메라가 필요하고 Android 2.1부터 도입된 API를 사용하는 경우(API 레벨 7) -이과 같은 내용을 매니페스트 파일에 요구 사항으로 선언하려면 다음과 같이 합니다.

      +

      예를 들어, 앱에 카메라가 필요하고 Android 2.1부터 도입된 API를 사용하는 경우(API 레벨 7) +이과 같은 내용을 매니페스트 파일에 요구 사항으로 선언하려면 다음과 같이 합니다.

       <manifest ... >
      @@ -390,15 +390,15 @@ Google Play와 같은 외부 서비스는 사용자가 본인의 기기에서 
       </manifest>
       
      -

      이제 카메라가 없고 Android 버전이 2.1 이하인 기기는 +

      이제 카메라가 없고 Android 버전이 2.1 이하인 기기는 Google Play에서 여러분의 앱을 설치할 수 없습니다.

      -

      그러나, 앱이 카메라를 사용하기는 하지만 꼭 +

      그러나, 앱이 카메라를 사용하기는 하지만 꼭 필요한 것은 아니라고 선언할 수도 있습니다. 이 경우에는, 앱이 {@code required} - 속성을 {@code "false"}에 설정하고 런타임을 확인하여 + 속성을 {@code "false"}에 설정하고 런타임을 확인하여 해당 기기에 카메라가 있는지, 경우에 따라 모든 카메라 기능을 비활성화할 수 있는지 알아봅니다.

      -

      여러 가지 기기와 앱의 호환성을 관리하는 방법에 대한 자세한 정보는 +

      여러 가지 기기와 앱의 호환성을 관리하는 방법에 대한 자세한 정보는 기기 호환성 문서를 참조하십시오.

      @@ -407,40 +407,40 @@ Google Play에서 여러분의 앱을 설치할 수 없습니다.

      앱 리소스

      Android 앱을 이루는 것은 코드만이 아닙니다. 소스 코드와는 별개인 여러 리소스가 필요합니다. -예를 들어 이미지, 오디오 파일과 앱을 시각적으로 표현하는 것과 관련된 모든 것들이 있습니다. -예컨대 애니메이션, 메뉴, 스타일, 색상과 액티비티 사용자 인터페이스의 레이아웃을 XML 파일로 -정의해야 합니다. 앱 리소스를 사용하면 앱의 다양한 특성을 -쉽게 업데이트할 수 있으며 코드를 수정하지 않아도 되고 일련의 대체 리소스를 -제공함으로써 다양한 기기 구성에 맞게 앱을 +예를 들어 이미지, 오디오 파일과 앱을 시각적으로 표현하는 것과 관련된 모든 것들이 있습니다. +예컨대 애니메이션, 메뉴, 스타일, 색상과 액티비티 사용자 인터페이스의 레이아웃을 XML 파일로 +정의해야 합니다. 앱 리소스를 사용하면 앱의 다양한 특성을 +쉽게 업데이트할 수 있으며 코드를 수정하지 않아도 되고 일련의 대체 리소스를 +제공함으로써 다양한 기기 구성에 맞게 앱을 최적화할 수도 있습니다(예: 여러 가지 언어 및 화면 크기).

      -

      Android 프로젝트에 포함시키는 리소스마다 SDK 빌드 도구가 고유한 -정수 ID를 정의하므로, 이를 사용하여 앱 코드에서의 리소스나 XML로 정의된 +

      Android 프로젝트에 포함시키는 리소스마다 SDK 빌드 도구가 고유한 +정수 ID를 정의하므로, 이를 사용하여 앱 코드에서의 리소스나 XML로 정의된 다른 리소스에서 참조할 수 있습니다. 예를 들어 앱에 {@code -logo.png}라는 이름의 이미지 파일이 들어 있다고 하면({@code res/drawable/} 디렉터리에 저장됨) SDK 도구가 -{@code R.drawable.logo}라는 리소스 ID를 생성합니다. 이것을 사용하여 이미지를 참조하고 사용자 인터페이스에 +logo.png}라는 이름의 이미지 파일이 들어 있다고 하면({@code res/drawable/} 디렉터리에 저장됨) SDK 도구가 +{@code R.drawable.logo}라는 리소스 ID를 생성합니다. 이것을 사용하여 이미지를 참조하고 사용자 인터페이스에 삽입할 수 있습니다.

      -

      소스 코드와는 별개로 리소스를 제공하는 것의 가장 중요한 측면 중 하나는 -여러 가지 기기 구성에 맞게 대체 리소스를 제공할 능력을 갖추게 -됩니다. 예를 들어 UI 문자열을 XML로 정의하면 이러한 문자열을 다른 언어로 변환한 뒤 +

      소스 코드와는 별개로 리소스를 제공하는 것의 가장 중요한 측면 중 하나는 +여러 가지 기기 구성에 맞게 대체 리소스를 제공할 능력을 갖추게 +됩니다. 예를 들어 UI 문자열을 XML로 정의하면 이러한 문자열을 다른 언어로 변환한 뒤 그러한 문자열을 별개의 파일에 저장할 수 있습니다. 그런 다음, 리소스 디렉터리 이름에 추가한 언어 한정자 -(예를 들어 프랑스어 문자열 값의 경우 {@code res/values-fr/}) 및 -사용자의 언어 설정을 근거로 하여 Android 시스템이 적절한 언어 문자열을 UI에 +(예를 들어 프랑스어 문자열 값의 경우 {@code res/values-fr/}) 및 +사용자의 언어 설정을 근거로 하여 Android 시스템이 적절한 언어 문자열을 UI에 적용하는 것입니다.

      Android는 대체 리소스에 대해 다양한 한정자를 지원합니다. 한정자란 - 리소스 디렉터리의 이름에 포함시키는 짧은 문자열로, 이를 사용해 해당 리소스를 사용할 기기 구성을 -정의합니다. 또 다른 예를 들자면, -기기의 화면 방향과 크기에 따라 액티비티에 여러 가지 레이아웃을 생성해야 할 때가 -많습니다. 예를 들어 기기 화면이 세로 -방향(키가 큼)인 경우, 버튼이 세로 방향으로 되어 있는 레이아웃을 사용하는 것이 좋지만 화면이 -가로 방향(폭이 넓음)인 경우, 버튼이 가로 방향으로 정렬되어야 합니다. 방향에 따라 레이아웃을 변경하려면, -서로 다른 두 가지 레이아웃을 정의하여 적절한 한정자를 각각의 레이아웃의 디렉터리 이름에 -적용하면 됩니다. 그러면 시스템이 현재 기기 방향에 따라 적절한 레이아웃을 + 리소스 디렉터리의 이름에 포함시키는 짧은 문자열로, 이를 사용해 해당 리소스를 사용할 기기 구성을 +정의합니다. 또 다른 예를 들자면, +기기의 화면 방향과 크기에 따라 액티비티에 여러 가지 레이아웃을 생성해야 할 때가 +많습니다. 예를 들어 기기 화면이 세로 +방향(키가 큼)인 경우, 버튼이 세로 방향으로 되어 있는 레이아웃을 사용하는 것이 좋지만 화면이 +가로 방향(폭이 넓음)인 경우, 버튼이 가로 방향으로 정렬되어야 합니다. 방향에 따라 레이아웃을 변경하려면, +서로 다른 두 가지 레이아웃을 정의하여 적절한 한정자를 각각의 레이아웃의 디렉터리 이름에 +적용하면 됩니다. 그러면 시스템이 현재 기기 방향에 따라 적절한 레이아웃을 자동으로 적용합니다.

      -

      애플리케이션에 포함할 수 있는 여러 가지 종류의 리소스와, 각기 다른 기기 구성에 따라 +

      애플리케이션에 포함할 수 있는 여러 가지 종류의 리소스와, 각기 다른 기기 구성에 따라 대체 리소스를 생성하는 방법에 대한 자세한 내용은 리소스 제공을 읽어보십시오.

      @@ -451,15 +451,15 @@ logo.png}라는 이름의 이미지 파일이 들어 있다고 하면({@code res
      인텐트 및 인텐트 필터
      -
      {@link android.content.Intent} API를 사용하여 -앱 구성 요소(예: 액티비티 및 서비스 등)를 활성화하는 방법, 앱 구성 요소를 다른 여러 앱이 사용할 수 있도록 하는 방법 +
      {@link android.content.Intent} API를 사용하여 +앱 구성 요소(예: 액티비티 및 서비스 등)를 활성화하는 방법, 앱 구성 요소를 다른 여러 앱이 사용할 수 있도록 하는 방법 등에 관한 정보입니다.
      액티비티
      -
      {@link android.app.Activity} 클래스의 인스턴스를 생성하는 방법에 관한 정보로, +
      {@link android.app.Activity} 클래스의 인스턴스를 생성하는 방법에 관한 정보로, 애플리케이션에 사용자 인터페이스가 있는 독특한 화면을 제공합니다.
      리소스 제공
      -
      Android 앱이 앱 코드와는 별개의 앱 리소스에 대해 구조화된 방식에 관한 정보로, -특정 기기 구성에 맞게 대체 리소스를 제공하는 방법도 포함되어 +
      Android 앱이 앱 코드와는 별개의 앱 리소스에 대해 구조화된 방식에 관한 정보로, +특정 기기 구성에 맞게 대체 리소스를 제공하는 방법도 포함되어 있습니다.
      @@ -468,11 +468,11 @@ logo.png}라는 이름의 이미지 파일이 들어 있다고 하면({@code res

      혹시 다음과 같은 내용에도 흥미가 있으신가요?

      기기 호환성
      -
      여러 가지 유형의 기기에서 Android의 작동 방식과 앱을 각 기기에 맞춰 최적화하는 방법 -또는 여러 가지 기기에 대해 앱의 가용성을 제한하는 방법 등에 관한 +
      여러 가지 유형의 기기에서 Android의 작동 방식과 앱을 각 기기에 맞춰 최적화하는 방법 +또는 여러 가지 기기에 대해 앱의 가용성을 제한하는 방법 등에 관한 정보입니다.
      시스템 권한
      -
      Android가 특정 API에 대한 앱의 액세스를 제한하기 위해 권한 시스템을 +
      Android가 특정 API에 대한 앱의 액세스를 제한하기 위해 권한 시스템을 사용하는 방법으로, 그러한 API를 사용하려면 앱에 대해 사용자의 승인이 필요합니다.
      diff --git a/docs/html-intl/intl/ko/guide/components/index.jd b/docs/html-intl/intl/ko/guide/components/index.jd index 36626324e817871dfd68082d049a9bda187cc02e..a860c0f5349f9803290843e9ee9575f318c2f5b2 100644 --- a/docs/html-intl/intl/ko/guide/components/index.jd +++ b/docs/html-intl/intl/ko/guide/components/index.jd @@ -1,7 +1,7 @@ page.title=앱 구성 요소 page.landing=true -page.landing.intro=Android의 애플리케이션 프레임워크는 일련의 재사용 가능한 구성 요소를 사용하여 풍성하고 혁신적인 앱을 생성할 수 있습니다. 이 섹션에서는 앱의 구성 단위를 정의 내리는 구성 요소를 구축하는 방법과 인텐트를 사용하여 이와 같은 구성 요소를 연결시키는 법을 설명합니다. -page.metaDescription=Android의 애플리케이션 프레임워크는 일련의 재사용 가능한 구성 요소를 사용하여 풍성하고 혁신적인 앱을 생성할 수 있습니다. 이 섹션에서는 앱의 구성 단위를 정의 내리는 구성 요소를 구축하는 방법과 인텐트를 사용하여 이와 같은 구성 요소를 연결시키는 법을 설명합니다. +page.landing.intro=Android의 애플리케이션 프레임워크는 일련의 재사용 가능한 구성 요소를 사용하여 풍성하고 혁신적인 앱을 생성할 수 있습니다. 이 섹션에서는 앱의 구성 단위를 정의 내리는 구성 요소를 구축하는 방법과 인텐트를 사용하여 이와 같은 구성 요소를 연결시키는 법을 설명합니다. +page.metaDescription=Android의 애플리케이션 프레임워크는 일련의 재사용 가능한 구성 요소를 사용하여 풍성하고 혁신적인 앱을 생성할 수 있습니다. 이 섹션에서는 앱의 구성 단위를 정의 내리는 구성 요소를 구축하는 방법과 인텐트를 사용하여 이와 같은 구성 요소를 연결시키는 법을 설명합니다. page.landing.image=images/develop/app_components.png page.image=images/develop/app_components.png @@ -11,7 +11,7 @@ page.image=images/develop/app_components.png

      교육

      - +

      액티비티 수명 주기 관리하기

      -

      이 클래스에서는 각각의 액티비티 -인스턴스가 수신하는 중요한 수명 주기 콜백 메서드를 설명합니다. 또한 이러한 콜백 메서드를 사용하여 액티비티가 +

      이 클래스에서는 각각의 액티비티 +인스턴스가 수신하는 중요한 수명 주기 콜백 메서드를 설명합니다. 또한 이러한 콜백 메서드를 사용하여 액티비티가 사용자가 원하는 작업을 하고, 액티비티가 필요로 하지 않을 때 시스템 리소스 사용을 방지하는 방법에 대해서도 설명합니다.

      프래그먼트로 동적 UI 구축하기

      -

      이 클래스에서는 Android 1.6만큼 오래된 버전을 실행하는 기기도 -계속 지원하면서 프래그먼트로 동적 사용자 경험을 생성하고, 기기의 화면 크기에 따라 앱의 사용자 환경을 +

      이 클래스에서는 Android 1.6만큼 오래된 버전을 실행하는 기기도 +계속 지원하면서 프래그먼트로 동적 사용자 경험을 생성하고, 기기의 화면 크기에 따라 앱의 사용자 환경을 최적화할 수 있는 방법을 보여줍니다.

      콘텐츠 공유하기

      -

      이 클래스는 인텐트 API와 ActionProvider 객체를 사용하여 여러 애플리케이션 사이에서 +

      이 클래스는 인텐트 API와 ActionProvider 객체를 사용하여 여러 애플리케이션 사이에서 콘텐츠를 전송하고 수신하는 몇 가지 보편적인 방법을 다룹니다.

      diff --git a/docs/html-intl/intl/ko/guide/components/loaders.jd b/docs/html-intl/intl/ko/guide/components/loaders.jd index cfbbb9133ed416d4ac66e20f0f5120b17414fb8f..dd02e117f7c7e7ee04e954292d7ed62fb7e7f754 100644 --- a/docs/html-intl/intl/ko/guide/components/loaders.jd +++ b/docs/html-intl/intl/ko/guide/components/loaders.jd @@ -21,14 +21,14 @@ parent.link=activities.html - +

      Key 클래스

      1. {@link android.app.LoaderManager}
      2. {@link android.content.Loader}
      3. -
      - + +

      관련 샘플

      1. @@ -39,22 +39,22 @@ LoaderThrottle
      2. -

        로더는 Android 3.0부터 도입된 것으로, 액티비티 또는 프래그먼트에서 비동기식으로 데이터를 쉽게 +

        로더는 Android 3.0부터 도입된 것으로, 액티비티 또는 프래그먼트에서 비동기식으로 데이터를 쉽게 로딩할 수 있게 합니다. 로더의 특성은 다음과 같습니다.

        • 모든 {@link android.app.Activity}와 {@link android.app.Fragment}에 사용할 수 있습니다.
        • 데이터의 비동기식 로딩을 제공합니다.
        • -
        • 데이터의 출처를 모니터링하여 그 콘텐츠가 변경되면 새 결과를 +
        • 데이터의 출처를 모니터링하여 그 콘텐츠가 변경되면 새 결과를 전달합니다.
        • -
        • 구성 변경 후에 재생성된 경우, 마지막 로더의 커서로 자동으로 -다시 연결됩니다. 따라서 데이터를 다시 쿼리하지 않아도 +
        • 구성 변경 후에 재생성된 경우, 마지막 로더의 커서로 자동으로 +다시 연결됩니다. 따라서 데이터를 다시 쿼리하지 않아도 됩니다.
        - +

        로더 API 요약

        -

        애플리케이션 안에서 로더를 사용하는 데 관련된 클래스와 인터페이스는 +

        애플리케이션 안에서 로더를 사용하는 데 관련된 클래스와 인터페이스는 여러 가지가 있습니다. 다음 표에서 요약되어 있습니다.

        @@ -64,16 +64,16 @@ android.app.Fragment}에 사용할 수 있습니다. - @@ -85,10 +85,10 @@ android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} - @@ -97,118 +97,118 @@ android.content.CursorLoader}를 사용하기 마련이지만, 자신만의 하 -
        {@link android.app.LoaderManager}{@link android.app.Activity} 또는 + {@link android.app.Activity} 또는 {@link android.app.Fragment}와 연관된 추상 클래스로, 하나 이상의 {@link -android.content.Loader} 인스턴스를 관리하는 데 쓰입니다. 이것을 사용하면 애플리케이션이 +android.content.Loader} 인스턴스를 관리하는 데 쓰입니다. 이것을 사용하면 애플리케이션이 {@link android.app.Activity} - 또는 {@link android.app.Fragment} 수명 주기와 함께 실행 시간이 긴 작업을 관리하는 데 도움이 됩니다. 이것의 가장 보편적인 용법은 -{@link android.content.CursorLoader}와 함께 사용하는 것이지만, + 또는 {@link android.app.Fragment} 수명 주기와 함께 실행 시간이 긴 작업을 관리하는 데 도움이 됩니다. 이것의 가장 보편적인 용법은 +{@link android.content.CursorLoader}와 함께 사용하는 것이지만, 다른 유형의 데이터를 로드하기 위해 애플리케이션이 자체 로더를 작성하는 것도 얼마든지 가능합니다.

        - 액티비티 또는 프래그먼트당 {@link android.app.LoaderManager}는 하나씩밖에 없습니다. 하지만 {@link android.app.LoaderManager}에는 로더가 여러 개 있어도 + 액티비티 또는 프래그먼트당 {@link android.app.LoaderManager}는 하나씩밖에 없습니다. 하지만 {@link android.app.LoaderManager}에는 로더가 여러 개 있어도 됩니다.
        {@link android.content.Loader}데이터의 비동기식 로딩을 수행하는 추상 클래스입니다. 이것이 로더의 기본 + 데이터의 비동기식 로딩을 수행하는 추상 클래스입니다. 이것이 로더의 기본 클래스입니다. 보통은 {@link -android.content.CursorLoader}를 사용하기 마련이지만, 자신만의 하위 클래스를 구현해도 됩니다. 로더가 활성 상태인 동안에는 -소속 데이터의 출처를 모니터링하고 콘텐츠가 변경되면 새 결과를 +android.content.CursorLoader}를 사용하기 마련이지만, 자신만의 하위 클래스를 구현해도 됩니다. 로더가 활성 상태인 동안에는 +소속 데이터의 출처를 모니터링하고 콘텐츠가 변경되면 새 결과를 전달하는 것이 정상입니다.
        {@link android.content.CursorLoader}{@link android.content.AsyncTaskLoader}의 하위 클래스로, 이것이 + {@link android.content.AsyncTaskLoader}의 하위 클래스로, 이것이 {@link android.content.ContentResolver}를 쿼리하고 {@link android.database.Cursor}를 반환합니다. 이 클래스는 커서 쿼리에 대한 표준 방식으로 {@link -android.content.Loader} 프로토콜을 구현하며, -{@link android.content.AsyncTaskLoader}에 구축되어 -배경 스레드에서 커서 쿼리를 수행하므로 애플리케이션의 UI를 차단하지 않습니다. +android.content.Loader} 프로토콜을 구현하며, +{@link android.content.AsyncTaskLoader}에 구축되어 +배경 스레드에서 커서 쿼리를 수행하므로 애플리케이션의 UI를 차단하지 않습니다. 이 로더를 사용하는 것이 프래그먼트나 액티비티의 API를 통해 관리된 쿼리를 수행하는 대신 {@link -android.content.ContentProvider}에서 +android.content.ContentProvider}에서 비동기식으로 데이터를 로딩하는 최선의 방법입니다.
        -

        위의 표에 나열된 클래스와 인터페이스가 애플리케이션 내에서 로더를 구현하는 데 -사용할 기본적인 구성 요소입니다. 생성하는 로더마다 +

        위의 표에 나열된 클래스와 인터페이스가 애플리케이션 내에서 로더를 구현하는 데 +사용할 기본적인 구성 요소입니다. 생성하는 로더마다 이 모든 것이 다 필요한 것은 아니지만, 로더를 초기화하려면 항상 {@link android.app.LoaderManager}를 참조해야 하고 {@link -android.content.CursorLoader}와 같은 {@link android.content.Loader} -클래스도 구현해야 합니다. 다음 몇 섹션에서는 애플리케이션 안에서 이와 같은 +android.content.CursorLoader}와 같은 {@link android.content.Loader} +클래스도 구현해야 합니다. 다음 몇 섹션에서는 애플리케이션 안에서 이와 같은 클래스와 인터페이스를 사용하는 법을 보여줍니다.

        애플리케이션 안에서 로더 사용하기

        -

        이 섹션에서는 Android 애플리케이션 내에서 로더를 사용하는 방법을 설명합니다. 로더를 +

        이 섹션에서는 Android 애플리케이션 내에서 로더를 사용하는 방법을 설명합니다. 로더를 사용하는 애플리케이션에는 보통 다음이 포함되어 있습니다.

        • {@link android.app.Activity} 또는 {@link android.app.Fragment}.
        • {@link android.app.LoaderManager}의 인스턴스.
        • {@link -android.content.ContentProvider}가 지원하는 데이터를 로딩할 {@link android.content.CursorLoader}. 아니면, 개발자 나름의 -{@link android.content.Loader} 또는 {@link android.content.AsyncTaskLoader} 하위 클래스를 구현하여 +android.content.ContentProvider}가 지원하는 데이터를 로딩할 {@link android.content.CursorLoader}. 아니면, 개발자 나름의 +{@link android.content.Loader} 또는 {@link android.content.AsyncTaskLoader} 하위 클래스를 구현하여 다른 출처에서 데이터를 로딩해도 됩니다.
        • {@link android.app.LoaderManager.LoaderCallbacks}의 구현. -여기에서 새 로더를 생성하고 기존 로더에 대한 참조를 -관리합니다.
        • +여기에서 새 로더를 생성하고 기존 로더에 대한 참조를 +관리합니다.
        • 로더의 데이터를 표시하는 방법(예: {@link android.widget.SimpleCursorAdapter})
        • -
        • {@link android.content.ContentProvider}와 같은 데이터 출처로, +
        • {@link android.content.ContentProvider}와 같은 데이터 출처로, {@link android.content.CursorLoader}를 사용하는 경우에 해당.

        로더 시작

        -

        {@link android.app.LoaderManager}는 {@link android.app.Activity} 또는 +

        {@link android.app.LoaderManager}는 {@link android.app.Activity} 또는 {@link android.app.Fragment} 내에서 하나 이상의 {@link android.content.Loader} 인스턴스를 관리합니다. 액티비티 또는 프래그먼트당 {@link -android.app.LoaderManager}는 하나씩밖에 없습니다.

        +android.app.LoaderManager}는 하나씩밖에 없습니다.

        -

        보통은 +

        보통은 액티비티의 {@link -android.app.Activity#onCreate onCreate()} 메서드 내에서, 또는 프래그먼트의 -{@link android.app.Fragment#onActivityCreated onActivityCreated()} 메서드 내에서 {@link android.content.Loader}를 초기화합니다. 이렇게 하려면 +android.app.Activity#onCreate onCreate()} 메서드 내에서, 또는 프래그먼트의 +{@link android.app.Fragment#onActivityCreated onActivityCreated()} 메서드 내에서 {@link android.content.Loader}를 초기화합니다. 이렇게 하려면 다음과 같은 방법을 따릅니다.

        // Prepare the loader.  Either re-connect with an existing one,
         // or start a new one.
         getLoaderManager().initLoader(0, null, this);
        -

        {@link android.app.LoaderManager#initLoader initLoader()} 메서드는 +

        {@link android.app.LoaderManager#initLoader initLoader()} 메서드는 다음과 같은 인수를 취합니다.

        • 로더를 식별하는 고유한 ID. 이 예시에서 ID는 0입니다.
        • 생성 시 로더에 제공할 선택적 인수 -(이 예시에서는 null).
        • +(이 예시에서는 null). -
        • {@link android.app.LoaderManager.LoaderCallbacks} 구현. 로더 이벤트를 보고하기 위해 +
        • {@link android.app.LoaderManager.LoaderCallbacks} 구현. 로더 이벤트를 보고하기 위해 {@link android.app.LoaderManager}가 이것을 호출합니다. 이 예시에서는 로컬 클래스가 {@link -android.app.LoaderManager.LoaderCallbacks} 인터페이스를 구현하여 자신에 대한 참조인 -{@code this}를 통과합니다.
        • +android.app.LoaderManager.LoaderCallbacks} 인터페이스를 구현하여 자신에 대한 참조인 +{@code this}를 통과합니다.
        -

        {@link android.app.LoaderManager#initLoader initLoader()} 호출로 로더가 초기화되었고 활성 상태이도록 +

        {@link android.app.LoaderManager#initLoader initLoader()} 호출로 로더가 초기화되었고 활성 상태이도록 확실히 합니다. 이로써 발생할 수 있는 결과가 두 가지 있습니다.

          -
        • ID가 지정한 로더가 이미 존재하는 경우, 마지막으로 생성된 로더를 +
        • ID가 지정한 로더가 이미 존재하는 경우, 마지막으로 생성된 로더를 재사용합니다.
        • -
        • ID가 지정한 로더가 존재하지 않는 경우, -{@link android.app.LoaderManager#initLoader initLoader()}가 -{@link android.app.LoaderManager.LoaderCallbacks} 메서드 {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}를 발생시킵니다. +
        • ID가 지정한 로더가 존재하지 않는 경우, +{@link android.app.LoaderManager#initLoader initLoader()}가 +{@link android.app.LoaderManager.LoaderCallbacks} 메서드 {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}를 발생시킵니다. 여기에서 인스턴트화할 코드를 구현하고 새 로더를 반환합니다. 자세한 논의는 onCreateLoader 섹션을 참조하십시오.

        어떤 경우에든 주어진 {@link android.app.LoaderManager.LoaderCallbacks} -구현은 해당 로더와 연관되어 있으며, 로더 상태가 변경되면 -이것이 호출됩니다. 이 호출의 그러한 시점에서 발신자가 -시작된 상태에 있으며 요청한 로더가 이미 존재하고 자신의 데이터를 +구현은 해당 로더와 연관되어 있으며, 로더 상태가 변경되면 +이것이 호출됩니다. 이 호출의 그러한 시점에서 발신자가 +시작된 상태에 있으며 요청한 로더가 이미 존재하고 자신의 데이터를 생성해 놓은 경우, 시스템은 즉시 {@link -android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}를 -호출합니다({@link android.app.LoaderManager#initLoader initLoader()} 도중). +android.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}를 +호출합니다({@link android.app.LoaderManager#initLoader initLoader()} 도중). 따라서 이런 일이 발생할 것에 대비해두어야만 합니다. 이 콜백에 대한 자세한 논의는 onLoadFinished를 참조하십시오.

        {@link android.app.LoaderManager#initLoader initLoader()} -메서드는 생성된 {@link android.content.Loader}를 반환하지만, 이에 대한 참조를 캡처하지 않아도 된다는 점을 -유의하십시오. {@link android.app.LoaderManager}는 로더의 수명을 -자동으로 관리합니다. {@link android.app.LoaderManager}는 -필요에 따라 로딩을 시작하고 중단하며, 로더와 그에 연관된 콘텐츠의 상태를 -유지관리합니다. 이것이 시사하는 바와 같이, 로더와 직접적으로 -상호 작용하는 경우는 극히 드뭅니다(다만, 로더의 행동을 미세하게 조정하기 위해 로더 메서드를 사용하는 사례를 알아보려면 - LoaderThrottle 샘플을 참조하면 좋습니다). +메서드는 생성된 {@link android.content.Loader}를 반환하지만, 이에 대한 참조를 캡처하지 않아도 된다는 점을 +유의하십시오. {@link android.app.LoaderManager}는 로더의 수명을 +자동으로 관리합니다. {@link android.app.LoaderManager}는 +필요에 따라 로딩을 시작하고 중단하며, 로더와 그에 연관된 콘텐츠의 상태를 +유지관리합니다. 이것이 시사하는 바와 같이, 로더와 직접적으로 +상호 작용하는 경우는 극히 드뭅니다(다만, 로더의 행동을 미세하게 조정하기 위해 로더 메서드를 사용하는 사례를 알아보려면 + LoaderThrottle 샘플을 참조하면 좋습니다). 가장 보편적으로 사용되는 메서드는 {@link -android.app.LoaderManager.LoaderCallbacks}로, 이를 사용해 특정한 이벤트가 일어났을 때 +android.app.LoaderManager.LoaderCallbacks}로, 이를 사용해 특정한 이벤트가 일어났을 때 로딩 프로세스에 개입하게 됩니다. 이 주제에 대한 자세한 논의는 LoaderManager 콜백 사용하기를 참조하십시오.

        로더 다시 시작

        -

        위에서 나타난 것과 같이 {@link android.app.LoaderManager#initLoader initLoader()}를 사용하는 경우, -이것은 지정된 ID에 해당되는 기존 로더가 있으면 그것을 사용합니다. -없으면, 하나 생성합니다. 하지만 때로는 오래된 데이터를 폐기하고 새로 시작하고 싶을 때가 +

        위에서 나타난 것과 같이 {@link android.app.LoaderManager#initLoader initLoader()}를 사용하는 경우, +이것은 지정된 ID에 해당되는 기존 로더가 있으면 그것을 사용합니다. +없으면, 하나 생성합니다. 하지만 때로는 오래된 데이터를 폐기하고 새로 시작하고 싶을 때가 있습니다.

        오래된 데이터를 폐기하려면 {@link -android.app.LoaderManager#restartLoader restartLoader()}를 사용합니다. 예를 들어, 다음의 -{@link android.widget.SearchView.OnQueryTextListener} 구현은 -사용자의 쿼리가 변경되면 로더를 다시 시작합니다. 로더를 다시 시작해야 수정된 검색 필터를 사용하여 +android.app.LoaderManager#restartLoader restartLoader()}를 사용합니다. 예를 들어, 다음의 +{@link android.widget.SearchView.OnQueryTextListener} 구현은 +사용자의 쿼리가 변경되면 로더를 다시 시작합니다. 로더를 다시 시작해야 수정된 검색 필터를 사용하여 새 쿼리를 수행할 수 있습니다.

        @@ -223,18 +223,18 @@ public boolean onQueryTextChanged(String newText) {
         
         

        LoaderManager 콜백 사용하기

        -

        {@link android.app.LoaderManager.LoaderCallbacks}는 클라이언트가 +

        {@link android.app.LoaderManager.LoaderCallbacks}는 클라이언트가 {@link android.app.LoaderManager}와 상호 작용할 수 있게 해주는 콜백 인터페이스입니다.

        -

        로더, 특히 {@link android.content.CursorLoader}는 중단된 후에도 -자신의 데이터를 유지할 것으로 기대됩니다. 이 때문에 애플리케이션이 +

        로더, 특히 {@link android.content.CursorLoader}는 중단된 후에도 +자신의 데이터를 유지할 것으로 기대됩니다. 이 때문에 애플리케이션이 액티비티 또는 프래그먼트의 @link android.app.Activity#onStop -onStop()} 및 {@link android.app.Activity#onStart onStart()}를 가로질러 데이터를 유지할 수 있고, -따라서 사용자가 애플리케이션에 되돌아오면 데이터가 다시 로딩되기를 기다리지 -않아도 됩니다. 새 로더를 언제 생성해야 할지 알아보려면 {@link android.app.LoaderManager.LoaderCallbacks} -메서드를 사용합니다. 또한 로더의 데이터 사용을 중단할 때가 되면 +onStop()} 및 {@link android.app.Activity#onStart onStart()}를 가로질러 데이터를 유지할 수 있고, +따라서 사용자가 애플리케이션에 되돌아오면 데이터가 다시 로딩되기를 기다리지 +않아도 됩니다. 새 로더를 언제 생성해야 할지 알아보려면 {@link android.app.LoaderManager.LoaderCallbacks} +메서드를 사용합니다. 또한 로더의 데이터 사용을 중단할 때가 되면 이를 애플리케이션에 알리는 데에도 이것을 사용할 수 있습니다.

        -

        {@link android.app.LoaderManager.LoaderCallbacks}에는 다음과 같은 메서드가 +

        {@link android.app.LoaderManager.LoaderCallbacks}에는 다음과 같은 메서드가 포함됩니다.

        • {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} - @@ -246,7 +246,7 @@ onStop()} 및 {@link android.app.Activity#onStart onStart()}를 가로질러 데
        • {@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} -- 이전에 생성된 로더가 휴식 중이라서 해당되는 데이터를 사용할 수 없을 경우 +- 이전에 생성된 로더가 휴식 중이라서 해당되는 데이터를 사용할 수 없을 경우 호출됩니다.
        @@ -255,32 +255,32 @@ onStop()} 및 {@link android.app.Activity#onStart onStart()}를 가로질러 데

        onCreateLoader

        로더에 액세스하려 시도하는 경우(예를 들어 {@link -android.app.LoaderManager#initLoader initLoader()}를 통해), 로더는 해당 ID가 지정하는 로더가 존재하는지 +android.app.LoaderManager#initLoader initLoader()}를 통해), 로더는 해당 ID가 지정하는 로더가 존재하는지 여부를 확인합니다. 그런 로더가 없으면, {@link android.app.LoaderManager.LoaderCallbacks} 메서드 {@link -android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}를 발생시킵니다. 여기에서 +android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}를 발생시킵니다. 여기에서 새 로더를 생성합니다. 이것은 보통 {@link android.content.CursorLoader}이지만, 개발자 나름대로 {@link android.content.Loader} 하위 클래스를 구현해도 됩니다.

        이 예시에서는, {@link android.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} - 콜백 메서드가 {@link android.content.CursorLoader}를 생성합니다. -{@link android.content.CursorLoader}를 자체 생성자 메서드를 사용하여 구축해야 합니다. 이것은 + 콜백 메서드가 {@link android.content.CursorLoader}를 생성합니다. +{@link android.content.CursorLoader}를 자체 생성자 메서드를 사용하여 구축해야 합니다. 이것은 {@link android.content.ContentProvider}로 쿼리를 수행하기 위해 필요한 모든 정보 집합을 필요로 합니다. 구체적으로 필요한 것은 다음과 같습니다.

        • uri — 검색할 콘텐츠의 URI입니다.
        • -
        • 예측 — 반환할 열 목록입니다. +
        • 예측 — 반환할 열 목록입니다. null을 전달하면 모든 열을 반환하며, 이는 비효율적입니다.
        • -
        • 선택 — 반환할 행을 선언하는 필터로, -SQL WHERE 절로 형식이 설정됩니다(WHERE 자체는 제외). +
        • 선택 — 반환할 행을 선언하는 필터로, +SQL WHERE 절로 형식이 설정됩니다(WHERE 자체는 제외). null을 반환하면 주어진 URI에 대한 모든 행을 반환합니다.
        • -
        • selectionArgs — 선택에 ?를 포함해도 됩니다. 이렇게 하면 -이것이 selectionArgs에서 가져온 값으로 교체되며, 이때 선택에 표시되는 +
        • selectionArgs — 선택에 ?를 포함해도 됩니다. 이렇게 하면 +이것이 selectionArgs에서 가져온 값으로 교체되며, 이때 선택에 표시되는 순서를 따릅니다. 값은 문자열로 바인딩됩니다.
        • -
        • sortOrder — SQL ORDER BY 절 형식으로 설정된 -행의 순서 지정 방법입니다(ORDER BY 자체는 제외). null을 +
        • sortOrder — SQL ORDER BY 절 형식으로 설정된 +행의 순서 지정 방법입니다(ORDER BY 자체는 제외). null을 전달하면 기본 정렬 순서를 사용하는데, 이는 순서가 없습니다.

        예:

        @@ -312,19 +312,19 @@ public Loader<Cursor> onCreateLoader(int id, Bundle args) { }

        onLoadFinished

        -

        이 메서드는 이전에 생성된 로더가 로딩을 완료하면 호출됩니다. -이 로더에 대해 제공된 마지막 데이터가 릴리스되기 전에 틀림없이 -이 메서드가 호출됩니다. 이 시점에서 오래된 데이터의 -사용 내용을 모두 제거해야 하지만(곧 릴리스될 것이므로), 데이터 릴리스를 직접 수행해서는 안 됩니다. 해당 데이터는 +

        이 메서드는 이전에 생성된 로더가 로딩을 완료하면 호출됩니다. +이 로더에 대해 제공된 마지막 데이터가 릴리스되기 전에 틀림없이 +이 메서드가 호출됩니다. 이 시점에서 오래된 데이터의 +사용 내용을 모두 제거해야 하지만(곧 릴리스될 것이므로), 데이터 릴리스를 직접 수행해서는 안 됩니다. 해당 데이터는 로더의 소유이며, 로더가 알아서 처리할 것이기 때문입니다.

        -

        로더는 애플리케이션이 데이터를 더 이상 사용하지 않는다는 사실을 알게 되면 곧바로 해당 데이터를 +

        로더는 애플리케이션이 데이터를 더 이상 사용하지 않는다는 사실을 알게 되면 곧바로 해당 데이터를 릴리스할 것입니다. 예를 들어 데이터가 {@link android.content.CursorLoader}의 커서인 경우, 거기에서 직접 {@link -android.database.Cursor#close close()}를 호출하면 안 됩니다. 커서가 +android.database.Cursor#close close()}를 호출하면 안 됩니다. 커서가 {@link android.widget.CursorAdapter}에 배치되는 경우, {@link -android.widget.SimpleCursorAdapter#swapCursor swapCursor()} 메서드를 사용해야 합니다. 그래야 +android.widget.SimpleCursorAdapter#swapCursor swapCursor()} 메서드를 사용해야 합니다. 그래야 오래된 {@link android.database.Cursor}가 종료되지 않습니다. 예:

        @@ -340,11 +340,11 @@ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
         
         

        onLoaderReset

        -

        이 메서드는 이전에 생성된 로더가 휴식 중이라서 해당되는 데이터를 사용할 수 없는 경우 -호출됩니다. 이 콜백을 사용하면 데이터가 언제 릴리스될지 알아낼 수 있어 +

        이 메서드는 이전에 생성된 로더가 휴식 중이라서 해당되는 데이터를 사용할 수 없는 경우 +호출됩니다. 이 콜백을 사용하면 데이터가 언제 릴리스될지 알아낼 수 있어 이에 대한 참조를 직접 제거할 수 있습니다.  

        -

        이 구현은 -{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}를 호출하며, +

        이 구현은 +{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}를 호출하며, 이때 값은 null을 씁니다.

        @@ -363,12 +363,12 @@ public void onLoaderReset(Loader<Cursor> loader) {
         

        일례를 제시하기 위해 아래에 {@link android.widget.ListView}를 표시하는 {@link -android.app.Fragment}의 전체 구현을 나타내었습니다. 여기에는 +android.app.Fragment}의 전체 구현을 나타내었습니다. 여기에는 연락처 콘텐츠 제공자에 대한 쿼리 결과가 들어 있습니다. 이것은 {@link android.content.CursorLoader}를 사용하여 제공자에 대한 쿼리를 관리합니다.

        - -

        이 예시에서 나타낸 바와 같이 애플리케이션이 사용자의 연락처에 액세스하려면 -애플리케이션의 매니페스트에 + +

        이 예시에서 나타낸 바와 같이 애플리케이션이 사용자의 연락처에 액세스하려면 +애플리케이션의 매니페스트에 {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS} 권한이 포함되어 있어야 합니다.

        @@ -479,16 +479,16 @@ public static class CursorLoaderListFragment extends ListFragment
         }

        추가 예

        -

        로더를 사용하는 법을 보여주는 몇 가지 다른 예가 ApiDemos에 +

        로더를 사용하는 법을 보여주는 몇 가지 다른 예가 ApiDemos에 소개되어 있습니다.

        • -LoaderCursor — 위에 표시된 코드 조각의 완전한 +LoaderCursor — 위에 표시된 코드 조각의 완전한 버전입니다.
        • -
        • LoaderThrottle — 데이터가 변경될 때 콘텐츠 제공자가 +
        • LoaderThrottle — 데이터가 변경될 때 콘텐츠 제공자가 수행하는 쿼리의 수를 줄이기 위해 제한을 사용하는 방법을 예시로 나타낸 것입니다.
        -

        SDK 샘플을 다운로드하고 설치하는 데 대한 정보는 샘플 +

        SDK 샘플을 다운로드하고 설치하는 데 대한 정보는 샘플 가져오기를 참조하십시오.

        diff --git a/docs/html-intl/intl/ko/guide/components/processes-and-threads.jd b/docs/html-intl/intl/ko/guide/components/processes-and-threads.jd index 850d55cf9c71d5898ba354f955cf072d57a97143..cad4917a8c43fd8014fe88a251b80b7e96955876 100644 --- a/docs/html-intl/intl/ko/guide/components/processes-and-threads.jd +++ b/docs/html-intl/intl/ko/guide/components/processes-and-threads.jd @@ -28,10 +28,10 @@ page.tags=수명 주기, 배경

        애플리케이션 구성 요소가 시작되고 애플리케이션에 실행 중인 다른 구성 요소가 없으면 Android 시스템은 하나의 실행 스레드로 애플리케이션의 Linux 프로세스를 시작합니다. 기본적으로 같은 애플리케이션의 모든 구성 요소는 같은 프로세스와 스레드에서 실행됩니다 -("기본" 스레드라고 합니다). 애플리케이션 구성 요소가 시작되고 (애플리케이션의 다른 구성 요소가 존재해서) +("기본" 스레드라고 합니다). 애플리케이션 구성 요소가 시작되고 (애플리케이션의 다른 구성 요소가 존재해서) 해당 애플리케이션의 프로세스가 이미 존재하면 해당 구성 요소는 -프로세스 내에서 시작되고 같은 실행 스레드를 사용합니다. 하지만 애플리케이션 내의 -여러 가지 구성 요소가 각자 별도의 프로세스에서 실행되도록 할 수도 있고, 어느 프로세스에든 추가 스레드를 +프로세스 내에서 시작되고 같은 실행 스레드를 사용합니다. 하지만 애플리케이션 내의 +여러 가지 구성 요소가 각자 별도의 프로세스에서 실행되도록 할 수도 있고, 어느 프로세스에든 추가 스레드를 만들 수 있습니다.

        이 문서는 프로세스와 스레드가 Android 애플리케이션에서 작동하는 방식을 설명합니다.

        @@ -48,8 +48,8 @@ Android 시스템은 하나의 실행 스레드로 애플리케이션의 Linux <service>}, {@code <receiver>}{@code <provider>}—의 각 유형에 대한 매니페스트 항목은 구성 요소를 실행할 프로세스를 지정하는 {@code android:process} 속성을 지원합니다. - 이러한 속성을 설정하여 각 구성 요소를 자체 프로세스에서 실행시키거나 -다른 구성 요소를 제외한 일부 구성 요소만 프로세스를 공유하게 할 수 있습니다 또한, + 이러한 속성을 설정하여 각 구성 요소를 자체 프로세스에서 실행시키거나 +다른 구성 요소를 제외한 일부 구성 요소만 프로세스를 공유하게 할 수 있습니다 또한, {@code android:process}를 설정하여 다른 애플리케이션의 구성 요소를 같은 프로세스에서 실행시킬 수 있습니다. 단, 이는 애플리케이션이 같은 Linux 사용자 ID를 공유하고 같은 인증서에 서명되었을 경우에 한합니다.

        @@ -58,35 +58,35 @@ Android 시스템은 하나의 실행 스레드로 애플리케이션의 Linux <application>} 요소도 {@code android:process} 속성을 지원하여, 모든 구성 요소에 적용되는 기본값을 설정합니다.

        -

        Android는 어느 시점엔가 프로세스를 종료하기로 결정할 수도 있습니다. 즉 메모리가 부족하거나, 사용자에게 더욱 즉각적인 서비스를 제공하는 -다른 프로세스가 이 프로세스의 중단을 필요로 하는 경우 등입니다. 그러면 중단된 -프로세스에서 실행되고 있던 애플리케이션 구성 요소도 따라서 소멸됩니다. 그와 같은 구성 요소가 할 작업이 다시 생기면 +

        Android는 어느 시점엔가 프로세스를 종료하기로 결정할 수도 있습니다. 즉 메모리가 부족하거나, 사용자에게 더욱 즉각적인 서비스를 제공하는 +다른 프로세스가 이 프로세스의 중단을 필요로 하는 경우 등입니다. 그러면 중단된 +프로세스에서 실행되고 있던 애플리케이션 구성 요소도 따라서 소멸됩니다. 그와 같은 구성 요소가 할 작업이 다시 생기면 그에 대한 프로세스도 다시 시작됩니다.

        -

        어느 프로세스를 삭제할지 결정할 때, Android 시스템은 -사용자에 대한 이들의 상대적 중요성을 가늠합니다. 예를 들어, 눈에 보이는 액티비티를 호스팅하는 프로세스와 비교하여 -화면에 보이지 않는 액티비티를 호스팅하는 프로세스를 쉽게 종료할 수 있습니다. 프로세스 종료 결정은 -해당 프로세스에서 실행되는 구성 요소의 상태에 따라 달라집니다. 종료할 +

        어느 프로세스를 삭제할지 결정할 때, Android 시스템은 +사용자에 대한 이들의 상대적 중요성을 가늠합니다. 예를 들어, 눈에 보이는 액티비티를 호스팅하는 프로세스와 비교하여 +화면에 보이지 않는 액티비티를 호스팅하는 프로세스를 쉽게 종료할 수 있습니다. 프로세스 종료 결정은 +해당 프로세스에서 실행되는 구성 요소의 상태에 따라 달라집니다. 종료할 프로세스를 결정하는 데 사용하는 규칙은 아래에 설명되어 있습니다.

        프로세스 수명 주기

        Android 시스템은 최대한 오래 애플리케이션 프로세스를 유지하려고 시도하지만, -결국 오래된 프로세스를 제거하고 새 프로세스나 더 중요한 프로세스에 사용할 메모리를 확보해야 합니다. 유지할 +결국 오래된 프로세스를 제거하고 새 프로세스나 더 중요한 프로세스에 사용할 메모리를 확보해야 합니다. 유지할 프로세스와 종료할 프로세스를 결정하기 위해 -시스템은 프로세스에서 실행되는 구성 요소와 해당 구성 요소의 상태에 기초하여 각 프로세스에 -"중요 계층"을 부여합니다. 중요도가 낮은 +시스템은 프로세스에서 실행되는 구성 요소와 해당 구성 요소의 상태에 기초하여 각 프로세스에 +"중요 계층"을 부여합니다. 중요도가 낮은 프로세스가 먼저 제거되고, 그 다음으로 중요도가 낮은 프로세스를 제거하는 식으로 필요에 따라 시스템 리소스를 회복하는 것입니다.

        -

        중요 계층에는 다섯 가지 단계가 있습니다. 다음 목록은 -중요도 순서에 따른 프로세스 유형을 나타낸 것입니다(첫 번째 프로세스가 가장 중요하고 +

        중요 계층에는 다섯 가지 단계가 있습니다. 다음 목록은 +중요도 순서에 따른 프로세스 유형을 나타낸 것입니다(첫 번째 프로세스가 가장 중요하고 마지막으로 종료됩니다).

        1. 전경 프로세스 -

          사용자가 현재 진행하는 작업에 필요한 프로세스입니다. 다음 조건 중 +

          사용자가 현재 진행하는 작업에 필요한 프로세스입니다. 다음 조건 중 하나가 참일 경우 프로세스가 전경에 있는 것으로 간주합니다.

            @@ -108,19 +108,19 @@ onStart()} 또는 {@link android.app.Service#onDestroy onDestroy()}). android.content.BroadcastReceiver#onReceive onReceive()} 메서드를 실행하는 {@link android.content.BroadcastReceiver}를 호스팅할 경우.
          -

          일반적으로, 주어진 시간에 존재하는 전경 프로세스는 몇 개밖에 되지 않습니다. 이들은 최후의 -수단으로서만 종료됩니다. 즉, 메모리가 너무 부족해 계속 실행할 수 없는 경우를 말합니다. 일반적으로 그 시점이 되면 -기기가 메모리 페이징 상태에 도달한 것이므로 전경 프로세스 몇 개를 중단해야만 +

          일반적으로, 주어진 시간에 존재하는 전경 프로세스는 몇 개밖에 되지 않습니다. 이들은 최후의 +수단으로서만 종료됩니다. 즉, 메모리가 너무 부족해 계속 실행할 수 없는 경우를 말합니다. 일반적으로 그 시점이 되면 +기기가 메모리 페이징 상태에 도달한 것이므로 전경 프로세스 몇 개를 중단해야만 사용자 인터페이스의 반응성을 유지할 수 있습니다.

        2. 가시적 프로세스 -

          전경 구성 요소는 없지만 -사용자가 화면에서 보는 것에 영향을 미칠 수 있는 프로세스입니다. 다음 조건 중 하나가 참이면 +

          전경 구성 요소는 없지만 +사용자가 화면에서 보는 것에 영향을 미칠 수 있는 프로세스입니다. 다음 조건 중 하나가 참이면 가시적 프로세스로 간주합니다.

          • 전경에 있지는 않지만 사용자에게 보이는 {@link android.app.Activity}를 호스팅할 경우 -({@link android.app.Activity#onPause onPause()} 메서드가 호출되었을 경우). +({@link android.app.Activity#onPause onPause()} 메서드가 호출되었을 경우). 예를 들어 이것은 전경 액티비티가 대화를 시작하여 이전 액티비티가 그 뒤에 보일 경우 발생합니다.
          • @@ -128,59 +128,59 @@ android.content.BroadcastReceiver#onReceive onReceive()} 메서드를 실행하
          -

          가시적인 프로세스는 매우 중요도가 높은 것으로 취급하고 모든 전경 프로세스를 실행하는 데 필요할 경우에만 +

          가시적인 프로세스는 매우 중요도가 높은 것으로 취급하고 모든 전경 프로세스를 실행하는 데 필요할 경우에만 종료됩니다.

        3. 서비스 프로세스

          {@link -android.content.Context#startService startService()} 메서드로 시작되었지만 두 개의 상위 계층 분류에 -들어가지 않는 서비스를 실행하는 프로세스입니다. 서비스 프로세스는 사용자가 보는 것과 직접 연결되어 있지는 않지만, -일반적으로 사용자가 신경 쓰는 작업을 하므로(배경에서 음악 재생 또는 네트워크에서 데이터 다운로드) -시스템은 모든 전경 및 가시적 프로세스와 함께 실행할 만큼 메모리가 충분하지 않을 경우에만 +android.content.Context#startService startService()} 메서드로 시작되었지만 두 개의 상위 계층 분류에 +들어가지 않는 서비스를 실행하는 프로세스입니다. 서비스 프로세스는 사용자가 보는 것과 직접 연결되어 있지는 않지만, +일반적으로 사용자가 신경 쓰는 작업을 하므로(배경에서 음악 재생 또는 네트워크에서 데이터 다운로드) +시스템은 모든 전경 및 가시적 프로세스와 함께 실행할 만큼 메모리가 충분하지 않을 경우에만 프로세스를 중단합니다.

        4. 배경 프로세스 -

          현재 사용자에게 보이지 않는 액티비티를 보유한 프로세스입니다(액티비티의 -{@link android.app.Activity#onStop onStop()} 메서드가 호출되었습니다). 이와 같은 프로세스는 -사용자 환경에 직접적 영향을 미치지 않고, 시스템은 언제든 이 프로세스를 중단시켜 +

          현재 사용자에게 보이지 않는 액티비티를 보유한 프로세스입니다(액티비티의 +{@link android.app.Activity#onStop onStop()} 메서드가 호출되었습니다). 이와 같은 프로세스는 +사용자 환경에 직접적 영향을 미치지 않고, 시스템은 언제든 이 프로세스를 중단시켜 전경, -가시적 또는 서비스 프로세스를 위한 메모리를 확보할 수 있습니다. 보통 한번에 실행 중인 배경 프로세스가 많은 편이므로 이들은 -LRU(최저 사용 빈도) 목록에 보관하여 사용자가 가장 최근에 본 액티비티가 있는 -프로세스가 가장 마지막에 중단되도록 합니다. 액티비티가 수명 주기 메서드를 올바르게 구현하고 -자신의 현재 상태를 저장할 경우, 사용자가 액티비티로 다시 이동할 때 액티비티가 모든 가시적 상태를 -복원하므로 프로세스를 중단시키더라도 사용자 환경에는 눈에 띄게 영향을 미치지 +가시적 또는 서비스 프로세스를 위한 메모리를 확보할 수 있습니다. 보통 한번에 실행 중인 배경 프로세스가 많은 편이므로 이들은 +LRU(최저 사용 빈도) 목록에 보관하여 사용자가 가장 최근에 본 액티비티가 있는 +프로세스가 가장 마지막에 중단되도록 합니다. 액티비티가 수명 주기 메서드를 올바르게 구현하고 +자신의 현재 상태를 저장할 경우, 사용자가 액티비티로 다시 이동할 때 액티비티가 모든 가시적 상태를 +복원하므로 프로세스를 중단시키더라도 사용자 환경에는 눈에 띄게 영향을 미치지 않습니다. 상태 저장과 복원에 관한 정보는 액티비티 문서를 참조하십시오.

        5. 빈 프로세스 -

          활성 애플리케이션 구성 요소를 보유하지 않은 프로세스입니다. 이런 프로세스를 -유지하는 유일한 이유는 다음에 내부 구성 요소를 실행할 때 시작 시간을 절약하기 위한 캐싱 +

          활성 애플리케이션 구성 요소를 보유하지 않은 프로세스입니다. 이런 프로세스를 +유지하는 유일한 이유는 다음에 내부 구성 요소를 실행할 때 시작 시간을 절약하기 위한 캐싱 때문입니다. 시스템은 프로세스 캐시와 기본 커널 캐시 사이에서 전반적인 시스템 리소스의 균형을 맞추기 위해 이 프로세스를 중단시키는 경우가 많습니다.

        -

        Android는 프로세스에서 현재 활성 상태인 구성 요소의 중요도에 따라 -프로세스에 가장 높은 수준을 부여합니다. 예를 들어, 프로세스가 서비스와 가시적 액티비티를 호스팅할 경우, +

        Android는 프로세스에서 현재 활성 상태인 구성 요소의 중요도에 따라 +프로세스에 가장 높은 수준을 부여합니다. 예를 들어, 프로세스가 서비스와 가시적 액티비티를 호스팅할 경우, 해당 프로세스는 서비스 프로세스가 아니라 가시적 프로세스 등급이 부여됩니다.

        또한, 프로세스의 등급은 다른 프로세스가 이에 의존할 경우 상승할 수 있습니다. -즉, 다른 프로세스에 서비스를 제공하는 프로세스가 서비스 제공 대상 프로세스보다 -등급이 낮은 경우는 있을 수 없습니다. 예를 들어 프로세스 A의 콘텐츠 제공자가 프로세스 B의 클라이언트에 서비스를 제공하거나 -프로세스 A의 서비스가 프로세스 B의 구성 요소에 바인딩되어 있을 경우 프로세스 A는 항상 중요도가 +즉, 다른 프로세스에 서비스를 제공하는 프로세스가 서비스 제공 대상 프로세스보다 +등급이 낮은 경우는 있을 수 없습니다. 예를 들어 프로세스 A의 콘텐츠 제공자가 프로세스 B의 클라이언트에 서비스를 제공하거나 +프로세스 A의 서비스가 프로세스 B의 구성 요소에 바인딩되어 있을 경우 프로세스 A는 항상 중요도가 프로세스 B와 같거나 그보다 높습니다.

        -

        서비스를 실행하는 프로세스가 배경 액티비티가 포함된 프로세스보다 높으므로, +

        서비스를 실행하는 프로세스가 배경 액티비티가 포함된 프로세스보다 높으므로, 장기 작업을 시작하는 액티비티는 작업자 스레드만 생성하기보다는 해당 작업에 대한 서비스를 시작하는 것이 좋습니다. -이는 특히 작업이 해당 액티비티보다 오래 지속될 경우 더욱 중요합니다. -예를 들어, 웹사이트에 사진을 업로드하는 액티비티가 업로드를 수행하는 서비스를 시작해야 -사용자가 액티비티를 떠나더라도 배경에서 업로드를 지속할 수 있습니다. -서비스를 사용하면 액티비티에 어떤 일이 발생하든 해당 작업에 반드시 -"서비스 프로세스" 우선 순위 이상이 부여됩니다. 이것이 브로드캐스트 수신기가 시간이 오래 걸리는 작업을 +이는 특히 작업이 해당 액티비티보다 오래 지속될 경우 더욱 중요합니다. +예를 들어, 웹사이트에 사진을 업로드하는 액티비티가 업로드를 수행하는 서비스를 시작해야 +사용자가 액티비티를 떠나더라도 배경에서 업로드를 지속할 수 있습니다. +서비스를 사용하면 액티비티에 어떤 일이 발생하든 해당 작업에 반드시 +"서비스 프로세스" 우선 순위 이상이 부여됩니다. 이것이 브로드캐스트 수신기가 시간이 오래 걸리는 작업을 스레드에 넣기보다는 서비스를 사용해야 하는 것과 같은 이유입니다.

        @@ -188,36 +188,36 @@ LRU(최저 사용 빈도) 목록에 보관하여 사용자가 가장 최근에

        스레드

        -

        애플리케이션이 시작되면 시스템이 애플리케이션에 대한 실행의 스레드를 생성하며, 이를 -"기본"이라고 합니다. 이 스레드는 드로어블 이벤트를 포함하여 적절한 사용자 인터페이스 위젯에 +

        애플리케이션이 시작되면 시스템이 애플리케이션에 대한 실행의 스레드를 생성하며, 이를 +"기본"이라고 합니다. 이 스레드는 드로어블 이벤트를 포함하여 적절한 사용자 인터페이스 위젯에 이벤트를 발송하는 역할을 맡기 때문에 중요합니다. 이것은 Android UI 도구 키트의 구성 요소({@link android.widget}과 {@link android.view} 패키지의 구성 요소)와 개발자의 애플리케이션이 -상호 작용하는 스레드이기도 합니다. 따라서 기본 스레드는 +상호 작용하는 스레드이기도 합니다. 따라서 기본 스레드는 UI 스레드라고 불릴 때도 있습니다.

        -

        시스템은 구성 요소의 각 인스턴스에 대해 별도의 스레드를 생성하지 않습니다. 같은 +

        시스템은 구성 요소의 각 인스턴스에 대해 별도의 스레드를 생성하지 않습니다. 같은 프로세스에서 실행되는 모든 구성 요소는 UI 스레드에서 시작되고, 각 구성 요소를 호출하는 시스템이 -해당 스레드에서 발송됩니다. 따라서 -시스템 콜백에 응답하는 메서드(사용자 작업을 보고하는 {@link android.view.View#onKeyDown onKeyDown()} 또는 +해당 스레드에서 발송됩니다. 따라서 +시스템 콜백에 응답하는 메서드(사용자 작업을 보고하는 {@link android.view.View#onKeyDown onKeyDown()} 또는 수명 주기 콜백 메서드)는 항상 프로세스의 UI 스레드에서 실행됩니다.

        예를 들어, 사용자가 화면의 버튼을 터치하면, 앱 UI 스레드가 위젯에 터치 이벤트를 발송하고, -위젯은 눌린 상태를 설정하고 이벤트 대기열에 -무효화 요청을 게시합니다. UI 스레드가 이 요청을 대기열에서 해제하고 위젯에 스스로를 다시 +위젯은 눌린 상태를 설정하고 이벤트 대기열에 +무효화 요청을 게시합니다. UI 스레드가 이 요청을 대기열에서 해제하고 위젯에 스스로를 다시 그려야 한다고 알립니다.

        앱이 사용자 상호작용에 응답하여 집약적인 작업을 수행할 때는 이 단일 스레드 모델은 애플리케이션을 제대로 구현하지 않으면 낮은 성능을 보일 수 있습니다. 특히, -모든 것이 UI 스레드에서 발생하고 네트워크 액세스나 데이터 베이스 쿼리 등의 긴 작업을 수행하면 -UI가 통째로 차단됩니다. 스레드가 차단되면 드로잉 이벤트를 포함하여 -모든 이벤트가 발송되지 않습니다. 사용자가 보기에는 애플리케이션이 +모든 것이 UI 스레드에서 발생하고 네트워크 액세스나 데이터 베이스 쿼리 등의 긴 작업을 수행하면 +UI가 통째로 차단됩니다. 스레드가 차단되면 드로잉 이벤트를 포함하여 +모든 이벤트가 발송되지 않습니다. 사용자가 보기에는 애플리케이션이 중단된 것처럼 보입니다. 더 나쁜 경우, UI 스레드가 몇 초 이상 차단되어 있으면 -(현재 약 5초) 사용자에게 악명 높은 "애플리케이션이 응답하지 -않습니다"(ANR) 대화가 표시됩니다. 그러면 사용자가 여러분의 애플리케이션을 종료 할 수도 있고, 불만족한 경우 앱을 +(현재 약 5초) 사용자에게 악명 높은 "애플리케이션이 응답하지 +않습니다"(ANR) 대화가 표시됩니다. 그러면 사용자가 여러분의 애플리케이션을 종료 할 수도 있고, 불만족한 경우 앱을 제거할 수도 있습니다.

        -

        또한, Andoid UI 도구 키트는 스레드로부터 안전하지 않습니다. 따라서 UI를 -작업자 스레드에서 조작해서는 안 됩니다. 사용자 인터페이스 조작 작업은 모두 UI +

        또한, Andoid UI 도구 키트는 스레드로부터 안전하지 않습니다. 따라서 UI를 +작업자 스레드에서 조작해서는 안 됩니다. 사용자 인터페이스 조작 작업은 모두 UI 스레드에서 해야만 합니다. 결론적으로, Android의 단일 스레드 모델에는 두 가지 단순한 규칙이 있습니다.

          @@ -227,12 +227,12 @@ UI가 통째로 차단됩니다. 스레드가 차단되면 드로잉 이벤트

          작업자 스레드

          -

          위에 설명한 단일 스레드 모델로 인해, 애플리케이션 UI의 반응성을 위해서는 -UI 스레드를 차단하지 않는 것이 매우 중요합니다. 수행해야 할 작업이 있는데 -이들이 즉각적인 조치를 요하지 않는 경우, 이런 작업은 반드시 별도의 스레드에서 수행해야 합니다("배경" 또는 +

          위에 설명한 단일 스레드 모델로 인해, 애플리케이션 UI의 반응성을 위해서는 +UI 스레드를 차단하지 않는 것이 매우 중요합니다. 수행해야 할 작업이 있는데 +이들이 즉각적인 조치를 요하지 않는 경우, 이런 작업은 반드시 별도의 스레드에서 수행해야 합니다("배경" 또는 "작업자" 스레드).

          -

          예를 들어, 아래는 별도의 스레드에서 이미지를 다운로드하고 이를 +

          예를 들어, 아래는 별도의 스레드에서 이미지를 다운로드하고 이를 {@link android.widget.ImageView}에 표시하는 클릭 수신기에 대한 몇 가지 코드입니다.

          @@ -246,10 +246,10 @@ public void onClick(View v) {
           }
           
          -

          처음에는 네트워크 작업을 처리하기 위한 새 스레드를 생성하므로 -아무 문제 없이 작동하는 것처럼 보입니다. 하지만, 이것은 단일 스레드된 모델의 두 번째 규칙 즉, 'UI 스레드 외부에서 +

          처음에는 네트워크 작업을 처리하기 위한 새 스레드를 생성하므로 +아무 문제 없이 작동하는 것처럼 보입니다. 하지만, 이것은 단일 스레드된 모델의 두 번째 규칙 즉, 'UI 스레드 외부에서 Android UI 도구 키트에 액세스하지 마세요.'를 위반합니다. 이 샘플은 UI 스레드 대신 작업자 스레드에서 {@link -android.widget.ImageView}를 수정합니다. 이렇게 되면 +android.widget.ImageView}를 수정합니다. 이렇게 되면 정의되지 않고 예기치 못한 동작이 발생하는 결과를 초래할 수 있고, 이는 추적하기 어려워 시간도 오래 걸립니다.

          이 문제를 해결하기 위해 Android는 다른 스레드에서 UI 스레드에 액세스하는 여러 가지 방식을 @@ -281,28 +281,28 @@ public void onClick(View v) { }

        -

        이 구현은 이제 스레드로부터 안전합니다. 네트워크 작업은 별도의 스레드에서 수행된 반면 +

        이 구현은 이제 스레드로부터 안전합니다. 네트워크 작업은 별도의 스레드에서 수행된 반면 {@link android.widget.ImageView}는 UI 스레드에서 조작되었기 때문입니다.

        -

        그러나, 작업이 복잡해질수록 이런 종류의 코드가 더 복잡해질 수 있고 유지 관리하기 -까다로워질 수 있습니다. 더 복잡한 상호 작용을 작업자 스레드로 처리하려면, 작업자 스레드에서 -{@link android.os.Handler}를 사용하여 UI 스레드에서 전달 받은 메시지를 처리하는 방안을 -고려해보십시오. 하지만 최선의 해결책은 {@link android.os.AsyncTask} 클래스를 확장하는 방법일 것입니다. +

        그러나, 작업이 복잡해질수록 이런 종류의 코드가 더 복잡해질 수 있고 유지 관리하기 +까다로워질 수 있습니다. 더 복잡한 상호 작용을 작업자 스레드로 처리하려면, 작업자 스레드에서 +{@link android.os.Handler}를 사용하여 UI 스레드에서 전달 받은 메시지를 처리하는 방안을 +고려해보십시오. 하지만 최선의 해결책은 {@link android.os.AsyncTask} 클래스를 확장하는 방법일 것입니다. 이것은 UI와 상호 작용해야 하는 작업자 스레드 작업의 실행을 단순화합니다.

        AsyncTask 사용

        -

        {@link android.os.AsyncTask}를 사용하면 사용자 인터페이스에서 비동기식 작업을 수행할 수 -있게 해줍니다. 이것은 작업자 스레드에서 차단 작업을 수행하고 그런 다음 그 결과를 UI 스레드에 +

        {@link android.os.AsyncTask}를 사용하면 사용자 인터페이스에서 비동기식 작업을 수행할 수 +있게 해줍니다. 이것은 작업자 스레드에서 차단 작업을 수행하고 그런 다음 그 결과를 UI 스레드에 게시하며, 개발자가 직접 스레드 및/또는 처리기를 처리할 필요가 없습니다.

        이를 사용하려면 우선 {@link android.os.AsyncTask}를 하위 클래스로 한 다음 {@link -android.os.AsyncTask#doInBackground doInBackground()} 콜백 메서드를 구현해야 합니다. 이것은 여러 가지 +android.os.AsyncTask#doInBackground doInBackground()} 콜백 메서드를 구현해야 합니다. 이것은 여러 가지 배경 스레드에서 실행됩니다. UI를 업데이트하려면 {@link android.os.AsyncTask#onPostExecute onPostExecute()}를 구현해야 합니다. 이는 {@link -android.os.AsyncTask#doInBackground doInBackground()}로부터의 결과를 전달하며 UI 스레드에서 실행되므로, -안전하게 UI를 업데이트할 수 있습니다. 그런 다음 UI 스레드에서 {@link android.os.AsyncTask#execute execute()}를 +android.os.AsyncTask#doInBackground doInBackground()}로부터의 결과를 전달하며 UI 스레드에서 실행되므로, +안전하게 UI를 업데이트할 수 있습니다. 그런 다음 UI 스레드에서 {@link android.os.AsyncTask#execute execute()}를 호출하여 해당 작업을 실행하면 됩니다.

        예를 들어, 이런 방식으로 {@link android.os.AsyncTask}를 사용하여 @@ -319,7 +319,7 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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) { @@ -328,21 +328,21 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { }

        -

        이제 UI는 안전하고 코드는 더욱 단순해졌습니다. 작업을 작업자 스레드에서 수행되어야 하는 +

        이제 UI는 안전하고 코드는 더욱 단순해졌습니다. 작업을 작업자 스레드에서 수행되어야 하는 부분과 UI 스레드에서 수행되어야 하는 부분으로 구분하기 때문입니다.

        -

        이 클래스를 사용하는 법을 완전히 숙지하려면 {@link android.os.AsyncTask} 참조를 +

        이 클래스를 사용하는 법을 완전히 숙지하려면 {@link android.os.AsyncTask} 참조를 읽어보시는 것이 좋습니다. 개괄적인 작동 방식은 아래에 간략히 소개해 놓았습니다.

          -
        • 매개 변수의 유형, 진행률 값과 작업의 최종 값을 제네릭을 사용하여 +
        • 매개 변수의 유형, 진행률 값과 작업의 최종 값을 제네릭을 사용하여 지정할 수 있습니다.
        • 메서드 {@link android.os.AsyncTask#doInBackground doInBackground()}는 작업자 스레드에서 자동으로 실행됩니다.
        • {@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link android.os.AsyncTask#onPostExecute onPostExecute()} 및 {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()}는 모두 UI 스레드에서 호출됩니다.
        • -
        • {@link android.os.AsyncTask#doInBackground doInBackground()}가 반환한 값이 +
        • {@link android.os.AsyncTask#doInBackground doInBackground()}가 반환한 값이 {@link android.os.AsyncTask#onPostExecute onPostExecute()}로 전송됩니다.
        • 언제든 {@link android.os.AsyncTask#publishProgress publishProgress()}를 {@link android.os.AsyncTask#doInBackground doInBackground()}에서 호출하여 UI 스레드에서 {@link @@ -350,27 +350,27 @@ android.os.AsyncTask#onProgressUpdate onProgressUpdate()}를 실행하도록 할
        • 모든 스레드에서 언제든 작업을 취소할 수 있습니다.
        -

        주의: 작업자 스레드를 사용할 때 마주칠 수 있는 또 한 가지 문제는 +

        주의: 작업자 스레드를 사용할 때 마주칠 수 있는 또 한 가지 문제는 런타임 구성 변경으로 인해 액티비티가 예기치 못하게 다시 시작되는 것입니다 -(예를 들어 사용자가 화면 방향을 바꾸는 경우). 이 경우 작업자 스레드를 소멸시킬 수 있습니다. +(예를 들어 사용자가 화면 방향을 바꾸는 경우). 이 경우 작업자 스레드를 소멸시킬 수 있습니다. 스레드가 재시작될 때 작업을 지속하는 방법과 액티비티가 제거되었을 때 작업을 적절히 취소하는 방법은 Shelves 샘플 애플리케이션의 소스 코드를 참조하십시오.

        스레드로부터 안전한 메서드

        -

        어떤 경우에는 구현하는 메서드가 하나 이상의 스레드에서 호출되는 일도 있습니다. 따라서 +

        어떤 경우에는 구현하는 메서드가 하나 이상의 스레드에서 호출되는 일도 있습니다. 따라서 이를 스레드로부터 안전하게 작성해야만 합니다.

        -

        이것은 주로 원격으로 호출할 수 있는 메서드에 대해 참입니다. 예를 들어 바인딩된 서비스 내의 메서드 등이 해당됩니다. -{@link android.os.IBinder}에서 구현된 메서드가 -{@link android.os.IBinder IBinder}가 실행되는 프로세스에서 호출될 경우, 해당 메서드는 발신자의 스레드에서 실행됩니다. -그러나 호출이 다른 프로세스에서 발생하면, 해당 메서드는 시스템이 +

        이것은 주로 원격으로 호출할 수 있는 메서드에 대해 참입니다. 예를 들어 바인딩된 서비스 내의 메서드 등이 해당됩니다. +{@link android.os.IBinder}에서 구현된 메서드가 +{@link android.os.IBinder IBinder}가 실행되는 프로세스에서 호출될 경우, 해당 메서드는 발신자의 스레드에서 실행됩니다. +그러나 호출이 다른 프로세스에서 발생하면, 해당 메서드는 시스템이 {@link android.os.IBinder -IBinder}와 같은 프로세스에 유지하는 스레드 풀에서 선택된 스레드에서 실행됩니다(프로세스의 UI 스레드에서 실행되지 않습니다). 예를 들어, 어느 서비스의 -{@link android.app.Service#onBind onBind()} 메서드는 해당 서비스 +IBinder}와 같은 프로세스에 유지하는 스레드 풀에서 선택된 스레드에서 실행됩니다(프로세스의 UI 스레드에서 실행되지 않습니다). 예를 들어, 어느 서비스의 +{@link android.app.Service#onBind onBind()} 메서드는 해당 서비스 프로세스의 UI 스레드에서 호출되고, {@link android.app.Service#onBind -onBind()}가 반환하는 객체에서 구현된 메서드는(예: RPC 메서드를 구현하는 하위 클래스) 해당 풀 안의 여러 스레드에서 +onBind()}가 반환하는 객체에서 구현된 메서드는(예: RPC 메서드를 구현하는 하위 클래스) 해당 풀 안의 여러 스레드에서 호출되게 됩니다. 서비스에 클라이언트가 하나 이상 있을 수 있으므로, 하나 이상의 풀이 동시에 같은 {@link android.os.IBinder IBinder} 메서드에 참여할 수 있습니다. 그러므로 {@link android.os.IBinder IBinder} 메서드는 스레드로부터 안전하게 구현되어야 합니다.

        @@ -389,13 +389,13 @@ getType()} 메서드—)가 프로세스의 UI 스레드가 아니라

        프로세스 간 통신

        -

        Android는 원격 프로시저 호출(RPC)을 사용한 프로세스 간 통신(IPC) 메커니즘을 제공합니다. -여기서 메서드는 액티비티나 다른 애플리케이션 구성 요소에 호출되지만 -원격으로 (또 다른 프로세스에서) 실행되고, 결과는 모두 발신자에게 되돌려 -보냅니다. 메서드 호출과 메서드의 데이터는 운영 체제가 이해할 수 있는 수준으로 분해되고, -로컬 프로세스와 주소 공간에서 원격 프로세스와 주소 공간으로 전송된 다음 -다시 결합되어 여기서 호출에 다시 응답합니다. 그런 다음 반환 값이 -반대 방향으로 전송됩니다. Android가 이와 같은 IPC 트랜잭션을 수행하는 데 필요한 +

        Android는 원격 프로시저 호출(RPC)을 사용한 프로세스 간 통신(IPC) 메커니즘을 제공합니다. +여기서 메서드는 액티비티나 다른 애플리케이션 구성 요소에 호출되지만 +원격으로 (또 다른 프로세스에서) 실행되고, 결과는 모두 발신자에게 되돌려 +보냅니다. 메서드 호출과 메서드의 데이터는 운영 체제가 이해할 수 있는 수준으로 분해되고, +로컬 프로세스와 주소 공간에서 원격 프로세스와 주소 공간으로 전송된 다음 +다시 결합되어 여기서 호출에 다시 응답합니다. 그런 다음 반환 값이 +반대 방향으로 전송됩니다. Android가 이와 같은 IPC 트랜잭션을 수행하는 데 필요한 모든 코드를 제공하므로, 개발자는 그저 RPC 프로그래밍 인터페이스를 정의하고 구현하는 데에만 집중하면 됩니다.

        IPC를 수행하려면 애플리케이션이 반드시 서비스에 바인딩되어야만 하며, 이때 {@link diff --git a/docs/html-intl/intl/ko/guide/components/recents.jd b/docs/html-intl/intl/ko/guide/components/recents.jd index cba3c45da3daeab4ce42883e75f559a2a3642254..28b3c681f5a2b5fb46e93f2c43e3cb6c2d0d7af8 100644 --- a/docs/html-intl/intl/ko/guide/components/recents.jd +++ b/docs/html-intl/intl/ko/guide/components/recents.jd @@ -38,50 +38,50 @@ page.tags="recents","overview"

        개요 화면(다른 말로 최근 사용 화면, 최근 작업 목록 또는 최근 앱이라고도 함)은 시스템 수준 UI로, 최근에 액세스한 -액티비티작업을 목록으로 나열한 것입니다. 사용자는 -목록을 가로질러 이동하며 작업을 선택해서 재개할 수도 있고, 아니면 -목록에서 한 작업을 스와이프하여 밀어내어 목록에서 제거할 수도 있습니다. Android 5.0 릴리스(API 레벨 21)의 경우, 같은 액티비티의 여러 인스턴스에 -각기 다른 문서가 담겨 있는 경우 이들이 개요 화면에 작업으로 나타날 수 있습니다. 예를 들어 -Google Drive에 여러 개의 Google 문서 각각에 대한 작업이 있을 수 있습니다. 각 문서는 개요 화면에 하나의 +액티비티 및 작업을 목록으로 나열한 것입니다. 사용자는 +목록을 가로질러 이동하며 작업을 선택해서 재개할 수도 있고, 아니면 +목록에서 한 작업을 스와이프하여 밀어내어 목록에서 제거할 수도 있습니다. Android 5.0 릴리스(API 레벨 21)의 경우, 같은 액티비티의 여러 인스턴스에 +각기 다른 문서가 담겨 있는 경우 이들이 개요 화면에 작업으로 나타날 수 있습니다. 예를 들어 +Google Drive에 여러 개의 Google 문서 각각에 대한 작업이 있을 수 있습니다. 각 문서는 개요 화면에 하나의 작업으로 나타납니다.

        -

        그림 1. 세 개의 Google Drive 문서가 각기 별도의 +

        그림 1. 세 개의 Google Drive 문서가 각기 별도의 작업을 나타내는 모습을 표시한 개요 화면입니다.

        -

        보통은 개요 화면에 작업과 액티비티가 어떻게 표현될지는 시스템이 -정의하도록 두어야 합니다. 이 행동을 개발자가 수정할 필요도 없습니다. -하지만, 개요 화면에 액티비티가 언제, 어떻게 나타날지는 앱이 결정할 수 있습니다. -{@link android.app.ActivityManager.AppTask} 클래스를 사용하면 작업을 관리할 수 있게 해주고, -{@link android.content.Intent} 클래스의 액티비티 플래그를 사용하면 개요 화면에서 액티비티가 추가되거나 제거되는 시점을 +

        보통은 개요 화면에 작업과 액티비티가 어떻게 표현될지는 시스템이 +정의하도록 두어야 합니다. 이 행동을 개발자가 수정할 필요도 없습니다. +하지만, 개요 화면에 액티비티가 언제, 어떻게 나타날지는 앱이 결정할 수 있습니다. +{@link android.app.ActivityManager.AppTask} 클래스를 사용하면 작업을 관리할 수 있게 해주고, +{@link android.content.Intent} 클래스의 액티비티 플래그를 사용하면 개요 화면에서 액티비티가 추가되거나 제거되는 시점을 지정할 수 있습니다. 또한, <activity> 특성을 사용하면 매니페스트에서의 동작을 설정할 수 있습니다.

        개요 화면에 작업 추가

        -

        {@link android.content.Intent} 클래스의 플래그를 사용하여 작업을 추가하면 -개요 화면에서 문서가 열리거나 다시 열리는 시점과 방법을 보다 철저히 통제할 수 있습니다. +

        {@link android.content.Intent} 클래스의 플래그를 사용하여 작업을 추가하면 +개요 화면에서 문서가 열리거나 다시 열리는 시점과 방법을 보다 철저히 통제할 수 있습니다. <activity> - 특성을 사용하는 경우, 문서를 항상 새 작업에서 여는 방법과 기존 작업을 해당 문서에 다시 사용하는 방법 중에서 + 특성을 사용하는 경우, 문서를 항상 새 작업에서 여는 방법과 기존 작업을 해당 문서에 다시 사용하는 방법 중에서 선택할 수 있습니다.

        작업 추가에 인텐트 플래그 사용

        -

        액티비티를 위해 새 문서를 생성하는 경우, -{@link android.app.ActivityManager.AppTask} 클래스의 +

        액티비티를 위해 새 문서를 생성하는 경우, +{@link android.app.ActivityManager.AppTask} 클래스의 {@link android.app.ActivityManager.AppTask#startActivity(android.content.Context, android.content.Intent, android.os.Bundle) startActivity()} - 메서드를 호출하고, 이것을 액티비티를 시작하는 인텐트에 전달하면 됩니다. 논리적인 중단을 삽입하여 시스템이 개요 화면에서 액티비티를 -새 작업으로 처리하도록 하려면, {@link android.content.Intent}의 -{@link android.content.Intent#addFlags(int) addFlags()} 메서드에 있는 {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} + 메서드를 호출하고, 이것을 액티비티를 시작하는 인텐트에 전달하면 됩니다. 논리적인 중단을 삽입하여 시스템이 개요 화면에서 액티비티를 +새 작업으로 처리하도록 하려면, {@link android.content.Intent}의 +{@link android.content.Intent#addFlags(int) addFlags()} 메서드에 있는 {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} 플래그를 전달하여 액티비티를 시작하도록 합니다.

        참고: {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} -플래그가 {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET} 플래그를 +플래그가 {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET} 플래그를 대체합니다. 이것은 Android 5.0(API 레벨 21)부터 사용이 중단되었습니다.

        -

        새 문서를 생성하면서 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 플래그를 설정하는 경우, -시스템은 항상 대상 액티비티를 루트로 하여 새 작업을 만듭니다. -이렇게 설정하면 같은 문서를 하나 이상의 작업에서 열 수 있습니다. 다음 코드는 기본 액티비티가 이 작업을 수행하는 방법을 +

        새 문서를 생성하면서 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 플래그를 설정하는 경우, +시스템은 항상 대상 액티비티를 루트로 하여 새 작업을 만듭니다. +이렇게 설정하면 같은 문서를 하나 이상의 작업에서 열 수 있습니다. 다음 코드는 기본 액티비티가 이 작업을 수행하는 방법을 보여줍니다.

        @@ -111,15 +111,15 @@ public void createNewDocument(View view) {

      참고: {@code FLAG_ACTIVITY_NEW_DOCUMENT} - 플래그로 시작된 액티비티의 경우, 반드시 매니페스트에 {@code android:launchMode="standard"} 특성 값(기본)이 설정되어 + 플래그로 시작된 액티비티의 경우, 반드시 매니페스트에 {@code android:launchMode="standard"} 특성 값(기본)이 설정되어 있어야 합니다.

      -

      기본 액티비티가 새 액티비티를 시작하면 시스템은 기존의 작업을 검색하여 그 중 -해당 액티비티에 대한 인텐트 구성 요소 이름과 인텐트 데이터와 일치하는 인텐트를 가진 작업을 찾습니다. 그러한 작업을 +

      기본 액티비티가 새 액티비티를 시작하면 시스템은 기존의 작업을 검색하여 그 중 +해당 액티비티에 대한 인텐트 구성 요소 이름과 인텐트 데이터와 일치하는 인텐트를 가진 작업을 찾습니다. 그러한 작업을 찾을 수 없거나 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} - 플래그에 들어 있는 인텐트를 찾을 수 없는 경우, 해당 액티비티를 루트로 하여 새 작업이 생성됩니다. 원하는 항목을 찾으면, 시스템은 해당 작업을 전경으로 가지고 와 -새 인텐트를 {@link android.app.Activity#onNewIntent onNewIntent()}에 전달합니다. -새 액티비티가 인텐트를 받아 개요 화면에서 새 문서를 생성하며, 이는 다음 예시에 나타낸 + 플래그에 들어 있는 인텐트를 찾을 수 없는 경우, 해당 액티비티를 루트로 하여 새 작업이 생성됩니다. 원하는 항목을 찾으면, 시스템은 해당 작업을 전경으로 가지고 와 +새 인텐트를 {@link android.app.Activity#onNewIntent onNewIntent()}에 전달합니다. +새 액티비티가 인텐트를 받아 개요 화면에서 새 문서를 생성하며, 이는 다음 예시에 나타낸 것과 같습니다.

      @@ -149,64 +149,64 @@ protected void onNewIntent(Intent intent) {

      작업 추가에 액티비티 특성 사용

      -

      액티비티는 자신의 매니페스트에 새 작업을 시작할 때는 항상 +

      액티비티는 자신의 매니페스트에 새 작업을 시작할 때는 항상 <activity> 특성, -{@code android:documentLaunchMode}를 사용한다고 나타낼 수도 있습니다. 이 특성에는 네 가지 값이 있어 사용자가 애플리케이션으로 문서를 열면 +{@code android:documentLaunchMode}를 사용한다고 나타낼 수도 있습니다. 이 특성에는 네 가지 값이 있어 사용자가 애플리케이션으로 문서를 열면 다음과 같은 효과를 발생시킵니다.

      "{@code intoExisting}"
      -
      액티비티가 문서에 대해 기존의 작업을 재사용합니다. 이것은 -{@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} 플래그를 설정할 때 -{@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 플래그 없이 설정하는 것과 같습니다. +
      액티비티가 문서에 대해 기존의 작업을 재사용합니다. 이것은 +{@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} 플래그를 설정할 때 +{@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 플래그 없이 설정하는 것과 같습니다. 이는 위의 작업 추가에 인텐트 플래그 사용에서 설명한 것과 같습니다.
      "{@code always}"
      -
      액티비티가 문서에 대해 새 작업을 생성하며, 이는 문서가 이미 열려 있는 경우라도 마찬가지입니다. 이 값을 +
      액티비티가 문서에 대해 새 작업을 생성하며, 이는 문서가 이미 열려 있는 경우라도 마찬가지입니다. 이 값을 사용하는 것은 {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} 및 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 플래그를 둘 다 설정하는 것과 같습니다.
      "{@code none”}"
      -
      액티비티가 문서에 대해 새 작업을 생성하지 않습니다. 개요 화면은 액티비티를 기본 상태에서와 -같이 다룹니다. 즉 앱에 대한 하나의 작업을 표시하며, 이때 사용자가 +
      액티비티가 문서에 대해 새 작업을 생성하지 않습니다. 개요 화면은 액티비티를 기본 상태에서와 +같이 다룹니다. 즉 앱에 대한 하나의 작업을 표시하며, 이때 사용자가 마지막으로 호출한 작업이 무엇이든 관계 없이 그 작업에서부터 재개합니다.
      "{@code never}"
      -
      액티비티가 문서에 대해 새 작업을 생성하지 않습니다. 이 값을 설정하면 +
      액티비티가 문서에 대해 새 작업을 생성하지 않습니다. 이 값을 설정하면 {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} - 및 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 플래그의 행동을 -재정의합니다(이들 중 하나가 인텐트에서 설정되어 있는 경우). 개요 화면은 앱에 대한 하나의 작업을 표시하고, + 및 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 플래그의 행동을 +재정의합니다(이들 중 하나가 인텐트에서 설정되어 있는 경우). 개요 화면은 앱에 대한 하나의 작업을 표시하고, 이것이 사용자가 마지막으로 호출한 액티비티가 무엇이든 그것부터 재개합니다.
      -

      참고: {@code none} 및 {@code never}를 제외한 다른 값의 경우, -액티비티를 {@code launchMode="standard"}로 정의해야 합니다. 이 특성을 지정하지 않으면 +

      참고: {@code none} 및 {@code never}를 제외한 다른 값의 경우, +액티비티를 {@code launchMode="standard"}로 정의해야 합니다. 이 특성을 지정하지 않으면 {@code documentLaunchMode="none"}이 사용됩니다.

      작업 제거

      -

      기본적으로 문서 작업은 해당되는 액티비티가 완료되면 자동으로 개요 화면에서 -제거됩니다. 이 행동을 재정의하려면 {@link android.app.ActivityManager.AppTask} 클래스를 사용합니다. 이때 +

      기본적으로 문서 작업은 해당되는 액티비티가 완료되면 자동으로 개요 화면에서 +제거됩니다. 이 행동을 재정의하려면 {@link android.app.ActivityManager.AppTask} 클래스를 사용합니다. 이때 {@link android.content.Intent} 플래그 또는 <activity> 특성을 함께 사용하십시오.

      -

      개요 화면에서 작업을 완전히 제외하려면 언제든 +

      개요 화면에서 작업을 완전히 제외하려면 언제든 <activity> 특성, {@code android:excludeFromRecents}를 {@code true}로 설정합니다.

      -

      개요 화면에서 앱이 포함할 수 있는 작업의 최대 개수를 설정하려면 +

      개요 화면에서 앱이 포함할 수 있는 작업의 최대 개수를 설정하려면 <activity> 특성 {@code android:maxRecents} -를 정수 값으로 설정합니다. 기본은 16개입니다. 작업의 최대 대수에 도달하면 가장 예전에 사용된 작업이 개요 화면에서 -제거됩니다. {@code android:maxRecents} 최대값은 +를 정수 값으로 설정합니다. 기본은 16개입니다. 작업의 최대 대수에 도달하면 가장 예전에 사용된 작업이 개요 화면에서 +제거됩니다. {@code android:maxRecents} 최대값은 50입니다(메모리 용량이 적은 기기에서는 25). 1 미만의 값은 유효하지 않습니다.

      작업 제거에 AppTask 클래스 사용

      -

      개요 화면에서 새 작업을 생성하는 액티비티에서는 작업을 언제 제거할 것인지와 -그와 관련된 모든 액티비티를 언제 완료할 것인지 지정할 수 있습니다. +

      개요 화면에서 새 작업을 생성하는 액티비티에서는 작업을 언제 제거할 것인지와 +그와 관련된 모든 액티비티를 언제 완료할 것인지 지정할 수 있습니다. {@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()} 메서드를 호출하면 됩니다.

      @@ -218,15 +218,15 @@ public void onRemoveFromRecents(View view) { }

      -

      참고: -{@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()} 메서드를 -사용하면 {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} 태그 사용을 재정의합니다. +

      참고: +{@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()} 메서드를 +사용하면 {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} 태그 사용을 재정의합니다. 이 내용은 아래에서 설명합니다.

      완료된 작업 보존

      -

      작업을 개요 화면에 보존하려면(액티비티가 완료되었더라도), -액티비티를 시작하는 인텐트의 {@link android.content.Intent#addFlags(int) addFlags()} 메서드에 있는 +

      작업을 개요 화면에 보존하려면(액티비티가 완료되었더라도), +액티비티를 시작하는 인텐트의 {@link android.content.Intent#addFlags(int) addFlags()} 메서드에 있는 {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} 플래그를 전달합니다.

      @@ -241,11 +241,11 @@ private Intent newDocumentIntent() { } -

      같은 효과를 얻기 위해 +

      같은 효과를 얻기 위해 <activity> 특성 {@code android:autoRemoveFromRecents}를 {@code false}로 설정해도 됩니다. 기본 값은 문서 액티비티의 경우 {@code true} -이고, 일반 액티비티의 경우 {@code false}입니다. 이 특성을 사용하면 이전에 논한 것과 같이 +이고, 일반 액티비티의 경우 {@code false}입니다. 이 특성을 사용하면 이전에 논한 것과 같이 {@link android.content.Intent#FLAG_ACTIVITY_RETAIN_IN_RECENTS} 플래그를 재정의하게 됩니다.

      diff --git a/docs/html-intl/intl/ko/guide/components/services.jd b/docs/html-intl/intl/ko/guide/components/services.jd index fb95ea5ed0fa3a2ed3f3fca333a0fd8255702a19..71c2b50424e867e2185cd7b2cff9f532a954d2bd 100644 --- a/docs/html-intl/intl/ko/guide/components/services.jd +++ b/docs/html-intl/intl/ko/guide/components/services.jd @@ -49,52 +49,52 @@ page.title=서비스 -

      {@link android.app.Service}는 배경에서 오래 실행되는 작업을 -수행할 수 있는 애플리케이션 구성 요소이며 사용자 인터페이스를 제공하지 않습니다. 또 다른 -애플리케이션 구성 요소가 서비스를 시작할 수 있으며, 이는 사용자가 또 다른 -애플리케이션으로 전환하더라도 배경에서 계속해서 실행됩니다. 이외에도, 구성 요소를 서비스에 바인딩하여 -서비스와 상호 작용할 수 있으며, 심지어는 프로세스 간 통신(IPC)도 수행할 수 있습니다. 예를 들어 한 서비스는 -네트워크 트랜잭션을 처리하고, 음악을 재생하고 파일 I/O를 수행하거나 콘텐츠 제공자와 상호 작용할 수 있으며 +

      {@link android.app.Service}는 배경에서 오래 실행되는 작업을 +수행할 수 있는 애플리케이션 구성 요소이며 사용자 인터페이스를 제공하지 않습니다. 또 다른 +애플리케이션 구성 요소가 서비스를 시작할 수 있으며, 이는 사용자가 또 다른 +애플리케이션으로 전환하더라도 배경에서 계속해서 실행됩니다. 이외에도, 구성 요소를 서비스에 바인딩하여 +서비스와 상호 작용할 수 있으며, 심지어는 프로세스 간 통신(IPC)도 수행할 수 있습니다. 예를 들어 한 서비스는 +네트워크 트랜잭션을 처리하고, 음악을 재생하고 파일 I/O를 수행하거나 콘텐츠 제공자와 상호 작용할 수 있으며 이 모든 것을 배경에서 수행할 수 있습니다.

      서비스는 본질적으로 두 가지 형식을 취합니다.

      시작됨
      -
      서비스가 "시작된" 상태가 되려면 애플리케이션 구성 요소(예: 액티비티)가 -{@link android.content.Context#startService startService()}를 호출하여 시작하면 됩니다. 서비스는 한 번 시작되고 나면 -배경에서 무기한으로 실행될 수 있으며, 이는 해당 서비스를 시작한 구성 요소가 소멸되었더라도 무관합니다. 보통, +
      서비스가 "시작된" 상태가 되려면 애플리케이션 구성 요소(예: 액티비티)가 +{@link android.content.Context#startService startService()}를 호출하여 시작하면 됩니다. 서비스는 한 번 시작되고 나면 +배경에서 무기한으로 실행될 수 있으며, 이는 해당 서비스를 시작한 구성 요소가 소멸되었더라도 무관합니다. 보통, 시작된 서비스는 한 작업을 수행하고 결과를 발신자에게 반환하지 않습니다. -예를 들어 네트워크에서 파일을 다운로드하거나 업로드할 수 있습니다. 작업을 완료하면, 해당 서비스는 +예를 들어 네트워크에서 파일을 다운로드하거나 업로드할 수 있습니다. 작업을 완료하면, 해당 서비스는 알아서 중단되는 것이 정상입니다.
      바인딩됨
      서비스가 "바인딩된" 상태가 되려면 애플리케이션 구성 요소가 {@link -android.content.Context#bindService bindService()}를 사용하여 해당 서비스에 바인딩되면 됩니다. 바인딩된 서비스는 클라이언트-서버 -인터페이스를 제공하여 구성 요소가 서비스와 상호 작용할 수 있도록 해주며, 결과를 가져올 수도 있고 심지어 -이와 같은 작업을 여러 프로세스에 걸쳐 프로세스 간 통신(IPC)으로 수행할 수도 있습니다. 바인딩된 서비스는 또 다른 애플리케이션 구성 요소가 -이에 바인딩되어 있는 경우에만 실행됩니다. 여러 개의 구성 요소가 서비스에 한꺼번에 바인딩될 수 있지만, +android.content.Context#bindService bindService()}를 사용하여 해당 서비스에 바인딩되면 됩니다. 바인딩된 서비스는 클라이언트-서버 +인터페이스를 제공하여 구성 요소가 서비스와 상호 작용할 수 있도록 해주며, 결과를 가져올 수도 있고 심지어 +이와 같은 작업을 여러 프로세스에 걸쳐 프로세스 간 통신(IPC)으로 수행할 수도 있습니다. 바인딩된 서비스는 또 다른 애플리케이션 구성 요소가 +이에 바인딩되어 있는 경우에만 실행됩니다. 여러 개의 구성 요소가 서비스에 한꺼번에 바인딩될 수 있지만, 이 모든 것이 바인딩을 해제하면 해당 서비스는 소멸됩니다.
      -

      이 문서는 주로 이러한 두 가지 유형의 서비스를 따로따로 논하지만, 서비스는 +

      이 문서는 주로 이러한 두 가지 유형의 서비스를 따로따로 논하지만, 서비스는 두 가지 방식 모두로 작동할 수 있습니다. 즉 서비스가 시작될 수도 있고(나아가 무기한으로 실행되고) 바인딩도 허용할 수 있다는 뜻입니다. 이는 그저 두어 가지 콜백 메서드의 구현 여부에 달린 문제입니다. {@link android.app.Service#onStartCommand onStartCommand()}를 사용하면 구성 요소가 서비스를 시작할 수 있게 허용하고, {@link android.app.Service#onBind onBind()}를 사용하면 바인딩을 허용합니다.

      애플리케이션이 시작되었든, 바인딩되었든 아니면 양쪽 모두이든 모든 애플리케이션 구성 요소가 -해당 서비스를 사용할 수 있으며(별도의 애플리케이션에서라도), 이는 어느 구성 요소든 액티비티를 -사용할 수 있는 것과 같습니다. 이를 {@link android.content.Intent}로 시작하면 됩니다. 그러나, -매니페스트에서 서비스를 비공개로 선언하고 다른 애플리케이션으로부터의 액세스를 차단할 수도 있습니다. 이것은 -매니페스트에서 서비스 +해당 서비스를 사용할 수 있으며(별도의 애플리케이션에서라도), 이는 어느 구성 요소든 액티비티를 +사용할 수 있는 것과 같습니다. 이를 {@link android.content.Intent}로 시작하면 됩니다. 그러나, +매니페스트에서 서비스를 비공개로 선언하고 다른 애플리케이션으로부터의 액세스를 차단할 수도 있습니다. 이것은 +매니페스트에서 서비스 선언하기에 관한 섹션에서 더 자세히 이야기합니다.

      -

      주의: 서비스는 자신의 호스팅 프로세스의 -기본 스레드에서 실행됩니다. 서비스는 자신의 스레드를 직접 생성하지 않으며, -별도의 프로세스에서 실행되지도 않습니다(별도로 지정하는 경우는 예외). 이것은 즉, -서비스가 CPU 집약적인 작업을 수행할 예정이거나 차단적인 작업을 수행할 예정인 경우(예를 들어 MP3 -재생 또는 네트워킹 등), 서비스 내에 새 스레드를 생성하여 해당 작업을 수행하도록 해야 한다는 뜻입니다. 별도의 스레드를 사용하면 -'애플리케이션이 응답하지 않습니다(ANR)' 오류가 일어날 위험을 줄일 수 있으며 +

      주의: 서비스는 자신의 호스팅 프로세스의 +기본 스레드에서 실행됩니다. 서비스는 자신의 스레드를 직접 생성하지 않으며, +별도의 프로세스에서 실행되지도 않습니다(별도로 지정하는 경우는 예외). 이것은 즉, +서비스가 CPU 집약적인 작업을 수행할 예정이거나 차단적인 작업을 수행할 예정인 경우(예를 들어 MP3 +재생 또는 네트워킹 등), 서비스 내에 새 스레드를 생성하여 해당 작업을 수행하도록 해야 한다는 뜻입니다. 별도의 스레드를 사용하면 +'애플리케이션이 응답하지 않습니다(ANR)' 오류가 일어날 위험을 줄일 수 있으며 애플리케이션의 기본 스레드는 액티비티와 사용자 상호 작용 전용으로 유지될 수 있습니다.

      @@ -103,89 +103,89 @@ android.app.Service#onBind onBind()}를 사용하면 바인딩을 허용합니 -

      서비스를 생성하려면 {@link android.app.Service}의 하위 클래스를 생성해야 합니다(아니면 이의 -기존 하위 클래스 중 하나). 구현에서는 서비스 수명 주기의 주요 측면을 처리하는 콜백 메서드를 -몇 가지 재정의해야 하며 서비스에 바인딩할 구성 요소에 대한 메커니즘을 +

      서비스를 생성하려면 {@link android.app.Service}의 하위 클래스를 생성해야 합니다(아니면 이의 +기존 하위 클래스 중 하나). 구현에서는 서비스 수명 주기의 주요 측면을 처리하는 콜백 메서드를 +몇 가지 재정의해야 하며 서비스에 바인딩할 구성 요소에 대한 메커니즘을 제공해야 합니다(해당되는 경우). 재정의해야 하는 가장 중요한 콜백 메서드는 다음과 같습니다.

      {@link android.app.Service#onStartCommand onStartCommand()}
      -
      시스템이 이 메서드를 호출하는 것은 또 다른 구성 요소(예: 액티비티)가 서비스를 +
      시스템이 이 메서드를 호출하는 것은 또 다른 구성 요소(예: 액티비티)가 서비스를 시작하도록 요청하는 경우입니다. 이때 {@link android.content.Context#startService -startService()}를 호출하는 방법을 씁니다. 이 메서드가 실행되면 서비스가 시작되고 배경에서 무기한으로 실행될 수 -있습니다. 이것을 구성하면 서비스의 작업이 완료되었을 때 해당 서비스를 중단하는 것은 +startService()}를 호출하는 방법을 씁니다. 이 메서드가 실행되면 서비스가 시작되고 배경에서 무기한으로 실행될 수 +있습니다. 이것을 구성하면 서비스의 작업이 완료되었을 때 해당 서비스를 중단하는 것은 개발자 본인의 책임입니다. 이때 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link -android.content.Context#stopService stopService()}를 호출하면 됩니다 (바인딩만 제공하고자 하는 경우, 이 메서드를 구현하지 +android.content.Context#stopService stopService()}를 호출하면 됩니다 (바인딩만 제공하고자 하는 경우, 이 메서드를 구현하지 않아도 됩니다).
      {@link android.app.Service#onBind onBind()}
      시스템이 이 메서드를 호출하는 것은 또 다른 구성 요소가 해당 서비스에 바인딩되고자 하는 경우 (예를 들어 RPC를 수행하기 위해)입니다. 이때 {@link android.content.Context#bindService -bindService()}를 호출하는 방법을 씁니다. 이 메서드를 구현할 때에는 클라이언트가 서비스와 통신을 주고받기 위해 사용할 -인터페이스를 제공해야 합니다. 이때 {@link android.os.IBinder}를 반환하면 됩니다. 이 메서드는 항상 +bindService()}를 호출하는 방법을 씁니다. 이 메서드를 구현할 때에는 클라이언트가 서비스와 통신을 주고받기 위해 사용할 +인터페이스를 제공해야 합니다. 이때 {@link android.os.IBinder}를 반환하면 됩니다. 이 메서드는 항상 구현해야 하지만, 바인딩을 허용하지 않고자 하면 null을 반환해야 합니다.
      {@link android.app.Service#onCreate()}
      -
      시스템이 이 메서드를 호출하는 것은 서비스가 처음 생성되어 일회성 설정 -절차를 수행하는 경우입니다({@link android.app.Service#onStartCommand onStartCommand()} 또는 -{@link android.app.Service#onBind onBind()}를 호출하기 전에). 서비스가 이미 실행 중인 경우, 이 메서드는 호출되지 +
      시스템이 이 메서드를 호출하는 것은 서비스가 처음 생성되어 일회성 설정 +절차를 수행하는 경우입니다({@link android.app.Service#onStartCommand onStartCommand()} 또는 +{@link android.app.Service#onBind onBind()}를 호출하기 전에). 서비스가 이미 실행 중인 경우, 이 메서드는 호출되지 않습니다.
      {@link android.app.Service#onDestroy()}
      -
      시스템이 이 메서드를 호출하는 것은 해당 서비스를 더 이상 사용하지 않고 소멸시키는 경우입니다. -서비스에 이것을 구현해야 스레드, 등록된 각종 수신기(listener, receiver) 등 +
      시스템이 이 메서드를 호출하는 것은 해당 서비스를 더 이상 사용하지 않고 소멸시키는 경우입니다. +서비스에 이것을 구현해야 스레드, 등록된 각종 수신기(listener, receiver) 등 모든 리소스를 정리할 수 있습니다. 이것이 서비스가 수신하는 마지막 호출입니다.

      한 구성 요소가 {@link android.content.Context#startService startService()}를 호출하여 서비스를 시작하면({@link -android.app.Service#onStartCommand onStartCommand()}로의 호출을 초래함), 해당 서비스는 -알아서 {@link android.app.Service#stopSelf()}로 스스로를 중단할 때까지 또는 +android.app.Service#onStartCommand onStartCommand()}로의 호출을 초래함), 해당 서비스는 +알아서 {@link android.app.Service#stopSelf()}로 스스로를 중단할 때까지 또는 또 다른 구성 요소가 {@link android.content.Context#stopService stopService()}를 호출하여 서비스를 중단시킬 때까지 실행 중인 상태로 유지됩니다.

      -

      한 구성 요소가 +

      한 구성 요소가 {@link android.content.Context#bindService bindService()}를 호출하여 서비스를 생성하는 경우(그리고 {@link -android.app.Service#onStartCommand onStartCommand()}를 호출하지 않은 경우), 해당 서비스는 -해당 구성 요소가 바인딩되어 있는 경우에만 실행됩니다. 서비스가 모든 클라이언트로부터 바인딩 해제되면 시스템이 이를 +android.app.Service#onStartCommand onStartCommand()}를 호출하지 않은 경우), 해당 서비스는 +해당 구성 요소가 바인딩되어 있는 경우에만 실행됩니다. 서비스가 모든 클라이언트로부터 바인딩 해제되면 시스템이 이를 소멸시킵니다.

      -

      Android 시스템이 서비스를 강제 중단시키는 것은 메모리가 부족하여 사용자가 초점을 집중하고 있는 -액티비티를 위해 시스템 리소스를 회복해야만 하는 경우로만 국한됩니다. 해당 서비스가 사용자의 주목을 -끌고 있는 액티비티에 바인딩되어 있다면 중단될 가능성이 낮고, 서비스가 전경에서 실행된다고 선언된 경우(나중에 자세히 논함), 거의 절대 중단되지 않습니다. -그렇지 않으면, 서비스가 시작되었고 오랫동안 실행되는 경우 -시간이 지나면서 시스템이 배경 작업 목록에서의 이 서비스의 위치를 점점 낮추고 -서비스는 중단되기 매우 쉬워집니다. 서비스가 시작되었다면 이를 시스템에 의한 재시작을 정상적으로 -처리하도록 디자인해야 합니다. 시스템이 서비스를 중단시키는 경우, 리소스를 다시 사용할 수 있게 되면 +

      Android 시스템이 서비스를 강제 중단시키는 것은 메모리가 부족하여 사용자가 초점을 집중하고 있는 +액티비티를 위해 시스템 리소스를 회복해야만 하는 경우로만 국한됩니다. 해당 서비스가 사용자의 주목을 +끌고 있는 액티비티에 바인딩되어 있다면 중단될 가능성이 낮고, 서비스가 전경에서 실행된다고 선언된 경우(나중에 자세히 논함), 거의 절대 중단되지 않습니다. +그렇지 않으면, 서비스가 시작되었고 오랫동안 실행되는 경우 +시간이 지나면서 시스템이 배경 작업 목록에서의 이 서비스의 위치를 점점 낮추고 +서비스는 중단되기 매우 쉬워집니다. 서비스가 시작되었다면 이를 시스템에 의한 재시작을 정상적으로 +처리하도록 디자인해야 합니다. 시스템이 서비스를 중단시키는 경우, 리소스를 다시 사용할 수 있게 되면 시스템이 가능한 한 빨리 이를 다시 시작합니다(다만 이것은 개발자가 {@link -android.app.Service#onStartCommand onStartCommand()}에서 반환하는 값에도 좌우됩니다. 이 내용은 나중에 논합니다). 시스템이 서비스를 +android.app.Service#onStartCommand onStartCommand()}에서 반환하는 값에도 좌우됩니다. 이 내용은 나중에 논합니다). 시스템이 서비스를 소멸시킬 수 있는 경우에 대한 자세한 정보는 프로세스 및 스레딩 문서를 참조하십시오.

      -

      다음 섹션에서는 각 유형의 서비스를 생성하는 방법과 다른 애플리케이션 구성 요소에서 +

      다음 섹션에서는 각 유형의 서비스를 생성하는 방법과 다른 애플리케이션 구성 요소에서 이를 사용하는 방법을 배우게 됩니다.

      매니페스트에서 서비스 선언하기

      -

      액티비티(및 다른 구성 요소)와 마찬가지로, 서비스는 모두 애플리케이션의 매니페스트 +

      액티비티(및 다른 구성 요소)와 마찬가지로, 서비스는 모두 애플리케이션의 매니페스트 파일에서 선언해야 합니다.

      -

      서비스를 선언하려면 {@code <service>} 요소를 +

      서비스를 선언하려면 {@code <service>} 요소를 {@code <application>} 요소의 하위로 추가하면 됩니다. 예:

      @@ -199,28 +199,28 @@ android.app.Service#onStartCommand onStartCommand()}에서 반환하는 값에 </manifest> -

      매니페스트에서 서비스를 선언하는 데 대한 자세한 정보는 {@code <service>} +

      매니페스트에서 서비스를 선언하는 데 대한 자세한 정보는 {@code <service>} 요소 참조를 확인하십시오.

      -

      {@code <service>} 요소에 포함시킬 수 있는 다른 속성도 있습니다. -이를 포함시켜 서비스를 시작하는 데 필요한 권한과 서비스가 실행되어야 하는 프로세스 등의 +

      {@code <service>} 요소에 포함시킬 수 있는 다른 속성도 있습니다. +이를 포함시켜 서비스를 시작하는 데 필요한 권한과 서비스가 실행되어야 하는 프로세스 등의 속성을 정의할 수 있습니다. {@code android:name} -속성이 유일한 필수 속성입니다. 이것은 서비스의 클래스 이름을 나타냅니다. 일단 애플리케이션을 -게시하고 나면 이 이름을 변경해서는 안 됩니다. 이름을 변경하면 +속성이 유일한 필수 속성입니다. 이것은 서비스의 클래스 이름을 나타냅니다. 일단 애플리케이션을 +게시하고 나면 이 이름을 변경해서는 안 됩니다. 이름을 변경하면 서비스를 시작하거나 바인딩할 명시적 인텐트에 대한 종속성으로 인해 코드를 단절시킬 위험이 있기 때문입니다(블로그 게시물의 바꿀 수 없는 항목을 참조하십시오).

      앱의 보안을 보장하려면 -{@link android.app.Service}을 시작하거나 바인딩할 때 항상 명시적 인텐트를 사용하고 서비스에 대한 인텐트 필터는 선언하지 마십시오. 어느 -서비스를 시작할지 어느 정도 모호성을 허용하는 것이 중요한 경우, 서비스에 대해 +{@link android.app.Service}을 시작하거나 바인딩할 때 항상 명시적 인텐트를 사용하고 서비스에 대한 인텐트 필터는 선언하지 마십시오. 어느 +서비스를 시작할지 어느 정도 모호성을 허용하는 것이 중요한 경우, 서비스에 대해 인텐트 필터를 제공하고 구성 요소 이름을 {@link android.content.Intent}에서 배제할 수 있지만, 그러면 해당 인텐트에 대한 패키지를 {@link -android.content.Intent#setPackage setPackage()}로 설정하여 대상 서비스에 대해 충분한 명확화를 +android.content.Intent#setPackage setPackage()}로 설정하여 대상 서비스에 대해 충분한 명확화를 제공하도록 해야 합니다.

      -

      이외에도 서비스를 본인의 앱에만 사용 가능하도록 보장할 수도 있습니다. +

      이외에도 서비스를 본인의 앱에만 사용 가능하도록 보장할 수도 있습니다. {@code android:exported} - 속성을 포함시킨 뒤 이를 {@code "false"}로 설정하면 됩니다. 이렇게 하면 다른 앱이 여러분의 서비스를 시작하지 못하도록 효과적으로 방지해주며, + 속성을 포함시킨 뒤 이를 {@code "false"}로 설정하면 됩니다. 이렇게 하면 다른 앱이 여러분의 서비스를 시작하지 못하도록 효과적으로 방지해주며, 이는 명시적 인텐트를 사용하는 경우에도 문제 없이 적용됩니다.

      @@ -229,71 +229,71 @@ android.content.Intent#setPackage setPackage()}로 설정하여 대상 서비스

      시작된 서비스 생성하기

      시작된 서비스란 다른 구성 요소가 {@link -android.content.Context#startService startService()}를 호출하여 시작하고, 그 결과 서비스의 +android.content.Context#startService startService()}를 호출하여 시작하고, 그 결과 서비스의 {@link android.app.Service#onStartCommand onStartCommand()} 메서드를 호출하는 결과를 초래한 것을 말합니다.

      -

      서비스가 시작되면 이를 시작한 구성 요소와 독립된 자신만의 -수명 주기를 가지며 해당 서비스는 배경에서 무기한으로 실행될 수 있습니다. 이는 해당 서비스를 -시작한 구성 요소가 소멸되었더라도 무관합니다. 따라서, 서비스는 작업이 완료되면 -{@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 알아서 중단되는 것이 정상이며 아니면 다른 구성 요소가 +

      서비스가 시작되면 이를 시작한 구성 요소와 독립된 자신만의 +수명 주기를 가지며 해당 서비스는 배경에서 무기한으로 실행될 수 있습니다. 이는 해당 서비스를 +시작한 구성 요소가 소멸되었더라도 무관합니다. 따라서, 서비스는 작업이 완료되면 +{@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 알아서 중단되는 것이 정상이며 아니면 다른 구성 요소가 {@link android.content.Context#stopService stopService()}를 호출하여 중단시킬 수도 있습니다.

      애플리케이션 구성 요소(예: 액티비티)가 서비스를 시작하려면 {@link -android.content.Context#startService startService()}를 호출하고, {@link android.content.Intent}를 -전달하면 됩니다. 이것은 서비스를 나타내고 서비스가 사용할 모든 데이터를 포함합니다. 서비스는 이 +android.content.Context#startService startService()}를 호출하고, {@link android.content.Intent}를 +전달하면 됩니다. 이것은 서비스를 나타내고 서비스가 사용할 모든 데이터를 포함합니다. 서비스는 이 {@link android.content.Intent}를 {@link android.app.Service#onStartCommand onStartCommand()} 메서드에서 수신합니다.

      -

      예를 들어 어느 액티비티가 온라인 데이터베이스에 데이터를 약간 저장해야 한다고 가정합니다. 액티비티가 +

      예를 들어 어느 액티비티가 온라인 데이터베이스에 데이터를 약간 저장해야 한다고 가정합니다. 액티비티가 동반자 서비스를 시작하여 저장할 데이터를 이에 전달할 수 있습니다. 이때 인텐트를 {@link android.content.Context#startService startService()}에 전달하면 됩니다. 서비스는 이 인텐트를 {@link -android.app.Service#onStartCommand onStartCommand()}에서 수신하고 인터넷에 연결한 다음 데이터베이스 -트랜잭션을 수행합니다. 작업을 완료하면, 해당 서비스는 알아서 스스로 중단되고 +android.app.Service#onStartCommand onStartCommand()}에서 수신하고 인터넷에 연결한 다음 데이터베이스 +트랜잭션을 수행합니다. 작업을 완료하면, 해당 서비스는 알아서 스스로 중단되고 소멸됩니다.

      -

      주의: 서비스는 기본적으로 자신이 선언된 애플리케이션의 같은 -프로세스에서 실행되기도 하고 해당 애플리케이션의 기본 스레드에서 실행되기도 합니다. 따라서, 사용자가 -같은 애플리케이션의 액티비티와 상호 작용하는 동안 서비스가 집약적이거나 차단적인 작업을 수행하는 경우, -해당 서비스 때문에 액티비티 성능이 느려지게 됩니다. 애플리케이션 성능에 영향을 미치는 것을 방지하려면, +

      주의: 서비스는 기본적으로 자신이 선언된 애플리케이션의 같은 +프로세스에서 실행되기도 하고 해당 애플리케이션의 기본 스레드에서 실행되기도 합니다. 따라서, 사용자가 +같은 애플리케이션의 액티비티와 상호 작용하는 동안 서비스가 집약적이거나 차단적인 작업을 수행하는 경우, +해당 서비스 때문에 액티비티 성능이 느려지게 됩니다. 애플리케이션 성능에 영향을 미치는 것을 방지하려면, 서비스 내에서 새 스레드를 시작해야 합니다.

      기존에는 시작된 서비스를 생성하기 위해 확장할 수 있는 클래스가 두 개 있었습니다.

      {@link android.app.Service}
      -
      이것이 모든 서비스의 기본 클래스입니다. 이 클래스를 확장하는 경우, 서비스의 모든 작업을 수행할 -새 스레드를 만드는 것이 중요합니다. 서비스가 기본적으로 애플리케이션의 기본 스레드를 사용하기 -때문인데, 이로 인해 애플리케이션이 실행 중인 모든 액티비티의 성능이 +
      이것이 모든 서비스의 기본 클래스입니다. 이 클래스를 확장하는 경우, 서비스의 모든 작업을 수행할 +새 스레드를 만드는 것이 중요합니다. 서비스가 기본적으로 애플리케이션의 기본 스레드를 사용하기 +때문인데, 이로 인해 애플리케이션이 실행 중인 모든 액티비티의 성능이 느려질 수 있기 때문입니다.
      {@link android.app.IntentService}
      -
      이것은 {@link android.app.Service}의 하위 클래스로, 작업자 스레드를 -사용하여 모든 시작 요청을 처리하되 한 번에 하나씩 처리합니다. 서비스가 여러 개의 요청을 +
      이것은 {@link android.app.Service}의 하위 클래스로, 작업자 스레드를 +사용하여 모든 시작 요청을 처리하되 한 번에 하나씩 처리합니다. 서비스가 여러 개의 요청을 동시에 처리하지 않아도 되는 경우 이것이 최선의 옵션입니다. 해야 할 일은 {@link -android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐으로, 이것이 각 시작 요청에 대한 인텐트를 수신하여 +android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐으로, 이것이 각 시작 요청에 대한 인텐트를 수신하여 개발자는 배경 작업을 수행할 수 있습니다.
      -

      다음 섹션에서는 이와 같은 클래스 중 하나를 사용하여 서비스를 구현하는 방법을 +

      다음 섹션에서는 이와 같은 클래스 중 하나를 사용하여 서비스를 구현하는 방법을 설명합니다.

      IntentService 클래스 확장하기

      대부분의 시작된 서비스는 여러 개의 요청을 동시에 처리하지 않아도 되기 때문에 -(이는 사실 위험한 다중 스레딩 시나리오일 수 있습니다), 서비스를 구현할 때에는 +(이는 사실 위험한 다중 스레딩 시나리오일 수 있습니다), 서비스를 구현할 때에는 {@link android.app.IntentService} 클래스를 사용하는 것이 최선의 방안일 것입니다.

      {@link android.app.IntentService}는 다음과 같은 작업을 수행합니다.

      • 애플리케이션의 기본 스레드와는 별도로 {@link -android.app.Service#onStartCommand onStartCommand()}에 전달된 모든 인텐트를 실행하는 기본 작업자 스레드를 +android.app.Service#onStartCommand onStartCommand()}에 전달된 모든 인텐트를 실행하는 기본 작업자 스레드를 생성합니다.
      • 한 번에 인텐트를 하나씩 {@link -android.app.IntentService#onHandleIntent onHandleIntent()} 구현에 전달하는 작업 대기열을 생성하므로 다중 스레딩에 대해 염려할 필요가 +android.app.IntentService#onHandleIntent onHandleIntent()} 구현에 전달하는 작업 대기열을 생성하므로 다중 스레딩에 대해 염려할 필요가 전혀 없습니다.
      • -
      • 시작 요청이 모두 처리된 후 서비스를 중단하므로 개발자가 +
      • 시작 요청이 모두 처리된 후 서비스를 중단하므로 개발자가 {@link android.app.Service#stopSelf}를 호출할 필요가 전혀 없습니다.
      • -
      • {@link android.app.IntentService#onBind onBind()}의 기본 구현을 제공하여 null을 +
      • {@link android.app.IntentService#onBind onBind()}의 기본 구현을 제공하여 null을 반환하도록 합니다.
      • {@link android.app.IntentService#onStartCommand onStartCommand()}의 기본 구현을 제공하여 인텐트를 작업 대기열에 보내고, 다음으로 {@link @@ -301,7 +301,7 @@ android.app.IntentService#onHandleIntent onHandleIntent()} 구현에 보내도

      이 모든 것은 결론적으로 개발자가 직접 할 일은 클라이언트가 제공한 작업을 수행할 {@link -android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐이라는 사실로 +android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐이라는 사실로 이어집니다. (다만, 서비스에 대해 작은 생성자를 제공해야 하기도 합니다.)

      다음은 {@link android.app.IntentService}의 구현을 예시로 나타낸 것입니다.

      @@ -345,10 +345,10 @@ android.app.IntentService#onHandleIntent onHandleIntent()} 구현뿐이죠.

      다른 콜백 메서드도 재정의하기로 결정하는 경우-예를 들어 {@link android.app.IntentService#onCreate onCreate()}, {@link android.app.IntentService#onStartCommand onStartCommand()} 또는 {@link -android.app.IntentService#onDestroy onDestroy()}-슈퍼 구현을 꼭 호출해야 합니다. +android.app.IntentService#onDestroy onDestroy()}-슈퍼 구현을 꼭 호출해야 합니다. 그래야 {@link android.app.IntentService}가 작업자 스레드의 수명을 적절하게 처리할 수 있습니다.

      -

      예를 들어 {@link android.app.IntentService#onStartCommand onStartCommand()}는 반드시 +

      예를 들어 {@link android.app.IntentService#onStartCommand onStartCommand()}는 반드시 기본 구현을 반환해야 합니다(이로써 인텐트가 {@link android.app.IntentService#onHandleIntent onHandleIntent()}로 전달되는 것입니다).

      @@ -360,25 +360,25 @@ public int onStartCommand(Intent intent, int flags, int startId) { } -

      {@link android.app.IntentService#onHandleIntent onHandleIntent()} 외에 슈퍼 클래스를 +

      {@link android.app.IntentService#onHandleIntent onHandleIntent()} 외에 슈퍼 클래스를 호출하지 않아도 되는 유일한 메서드는 {@link android.app.IntentService#onBind onBind()}입니다(다만 이를 구현하는 것은 서비스가 바인딩을 허용할 때에만 필요합니다).

      -

      다음 섹션에서는 기본 {@link android.app.Service} -클래스를 확장할 때 같은 종류의 서비스를 구현하는 방법을 배우게 됩니다. 이때에는 코드가 훨씬 많이 필요하지만, +

      다음 섹션에서는 기본 {@link android.app.Service} +클래스를 확장할 때 같은 종류의 서비스를 구현하는 방법을 배우게 됩니다. 이때에는 코드가 훨씬 많이 필요하지만, 동시 시작 요청을 처리해야 하는 경우 이것이 적절할 수 있습니다.

      서비스 클래스 확장하기

      -

      이전 섹션에서 본 것과 같이 {@link android.app.IntentService}를 사용하면 -시작된 서비스 구현이 매우 단순해집니다. 하지만 서비스가 다중 스레딩을 -수행해야 하는 경우(작업 대기열을 통해 시작 요청을 처리하는 대신), 그때는 +

      이전 섹션에서 본 것과 같이 {@link android.app.IntentService}를 사용하면 +시작된 서비스 구현이 매우 단순해집니다. 하지만 서비스가 다중 스레딩을 +수행해야 하는 경우(작업 대기열을 통해 시작 요청을 처리하는 대신), 그때는 {@link android.app.Service} 클래스를 확장하여 각 인텐트를 처리하게 할 수 있습니다.

      비교를 위해 다음 예시의 코드를 보겠습니다. 이는 {@link android.app.Service} 클래스의 구현으로, 위의 예시에서 {@link -android.app.IntentService}를 사용하여 수행한 것과 똑같은 작업을 수행합니다. 바꿔 말하면 각 시작 요청에 대해 +android.app.IntentService}를 사용하여 수행한 것과 똑같은 작업을 수행합니다. 바꿔 말하면 각 시작 요청에 대해 작업자 스레드를 사용하여 작업을 수행하고 한 번에 요청을 하나씩만 처리한다는 뜻입니다.

      @@ -455,46 +455,46 @@ public class HelloService extends Service {
       

      보시다시피 {@link android.app.IntentService}를 사용할 때보다 훨씬 손이 많이 갑니다.

      그러나, 각 호출을 {@link android.app.Service#onStartCommand -onStartCommand()}로 직접 처리할 수 있기 때문에 여러 개의 요청을 동시에 수행할 수 있습니다. 이 예시는 그것을 -보여주는 것은 아니지만, 그런 작업을 원하는 경우 각 요청에 대해 새 스레드를 +onStartCommand()}로 직접 처리할 수 있기 때문에 여러 개의 요청을 동시에 수행할 수 있습니다. 이 예시는 그것을 +보여주는 것은 아니지만, 그런 작업을 원하는 경우 각 요청에 대해 새 스레드를 하나씩 생성한 다음 곧바로 실행하면 됩니다(이전 요청이 끝날 때까지 기다리는 대신).

      -

      {@link android.app.Service#onStartCommand onStartCommand()} 메서드가 반드시 -정수를 반환해야 한다는 사실을 유의하십시오. 정수는 시스템이 서비스를 중단시킨 경우 시스템이 해당 서비스를 +

      {@link android.app.Service#onStartCommand onStartCommand()} 메서드가 반드시 +정수를 반환해야 한다는 사실을 유의하십시오. 정수는 시스템이 서비스를 중단시킨 경우 시스템이 해당 서비스를 계속하는 방법에 대해 설명하는 값입니다(위에서 논한 바와 같이 {@link -android.app.IntentService}의 기본 구현이 이것을 개발자 대신 처리해줍니다. 개발자가 이를 수정할 수도 있습니다). -{@link android.app.Service#onStartCommand onStartCommand()}로부터의 반환 값은 반드시 +android.app.IntentService}의 기본 구현이 이것을 개발자 대신 처리해줍니다. 개발자가 이를 수정할 수도 있습니다). +{@link android.app.Service#onStartCommand onStartCommand()}로부터의 반환 값은 반드시 다음 상수 중 하나여야 합니다.

      {@link android.app.Service#START_NOT_STICKY}
      시스템이 서비스를 {@link android.app.Service#onStartCommand -onStartCommand()} 반환 후에 중단시키면 서비스를 재생성하면 안 됩니다. 다만 전달할 -보류 인텐트가 있는 경우는 예외입니다. 이것은 서비스가 불필요하게 실행되는 일을 피할 수 있는 가장 안전한 옵션이며, +onStartCommand()} 반환 후에 중단시키면 서비스를 재생성하면 안 됩니다. 다만 전달할 +보류 인텐트가 있는 경우는 예외입니다. 이것은 서비스가 불필요하게 실행되는 일을 피할 수 있는 가장 안전한 옵션이며, 애플리케이션이 완료되지 않은 모든 작업을 단순히 재시작할 수 있을 때 좋습니다.
      {@link android.app.Service#START_STICKY}
      시스템이 서비스를 {@link android.app.Service#onStartCommand onStartCommand()} 반환 후에 중단시키는 경우, 서비스를 재생성하고 {@link -android.app.Service#onStartCommand onStartCommand()}를 호출하되 마지막 인텐트를 다시 전달하지는 마십시오. -그 대신, 시스템이 null 인텐트로 {@link android.app.Service#onStartCommand onStartCommand()}를 -호출합니다. 다만 서비스를 시작할 보류 인텐트가 있는 경우만은 예외이며, 이럴 때에는 -그러한 인텐트를 전달합니다. 이것은 명령을 실행하지는 않지만 무기한으로 실행 중이며 작업을 기다리고 있는 +android.app.Service#onStartCommand onStartCommand()}를 호출하되 마지막 인텐트를 다시 전달하지는 마십시오. +그 대신, 시스템이 null 인텐트로 {@link android.app.Service#onStartCommand onStartCommand()}를 +호출합니다. 다만 서비스를 시작할 보류 인텐트가 있는 경우만은 예외이며, 이럴 때에는 +그러한 인텐트를 전달합니다. 이것은 명령을 실행하지는 않지만 무기한으로 실행 중이며 작업을 기다리고 있는 미디어 플레이어(또는 그와 비슷한 서비스)에 적합합니다.
      {@link android.app.Service#START_REDELIVER_INTENT}
      시스템이 서비스를 {@link android.app.Service#onStartCommand onStartCommand()} 반환 후에 중단시키는 경우, 서비스를 재생성하고 서비스에 전달된 마지막 인텐트로 {@link -android.app.Service#onStartCommand onStartCommand()}를 -호출하십시오. 모든 보류 인텐트가 차례로 전달됩니다. 이것은 즉시 재개되어야 하는 작업을 +android.app.Service#onStartCommand onStartCommand()}를 +호출하십시오. 모든 보류 인텐트가 차례로 전달됩니다. 이것은 즉시 재개되어야 하는 작업을 능동적으로 수행 중인 서비스(예를 들어 파일 다운로드 등)에 적합합니다.
      -

      이러한 반환 값에 대한 자세한 내용은 각 상수에 대해 링크로 연결된 참조 문서를 +

      이러한 반환 값에 대한 자세한 내용은 각 상수에 대해 링크로 연결된 참조 문서를 확인하십시오.

      서비스 시작

      -

      액티비티나 다른 구성 요소에서 서비스를 시작하려면 +

      액티비티나 다른 구성 요소에서 서비스를 시작하려면 {@link android.content.Intent}를(시작할 서비스를 나타냄) {@link android.content.Context#startService startService()}에 전달하면 됩니다. Android 시스템이 서비스의 {@link android.app.Service#onStartCommand onStartCommand()} 메서드를 호출하여 여기에 {@link @@ -510,53 +510,53 @@ Intent intent = new Intent(this, HelloService.class); startService(intent);

      -

      {@link android.content.Context#startService startService()} 메서드가 즉시 반환되며 +

      {@link android.content.Context#startService startService()} 메서드가 즉시 반환되며 Android 시스템이 서비스의 {@link android.app.Service#onStartCommand onStartCommand()} 메서드를 호출합니다. 서비스가 이미 실행 중이지 않은 경우, 시스템은 우선 {@link android.app.Service#onCreate onCreate()}를 호출하고, 다음으로 {@link android.app.Service#onStartCommand onStartCommand()}를 호출합니다.

      서비스가 바인딩도 제공하지 않는 경우, {@link -android.content.Context#startService startService()}와 함께 전달된 인텐트가 애플리케이션 구성 요소와 서비스 사이의 -유일한 통신 방법입니다. 그러나 서비스가 결과를 돌려보내기를 원하는 경우, 서비스를 시작한 -클라이언트가 브로드캐스트를 위해 {@link android.app.PendingIntent}를 -만들 수 있고({@link android.app.PendingIntent#getBroadcast getBroadcast()} 사용) 이를 서비스를 시작한 -{@link android.content.Intent} 내의 서비스에 전달할 수 있습니다. 그러면 서비스가 +android.content.Context#startService startService()}와 함께 전달된 인텐트가 애플리케이션 구성 요소와 서비스 사이의 +유일한 통신 방법입니다. 그러나 서비스가 결과를 돌려보내기를 원하는 경우, 서비스를 시작한 +클라이언트가 브로드캐스트를 위해 {@link android.app.PendingIntent}를 +만들 수 있고({@link android.app.PendingIntent#getBroadcast getBroadcast()} 사용) 이를 서비스를 시작한 +{@link android.content.Intent} 내의 서비스에 전달할 수 있습니다. 그러면 서비스가 이 브로드캐스트를 사용하여 결과를 전달할 수 있게 됩니다.

      -

      서비스를 시작하기 위한 여러 개의 요청은 서비스의 -{@link android.app.Service#onStartCommand onStartCommand()}로의 상응하는 여러 개의 호출이라는 결과를 낳습니다. 하지만, 서비스를 중단하려면 +

      서비스를 시작하기 위한 여러 개의 요청은 서비스의 +{@link android.app.Service#onStartCommand onStartCommand()}로의 상응하는 여러 개의 호출이라는 결과를 낳습니다. 하지만, 서비스를 중단하려면 이를 중단하라는 요청 하나({@link android.app.Service#stopSelf stopSelf()} 또는 {@link android.content.Context#stopService stopService()} 사용)만 있으면 됩니다.

      서비스 중단

      -

      시작된 서비스는 자신만의 수명 주기를 직접 관리해야 합니다. 다시 말해, 시스템이 -서비스를 중단하거나 소멸시키지 않는다는 뜻입니다. 다만 시스템 메모리를 회복해야 하고 서비스가 -{@link android.app.Service#onStartCommand onStartCommand()} 반환 후에도 계속 실행되는 경우는 예외입니다. 따라서, -서비스는 {@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 중단시켜야 하고, 아니면 +

      시작된 서비스는 자신만의 수명 주기를 직접 관리해야 합니다. 다시 말해, 시스템이 +서비스를 중단하거나 소멸시키지 않는다는 뜻입니다. 다만 시스템 메모리를 회복해야 하고 서비스가 +{@link android.app.Service#onStartCommand onStartCommand()} 반환 후에도 계속 실행되는 경우는 예외입니다. 따라서, +서비스는 {@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 중단시켜야 하고, 아니면 다른 구성 요소가 {@link android.content.Context#stopService stopService()}를 호출하여 이를 중단시킬 수 있습니다.

      일단 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link -android.content.Context#stopService stopService()}로 중단하기를 요청하고 나면 시스템이 서비스를 가능한 한 빨리 +android.content.Context#stopService stopService()}로 중단하기를 요청하고 나면 시스템이 서비스를 가능한 한 빨리 소멸시킵니다.

      그러나, 서비스가 {@link -android.app.Service#onStartCommand onStartCommand()}로의 요청을 동시에 여러 개 처리하기를 바라는 경우라면 시작 요청 처리를 완료한 뒤에도 -서비스를 중단하면 안 됩니다. 그 이후 새 시작 요청을 받았을 수 있기 -때문입니다(첫 요청 종료 시에 중단하면 두 번째 요청을 종료시킵니다). 이 문제를 -피하려면, {@link android.app.Service#stopSelf(int)}를 사용하여 서비스를 +android.app.Service#onStartCommand onStartCommand()}로의 요청을 동시에 여러 개 처리하기를 바라는 경우라면 시작 요청 처리를 완료한 뒤에도 +서비스를 중단하면 안 됩니다. 그 이후 새 시작 요청을 받았을 수 있기 +때문입니다(첫 요청 종료 시에 중단하면 두 번째 요청을 종료시킵니다). 이 문제를 +피하려면, {@link android.app.Service#stopSelf(int)}를 사용하여 서비스를 중단시키라는 개발자의 요청이 항상 최신 시작 요청에 기반하도록 해야 합니다. 다시 말해, {@link -android.app.Service#stopSelf(int)}를 호출할 때면 시작 요청의 ID({@link android.app.Service#onStartCommand onStartCommand()}에 전달된 -startId)를 전달하게 됩니다. 여기에 중단 요청이 +android.app.Service#stopSelf(int)}를 호출할 때면 시작 요청의 ID({@link android.app.Service#onStartCommand onStartCommand()}에 전달된 +startId)를 전달하게 됩니다. 여기에 중단 요청이 부합됩니다. 그런 다음 개발자가 {@link android.app.Service#stopSelf(int)}를 호출할 수 있기 전에 서비스가 새 시작 요청을 받은 경우, ID가 일치하지 않게 되고 서비스는 중단되지 않습니다.

      -

      주의: 서비스가 작업을 완료한 다음 애플리케이션이 -소속 서비스를 중단할 수 있어야 한다는 점이 중요합니다. 그래야 시스템 리소스 낭비를 피하고 배터리 전력 소모를 줄일 수 있습니다. 필요한 경우 +

      주의: 서비스가 작업을 완료한 다음 애플리케이션이 +소속 서비스를 중단할 수 있어야 한다는 점이 중요합니다. 그래야 시스템 리소스 낭비를 피하고 배터리 전력 소모를 줄일 수 있습니다. 필요한 경우 다른 구성 요소도 서비스를 중단시킬 수 있습니다. {@link -android.content.Context#stopService stopService()}를 호출하면 됩니다. 서비스에 대해 바인딩을 활성화하더라도, +android.content.Context#stopService stopService()}를 호출하면 됩니다. 서비스에 대해 바인딩을 활성화하더라도, 서비스가 {@link android.app.Service#onStartCommand onStartCommand()}로의 호출을 한 번이라도 받았으면 항상 서비스를 직접 중단시켜야 합니다.

      @@ -571,32 +571,32 @@ android.content.Context#bindService bindService()}를 호출하여 오래 지속 (또한 보통은 구성 요소가 {@link android.content.Context#startService startService()}를 호출하여 서비스를 시작하는 것을 허용하지 않습니다).

      -

      액티비티와 애플리케이션의 다른 구성 요소에서 서비스와 상호 작용하기를 원하는 경우 -바인딩된 서비스를 생성해야 합니다. 아니면 애플리케이션의 기능 몇 가지를 프로세스 간 통신(IPC)을 통해 +

      액티비티와 애플리케이션의 다른 구성 요소에서 서비스와 상호 작용하기를 원하는 경우 +바인딩된 서비스를 생성해야 합니다. 아니면 애플리케이션의 기능 몇 가지를 프로세스 간 통신(IPC)을 통해 다른 애플리케이션에 노출하고자 하는 경우에도 좋습니다.

      바인딩된 서비스를 생성하려면 {@link -android.app.Service#onBind onBind()} 콜백 메서드를 구현하여 서비스와의 통신을 위한 인터페이스를 정의하는 -{@link android.os.IBinder}를 반환하도록 해야 합니다. 그러면 다른 애플리케이션 구성 요소가 -{@link android.content.Context#bindService bindService()}를 호출하여 해당 인터페이스를 검색하고, 서비스에 있는 메서드를 -호출하기 시작할 수 있습니다. 서비스는 자신에게 바인딩된 애플리케이션 구성 요소에게 도움이 되기 위해서만 -존재하는 것이므로, 서비스에 바인딩된 구성 요소가 없으면 시스템이 이를 소멸시킵니다(바인딩된 서비스는 시작된 서비스처럼 -{@link android.app.Service#onStartCommand onStartCommand()}를 통해 +android.app.Service#onBind onBind()} 콜백 메서드를 구현하여 서비스와의 통신을 위한 인터페이스를 정의하는 +{@link android.os.IBinder}를 반환하도록 해야 합니다. 그러면 다른 애플리케이션 구성 요소가 +{@link android.content.Context#bindService bindService()}를 호출하여 해당 인터페이스를 검색하고, 서비스에 있는 메서드를 +호출하기 시작할 수 있습니다. 서비스는 자신에게 바인딩된 애플리케이션 구성 요소에게 도움이 되기 위해서만 +존재하는 것이므로, 서비스에 바인딩된 구성 요소가 없으면 시스템이 이를 소멸시킵니다(바인딩된 서비스는 시작된 서비스처럼 +{@link android.app.Service#onStartCommand onStartCommand()}를 통해 중단시키지 않아도 됩니다).

      -

      바인딩된 서비스를 생성하려면 가장 먼저 해야 할 일은 클라이언트가 서비스와 -통신할 수 있는 방법을 나타내는 인터페이스를 정의하는 것입니다. 서비스와 클라이언트 사이에서 쓰이는 이 인터페이스는 -반드시 {@link android.os.IBinder}의 구현이어야 하며 이를 +

      바인딩된 서비스를 생성하려면 가장 먼저 해야 할 일은 클라이언트가 서비스와 +통신할 수 있는 방법을 나타내는 인터페이스를 정의하는 것입니다. 서비스와 클라이언트 사이에서 쓰이는 이 인터페이스는 +반드시 {@link android.os.IBinder}의 구현이어야 하며 이를 서비스가 {@link android.app.Service#onBind -onBind()} 콜백 메서드에서 반환해야 합니다. 클라이언트가 {@link android.os.IBinder}를 수신하면 해당 인터페이스를 통해 서비스와 +onBind()} 콜백 메서드에서 반환해야 합니다. 클라이언트가 {@link android.os.IBinder}를 수신하면 해당 인터페이스를 통해 서비스와 상호 작용을 시작할 수 있습니다.

      -

      여러 클라이언트가 서비스에 한꺼번에 바인딩될 수 있습니다. 클라이언트가 서비스와의 상호 작용을 완료하면 이는 -{@link android.content.Context#unbindService unbindService()}를 호출하여 바인딩을 해제합니다. 서비스에 +

      여러 클라이언트가 서비스에 한꺼번에 바인딩될 수 있습니다. 클라이언트가 서비스와의 상호 작용을 완료하면 이는 +{@link android.content.Context#unbindService unbindService()}를 호출하여 바인딩을 해제합니다. 서비스에 바인딩된 클라이언트가 하나도 없으면 시스템이 해당 서비스를 소멸시킵니다.

      -

      바인딩된 서비스를 구현하는 데에는 여러 가지 방법이 있으며 그러한 구현은 시작된 서비스보다 -훨씬 복잡합니다. 따라서 바인딩된 서비스 논의는 +

      바인딩된 서비스를 구현하는 데에는 여러 가지 방법이 있으며 그러한 구현은 시작된 서비스보다 +훨씬 복잡합니다. 따라서 바인딩된 서비스 논의는 바인딩된 서비스에 관한 별도의 문서에서 다룹니다.

      @@ -605,13 +605,13 @@ onBind()} 콜백 메서드에서 반환해야 합니다. 클라이언트가 {@li

      서비스는 일단 실행되고 나면 사용자에게 알림 메시지 또는 상태 표시줄 알림 등을 사용해 이벤트를 알릴 수 있습니다.

      -

      알림 메시지란 현재 창의 표면에 잠시 나타났다가 사라지는 메시지이고, -상태 표시줄 알림은 상태 표시줄에 메시지가 담긴 아이콘을 제공하여 사용자가 이를 선택하여 +

      알림 메시지란 현재 창의 표면에 잠시 나타났다가 사라지는 메시지이고, +상태 표시줄 알림은 상태 표시줄에 메시지가 담긴 아이콘을 제공하여 사용자가 이를 선택하여 조치를 취할 수 있게 하는 것입니다(예: 액티비티 시작).

      보통, 일종의 배경 작업이 완료되었고 -(예: 파일 다운로드 완료) 이제 사용자가 그에 대해 조치를 취할 수 있는 경우 상태 표시줄 알림이 -최선의 기법입니다. 사용자가 확장된 보기에서 알림을 선택하면, +(예: 파일 다운로드 완료) 이제 사용자가 그에 대해 조치를 취할 수 있는 경우 상태 표시줄 알림이 +최선의 기법입니다. 사용자가 확장된 보기에서 알림을 선택하면, 해당 알림이 액티비티를 시작할 수 있습니다(예: 다운로드한 파일 보기).

      자세한 정보는 알림 메시지 또는 상태 표시줄 알림 @@ -621,19 +621,19 @@ onBind()} 콜백 메서드에서 반환해야 합니다. 클라이언트가 {@li

      전경에서 서비스 실행하기

      -

      전경 서비스는 사용자가 능동적으로 인식하고 있으므로 메모리 부족 시에도 -시스템이 중단할 후보로 고려되지 않는 서비스를 말합니다. 전경 -서비스는 상태 표시줄에 대한 알림을 제공해야 합니다. 이것은 -"진행 중" 제목 아래에 배치되며, 이는 곧 해당 알림은 서비스가 중단되었거나 +

      전경 서비스는 사용자가 능동적으로 인식하고 있으므로 메모리 부족 시에도 +시스템이 중단할 후보로 고려되지 않는 서비스를 말합니다. 전경 +서비스는 상태 표시줄에 대한 알림을 제공해야 합니다. 이것은 +"진행 중" 제목 아래에 배치되며, 이는 곧 해당 알림은 서비스가 중단되었거나 전경에서 제거되지 않은 이상 무시할 수 없다는 뜻입니다.

      -

      예를 들어 서비스에서 음악을 재생하는 음악 플레이어는 전경에서 -실행되도록 설정해야 합니다. 사용자가 이것의 작동을 분명히 인식하고 있기 -때문입니다. 상태 표시줄에 있는 알림은 현재 노래를 나타내고 +

      예를 들어 서비스에서 음악을 재생하는 음악 플레이어는 전경에서 +실행되도록 설정해야 합니다. 사용자가 이것의 작동을 분명히 인식하고 있기 +때문입니다. 상태 표시줄에 있는 알림은 현재 노래를 나타내고 사용자로 하여금 음악 플레이어와 상호 작용할 액티비티를 시작하게 해줄 수도 있습니다.

      서비스가 전경에서 실행되도록 요청하려면 {@link -android.app.Service#startForeground startForeground()}를 호출하면 됩니다. 이 메서드는 두 개의 매개변수를 취합니다. +android.app.Service#startForeground startForeground()}를 호출하면 됩니다. 이 메서드는 두 개의 매개변수를 취합니다. 그 중 하나는 해당 알림을 고유하게 식별하는 정수이고 다른 하나는 상태 표시줄에 해당되는 {@link android.app.Notification}입니다. 예:

      @@ -652,48 +652,48 @@ android.app.Service#startForeground startForeground()}에 부여하는 정수 ID

      서비스를 전경에서 제거하려면 {@link -android.app.Service#stopForeground stopForeground()}를 호출하면 됩니다. 이 메서드는 부울 값을 취하며, 이것이 +android.app.Service#stopForeground stopForeground()}를 호출하면 됩니다. 이 메서드는 부울 값을 취하며, 이것이 상태 표시줄 알림도 제거할지 여부를 나타냅니다. 이 메서드는 서비스를 중단시키지 않습니다. - 그러나, 서비스가 전경에서 실행 중인 동안 서비스를 중단시키면 + 그러나, 서비스가 전경에서 실행 중인 동안 서비스를 중단시키면 알림도 마찬가지로 제거됩니다.

      -

      알림에 대한 자세한 정보는 상태 표시줄 +

      알림에 대한 자세한 정보는 상태 표시줄 알림 생성을 참조하십시오.

      서비스 수명 주기 관리

      -

      서비스의 수명 주기는 액티비티의 수명 주기보다 훨씬 간단합니다. 하지만, 서비스를 생성하고 -소멸시키는 방법에 특히 주의를 기울여야 한다는 면에서 중요도는 이쪽이 더 높습니다. 서비스는 사용자가 모르는 채로 +

      서비스의 수명 주기는 액티비티의 수명 주기보다 훨씬 간단합니다. 하지만, 서비스를 생성하고 +소멸시키는 방법에 특히 주의를 기울여야 한다는 면에서 중요도는 이쪽이 더 높습니다. 서비스는 사용자가 모르는 채로 배경에서 실행될 수 있기 때문입니다.

      -

      서비스 수명 주기—생성되었을 때부터 소멸될 때까지—는 두 가지 서로 다른 경로를 +

      서비스 수명 주기—생성되었을 때부터 소멸될 때까지—는 두 가지 서로 다른 경로를 따를 수 있습니다.

      • 시작된 서비스

        서비스는 또 다른 구성 요소가 {@link -android.content.Context#startService startService()}를 호출하면 생성됩니다. 그러면 서비스가 무기한으로 실행될 수 있으며 +android.content.Context#startService startService()}를 호출하면 생성됩니다. 그러면 서비스가 무기한으로 실행될 수 있으며 스스로 알아서 중단되어야 합니다. 이때 {@link -android.app.Service#stopSelf() stopSelf()}를 호출하는 방법을 씁니다. 또 다른 구성 요소도 서비스를 중단시킬 수 +android.app.Service#stopSelf() stopSelf()}를 호출하는 방법을 씁니다. 또 다른 구성 요소도 서비스를 중단시킬 수 있습니다. {@link android.content.Context#stopService stopService()}를 호출하면 됩니다. 서비스가 중단되면 시스템이 이를 소멸시킵니다.

      • 바인딩된 서비스

        서비스는 또 다른 구성 요소(클라이언트)가 {@link -android.content.Context#bindService bindService()}를 호출하면 생성됩니다. 그러면 클라이언트가 -{@link android.os.IBinder} 인터페이스를 통해 서비스와 통신을 주고받을 수 있습니다. 클라이언트가 연결을 종료하려면 -{@link android.content.Context#unbindService unbindService()}를 호출하면 됩니다. 여러 클라이언트가 같은 서비스에 -바인딩될 수 있으며, 이 모두가 바인딩을 해제하면 시스템이 해당 서비스를 소멸시킵니다 (서비스가 스스로를 중단시키지 +android.content.Context#bindService bindService()}를 호출하면 생성됩니다. 그러면 클라이언트가 +{@link android.os.IBinder} 인터페이스를 통해 서비스와 통신을 주고받을 수 있습니다. 클라이언트가 연결을 종료하려면 +{@link android.content.Context#unbindService unbindService()}를 호출하면 됩니다. 여러 클라이언트가 같은 서비스에 +바인딩될 수 있으며, 이 모두가 바인딩을 해제하면 시스템이 해당 서비스를 소멸시킵니다 (서비스가 스스로를 중단시키지 않아도 됩니다).

      -

      이와 같은 두 가지 경로는 완전히 별개의 것은 아닙니다. 다시 말해, 이미 -{@link android.content.Context#startService startService()}로 시작된 서비스에 바인딩할 수도 있다는 뜻입니다. 예를 +

      이와 같은 두 가지 경로는 완전히 별개의 것은 아닙니다. 다시 말해, 이미 +{@link android.content.Context#startService startService()}로 시작된 서비스에 바인딩할 수도 있다는 뜻입니다. 예를 들어, 배경 음악 서비스를 시작하려면 {@link android.content.Context#startService -startService()}를 호출하되 재생할 음악을 식별하는 {@link android.content.Intent}를 사용하면 됩니다. 나중에, -아마도 사용자가 플레이어에 좀 더 많은 통제권을 발휘하고자 하거나 +startService()}를 호출하되 재생할 음악을 식별하는 {@link android.content.Intent}를 사용하면 됩니다. 나중에, +아마도 사용자가 플레이어에 좀 더 많은 통제권을 발휘하고자 하거나 현재 노래에 대한 정보를 얻고자 할 때, 액티비티가 서비스에 바인딩될 수 있습니다. {@link android.content.Context#bindService bindService()}를 사용하면 됩니다. 이런 경우에는 {@link android.content.Context#stopService stopService()} 또는 {@link android.app.Service#stopSelf @@ -702,8 +702,8 @@ stopSelf()}도 클라이언트가 모두 바인딩 해제될 때까지 실제로

      수명 주기 콜백 구현하기

      -

      액티비티와 마찬가지로 서비스에도 수명 주기 콜백 메서드가 있어 이를 구현하면 서비스의 -상태 변경 내용을 모니터링할 수 있고 적절한 시기에 작업을 수행할 수 있습니다. 다음의 골격 +

      액티비티와 마찬가지로 서비스에도 수명 주기 콜백 메서드가 있어 이를 구현하면 서비스의 +상태 변경 내용을 모니터링할 수 있고 적절한 시기에 작업을 수행할 수 있습니다. 다음의 골격 서비스는 각 수명 주기 메서드를 설명한 것입니다.

      @@ -743,13 +743,13 @@ public class ExampleService extends Service {
       }
       
      -

      참고: 액티비티 수명 주기 콜백 메서드와는 달리 이와 같은 콜백 메서드를 구현하는 데에는 +

      참고: 액티비티 수명 주기 콜백 메서드와는 달리 이와 같은 콜백 메서드를 구현하는 데에는 슈퍼클래스 구현을 호출하지 않아도 됩니다.

      -

      그림 2. 서비스 수명 주기입니다. 왼쪽의 다이어그램은 +

      그림 2. 서비스 수명 주기입니다. 왼쪽의 다이어그램은 서비스가 {@link android.content.Context#startService -startService()}로 생성된 경우의 수명 주기를 나타내며 오른쪽의 다이어그램은 서비스가 +startService()}로 생성된 경우의 수명 주기를 나타내며 오른쪽의 다이어그램은 서비스가 {@link android.content.Context#bindService bindService()}로 생성된 경우의 수명 주기를 나타낸 것입니다.

      이와 같은 메서드를 구현함으로써, 서비스 수명 주기의 두 가지 중첩된 루프를 모니터링할 수 있습니다.

      @@ -757,20 +757,20 @@ startService()}로 생성된 경우의 수명 주기를 나타내며 오른쪽
      • 서비스의 수명 주기 전체는 {@link android.app.Service#onCreate onCreate()}가 호출된 시점과 {@link -android.app.Service#onDestroy}가 반환된 시점 사이에 일어납니다. 액티비티와 마찬가지로 서비스는 자신의 초기 설정을 +android.app.Service#onDestroy}가 반환된 시점 사이에 일어납니다. 액티비티와 마찬가지로 서비스는 자신의 초기 설정을 {@link android.app.Service#onCreate onCreate()}에서 수행하며 남은 리소스를 모두 {@link -android.app.Service#onDestroy onDestroy()}에 릴리스합니다. 예를 들어 +android.app.Service#onDestroy onDestroy()}에 릴리스합니다. 예를 들어 음악 재생 서비스의 경우 음악이 재생될 스레드를 {@link android.app.Service#onCreate onCreate()}로 생성하고, 그럼 다음 해당 스레드를 중단할 때에는 {@link android.app.Service#onDestroy onDestroy()}에서 할 수도 있습니다.

        {@link android.app.Service#onCreate onCreate()}와 {@link android.app.Service#onDestroy -onDestroy()} 메서드는 모든 서비스에 대해 호출됩니다. 이는 서비스가 +onDestroy()} 메서드는 모든 서비스에 대해 호출됩니다. 이는 서비스가 {@link android.content.Context#startService startService()}로 생성되었든 {@link android.content.Context#bindService bindService()}로 생성되었든 관계 없이 적용됩니다.

      • 서비스의 활성 수명 주기는 {@link -android.app.Service#onStartCommand onStartCommand()} 또는 {@link android.app.Service#onBind onBind()}로의 호출과 함께 시작됩니다. +android.app.Service#onStartCommand onStartCommand()} 또는 {@link android.app.Service#onBind onBind()}로의 호출과 함께 시작됩니다. 각 메서드에 {@link android.content.Intent}가 전달되는데 이것은 각각 {@link android.content.Context#startService startService()} 또는 {@link android.content.Context#bindService bindService()} 중 하나에 전달된 것입니다. @@ -781,25 +781,25 @@ android.app.Service#onUnbind onUnbind()}가 반환되면 종료됩니다.

      -

      참고: 시작된 서비스를 중단하려면 +

      참고: 시작된 서비스를 중단하려면 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link -android.content.Context#stopService stopService()}를 호출하면 되지만, 서비스에 대한 상응하는 콜백은 -없습니다(즉 {@code onStop()} 콜백이 없습니다). 그러므로, 서비스가 클라이언트에 바인딩되어 있지 않은 한 +android.content.Context#stopService stopService()}를 호출하면 되지만, 서비스에 대한 상응하는 콜백은 +없습니다(즉 {@code onStop()} 콜백이 없습니다). 그러므로, 서비스가 클라이언트에 바인딩되어 있지 않은 한 시스템은 서비스가 중단되면 이를 소멸시킵니다. 수신되는 콜백은 {@link android.app.Service#onDestroy onDestroy()}가 유일합니다.

      -

      그림 2는 서비스에 대한 일반적인 콜백 메서드를 나타낸 것입니다. 이 그림에서는 -{@link android.content.Context#startService startService()}로 생성된 서비스와 -{@link android.content.Context#bindService bindService()}로 생성된 서비스를 +

      그림 2는 서비스에 대한 일반적인 콜백 메서드를 나타낸 것입니다. 이 그림에서는 +{@link android.content.Context#startService startService()}로 생성된 서비스와 +{@link android.content.Context#bindService bindService()}로 생성된 서비스를 구분하고 있지만, 어떤 식으로 시작되었든 모든 서비스는 클라이언트가 자신에 바인딩되도록 허용할 수 있다는 점을 명심하십시오. 말하자면, {@link android.app.Service#onStartCommand -onStartCommand()}로 처음 시작된 서비스(클라이언트가 {@link android.content.Context#startService startService()}를 호출해서)라고 해도 -여전히 {@link android.app.Service#onBind onBind()}로의 호출을 받을 수 있습니다(클라이언트가 +onStartCommand()}로 처음 시작된 서비스(클라이언트가 {@link android.content.Context#startService startService()}를 호출해서)라고 해도 +여전히 {@link android.app.Service#onBind onBind()}로의 호출을 받을 수 있습니다(클라이언트가 {@link android.content.Context#bindService bindService()}를 호출하는 경우).

      바인딩을 제공하는 서비스 생성에 대한 자세한 내용은 바인딩된 서비스 문서를 참조하십시오. 이 안에는 {@link android.app.Service#onRebind onRebind()} -콜백 메서드에 대한 자세한 정보가 바인딩된 서비스의 -수명 주기 관리에 관한 섹션에 +콜백 메서드에 대한 자세한 정보가 바인딩된 서비스의 +수명 주기 관리에 관한 섹션에 담겨 있습니다.

      diff --git a/docs/html-intl/intl/ko/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/ko/guide/components/tasks-and-back-stack.jd index 6b896f9d50ad481b927a4c0c5dd0bac193a56e54..166cedd3a182b1500c87f7c0caaf8216c7f3d254 100644 --- a/docs/html-intl/intl/ko/guide/components/tasks-and-back-stack.jd +++ b/docs/html-intl/intl/ko/guide/components/tasks-and-back-stack.jd @@ -37,23 +37,23 @@ Android식 멀티태스킹 -

      하나의 애플리케이션에는 보통 여러 개의 액티비티가 들어있습니다. 각 액티비티는 -사용자가 수행할 수 있는 특정한 종류의 작업을 중심으로 디자인되어야 하며 다른 액티비티를 +

      하나의 애플리케이션에는 보통 여러 개의 액티비티가 들어있습니다. 각 액티비티는 +사용자가 수행할 수 있는 특정한 종류의 작업을 중심으로 디자인되어야 하며 다른 액티비티를 시작할 수 있는 기능이 있습니다. 예를 들어 이메일 애플리케이션에는 새 메시지 목록을 표시하는 하나의 액티비티가 있을 수 있습니다. 사용자가 메시지를 하나 선택하면, 새 액티비티가 열려 해당 메시지를 볼 수 있게 합니다.

      -

      액티비티는 기기에서 다른 애플리케이션에 존재하는 액티비티를 시작할 수도 있습니다. 예를 들어 -애플리케이션이 이메일 메시지를 보내고자 하는 경우, "전송" 작업을 수행할 인텐트를 -정의하여 이메일 주소와 메시지 등의 몇 가지 데이터를 포함시키면 됩니다. 그러면 다른 애플리케이션에서 가져온 액티비티 중 -이러한 종류의 인텐트를 처리한다고 스스로 선언한 것이 열립니다. 이 경우, 이 인텐트는 -이메일을 전송하기 위한 것이므로 이메일 애플리케이션의 "작성" 액티비티가 시작됩니다(같은 인텐트를 -지원하는 액티비티가 여러 개 있는 경우, 시스템은 사용자에게 어느 것을 사용할지 선택하도록 합니다). 이메일이 전송되면 -액티비티가 재개되고 해당 이메일 액티비티가 애플리케이션의 일부였던 것처럼 보입니다. 액티비티는 -서로 다른 애플리케이션에서 온 것일 수 있지만, Android는 두 액티비티를 +

      액티비티는 기기에서 다른 애플리케이션에 존재하는 액티비티를 시작할 수도 있습니다. 예를 들어 +애플리케이션이 이메일 메시지를 보내고자 하는 경우, "전송" 작업을 수행할 인텐트를 +정의하여 이메일 주소와 메시지 등의 몇 가지 데이터를 포함시키면 됩니다. 그러면 다른 애플리케이션에서 가져온 액티비티 중 +이러한 종류의 인텐트를 처리한다고 스스로 선언한 것이 열립니다. 이 경우, 이 인텐트는 +이메일을 전송하기 위한 것이므로 이메일 애플리케이션의 "작성" 액티비티가 시작됩니다(같은 인텐트를 +지원하는 액티비티가 여러 개 있는 경우, 시스템은 사용자에게 어느 것을 사용할지 선택하도록 합니다). 이메일이 전송되면 +액티비티가 재개되고 해당 이메일 액티비티가 애플리케이션의 일부였던 것처럼 보입니다. 액티비티는 +서로 다른 애플리케이션에서 온 것일 수 있지만, Android는 두 액티비티를 모두 같은 작업 안에 유지하여 이처럼 막힘 없는 사용자 환경을 유지합니다.

      -

      작업이란 액티비티 컬렉션을 일컫는 말로, 사용자가 특정 작업을 수행할 때 이것과 -상호 작용합니다. 액티비티는 스택 안에 정렬되며(백 스택), 이때 +

      작업이란 액티비티 컬렉션을 일컫는 말로, 사용자가 특정 작업을 수행할 때 이것과 +상호 작용합니다. 액티비티는 스택 안에 정렬되며(백 스택), 이때 순서는 각 액티비티가 열린 순서와 같습니다.

      -

      기기 메인 스크린이 대다수 작업의 시작 지점입니다. 사용자가 -애플리케이션 -시작 관리자에 있는 아이콘(또는 메인 스크린의 바로 가기)을 터치하면 해당 애플리케이션의 작업이 전경으로 나옵니다. 해당 애플리케이션에 대한 -작업이 존재하지 않으면(이 애플리케이션을 최근에 사용한 적이 없는 경우), 새 작업이 생성되고 +

      기기 메인 스크린이 대다수 작업의 시작 지점입니다. 사용자가 +애플리케이션 +시작 관리자에 있는 아이콘(또는 메인 스크린의 바로 가기)을 터치하면 해당 애플리케이션의 작업이 전경으로 나옵니다. 해당 애플리케이션에 대한 +작업이 존재하지 않으면(이 애플리케이션을 최근에 사용한 적이 없는 경우), 새 작업이 생성되고 해당 애플리케이션의 "기본" 액티비티가 스택에 있는 루트 액티비티로 열립니다.

      -

      현재 액티비티가 또 다른 액티비티를 시작하는 경우, 새 액티비티가 스택의 맨 위로 밀어올려지고 -사용자의 초점이 이에 맞춰집니다. 이전 액티비티는 스택에 유지되지만, 중단됩니다. 액티비티가 중단되면 -시스템은 이 액티비티의 사용자 인터페이스의 현재 상태를 보존합니다. 사용자가 +

      현재 액티비티가 또 다른 액티비티를 시작하는 경우, 새 액티비티가 스택의 맨 위로 밀어올려지고 +사용자의 초점이 이에 맞춰집니다. 이전 액티비티는 스택에 유지되지만, 중단됩니다. 액티비티가 중단되면 +시스템은 이 액티비티의 사용자 인터페이스의 현재 상태를 보존합니다. 사용자가 뒤로 - 버튼을 누르면, 현재 액티비티가 스택의 맨 위에서 튀어나오고(해당 액티비티는 소멸됩니다) -이전 액티비티가 재개됩니다(이것의 UI 이전 상태가 복원됩니다). 스택에 있는 액티비티는 -결코 다시 정렬되지 않습니다. 다만 스택에서 밀어올려지거나 튀어나올 뿐입니다. 즉, 현재 액티비티에 의해 -시작되면 스택 위로 밀어올려지고, 사용자가 뒤로 버튼을 사용하여 액티비티를 떠나면 튀어나와 사라지는 것입니다. 따라서, -백 스택은 -일종의 "후입선출" 객체 구조로서 작동한다고 할 수 있습니다. 그림 1은 -이 행동을 시간 표시 막대와 함께 표시하여 여러 액티비티 사이의 진행률을 보여주며, + 버튼을 누르면, 현재 액티비티가 스택의 맨 위에서 튀어나오고(해당 액티비티는 소멸됩니다) +이전 액티비티가 재개됩니다(이것의 UI 이전 상태가 복원됩니다). 스택에 있는 액티비티는 +결코 다시 정렬되지 않습니다. 다만 스택에서 밀어올려지거나 튀어나올 뿐입니다. 즉, 현재 액티비티에 의해 +시작되면 스택 위로 밀어올려지고, 사용자가 뒤로 버튼을 사용하여 액티비티를 떠나면 튀어나와 사라지는 것입니다. 따라서, +백 스택은 +일종의 "후입선출" 객체 구조로서 작동한다고 할 수 있습니다. 그림 1은 +이 행동을 시간 표시 막대와 함께 표시하여 여러 액티비티 사이의 진행률을 보여주며, 각 시점에서 현재 백 스택의 모습을 나타낸 것입니다.

      -

      그림 1. 작업에 있는 각각의 새 액티비티가 백 스택에 항목을 추가하는 -방법을 나타낸 것입니다. 사용자가 뒤로 버튼을 누르면 현재 -액티비티가 +

      그림 1. 작업에 있는 각각의 새 액티비티가 백 스택에 항목을 추가하는 +방법을 나타낸 것입니다. 사용자가 뒤로 버튼을 누르면 현재 +액티비티가 소멸되고 이전 액티비티가 재개됩니다.

      -

      사용자가 계속해서 뒤로 버튼을 누르면, 스택에 있는 각 액티비티가 하나씩 튀어나가 -이전 것을 -드러내고, 마침내는 사용자가 메인 스크린으로 되돌아가게 됩니다(아니면 작업이 시작되었을 때 +

      사용자가 계속해서 뒤로 버튼을 누르면, 스택에 있는 각 액티비티가 하나씩 튀어나가 +이전 것을 +드러내고, 마침내는 사용자가 메인 스크린으로 되돌아가게 됩니다(아니면 작업이 시작되었을 때 실행 중이던 액티비티가 무엇이든 그것으로 되돌아갑니다). 스택에서 모든 액티비티가 제거되면 이 작업은 더 이상 존재하지 않게 됩니다.

      그림 2. 두 개의 작업: 작업 B가 전경에서 사용자 상호 작용을 수신하는 한편, +class="img-caption">그림 2. 두 개의 작업: 작업 B가 전경에서 사용자 상호 작용을 수신하는 한편, 작업 A는 배경에서 재개되기를 기다립니다.

      @@ -118,39 +118,39 @@ class="img-caption">그림 2. 두 개의 작업: 작업 B가 class="img-caption">그림 3. 하나의 액티비티가 여러 번 인스턴트화됩니다.

      -

      작업이란 하나의 잘 짜여진 단위로 사용자가 새 작업을 시작할 때 "배경"으로 이동할 수도 있고 - 버튼을 통해 메인 스크린으로 이동할 수도 있습니다. 작업의 모든 액티비티는 배경에 있는 동안은 +

      작업이란 하나의 잘 짜여진 단위로 사용자가 새 작업을 시작할 때 "배경"으로 이동할 수도 있고 + 버튼을 통해 메인 스크린으로 이동할 수도 있습니다. 작업의 모든 액티비티는 배경에 있는 동안은 중단되지만 -, 해당 작업에 대한 백 스택은 그대로 변함 없이 유지됩니다. 이 작업은 또 다른 작업이 발생하는 동안 -초점을 잃을 뿐입니다(그림 2 참조). 그런 다음 작업이 "전경"으로 되돌아와 사용자가 -이전에 하던 일을 계속할 수 있습니다. 예를 들어 현재 작업(작업 A)의 스택에 세 개의 액티비티가 있다고 +, 해당 작업에 대한 백 스택은 그대로 변함 없이 유지됩니다. 이 작업은 또 다른 작업이 발생하는 동안 +초점을 잃을 뿐입니다(그림 2 참조). 그런 다음 작업이 "전경"으로 되돌아와 사용자가 +이전에 하던 일을 계속할 수 있습니다. 예를 들어 현재 작업(작업 A)의 스택에 세 개의 액티비티가 있다고 가정하면 그 중 둘은 현재 액티비티 아래에 있습니다. 사용자가 - 버튼을 누른 다음 -애플리케이션 시작 관리자로부터 새 애플리케이션을 시작합니다. 메인 스크린이 나타나면 작업 A는 + 버튼을 누른 다음 +애플리케이션 시작 관리자로부터 새 애플리케이션을 시작합니다. 메인 스크린이 나타나면 작업 A는 배경으로 이동합니다. 새 애플리케이션이 시작되면 시스템은 해당 애플리케이션에 대한 작업을 시작하며 -(작업 B) 여기에는 나름의 액티비티 스택이 딸려 있습니다. 해당 애플리케이션과 -상호 작용한 후, 사용자는 다시 홈으로 돌아와 원래 작업 A를 시작한 +(작업 B) 여기에는 나름의 액티비티 스택이 딸려 있습니다. 해당 애플리케이션과 +상호 작용한 후, 사용자는 다시 홈으로 돌아와 원래 작업 A를 시작한 애플리케이션을 선택합니다. 이제 작업 A가 전경으로 옵니다. -이 스택에 있는 액티비티 세 개는 모두 멀쩡하고, 스택 맨 위에 있는 액티비티가 -재개됩니다. 이 시점에서 -사용자는 작업 B로 도로 전환할 수도 있습니다. 홈으로 이동하여 해당 작업을 -시작한 애플리케이션 아이콘을 선택하면 됩니다(아니면 -개요 화면에서 해당 앱의 작업을 선택해도 됩니다). +이 스택에 있는 액티비티 세 개는 모두 멀쩡하고, 스택 맨 위에 있는 액티비티가 +재개됩니다. 이 시점에서 +사용자는 작업 B로 도로 전환할 수도 있습니다. 홈으로 이동하여 해당 작업을 +시작한 애플리케이션 아이콘을 선택하면 됩니다(아니면 +개요 화면에서 해당 앱의 작업을 선택해도 됩니다). 이것이 Android에서 멀티태스킹을 하는 작업의 예시입니다.

      -

      참고: 여러 개의 작업을 배경에 한꺼번에 대기시킬 수 있습니다. -하지만, 사용자가 수많은 배경 작업을 동시에 실행하면 시스템이 메모리를 복원하기 위해 -배경 액티비티를 소멸시키기 시작할 수 있고, 그러면 액티비티 상태가 손실됩니다. +

      참고: 여러 개의 작업을 배경에 한꺼번에 대기시킬 수 있습니다. +하지만, 사용자가 수많은 배경 작업을 동시에 실행하면 시스템이 메모리를 복원하기 위해 +배경 액티비티를 소멸시키기 시작할 수 있고, 그러면 액티비티 상태가 손실됩니다. 다음의 액티비티 상태에 관한 섹션을 참조하십시오.

      -

      백 스택에 있는 액티비티는 결코 다시 정렬되지 않으므로, 애플리케이션에서 -사용자에게 하나 이상의 액티비티로부터 특정 액티비티를 시작하도록 허용하는 경우, 해당 액티비티의 새 인스턴스가 -생성되어 스택 위로 밀려옵니다(해당 액티비티의 기존 인스턴스를 -맨 위로 가져오는 대신). 따라서, 애플리케이션 안의 한 액티비티가 여러 번 -인스턴트화될 수 있으며(서로 다른 작업으로부터도 가능), 이를 나타낸 것이 그림 3입니다. 이 때문에 사용자가 +

      백 스택에 있는 액티비티는 결코 다시 정렬되지 않으므로, 애플리케이션에서 +사용자에게 하나 이상의 액티비티로부터 특정 액티비티를 시작하도록 허용하는 경우, 해당 액티비티의 새 인스턴스가 +생성되어 스택 위로 밀려옵니다(해당 액티비티의 기존 인스턴스를 +맨 위로 가져오는 대신). 따라서, 애플리케이션 안의 한 액티비티가 여러 번 +인스턴트화될 수 있으며(서로 다른 작업으로부터도 가능), 이를 나타낸 것이 그림 3입니다. 이 때문에 사용자가 뒤로 버튼을 사용하여 뒤로 이동하는 경우, 액티비티의 각 인스턴스가 열린 순서대로 드러납니다 -(각자 나름의 -UI 상태를 가지고). 다만, 액티비티가 한 번 이상 인스턴트화되는 것을 원치 않으면 이 행동은 수정할 수 +(각자 나름의 +UI 상태를 가지고). 다만, 액티비티가 한 번 이상 인스턴트화되는 것을 원치 않으면 이 행동은 수정할 수 있습니다. 그 방법에 대해서는 작업 관리하기에 관한 이후 섹션에서 이야기합니다.

      @@ -159,16 +159,16 @@ UI 상태를 가지고). 다만, 액티비티가 한 번 이상 인스턴트화
      • 액티비티 A가 액티비티 B를 시작하면 액티비티 A는 중단되지만, 시스템이 그 상태를 (예: 스크롤 위치 및 양식에 입력된 텍스트 등) 보존합니다. -사용자가 액티비티 B에 있는 동안 뒤로 버튼을 누르면 액티비티 A가 재개되며 상태도 +사용자가 액티비티 B에 있는 동안 뒤로 버튼을 누르면 액티비티 A가 재개되며 상태도 복원됩니다.
      • -
      • 사용자가 버튼을 눌러 작업을 떠나면 현재 액티비티가 -중단되고 -그 소속 작업이 배경으로 들어갑니다. 시스템은 작업에 속한 모든 액티비티의 상태를 보존합니다. 사용자가 -나중에 작업을 시작한 시작 관리자 아이콘을 선택하여 해당 작업을 재개하면, 그 작업이 +
      • 사용자가 버튼을 눌러 작업을 떠나면 현재 액티비티가 +중단되고 +그 소속 작업이 배경으로 들어갑니다. 시스템은 작업에 속한 모든 액티비티의 상태를 보존합니다. 사용자가 +나중에 작업을 시작한 시작 관리자 아이콘을 선택하여 해당 작업을 재개하면, 그 작업이 전경으로 나오고 스택 맨 위에서 액티비티를 재개합니다.
      • -
      • 사용자가 뒤로 버튼을 누르면, 현재 액티비티가 스택에서 튀어나오고 +
      • 사용자가 뒤로 버튼을 누르면, 현재 액티비티가 스택에서 튀어나오고 소멸됩니다. - 스택에 있던 이전 액티비티가 재개됩니다. 액티비티가 소멸되면, 시스템은 그 액티비티의 상태를 + 스택에 있던 이전 액티비티가 재개됩니다. 액티비티가 소멸되면, 시스템은 그 액티비티의 상태를 보존하지 않습니다.
      • 액티비티는 여러 번 인스턴트화할 수 있으며, 다른 작업에서도 이를 수행할 수 있습니다.
      @@ -182,20 +182,20 @@ UI 상태를 가지고). 다만, 액티비티가 한 번 이상 인스턴트화

      액티비티 상태 저장하기

      -

      위에서 논한 바와 같이, 시스템의 기본 행동은 액티비티가 중단되면 그 상태를 보존해두는 -것입니다. 이렇게 하면, 사용자가 이전 액티비티로 도로 이동했을 때 그에 속한 사용자 인터페이스가 이전 상태 +

      위에서 논한 바와 같이, 시스템의 기본 행동은 액티비티가 중단되면 그 상태를 보존해두는 +것입니다. 이렇게 하면, 사용자가 이전 액티비티로 도로 이동했을 때 그에 속한 사용자 인터페이스가 이전 상태 그대로 표시됩니다. 그러나 액티비티의 상태를 미리 보존할 수도 있으며 사전에 이렇게 해야 합니다. -이때에는, 액티비티가 소멸되고 다시 만들어야 하는 경우를 대비해 +이때에는, 액티비티가 소멸되고 다시 만들어야 하는 경우를 대비해 콜백 메서드를 사용합니다.

      -

      시스템이 액티비티 중 하나를 중단시키는 경우(예를 들어 새 액티비티가 시작되었을 때 또는 작업이 -배경으로 이동하는 경우), 시스템은 시스템 메모리를 회복해야 하는 경우 액티비티를 -완전히 소멸시켜버릴 수도 있습니다. 이런 상황이 벌어지면, 액티비티 상태에 대한 정보는 손실됩니다. 이런 일이 벌어지더라도, -시스템은 여전히 -백 스택에 해당 액티비티의 자리가 있다는 것을 알고 있습니다. 다만 액티비티가 스택 맨 위로 올라오면 -시스템이 이를 (재개하는 것이 아니라) 재생성해야만 합니다. 사용자의 작업 내용을 -잃어버리는 불상사를 피하려면 그 내용을 미리 보존해두어야 합니다. 이때 액티비티의 -{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} 콜백 +

      시스템이 액티비티 중 하나를 중단시키는 경우(예를 들어 새 액티비티가 시작되었을 때 또는 작업이 +배경으로 이동하는 경우), 시스템은 시스템 메모리를 회복해야 하는 경우 액티비티를 +완전히 소멸시켜버릴 수도 있습니다. 이런 상황이 벌어지면, 액티비티 상태에 대한 정보는 손실됩니다. 이런 일이 벌어지더라도, +시스템은 여전히 +백 스택에 해당 액티비티의 자리가 있다는 것을 알고 있습니다. 다만 액티비티가 스택 맨 위로 올라오면 +시스템이 이를 (재개하는 것이 아니라) 재생성해야만 합니다. 사용자의 작업 내용을 +잃어버리는 불상사를 피하려면 그 내용을 미리 보존해두어야 합니다. 이때 액티비티의 +{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} 콜백 메서드를 구현하는 방법을 씁니다.

      액티비티 상태를 저장하는 방법에 대한 자세한 정보는 액티비티 @@ -205,19 +205,19 @@ UI 상태를 가지고). 다만, 액티비티가 한 번 이상 인스턴트화

      작업 관리하기

      -

      Android가 작업과 백 스택을 관리하는 방식은 위에 설명된 바와 같고—같은 작업 안에서 -연이어 시작된 모든 작업을 한곳에 배치하되 "후입선출" 스택에 두는 것—이 방식은 -대부분의 애플리케이션에 아주 효과적입니다. 여러분은 액티비티가 작업과 연관된 방식이나 -백 스택에서의 존재 방식에 대해 염려하지 않아도 됩니다. 그러나, 정상적인 동작을 인터럽트하기로 결정할 수도 -있습니다. 애플리케이션의 액티비티 하나가 시작되면 새 작업을 시작하려 -할 수도 있습니다(현재 작업 내에 배치되는 것 대신에). 아니면, 액티비티를 시작하면 그것의 -기존 인스턴스 하나를 앞으로 가져오고자 할 수도 있습니다(백 스택 맨 위에서 새 인스턴스를 -생성하는 것 대신에). 또는 백 스택에서 사용자가 작업을 떠날 때의 루트 액티비티를 제외하고 +

      Android가 작업과 백 스택을 관리하는 방식은 위에 설명된 바와 같고—같은 작업 안에서 +연이어 시작된 모든 작업을 한곳에 배치하되 "후입선출" 스택에 두는 것—이 방식은 +대부분의 애플리케이션에 아주 효과적입니다. 여러분은 액티비티가 작업과 연관된 방식이나 +백 스택에서의 존재 방식에 대해 염려하지 않아도 됩니다. 그러나, 정상적인 동작을 인터럽트하기로 결정할 수도 +있습니다. 애플리케이션의 액티비티 하나가 시작되면 새 작업을 시작하려 +할 수도 있습니다(현재 작업 내에 배치되는 것 대신에). 아니면, 액티비티를 시작하면 그것의 +기존 인스턴스 하나를 앞으로 가져오고자 할 수도 있습니다(백 스택 맨 위에서 새 인스턴스를 +생성하는 것 대신에). 또는 백 스택에서 사용자가 작업을 떠날 때의 루트 액티비티를 제외하고 모든 액티비티를 지우고자 할 수도 있습니다.

      -

      이 모든 것과 그 외에도 많은 것을 할 수 있는 것이 바로 +

      이 모든 것과 그 외에도 많은 것을 할 수 있는 것이 바로 {@code <activity>} -매니페스트 요소 안에 있는 속성과, +매니페스트 요소 안에 있는 속성과, {@link android.app.Activity#startActivity startActivity()}에 전달한 인텐트에 있는 플래그입니다.

      이런 면에서, 여러분이 사용할 수 있는 주요 @@ -246,170 +246,170 @@ UI 상태를 가지고). 다만, 액티비티가 한 번 이상 인스턴트화

    • {@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}
    -

    다음 섹션에서는 이와 같은 매니페스트 속성과 인텐트 플래그를 사용하여 +

    다음 섹션에서는 이와 같은 매니페스트 속성과 인텐트 플래그를 사용하여 액티비티가 작업과 연관되는 방식을 정의하고 백 스택에서 액티비티가 동작하는 방식을 정의하는 방법을 배우게 됩니다.

    -

    이외에도 별도로 작업과 액티비티를 표시하는 방법에 대한 고려 사항과 -개요 화면에서의 관리 방법을 논합니다. 자세한 정보는 개요 화면을 -참조하십시오. 보통은 개요 화면에 작업과 액티비티가 어떻게 표현될지는 +

    이외에도 별도로 작업과 액티비티를 표시하는 방법에 대한 고려 사항과 +개요 화면에서의 관리 방법을 논합니다. 자세한 정보는 개요 화면을 +참조하십시오. 보통은 개요 화면에 작업과 액티비티가 어떻게 표현될지는 시스템이 정의하도록 두어야 합니다. 이 동작을 개발자가 수정할 필요도 없습니다.

    -

    주의: 대부분의 애플리케이션은 액티비티와 작업에 대한 -기본 동작을 인터럽트하지 않는 것이 정상입니다. 액티비티가 기본 동작을 수정하는 것이 필요하다는 -판단이 서면, 시작 과정 중에 액티비티의 유용성을 테스트하십시오. +

    주의: 대부분의 애플리케이션은 액티비티와 작업에 대한 +기본 동작을 인터럽트하지 않는 것이 정상입니다. 액티비티가 기본 동작을 수정하는 것이 필요하다는 +판단이 서면, 시작 과정 중에 액티비티의 유용성을 테스트하십시오. 또한 다른 액티비티와 작업에서 뒤로 버튼을 써서 해당 액티비티로 돌아올 때에도 유용성을 테스트해야 합니다. 사용자의 예상되는 동작과 충돌할 가능성이 있는 탐색 동작을 꼭 테스트하십시오.

    시작 모드 정의하기

    -

    시작 모드를 사용하면 액티비티의 새 인스턴스가 현재 작업과 연관된 방식을 정의할 수 있게 +

    시작 모드를 사용하면 액티비티의 새 인스턴스가 현재 작업과 연관된 방식을 정의할 수 있게 해줍니다. 여러 가지 시작 모드를 두 가지 방식으로 정의할 수 있습니다.

    • 매니페스트 파일 사용하기 -

      매니페스트 파일에서 액티비티를 선언하는 경우, 액티비티가 시작될 때 여러 작업과 어떤 식으로 +

      매니페스트 파일에서 액티비티를 선언하는 경우, 액티비티가 시작될 때 여러 작업과 어떤 식으로 연관을 맺어야 하는지 지정할 수 있습니다.

    • 인텐트 플래그 사용하기 -

      {@link android.app.Activity#startActivity startActivity()}를 호출하는 경우 -{@link android.content.Intent}에 플래그를 포함시켜 새 액티비티가 현재 작업과 어떻게 연관되어야 할지(또는 +

      {@link android.app.Activity#startActivity startActivity()}를 호출하는 경우 +{@link android.content.Intent}에 플래그를 포함시켜 새 액티비티가 현재 작업과 어떻게 연관되어야 할지(또는 애초에 연관을 맺을지 아닐지) 선언하도록 할 수 있습니다.

    -

    따라서, 액티비티 A가 액티비티 B를 시작하면 액티비티 B는 자신의 매니페스트에서 -현재 작업과 연관을 맺는 데 적당한 방식(연관을 맺어야 한다면)을 정의할 수 있고 액티비티 A 또한 -액티비티 B가 현재 작업과 연관을 맺는 방식을 요청할 수 있습니다. 두 액티비티가 모두 액티비티 B가 작업과 -연관되는 방식을 정의하는 경우, 액티비티 A의 요청(인텐트에 정의된 바를 따름)을 액티비티 B의 +

    따라서, 액티비티 A가 액티비티 B를 시작하면 액티비티 B는 자신의 매니페스트에서 +현재 작업과 연관을 맺는 데 적당한 방식(연관을 맺어야 한다면)을 정의할 수 있고 액티비티 A 또한 +액티비티 B가 현재 작업과 연관을 맺는 방식을 요청할 수 있습니다. 두 액티비티가 모두 액티비티 B가 작업과 +연관되는 방식을 정의하는 경우, 액티비티 A의 요청(인텐트에 정의된 바를 따름)을 액티비티 B의 요청(자신의 매니페스트에서 정의)보다 우위로 인식합니다.

    -

    참고: 매니페스트 파일에 사용할 수 있는 시작 모드 중에는 -인텐트의 플래그로 사용할 수는 없는 것도 있으며, 이와 마찬 가지로 인텐트의 플래그로 사용할 수 있는 시작 모드 중에는 +

    참고: 매니페스트 파일에 사용할 수 있는 시작 모드 중에는 +인텐트의 플래그로 사용할 수는 없는 것도 있으며, 이와 마찬 가지로 인텐트의 플래그로 사용할 수 있는 시작 모드 중에는 매니페스트에서 정의할 수 없는 것도 있습니다.

    매니페스트 파일 사용하기

    -

    매니페스트 파일에서 액티비티를 선언하는 경우, 액티비티가 작업과 +

    매니페스트 파일에서 액티비티를 선언하는 경우, 액티비티가 작업과 어떤 식으로 연관되어야 할지 지정하려면 {@code <activity>} 요소의 {@code launchMode} 속성을 사용하면 됩니다.

    {@code -launchMode} 속성은 액티비티가 작업 안으로 들어가며 시작되는 방법에 대한 지침을 -나타냅니다. +launchMode} 속성은 액티비티가 작업 안으로 들어가며 시작되는 방법에 대한 지침을 +나타냅니다. launchMode 속성에 할당할 수 있는 시작 모드는 네 가지가 있습니다.

    {@code "standard"} (기본 모드)
    -
    기본입니다. 시스템이 액티비티가 시작된 작업에서 액티비티의 새 인스턴스를 만들고 -인텐트의 경로를 이것으로 지정합니다. 액티비티는 여러 번 인스턴트화될 수 있고, +
    기본입니다. 시스템이 액티비티가 시작된 작업에서 액티비티의 새 인스턴스를 만들고 +인텐트의 경로를 이것으로 지정합니다. 액티비티는 여러 번 인스턴트화될 수 있고, 각 인스턴스는 서로 다른 작업에 속할 수 있으며 한 작업에 여러 개의 인스턴스가 있을 수 있습니다.
    {@code "singleTop"}
    -
    액티비티의 인스턴스가 이미 현재 작업의 맨 위에 존재하는 경우, 시스템은 인텐트의 경로를 +
    액티비티의 인스턴스가 이미 현재 작업의 맨 위에 존재하는 경우, 시스템은 인텐트의 경로를 해당 인스턴스로 지정합니다. 이때 액티비티의 새 인스턴스를 만들기보다는 해당 인스턴스의 {@link -android.app.Activity#onNewIntent onNewIntent()} 메서드를 호출하는 방법을 -통합니다. 액티비티는 여러 번 인스턴트화될 수 있고, 각 인스턴스는 서로 다른 작업에 -속할 수 있으며 한 작업에 여러 개의 인스턴스가 있을 수 있습니다(다만 백 스택의 맨 위에 있는 +android.app.Activity#onNewIntent onNewIntent()} 메서드를 호출하는 방법을 +통합니다. 액티비티는 여러 번 인스턴트화될 수 있고, 각 인스턴스는 서로 다른 작업에 +속할 수 있으며 한 작업에 여러 개의 인스턴스가 있을 수 있습니다(다만 백 스택의 맨 위에 있는 액티비티가 액티비티의 기존 인스턴스가 아닌 경우에만 이것이 적용됩니다). -

    예를 들어 어느 작업의 백 스택이 루트 액티비티 A와 액티비티 B, C, 그리고 맨 위의 액티비티 D로 +

    예를 들어 어느 작업의 백 스택이 루트 액티비티 A와 액티비티 B, C, 그리고 맨 위의 액티비티 D로 구성되어 있다고 가정합니다(이 스택은 A-B-C-D 형태를 띠며 D가 맨 위에 있습니다). 유형 D의 액티비티에 대한 인텐트가 도착합니다. -D에 기본 {@code "standard"} 시작 모드가 있는 경우, 클래스의 새 인스턴스가 시작되고 이 스택은 -A-B-C-D-D가 됩니다. 하지만, D의 시작 모드가 {@code "singleTop"}인 경우, D의 +D에 기본 {@code "standard"} 시작 모드가 있는 경우, 클래스의 새 인스턴스가 시작되고 이 스택은 +A-B-C-D-D가 됩니다. 하지만, D의 시작 모드가 {@code "singleTop"}인 경우, D의 기존 인스턴스가 해당 인텐트를 {@link -android.app.Activity#onNewIntent onNewIntent()}를 통해 받게 됩니다. 이것이 스택의 맨 위에 있기 때문입니다. 스택은 -계속 A-B-C-D로 유지됩니다. 그러나 유형 B의 액티비티에 대한 인텐트가 도착하는 경우, +android.app.Activity#onNewIntent onNewIntent()}를 통해 받게 됩니다. 이것이 스택의 맨 위에 있기 때문입니다. 스택은 +계속 A-B-C-D로 유지됩니다. 그러나 유형 B의 액티비티에 대한 인텐트가 도착하는 경우, B의 새 인스턴스가 스택에 추가되며 이는 액티비티의 시작 모드가 {@code "singleTop"}이더라도 무관하게 적용됩니다.

    -

    참고: 어느 액티비티의 새 인스턴스가 생성되면, -사용자가 뒤로 버튼을 눌러 이전 액티비티로 되돌아갈 수 있게 됩니다. 그러나 액티비티의 기존 -인스턴스가 +

    참고: 어느 액티비티의 새 인스턴스가 생성되면, +사용자가 뒤로 버튼을 눌러 이전 액티비티로 되돌아갈 수 있게 됩니다. 그러나 액티비티의 기존 +인스턴스가 새 인텐트를 처리하는 경우, 사용자가 뒤로 버튼을 눌러도 새 인텐트가 {@link android.app.Activity#onNewIntent -onNewIntent()}에 도착하기 전의 액티비티 -상태로 +onNewIntent()}에 도착하기 전의 액티비티 +상태로 되돌아갈 수 없습니다.

    {@code "singleTask"}
    시스템이 새 작업을 만들고 새 작업의 루트에 있는 액티비티를 인스턴트화합니다. -하지만, 액티비티의 인스턴스가 이미 별개의 작업에 존재하는 경우, 시스템은 인텐트의 경로를 +하지만, 액티비티의 인스턴스가 이미 별개의 작업에 존재하는 경우, 시스템은 인텐트의 경로를 기존 인스턴스로 지정합니다. 이때 새 인스턴스를 만들기보다 해당 인스턴스의 {@link -android.app.Activity#onNewIntent onNewIntent()} 메서드를 호출하는 방법을 통합니다. 한 번에 +android.app.Activity#onNewIntent onNewIntent()} 메서드를 호출하는 방법을 통합니다. 한 번에 액티비티 인스턴스 한 개씩만 존재할 수 있습니다. -

    참고: 액티비티가 새 작업에서 시작되더라도, +

    참고: 액티비티가 새 작업에서 시작되더라도, 뒤로 버튼을 누르면 여전히 사용자를 이전 액티비티로 돌려보냅니다.

    {@code "singleInstance"}.
    -
    {@code "singleTask"}와 같습니다. 다만 시스템이 인스턴스를 보유하고 있는 작업 안으로 -다른 어떤 액티비티도 시작하지 않는다는 것은 예외입니다. 액티비티는 언제나 자신의 작업의 유일무이한 구성원입니다. +
    {@code "singleTask"}와 같습니다. 다만 시스템이 인스턴스를 보유하고 있는 작업 안으로 +다른 어떤 액티비티도 시작하지 않는다는 것은 예외입니다. 액티비티는 언제나 자신의 작업의 유일무이한 구성원입니다. 이것으로 시작한 액티비티는 모두 별개의 작업에서 열립니다.
    -

    또 다른 예로 Android 브라우저 애플리케이션이 있습니다. 이것은 웹 브라우저 액티비티가 항상 -자신만의 작업에서 열려야 한다고 선언합니다. 이때 {@code <activity>} 요소에 {@code singleTask} 시작 모드를 지정하는 방법을 씁니다. -다시 말해 애플리케이션이 Android 브라우저를 열라는 인텐트를 발행하면 -브라우저의 액티비티가 애플리케이션과 같은 작업에 배치되지 않는다는 -뜻입니다. 그 대신, 브라우저에 대한 새 작업이 시작되거나, 브라우저에 이미 -배경에서 실행 중인 작업이 있는 경우 해당 작업이 전경으로 불려나와 새 인텐트를 처리하게 +

    또 다른 예로 Android 브라우저 애플리케이션이 있습니다. 이것은 웹 브라우저 액티비티가 항상 +자신만의 작업에서 열려야 한다고 선언합니다. 이때 {@code <activity>} 요소에 {@code singleTask} 시작 모드를 지정하는 방법을 씁니다. +다시 말해 애플리케이션이 Android 브라우저를 열라는 인텐트를 발행하면 +브라우저의 액티비티가 애플리케이션과 같은 작업에 배치되지 않는다는 +뜻입니다. 그 대신, 브라우저에 대한 새 작업이 시작되거나, 브라우저에 이미 +배경에서 실행 중인 작업이 있는 경우 해당 작업이 전경으로 불려나와 새 인텐트를 처리하게 됩니다.

    -

    액티비티가 새 작업에서 시작되었든 액티비티를 시작한 것과 같은 작업에서 시작되었든 관계 없이 -뒤로 버튼을 사용하면 언제나 사용자를 이전 액티비티로 돌려보냅니다. 다만, -{@code singleTask} 시작 모드를 나타내는 액티비티를 시작한 다음 해당 -액티비티의 인스턴스가 이미 배경 작업에 존재하는 경우, 그 작업 전체가 전경에 불려나옵니다. 이 시점에서 -백 스택에는 이제 앞으로 가져온 작업에서 가져온 모든 액티비티가 포함되어 있으며, 이는 스택의 +

    액티비티가 새 작업에서 시작되었든 액티비티를 시작한 것과 같은 작업에서 시작되었든 관계 없이 +뒤로 버튼을 사용하면 언제나 사용자를 이전 액티비티로 돌려보냅니다. 다만, +{@code singleTask} 시작 모드를 나타내는 액티비티를 시작한 다음 해당 +액티비티의 인스턴스가 이미 배경 작업에 존재하는 경우, 그 작업 전체가 전경에 불려나옵니다. 이 시점에서 +백 스택에는 이제 앞으로 가져온 작업에서 가져온 모든 액티비티가 포함되어 있으며, 이는 스택의 맨 위에 위치합니다. 그림 4는 이와 같은 유형의 시나리오를 나타낸 것입니다.

    -

    그림 4. 시작 모드가 "singleTask"인 액티비티가 -백 스택에 추가되는 방법을 표현한 것입니다. 이 액티비티가 이미 자신의 백 스택을 가지고 있는 -배경 작업의 일부인 경우, 해당 백 스택도 모두 전경으로 +

    그림 4. 시작 모드가 "singleTask"인 액티비티가 +백 스택에 추가되는 방법을 표현한 것입니다. 이 액티비티가 이미 자신의 백 스택을 가지고 있는 +배경 작업의 일부인 경우, 해당 백 스택도 모두 전경으로 불려나오며, 이는 현재 작업 위에 배치됩니다.

    -

    매니페스트 파일에서 시작 모드를 사용하는 것에 대한 자세한 정보는 +

    매니페스트 파일에서 시작 모드를 사용하는 것에 대한 자세한 정보는 <activity> -요소 문서를 참조하십시오. 여기에서 {@code launchMode} 속성과 허용된 값을 더 자세히 +요소 문서를 참조하십시오. 여기에서 {@code launchMode} 속성과 허용된 값을 더 자세히 논합니다.

    -

    참고: 액티비티에 대하여 {@code launchMode} 속성으로 지정한 동작을 -재정의하려면 액티비티를 시작한 인텐트에 포함된 플래그를 사용하면 됩니다. 이 내용은 +

    참고: 액티비티에 대하여 {@code launchMode} 속성으로 지정한 동작을 +재정의하려면 액티비티를 시작한 인텐트에 포함된 플래그를 사용하면 됩니다. 이 내용은 다음 섹션에서 논합니다.

    인텐트 플래그 사용하기

    -

    액티비티를 시작할 때면, 액티비티가 자신의 작업과 연관되는 기본 방식을 수정할 수 있습니다. +

    액티비티를 시작할 때면, 액티비티가 자신의 작업과 연관되는 기본 방식을 수정할 수 있습니다. {@link -android.app.Activity#startActivity startActivity()}에 전달한 인텐트 안에 있는 플래그를 포함시키면 됩니다. 기본 동작을 수정하는 데 사용할 수 있는 +android.app.Activity#startActivity startActivity()}에 전달한 인텐트 안에 있는 플래그를 포함시키면 됩니다. 기본 동작을 수정하는 데 사용할 수 있는 플래그는 다음과 같습니다.

    {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
    -
    액티비티를 새 작업에서 시작합니다. 지금 시작하고 있는 액티비티에 대해 이미 실행 중인 작업이 있으면, -해당 작업의 마지막 상태를 복원하여 전경으로 불려나오고 액티비티는 새 인텐트를 +
    액티비티를 새 작업에서 시작합니다. 지금 시작하고 있는 액티비티에 대해 이미 실행 중인 작업이 있으면, +해당 작업의 마지막 상태를 복원하여 전경으로 불려나오고 액티비티는 새 인텐트를 {@link android.app.Activity#onNewIntent onNewIntent()}에서 수신합니다. -

    이렇게 하면 {@code "singleTask"} {@code launchMode} 값에서와 같은 동작을 발생시키며, +

    이렇게 하면 {@code "singleTask"} {@code launchMode} 값에서와 같은 동작을 발생시키며, 이는 이전 섹션에서 논한 것과 같습니다.

    {@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}
    -
    시작되고 있는 액티비티가 현재 액티비티인 경우(백 스택 맨 위에 있는), 해당 액티비티의 새 인스턴스를 생성하는 대신 기존 -인스턴스가 {@link android.app.Activity#onNewIntent onNewIntent()}에 +
    시작되고 있는 액티비티가 현재 액티비티인 경우(백 스택 맨 위에 있는), 해당 액티비티의 새 인스턴스를 생성하는 대신 기존 +인스턴스가 {@link android.app.Activity#onNewIntent onNewIntent()}에 대한 호출을 받습니다. -

    이렇게 하면 {@code "singleTop"} {@code launchMode} 값에서와 같은 동작을 발생시키며, +

    이렇게 하면 {@code "singleTop"} {@code launchMode} 값에서와 같은 동작을 발생시키며, 이는 이전 섹션에서 논한 것과 같습니다.

    {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}
    -
    시작되고 있는 액티비티가 이미 현재 작업에서 실행 중인 경우, 해당 액티비티의 -새 인스턴스를 시작하는 대신 그 위에 있는 모든 다른 액티비티가 -소멸되고 이 인텐트는 해당 액티비티(이제 맨 위로 올라옴)의 재개된 인스턴스로, +
    시작되고 있는 액티비티가 이미 현재 작업에서 실행 중인 경우, 해당 액티비티의 +새 인스턴스를 시작하는 대신 그 위에 있는 모든 다른 액티비티가 +소멸되고 이 인텐트는 해당 액티비티(이제 맨 위로 올라옴)의 재개된 인스턴스로, {@link android.app.Activity#onNewIntent onNewIntent()}를 통해 전달됩니다.

    이 동작을 발생시키는 {@code launchMode} 속성에 대한 값은 없습니다.

    -

    {@code FLAG_ACTIVITY_CLEAR_TOP}는 -{@code FLAG_ACTIVITY_NEW_TASK}와 함께 쓰이는 경우가 가장 보편적입니다. -이들 플래그를 함께 사용하면 다른 작업에 있는 기존 액티비티의 위치를 +

    {@code FLAG_ACTIVITY_CLEAR_TOP}는 +{@code FLAG_ACTIVITY_NEW_TASK}와 함께 쓰이는 경우가 가장 보편적입니다. +이들 플래그를 함께 사용하면 다른 작업에 있는 기존 액티비티의 위치를 찾아 이를 인텐트에 응답할 수 있는 위치에 놓을 한 가지 방편이 됩니다.

    -

    참고: 지정된 액티비티의 시작 모드가 -{@code "standard"}인 경우, -이것 또한 스택에서 제거되고 그 자리에 새 인스턴스가 대신 생성되어 수신되는 인텐트를 -처리하게 됩니다. 이는 시작 모드가 +

    참고: 지정된 액티비티의 시작 모드가 +{@code "standard"}인 경우, +이것 또한 스택에서 제거되고 그 자리에 새 인스턴스가 대신 생성되어 수신되는 인텐트를 +처리하게 됩니다. 이는 시작 모드가 {@code "standard"}인 경우, 새 인텐트에 대해서는 항상 새 인스턴스가 생성되기 때문입니다.

    @@ -420,65 +420,65 @@ android.app.Activity#startActivity startActivity()}에 전달한 인텐트 안

    유사성 처리하기

    -

    유사성이란 액티비티가 어느 작업에 소속되기를 선호하는지를 나타내는 것입니다. 기본적으로, -같은 애플리케이션에서 나온 액티비티는 서로 유사성을 지니고 있습니다. 따라서, 기본적으로 -같은 애플리케이션 안에 있는 모든 액티비티는 같은 작업 안에 있는 것을 선호합니다. 하지만 액티비티에 대한 기본 유사성은 개발자가 -수정할 수 있습니다. 각기 다른 애플리케이션에서 정의된 -액티비티가 하나의 유사성을 공유할 수도 있고, 같은 애플리케이션에서 정의된 여러 액티비티에 +

    유사성이란 액티비티가 어느 작업에 소속되기를 선호하는지를 나타내는 것입니다. 기본적으로, +같은 애플리케이션에서 나온 액티비티는 서로 유사성을 지니고 있습니다. 따라서, 기본적으로 +같은 애플리케이션 안에 있는 모든 액티비티는 같은 작업 안에 있는 것을 선호합니다. 하지만 액티비티에 대한 기본 유사성은 개발자가 +수정할 수 있습니다. 각기 다른 애플리케이션에서 정의된 +액티비티가 하나의 유사성을 공유할 수도 있고, 같은 애플리케이션에서 정의된 여러 액티비티에 서로 다른 작업 유사성을 할당할 수도 있습니다.

    어느 액티비티라도 {@code <activity>} -요소의 {@code taskAffinity} 속성을 +요소의 {@code taskAffinity} 속성을 사용하여 유사성을 수정할 수 있습니다.

    {@code taskAffinity} -속성은 문자열 값을 취합니다. 이는 +속성은 문자열 값을 취합니다. 이는 {@code <manifest>} - 요소에서 선언한 기본 패키지 이름과 달리 고유해야 합니다. 왜냐하면 시스템이 이 이름을 사용하여 애플리케이션의 기본 작업 유사성을 + 요소에서 선언한 기본 패키지 이름과 달리 고유해야 합니다. 왜냐하면 시스템이 이 이름을 사용하여 애플리케이션의 기본 작업 유사성을 식별하기 때문입니다.

    유사성이 역할을 갖는 것은 다음과 같은 두 가지 상황에서입니다.

      -
    • 액티비티를 시작한 인텐트에 +
    • 액티비티를 시작한 인텐트에 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} 플래그가 들어 있는 경우. -

      새로운 액티비티는 기본적으로 -{@link android.app.Activity#startActivity startActivity()}를 호출한 액티비티의 작업 안으로 들어가며 시작됩니다. 이것은 발신자와 같은 -백 스택 위로 밀어내집니다. 하지만 -{@link android.app.Activity#startActivity startActivity()}에 +

      새로운 액티비티는 기본적으로 +{@link android.app.Activity#startActivity startActivity()}를 호출한 액티비티의 작업 안으로 들어가며 시작됩니다. 이것은 발신자와 같은 +백 스택 위로 밀어내집니다. 하지만 +{@link android.app.Activity#startActivity startActivity()}에 전달된 인텐트에 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} 플래그가 들어있는 경우, 시스템은 새 액티비티를 담을 다른 작업을 찾습니다. 이는 새 작업인 경우가 많습니다. -그렇지만 꼭 그래야 하는 것은 아닙니다. 새 액티비티와 같은 유사성을 가진 기존 작업이 이미 존재하는 경우, +그렇지만 꼭 그래야 하는 것은 아닙니다. 새 액티비티와 같은 유사성을 가진 기존 작업이 이미 존재하는 경우, 해당 액티비티는 그 작업 안으로 들어가며 시작됩니다. 그렇지 않으면, 새 작업을 시작합니다.

      -

      이 플래그 때문에 액티비티가 새 작업을 시작하게 되고 사용자가 버튼을 눌러 이 액티비티를 -떠나고자 -하는 경우, 사용자가 작업으로 도로 이동할 방법이 있어야 합니다. 엔티티 중에는(예를 들어 -알림 관리자) 액티비티를 항상 외부 작업으로만 시작하고 자신의 일부로서는 절대 시작하지 않는 것이 있습니다. -따라서 이들은 {@code FLAG_ACTIVITY_NEW_TASK}를 -{@link android.app.Activity#startActivity startActivity()}에 전달하는 인텐트에 포함시킵니다. -이 플래그를 사용할 수 있는 외부 엔티티가 -호출할 수 있는 액티비티를 가지고 있는 경우, 사용자가 시작된 작업에 돌아갈 수 있는 -방법을 따로 가지고 있어야 합니다. 예를 들어 시작 관리자 아이콘을 이용한다든지 하는 방법입니다(작업의 루트 액티비티에 +

      이 플래그 때문에 액티비티가 새 작업을 시작하게 되고 사용자가 버튼을 눌러 이 액티비티를 +떠나고자 +하는 경우, 사용자가 작업으로 도로 이동할 방법이 있어야 합니다. 엔티티 중에는(예를 들어 +알림 관리자) 액티비티를 항상 외부 작업으로만 시작하고 자신의 일부로서는 절대 시작하지 않는 것이 있습니다. +따라서 이들은 {@code FLAG_ACTIVITY_NEW_TASK}를 +{@link android.app.Activity#startActivity startActivity()}에 전달하는 인텐트에 포함시킵니다. +이 플래그를 사용할 수 있는 외부 엔티티가 +호출할 수 있는 액티비티를 가지고 있는 경우, 사용자가 시작된 작업에 돌아갈 수 있는 +방법을 따로 가지고 있어야 합니다. 예를 들어 시작 관리자 아이콘을 이용한다든지 하는 방법입니다(작업의 루트 액티비티에 {@link android.content.Intent#CATEGORY_LAUNCHER} 인텐트 필터가 있습니다. 아래의 작업 시작하기 섹션을 참조하십시오).

    • 액티비티의 {@code allowTaskReparenting} 속성이 {@code "true"}로 설정된 경우. -

      이 경우, 액티비티는 자신이 시작한 작업에서 벗어나 유사성을 가진 다른 작업이 전경으로 +

      이 경우, 액티비티는 자신이 시작한 작업에서 벗어나 유사성을 가진 다른 작업이 전경으로 나오면 그 작업으로 이동할 수 있습니다.

      -

      예를 들어 선택한 몇몇 도시에서 기상 상태를 예보하는 어느 액티비티가 -여행 애플리케이션의 일부로 정의되어 있다고 가정합니다. 이것은 같은 애플리케이션에 있는 -다른 여러 액티비티와 같은 유사성을 가지며(기본 애플리케이션 유사성) 이 속성으로 상위 재지정을 허용하기도 합니다. -액티비티 중 하나가 일기 예보 액티비티를 시작하면, 이는 처음에는 액티비티와 같은 작업에 -속합니다. 하지만 여행 애플리케이션의 작업이 전경으로 불려나오면 +

      예를 들어 선택한 몇몇 도시에서 기상 상태를 예보하는 어느 액티비티가 +여행 애플리케이션의 일부로 정의되어 있다고 가정합니다. 이것은 같은 애플리케이션에 있는 +다른 여러 액티비티와 같은 유사성을 가지며(기본 애플리케이션 유사성) 이 속성으로 상위 재지정을 허용하기도 합니다. +액티비티 중 하나가 일기 예보 액티비티를 시작하면, 이는 처음에는 액티비티와 같은 작업에 +속합니다. 하지만 여행 애플리케이션의 작업이 전경으로 불려나오면 일기 예보 액티비티는 그 작업에 다시 할당되며 그 안에 표시됩니다.

    -

    팁: {@code .apk} 파일에 사용자 쪽에서 보기에 하나 이상의 "애플리케이션"이 +

    팁: {@code .apk} 파일에 사용자 쪽에서 보기에 하나 이상의 "애플리케이션"이 들어있는 경우, {@code taskAffinity} 속성을 사용하여 각 "애플리케이션"과 연관된 액티비티에 서로 다른 유사성을 할당하는 것이 좋습니다.

    @@ -486,9 +486,9 @@ android.app.Activity#startActivity startActivity()}에 전달한 인텐트 안

    백 스택 지우기

    -

    사용자가 작업을 오랜 시간 동안 떠나 있으면, 시스템이 루트 액티비티만 빼고 모든 액티비티를 -해당 작업에서 지웁니다. 사용자가 다시 작업으로 돌아오면, 루트 액티비티만 복원됩니다. -시스템이 이런 식으로 동작하는 것은 오랜 시간이 지난 다음에는 사용자가 전에 하던 일을 중단하고 +

    사용자가 작업을 오랜 시간 동안 떠나 있으면, 시스템이 루트 액티비티만 빼고 모든 액티비티를 +해당 작업에서 지웁니다. 사용자가 다시 작업으로 돌아오면, 루트 액티비티만 복원됩니다. +시스템이 이런 식으로 동작하는 것은 오랜 시간이 지난 다음에는 사용자가 전에 하던 일을 중단하고 새로운 일을 시작하기 위해 작업에 돌아올 가능성이 크기 때문입니다.

    이 동작을 수정하는 데 사용할 수 있는 액티비티 속성이 몇 가지 있습니다.

    @@ -497,27 +497,27 @@ android.app.Activity#startActivity startActivity()}에 전달한 인텐트 안
    alwaysRetainTaskState
    -
    이 속성이 작업의 루트 액티비티 안에서 {@code "true"}로 설정되어 있는 경우, -방금 설명한 기본 동작이 일어나지 않습니다. +
    이 속성이 작업의 루트 액티비티 안에서 {@code "true"}로 설정되어 있는 경우, +방금 설명한 기본 동작이 일어나지 않습니다. 작업은 오랜 시간이 지난 뒤에도 자신의 스택에 있는 모든 액티비티를 유지합니다.
    clearTaskOnLaunch
    -
    이 속성이 작업의 루트 액티비티 안에서 {@code "true"}로 설정되어 있는 경우, -사용자가 작업을 떠났다가 다시 돌아올 때마다 스택을 루트 액티비티까지 -지웁니다. 바꿔 말하면, 이것은 +
    이 속성이 작업의 루트 액티비티 안에서 {@code "true"}로 설정되어 있는 경우, +사용자가 작업을 떠났다가 다시 돌아올 때마다 스택을 루트 액티비티까지 +지웁니다. 바꿔 말하면, 이것은 -{@code alwaysRetainTaskState}와 정반대입니다. 사용자는 항상 작업의 초기 상태로 돌아오게 되며, +{@code alwaysRetainTaskState}와 정반대입니다. 사용자는 항상 작업의 초기 상태로 돌아오게 되며, 이는 아주 잠깐 동안만 작업을 떠난 경우에도 마찬가지입니다.
    finishOnTaskLaunch
    -
    이 속성은 {@code clearTaskOnLaunch}와 같지만, -작업 전체가 아니라 -하나의 액티비티에서 작동합니다. 이것은 루트 액티비티를 포함한 모든 액티비티가 없어지게 -하기도 합니다. 이것을 {@code "true"}로 설정하면, -액티비티는 현재 세션에 대해서만 작업의 일부로 유지됩니다. 사용자가 작업을 떠났다가 +
    이 속성은 {@code clearTaskOnLaunch}와 같지만, +작업 전체가 아니라 +하나의 액티비티에서 작동합니다. 이것은 루트 액티비티를 포함한 모든 액티비티가 없어지게 +하기도 합니다. 이것을 {@code "true"}로 설정하면, +액티비티는 현재 세션에 대해서만 작업의 일부로 유지됩니다. 사용자가 작업을 떠났다가 다시 돌아오면 이 작업은 더 이상 존재하지 않습니다.
    @@ -526,9 +526,9 @@ href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTask

    작업 시작하기

    -

    액티비티를 작업의 진입 지점으로 설정하려면 여기에 작업에서 지정한 대로 -{@code "android.intent.action.MAIN"}이 있는 인텐트 필터를 부여하고 -{@code "android.intent.category.LAUNCHER"}를 +

    액티비티를 작업의 진입 지점으로 설정하려면 여기에 작업에서 지정한 대로 +{@code "android.intent.action.MAIN"}이 있는 인텐트 필터를 부여하고 +{@code "android.intent.category.LAUNCHER"}를 지정된 카테고리로 설정하면 됩니다. 예:

    @@ -541,29 +541,29 @@ href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTask
     </activity>
     
    -

    이런 종류의 인텐트 필터를 사용하면 액티비티에 대한 아이콘과 레이블이 -애플리케이션 시작 관리자에 표시되어 사용자에게 액티비티를 시작할 방법을 부여하며, +

    이런 종류의 인텐트 필터를 사용하면 액티비티에 대한 아이콘과 레이블이 +애플리케이션 시작 관리자에 표시되어 사용자에게 액티비티를 시작할 방법을 부여하며, 액티비티를 시작하고 나면 이것이 생성한 작업에 언제든 돌아올 수 있게 됩니다.

    -

    이 두 번째 능력이 중요합니다. 사용자는 작업을 떠났다가 이 액티비티 시작 관리자를 사용하여 나중에 작업에 +

    이 두 번째 능력이 중요합니다. 사용자는 작업을 떠났다가 이 액티비티 시작 관리자를 사용하여 나중에 작업에 돌아올 수 있어야 합니다. 이러한 이유로, 액티비티가 항상 작업을 시작하는 것으로 표시하는 시작 -모드 두 가지, 즉 {@code "singleTask"}와 -{@code "singleInstance"}는 액티비티에 +모드 두 가지, 즉 {@code "singleTask"}와 +{@code "singleInstance"}는 액티비티에 {@link android.content.Intent#ACTION_MAIN} - 및 {@link android.content.Intent#CATEGORY_LAUNCHER} 필터가 있을 때에만 사용해야 합니다. 예를 들어 필터가 누락되면 다음과 같은 일이 -발생합니다. 어느 인텐트가 {@code "singleTask"} 액티비티를 시작하여 새 작업을 시작하고, + 및 {@link android.content.Intent#CATEGORY_LAUNCHER} 필터가 있을 때에만 사용해야 합니다. 예를 들어 필터가 누락되면 다음과 같은 일이 +발생합니다. 어느 인텐트가 {@code "singleTask"} 액티비티를 시작하여 새 작업을 시작하고, 사용자가 이 작업에서 일하며 어느 정도 시간을 보냅니다. 그런 다음 사용자가 - 버튼을 누릅니다. 이제 이 작업은 배경으로 전송되었으며 눈에 보이지 않습니다. 이제 사용자가 작업으로 되돌아갈 + 버튼을 누릅니다. 이제 이 작업은 배경으로 전송되었으며 눈에 보이지 않습니다. 이제 사용자가 작업으로 되돌아갈 방법이 없어졌습니다. 이는 애플리케이션 시작 관리자에 표시되지 않기 때문입니다.

    -

    사용자가 액티비티로 되돌아갈 수 있도록 하는 것을 원치 않는 경우, +

    사용자가 액티비티로 되돌아갈 수 있도록 하는 것을 원치 않는 경우, <activity> - 요소의 + 요소의 {@code finishOnTaskLaunch} 를 {@code "true"}로 설정하면 됩니다(스택 지우기를 참조하십시오).

    -

    작업과 액티비티가 개요 화면에서 어떻게 표시되고 관리되는지에 대한 +

    작업과 액티비티가 개요 화면에서 어떻게 표시되고 관리되는지에 대한 자세한 정보는 개요 화면에서 확인하실 수 있습니다.

    diff --git a/docs/html-intl/intl/ko/guide/index.jd b/docs/html-intl/intl/ko/guide/index.jd index 73af3df9b8c0ffc8a6fc5d88685f8450bb98ed92..debd05312e98802b9c01a54f2405ecfc15e05172 100644 --- a/docs/html-intl/intl/ko/guide/index.jd +++ b/docs/html-intl/intl/ko/guide/index.jd @@ -4,16 +4,16 @@ page.title=Android 소개 -

    Android는 풍성한 애플리케이션 프레임워크를 제공하여 Java 언어 환경에서 실행되는 -모바일 기기에서 사용할 혁신적인 앱과 게임을 구축할 수 있습니다. 왼쪽 탐색 영역에 목록으로 나열된 +

    Android는 풍성한 애플리케이션 프레임워크를 제공하여 Java 언어 환경에서 실행되는 +모바일 기기에서 사용할 혁신적인 앱과 게임을 구축할 수 있습니다. 왼쪽 탐색 영역에 목록으로 나열된 여러 문서에서 Android의 다양한 API를 사용하여 앱을 구축하는 방법에 대한 상세한 정보를 제공합니다.

    -

    Android 개발을 처음 시도하신다면, 다음과 같은 +

    Android 개발을 처음 시도하신다면, 다음과 같은 Android 앱 프레임워크 기본 개념을 숙지하는 것이 중요합니다.

    @@ -23,14 +23,14 @@ Android 앱 프레임워크 기본 개념을 숙지하는 것이 중요합니다

    앱은 여러 개의 진입 지점을 제공합니다.

    -

    Android 앱은 여러 가지 고유한 구성 요소들의 조합으로 구축되며, 이러한 구성 요소는 개별적으로 -호출할 수도 있습니다. 예를 들어 어떤 하나의 액티비티가 사용자 인터페이스를 위한 -화면을 하나 제공하고, 서비스가 배경에서 독립적으로 작업을 수행할 +

    Android 앱은 여러 가지 고유한 구성 요소들의 조합으로 구축되며, 이러한 구성 요소는 개별적으로 +호출할 수도 있습니다. 예를 들어 어떤 하나의 액티비티가 사용자 인터페이스를 위한 +화면을 하나 제공하고, 서비스가 배경에서 독립적으로 작업을 수행할 수 있습니다.

    -

    한 구성 요소에서 또 다른 구성 요소를 시작하려면 인텐트를 사용하면 됩니다. 심지어 다른 앱에서도 -구성 요소를 시작할 수 있습니다. 지도 앱에서 주소를 표시하는 액티비티를 시작하는 것이 좋은 예입니다. 이 모델은 -하나의 앱에 대한 여러 개의 진입 지점을 제공하여 어느 앱이라도 다른 여러 앱이 호출할 수 있는 작업에 대해 +

    한 구성 요소에서 또 다른 구성 요소를 시작하려면 인텐트를 사용하면 됩니다. 심지어 다른 앱에서도 +구성 요소를 시작할 수 있습니다. 지도 앱에서 주소를 표시하는 액티비티를 시작하는 것이 좋은 예입니다. 이 모델은 +하나의 앱에 대한 여러 개의 진입 지점을 제공하여 어느 앱이라도 다른 여러 앱이 호출할 수 있는 작업에 대해 사용자의 "기본" 앱 역할을 합니다.

    @@ -48,14 +48,14 @@ Android 앱 프레임워크 기본 개념을 숙지하는 것이 중요합니다

    앱은 여러 가지 기기에 맞게 변경됩니다.

    -

    Android는 적응형 앱 프레임워크를 제공하여 여러 가지 기기 구성에 맞게 -고유한 리소스를 제공할 수 있습니다. 예를 들어, 여러 가지 화면 크기에 맞춰 각기 다른 XML -레이아웃 파일을 생성하면 시스템이 현재 기기의 화면 크기를 근거로 +

    Android는 적응형 앱 프레임워크를 제공하여 여러 가지 기기 구성에 맞게 +고유한 리소스를 제공할 수 있습니다. 예를 들어, 여러 가지 화면 크기에 맞춰 각기 다른 XML +레이아웃 파일을 생성하면 시스템이 현재 기기의 화면 크기를 근거로 어느 레이아웃을 적용할지 결정합니다.

    -

    앱 기능이 특정한 하드웨어(예: 카메라)를 필요로 하는 경우 런타임에 -기기 특징의 기능을 쿼리할 수 있습니다. 필요하다면 앱이 필요로 하는 기능을 선언할 수도 있습니다. -그러면 Google Play Store와 같은 앱 마켓에서 해당 기능을 지원하지 않는 기기에서 +

    앱 기능이 특정한 하드웨어(예: 카메라)를 필요로 하는 경우 런타임에 +기기 특징의 기능을 쿼리할 수 있습니다. 필요하다면 앱이 필요로 하는 기능을 선언할 수도 있습니다. +그러면 Google Play Store와 같은 앱 마켓에서 해당 기능을 지원하지 않는 기기에서 설치를 허용하지 않습니다.

    diff --git a/docs/html-intl/intl/ko/preview/j8-jack.jd b/docs/html-intl/intl/ko/guide/platform/j8-jack.jd similarity index 100% rename from docs/html-intl/intl/ko/preview/j8-jack.jd rename to docs/html-intl/intl/ko/guide/platform/j8-jack.jd diff --git a/docs/html-intl/intl/ko/guide/topics/manifest/manifest-intro.jd b/docs/html-intl/intl/ko/guide/topics/manifest/manifest-intro.jd index c3550d0e7dc8bf2ebeaac90efff2c730feb48119..2f397c71dbb3826b95883c75d45fa827727a6e51 100644 --- a/docs/html-intl/intl/ko/guide/topics/manifest/manifest-intro.jd +++ b/docs/html-intl/intl/ko/guide/topics/manifest/manifest-intro.jd @@ -20,38 +20,38 @@ page.title=앱 매니페스트

    - 모든 애플리케이션에는 루트 라이브러리에 AndroidManifest.xml 파일(정확히 -이 이름으로)이 있어야 합니다. 매니페스트 파일은 -Android 시스템에 대한 여러분의 앱 관련 필수 정보를 나타냅니다. -즉 앱의 코드를 실행하기 전에 시스템이 반드시 필요로 하는 정보를 + 모든 애플리케이션에는 루트 라이브러리에 AndroidManifest.xml 파일(정확히 +이 이름으로)이 있어야 합니다. 매니페스트 파일은 +Android 시스템에 대한 여러분의 앱 관련 필수 정보를 나타냅니다. +즉 앱의 코드를 실행하기 전에 시스템이 반드시 필요로 하는 정보를 말합니다. 매니페스트가 하는 일에는 여러 가지가 있지만, 그 중에서 몇 가지만 소개하면 다음과 같습니다.

      -
    • 애플리케이션에 대한 Java 패키지의 이름을 나타냅니다. +
    • 애플리케이션에 대한 Java 패키지의 이름을 나타냅니다. 패키지 이름이 애플리케이션에 대한 고유한 식별자 역할을 합니다.
    • -
    • 애플리케이션의 구성 요소를 설명합니다. 액티비티, -서비스, 브로드캐스트 수신기 및 콘텐츠 제공자 등 애플리케이션을 이루는 여러 항목을 -말합니다. 이것은 각 구성 요소를 구현하는 클래스의 이름을 나타내고 -각각의 기능을 게시합니다(예를 들어 처리할 수 있는 {@link android.content.Intent -Intent} 메시지 종류 등). 이러한 선언을 통해 Android 시스템이 여러 구성 요소가 +
    • 애플리케이션의 구성 요소를 설명합니다. 액티비티, +서비스, 브로드캐스트 수신기 및 콘텐츠 제공자 등 애플리케이션을 이루는 여러 항목을 +말합니다. 이것은 각 구성 요소를 구현하는 클래스의 이름을 나타내고 +각각의 기능을 게시합니다(예를 들어 처리할 수 있는 {@link android.content.Intent +Intent} 메시지 종류 등). 이러한 선언을 통해 Android 시스템이 여러 구성 요소가 각각 무엇인지 알게 되고, 어떤 조건에서 시작해야 하는지 알 수 있습니다.
    • -
    • 어느 프로세스가 애플리케이션 구성 요소를 호스팅할 것인지 결정합니다.
    • +
    • 어느 프로세스가 애플리케이션 구성 요소를 호스팅할 것인지 결정합니다.
    • -
    • API의 보호된 부분에 액세스하여 다른 애플리케이션과 상호 작용하려면 -애플리케이션에 어느 권한이 꼭 필요한지 선언합니다.
    • +
    • API의 보호된 부분에 액세스하여 다른 애플리케이션과 상호 작용하려면 +애플리케이션에 어느 권한이 꼭 필요한지 선언합니다.
    • -
    • 또한, 이 애플리케이션의 구성 요소와 상호 작용하려면 다른 애플리케이션이 +
    • 또한, 이 애플리케이션의 구성 요소와 상호 작용하려면 다른 애플리케이션이 반드시 가지고 있어야 하는 권한도 선언합니다.
    • -
    • 이는 애플리케이션이 실행 중일 때 프로파일링과 기타 정보를 제공하는 -{@link android.app.Instrumentation} 클래스를 목록으로 표시합니다. 이러한 선언이 매니페스트에 나타나는 것은 -애플리케이션이 개발 중이고 테스트되는 단계에만 국한됩니다. +
    • 이는 애플리케이션이 실행 중일 때 프로파일링과 기타 정보를 제공하는 +{@link android.app.Instrumentation} 클래스를 목록으로 표시합니다. 이러한 선언이 매니페스트에 나타나는 것은 +애플리케이션이 개발 중이고 테스트되는 단계에만 국한됩니다. 이들은 애플리케이션이 게시되기 전에 제거됩니다.
    • -
    • 이는 애플리케이션이 필요로 하는 Android API의 최소 레벨을 +
    • 이는 애플리케이션이 필요로 하는 Android API의 최소 레벨을 선언합니다.
    • 애플리케이션이 연결되어야 하는 라이브러리를 목록으로 표시합니다.
    • @@ -61,12 +61,12 @@ Intent} 메시지 종류 등). 이러한 선언을 통해 Android 시스템이

      매니페스트 파일의 구조

      -아래의 다이어그램은 매니페스트 파일의 일반적인 구조와 매니페스트 파일에 -들어있을 수 있는 모든 요소를 표시한 것입니다. 각 요소와 각각의 속성을 모두 문서화한 -전문은 별도의 파일에서 확인하실 수 있습니다. 어떤 요소에 대해서든 -상세한 정보를 보려면 다이어그램에서 해당 요소 이름을 클릭하십시오. -이름은 다이어그램 뒤에 나오는 요소 목록(알파벳 순) 또는 -요소 이름이 언급되는 기타 영역 어디서든 클릭할 수 있습니다. +아래의 다이어그램은 매니페스트 파일의 일반적인 구조와 매니페스트 파일에 +들어있을 수 있는 모든 요소를 표시한 것입니다. 각 요소와 각각의 속성을 모두 문서화한 +전문은 별도의 파일에서 확인하실 수 있습니다. 어떤 요소에 대해서든 +상세한 정보를 보려면 다이어그램에서 해당 요소 이름을 클릭하십시오. +이름은 다이어그램 뒤에 나오는 요소 목록(알파벳 순) 또는 +요소 이름이 언급되는 기타 영역 어디서든 클릭할 수 있습니다.

      @@ -126,9 +126,9 @@ Intent} 메시지 종류 등).  이러한 선언을 통해 Android 시스템이
       

      -매니페스트 파일에 표시될 수 있는 모든 요소는 아래에 알파벳 순서로 -목록으로 표시되어 있습니다. 합법적인 요소는 이들이 전부입니다. 개발자 나름대로 요소 또는 속성을 -추가해서는 안 됩니다. +매니페스트 파일에 표시될 수 있는 모든 요소는 아래에 알파벳 순서로 +목록으로 표시되어 있습니다. 합법적인 요소는 이들이 전부입니다. 개발자 나름대로 요소 또는 속성을 +추가해서는 안 됩니다.

      @@ -158,74 +158,74 @@ Intent} 메시지 종류 등). 이러한 선언을 통해 Android 시스템이

      - +

      파일 규칙

      -몇몇 규칙과 규정은 매니페스트 내의 모든 요소와 속성에 전반적으로 +몇몇 규칙과 규정은 매니페스트 내의 모든 요소와 속성에 전반적으로 적용됩니다.

      요소
      -
      필수 요소는 -<manifest> 및 -<application> 요소뿐으로, -이들은 각기 따로 표시되어야 하며 한 번씩만 발생할 수 있습니다. -나머지는 대부분 여러 번 발생할 수 있거나 전혀 발생하지 않기도 합니다. 다만, -그 중 최소한 몇몇은 있어야 매니페스트가 무엇이든 의미 있는 작업을 +
      필수 요소는 +<manifest> 및 +<application> 요소뿐으로, +이들은 각기 따로 표시되어야 하며 한 번씩만 발생할 수 있습니다. +나머지는 대부분 여러 번 발생할 수 있거나 전혀 발생하지 않기도 합니다. 다만, +그 중 최소한 몇몇은 있어야 매니페스트가 무엇이든 의미 있는 작업을 달성할 수 있습니다.

      -요소에 무엇이든 들어있기만 하면 다른 요소가 그 요소에 들어 있는 것입니다. +요소에 무엇이든 들어있기만 하면 다른 요소가 그 요소에 들어 있는 것입니다. 모든 값은 요소 내의 문자 데이터로서가 아니라 속성을 통해 설정됩니다.

      -같은 레벨에 있는 여러 요소는 보통 순서가 지정되지 않습니다. 예를 들어 -<activity>, -<provider> 및 -<service> -요소는 어떤 순서로든 서로 섞여도 됩니다 (이 규칙에서 +같은 레벨에 있는 여러 요소는 보통 순서가 지정되지 않습니다. 예를 들어 +<activity>, +<provider> 및 +<service> +요소는 어떤 순서로든 서로 섞여도 됩니다 (이 규칙에서 <activity-alias> -요소는 예외입니다. 이것은 -<activity>의 별칭이므로 +요소는 예외입니다. 이것은 +<activity>의 별칭이므로 이를 반드시 따라야 합니다).

      속성
      -
      공식적인 의미에서 모든 속성은 선택 항목입니다. 그러나, 요소가 목적을 달성하기 -위해서 반드시 지정되어야 하는 것이 몇 가지 있습니다. 관련 문서를 -지침으로 사용하십시오. 정말로 선택적인 속성의 경우, 기본 값을 언급하거나 +
      공식적인 의미에서 모든 속성은 선택 항목입니다. 그러나, 요소가 목적을 달성하기 +위해서 반드시 지정되어야 하는 것이 몇 가지 있습니다. 관련 문서를 +지침으로 사용하십시오. 정말로 선택적인 속성의 경우, 기본 값을 언급하거나 사양이 없으면 어떤 일이 벌어지는지 진술합니다. -

      루트 -<manifest> +

      루트 +<manifest> 요소의 몇 가지 속성을 제외하고 모든 속성 이름은 {@code android:alwaysRetainTaskState} 접두사로 시작합니다. -예를 들어, {@code android:}와 같습니다. 이 접두사는 범용이기 때문에 -속성을 이름으로 참조하는 경우 관련 문서가 이를 생략하는 경우가 +예를 들어, {@code android:}와 같습니다. 이 접두사는 범용이기 때문에 +속성을 이름으로 참조하는 경우 관련 문서가 이를 생략하는 경우가 일반적입니다.

      클래스 이름 선언
      -
      대다수의 요소가 Java 객체에 상응합니다. 여기에는 +
      대다수의 요소가 Java 객체에 상응합니다. 여기에는 애플리케이션 자체에 대한 요소가 포함되며( -<application> -요소), 그것의 주 구성 요소도 포함됩니다. 즉, 액티비티 -(<activity>), +<application> +요소), 그것의 주 구성 요소도 포함됩니다. 즉, 액티비티 +(<activity>), 서비스 -(<service>), +(<service>), 브로드캐스트 수신기 -(<receiver>) 및 +(<receiver>) 및 콘텐츠 제공자 -(<provider>) 등이 이에 해당됩니다. +(<provider>) 등이 이에 해당됩니다.

      하위 클래스를 정의하는 경우 구성 요소 클래스 -({@link android.app.Activity}, {@link android.app.Service}, -{@link android.content.BroadcastReceiver} 및 {@link android.content.ContentProvider})는 거의 항상 이렇게 하게 되는데, -이때 하위 클래스는 {@code name} 속성을 통해 선언됩니다. 이 이름에 반드시 -완전한 패키지 지정이 포함되어 있어야 합니다. +({@link android.app.Activity}, {@link android.app.Service}, +{@link android.content.BroadcastReceiver} 및 {@link android.content.ContentProvider})는 거의 항상 이렇게 하게 되는데, +이때 하위 클래스는 {@code name} 속성을 통해 선언됩니다. 이 이름에 반드시 +완전한 패키지 지정이 포함되어 있어야 합니다. 예를 들어, {@link android.app.Service} 하위 클래스를 선언하려면 다음과 같이 할 수 있습니다.

      @@ -239,12 +239,12 @@ Intent} 메시지 종류 등). 이러한 선언을 통해 Android 시스템이 </manifest>

      -그러나 일종의 줄임으로서 문자열의 첫 번째 글자가 마침표인 경우, 해당 +그러나 일종의 줄임으로서 문자열의 첫 번째 글자가 마침표인 경우, 해당 문자열은 애플리케이션의 패키지 이름에 추가됩니다( -<manifest> -요소의 -package -속성에서 지정한 바와 같이). 다음 할당은 위의 것과 같습니다. +<manifest> +요소의 +package +속성에서 지정한 바와 같이). 다음 할당은 위의 것과 같습니다.

      <manifest package="com.example.project" . . . >
      @@ -257,13 +257,13 @@ Intent} 메시지 종류 등).  이러한 선언을 통해 Android 시스템이
       </manifest>

      -Android는 구성 요소를 시작할 때 이름이 명명된 하위 클래스의 인스턴스를 생성합니다. +Android는 구성 요소를 시작할 때 이름이 명명된 하위 클래스의 인스턴스를 생성합니다. 하위 클래스가 지정되지 않은 경우, 기본 클래스의 인스턴스를 생성합니다.

      여러 개의 값
      -
      하나 이상의 값을 지정할 수 있는 경우, 해당 요소는 -한 요소 안에 여러 개의 값을 목록으로 표시하기보다 거의 항상 반복됩니다. +
      하나 이상의 값을 지정할 수 있는 경우, 해당 요소는 +한 요소 안에 여러 개의 값을 목록으로 표시하기보다 거의 항상 반복됩니다. 예를 들어 한 인텐트 필터가 여러 개의 작업을 목록으로 표시할 수 있습니다.
      <intent-filter . . . >
      @@ -274,9 +274,9 @@ Android는 구성 요소를 시작할 때 이름이 명명된 하위 클래스
       </intent-filter>
      리소스 값
      -
      몇몇 속성에는 사용자에게 표시될 수 있는 값이 있습니다. 예를 들어 -액티비티에 대한 레이블과 아이콘 등이 이에 해당됩니다. 이러한 속성의 값은 -지역화해야 하며 따라서 리소스나 테마에서 설정됩니다. 리소스 +
      몇몇 속성에는 사용자에게 표시될 수 있는 값이 있습니다. 예를 들어 +액티비티에 대한 레이블과 아이콘 등이 이에 해당됩니다. 이러한 속성의 값은 +지역화해야 하며 따라서 리소스나 테마에서 설정됩니다. 리소스 값은 다음과 같은 형식으로 표현됩니다.

      {@code @[패키지:]유형:이름}

      @@ -284,7 +284,7 @@ Android는 구성 요소를 시작할 때 이름이 명명된 하위 클래스

      여기에서 패키지 이름은 리소스가 애플리케이션과 같은 패키지에 있으면 생략할 수 있고, 유형 은 "문자열" 또는 "그릴 수 있음" 같은 리소스 유형입니다. 그리고 - 이름 은 특정 리소스를 식별하는 이름입니다. + 이름 은 특정 리소스를 식별하는 이름입니다. 예:

      @@ -299,8 +299,8 @@ Android는 구성 요소를 시작할 때 이름이 명명된 하위 클래스

      문자열 값
      -
      속성 값이 문자열인 경우, 이중 백슬래시('{@code \\}')를 사용하여 -문자 이스케이프를 수행해야 합니다. 예를 들어 줄바꿈에는 {@code \\n}, +
      속성 값이 문자열인 경우, 이중 백슬래시('{@code \\}')를 사용하여 +문자 이스케이프를 수행해야 합니다. 예를 들어 줄바꿈에는 {@code \\n}, 유니코드 문자에는 '{@code \\uxxxx}'를 쓰십시오.
      @@ -308,7 +308,7 @@ Android는 구성 요소를 시작할 때 이름이 명명된 하위 클래스

      파일 기능

      -다음 섹션에서는 Android 기능을 매니페스트 파일에 반영하는 +다음 섹션에서는 Android 기능을 매니페스트 파일에 반영하는 몇 가지 방식을 설명합니다.

      @@ -316,37 +316,37 @@ Android는 구성 요소를 시작할 때 이름이 명명된 하위 클래스

      인텐트 필터

      -애플리케이션의 핵심 구성 요소(액티비티, 서비스 및 브로드캐스트 -수신기)를 활성화하는 것은 인텐트입니다. 인텐트는 +애플리케이션의 핵심 구성 요소(액티비티, 서비스 및 브로드캐스트 +수신기)를 활성화하는 것은 인텐트입니다. 인텐트는 원하는 작업을 설명하는 정보 묶음입니다({@link android.content.Intent} 객체). -여기에는 작업을 수행할 데이터, 작업을 수행할 구성 요소의 카테고리와 -기타 관련 지침 등이 포함됩니다. -Android는 인텐트에 응답할 적절한 구성 요소를 찾아 필요한 경우 구성 요소의 -새 인스턴스를 시작하고, 이것을 인텐트 객체에 +여기에는 작업을 수행할 데이터, 작업을 수행할 구성 요소의 카테고리와 +기타 관련 지침 등이 포함됩니다. +Android는 인텐트에 응답할 적절한 구성 요소를 찾아 필요한 경우 구성 요소의 +새 인스턴스를 시작하고, 이것을 인텐트 객체에 전달합니다.

      -구성 요소는 자신의 능력을 알립니다. 즉, 자신이 응답할 수 있는 -인텐트 종류를 밝힙니다. 이때 사용하는 것이 인텐트 필터입니다. Android 시스템은 -구성 요소를 시작하기 전에 해당 구성 요소가 처리할 수 있는 인텐트에 대해 학습해야 하기 때문에, -인텐트 필터는 매니페스트 파일에 -<intent-filter> -요소로 지정됩니다. 구성 요소 하나에 필터는 얼마든지 있을 수 있으며, 각각 서로 다른 기능을 +구성 요소는 자신의 능력을 알립니다. 즉, 자신이 응답할 수 있는 +인텐트 종류를 밝힙니다. 이때 사용하는 것이 인텐트 필터입니다. Android 시스템은 +구성 요소를 시작하기 전에 해당 구성 요소가 처리할 수 있는 인텐트에 대해 학습해야 하기 때문에, +인텐트 필터는 매니페스트 파일에 +<intent-filter> +요소로 지정됩니다. 구성 요소 하나에 필터는 얼마든지 있을 수 있으며, 각각 서로 다른 기능을 설명하게 됩니다.

      대상 구성 요소를 명시적으로 지명하는 인텐트가 해당 구성 요소를 활성화합니다. -필터는 아무런 역할을 하지 않습니다. 하지만 대상을 이름으로 지정하지 않는 인텐트의 경우에는 -자신이 구성 요소의 필터 중 하나를 통과할 수 있을 때에만 해당 구성 요소를 활성화할 수 +필터는 아무런 역할을 하지 않습니다. 하지만 대상을 이름으로 지정하지 않는 인텐트의 경우에는 +자신이 구성 요소의 필터 중 하나를 통과할 수 있을 때에만 해당 구성 요소를 활성화할 수 있습니다.

      -인텐트 객체를 인텐트 필터에 대해 테스트하는 방법에 대한 자세한 방법은 -별도의 문서인 -인텐트 +인텐트 객체를 인텐트 필터에 대해 테스트하는 방법에 대한 자세한 방법은 +별도의 문서인 +인텐트 및 인텐트 필터를 참조하십시오.

      @@ -354,42 +354,42 @@ Android는 인텐트에 응답할 적절한 구성 요소를 찾아 필요한

      아이콘 및 레이블

      -대다수의 요소에 {@code icon}과 {@code label} 속성이 있으며 -이것으로 사용자에게 표시될 수 있는 작은 아이콘과 텍스트 레이블을 나타냅니다. 몇몇 요소에는 -{@code description} 속성도 있어 좀 더 긴 설명 텍스트를 나타낼 수 있고, 이것 또한 화면에 -표시될 수 있습니다. 예를 들어 +대다수의 요소에 {@code icon}과 {@code label} 속성이 있으며 +이것으로 사용자에게 표시될 수 있는 작은 아이콘과 텍스트 레이블을 나타냅니다. 몇몇 요소에는 +{@code description} 속성도 있어 좀 더 긴 설명 텍스트를 나타낼 수 있고, 이것 또한 화면에 +표시될 수 있습니다. 예를 들어 <permission> -요소는 이와 같은 속성을 셋 모두 가지고 있어 사용자가 이를 요청한 애플리케이션에 대한 -권한을 허가할 것인지 여부를 물으면 해당 권한, -권한의 이름과 그에 수반되는 내용에 대한 설명을 +요소는 이와 같은 속성을 셋 모두 가지고 있어 사용자가 이를 요청한 애플리케이션에 대한 +권한을 허가할 것인지 여부를 물으면 해당 권한, +권한의 이름과 그에 수반되는 내용에 대한 설명을 사용자에게 표시할 수 있습니다.

      -어떤 경우에든, 요소에서 설정된 아이콘과 레이블이 해당 컨테이너의 모든 하위 요소에 대한 기본 -{@code icon}과 {@code label} 설정이 됩니다. -따라서 -<application> -요소에서 설정된 아이콘과 레이블이 애플리케이션의 각 요소에 대한 기본 아이콘과 레이블입니다. -이와 유사하게, 구성 요소에 대해 설정된 아이콘과 레이블이 — 예를 들어 -<activity> -요소 — 각 구성 요소의 -<intent-filter> -요소에 대한 기본 설정입니다. -<application> -요소가 레이블을 설정하지만 액티비티와 그 인텐트 필터는 이를 설정하지 않는 경우, -애플리케이션 레이블을 액티비티와 인텐트 필터 양쪽 모두의 레이블인 것으로 +어떤 경우에든, 요소에서 설정된 아이콘과 레이블이 해당 컨테이너의 모든 하위 요소에 대한 기본 +{@code icon}과 {@code label} 설정이 됩니다. +따라서 +<application> +요소에서 설정된 아이콘과 레이블이 애플리케이션의 각 요소에 대한 기본 아이콘과 레이블입니다. +이와 유사하게, 구성 요소에 대해 설정된 아이콘과 레이블이 — 예를 들어 +<activity> +요소 — 각 구성 요소의 +<intent-filter> +요소에 대한 기본 설정입니다. +<application> +요소가 레이블을 설정하지만 액티비티와 그 인텐트 필터는 이를 설정하지 않는 경우, +애플리케이션 레이블을 액티비티와 인텐트 필터 양쪽 모두의 레이블인 것으로 취급합니다.

      -인텐트 필터에 대해 설정된 아이콘과 레이블은 구성 요소가 사용자에게 -표시될 때마다 구성 요소를 나타내는 데 사용되며, 이는 필터가 알린 기능을 -충족하는 것입니다. 예를 들어 -"{@code android.intent.action.MAIN}" 및 -"{@code android.intent.category.LAUNCHER}"가 설정된 필터는 -액티비티를 애플리케이션을 초기화하는 주역으로 알립니다. 다시 말해, -애플리케이션 시작 관리자에 표시되어야 하는 것이 됩니다. 따라서 필터에서 설정된 아이콘과 레이블이 +인텐트 필터에 대해 설정된 아이콘과 레이블은 구성 요소가 사용자에게 +표시될 때마다 구성 요소를 나타내는 데 사용되며, 이는 필터가 알린 기능을 +충족하는 것입니다. 예를 들어 +"{@code android.intent.action.MAIN}" 및 +"{@code android.intent.category.LAUNCHER}"가 설정된 필터는 +액티비티를 애플리케이션을 초기화하는 주역으로 알립니다. 다시 말해, +애플리케이션 시작 관리자에 표시되어야 하는 것이 됩니다. 따라서 필터에서 설정된 아이콘과 레이블이 시작 관리자에 표시되는 아이콘과 레이블입니다.

      @@ -397,14 +397,14 @@ Android는 인텐트에 응답할 적절한 구성 요소를 찾아 필요한

      권한

      -통상 권한 이란 기기에서 코드의 일부분 또는 데이터에 대한 액세스를 한정하는 -제한입니다. 이런 한계를 부과하는 것은 중요한 데이터와 코드를 보호하여 -이들이 남용되어서 사용자 환경을 왜곡하거나 손상시키지 않도록 하기 위해서입니다. +통상 권한 이란 기기에서 코드의 일부분 또는 데이터에 대한 액세스를 한정하는 +제한입니다. 이런 한계를 부과하는 것은 중요한 데이터와 코드를 보호하여 +이들이 남용되어서 사용자 환경을 왜곡하거나 손상시키지 않도록 하기 위해서입니다.

      -각 권한은 고유한 레이블로 식별할 수 있습니다. 레이블을 보면 자신이 어떤 작업을 제한하는지 -나타내는 경우가 잦습니다. 예를 들어 다음은 Android가 정의하는 몇 가지 권한을 나타낸 +각 권한은 고유한 레이블로 식별할 수 있습니다. 레이블을 보면 자신이 어떤 작업을 제한하는지 +나타내는 경우가 잦습니다. 예를 들어 다음은 Android가 정의하는 몇 가지 권한을 나타낸 것입니다.

      @@ -418,26 +418,26 @@ Android는 인텐트에 응답할 적절한 구성 요소를 찾아 필요한

      -애플리케이션에서 권한으로 보호하는 기능에 액세스해야 하는 경우, -해당 권한이 필요하다고 매니페스트의 -<uses-permission> -요소로 선언해야 합니다. 그런 다음, 해당 애플리케이션이 기기에 설치되고 나면 -설치 관리자가 요청한 권한을 허가할지 여부를 판별합니다. -이때 애플리케이션의 인증서를 서명한 권한을 확인하고 어떤 경우에는 사용자에게 -묻기도 합니다. -권한이 허가되면 해당 애플리케이션은 보호된 기능을 사용할 수 -있습니다. 허가되지 않으면, 그러한 기능에 액세스하려는 애플리케이션의 시도가 단순히 실패하고 사용자에게는 -아무런 알림도 표시되지 않습니다. +애플리케이션에서 권한으로 보호하는 기능에 액세스해야 하는 경우, +해당 권한이 필요하다고 매니페스트의 +<uses-permission> +요소로 선언해야 합니다. 그런 다음, 해당 애플리케이션이 기기에 설치되고 나면 +설치 관리자가 요청한 권한을 허가할지 여부를 판별합니다. +이때 애플리케이션의 인증서를 서명한 권한을 확인하고 어떤 경우에는 사용자에게 +묻기도 합니다. +권한이 허가되면 해당 애플리케이션은 보호된 기능을 사용할 수 +있습니다. 허가되지 않으면, 그러한 기능에 액세스하려는 애플리케이션의 시도가 단순히 실패하고 사용자에게는 +아무런 알림도 표시되지 않습니다.

      -애플리케이션은 권한을 사용하여 자신의 구성 요소를(액티비티, 서비스, -브로드캐스트 수신기 및 콘텐츠 제공자) 보호할 수도 있습니다. Android가 정의한 +애플리케이션은 권한을 사용하여 자신의 구성 요소를(액티비티, 서비스, +브로드캐스트 수신기 및 콘텐츠 제공자) 보호할 수도 있습니다. Android가 정의한 권한이라면 어떤 것이든 사용할 수 있고( -{@link android.Manifest.permission android.Manifest.permission}에 목록으로 나열), -아니면 다른 애플리케이션이 선언한 권한을 사용해도 됩니다. 아예 직접 자신만의 권한을 정의해도 됩니다. 새 권한을 선언할 때에는 +{@link android.Manifest.permission android.Manifest.permission}에 목록으로 나열), +아니면 다른 애플리케이션이 선언한 권한을 사용해도 됩니다. 아예 직접 자신만의 권한을 정의해도 됩니다. 새 권한을 선언할 때에는 -<permission> +<permission> 요소를 사용합니다. 예를 들어 액티비티를 보호하려면 다음과 같이 하면 됩니다.

      @@ -457,43 +457,43 @@ Android는 인텐트에 응답할 적절한 구성 요소를 찾아 필요한

      -이 예시에서는 {@code DEBIT_ACCT} 권한이 - -<permission> -요소로 선언하였을 뿐만 아니라, 해당 권한의 사용 또한 -<uses-permission> -요소로 요청되었다는 점을 눈여겨 보십시오. 이것의 사용을 요청해야 애플리케이션의 다른 구성 요소가 보호된 -액티비티를 시작할 수 있습니다. 이는 해당 보호를 애플리케이션 자신이 부과한 것이더라도 -관계 없이 적용됩니다. +이 예시에서는 {@code DEBIT_ACCT} 권한이 + +<permission> +요소로 선언하였을 뿐만 아니라, 해당 권한의 사용 또한 +<uses-permission> +요소로 요청되었다는 점을 눈여겨 보십시오. 이것의 사용을 요청해야 애플리케이션의 다른 구성 요소가 보호된 +액티비티를 시작할 수 있습니다. 이는 해당 보호를 애플리케이션 자신이 부과한 것이더라도 +관계 없이 적용됩니다.

      -같은 예시에서, {@code permission} 속성이 다른 곳에서 +같은 예시에서, {@code permission} 속성이 다른 곳에서 선언한 권한에 설정된 경우 -(예: {@code android.permission.CALL_EMERGENCY_NUMBERS}), 이것을 +(예: {@code android.permission.CALL_EMERGENCY_NUMBERS}), 이것을 -<permission> -요소를 사용하여 다시 선언할 필요가 없습니다. 하지만 해당 권한의 사용은 여전히 -<uses-permission>로 요청해야 합니다. +<permission> +요소를 사용하여 다시 선언할 필요가 없습니다. 하지만 해당 권한의 사용은 여전히 +<uses-permission>로 요청해야 합니다.

      -<permission-tree> -요소는 코드로 정의될 권한 그룹에 대한 네임스페이스를 -선언합니다. 그리고 +<permission-tree> +요소는 코드로 정의될 권한 그룹에 대한 네임스페이스를 +선언합니다. 그리고 <permission-group> -가 권한 집합에 대한 레이블을 정의합니다(매니페스트에 -<permission> -요소로 선언한 것과 다른 곳에서 선언한 것 양쪽 모두). 이것은 권한이 사용자에게 표시될 때 -그룹 지정될 방식에만 영향을 미칩니다. +가 권한 집합에 대한 레이블을 정의합니다(매니페스트에 +<permission> +요소로 선언한 것과 다른 곳에서 선언한 것 양쪽 모두). 이것은 권한이 사용자에게 표시될 때 +그룹 지정될 방식에만 영향을 미칩니다. <permission-group> -요소는 그룹에 어느 권한이 속해 있는지 지정하는 것이 아니라, 그저 -그룹에 이름을 부여할 뿐입니다. 그룹에 권한을 배치하려면 그룹 이름을 +요소는 그룹에 어느 권한이 속해 있는지 지정하는 것이 아니라, 그저 +그룹에 이름을 부여할 뿐입니다. 그룹에 권한을 배치하려면 그룹 이름을 -<permission> -요소의 -permissionGroup +<permission> +요소의 +permissionGroup 속성에 할당하면 됩니다.

      @@ -501,17 +501,17 @@ Android는 인텐트에 응답할 적절한 구성 요소를 찾아 필요한

      라이브러리

      -모든 애플리케이션은 기본 Android 라이브러리에 연결되어 있습니다. 여기에는 -애플리케이션 구축을 위한 기본적인 패키지(액티비티, 서비스, -인텐트, 보기, 버튼, 애플리케이션, ContentProvider 등 보편적인 클래스 포함)가 포함되어 +모든 애플리케이션은 기본 Android 라이브러리에 연결되어 있습니다. 여기에는 +애플리케이션 구축을 위한 기본적인 패키지(액티비티, 서비스, +인텐트, 보기, 버튼, 애플리케이션, ContentProvider 등 보편적인 클래스 포함)가 포함되어 있습니다.

      -그러나 패키지 가운데에는 자신만의 라이브러리에 속한 것도 있습니다. 애플리케이션이 -사용하는 코드의 출처가 이러한 패키지 가운데 어느 한 가지에 해당되는 경우, 해당 패키지에 연결되도록 -명시적으로 요청해야만 합니다. 매니페스트에는 별도의 -<uses-library> -요소가 들어 있어 각 라이브러리의 이름을 나타내야 합니다 (라이브러리 이름은 패키지에 대한 +그러나 패키지 가운데에는 자신만의 라이브러리에 속한 것도 있습니다. 애플리케이션이 +사용하는 코드의 출처가 이러한 패키지 가운데 어느 한 가지에 해당되는 경우, 해당 패키지에 연결되도록 +명시적으로 요청해야만 합니다. 매니페스트에는 별도의 +<uses-library> +요소가 들어 있어 각 라이브러리의 이름을 나타내야 합니다 (라이브러리 이름은 패키지에 대한 관련 문서에서 찾을 수 있습니다).

      diff --git a/docs/html-intl/intl/ko/guide/topics/providers/calendar-provider.jd b/docs/html-intl/intl/ko/guide/topics/providers/calendar-provider.jd index 4d69b6029ec4907f3faa3b19a196dd1d84048fc1..a2a20aff40ffdfedbfca6b73f61efb70cb6cd2be 100644 --- a/docs/html-intl/intl/ko/guide/topics/providers/calendar-provider.jd +++ b/docs/html-intl/intl/ko/guide/topics/providers/calendar-provider.jd @@ -42,7 +42,7 @@ page.title=캘린더 제공자
    • 인텐트를 사용하여 캘린더 데이터 보기
    • - +
    • 동기화 어댑터
    • @@ -56,47 +56,47 @@ page.title=캘린더 제공자 -

      캘린더 제공자는 사용자의 캘린더 이벤트를 저장하는 리포지토리입니다. -캘린더 제공자 API를 사용하면 캘린더, 이벤트, 참석자, 알림 등의 쿼리, 삽입, 업데이트 및 +

      캘린더 제공자는 사용자의 캘린더 이벤트를 저장하는 리포지토리입니다. +캘린더 제공자 API를 사용하면 캘린더, 이벤트, 참석자, 알림 등의 쿼리, 삽입, 업데이트 및 삭제 등의 작업을 수행할 수 있습니다.

      -

      캘린더 제공자 API는 애플리케이션과 동기화 어댑터에서 사용할 수 있습니다. -어떤 유형의 프로그램이 호출을 하는 주체인지에 따라 규칙이 각기 다릅니다. -이 문서는 주로 캘린더 제공자 API를 애플리케이션으로 사용하는 것에 주안점을 두었습니다. -여러 동기화 어댑터가 서로 어떻게 다른지 논의한 내용은 +

      캘린더 제공자 API는 애플리케이션과 동기화 어댑터에서 사용할 수 있습니다. +어떤 유형의 프로그램이 호출을 하는 주체인지에 따라 규칙이 각기 다릅니다. +이 문서는 주로 캘린더 제공자 API를 애플리케이션으로 사용하는 것에 주안점을 두었습니다. +여러 동기화 어댑터가 서로 어떻게 다른지 논의한 내용은 동기화 어댑터를 참조하십시오.

      -

      캘린더 데이터를 읽거나 쓰려면 보통 애플리케이션의 매니페스트에 -적절한 권한이 포함되어 있어야 합니다. 이는 사용자 +

      캘린더 데이터를 읽거나 쓰려면 보통 애플리케이션의 매니페스트에 +적절한 권한이 포함되어 있어야 합니다. 이는 사용자 권한에 설명되어 있습니다. 공통 작업을 쉽게 수행하기 위해 캘린더 제공자는 캘린더 -인텐트에 설명된 바와 같이 인텐트 집합을 제공합니다. 이와 같은 인텐트는 사용자를 캘린더 애플리케이션으로 이동시켜 -이벤트 삽입, 보기 및 편집을 할 수 있게 해줍니다. 사용자는 캘린더 애플리케이션과 상호 작용한 다음 -원래 애플리케이션으로 돌아옵니다. 따라서, 여러분의 애플리케이션이 이벤트를 보거나 +인텐트에 설명된 바와 같이 인텐트 집합을 제공합니다. 이와 같은 인텐트는 사용자를 캘린더 애플리케이션으로 이동시켜 +이벤트 삽입, 보기 및 편집을 할 수 있게 해줍니다. 사용자는 캘린더 애플리케이션과 상호 작용한 다음 +원래 애플리케이션으로 돌아옵니다. 따라서, 여러분의 애플리케이션이 이벤트를 보거나 생성하기 위해 권한 허가를 요청할 필요도 없고 사용자 인터페이스를 제공할 필요도 없는 것입니다.

      기본 정보

      -

      콘텐츠 제공자는 데이터를 저장하여 애플리케이션에서 +

      콘텐츠 제공자는 데이터를 저장하여 애플리케이션에서 이에 액세스할 수 있도록 합니다. 일반적으로, Android 플랫폼에서 제공하는 콘텐츠 제공자(캘린더 제공자 포함)는 관계 데이터베이스 모델에 기초하여 테이블 집합으로 데이터를 노출합니다. 이 모델에서 각 행은 레코드이고, -각 열은 특정한 유형과 의미를 가진 데이터입니다. 애플리케이션과 동기화 어댑터는 -캘린더 제공자 API를 통해 사용자의 캘린더 데이터를 보관하고 있는 데이터베이스 테이블에 +각 열은 특정한 유형과 의미를 가진 데이터입니다. 애플리케이션과 동기화 어댑터는 +캘린더 제공자 API를 통해 사용자의 캘린더 데이터를 보관하고 있는 데이터베이스 테이블에 읽기/쓰기 액세스 권한을 얻을 수 있습니다.

      모든 콘텐츠 제공자는 데이터 세트를 고유하게 식별하는 공개 URI( -{@link android.net.Uri} +{@link android.net.Uri} 개체로 래핑됨)를 노출합니다. 여러 데이터 세트(여러 테이블)를 제어하는 콘텐츠 제공자는 -각 데이터 세트에 별도의 URI를 노출합니다. -제공자에 대한 URI는 모두 문자열 "content://"로 시작합니다. -이것을 보면 데이터를 콘텐츠 제공자가 제어하고 있다는 것을 알아볼 수 있습니다. -캘린더 제공자가 각각의 클래스(테이블)에 대한 URI의 상수를 정의합니다. -이와 같은 URI는 <class>.CONTENT_URI 형식을 취합니다. +각 데이터 세트에 별도의 URI를 노출합니다. +제공자에 대한 URI는 모두 문자열 "content://"로 시작합니다. +이것을 보면 데이터를 콘텐츠 제공자가 제어하고 있다는 것을 알아볼 수 있습니다. +캘린더 제공자가 각각의 클래스(테이블)에 대한 URI의 상수를 정의합니다. +이와 같은 URI는 <class>.CONTENT_URI 형식을 취합니다. 예를 들면 다음과 같습니다. {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}

      -

      그림 1은 캘린더 제공자 데이터 모델을 그림으로 나타낸 것입니다. +

      그림 1은 캘린더 제공자 데이터 모델을 그림으로 나타낸 것입니다. 이 그림에는 메인 테이블과이들을 서로 연결하는 필드가 표시되어 있습니다.

      Calendar Provider Data Model @@ -113,77 +113,77 @@ page.title=캘린더 제공자

      {@link android.provider.CalendarContract.Calendars}

      - + 이 테이블에는 캘린더별 정보가 담겨 있습니다. - 이 테이블의 행마다 한 캘린더의 세부 정보, + 이 테이블의 행마다 한 캘린더의 세부 정보, 예를 들어 이름, 색상, 동기화 정보 등이 들어갑니다. {@link android.provider.CalendarContract.Events} - + 이 테이블에는 이벤트별 정보가 담겨 있습니다. 이 테이블의 행마다 한 이벤트의 세부 정보 예를 들어 이벤트 제목, 위치, 시작 시간, 종료 시간 등의 정보가 들어갑니다. - 이벤트는 일회성일 수도 있고 여러 번 반복될 수도 있습니다. -참석자, 알림 및 확장된 속성 등은 별도의 테이블에 저장됩니다. -이들 테이블에는 각기 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}가 있어 + 이벤트는 일회성일 수도 있고 여러 번 반복될 수도 있습니다. +참석자, 알림 및 확장된 속성 등은 별도의 테이블에 저장됩니다. +이들 테이블에는 각기 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}가 있어 이벤트 테이블의 {@link android.provider.BaseColumns#_ID}를 참조합니다. {@link android.provider.CalendarContract.Instances} - - 이 테이블에는 각 이벤트 발생의 시작 시간과 종료 시간이 + + 이 테이블에는 각 이벤트 발생의 시작 시간과 종료 시간이 담겨 있습니다. 이 테이블의 각 행이 하나의 이벤트 발생을 나타냅니다. 일회성 이벤트의 경우, 이벤트에 대한 1:1 인스턴스 매핑이 있습니다. - 반복되는 이벤트의 경우, 해당 이벤트가 여러 번 발생하는 것에 맞추어 + 반복되는 이벤트의 경우, 해당 이벤트가 여러 번 발생하는 것에 맞추어 자동으로 여러 행이 생성됩니다. {@link android.provider.CalendarContract.Attendees} - + 이 테이블에는 이벤트 참석자(게스트) 정보가 담겨 있습니다. 각 행이 주어진 이벤트의 게스트 한 사람을 나타냅니다. - 이것이 게스트의 유형과, 이벤트에 대한 해당 게스트의 참석 여부 응답을 + 이것이 게스트의 유형과, 이벤트에 대한 해당 게스트의 참석 여부 응답을 나타냅니다. {@link android.provider.CalendarContract.Reminders} - + 이 테이블에는 경고/알림 데이터가 담겨 있습니다. - 각 행이 주어진 이벤트에 대한 경고 하나를 나타냅니다. + 각 행이 주어진 이벤트에 대한 경고 하나를 나타냅니다. 이벤트 하나에 여러 개의 알림이 있을 수 있습니다. 이벤트당 최대 알림 개수는 -{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}에서 지정되고, +{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}에서 지정되고, 이는 주어진 캘린더를 소유한 동기화 어댑터가 설정합니다. - 알림은 이벤트 몇 분 전에 지정되며 사용자에게 어떻게 경고할 것인지를 + 알림은 이벤트 몇 분 전에 지정되며 사용자에게 어떻게 경고할 것인지를 결정하는 메서드를 가지고 있습니다. - + -

      캘린더 제공자 API는 유연성과 강력함을 염두에 두고 만들어진 것입니다. -그와 동시에 우수한 최종 사용자 경험을 제공하고 캘린더와 그 데이터의 +

      캘린더 제공자 API는 유연성과 강력함을 염두에 두고 만들어진 것입니다. +그와 동시에 우수한 최종 사용자 경험을 제공하고 캘린더와 그 데이터의 무결성을 보호하는 것 또한 중요합니다. 이를 위해서 API를 사용할 때 유념해야 할 사항은 다음과 같습니다.

        -
      • 캘린더 이벤트 삽입, 업데이트 및 보기. 캘린더 제공자로부터 직접 이벤트를 삽입, 변경하고 읽으려면 적절한 권한이 필요합니다. 그러나, 완전한 캘린더 애플리케이션 또는 동기화 어댑터를 구축하는 경우가 아니라면 이와 같은 권한을 요청할 필요가 없습니다. 대신 Android의 캘린더 애플리케이션이 지원하는 인텐트를 사용하여 해당 애플리케이션에 읽기 및 쓰기 작업을 분배하면 됩니다. 인텐트를 사용하면, 애플리케이션이 사용자를 캘린더 애플리케이션으로 보내 사전에 작성된 양식으로 원하는 작업을 -수행하게 합니다. 작업이 끝나면 사용자는 애플리케이션으로 돌아옵니다. -캘린더를 통해 공통 작업을 수행하도록 애플리케이션을 설계함으로써 사용자에게 일관되고 강력한 +
      • 캘린더 이벤트 삽입, 업데이트 및 보기. 캘린더 제공자로부터 직접 이벤트를 삽입, 변경하고 읽으려면 적절한 권한이 필요합니다. 그러나, 완전한 캘린더 애플리케이션 또는 동기화 어댑터를 구축하는 경우가 아니라면 이와 같은 권한을 요청할 필요가 없습니다. 대신 Android의 캘린더 애플리케이션이 지원하는 인텐트를 사용하여 해당 애플리케이션에 읽기 및 쓰기 작업을 분배하면 됩니다. 인텐트를 사용하면, 애플리케이션이 사용자를 캘린더 애플리케이션으로 보내 사전에 작성된 양식으로 원하는 작업을 +수행하게 합니다. 작업이 끝나면 사용자는 애플리케이션으로 돌아옵니다. +캘린더를 통해 공통 작업을 수행하도록 애플리케이션을 설계함으로써 사용자에게 일관되고 강력한 사용자 인터페이스를 제공하는 것입니다. 이것이 권장 방법입니다. 자세한 정보는 캘린더 인텐트를 참조하십시오.

        -
      • 동기화 어댑터. -동기화 어댑터는 사용자의 기기에 있는 캘린더 데이터를 다른 서버 또는 데이터 소스와 동기화합니다. +
      • 동기화 어댑터. +동기화 어댑터는 사용자의 기기에 있는 캘린더 데이터를 다른 서버 또는 데이터 소스와 동기화합니다. {@link android.provider.CalendarContract.Calendars}와 {@link android.provider.CalendarContract.Events} 테이블에는 동기화 어댑터가 사용하도록 예약된 열이 있습니다. -제공자와 애플리케이션은 이를 수정해서는 안 됩니다. 사실, 동기화 어댑터로 액세스하지 않는 한 -이 열이 표시되지 않습니다. +제공자와 애플리케이션은 이를 수정해서는 안 됩니다. 사실, 동기화 어댑터로 액세스하지 않는 한 +이 열이 표시되지 않습니다. 동기화 어댑터에 대한 자세한 정보는 동기화 어댑터를 참조하십시오.
      @@ -192,8 +192,8 @@ API를 사용할 때 유념해야 할 사항은 다음과 같습니다.

      사용자 권한

      캘린더 데이터를 읽으려면 애플리케이션의 매니페스트 파일에 {@link -android.Manifest.permission#READ_CALENDAR} 권한이 포함되어 있어야 합니다. -캘린더 데이터를 삭제, 삽입 또는 업데이트하려면{@link android.Manifest.permission#WRITE_CALENDAR} +android.Manifest.permission#READ_CALENDAR} 권한이 포함되어 있어야 합니다. +캘린더 데이터를 삭제, 삽입 또는 업데이트하려면{@link android.Manifest.permission#WRITE_CALENDAR} 권한이 포함되어 있어야 합니다.

      @@ -209,10 +209,10 @@ android.Manifest.permission#READ_CALENDAR} 권한이 포함되어 있어야 합
       
       

      캘린더 테이블

      -

      {@link android.provider.CalendarContract.Calendars} -테이블에는 각각의 캘린더에 대한 세부 정보가 들어 있습니다. -다음 캘린더 열은 애플리케이션과 동기화 어댑터 모두 쓸 수 있는 것입니다. -지원되는 필드의 전체 목록은 +

      {@link android.provider.CalendarContract.Calendars} +테이블에는 각각의 캘린더에 대한 세부 정보가 들어 있습니다. +다음 캘린더 열은 애플리케이션과 동기화 어댑터 모두 쓸 수 있는 것입니다. +지원되는 필드의 전체 목록은 {@link android.provider.CalendarContract.Calendars} 참조를 확인하십시오.

      @@ -229,8 +229,8 @@ android.Manifest.permission#READ_CALENDAR} 권한이 포함되어 있어야 합 - - - -
      {@link android.provider.CalendarContract.Calendars#VISIBLE}캘린더를 표시하기로 선택했는지를 나타내는 부울입니다. + + 캘린더를 표시하기로 선택했는지를 나타내는 부울입니다. 값이 0이면 이 캘린더와 연관된 이벤트는 표시하면 안 된다는 뜻입니다. 값이 1이면 이 캘린더와 연관된 이벤트를 표시해야 한다는 뜻입니다. 이 값이 {@link @@ -240,10 +240,10 @@ android.provider.CalendarContract.Instances} 테이블의 행 생성에 영향
      {@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}캘린더를 동기화하고 이 캘린더의 이벤트를 기기에 저장해야할지를 -나타내는 부울입니다. 값이 0이면 이 캘린더를 동기화하거나 이에 속한 이벤트를 -기기에 저장하면 안 된다는 뜻입니다. 값이 1이면 이 캘린더에 대한 이벤트를 동기화하고 이에 속한 + + 캘린더를 동기화하고 이 캘린더의 이벤트를 기기에 저장해야할지를 +나타내는 부울입니다. 값이 0이면 이 캘린더를 동기화하거나 이에 속한 이벤트를 +기기에 저장하면 안 된다는 뜻입니다. 값이 1이면 이 캘린더에 대한 이벤트를 동기화하고 이에 속한 이벤트를 기기에 저장하라는 뜻입니다.
      @@ -253,8 +253,8 @@ android.provider.CalendarContract.Instances} 테이블의 행 생성에 영향

      다음은 특정한 사용자가 소유한 캘린더를 가져오는 법을 나타낸 예시입니다. 이 예시에서는 단순하게 나타내기 위해 쿼리 작업을 사용자 인터페이스 스레드("주 스레드")에 표시했습니다. 실제로는, 이 작업은 주 스레드 대신 비동기화 스레드에서 해야 합니다. - 자세한 논의는 -로더를 참조하십시오. 데이터를 읽기만 하는 것이 아니라 변경도 하는 경우라면, + 자세한 논의는 +로더를 참조하십시오. 데이터를 읽기만 하는 것이 아니라 변경도 하는 경우라면, {@link android.content.AsyncQueryHandler}를 참조하십시오.

      @@ -268,90 +268,90 @@ public static final String[] EVENT_PROJECTION = new String[] { Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;
      - + +

      다음 예시에서는 여러분이 직접 나름의 쿼리를 생성해보십시오. 선택 영역이 쿼리의 기준을 나타냅니다. - 이 예시에서 쿼리는 + 이 예시에서 쿼리는 ACCOUNT_NAME "sampleuser@google.com", ACCOUNT_TYPE "com.google" 및 OWNER_ACCOUNT -"sampleuser@google.com"을 가지고 있는 캘린더를 찾고 있습니다. 사용자가 소유한 캘린더뿐만 아니라 사용자가 전에 본 캘린더까지 모두 확인하려면 -OWNER_ACCOUNT를 생략합니다. +"sampleuser@google.com"을 가지고 있는 캘린더를 찾고 있습니다. 사용자가 소유한 캘린더뿐만 아니라 사용자가 전에 본 캘린더까지 모두 확인하려면 +OWNER_ACCOUNT를 생략합니다. 쿼리가 {@link android.database.Cursor} 개체를 반환하여 이를 시용하면 데이터베이스 쿼리가 반환한 결과 집합을 트래버스할 수 있습니다. - 콘텐츠 제공자에서 쿼리를 사용하는 법에 대한 자세한 논의는 + 콘텐츠 제공자에서 쿼리를 사용하는 법에 대한 자세한 논의는 콘텐츠 제공자를 참조하십시오.

      // Run query
       Cursor cur = null;
       ContentResolver cr = getContentResolver();
      -Uri uri = Calendars.CONTENT_URI;   
      -String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
      +Uri uri = Calendars.CONTENT_URI;
      +String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                               + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                               + Calendars.OWNER_ACCOUNT + " = ?))";
       String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
      -        "sampleuser@gmail.com"}; 
      -// Submit the query and get a Cursor object back. 
      +        "sampleuser@gmail.com"};
      +// Submit the query and get a Cursor object back.
       cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
      -

      다음에 표시된 섹션에서는 커서를 사용하여 결과 집합을 단계별로 살펴봅니다. +

      다음에 표시된 섹션에서는 커서를 사용하여 결과 집합을 단계별로 살펴봅니다. 여기에서는 예시의 시작 부분에서 설정된 상수를 사용하여 각 필드에 대한 값을 반환합니다.

      - +
      // Use the cursor to step through the returned records
       while (cur.moveToNext()) {
           long calID = 0;
           String displayName = null;
           String accountName = null;
           String ownerName = null;
      -      
      +
           // Get the field values
           calID = cur.getLong(PROJECTION_ID_INDEX);
           displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
           accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
           ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
      -              
      +
           // Do something with the values...
       
          ...
       }
       
      - +

      캘린더 수정

      캘린더 업데이트를 수행하려면 캘린더의 {@link -android.provider.BaseColumns#_ID}를 +android.provider.BaseColumns#_ID}를 URI에 추가된 ID로 ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}), 또는 첫 번째 선택 항목으로 제공하면 됩니다. - -선택은 "_id=?"로 시작해야 하며, 첫 번째 + +선택은 "_id=?"로 시작해야 하며, 첫 번째 selectionArg는 캘린더의 {@link -android.provider.BaseColumns#_ID}여야 합니다. -또한 ID를 URI에 인코딩해서도 업데이트를 수행할 수 있습니다. 이 예시에서는 캘린더의 표시 이름을 +android.provider.BaseColumns#_ID}여야 합니다. +또한 ID를 URI에 인코딩해서도 업데이트를 수행할 수 있습니다. 이 예시에서는 캘린더의 표시 이름을 ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 방식으로 변경하였습니다.

      @@ -368,26 +368,26 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows);

      캘린더 삽입

      -

      캘린더는 주로 동기화 어댑터가 관리하도록 설계되어 있습니다. 따라서 새 캘린더는 -동기화 어댑터로서만 삽입해야 합니다. 대다수의 경우 애플리케이션은 캘린더에 -표면적인 사항만 변경할 수 있게 되어 있습니다(예: 표시 이름 변경 등). -어떤 애플리케이션이 로컬 캘린더를 생성해야 하는 경우, 캘린더 삽입을 동기화 어댑터로 수행하면 됩니다. +

      캘린더는 주로 동기화 어댑터가 관리하도록 설계되어 있습니다. 따라서 새 캘린더는 +동기화 어댑터로서만 삽입해야 합니다. 대다수의 경우 애플리케이션은 캘린더에 +표면적인 사항만 변경할 수 있게 되어 있습니다(예: 표시 이름 변경 등). +어떤 애플리케이션이 로컬 캘린더를 생성해야 하는 경우, 캘린더 삽입을 동기화 어댑터로 수행하면 됩니다. 이때 {@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}의 {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE}을 사용합니다. {@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} 은 기기 계정과 연관되지 않은 캘린더에 적용되는 특별한 유형의 계정입니다. - 이 유형의 캘린더는 서버에 동기화되지 않습니다. + 이 유형의 캘린더는 서버에 동기화되지 않습니다. 동기화 어댑터에 대한 논의는 동기화 어댑터를 참조하십시오.

      이벤트 테이블

      -

      {@link android.provider.CalendarContract.Events} -테이블에는 각각의 이벤트에 대한 세부 정보가 들어 있습니다. 이벤트를 추가, 업데이트 또는 삭제하려면 애플리케이션의 +

      {@link android.provider.CalendarContract.Events} +테이블에는 각각의 이벤트에 대한 세부 정보가 들어 있습니다. 이벤트를 추가, 업데이트 또는 삭제하려면 애플리케이션의 매니페스트 파일에 {@link android.Manifest.permission#WRITE_CALENDAR} 권한이 포함되어 있어야 합니다.

      -

      다음 이벤트 열은 애플리케이션과 +

      다음 이벤트 열은 애플리케이션과 동기화 어댑터 모두 쓸 수 있는 것입니다. 지원되는 필드의 전체 목록은 {@link android.provider.CalendarContract.Events} 참조를 확인하십시오.

      @@ -434,9 +434,9 @@ android.provider.CalendarContract.Events} 참조를 확인하십시오.

      {@link android.provider.CalendarContract.EventsColumns#DURATION} - + 이벤트 기간을 RFC5545 형식으로 나타낸 것입니다. -예를 들어 "PT1H" 값을 보면 이벤트가 한 시간 지속될 것임을 알 수 있고, +예를 들어 "PT1H" 값을 보면 이벤트가 한 시간 지속될 것임을 알 수 있고, "P2W"는 2주의 지속 기간을 나타냅니다. @@ -444,39 +444,39 @@ android.provider.CalendarContract.Events} 참조를 확인하십시오.

      {@link android.provider.CalendarContract.EventsColumns#ALL_DAY} - + 값이 1이면 이 이벤트가 현지 시간대에서 정의한 바에 의해 하루 종일 걸린다는 것을 나타냅니다. 값이 0이면 이것이 하루 중 언제라도 시작하고 종료될 수 있는 정기 이벤트라는 것을 나타냅니다. - + - - + + {@link android.provider.CalendarContract.EventsColumns#RRULE} - - 이벤트 형식의 반복 규칙입니다. -예를 들면 다음과 같습니다. "FREQ=WEEKLY;COUNT=10;WKST=SU" 더 많은 예시를 확인하려면 + + 이벤트 형식의 반복 규칙입니다. +예를 들면 다음과 같습니다. "FREQ=WEEKLY;COUNT=10;WKST=SU" 더 많은 예시를 확인하려면 여기를 참조하십시오. - + - + {@link android.provider.CalendarContract.EventsColumns#RDATE} - 이벤트의 반복 날짜입니다. + 이벤트의 반복 날짜입니다. 일반적으로 {@link android.provider.CalendarContract.EventsColumns#RDATE} 를 {@link android.provider.CalendarContract.EventsColumns#RRULE} 과 함께 사용하여 반복되는 발생의 집계 집합을 정의하게 됩니다. 자세한 논의는 RFC5545 사양을 참조하십시오. - + {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY} - + 이 이벤트가 사용 중인 시간으로 간주되는지, 다시 일정을 예약할 수 있는 자유 시간으로 간주되는지를 나타냅니다. - + {@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY} @@ -494,7 +494,7 @@ android.provider.CalendarContract.Events} 참조를 확인하십시오.

      이벤트 추가

      -

      애플리케이션이 새 이벤트를 추가하는 경우, +

      애플리케이션이 새 이벤트를 추가하는 경우, {@link android.content.Intent#ACTION_INSERT INSERT} 인텐트를 사용하는 것이 좋습니다. 이때 인텐트를 사용하여 이벤트 삽입에서 설명한 대로 따릅니다. 그러나, 필요한 경우 직접 이벤트를 삽입해도 됩니다. 이 섹션에서는 이렇게 하는 방법을 설명합니다.

      @@ -508,39 +508,39 @@ android.provider.CalendarContract.EventsColumns#CALENDAR_ID}와 {@link android.provider.CalendarContract.EventsColumns#DTSTART}를 포함해야 합니다.
    • {@link -android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}을 포함해야 합니다. +android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}을 포함해야 합니다. 시스템에 설치된 표준 시간대 ID 목록을 가져오려면 {@link java.util.TimeZone#getAvailableIDs()}를 사용하십시오. 이 규칙은 인텐트를 사용하여 이벤트 삽입에서 설명한 바와 같이 {@link android.content.Intent#ACTION_INSERT INSERT} 인텐트를 통해서 이벤트를 삽입할 경우에는 적용되지 않습니다. 이 시나리오의 경우, 기본 시간대가 제공됩니다.
    • - +
    • 비반복적인 이벤트의 경우, {@link android.provider.CalendarContract.EventsColumns#DTEND}를 포함해야 합니다.
    • - - + +
    • 반복적인 이벤트의 경우 {@link android.provider.CalendarContract.EventsColumns#DURATION}과 {@link android.provider.CalendarContract.EventsColumns#RRULE} 또는 {@link android.provider.CalendarContract.EventsColumns#RDATE}를 포함해야 합니다. 이 규칙은 인텐트를 사용하여 이벤트 삽입에서 설명한 바와 같이 {@link -android.content.Intent#ACTION_INSERT INSERT} 인텐트를 통해서 이벤트를 삽입할 경우에는 적용되지 않습니다. +android.content.Intent#ACTION_INSERT INSERT} 인텐트를 통해서 이벤트를 삽입할 경우에는 적용되지 않습니다. 이 시나리오에서는 {@link android.provider.CalendarContract.EventsColumns#DTSTART} 및 {@link android.provider.CalendarContract.EventsColumns#DTEND}와 함께 {@link android.provider.CalendarContract.EventsColumns#RRULE}를 사용할 수 있고, 캘린더 애플리케이션이 이것을 기간으로 자동 변환해줍니다.
    • - +

    다음은 이벤트 삽입의 예입니다. 단순하게 나타내기 위해 UI 스레드에서 수행한 것입니다. 실제로, 삽입과 업데이트는 비동기화 스레드에서 수행해야 작업을 배경 스레드로 이동시킬 수 있습니다. - + 자세한 정보는 {@link android.content.AsyncQueryHandler}를 참조하십시오.

     long calID = 3;
    -long startMillis = 0; 
    -long endMillis = 0;     
    +long startMillis = 0;
    +long endMillis = 0;
     Calendar beginTime = Calendar.getInstance();
     beginTime.set(2012, 9, 14, 7, 30);
     startMillis = beginTime.getTimeInMillis();
    @@ -561,13 +561,13 @@ Uri uri = cr.insert(Events.CONTENT_URI, values);
     
     // get the event ID that is the last element in the Uri
     long eventID = Long.parseLong(uri.getLastPathSegment());
    -// 
    +//
     // ... do something with event ID
     //
     //

    참고: 이벤트가 생성된 다음 이 예시가 이벤트 ID를 캡처하는 법을 눈여겨 보십시오. - 이것이 이벤트 ID를 가져오는 가장 쉬운 방법입니다. + 이것이 이벤트 ID를 가져오는 가장 쉬운 방법입니다. 다른 캘린더 작업을 수행하기 위해 이벤트 ID가 필요한 경우가 자주 있습니다. 예를 들어 이벤트에 참석자나 알림을 추가하는 데 필요합니다.

    @@ -577,15 +577,15 @@ long eventID = Long.parseLong(uri.getLastPathSegment());

    애플리케이션이 사용자에게 이벤트 편집을 허용할 경우, 인텐트로 이벤트 편집에서 설명한 바와 같이 {@link android.content.Intent#ACTION_EDIT EDIT} 인텐트 를 사용하는 것이 좋습니다. -그러나 필요한 경우 직접 이벤트를 편집해도 됩니다. +그러나 필요한 경우 직접 이벤트를 편집해도 됩니다. 이벤트 업데이트를 수행하려면 이벤트의 _ID를 URI에 추가된 ID로({@link -android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) +android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 또는 첫 번째 선택 항목으로 제공하면 됩니다. - -선택은 "_id=?"로 시작해야 하며, 첫 번째 -selectionArg는 이벤트의 _ID여야 합니다. + +선택은 "_id=?"로 시작해야 하며, 첫 번째 +selectionArg는 이벤트의 _ID여야 합니다. ID 없이 선택을 사용해도 업데이트를 수행할 수 있습니다. 다음은 이벤트 업데이트의 예입니다. - 여기에서는 이벤트 제목을 변경할 때 + 여기에서는 이벤트 제목을 변경할 때 {@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()} 방법을 사용합니다.

    @@ -598,7 +598,7 @@ ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event -values.put(Events.TITLE, "Kickboxing"); +values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows); @@ -608,11 +608,11 @@ Log.i(DEBUG_TAG, "Rows updated: " + rows);

    이벤트를 삭제하려면 이벤트의 {@link android.provider.BaseColumns#_ID}를 URI에 추가된 ID로 써도 되고, 표준 선택을 사용해도 됩니다. 추가된 ID를 사용하는 경우, 선택도 할 수 없습니다. -삭제에는 두 가지 버전이 있습니다. 애플리케이션으로 삭제와 동기화 어댑터로의 삭제입니다. -애플리케이션 삭제의 경우 삭제된 열을 1로 설정합니다. -이것은 동기화 어댑터에 행이 삭제되었다고 알리는 플래그이며, -이 삭제를 서버에 알려야 한다는 것을 나타내기도 합니다. -동기화 어댑터 삭제의 경우, 이벤트를 연관된 데이터 일체와 함께 데이터베이스에서 제거합니다. +삭제에는 두 가지 버전이 있습니다. 애플리케이션으로 삭제와 동기화 어댑터로의 삭제입니다. +애플리케이션 삭제의 경우 삭제된 열을 1로 설정합니다. +이것은 동기화 어댑터에 행이 삭제되었다고 알리는 플래그이며, +이 삭제를 서버에 알려야 한다는 것을 나타내기도 합니다. +동기화 어댑터 삭제의 경우, 이벤트를 연관된 데이터 일체와 함께 데이터베이스에서 제거합니다. 다음은 애플리케이션이 이벤트를 {@link android.provider.BaseColumns#_ID}를 통해 삭제하는 예입니다.

    @@ -625,22 +625,22 @@ ContentValues values = new ContentValues(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().delete(deleteUri, null, null); -Log.i(DEBUG_TAG, "Rows deleted: " + rows); +Log.i(DEBUG_TAG, "Rows deleted: " + rows);

    참석자 테이블

    {@link android.provider.CalendarContract.Attendees} 테이블의 각 행은 -이벤트의 참석자 또는 게스트 하나를 나타냅니다. +이벤트의 참석자 또는 게스트 하나를 나타냅니다. {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} -를호출하면 주어진 -{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}와 함께 해당 이벤트의 참석자 목록을 반환합니다. +를호출하면 주어진 +{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}와 함께 해당 이벤트의 참석자 목록을 반환합니다. 이 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}는 특정 이벤트의 {@link -android.provider.BaseColumns#_ID}와 반드시 일치해야 합니다.

    +android.provider.BaseColumns#_ID}와 반드시 일치해야 합니다.

    다음 표는 쓸 수 있는 필드를 목록으로 나열한 것입니다. - 새 참석자를 삽입하는 경우 이 모두를 포함해야 하며, + 새 참석자를 삽입하는 경우 이 모두를 포함해야 하며, 단 ATTENDEE_NAME은 예외입니다.

    @@ -697,7 +697,7 @@ android.provider.BaseColumns#_ID}와 반드시 일치해야 합니다.

    참석자 추가

    -

    다음은 이벤트에 참석자 한 명을 추가하는 예입니다. +

    다음은 이벤트에 참석자 한 명을 추가하는 예입니다. {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 가 필수인 점을 유념하십시오.

    @@ -717,8 +717,8 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values);

    알림 테이블

    -

    {@link android.provider.CalendarContract.Reminders} -테이블의 각 행은 이벤트의 알림 하나를 나타냅니다. +

    {@link android.provider.CalendarContract.Reminders} +테이블의 각 행은 이벤트의 알림 하나를 나타냅니다. {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 를 호출하면 주어진 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}와 함께 이벤트 알림 목록을 반환합니다.

    @@ -728,7 +728,7 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values); 동기화 어댑터가 {@link android.provider.CalendarContract.Calendars} 테이블에서 지원하는 알림을 나타낸다는 점을 눈여겨 보십시오. 자세한 내용은 -{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} +{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} 를 참조하십시오.

    @@ -774,15 +774,15 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values);

    인스턴스 테이블

    -{@link android.provider.CalendarContract.Instances} 테이블에는 +{@link android.provider.CalendarContract.Instances} 테이블에는 이벤트 발생의 시작 및 종료 시간이 담겨 있습니다. 이 테이블의 각 행이 하나의 이벤트 발생을 나타냅니다. 이 인스턴스 테이블은 쓸 수 없으며 이벤트 발생 쿼리 방법을 제공할 뿐입니다.

    -

    다음 표에는 인스턴스에 대해 쿼리할 수 있는 몇 가지 필드를 목록으로 나열하였습니다. -표준 시간대가 +

    다음 표에는 인스턴스에 대해 쿼리할 수 있는 몇 가지 필드를 목록으로 나열하였습니다. +표준 시간대가 {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} - 및 + 및 {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}에 의해 정의된다는 점을 눈여겨 보십시오.

    @@ -801,18 +801,18 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values); {@link android.provider.CalendarContract.Instances#END_DAY} - + 인스턴스의 율리우스력 종료 날짜를 캘린더의 시간대에 비례하여 나타낸 것입니다. - - + + {@link android.provider.CalendarContract.Instances#END_MINUTE} - + 인스턴스의 종료 시간(분 단위)을 캘린더 시간대의 자정부터 측정한 것입니다. - + {@link android.provider.CalendarContract.Instances#EVENT_ID} @@ -820,16 +820,16 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values); {@link android.provider.CalendarContract.Instances#START_DAY} - 인스턴스의 율리우스력 시작 날짜를 캘린더의 시간대에 비례하여 나타낸 것입니다. + 인스턴스의 율리우스력 시작 날짜를 캘린더의 시간대에 비례하여 나타낸 것입니다. {@link android.provider.CalendarContract.Instances#START_MINUTE} - + 인스턴스의 시작 시간(분 단위)을 캘린더 시간대에 비례하여 자정부터 측정한 것입니다. - + - + @@ -839,10 +839,10 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values);

    인스턴스 테이블을 쿼리하려면, 해당 쿼리에 대한 범위 시간을 URI에 지정해야 합니다. 이 예시에서는 {@link android.provider.CalendarContract.Instances} 가 {@link -android.provider.CalendarContract.EventsColumns#TITLE} 필드에 액세스 권한을 얻으며, 이때 -{@link android.provider.CalendarContract.EventsColumns} 인터페이스의 구현을 통합니다. +android.provider.CalendarContract.EventsColumns#TITLE} 필드에 액세스 권한을 얻으며, 이때 +{@link android.provider.CalendarContract.EventsColumns} 인터페이스의 구현을 통합니다. 바꿔 말하면, {@link -android.provider.CalendarContract.EventsColumns#TITLE}이 +android.provider.CalendarContract.EventsColumns#TITLE}이 데이터베이스 보기를 통해 반환되며 원시 {@link android.provider.CalendarContract.Instances} 테이블 쿼리를 통해서가 아니라는 뜻입니다.

    @@ -853,7 +853,7 @@ public static final String[] INSTANCE_PROJECTION = new String[] { Instances.BEGIN, // 1 Instances.TITLE // 2 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; @@ -868,7 +868,7 @@ long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); - + Cursor cur = null; ContentResolver cr = getContentResolver(); @@ -883,28 +883,28 @@ ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query -cur = cr.query(builder.build(), - INSTANCE_PROJECTION, - selection, - selectionArgs, +cur = cr.query(builder.build(), + INSTANCE_PROJECTION, + selection, + selectionArgs, null); - + while (cur.moveToNext()) { String title = null; long eventID = 0; - long beginVal = 0; - + long beginVal = 0; + // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); - - // Do something with the values. - Log.i(DEBUG_TAG, "Event: " + title); + + // Do something with the values. + Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(beginVal); + calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); + Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } } @@ -922,9 +922,9 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_VIEW VIEW}

    content://com.android.calendar/time/<ms_since_epoch>

    - -{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}로도 URI를 참조할 수 있습니다. -이 인텐트 사용법의 예시를 보려면 인텐트를 사용하여 캘린더 데이터 보기를 참조하십시오. + +{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}로도 URI를 참조할 수 있습니다. +이 인텐트 사용법의 예시를 보려면 인텐트를 사용하여 캘린더 데이터 보기를 참조하십시오. 캘린더를 <ms_since_epoch>에 의해 지정된 시간으로 엽니다. @@ -935,11 +935,11 @@ while (cur.moveToNext()) {

    content://com.android.calendar/events/<event_id>

    - - -{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다. + + +{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다. 이 인텐트 사용법의 예시를 보려면 인텐트를 사용하여 캘린더 데이터 보기를 참조하십시오. - + <event_id>에 의해 지정된 이벤트를 봅니다. @@ -952,12 +952,12 @@ while (cur.moveToNext()) { {@link android.content.Intent#ACTION_EDIT EDIT}

    content://com.android.calendar/events/<event_id>

    - - -{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다. + + +{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다. 이 인텐트 사용법의 예시를 보려면 인텐트를 사용하여 이벤트 편집을 참조하십시오. - - + + <event_id>에 의해 지정된 이벤트를 편집합니다. @@ -972,11 +972,11 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_INSERT INSERT}

    content://com.android.calendar/events

    - - -{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다. + + +{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다. 이 인텐트 사용법의 예시를 보려면 인텐트를 사용하여 이벤트 삽입을 참조하십시오. - + 이벤트를 생성합니다. @@ -996,7 +996,7 @@ while (cur.moveToNext()) { 이벤트의 이름입니다. - + {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} 이벤트 시작 시간을 Epoch로부터 밀리초 단위로 나타낸 것입니다. @@ -1004,25 +1004,25 @@ CalendarContract.EXTRA_EVENT_BEGIN_TIME} {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} - + 이벤트 종료 시간을 Epoch로부터 밀리초 단위로 나타낸 것입니다. {@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY CalendarContract.EXTRA_EVENT_ALL_DAY} - - 이벤트가 종일 이벤트인지 나타내는 부울입니다. 값은 + + 이벤트가 종일 이벤트인지 나타내는 부울입니다. 값은 true 또는 false가 될 수 있습니다. {@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION Events.EVENT_LOCATION} - + 이벤트 위치입니다. {@link android.provider.CalendarContract.EventsColumns#DESCRIPTION Events.DESCRIPTION} - + 이벤트 설명입니다. @@ -1039,43 +1039,43 @@ Events.DESCRIPTION} {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL Events.ACCESS_LEVEL} - + 이벤트가 비공개인지 공개인지 나타냅니다. {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY Events.AVAILABILITY} - + 이 이벤트가 사용 중인 시간으로 간주되는지, 다시 일정을 예약할 수 있는 자유 시간으로 간주되는지를 나타냅니다. - - + +

    아래 섹션에서는 이와 같은 인텐트의 사용법을 설명합니다.

    인텐트를 사용하여 이벤트 삽입

    -

    {@link android.content.Intent#ACTION_INSERT INSERT} 인텐트를 사용하면 +

    {@link android.content.Intent#ACTION_INSERT INSERT} 인텐트를 사용하면 캘린더에 이벤트 삽입 작업을 분배할 수 있습니다. 이 방법을 사용하는 경우, 애플리케이션의 매니페스트 파일에 {@link android.Manifest.permission#WRITE_CALENDAR} 권한을 포함할 필요가 없습니다.

    - +

    사용자가 이 방법을 사용하는 애플리케이션을 실행하면 해당 애플리케이션이 사용자를 캘린더로 보내 이벤트 추가를 완료합니다. {@link android.content.Intent#ACTION_INSERT INSERT} 인텐트는 추가 필드를 사용하여 -캘린더에 있는 이벤트 세부 정보로 양식을 미리 채웁니다. -그러면 사용자가 이벤트를 취소하거나 양식을 필요에 따라 편집할 수 있고, +캘린더에 있는 이벤트 세부 정보로 양식을 미리 채웁니다. +그러면 사용자가 이벤트를 취소하거나 양식을 필요에 따라 편집할 수 있고, 이벤트를 본인의 캘린더에 저장할 수도 있습니다.

    - -

    다음은 2012년 1월 19일에 이벤트 일정을 예약하는 코드 조각으로, + +

    다음은 2012년 1월 19일에 이벤트 일정을 예약하는 코드 조각으로, 이는 오전 7:30~오전 8:30까지 실행됩니다. 이 코드 조각에 관해서는 다음 내용을 주의하십시오.

    • 이것은 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}를 URI로 지정합니다.
    • - +
    • 이것은 {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} 및 {@link @@ -1083,10 +1083,10 @@ android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} 추가 필드를 사용하여 이벤트 시간으로 양식을 미리 채웁니다. 이러한 시간에 해당하는 값은 Epoch로부터 UTC 밀리초 단위로 표시해야 합니다.
    • - +
    • 이것은 {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL} 추가 필드를 사용하여 쉼표로 구분된 초청인 목록을 제공하며, 이는 이메일 주소로 나타납니다.
    • - +
     Calendar beginTime = Calendar.getInstance();
    @@ -1108,7 +1108,7 @@ startActivity(intent);
     

    인텐트를 사용하여 이벤트 편집

    이벤트 업데이트에서 설명한 바와 같이 이벤트를 직접 업데이트할 수 있습니다. 그러나 {@link -android.content.Intent#ACTION_EDIT EDIT} 인텐트를 사용하면 +android.content.Intent#ACTION_EDIT EDIT} 인텐트를 사용하면 캘린더 애플리케이션에 이벤트 편집을 분배할 권한이 없는 애플리케이션을 허용합니다. 사용자가 캘린더에서 이벤트 편집을 마치면 원래 애플리케이션으로 돌아오게 됩니다.

    다음은 지정된 이벤트에 새 제목을 설정하여 사용자에게 캘린더에서 이벤트를 편집할 수 있도록 해주는 인텐트의 예입니다. @@ -1158,18 +1158,18 @@ startActivity(intent);

    • 동기화 어댑터는 {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER}를 true로 설정하여 이것이 동기화 어댑터라는 것을 나타내야 합니다.
    • - - + +
    • 동기화 어댑터는 URI에서 쿼리 매개변수로 {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME}과 {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE}을 제공해야 합니다.
    • - +
    • 동기화 어댑터에는 애플리케이션 또는 위젯에 비해 더 많은 열에 대한 쓰기 액세스 권한이 있습니다. - 예를 들어, 애플리케이션은 캘린더의 몇 가지 특성만 수정할 수 있습니다. + 예를 들어, 애플리케이션은 캘린더의 몇 가지 특성만 수정할 수 있습니다. 즉 이름, 표시 이름, 가시성 설정 및 캘린더 동기화 여부 등만 해당됩니다. 이에 비해 동기화 어댑터의 경우 이 열만이 아니라 다른 수많은 열에도 액세스할 수 있습니다. 예를 들어 캘린더 색상, 표준 시간대, 액세스 수준 등이 해당됩니다. -다만, 동기화 어댑터는 지정된 ACCOUNT_NAME 및 +다만, 동기화 어댑터는 지정된 ACCOUNT_NAMEACCOUNT_TYPE에 한정됩니다.

    다음은 URI를 반환하여 동기화 어댑터와 사용하도록 할 때 쓸 수 있는 도우미 메서드입니다.

    @@ -1180,5 +1180,5 @@ android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE}을 제공해야 합 .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }
    -

    동기화 어댑터의 샘플 구현(캘린더에 구체적으로 관련된 것이 아님)은 +

    동기화 어댑터의 샘플 구현(캘린더에 구체적으로 관련된 것이 아님)은 SampleSyncAdpater를 참조하십시오. diff --git a/docs/html-intl/intl/ko/guide/topics/providers/contacts-provider.jd b/docs/html-intl/intl/ko/guide/topics/providers/contacts-provider.jd index 94d3295c1d465da128385bccf62976bf328fd0de..ad60b6dfbd856211a550e798c92586d316a4210a 100644 --- a/docs/html-intl/intl/ko/guide/topics/providers/contacts-provider.jd +++ b/docs/html-intl/intl/ko/guide/topics/providers/contacts-provider.jd @@ -83,12 +83,12 @@ page.title=연락처 제공자

    콘텐츠 제공자는 기기의 사람에 대한 중앙 데이터 리포지토리를 관리하는 강력하고 유연한 -Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애플리케이션에서 개발자에게 표시되는 -데이터의 출처입니다. 여기의 데이터에는 개발자 자신의 애플리케이션에서 -액세스하여 기기와 온라인 서비스 사이에서 데이터를 전송할 수도 있습니다. 제공자는 -광범위한 데이터 소스를 수용하며 각 인물에 대해 가능한 한 많은 데이터를 관리하여야 하므로, 그 결과 조직이 무척 -복잡합니다. 이 때문에 이 제공자의 API에는 -광범위한 계약 클래스와 인터페이스 세트가 포함되어 있어 데이터 검색과 수정을 모두 한층 +Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애플리케이션에서 개발자에게 표시되는 +데이터의 출처입니다. 여기의 데이터에는 개발자 자신의 애플리케이션에서 +액세스하여 기기와 온라인 서비스 사이에서 데이터를 전송할 수도 있습니다. 제공자는 +광범위한 데이터 소스를 수용하며 각 인물에 대해 가능한 한 많은 데이터를 관리하여야 하므로, 그 결과 조직이 무척 +복잡합니다. 이 때문에 이 제공자의 API에는 +광범위한 계약 클래스와 인터페이스 세트가 포함되어 있어 데이터 검색과 수정을 모두 한층 용이하게 해줍니다.

    @@ -105,23 +105,23 @@ Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애 제공자에서 데이터를 수정하는 방법.

  • - 동기화 어댑터를 작성하여 서버에서 가져온 데이터를 연락처 제공자와 + 동기화 어댑터를 작성하여 서버에서 가져온 데이터를 연락처 제공자와 동기화하는 방법.
  • - 이 가이드는 독자가 Android 콘텐츠 제공자의 기본 정보를 알고 있는 것으로 간주합니다. Android 콘텐츠 제공자에 -관한 자세한 내용은 + 이 가이드는 독자가 Android 콘텐츠 제공자의 기본 정보를 알고 있는 것으로 간주합니다. Android 콘텐츠 제공자에 +관한 자세한 내용은 -콘텐츠 제공자 기본 정보 가이드를 읽어보십시오. +콘텐츠 제공자 기본 정보 가이드를 읽어보십시오. 샘플 동기화 어댑터 샘플 앱은 동기화 어댑터를 사용하여 연락처 제공자와 Google Web Services가 호스팅하는 샘플 애플리케이션 사이에서 데이터를 전송하는 동기화 어댑터의 사용 예시입니다.

    연락처 제공자 조직

    - 연락처 제공자는 Android 콘텐츠 제공자 구성 요소입니다. 이것은 한 사람에 대해 -각기 세 가지 유형의 데이터를 관리합니다. 각 데이터는 그림 1에서 설명하는 바와 같이 제공자가 제공하는 + 연락처 제공자는 Android 콘텐츠 제공자 구성 요소입니다. 이것은 한 사람에 대해 +각기 세 가지 유형의 데이터를 관리합니다. 각 데이터는 그림 1에서 설명하는 바와 같이 제공자가 제공하는 각 테이블에 상응합니다.

    @@ -129,7 +129,7 @@ Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애 그림 1. 연락처 제공자 테이블 구조입니다.

    - 이 세 개의 테이블은 보통 자신의 계약 클래스의 이름으로 불립니다. 이들 클래스는 + 이 세 개의 테이블은 보통 자신의 계약 클래스의 이름으로 불립니다. 이들 클래스는 테이블에서 사용하는 콘텐츠 URI, 열 이름 및 열 값의 상수를 정의합니다.

    @@ -153,29 +153,29 @@ Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애

    - {@link android.provider.ContactsContract}의 계약 클래스가 대표하는 다른 테이블은 -보조 테이블로, 연락처 제공자는 이들을 사용하여 작업을 관리하거나 기기의 연락처에 있는 + {@link android.provider.ContactsContract}의 계약 클래스가 대표하는 다른 테이블은 +보조 테이블로, 연락처 제공자는 이들을 사용하여 작업을 관리하거나 기기의 연락처에 있는 특정 기능 또는 전화 통신 애플리케이션 등을 지원합니다.

    원시 연락처

    - 원시 연락처는 단일 계정 유형과 계정 이름에서 가져오는 -한 사람의 데이터를 나타냅니다. 연락처 제공자는 한 사람에 대해 하나 이상의 온라인 서비스를 데이터의 출처로 허용하므로, + 원시 연락처는 단일 계정 유형과 계정 이름에서 가져오는 +한 사람의 데이터를 나타냅니다. 연락처 제공자는 한 사람에 대해 하나 이상의 온라인 서비스를 데이터의 출처로 허용하므로, 연락처 제공자에서는 같은 사람에 대해 여러 개의 원시 연락처를 허용합니다. - 원시 연락처를 여러 개 사용하면 사용자가 같은 계정 유형의 하나 이상의 계정에서 가져온 + 원시 연락처를 여러 개 사용하면 사용자가 같은 계정 유형의 하나 이상의 계정에서 가져온 한 사람의 여러 데이터를 조합할 수 있습니다.

    - 원시 연락처의 데이터 대부분은 -{@link android.provider.ContactsContract.RawContacts} 테이블에 저장되지 않습니다. 대신, + 원시 연락처의 데이터 대부분은 +{@link android.provider.ContactsContract.RawContacts} 테이블에 저장되지 않습니다. 대신, {@link android.provider.ContactsContract.Data} 테이블에서 하나 이상의 행에 저장됩니다. 각 데이터 행에는 -상위 {@link android.provider.ContactsContract.RawContacts} 행의 {@code android.provider.BaseColumns#_ID RawContacts._ID} 값을 포함하는 -열 {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID Data.RAW_CONTACT_ID}가 +상위 {@link android.provider.ContactsContract.RawContacts} 행의 {@code android.provider.BaseColumns#_ID RawContacts._ID} 값을 포함하는 +열 {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID Data.RAW_CONTACT_ID}가 있습니다.

    중요한 원시 연락처 열

    - {@link android.provider.ContactsContract.RawContacts} 테이블의 중요한 열은 + {@link android.provider.ContactsContract.RawContacts} 테이블의 중요한 열은 표 1에 나열되어 있습니다. 표 뒤에 이어지는 참고 사항을 꼭 읽어주십시오.

    @@ -193,13 +193,13 @@ Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애 이 원시 연락처의 소스인 계정 유형에 대한 계정 이름입니다. - 예를 들어, Google 계정의 계정 이름은 -기기 소유자의 Gmail 주소 중 하나입니다. 자세한 정보는 -{@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE}의 + 예를 들어, Google 계정의 계정 이름은 +기기 소유자의 Gmail 주소 중 하나입니다. 자세한 정보는 +{@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE}의 다음 항목을 참조하십시오. - 이 이름의 형식은 각자의 계정 유형별로 다릅니다. 이것은 꼭 + 이 이름의 형식은 각자의 계정 유형별로 다릅니다. 이것은 꼭 이메일 주소여야 하는 것은 아닙니다. @@ -208,13 +208,13 @@ Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애 {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE} - 이 원시 연락처의 소스인 계정 유형입니다. 예를 들어, Google 계정의 -계정 유형은 com.google입니다. 계정 유형을 정규화할 때에는 항상 -본인이 소유하거나 제어하는 도메인의 도메인 식별자를 사용하십시오. 이렇게 하면 계정 유형이 고유한 것이도록 + 이 원시 연락처의 소스인 계정 유형입니다. 예를 들어, Google 계정의 +계정 유형은 com.google입니다. 계정 유형을 정규화할 때에는 항상 +본인이 소유하거나 제어하는 도메인의 도메인 식별자를 사용하십시오. 이렇게 하면 계정 유형이 고유한 것이도록 확실히 해둘 수 있습니다. - 연락처 데이터를 제공하는 계정 유형은 대개 연락처 제공자와 동기화되는 동기화 어댑터와 + 연락처 데이터를 제공하는 계정 유형은 대개 연락처 제공자와 동기화되는 동기화 어댑터와 연관되어 있습니다. @@ -225,44 +225,44 @@ Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애 원시 연락처에 대한 "삭제됨" 플래그입니다. - 이 플래그를 사용하면 연락처 제공자가 해당 행을 내부에 계속 유지할 수 있습니다. -이는 동기화 어댑터가 해당 행을 자신의 서버에서 삭제하고 마침내는 행을 리포지토리에서도 삭제할 수 있을 + 이 플래그를 사용하면 연락처 제공자가 해당 행을 내부에 계속 유지할 수 있습니다. +이는 동기화 어댑터가 해당 행을 자신의 서버에서 삭제하고 마침내는 행을 리포지토리에서도 삭제할 수 있을 때까지만입니다.

    참고

    - 다음은 + 다음은 {@link android.provider.ContactsContract.RawContacts} 테이블에 관한 중요한 참고 사항입니다.

    • - 원시 연락처의 이름은 -{@link android.provider.ContactsContract.RawContacts}에 있는 자신의 행에 저장되지 않습니다. 대신, -{@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 행에 있는 -{@link android.provider.ContactsContract.Data} 테이블에 저장됩니다. 원시 연락처 하나에는 + 원시 연락처의 이름은 +{@link android.provider.ContactsContract.RawContacts}에 있는 자신의 행에 저장되지 않습니다. 대신, +{@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 행에 있는 +{@link android.provider.ContactsContract.Data} 테이블에 저장됩니다. 원시 연락처 하나에는 {@link android.provider.ContactsContract.Data} 테이블에서 이런 유형의 행이 하나씩만 있습니다.
    • - 주의: 원시 연락처에서 본인의 계정 데이터를 사용하려면 이를 우선 -{@link android.accounts.AccountManager}로 등록해야 합니다. 이렇게 하려면, -사용자에게 계정 유형과 본인의 계정 이름을 계정 목록에 추가하라는 프롬프트를 표시하십시오. 이렇게 하지 않으면, + 주의: 원시 연락처에서 본인의 계정 데이터를 사용하려면 이를 우선 +{@link android.accounts.AccountManager}로 등록해야 합니다. 이렇게 하려면, +사용자에게 계정 유형과 본인의 계정 이름을 계정 목록에 추가하라는 프롬프트를 표시하십시오. 이렇게 하지 않으면, 연락처 제공자가 원시 연락처 행을 자동으로 삭제합니다.

      - 예를 들어, 앱에서 도메인 {@code com.example.dataservice}로 웹 베이스 서비스에 대한 연락처 데이터를 유지하고 -서비스에 대한 사용자 계정이 -{@code becky.sharp@dataservice.example.com}이라면, 사용자는 앱이 원시 연락처 행을 추가하기 전에 + 예를 들어, 앱에서 도메인 {@code com.example.dataservice}로 웹 베이스 서비스에 대한 연락처 데이터를 유지하고 +서비스에 대한 사용자 계정이 +{@code becky.sharp@dataservice.example.com}이라면, 사용자는 앱이 원시 연락처 행을 추가하기 전에 계정 "유형"({@code com.example.dataservice})과 계정 "이름" ({@code becky.smart@dataservice.example.com})을 먼저 추가해야 합니다. - 이 요구 사항을 사용자에게 설명하려면 관련 문서를 사용해도 되고, 아니면 사용자에게 -유형과 이름을 추가하라는 프롬프트를 표시해도 되고 두 가지 방법을 다 써도 됩니다. 계정 유형과 계정 이름은 + 이 요구 사항을 사용자에게 설명하려면 관련 문서를 사용해도 되고, 아니면 사용자에게 +유형과 이름을 추가하라는 프롬프트를 표시해도 되고 두 가지 방법을 다 써도 됩니다. 계정 유형과 계정 이름은 다음 섹션에서 더 자세히 설명되어 있습니다.

    원시 연락처 데이터 소스

    - 원시 연락처의 작동 원리를 이해하기 위해, 다음과 같이 기기에서 정의한 사용자 계정 세 가지를 보유한 사용자 "Emily Dickinson"이 있다고 + 원시 연락처의 작동 원리를 이해하기 위해, 다음과 같이 기기에서 정의한 사용자 계정 세 가지를 보유한 사용자 "Emily Dickinson"이 있다고 가정해 봅시다.

      @@ -275,11 +275,11 @@ Android 구성 요소입니다. 콘텐츠 제공자는 기기의 연락처 애 활성화했습니다.

      - Emily Dickinson이 브라우저 창을 열고, + Emily Dickinson이 브라우저 창을 열고, Gmail에 emily.dickinson@gmail.com으로 로그인하고, -연락처를 열어서 "Thomas Higginson"을 추가한다고 가정하겠습니다. 이 사용자는 나중에 Gmail에 -emilyd@gmail.com으로 로그인하고 "Thomas Higginson"에게 이메일을 전송합니다. -이렇게 하면 이 사람을 자동으로 연락처로 추가합니다. Emily는 Twitter에서 "colonel_tom"(Thomas Higginson의 Twitter ID)도 +연락처를 열어서 "Thomas Higginson"을 추가한다고 가정하겠습니다. 이 사용자는 나중에 Gmail에 +emilyd@gmail.com으로 로그인하고 "Thomas Higginson"에게 이메일을 전송합니다. +이렇게 하면 이 사람을 자동으로 연락처로 추가합니다. Emily는 Twitter에서 "colonel_tom"(Thomas Higginson의 Twitter ID)도 팔로우합니다.

      @@ -292,34 +292,34 @@ Gmail에 emily.dickinson@gmail.com으로 로그인하고,

    • emilyd@gmail.com과 연관된 "Thomas Higginson"의 두 번째 원시 연락처입니다. - 사용자 계정 유형은 마찬가지로 Google입니다. 이름이 이전 이름과 똑같더라도 두 번째 원시 연락처가 -더해집니다. 왜냐하면 이 사람은 아까와 다른 + 사용자 계정 유형은 마찬가지로 Google입니다. 이름이 이전 이름과 똑같더라도 두 번째 원시 연락처가 +더해집니다. 왜냐하면 이 사람은 아까와 다른 사용자 계정에 추가되었기 때문입니다.
    • - "belle_of_amherst"와 연관된 "Thomas Higginson"의 세 번째 원시 연락처입니다. 사용자 + "belle_of_amherst"와 연관된 "Thomas Higginson"의 세 번째 원시 연락처입니다. 사용자 계정 유형은 Twitter입니다.
    • 데이터

      이전에 언급한 바와 같이, 원시 연락처의 데이터는 -원시 연락처의 _ID 값과 연결된{@link android.provider.ContactsContract.Data} 행에 -저장됩니다. 이렇게 하면 하나의 원시 연락처에 같은 유형의 데이터의 인스턴스가 여러 개 있을 수 있게 됩니다. -예를 들어 이메일 주소 또는 전화 번호 등이 이에 해당됩니다. 예를 들어, +원시 연락처의 _ID 값과 연결된{@link android.provider.ContactsContract.Data} 행에 +저장됩니다. 이렇게 하면 하나의 원시 연락처에 같은 유형의 데이터의 인스턴스가 여러 개 있을 수 있게 됩니다. +예를 들어 이메일 주소 또는 전화 번호 등이 이에 해당됩니다. 예를 들어, {@code emilyd@gmail.com}에 대한 "Thomas Higginson"(Google 계정 emilyd@gmail.com과 연관된 Thomas Higginson의 -원시 연락처)에는 +원시 연락처)에는 thigg@gmail.com이라는 집 이메일 주소와 thomas.higginson@gmail.com이라는 직장 이메일 주소가 있고, 연락처 제공자는 두 개의 이메일 주소 행을 저장하고 원시 연락처에 두 가지를 연결합니다.

      - 이 테이블 하나에 여러 가지 유형의 데이터가 저장된 점에 주의하십시오. 표시 이름, -전화 번호, 이메일, 우편 주소, 사진 및 웹사이트 세부 정보 행은 모두 -{@link android.provider.ContactsContract.Data} 테이블에서 찾을 수 있습니다. 이런 데이터 관리를 돕기 위해 -{@link android.provider.ContactsContract.Data} 테이블에는 설명이 포함된 이름이 있는 열이 몇 개 있고 -일반적 이름이 포함된 열도 몇 개 있습니다. 설명이 포함된 이름 열의 콘텐츠는 행 안의 데이터 유형과 관계 없이 모두 의미가 같고, -일반적인 이름 열의 콘텐츠는 데이터 유형에 따라 + 이 테이블 하나에 여러 가지 유형의 데이터가 저장된 점에 주의하십시오. 표시 이름, +전화 번호, 이메일, 우편 주소, 사진 및 웹사이트 세부 정보 행은 모두 +{@link android.provider.ContactsContract.Data} 테이블에서 찾을 수 있습니다. 이런 데이터 관리를 돕기 위해 +{@link android.provider.ContactsContract.Data} 테이블에는 설명이 포함된 이름이 있는 열이 몇 개 있고 +일반적 이름이 포함된 열도 몇 개 있습니다. 설명이 포함된 이름 열의 콘텐츠는 행 안의 데이터 유형과 관계 없이 모두 의미가 같고, +일반적인 이름 열의 콘텐츠는 데이터 유형에 따라 서로 의미가 다릅니다.

      설명이 포함된 열 이름

      @@ -337,9 +337,9 @@ Gmail에 emily.dickinson@gmail.com으로 로그인하고, {@link android.provider.ContactsContract.Data#MIMETYPE}
      - 이 행에 저장되는 데이터 유형으로, 사용자 지정 MIME 유형으로 표현됩니다. 연락처 제공자는 -{@link android.provider.ContactsContract.CommonDataKinds}의 하위 클래스에서 정의된 -MIME 유형을 사용합니다. 이러한 MIME 유형은 오픈 소스이고, + 이 행에 저장되는 데이터 유형으로, 사용자 지정 MIME 유형으로 표현됩니다. 연락처 제공자는 +{@link android.provider.ContactsContract.CommonDataKinds}의 하위 클래스에서 정의된 +MIME 유형을 사용합니다. 이러한 MIME 유형은 오픈 소스이고, 연락처 제공자와 함께 사용할 수 있는 모든 애플리케이션 또는 동기화 어댑터가 사용할 수 있습니다.
      @@ -347,25 +347,25 @@ MIME 유형을 사용합니다. 이러한 MIME 유형은 오픈 소스이고,
      이 유형의 데이터 행이 원시 연락처에서 한 번 이상 발생하는 경우, -{@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} 열은 -해당 유형의 기본 데이터가 들어있는 데이터 행을 플래그로 표시합니다. 예를 들어, -사용자가 연락처의 전화 번호를 길게 누르고 기본값으로 설정을 선택하면 +{@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} 열은 +해당 유형의 기본 데이터가 들어있는 데이터 행을 플래그로 표시합니다. 예를 들어, +사용자가 연락처의 전화 번호를 길게 누르고 기본값으로 설정을 선택하면 그 번호가 들어있는 {@link android.provider.ContactsContract.Data} 행이 -{@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} 열을 +{@link android.provider.ContactsContract.DataColumns#IS_PRIMARY} 열을 0이 아닌 값으로 설정합니다.

      일반 열 이름

      - 15개의 일반 열 중에서 DATA1부터 -DATA15까지는 일반적으로 이용할 수 있고 이외에 추가로 마련된 네 개의 일반 -열, 즉 SYNC1부터 SYNC4까지는 -동기화 어댑터 전용입니다. 일반 열 이름 상수는 해당 행에 들어있는 데이터 유형과 관계 없이 + 15개의 일반 열 중에서 DATA1부터 +DATA15까지는 일반적으로 이용할 수 있고 이외에 추가로 마련된 네 개의 일반 +열, 즉 SYNC1부터 SYNC4까지는 +동기화 어댑터 전용입니다. 일반 열 이름 상수는 해당 행에 들어있는 데이터 유형과 관계 없이 언제나 통합니다.

      - DATA1 열은 색인됩니다. 연락처 제공자는 제공자가 가장 자주 쿼리의 대상이 될 것으로 예상하는 -데이터에 대해 항상 이 열을 사용합니다. 예컨대 + DATA1 열은 색인됩니다. 연락처 제공자는 제공자가 가장 자주 쿼리의 대상이 될 것으로 예상하는 +데이터에 대해 항상 이 열을 사용합니다. 예컨대 이메일 행의 경우, 이 열에 실제 이메일 주소가 들어있습니다.

      @@ -374,36 +374,36 @@ MIME 유형을 사용합니다. 이러한 MIME 유형은 오픈 소스이고,

      유형별 열 이름

      - 특정 유형의 행에 대한 열과의 작업을 돕기 위해, 연락처 제공자는 - 유형별 열 이름 상수도 제공합니다. 이는 -{@link android.provider.ContactsContract.CommonDataKinds}의 하위 클래스에서 정의합니다. 이 상수는 그저 같은 열 이름에 -서로 다른 상수 이름을 부여할 뿐이며, 이렇게 하면 개발자가 특정 유형의 행에 있는 데이터에 + 특정 유형의 행에 대한 열과의 작업을 돕기 위해, 연락처 제공자는 + 유형별 열 이름 상수도 제공합니다. 이는 +{@link android.provider.ContactsContract.CommonDataKinds}의 하위 클래스에서 정의합니다. 이 상수는 그저 같은 열 이름에 +서로 다른 상수 이름을 부여할 뿐이며, 이렇게 하면 개발자가 특정 유형의 행에 있는 데이터에 액세스하기 쉽습니다.

      - 예를 들어, {@link android.provider.ContactsContract.CommonDataKinds.Email} 클래스는 + 예를 들어, {@link android.provider.ContactsContract.CommonDataKinds.Email} 클래스는 MIME 유형{@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE Email.CONTENT_ITEM_TYPE}을 갖는 -{@link android.provider.ContactsContract.Data} 행에 +{@link android.provider.ContactsContract.Data} 행에 대한 유형별 열 이름 상수를 정의합니다. 이 클래스에는 이메일 주소 열에 대한 - 상수 {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS}가 -들어있습니다. -{@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS}의 실제 값은 + 상수 {@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS}가 +들어있습니다. +{@link android.provider.ContactsContract.CommonDataKinds.Email#ADDRESS}의 실제 값은 "data1"이고, 이는 열의 일반 이름과 같습니다.

      - 주의: 개발자 본인의 사용자 지정 데이터를 -{@link android.provider.ContactsContract.Data} 테이블에 -추가할 때 제공자의 미리 정의된 MIME 유형 중 하나가 있는 행을 사용하면 안 됩니다. 그렇게 하면 데이터가 손실되거나 제공자의 오작동을 -유발할 수 있습니다. 예를 들어, MIME 유형 + 주의: 개발자 본인의 사용자 지정 데이터를 +{@link android.provider.ContactsContract.Data} 테이블에 +추가할 때 제공자의 미리 정의된 MIME 유형 중 하나가 있는 행을 사용하면 안 됩니다. 그렇게 하면 데이터가 손실되거나 제공자의 오작동을 +유발할 수 있습니다. 예를 들어, MIME 유형 {@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_ITEM_TYPE - Email.CONTENT_ITEM_TYPE} 안에 -DATA1 열에 있는 이메일 주소 대신 사용자 이름이 들어있는 행은 추가하면 안 됩니다. 해당 행에 개발자 나름의 사용자 지정 MIME 유형을 사용하는 경우 + Email.CONTENT_ITEM_TYPE} 안에 +DATA1 열에 있는 이메일 주소 대신 사용자 이름이 들어있는 행은 추가하면 안 됩니다. 해당 행에 개발자 나름의 사용자 지정 MIME 유형을 사용하는 경우 본인만의 유형별 열 이름을 자유자재로 정의하고 이러한 열을 마음대로 사용해도 됩니다.

      - 그림 2는 -{@link android.provider.ContactsContract.Data} 행에서 설명 열과 데이터 열이 나타나는 방식과 유형별 열 이름이 + 그림 2는 +{@link android.provider.ContactsContract.Data} 행에서 설명 열과 데이터 열이 나타나는 방식과 유형별 열 이름이 일반 열 이름에 "오버레이"되는 방식을 나타낸 것입니다.

      How type-specific column names map to generic column names @@ -446,51 +446,51 @@ Email.CONTENT_ITEM_TYPE}을 갖는 {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} 원시 연락처를 연락처 제공자의 그룹 중 하나와 연결하는 식별자입니다. - 그룹은 계정 유형과 계정 이름의 선택적 기능입니다. 이러한 내용은 + 그룹은 계정 유형과 계정 이름의 선택적 기능입니다. 이러한 내용은 연락처 그룹 섹션에 자세히 설명되어 있습니다.

      연락처

      - 연락처 제공자는 모든 계정 유형과 계정 이름을 통틀어 원시 연락처 행을 조합하여 -하나의 연락처를 형성합니다. 이렇게 하면 사용자가 한 사람에 대해 수집한 -모든 데이터를 표시하고 수정하기 쉽습니다. 연락처 제공자는 새 연락처 행의 생성을 관리하고 -원시 연락처를 기존 연락처 행과 통합하기도 합니다. 애플리케이션과 + 연락처 제공자는 모든 계정 유형과 계정 이름을 통틀어 원시 연락처 행을 조합하여 +하나의 연락처를 형성합니다. 이렇게 하면 사용자가 한 사람에 대해 수집한 +모든 데이터를 표시하고 수정하기 쉽습니다. 연락처 제공자는 새 연락처 행의 생성을 관리하고 +원시 연락처를 기존 연락처 행과 통합하기도 합니다. 애플리케이션과 동기화 어댑터는 모두 연락처를 추가할 수 없으며, 연락처 행에 있는 열 중 몇몇은 읽기 전용입니다.

      - 참고: 연락처 제공자에 연락처를 추가하려고 -{@link android.content.ContentResolver#insert(Uri,ContentValues) insert()}를 사용하는 경우, -{@link java.lang.UnsupportedOperationException} 예외가 발생합니다. "읽기 전용"으로 표시된 열을 업데이트하려고 하면 + 참고: 연락처 제공자에 연락처를 추가하려고 +{@link android.content.ContentResolver#insert(Uri,ContentValues) insert()}를 사용하는 경우, +{@link java.lang.UnsupportedOperationException} 예외가 발생합니다. "읽기 전용"으로 표시된 열을 업데이트하려고 하면 그 업데이트는 무시됩니다.

      - 연락처 제공자는 기존 연락처 어느 것과도 일치하지 않는 새로운 원시 연락처가 추가되면 -새로운 연락처를 생성합니다. 제공자가 이 작업을 하는 또 다른 경우는 -기존 원시 연락처의 데이터가 변경되어 이전에 첨부되어 있던 연락처에 더 이상 일치하지 않는 -경우입니다. 애플리케이션이나 동기화 어댑터가 + 연락처 제공자는 기존 연락처 어느 것과도 일치하지 않는 새로운 원시 연락처가 추가되면 +새로운 연락처를 생성합니다. 제공자가 이 작업을 하는 또 다른 경우는 +기존 원시 연락처의 데이터가 변경되어 이전에 첨부되어 있던 연락처에 더 이상 일치하지 않는 +경우입니다. 애플리케이션이나 동기화 어댑터가 기존 연락처와 일치하는 새로운 원시 연락처를 생성하면, 새로운 원시 연락처는 기존 연락처에 통합됩니다.

      연락처 제공자는 -{@link android.provider.ContactsContract.Contacts Contacts} 테이블에 있는 연락처 행의 _ID 열로 -연락처 행과 원시 연락처 행를 연결합니다. 원시 연락처 테이블 {@link android.provider.ContactsContract.RawContacts}의 CONTACT_ID 행에는 -각 원시 연락처 행과 관련된 연락처 행에 대한 _ID 값이 +{@link android.provider.ContactsContract.Contacts Contacts} 테이블에 있는 연락처 행의 _ID 열로 +연락처 행과 원시 연락처 행를 연결합니다. 원시 연락처 테이블 {@link android.provider.ContactsContract.RawContacts}의 CONTACT_ID 행에는 +각 원시 연락처 행과 관련된 연락처 행에 대한 _ID 값이 들어있습니다.

      {@link android.provider.ContactsContract.Contacts} 테이블에는 연락처 행에 대한 "영구" 링크인 {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} 열도 -있습니다. 연락처 제공자가 연락처를 자동으로 관리하므로, -통합이나 동기화에 응답하여 연락처 행의 {@code android.provider.BaseColumns#_ID} 값을 -변경할 수도 있습니다. 이런 일이 발생한다 하더라도 콘텐츠 URI -{@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}와 -연락처의 {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY}는 여전히 -연락처 행을 가리키므로, -{@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY}를 -사용하여 "즐겨찾기" 연락처에 대한 연결 등을 그대로 유지할 수 있습니다. 이 열에는 +있습니다. 연락처 제공자가 연락처를 자동으로 관리하므로, +통합이나 동기화에 응답하여 연락처 행의 {@code android.provider.BaseColumns#_ID} 값을 +변경할 수도 있습니다. 이런 일이 발생한다 하더라도 콘텐츠 URI +{@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}와 +연락처의 {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY}는 여전히 +연락처 행을 가리키므로, +{@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY}를 +사용하여 "즐겨찾기" 연락처에 대한 연결 등을 그대로 유지할 수 있습니다. 이 열에는 {@code android.provider.BaseColumns#_ID} 열의 형식과 관련이 없는 나름의 형식이 있습니다.

      @@ -502,17 +502,17 @@ Email.CONTENT_ITEM_TYPE}을 갖는

      동기화 어댑터의 데이터

      - 사용자가 연락처 데이터를 기기에 직접 입력하기도 하지만, 데이터는 웹 서비스에서 -동기화 어댑터를 통해 연락처 제공자로 흘러들어가기도 합니다. 이것이 기기와 -서비스 사이에서 데이터의 전송을 자동화하는 것입니다. 동기화 어댑터는 시스템의 제어를 받으며 -배경에서 실행되고, {@link android.content.ContentResolver} 메서드를 + 사용자가 연락처 데이터를 기기에 직접 입력하기도 하지만, 데이터는 웹 서비스에서 +동기화 어댑터를 통해 연락처 제공자로 흘러들어가기도 합니다. 이것이 기기와 +서비스 사이에서 데이터의 전송을 자동화하는 것입니다. 동기화 어댑터는 시스템의 제어를 받으며 +배경에서 실행되고, {@link android.content.ContentResolver} 메서드를 호출하여 데이터를 관리합니다.

      Android에서 동기화 어댑터와 함께 작업하는 웹 서비스는 계정 유형으로 식별됩니다. - 각 동기화 어댑터는 계정 유형 하나에 통하지만, 그 유형에 대한 여러 개의 계정이름을 -지원할 수 있습니다. 계정 유형과 계정 이름은 -원시 연락처 데이터 소스 섹션에 간단히 설명되어 있습니다. 다음 정의는 좀 더 자세한 내용을 제공하며, + 각 동기화 어댑터는 계정 유형 하나에 통하지만, 그 유형에 대한 여러 개의 계정이름을 +지원할 수 있습니다. 계정 유형과 계정 이름은 +원시 연락처 데이터 소스 섹션에 간단히 설명되어 있습니다. 다음 정의는 좀 더 자세한 내용을 제공하며, 계정 유형과 이름이 동기화 어댑터와 서비스에 관련되는 방식을 설명합니다.

      @@ -520,34 +520,34 @@ Email.CONTENT_ITEM_TYPE}을 갖는 계정 유형
      - 사용자가 데이터를 저장해둔 서비스를 식별합니다. 대부분의 경우, 사용자가 -서비스로 인증해야 합니다. 예를 들어, Google 주소록은 계정 유형이고, 이는 -코드 google.com으로 식별됩니다. 이 값은 + 사용자가 데이터를 저장해둔 서비스를 식별합니다. 대부분의 경우, 사용자가 +서비스로 인증해야 합니다. 예를 들어, Google 주소록은 계정 유형이고, 이는 +코드 google.com으로 식별됩니다. 이 값은 {@link android.accounts.AccountManager}가 사용하는 계정 유형에 상응합니다.
      계정 이름
      - 하나의 계정 유형에 대한 특정 계정 또는 로그인을 식별합니다. Google 주소록 계정은 + 하나의 계정 유형에 대한 특정 계정 또는 로그인을 식별합니다. Google 주소록 계정은 Google 계정과 같고, 이는 계정 이름으로 이메일 주소를 사용합니다. 다른 서비스는 한 단어로 된 사용자 이름이나 숫자 ID를 사용할 수 있습니다.

      - 계정 유형은 고유하지 않아도 됩니다. 한 사람의 사용자가 여러 개의 Google 주소록을 구성할 수 있고 -그 데이터를 연락처 제공자에 다운로드할 수 있습니다. 이런 일은 사용자에게 -개인용 계정 이름에 대한 개인용 연락처가 한 세트 있고, 업무용으로 또 한 세트가 있는 경우 일어납니다. 계정 이름은 보통 -고유합니다. 이 둘은 함께 사용되어 연락처 제공자와 외부 서비스 사이의 특정 데이터 + 계정 유형은 고유하지 않아도 됩니다. 한 사람의 사용자가 여러 개의 Google 주소록을 구성할 수 있고 +그 데이터를 연락처 제공자에 다운로드할 수 있습니다. 이런 일은 사용자에게 +개인용 계정 이름에 대한 개인용 연락처가 한 세트 있고, 업무용으로 또 한 세트가 있는 경우 일어납니다. 계정 이름은 보통 +고유합니다. 이 둘은 함께 사용되어 연락처 제공자와 외부 서비스 사이의 특정 데이터 흐름을 식별합니다.

      - 서비스의 데이터를 연락처 제공자에 전송하려면, 나름의 -동기화 어댑터를 작성해야 합니다. 이 내용은 + 서비스의 데이터를 연락처 제공자에 전송하려면, 나름의 +동기화 어댑터를 작성해야 합니다. 이 내용은 연락처 제공자 동기화 어댑터 섹션에 자세히 설명되어 있습니다.

      - 그림 4는 연락처 제공자가 사람에 대한 데이터 흐름에 + 그림 4는 연락처 제공자가 사람에 대한 데이터 흐름에 어떻게 들어맞는지 나타낸 것입니다. "동기화 어댑터"라고 표시된 상자에서, 각 어댑터에는 계정 유형에 따라 레이블이 붙어 있습니다.

      Flow of data about people @@ -556,67 +556,67 @@ Google 계정과 같고, 이는 계정 이름으로 이메일 주소를 사용

      필수 권한

      - 연락처 제공자에 액세스하고자 하는 애플리케이션은 다음 권한을 + 연락처 제공자에 액세스하고자 하는 애플리케이션은 다음 권한을 요청해야 합니다.

      하나 이상의 테이블에 대한 읽기 액세스
      - {@link android.Manifest.permission#READ_CONTACTS}, -AndroidManifest.xml에서 + {@link android.Manifest.permission#READ_CONTACTS}, +AndroidManifest.xml에서 - <uses-permission> 요소와 함께 + <uses-permission> 요소와 함께 <uses-permission android:name="android.permission.READ_CONTACTS">로 지정된 것.
      하나 이상의 테이블에 대한 쓰기 액세스
      - {@link android.Manifest.permission#WRITE_CONTACTS}, -AndroidManifest.xml에서 + {@link android.Manifest.permission#WRITE_CONTACTS}, +AndroidManifest.xml에서 - <uses-permission> 요소와 함께 + <uses-permission> 요소와 함께 <uses-permission android:name="android.permission.WRITE_CONTACTS">로 지정된 것.

      - 이들 권한은 사용자 프로필 데이터로 확대되지 않습니다. 사용자 프로필과 -필수 권한은 + 이들 권한은 사용자 프로필 데이터로 확대되지 않습니다. 사용자 프로필과 +필수 권한은 다음 섹션인 사용자 프로필에서 논의합니다.

      - 사용자의 연락처 데이터는 중요한 개인 정보라는 사실을 명심하십시오. 사용자는 자신의 + 사용자의 연락처 데이터는 중요한 개인 정보라는 사실을 명심하십시오. 사용자는 자신의 개인정보보호를 중요하게 생각하고 신경 쓰기 때문에 애플리케이션이 자신이나 자신의 연락처에 관한 정보를 수집하는 것을 바라지 않습니다. - 사용자의 연락처 데이터에 액세스할 권한이 필요한 이유가 분명하지 않으면 여러분의 + 사용자의 연락처 데이터에 액세스할 권한이 필요한 이유가 분명하지 않으면 여러분의 애플리케이션에 낮은 순위를 매기거나 설치를 거부할 수도 있습니다.

      사용자 프로필

      - {@link android.provider.ContactsContract.Contacts} 테이블에 있는 한 개의 행에는 기기의 사용자에 대한 프로필 -데이터가 담겨 있습니다. 이 데이터는 사용자의 연락처 중 하나라기보다는 기기의 user를 -설명하는 것입니다. 프로필 연락처 행은 + {@link android.provider.ContactsContract.Contacts} 테이블에 있는 한 개의 행에는 기기의 사용자에 대한 프로필 +데이터가 담겨 있습니다. 이 데이터는 사용자의 연락처 중 하나라기보다는 기기의 user를 +설명하는 것입니다. 프로필 연락처 행은 프로필을 사용하는 각 시스템에 대한 원시 연락처 행에 연결되어 있습니다. - 각 프로필 원시 연락처 행에는 여러 개의 데이터 행이 있을 수 있습니다. 사용자 프로필에 액세스하기 위한 상수는 + 각 프로필 원시 연락처 행에는 여러 개의 데이터 행이 있을 수 있습니다. 사용자 프로필에 액세스하기 위한 상수는 {@link android.provider.ContactsContract.Profile} 클래스에서 이용할 수 있습니다.

      - 사용자 프로필에 액세스하려면 특수 권한이 필요합니다. 읽기와 쓰기에 필요한 + 사용자 프로필에 액세스하려면 특수 권한이 필요합니다. 읽기와 쓰기에 필요한 {@link android.Manifest.permission#READ_CONTACTS}와 -{@link android.Manifest.permission#WRITE_CONTACTS} 권한 외에도, -사용자 프로필에 액세스하려면 각각 읽기와 쓰기 액세스를 위한{@code android.Manifest.permission#READ_PROFILE}과 -{@code android.Manifest.permission#WRITE_PROFILE} 권한이 +{@link android.Manifest.permission#WRITE_CONTACTS} 권한 외에도, +사용자 프로필에 액세스하려면 각각 읽기와 쓰기 액세스를 위한{@code android.Manifest.permission#READ_PROFILE}과 +{@code android.Manifest.permission#WRITE_PROFILE} 권한이 필요합니다.

      - 사용자의 프로필은 중요한 정보로 간주해야 한다는 점을 명심하십시오. -{@code android.Manifest.permission#READ_PROFILE}권한을 사용하면 개발자가 기기 사용자의 -개인 식별 데이터에 액세스할 수 있게 해줍니다. 애플리케이션 설명에서 + 사용자의 프로필은 중요한 정보로 간주해야 한다는 점을 명심하십시오. +{@code android.Manifest.permission#READ_PROFILE}권한을 사용하면 개발자가 기기 사용자의 +개인 식별 데이터에 액세스할 수 있게 해줍니다. 애플리케이션 설명에서 사용자에게 왜 여러분이 사용자 프로필 권한을 필요로 하는지 밝혀두어야 합니다.

      사용자 프로필이 포함된 연락처 행을 검색하려면, {@link android.content.ContentResolver#query(Uri,String[], String, String[], String) ContentResolver.query()}를 호출합니다. 콘텐츠 URI 를 -{@link android.provider.ContactsContract.Profile#CONTENT_URI}로 설정하고 -선택 기준은 아무것도 제공하지 마십시오. 이 콘텐츠 URI는 원시 연락처 또는 프로필에 대한 데이터를 검색하기 위한 +{@link android.provider.ContactsContract.Profile#CONTENT_URI}로 설정하고 +선택 기준은 아무것도 제공하지 마십시오. 이 콘텐츠 URI는 원시 연락처 또는 프로필에 대한 데이터를 검색하기 위한 기본 URI로도 쓸 수 있습니다. 예를 들어, 이 코드 조각은 프로필에 대한 데이터를 검색합니다.

      @@ -639,18 +639,18 @@ mProfileCursor =
                       null);
       

      - 참고: 여러 개의 연락처 행을 검색하고 그 중 하나가 -사용자 프로필인지 판별하고자 하는 경우, -행의 {@link android.provider.ContactsContract.ContactsColumns#IS_USER_PROFILE} 열을 테스트합니다. 이 열은 + 참고: 여러 개의 연락처 행을 검색하고 그 중 하나가 +사용자 프로필인지 판별하고자 하는 경우, +행의 {@link android.provider.ContactsContract.ContactsColumns#IS_USER_PROFILE} 열을 테스트합니다. 이 열은 해당 연락처가 사용자 프로필이면 "1"로 설정됩니다.

      연락처 제공자 메타데이터

      - 연락처 제공자는 리포지토리에서 연락처 데이터 상태를 -추적하는 데이터를 관리합니다. 이 리포지토리 관련 데이터는 + 연락처 제공자는 리포지토리에서 연락처 데이터 상태를 +추적하는 데이터를 관리합니다. 이 리포지토리 관련 데이터는 원시 연락처, 데이터 및 연락처 테이블 행, -{@link android.provider.ContactsContract.Settings} 테이블 및 -{@link android.provider.ContactsContract.SyncState} 테이블 등의 여러 장소에 저장됩니다. 다음 표는 각 메타데이터 조각이 미치는 +{@link android.provider.ContactsContract.Settings} 테이블 및 +{@link android.provider.ContactsContract.SyncState} 테이블 등의 여러 장소에 저장됩니다. 다음 표는 각 메타데이터 조각이 미치는 영향을 나타낸 것입니다.

      @@ -667,14 +667,14 @@ mProfileCursor = {@link android.provider.ContactsContract.SyncColumns#DIRTY} "0" - 마지막 동기화 이후로 변경되지 않았습니다. - 기기에서 변경되었고 서버로 다시 동기화되어야 하는 원시 데이터를 -표시합니다. 이 값은 Android 애플리케이션이 행을 업데이트하면 연락처 제공자가 + 기기에서 변경되었고 서버로 다시 동기화되어야 하는 원시 데이터를 +표시합니다. 이 값은 Android 애플리케이션이 행을 업데이트하면 연락처 제공자가 자동으로 설정합니다.

      - 원시 연락처나 데이터 테이블을 수정하는 동기화 어댑터는 -언제나 문자열 {@link android.provider.ContactsContract#CALLER_IS_SYNCADAPTER}를 + 원시 연락처나 데이터 테이블을 수정하는 동기화 어댑터는 +언제나 문자열 {@link android.provider.ContactsContract#CALLER_IS_SYNCADAPTER}를 자신이 사용하는 콘텐츠 URI에 추가해야 합니다. 이렇게 하면 제공자가 행을 변경(dirty)으로 표시하지 못하게 방지합니다. - 그렇지 않으면, 동기화 어댑터 수정이 로컬 수정으로 나타나며 + 그렇지 않으면, 동기화 어댑터 수정이 로컬 수정으로 나타나며 서버가 수정의 근원이었다 하더라도 이 내용이 다시 서버로 전송됩니다.

      @@ -687,7 +687,7 @@ mProfileCursor = {@link android.provider.ContactsContract.SyncColumns#VERSION} 이 행의 버전 번호입니다. - 연락처 제공자는 행이나 관련 데이터가 변경될 때마다 이 값을 자동으로 + 연락처 제공자는 행이나 관련 데이터가 변경될 때마다 이 값을 자동으로 증가시킵니다. @@ -696,7 +696,7 @@ mProfileCursor = {@link android.provider.ContactsContract.DataColumns#DATA_VERSION} 이 행의 버전 번호입니다. - 연락처 제공자는 데이터 행이 변경될 때마다 이 값을 자동으로 + 연락처 제공자는 데이터 행이 변경될 때마다 이 값을 자동으로 증가시킵니다. @@ -704,33 +704,33 @@ mProfileCursor = {@link android.provider.ContactsContract.RawContacts} {@link android.provider.ContactsContract.SyncColumns#SOURCE_ID} - 이 원시 연락처를 자신이 생성된 계정에 대해 고유하게 식별하는 + 이 원시 연락처를 자신이 생성된 계정에 대해 고유하게 식별하는 문자열 값입니다. - 동기화 어댑터가 새로운 원시 연락처를 생성하면, 이 열이 -해당 원시 연락처에 대한 서버의 고유 ID로 설정되어야 합니다. Android 애플리케이션이 새로운 원시 연락처를 생성하면, -애플리케이션은 이 열을 빈 채로 두어야 합니다. 이것은 동기화 어댑터에 -서버에 새 원시 데이터를 생성해야 한다고 신호하고, + 동기화 어댑터가 새로운 원시 연락처를 생성하면, 이 열이 +해당 원시 연락처에 대한 서버의 고유 ID로 설정되어야 합니다. Android 애플리케이션이 새로운 원시 연락처를 생성하면, +애플리케이션은 이 열을 빈 채로 두어야 합니다. 이것은 동기화 어댑터에 +서버에 새 원시 데이터를 생성해야 한다고 신호하고, {@link android.provider.ContactsContract.SyncColumns#SOURCE_ID}에 대한 값을 가져오라고 알립니다.

      - 특히, 소스 ID는 각 계정 유형에 대해 고유해야 하고 + 특히, 소스 ID는 각 계정 유형에 대해 고유해야 하고 동기화 전체에서 안정적이어야 합니다.

      • - 고유: 하나의 계정에 대한 각 원시 연락처에는 나름의 소스 ID가 있어야 합니다. 개발자가 + 고유: 하나의 계정에 대한 각 원시 연락처에는 나름의 소스 ID가 있어야 합니다. 개발자가 이것을 강제 적용하지 않으면 연락처 애플리케이션에 문제를 유발하게 됩니다. - 같은 계정 유형에 대한 두 개의 원시 연락처는 소스 ID가 -같을 수 있다는 점을 유의하십시오. 예를 들어, -{@code emily.dickinson@gmail.com} 계정에 대한 원시 연락처 "Thomas Higginson"은 -{@code emilyd@gmail.com} 계정에 대한 + 같은 계정 유형에 대한 두 개의 원시 연락처는 소스 ID가 +같을 수 있다는 점을 유의하십시오. 예를 들어, +{@code emily.dickinson@gmail.com} 계정에 대한 원시 연락처 "Thomas Higginson"은 +{@code emilyd@gmail.com} 계정에 대한 원시 연락처 "Thomas Higginson"과 소스 ID가 같을 수 있습니다.
      • - 안정적: 소스 ID는 원시 연락처에 대한 온라인 서비스의 데이터 중 영구적인 -부분입니다. 예를 들어, 사용자가 앱 설정에서 연락처 저장소를 삭제하고 다시 동기화하면 -복원된 원시 연락처의 소스 ID는 전과 같아야 + 안정적: 소스 ID는 원시 연락처에 대한 온라인 서비스의 데이터 중 영구적인 +부분입니다. 예를 들어, 사용자가 앱 설정에서 연락처 저장소를 삭제하고 다시 동기화하면 +복원된 원시 연락처의 소스 ID는 전과 같아야 합니다. 개발자가 이것을 강제 적용하지 않으면 바로 가기가 더 이상 작동하지 않습니다.
      • @@ -742,7 +742,7 @@ mProfileCursor = {@link android.provider.ContactsContract.GroupsColumns#GROUP_VISIBLE} "0" - 이 그룹의 연락처는 Android 애플리케이션 UI에 표시되지 않아야 합니다. - 이 열은 사용자가 특정 그룹에 연락처를 숨길 수 있게 해주는 서버와의 + 이 열은 사용자가 특정 그룹에 연락처를 숨길 수 있게 해주는 서버와의 호환성을 위한 것입니다. @@ -754,22 +754,22 @@ mProfileCursor = {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE} - "0" - 이 계정과 계정 유형의 경우, 그룹에 속하지 않는 연락처는 Android 애플리케이션 UI에 + "0" - 이 계정과 계정 유형의 경우, 그룹에 속하지 않는 연락처는 Android 애플리케이션 UI에 표시되지 않습니다. - 기본적으로, 연락처에 그룹에 속한 원시 데이터가 하나도 없는 경우 이는 표시되지 않습니다(원시 연락처의 그룹 구성원은 -{@link android.provider.ContactsContract.Data} 테이블에서 -하나 이상의 {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} 행으로 + 기본적으로, 연락처에 그룹에 속한 원시 데이터가 하나도 없는 경우 이는 표시되지 않습니다(원시 연락처의 그룹 구성원은 +{@link android.provider.ContactsContract.Data} 테이블에서 +하나 이상의 {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} 행으로 표시됩니다). - 계정 유형과 계정에 대한 {@link android.provider.ContactsContract.Settings} 테이블 행에서 + 계정 유형과 계정에 대한 {@link android.provider.ContactsContract.Settings} 테이블 행에서 이 플래그를 설정하면 그룹이 없는 연락처가 표시되도록 강제할 수 있습니다. 이 플래그의 용도 중 하나는 그룹을 사용하지 않는 서버로부터 가져온 연락처를 표시하는 것입니다. - "1" - 이 계정과 계정 유형의 경우, 그룹에 속하지 않는 연락처가 애플리케이션 UI에 + "1" - 이 계정과 계정 유형의 경우, 그룹에 속하지 않는 연락처가 애플리케이션 UI에 표시됩니다. @@ -781,14 +781,14 @@ mProfileCursor = 이 테이블을 사용하여 동기화 어댑터의 메타데이터를 저장합니다. - 이 테이블을 사용하면 동기화 상태와 기타 동기화 관련 데이터를 기기에 영구적으로 + 이 테이블을 사용하면 동기화 상태와 기타 동기화 관련 데이터를 기기에 영구적으로 저장할 수 있습니다.

        연락처 제공자 액세스

        - 이 섹션은 연락처 제공자에서 가져온 데이터에 액세스하는 법에 대한 지침을 제공하며, + 이 섹션은 연락처 제공자에서 가져온 데이터에 액세스하는 법에 대한 지침을 제공하며, 요점은 다음과 같습니다.

          @@ -806,49 +806,49 @@ mProfileCursor =

        - 동기화 어댑터에서 수정하는 방법은 + 동기화 어댑터에서 수정하는 방법은 연락처 제공자 동기화 어댑터 섹션에도 자세히 설명되어 있습니다.

        엔티티 쿼리

        - 연락처 제공자 테이블은 계층을 사용하여 조직화되어 있으므로, -행과 그 행에 연결된 모든 "하위" 행을 검색하는 것이 유용할 때가 많습니다. 예를 들어, -어떤 개인의 모든 정보를 표시하려면 -하나의 {@link android.provider.ContactsContract.Contacts} 행에 대한 모든 -{@link android.provider.ContactsContract.RawContacts} 행을 검색하거나 하나의 -{@link android.provider.ContactsContract.RawContacts} 행에 대한 모든 -{@link android.provider.ContactsContract.CommonDataKinds.Email} 행을 검색하는 것이 좋습니다. 이를 용이하게 하기 위해, -연락처 제공자는 테이블 사이를 연결하는 데이터베이스 역할을 하는 엔티티 구조를 + 연락처 제공자 테이블은 계층을 사용하여 조직화되어 있으므로, +행과 그 행에 연결된 모든 "하위" 행을 검색하는 것이 유용할 때가 많습니다. 예를 들어, +어떤 개인의 모든 정보를 표시하려면 +하나의 {@link android.provider.ContactsContract.Contacts} 행에 대한 모든 +{@link android.provider.ContactsContract.RawContacts} 행을 검색하거나 하나의 +{@link android.provider.ContactsContract.RawContacts} 행에 대한 모든 +{@link android.provider.ContactsContract.CommonDataKinds.Email} 행을 검색하는 것이 좋습니다. 이를 용이하게 하기 위해, +연락처 제공자는 테이블 사이를 연결하는 데이터베이스 역할을 하는 엔티티 구조를 제공합니다.

        하나의 엔티티는 마치 상위 테이블과 그 하위 테이블에서 가져온 선택된 몇 개의 열로 이루어진 테이블과 같습니다. - 엔티티를 쿼리하는 경우, 해당 엔티티에서 사용할 수 있는 열을 기반으로 하여 예측과 검색 -기준을 제공합니다. 그 결과도 도출되는 것이 {@link android.database.Cursor}이며, -여기에 검색된 각 하위 테이블에 대해 행이 하나씩 들어있습니다. 예를 들어 연락처 이름에 대해 -{@link android.provider.ContactsContract.Contacts.Entity}를 쿼리하고 -그 이름에 대한 모든 원시 연락처에 대한 모든 {@link android.provider.ContactsContract.CommonDataKinds.Email} 행을 쿼리하면 -{@link android.database.Cursor}를 돌려받게 되며 이 안에 + 엔티티를 쿼리하는 경우, 해당 엔티티에서 사용할 수 있는 열을 기반으로 하여 예측과 검색 +기준을 제공합니다. 그 결과도 도출되는 것이 {@link android.database.Cursor}이며, +여기에 검색된 각 하위 테이블에 대해 행이 하나씩 들어있습니다. 예를 들어 연락처 이름에 대해 +{@link android.provider.ContactsContract.Contacts.Entity}를 쿼리하고 +그 이름에 대한 모든 원시 연락처에 대한 모든 {@link android.provider.ContactsContract.CommonDataKinds.Email} 행을 쿼리하면 +{@link android.database.Cursor}를 돌려받게 되며 이 안에 각 {@link android.provider.ContactsContract.CommonDataKinds.Email}행에 대한 행이 하나씩 들어있습니다.

        - 엔티티는 쿼리를 단순화합니다. 엔티티를 사용하면 연락처나 원시 연락처에 대한 모든 연락처 데이터를 -한꺼번에 검색할 수 있습니다. 즉 우선 상위 테이블을 검색하여 ID를 가져오고, 그런 다음 -하위 테이블을 그 ID로 검색하지 않아도 된다는 뜻입니다. 또한, 연락처 제공자에는 엔티티에 대한 쿼리를 -하나의 트랜잭션으로 처리하므로, 검색된 데이터가 내부적으로 일관성을 유지하도록 + 엔티티는 쿼리를 단순화합니다. 엔티티를 사용하면 연락처나 원시 연락처에 대한 모든 연락처 데이터를 +한꺼번에 검색할 수 있습니다. 즉 우선 상위 테이블을 검색하여 ID를 가져오고, 그런 다음 +하위 테이블을 그 ID로 검색하지 않아도 된다는 뜻입니다. 또한, 연락처 제공자에는 엔티티에 대한 쿼리를 +하나의 트랜잭션으로 처리하므로, 검색된 데이터가 내부적으로 일관성을 유지하도록 보장합니다.

        - 참고: 하나의 엔티티에 상위 및 하위 테이블의 모든 열이 들어있지는 않은 것이 -보통입니다. 엔티티에 대한 열 이름 상수 목록에 없는 열 이름으로 작업하려 시도하면, + 참고: 하나의 엔티티에 상위 및 하위 테이블의 모든 열이 들어있지는 않은 것이 +보통입니다. 엔티티에 대한 열 이름 상수 목록에 없는 열 이름으로 작업하려 시도하면, {@link java.lang.Exception}이 발생합니다.

        - 다음 조각은 하나의 연락처에 대해 모든 원시 연락처 행을 검색하는 방법을 나타낸 것입니다. 이 조각은 -두 개의 액티비티, 즉 "기본"과 "세부"를 가진 더 큰 애플리케이션의 일부입니다. 기본 액티비티는 -연락처 행 목록을 보여줍니다. 사용자가 하나를 선택하면, 이 액티비티가 해당 목록의 ID를 -세부 액티비티에 전송합니다. 세부 액티비티는 {@link android.provider.ContactsContract.Contacts.Entity}를 사용하여 -선택된 연락처와 연관된 모든 원시 연락처에서 + 다음 조각은 하나의 연락처에 대해 모든 원시 연락처 행을 검색하는 방법을 나타낸 것입니다. 이 조각은 +두 개의 액티비티, 즉 "기본"과 "세부"를 가진 더 큰 애플리케이션의 일부입니다. 기본 액티비티는 +연락처 행 목록을 보여줍니다. 사용자가 하나를 선택하면, 이 액티비티가 해당 목록의 ID를 +세부 액티비티에 전송합니다. 세부 액티비티는 {@link android.provider.ContactsContract.Contacts.Entity}를 사용하여 +선택된 연락처와 연관된 모든 원시 연락처에서 모든 데이터 행을 표시합니다.

        @@ -921,71 +921,71 @@ public Loader<Cursor> onCreateLoader(int id, Bundle args) { }

        - 로딩이 완료되면, {@link android.app.LoaderManager}가 + 로딩이 완료되면, {@link android.app.LoaderManager}가 {@link android.app.LoaderManager.LoaderCallbacks#onLoadFinished(Loader, D) -onLoadFinished()}에 대한 콜백을 호출합니다. 이 메서드로 수신되는 인수 중 하나가 -{@link android.database.Cursor}로, 여기에 쿼리 결과도 함께 들어옵니다. 개발자 본인의 앱에서는, 이 +onLoadFinished()}에 대한 콜백을 호출합니다. 이 메서드로 수신되는 인수 중 하나가 +{@link android.database.Cursor}로, 여기에 쿼리 결과도 함께 들어옵니다. 개발자 본인의 앱에서는, 이 {@link android.database.Cursor}에서 데이터를 가져와 이를 표시할 수도 있고 여기에 작업을 더할 수도 있습니다.

        일괄 수정

        - 연락처 제공자에서 데이터를 삽입, 업데이트 및 삭제하는 경우 가급적이면 -"일괄 모드"를 쓰는 것이 좋습니다. 이때 -{@link android.content.ContentProviderOperation} 객체의 {@link java.util.ArrayList}를 생성하고 -{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}를 호출하면 됩니다. 연락처 제공자는 + 연락처 제공자에서 데이터를 삽입, 업데이트 및 삭제하는 경우 가급적이면 +"일괄 모드"를 쓰는 것이 좋습니다. 이때 +{@link android.content.ContentProviderOperation} 객체의 {@link java.util.ArrayList}를 생성하고 +{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}를 호출하면 됩니다. 연락처 제공자는 -{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}에서의 모든 작업을 -하나의 트랜잭션으로 수행하기 때문에, 수정한 내용이 일관되지 않은 상태로 연락처 리포지토리를 -떠날 일이 결코 없습니다. 일괄 수정을 사용하면 원시 연락처와 그 세부 데이터를 동시에 삽입하는 것도 +{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}에서의 모든 작업을 +하나의 트랜잭션으로 수행하기 때문에, 수정한 내용이 일관되지 않은 상태로 연락처 리포지토리를 +떠날 일이 결코 없습니다. 일괄 수정을 사용하면 원시 연락처와 그 세부 데이터를 동시에 삽입하는 것도 쉽습니다.

        - 참고: 하나의 원시 연락처를 수정하려면 수정 작업을 앱에서 처리하는 것보다는 -인텐트를 기기의 연락처 애플리케이션에 보내는 방안을 고려하십시오. -이렇게 하는 방법이 + 참고: 하나의 원시 연락처를 수정하려면 수정 작업을 앱에서 처리하는 것보다는 +인텐트를 기기의 연락처 애플리케이션에 보내는 방안을 고려하십시오. +이렇게 하는 방법이 인텐트로 검색 및 수정 섹션에 자세히 설명되어 있습니다.

        양보 지점

        - 대량의 작업이 들어있는 일괄 수정은 다른 프로세스를 차단하므로, -그 결과 전반적으로 불량한 사용자 환경을 유발할 수 있습니다. 수행하고자 하는 모든 수정 작업을 가능한 한 -적은 수의 별도의 목록으로 정리하고 그와 동시에 이 작업이 시스템을 차단하지 못하도록 방지하려면 + 대량의 작업이 들어있는 일괄 수정은 다른 프로세스를 차단하므로, +그 결과 전반적으로 불량한 사용자 환경을 유발할 수 있습니다. 수행하고자 하는 모든 수정 작업을 가능한 한 +적은 수의 별도의 목록으로 정리하고 그와 동시에 이 작업이 시스템을 차단하지 못하도록 방지하려면 하나 이상의 작업에 양보 지점을 설정해야 합니다. 양보 지점은 {@link android.content.ContentProviderOperation#isYieldAllowed()} 값이 true로 설정된 {@link android.content.ContentProviderOperation} 객체입니다. - 연락처 제공자가 양보 지점을 만나면 -다른 프로세스가 실행되도록 작업을 잠시 멈추고 현재 트랜잭션을 종료합니다. 제공자가 다시 시작되면, 이는 -{@link java.util.ArrayList}에서 다음 작업을 계속 진행하고 + 연락처 제공자가 양보 지점을 만나면 +다른 프로세스가 실행되도록 작업을 잠시 멈추고 현재 트랜잭션을 종료합니다. 제공자가 다시 시작되면, 이는 +{@link java.util.ArrayList}에서 다음 작업을 계속 진행하고 새 트랜잭션을 시작합니다.

        - 양보 지점을 사용하면 그 결과 -{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}로의 호출 한 건당 하나 이상의 트랜잭션이 생기는 것은 사실입니다. 이 때문에, + 양보 지점을 사용하면 그 결과 +{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}로의 호출 한 건당 하나 이상의 트랜잭션이 생기는 것은 사실입니다. 이 때문에, 양보 지점은 관련된 행 한 세트에서 마지막 작업에 설정해야 합니다. - 예를 들어, 원시 연락처 행과 관련된 데이터 행을 추가하는 세트의 마지막 작업에 -양보 지점을 설정하거나, 하나의 연락처와 관련된 행 한 세트의 + 예를 들어, 원시 연락처 행과 관련된 데이터 행을 추가하는 세트의 마지막 작업에 +양보 지점을 설정하거나, 하나의 연락처와 관련된 행 한 세트의 마지막 작업에 양보 지점을 설정해야 합니다.

        - 양보 지점은 원자성 작업의 단위이기도 합니다. 두 개의 양보 지점 사이를 향한 액세스는 모두 -한 가지 단위로서 성공 또는 실패합니다. 양보 지점을 설정하지 않는 경우, 가장 작은 -원자성 작업은 작업 전체가 됩니다. 양보 지점을 사용하면, 작업이 -시스템 성능을 저하하지 않도록 방지하는 동시에 작업의 하위 세트가 원자성 작업이도록 + 양보 지점은 원자성 작업의 단위이기도 합니다. 두 개의 양보 지점 사이를 향한 액세스는 모두 +한 가지 단위로서 성공 또는 실패합니다. 양보 지점을 설정하지 않는 경우, 가장 작은 +원자성 작업은 작업 전체가 됩니다. 양보 지점을 사용하면, 작업이 +시스템 성능을 저하하지 않도록 방지하는 동시에 작업의 하위 세트가 원자성 작업이도록 보장할 수 있습니다.

        수정 역참조

        - 새로운 원시 연락처 행과 관련 데이터 행을 -일련의 {@link android.content.ContentProviderOperation} 개체로 삽입할 때는, - 원시 연락처의 + 새로운 원시 연락처 행과 관련 데이터 행을 +일련의 {@link android.content.ContentProviderOperation} 개체로 삽입할 때는, + 원시 연락처의 {@code android.provider.BaseColumns#_ID} 값을 -{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} 값으로 삽입하여 데이터 행과 원시 연락처 행을 연결해야 합니다. 그러나, 이 값은 -데이터 행에 대하여 {@link android.content.ContentProviderOperation}을 +{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} 값으로 삽입하여 데이터 행과 원시 연락처 행을 연결해야 합니다. 그러나, 이 값은 +데이터 행에 대하여 {@link android.content.ContentProviderOperation}을 생성하는 경우에는 사용할 수 없습니다. 원시 연락처 행에 대해 {@link android.content.ContentProviderOperation} -을 아직 적용하지 않았기 때문입니다. 이 문제를 해결하려면 +을 아직 적용하지 않았기 때문입니다. 이 문제를 해결하려면 {@link android.content.ContentProviderOperation.Builder} 클래스에 {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()} 메서드가 있어야 합니다. - 이 메서드를 사용하면 열을 이전 작업의 결과로 삽입 또는 수정할 수 + 이 메서드를 사용하면 열을 이전 작업의 결과로 삽입 또는 수정할 수 있습니다.

        @@ -997,29 +997,29 @@ onLoadFinished()}에 대한 콜백을 호출합니다. 이 메서드로 수신 key

        - 키-값 쌍의 키입니다. 이 인수의 값은 수정하는 테이블의 + 키-값 쌍의 키입니다. 이 인수의 값은 수정하는 테이블의 열 이름이어야 합니다.
        previousResult
        - + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}의 {@link android.content.ContentProviderResult} 객체 배열에 있는 -값의 0 기반 색인입니다. -일괄 작업이 적용되면 각 작업의 결과가 -결과의 중간 배열에 저장됩니다. previousResult 값은 -이러한 결과 중 하나의 색인이고, 이는 key 값으로 +값의 0 기반 색인입니다. +일괄 작업이 적용되면 각 작업의 결과가 +결과의 중간 배열에 저장됩니다. previousResult 값은 +이러한 결과 중 하나의 색인이고, 이는 key 값으로 검색 및 저장됩니다. 이것을 사용하면 새 원시 연락처 레코드를 삽입하고 -{@code android.provider.BaseColumns#_ID} 값을 다시 가져온 뒤, +{@code android.provider.BaseColumns#_ID} 값을 다시 가져온 뒤, {@link android.provider.ContactsContract.Data} 행을 추가할 때 해당 값을 "역참조"할 수 있게 해줍니다.

        - -{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}를 처음 호출할 때, -개발자가 제공하는 {@link android.content.ContentProviderOperation} 객체의 {@link java.util.ArrayList} 크기와 같은 크기로 -전체 결과 배열이 생성됩니다. 그러나 -결과 배열의 모든 요소는 null로 설정되고, -아직 적용되지 않은 작업 결과에 대한 역참조를 수행하려 시도하면 + +{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}를 처음 호출할 때, +개발자가 제공하는 {@link android.content.ContentProviderOperation} 객체의 {@link java.util.ArrayList} 크기와 같은 크기로 +전체 결과 배열이 생성됩니다. 그러나 +결과 배열의 모든 요소는 null로 설정되고, +아직 적용되지 않은 작업 결과에 대한 역참조를 수행하려 시도하면 {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}가 {@link java.lang.Exception}을 발생시킵니다. @@ -1027,15 +1027,15 @@ onLoadFinished()}에 대한 콜백을 호출합니다. 이 메서드로 수신

        - 다음 조각은 새로운 원시 연락처와 데이터를 일괄 삽입하는 방법을 나타낸 것입니다. 여기에는 -양보 지점을 지정하고 역참조를 사용하는 코드가 포함되어 있습니다. 이 조각은 -createContacEntry() 메서드의 확장 버전이며, 이는 + 다음 조각은 새로운 원시 연락처와 데이터를 일괄 삽입하는 방법을 나타낸 것입니다. 여기에는 +양보 지점을 지정하고 역참조를 사용하는 코드가 포함되어 있습니다. 이 조각은 +createContacEntry() 메서드의 확장 버전이며, 이는 - Contact Manager 샘플 애플리케이션에 있는 ContactAdder 클래스의 + Contact Manager 샘플 애플리케이션에 있는 ContactAdder 클래스의 일부입니다.

        - 첫 번째 조각은 UI에서 연락처 데이터를 검색합니다. 이 시점에서 사용자는 이미 + 첫 번째 조각은 UI에서 연락처 데이터를 검색합니다. 이 시점에서 사용자는 이미 새로운 원시 연락처를 추가할 계정을 선택하였습니다.

        @@ -1055,7 +1055,7 @@ protected void createContactEntry() {
                     mContactEmailTypeSpinner.getSelectedItemPosition());
         

        - 다음 조각은 + 다음 조각은 {@link android.provider.ContactsContract.RawContacts} 테이블에 원시 연락처 행을 삽입하는 작업을 생성합니다.

        @@ -1086,18 +1086,18 @@ protected void createContactEntry() {
             그런 다음, 코드가 표시 이름, 전화 및 이메일 행에 대한 데이터 행을 생성합니다.
         

        - 각 작업 빌더 개체는 -{@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}를 + 각 작업 빌더 개체는 +{@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}를 사용하여 -{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}를 가져옵니다. 참조는 -첫 번째 작업의 {@link android.content.ContentProviderResult} 객체를 다시 가리키고, +{@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}를 가져옵니다. 참조는 +첫 번째 작업의 {@link android.content.ContentProviderResult} 객체를 다시 가리키고, 이것이 원시 연락처 행을 추가한 뒤 이의 새 {@code android.provider.BaseColumns#_ID} -값을 반환합니다. 그 결과, 각 데이터 행은 자동으로 자신의 +값을 반환합니다. 그 결과, 각 데이터 행은 자동으로 자신의 {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID} 에 의해 자신이 속하는 새 {@link android.provider.ContactsContract.RawContacts} 행에 연결됩니다.

        - 이메일 행을 추가하는 {@link android.content.ContentProviderOperation.Builder} 객체는 + 이메일 행을 추가하는 {@link android.content.ContentProviderOperation.Builder} 객체는 양보 지점을 설정하는 {@link android.content.ContentProviderOperation.Builder#withYieldAllowed(boolean) withYieldAllowed()}로 플래그 표시합니다.

        @@ -1172,8 +1172,8 @@ withYieldAllowed()}로 플래그 표시합니다. ops.add(op.build());

        - 마지막 조각은 새로운 원시 연락처와 데이터 행을 삽입하는 -{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}에 대한 호출을 + 마지막 조각은 새로운 원시 연락처와 데이터 행을 삽입하는 +{@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()}에 대한 호출을 나타낸 것입니다.

        @@ -1205,32 +1205,32 @@ withYieldAllowed()}로 플래그 표시합니다.
         }
         

        - 일괄 작업을 사용하면 낙관적 동시성 제어도 구현할 수 있습니다. + 일괄 작업을 사용하면 낙관적 동시성 제어도 구현할 수 있습니다. 이것은 기본 리포지토리를 잠그지 않고도 수정 트랜잭션을 적용할 수 있는 메서드입니다. - 이 메서드를 사용하려면 트랜잭션을 적용하고 동시에 발생한 -다른 수정 사항이 있는지 확인합니다. 부합하지 않는 수정이 발생한 것을 발견하면 + 이 메서드를 사용하려면 트랜잭션을 적용하고 동시에 발생한 +다른 수정 사항이 있는지 확인합니다. 부합하지 않는 수정이 발생한 것을 발견하면 트랜잭션을 롤백하고 다시 시도합니다.

        - 낙관적 동시성 제어는 한 번에 한 명의 사용자만 존재하고 데이터 리포지토리에 대한 동시 액세스가 드문 모바일 기기에 -유용합니다. 잠금을 사용하지 않으므로 + 낙관적 동시성 제어는 한 번에 한 명의 사용자만 존재하고 데이터 리포지토리에 대한 동시 액세스가 드문 모바일 기기에 +유용합니다. 잠금을 사용하지 않으므로 잠금을 설정하거나 다른 트랜잭션이 잠금을 해제하기를 기다리면서 시간을 낭비하지 않습니다.

        - 하나의 + 하나의 {@link android.provider.ContactsContract.RawContacts} 행을 업데이트하면서 동시에 낙관적 동시성 제어를 사용하려면, 다음 단계를 따르십시오.

        1. - 검색하는 다른 데이터와 함께 행 연락처의 {@link android.provider.ContactsContract.SyncColumns#VERSION}을 + 검색하는 다른 데이터와 함께 행 연락처의 {@link android.provider.ContactsContract.SyncColumns#VERSION}을 검색합니다.
        2. - 제약을 강제 적용하는 데 적합한 -{@link android.content.ContentProviderOperation.Builder} 객체를 하나 생성하되 -{@link android.content.ContentProviderOperation#newAssertQuery(Uri)} 메서드를 사용합니다. 콘텐츠 URI의 경우, + 제약을 강제 적용하는 데 적합한 +{@link android.content.ContentProviderOperation.Builder} 객체를 하나 생성하되 +{@link android.content.ContentProviderOperation#newAssertQuery(Uri)} 메서드를 사용합니다. 콘텐츠 URI의 경우, {@link android.provider.ContactsContract.RawContacts#CONTENT_URI - RawContacts.CONTENT_URI}를 사용하되 + RawContacts.CONTENT_URI}를 사용하되 이에 추가된 원시 데이터의 {@code android.provider.BaseColumns#_ID}를 함께 씁니다.
        3. @@ -1256,13 +1256,13 @@ withExpectedCount()}를 호출하여 이 어설션이 테스트하는 행이 하

        행을 읽고 수정하려고 시도하는 사이에 다른 작업이 원시 연락처 행을 업데이트하면, -"어설션" {@link android.content.ContentProviderOperation}은 -실패하고 전체 일괄 작업이 취소됩니다. 그러면 일괄 작업을 다시 시도하거나 +"어설션" {@link android.content.ContentProviderOperation}은 +실패하고 전체 일괄 작업이 취소됩니다. 그러면 일괄 작업을 다시 시도하거나 다른 조치를 취하기로 선택할 수 있습니다.

        - 다음 조각은 {@link android.content.CursorLoader}를 사용하여 단일 원시 연락처를 쿼리한 후 -"어설션" {@link android.content.ContentProviderOperation}을 + 다음 조각은 {@link android.content.CursorLoader}를 사용하여 단일 원시 연락처를 쿼리한 후 +"어설션" {@link android.content.ContentProviderOperation}을 생성하는 방법을 나타낸 것입니다.

        @@ -1311,8 +1311,8 @@ try
         

        인텐트로 검색 및 수정

        - 기기 연락처 애플리케이션에 인텐트를 전송하면 연락처 제공자에 -간접적으로 액세스할 수 있습니다. 인텐트는 기기의 연락처 애플리케이션 UI를 시작하고, 여기서 사용자는 + 기기 연락처 애플리케이션에 인텐트를 전송하면 연락처 제공자에 +간접적으로 액세스할 수 있습니다. 인텐트는 기기의 연락처 애플리케이션 UI를 시작하고, 여기서 사용자는 연락처 관련 작업을 할 수 있습니다. 사용자가 이런 액세스 유형을 가지고 할 수 있는 일은 다음과 같습니다.

        • 목록에서 연락처를 선택하고 추가 작업을 위해 앱에 반환시킵니다.
        • @@ -1321,20 +1321,20 @@ try
        • 연락처 또는 연락처 데이터를 삭제합니다.

        - 사용자가 데이터를 삽입하거나 업데이트하고 있다면, 먼저 데이터를 수집하고 + 사용자가 데이터를 삽입하거나 업데이트하고 있다면, 먼저 데이터를 수집하고 인텐트의 일부로 전송할 수 있습니다.

        - 인텐트를 사용하여 기기의 연락처 애플리케이션을 통해 연락처 제공자에 액세스하는 경우 -제공자에 액세스하기 위해 개발자 나름의 UI나 코드를 작성하지 않아도 됩니다. 제공자에 대한 읽기 또는 쓰기 권한도 요청하지 않아도 -됩니다. 기기 연락처 애플리케이션은 -연락처에 대한 읽기 권한을 위임할 수 있고, 다른 애플리케이션을 통해 수정하기 때문에 + 인텐트를 사용하여 기기의 연락처 애플리케이션을 통해 연락처 제공자에 액세스하는 경우 +제공자에 액세스하기 위해 개발자 나름의 UI나 코드를 작성하지 않아도 됩니다. 제공자에 대한 읽기 또는 쓰기 권한도 요청하지 않아도 +됩니다. 기기 연락처 애플리케이션은 +연락처에 대한 읽기 권한을 위임할 수 있고, 다른 애플리케이션을 통해 수정하기 때문에 쓰기 권한도 필요 없습니다.

        - 제공자에 액세스하기 위해 인텐트를 전송하는 일반적인 과정은 + 제공자에 액세스하기 위해 인텐트를 전송하는 일반적인 과정은 "인텐트를 통한 데이터 액세스" 섹션의 -콘텐츠 제공자 기본 정보 가이드에 상세히 설명되어 있습니다. 이용 가능한 작업에 대해 사용하는 동작, +콘텐츠 제공자 기본 정보 가이드에 상세히 설명되어 있습니다. 이용 가능한 작업에 대해 사용하는 동작, MIME 유형 및 데이터 값은 표 4에 요약되어 있고, {@link android.content.Intent#putExtra(String, String) putExtra()}와 함께 사용할 수 있는 추가 값은 @@ -1358,20 +1358,20 @@ MIME 유형 및 데이터 값은 표 4에 요약되어 있고, 다음 중 하나로 정해집니다.

        • -{@link android.provider.ContactsContract.Contacts#CONTENT_URI Contacts.CONTENT_URI}, +{@link android.provider.ContactsContract.Contacts#CONTENT_URI Contacts.CONTENT_URI}, 이는 연락처 목록을 표시합니다.
        • -{@link android.provider.ContactsContract.CommonDataKinds.Phone#CONTENT_URI Phone.CONTENT_URI}, +{@link android.provider.ContactsContract.CommonDataKinds.Phone#CONTENT_URI Phone.CONTENT_URI}, 이는 원시 연락처에 대한 전화 번호 목록을 표시합니다.
        • {@link android.provider.ContactsContract.CommonDataKinds.StructuredPostal#CONTENT_URI -StructuredPostal.CONTENT_URI}, +StructuredPostal.CONTENT_URI}, 이는 원시 연락처에 대한 우편 주소 목록을 표시합니다.
        • -{@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_URI Email.CONTENT_URI}, +{@link android.provider.ContactsContract.CommonDataKinds.Email#CONTENT_URI Email.CONTENT_URI}, 이는 원시 연락처에 대한 이메일 주소 목록을 표시합니다.
        @@ -1380,15 +1380,15 @@ StructuredPostal.CONTENT_URI}, 사용하지 않음 - 개발자가 제공하는 콘텐츠 URI에 따라 원시 연락처 목록이나 원시 연락처에서 가져온 + 개발자가 제공하는 콘텐츠 URI에 따라 원시 연락처 목록이나 원시 연락처에서 가져온 데이터 목록을 표시합니다.

        - -{@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()} 호출, -이는 선택한 행의 콘텐츠 URI를 반환합니다. URI의 형태는 + +{@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()} 호출, +이는 선택한 행의 콘텐츠 URI를 반환합니다. URI의 형태는 테이블의 콘텐츠 URI에 행의 LOOKUP_ID를 추가한 것입니다. - 기기의 연락처 앱은 액티비티 수명 동안 이 콘텐츠 URI에 -읽기 및 쓰기 권한을 위임합니다. 자세한 내용은 + 기기의 연락처 앱은 액티비티 수명 동안 이 콘텐츠 URI에 +읽기 및 쓰기 권한을 위임합니다. 자세한 내용은 콘텐츠 제공자 기본 정보 가이드를 참조하십시오.

        @@ -1403,12 +1403,12 @@ StructuredPostal.CONTENT_URI}, RawContacts.CONTENT_TYPE}, 일련의 원시 연락처에 대한 MIME 유형입니다. - 기기의 연락처 애플리케이션의 연락처 추가 화면을 표시합니다. 개발자가 -인텐트에 추가하는 추가 사항 값이 표시됩니다. + 기기의 연락처 애플리케이션의 연락처 추가 화면을 표시합니다. 개발자가 +인텐트에 추가하는 추가 사항 값이 표시됩니다. {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()}와 함께 전송되는 경우, -새로 추가된 원시 연락처의 콘텐츠 URI는 +새로 추가된 원시 연락처의 콘텐츠 URI는 "데이터" 필드의 {@link android.content.Intent} 인수에 있는 액티비티의 {@link android.app.Activity#onActivityResult(int, int, Intent) onActivityResult()} -콜백 메서드로 +콜백 메서드로 다시 전달됩니다. 값을 가져오려면, {@link android.content.Intent#getData()}를 호출합니다. @@ -1416,16 +1416,16 @@ RawContacts.CONTENT_TYPE}, 일련의 원시 연락처에 대한 MIME 유형입 연락처 편집 {@link android.content.Intent#ACTION_EDIT} - 연락처에 대한 -{@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}입니다. 편집자 액티비티를 사용하면 사용자가 이 연락처와 관련된 데이터를 어느 것이든 + 연락처에 대한 +{@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}입니다. 편집자 액티비티를 사용하면 사용자가 이 연락처와 관련된 데이터를 어느 것이든 편집할 수 있습니다. {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE Contacts.CONTENT_ITEM_TYPE}, 하나의 연락처입니다. - 연락처 애플리케이션에 연락처 편집 화면을 표시합니다. 개발자가 -인텐트에 추가하는 추가 사항 값이 표시됩니다. 사용자가 완료를 클릭하여 편집 내용을 저장하면, + 연락처 애플리케이션에 연락처 편집 화면을 표시합니다. 개발자가 +인텐트에 추가하는 추가 사항 값이 표시됩니다. 사용자가 완료를 클릭하여 편집 내용을 저장하면, 액티비티가 전경으로 돌아옵니다. @@ -1439,31 +1439,31 @@ Contacts.CONTENT_ITEM_TYPE}, 하나의 연락처입니다. {@link android.provider.ContactsContract.Contacts#CONTENT_ITEM_TYPE} - 이 인텐트는 항상 연락처 앱의 선택기 화면을 표시합니다. 사용자는 -편집할 연락처를 선택하거나 새 연락처를 추가할 수 있습니다. 사용자의 선택에 따라 -편집 또는 추가 화면이 나타나고 개발자가 인텐트에 전달하는 추가 사항 데이터가 -표시됩니다. 앱이 이메일이나 전화 번호 등의 연락처 데이터를 표시하는 경우, -이 인텐트를 사용하면 사용자가 기존 연락처에 데이터를 추가할 수 + 이 인텐트는 항상 연락처 앱의 선택기 화면을 표시합니다. 사용자는 +편집할 연락처를 선택하거나 새 연락처를 추가할 수 있습니다. 사용자의 선택에 따라 +편집 또는 추가 화면이 나타나고 개발자가 인텐트에 전달하는 추가 사항 데이터가 +표시됩니다. 앱이 이메일이나 전화 번호 등의 연락처 데이터를 표시하는 경우, +이 인텐트를 사용하면 사용자가 기존 연락처에 데이터를 추가할 수 있습니다.

        - 참고: 이 인텐트의 추가 사항에서는 이름 값을 전송하지 않아도 됩니다. -사용자가 항상 기존의 이름을 선택하거나 새 이름을 추가하기 때문입니다. 게다가, -개발자가 이름을 전송하고 사용자가 편집을 선택하면 연락처 앱은 개발자가 전송한 이름을 표시하면서 -이전 값을 재정의하게 됩니다. 사용자가 + 참고: 이 인텐트의 추가 사항에서는 이름 값을 전송하지 않아도 됩니다. +사용자가 항상 기존의 이름을 선택하거나 새 이름을 추가하기 때문입니다. 게다가, +개발자가 이름을 전송하고 사용자가 편집을 선택하면 연락처 앱은 개발자가 전송한 이름을 표시하면서 +이전 값을 재정의하게 됩니다. 사용자가 이를 눈치채지 못하고 편집 내용을 저장하면 이전 값은 손실됩니다.

        - 기기의 연락처 앱은 개발자가 인텐트로 원시 연락처 또는 그에 속한 모든 데이터를 삭제하도록 -허용하지 않습니다. 대신, 원시 연락처를 삭제하려면 -{@link android.content.ContentResolver#delete(Uri, String, String[]) ContentResolver.delete()} + 기기의 연락처 앱은 개발자가 인텐트로 원시 연락처 또는 그에 속한 모든 데이터를 삭제하도록 +허용하지 않습니다. 대신, 원시 연락처를 삭제하려면 +{@link android.content.ContentResolver#delete(Uri, String, String[]) ContentResolver.delete()} 또는 {@link android.content.ContentProviderOperation#newDelete(Uri) ContentProviderOperation.newDelete()}를 사용합니다.

        - 다음 조각은 새로운 원시 연락처와 + 다음 조각은 새로운 원시 연락처와 데이터를 삽입하는 인텐트를 구성, 전송하는 방법을 나타낸 것입니다.

        @@ -1560,65 +1560,65 @@ startActivity(insertIntent);
         

        데이터 무결성

        - 연락처 리포지토리에는 사용자 측에서 올바르고 최신일 것으로 기대하는 중요하고 민감한 데이터가 들어있으므로 -연락처 제공자는 데이터 무결성에 대한 잘 정의된 규칙이 있습니다. 개발자 -여러분에게는 연락처 데이터를 수정할 때 이와 같은 규칙을 준수할 의무가 있습니다. 아래에는 중요한 규칙을 + 연락처 리포지토리에는 사용자 측에서 올바르고 최신일 것으로 기대하는 중요하고 민감한 데이터가 들어있으므로 +연락처 제공자는 데이터 무결성에 대한 잘 정의된 규칙이 있습니다. 개발자 +여러분에게는 연락처 데이터를 수정할 때 이와 같은 규칙을 준수할 의무가 있습니다. 아래에는 중요한 규칙을 몇 가지 나열해 놓았습니다.

        - {@link android.provider.ContactsContract.RawContacts} 행을 추가할 때마다 언제나 + {@link android.provider.ContactsContract.RawContacts} 행을 추가할 때마다 언제나 {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 행을 추가합니다.
        - {@link android.provider.ContactsContract.Data} 테이블에 {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 행이 없는 {@link android.provider.ContactsContract.RawContacts} 행이 있으면 + {@link android.provider.ContactsContract.Data} 테이블에 {@link android.provider.ContactsContract.CommonDataKinds.StructuredName} 행이 없는 {@link android.provider.ContactsContract.RawContacts} 행이 있으면 통합 과정에서 문제가 발생할 수 있습니다.
        - 언제나 새로운 {@link android.provider.ContactsContract.Data} 행을 + 언제나 새로운 {@link android.provider.ContactsContract.Data} 행을 해당 상위 {@link android.provider.ContactsContract.RawContacts} 행에 연결합니다.
        - {@link android.provider.ContactsContract.RawContacts}에 연결되지 않은 {@link android.provider.ContactsContract.Data} 행은 -기기 연락처 애플리케이션에 표시되지 않고, + {@link android.provider.ContactsContract.RawContacts}에 연결되지 않은 {@link android.provider.ContactsContract.Data} 행은 +기기 연락처 애플리케이션에 표시되지 않고, 동기화 어댑터에서 문제를 발생시킬 수 있습니다.
        개발자 본인의 소유인 원시 연락처에 대한 데이터만 변경하십시오.
        - 연락처 제공자는 보통 여러 가지 서로 다른 계정 유형/온라인 서비스에서 가져온 -데이터를 관리한다는 점을 명심하십시오. 개발자의 애플리케이션은 본인에게 -속한 행에 대한 데이터만 수정 또는 삭제하도록 확실히 해두어야 하며, 데이터를 삽입할 때에도 개발자 본인이 + 연락처 제공자는 보통 여러 가지 서로 다른 계정 유형/온라인 서비스에서 가져온 +데이터를 관리한다는 점을 명심하십시오. 개발자의 애플리케이션은 본인에게 +속한 행에 대한 데이터만 수정 또는 삭제하도록 확실히 해두어야 하며, 데이터를 삽입할 때에도 개발자 본인이 제어하는 계정 유형과 이름만 사용해야 합니다.
        - 권한, 콘텐츠 URI, URI 경로, 열 이름, MIME 유형 및 -{@link android.provider.ContactsContract.CommonDataKinds.CommonColumns#TYPE} 값에 대해서는 항상 + 권한, 콘텐츠 URI, URI 경로, 열 이름, MIME 유형 및 +{@link android.provider.ContactsContract.CommonDataKinds.CommonColumns#TYPE} 값에 대해서는 항상 {@link android.provider.ContactsContract} 및 그 하위 클래스에서 정의한 상수를 사용합니다.
        - 이런 상수를 사용하면 오류를 피하는 데 도움이 됩니다. 이런 상수 중 하나라도 사용하지 않게 되는 경우 컴파일러로부터 + 이런 상수를 사용하면 오류를 피하는 데 도움이 됩니다. 이런 상수 중 하나라도 사용하지 않게 되는 경우 컴파일러로부터 알림을 받기도 합니다.

        사용자 지정 데이터 행

        사용자 지정 MIME 유형을 생성하여 사용하면, -{@link android.provider.ContactsContract.Data} 테이블에 있는 본인의 데이터 행을 삽입, 편집, 삭제 및 검색할 수 있습니다. 개발자의 행은 -{@link android.provider.ContactsContract.DataColumns}에서 -정의된 열만 사용하도록 제한되어 있습니다. 다만 나름의 유형별 열 이름을 -기본 열 이름에 매핑할 수는 있습니다. 기기의 연락처 애플리케이션에서는 -개발자의 행에 대한 데이터가 표시는 되지만 편집이나 삭제는 할 수 없고, 사용자가 추가 데이터를 -추가할 수도 없습니다. 사용자가 개발자의 사용자 지정 데이터 행을 수정하도록 허용하려면, 본인의 애플리케이션에 +{@link android.provider.ContactsContract.Data} 테이블에 있는 본인의 데이터 행을 삽입, 편집, 삭제 및 검색할 수 있습니다. 개발자의 행은 +{@link android.provider.ContactsContract.DataColumns}에서 +정의된 열만 사용하도록 제한되어 있습니다. 다만 나름의 유형별 열 이름을 +기본 열 이름에 매핑할 수는 있습니다. 기기의 연락처 애플리케이션에서는 +개발자의 행에 대한 데이터가 표시는 되지만 편집이나 삭제는 할 수 없고, 사용자가 추가 데이터를 +추가할 수도 없습니다. 사용자가 개발자의 사용자 지정 데이터 행을 수정하도록 허용하려면, 본인의 애플리케이션에 편집기 액티비티를 제공해야 합니다.

        - 개발자의 사용자 지정 데이터를 표시하려면, <ContactsAccountType> 요소와 하나 이상의 <ContactsDataKind> 하위 요소를 포함하는 contacts.xml 파일을 + 개발자의 사용자 지정 데이터를 표시하려면, <ContactsAccountType> 요소와 하나 이상의 <ContactsDataKind> 하위 요소를 포함하는 contacts.xml 파일을 제공합니다. - 이 내용은 + 이 내용은 <ContactsDataKind> element 섹션에 자세히 설명되어 있습니다.

        @@ -1628,15 +1628,15 @@ startActivity(insertIntent);

        연락처 제공자 동기화 어댑터

        - 연락처 제공자는 기기와 온라인 서비스 사이에서 연락처 데이터의 동기화를 -처리한다는 구체적인 목적을 두고 디자인된 것입니다. 이것을 사용하면 사용자가 기존의 + 연락처 제공자는 기기와 온라인 서비스 사이에서 연락처 데이터의 동기화를 +처리한다는 구체적인 목적을 두고 디자인된 것입니다. 이것을 사용하면 사용자가 기존의 데이터를 새 기기에 다운로드할 수도 있고, 기존의 데이터를 새 계정에 업로드할 수도 있습니다. - 동기화를 사용하면 사용자가 추가나 변경의 출처와 관계 없이 최신 데이터를 -편리하게 사용할 수 있게 보장하기도 합니다. 동기화의 또 다른 장점은 + 동기화를 사용하면 사용자가 추가나 변경의 출처와 관계 없이 최신 데이터를 +편리하게 사용할 수 있게 보장하기도 합니다. 동기화의 또 다른 장점은 기기가 네트워크에 연결되어 있지 않더라도 연락처 데이터를 사용할 수 있다는 것입니다.

        - 다양한 방식으로 동기화를 구현할 수 있지만, Android 시스템은 + 다양한 방식으로 동기화를 구현할 수 있지만, Android 시스템은 플러그인 동기화 프레임워크를 제공하여 다음과 같은 작업들을 자동화해줍니다.

          @@ -1651,40 +1651,40 @@ startActivity(insertIntent);

        - 이 프레임워크를 사용하려면 동기화 어댑터 플러그인은 개발자가 직접 제공해야 합니다. 동기화 어댑터는 -서비스와 콘텐츠 제공자마다 각기 다르지만, 같은 서비스에 대해 여러 개의 계정 이름을 처리할 수 있습니다. 이 + 이 프레임워크를 사용하려면 동기화 어댑터 플러그인은 개발자가 직접 제공해야 합니다. 동기화 어댑터는 +서비스와 콘텐츠 제공자마다 각기 다르지만, 같은 서비스에 대해 여러 개의 계정 이름을 처리할 수 있습니다. 이 프레임워크 또한 같은 서비스와 제공자에 대해 여러 개의 동기화 어댑터를 허용합니다.

        동기화 어댑터 클래스 및 파일

        - 동기화 어댑터를 -{@link android.content.AbstractThreadedSyncAdapter}의 -하위 클래스로 구현하고 이를Android 애플리케이션의 일부로 설치합니다. 시스템은 애플리케이션 매니페스트의 요소와 매니페스트가 가리키는 -특수 XML 파일에서 동기화 어댑터에 관한 정보를 얻습니다. XML 파일은 -온라인 서비스와 콘텐츠 제공자의 권한에 대한 계정 유형을 정의하고, -이들이 함께 어댑터를 고유하게 식별합니다. 동기화 어댑터가 활성화되려면 사용자가 -동기화 어댑터의 계정 유형에 대해 계정을 추가하고 해당 동기화 어댑터와 동기화하는 콘텐츠 제공자의 동기화를 -활성화해야 합니다. 이 시점에서, 시스템이 어댑터 관리를 시작하고, + 동기화 어댑터를 +{@link android.content.AbstractThreadedSyncAdapter}의 +하위 클래스로 구현하고 이를Android 애플리케이션의 일부로 설치합니다. 시스템은 애플리케이션 매니페스트의 요소와 매니페스트가 가리키는 +특수 XML 파일에서 동기화 어댑터에 관한 정보를 얻습니다. XML 파일은 +온라인 서비스와 콘텐츠 제공자의 권한에 대한 계정 유형을 정의하고, +이들이 함께 어댑터를 고유하게 식별합니다. 동기화 어댑터가 활성화되려면 사용자가 +동기화 어댑터의 계정 유형에 대해 계정을 추가하고 해당 동기화 어댑터와 동기화하는 콘텐츠 제공자의 동기화를 +활성화해야 합니다. 이 시점에서, 시스템이 어댑터 관리를 시작하고, 콘텐츠 제공자와 서버 사이에서 동기화가 필요할 때 이를 호출합니다.

        - 참고: 계정 유형을 동기화 어댑터 식별의 일부로 사용하면 -시스템이 동일한 같은 조직에서 여러 서비스에 액세스하는 동기화 어댑터를 -감지하고 그룹화할 수 있습니다. 예를 들어, Google 온라인 서비스의 동기화 어댑터는 계정 유형이 모두 -com.google로 같습니다. 사용자가 기기에 Google 계정을 추가하면, -Google 서비스에 설치된 모든 동기화 어댑터가 함께 목록으로 표시됩니다. 목록에 게재된 각 동기화는 + 참고: 계정 유형을 동기화 어댑터 식별의 일부로 사용하면 +시스템이 동일한 같은 조직에서 여러 서비스에 액세스하는 동기화 어댑터를 +감지하고 그룹화할 수 있습니다. 예를 들어, Google 온라인 서비스의 동기화 어댑터는 계정 유형이 모두 +com.google로 같습니다. 사용자가 기기에 Google 계정을 추가하면, +Google 서비스에 설치된 모든 동기화 어댑터가 함께 목록으로 표시됩니다. 목록에 게재된 각 동기화는 기기에서 각기 다른 콘텐츠 제공자와 동기화합니다.

        - 대부분의 서비스에서는 사용자가 데이터에 액세스하기 전에 -ID를 확인해야 하기 때문에 Android에서는 동기화 어댑터 프레임워크와 비슷하면서 종종 이와 함께 쓰이기도 하는 -인증 프레임워크를 제공합니다. 인증 프레임워크는 -{@link android.accounts.AbstractAccountAuthenticator}의 하위 클래스인 -플러그인 인증자를 사용합니다. 인증자는 다음 절차에 따라 + 대부분의 서비스에서는 사용자가 데이터에 액세스하기 전에 +ID를 확인해야 하기 때문에 Android에서는 동기화 어댑터 프레임워크와 비슷하면서 종종 이와 함께 쓰이기도 하는 +인증 프레임워크를 제공합니다. 인증 프레임워크는 +{@link android.accounts.AbstractAccountAuthenticator}의 하위 클래스인 +플러그인 인증자를 사용합니다. 인증자는 다음 절차에 따라 사용자의 ID를 확인합니다.

        1. - 사용자 이름, 암호 또는 유사한 정보(사용자의 + 사용자 이름, 암호 또는 유사한 정보(사용자의 자격 증명)를 수집합니다.
        2. @@ -1695,9 +1695,9 @@ ID를 확인해야 하기 때문에 Android에서는 동기화 어댑터 프레

        - 서비스가 자격 증명을 수락하면 -인증자가 자격 증명을 저장하여 나중에 사용할 수 있습니다. 플러그인 인증자 프레임워크로 인해, -{@link android.accounts.AccountManager}는 Oauth2 authToken과 같이 인증자가 지원하고 노출하기로 선택하는 모든 authToken에 액세스를 + 서비스가 자격 증명을 수락하면 +인증자가 자격 증명을 저장하여 나중에 사용할 수 있습니다. 플러그인 인증자 프레임워크로 인해, +{@link android.accounts.AccountManager}는 Oauth2 authToken과 같이 인증자가 지원하고 노출하기로 선택하는 모든 authToken에 액세스를 제공합니다.

        @@ -1706,18 +1706,18 @@ ID를 확인해야 하기 때문에 Android에서는 동기화 어댑터 프레

        동기화 어댑터 구현

        - 연락처 제공자에 대한 동기화 어댑터를 구현하려면, + 연락처 제공자에 대한 동기화 어댑터를 구현하려면, 다음이 들어있는 Android 애플리케이션을 생성하는 것으로 시작합니다.

        - 시스템의 요청에 응답하여 동기화 어댑터에 바인딩하는 {@link android.app.Service} + 시스템의 요청에 응답하여 동기화 어댑터에 바인딩하는 {@link android.app.Service} 구성 요소.
        - 시스템이 동기화를 실행하고자 하는 경우, 이는 + 시스템이 동기화를 실행하고자 하는 경우, 이는 서비스의 {@link android.app.Service#onBind(Intent) onBind()} 메서드를 호출하여 -동기화 어댑터의 {@link android.os.IBinder}를 가져옵니다. 이렇게 하면 시스템이 어댑터의 +동기화 어댑터의 {@link android.os.IBinder}를 가져옵니다. 이렇게 하면 시스템이 어댑터의 메서드에 대해 프로세스간 호출을 수행할 수 있습니다.

        @@ -1726,18 +1726,18 @@ ID를 확인해야 하기 때문에 Android에서는 동기화 어댑터 프레

        - {@link android.content.AbstractThreadedSyncAdapter}의 + {@link android.content.AbstractThreadedSyncAdapter}의 하위 클래스로 구현된 실제 동기화 어댑터.
        - 이 클래스는 서버에서 데이터를 다운로드하고, 기기에서 데이터를 업로드하고, -충돌을 해결하는 작업을 수행합니다. 어댑터의 주요 작업은 + 이 클래스는 서버에서 데이터를 다운로드하고, 기기에서 데이터를 업로드하고, +충돌을 해결하는 작업을 수행합니다. 어댑터의 주요 작업은 {@link android.content.AbstractThreadedSyncAdapter#onPerformSync( Account, Bundle, String, ContentProviderClient, SyncResult) onPerformSync()} 메서드에서 실행합니다. 이 클래스는 반드시 단일 항목으로 인스턴트화해야 합니다.

        -샘플 동기화 어댑터 샘플 앱에서 동기화 어댑터는 +샘플 동기화 어댑터 샘플 앱에서 동기화 어댑터는 com.example.android.samplesync.syncadapter.SyncAdapter 클래스에서 정의됩니다.

        @@ -1745,23 +1745,23 @@ onPerformSync()} 메서드에서 실행합니다. 이 클래스는 반드시 단 {@link android.app.Application}의 하위 클래스.
        - 이 클래스는 동기화 어댑터 단일 항목의 팩터리 역할을 합니다. -{@link android.app.Application#onCreate()} 메서드는 -동기화 어댑터를 인스턴트화하고, 단일 항목을 동기화 어댑터 서비스의 -{@link android.app.Service#onBind(Intent) onBind()} 메서드에 반환할 정적 "getter" 메서드를 제공하는 데 + 이 클래스는 동기화 어댑터 단일 항목의 팩터리 역할을 합니다. +{@link android.app.Application#onCreate()} 메서드는 +동기화 어댑터를 인스턴트화하고, 단일 항목을 동기화 어댑터 서비스의 +{@link android.app.Service#onBind(Intent) onBind()} 메서드에 반환할 정적 "getter" 메서드를 제공하는 데 사용하십시오.
        - 선택 항목: 사용자 인증에 대한 시스템으로부터의 요청에 응답하는 {@link android.app.Service} + 선택 항목: 사용자 인증에 대한 시스템으로부터의 요청에 응답하는 {@link android.app.Service} 구성 요소.
        - {@link android.accounts.AccountManager}가 이 서비스를 시작하여 인증 -절차를 시작합니다. 서비스의 {@link android.app.Service#onCreate()} 메서드가 -인증자 객체를 인스턴트화합니다. 시스템이 애플리케이션 동기화 어댑터의 사용자 계정을 인증하고자 하는 경우, -시스템은 서비스의 -{@link android.app.Service#onBind(Intent) onBind()} 메서드를 호출하여 -인증자의 {@link android.os.IBinder}를 가져옵니다. 이렇게 하면 시스템이 인증자의 + {@link android.accounts.AccountManager}가 이 서비스를 시작하여 인증 +절차를 시작합니다. 서비스의 {@link android.app.Service#onCreate()} 메서드가 +인증자 객체를 인스턴트화합니다. 시스템이 애플리케이션 동기화 어댑터의 사용자 계정을 인증하고자 하는 경우, +시스템은 서비스의 +{@link android.app.Service#onBind(Intent) onBind()} 메서드를 호출하여 +인증자의 {@link android.os.IBinder}를 가져옵니다. 이렇게 하면 시스템이 인증자의 메서드에 대해 프로세스간 호출을 수행할 수 있습니다.

        @@ -1770,18 +1770,18 @@ onPerformSync()} 메서드에서 실행합니다. 이 클래스는 반드시 단

        - 선택 항목: 인증에 대한 요청을 처리하는 -{@link android.accounts.AbstractAccountAuthenticator}의 구체적인 + 선택 항목: 인증에 대한 요청을 처리하는 +{@link android.accounts.AbstractAccountAuthenticator}의 구체적인 하위 클래스.
        - 이 클래스는 {@link android.accounts.AccountManager}가 -서버로 사용자 자격 증명 인증을 호출하는 메서드를 제공합니다. 인증 절차의 세부 사항은 -사용하는 서버 기술에 따라 매우 차이가 있습니다. 인증에 대한 + 이 클래스는 {@link android.accounts.AccountManager}가 +서버로 사용자 자격 증명 인증을 호출하는 메서드를 제공합니다. 인증 절차의 세부 사항은 +사용하는 서버 기술에 따라 매우 차이가 있습니다. 인증에 대한 자세한 정보는 각자의 서버 소프트웨어에 해당되는 관련 문서를 참조하십시오.

        -샘플 동기화 어댑터 샘플 앱에서 인증자는 +샘플 동기화 어댑터 샘플 앱에서 인증자는 com.example.android.samplesync.authenticator.Authenticator 클래스에서 정의됩니다.

        @@ -1789,31 +1789,31 @@ onPerformSync()} 메서드에서 실행합니다. 이 클래스는 반드시 단 동기화 어댑터와 서버의 인증자를 정의하는 XML 파일.
        - 이전에 설명한 동기화 어댑터와 인증자 서비스 구성 요소는 -애플리케이션 매니페스트의 -<service> 요소에서 -정의합니다. 이런 요소에는 -시스템에 특정 데이터를 제공하는 + 이전에 설명한 동기화 어댑터와 인증자 서비스 구성 요소는 +애플리케이션 매니페스트의 +<service> 요소에서 +정의합니다. 이런 요소에는 +시스템에 특정 데이터를 제공하는 <meta-data> -하위 요소가 +하위 요소가 들어있습니다.
        • - 동기화 어댑터 서비스에 대한 + 동기화 어댑터 서비스에 대한 <meta-data> -요소는 -XML 파일 res/xml/syncadapter.xml을 가리킵니다. 그런가 하면 -이 파일은 연락처 제공자와 동기화될 웹 서비스에 대한 URI와 웹 서비스에 대한 계정 유형을 +요소는 +XML 파일 res/xml/syncadapter.xml을 가리킵니다. 그런가 하면 +이 파일은 연락처 제공자와 동기화될 웹 서비스에 대한 URI와 웹 서비스에 대한 계정 유형을 나타냅니다.
        • - 선택 항목: 인증자의 + 선택 항목: 인증자의 <meta-data> -요소는 XML 파일 -res/xml/authenticator.xml을 가리킵니다. 이 파일은 다시 -이 인증이 지원하는 계정 유형과, 인증 과정 중에 표시되는 UI 리소스를 -나타냅니다. 이 요소에서 지정한 계정 유형은 반드시 -동기화 어댑터에 대해 지정된 계정 유형과 +요소는 XML 파일 +res/xml/authenticator.xml을 가리킵니다. 이 파일은 다시 +이 인증이 지원하는 계정 유형과, 인증 과정 중에 표시되는 UI 리소스를 +나타냅니다. 이 요소에서 지정한 계정 유형은 반드시 +동기화 어댑터에 대해 지정된 계정 유형과 같아야 합니다.
        @@ -1821,18 +1821,18 @@ XML 파일 res/xml/syncadapter.xml을 가리킵니다. 그런가

        소셜 스트림 데이터

        - {@code android.provider.ContactsContract.StreamItems}와 -{@code android.provider.ContactsContract.StreamItemPhotos} 테이블은 -소셜 네트워크에서 수신하는 데이터를 관리합니다. 개발자는 본인의 네트워크의 스트림 데이터를 이 테이블에 추가하는 -동기화 어댑터를 작성할 수도 있고, 이 테이블에서 스트림 데이터를 읽어서 -본인의 애플리케이션에 표시할 수도 있으며 두 가지를 모두 해도 됩니다. 이 기능을 사용하면 소셜 네트워킹 + {@code android.provider.ContactsContract.StreamItems}와 +{@code android.provider.ContactsContract.StreamItemPhotos} 테이블은 +소셜 네트워크에서 수신하는 데이터를 관리합니다. 개발자는 본인의 네트워크의 스트림 데이터를 이 테이블에 추가하는 +동기화 어댑터를 작성할 수도 있고, 이 테이블에서 스트림 데이터를 읽어서 +본인의 애플리케이션에 표시할 수도 있으며 두 가지를 모두 해도 됩니다. 이 기능을 사용하면 소셜 네트워킹 서비스와 애플리케이션을 Android의 소셜 네트워킹 환경에 통합할 수 있습니다.

        소셜 스트림 텍스트

        - 스트림 항목은 항상 원시 연락처와 연관됩니다. -{@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}는 -원시 연락처의 _ID 값과 연관됩니다. 원시 연락처의 계정 유형과 계정 이름도 + 스트림 항목은 항상 원시 연락처와 연관됩니다. +{@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}는 +원시 연락처의 _ID 값과 연관됩니다. 원시 연락처의 계정 유형과 계정 이름도 스트림 항목 행에 저장됩니다.

        @@ -1843,36 +1843,36 @@ XML 파일 res/xml/syncadapter.xml을 가리킵니다. 그런가 {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE}

        - 필수입니다. 이 스트림 항목과 연관된 원시 연락처에 대한 + 필수입니다. 이 스트림 항목과 연관된 원시 연락처에 대한 사용자 계정입니다. 스트림 항목을 삽입할 때 이 값을 설정하는 것을 잊지 마십시오.
        {@code android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME}
        - 필수입니다. 이 스트림 항목과 연관된 원시 연락처에 대한 + 필수입니다. 이 스트림 항목과 연관된 원시 연락처에 대한 사용자 계정 이름입니다. 스트림 항목을 삽입할 때 이 값을 설정하는 것을 잊지 마십시오.
        식별자 열
        - 필수입니다. 스트림 항목을 삽입할 때 + 필수입니다. 스트림 항목을 삽입할 때 다음 식별자 열을 삽입해야 합니다.
        • - {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID}: 이 -스트림 항목과 연관된 연락처의 {@code android.provider.BaseColumns#_ID} + {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID}: 이 +스트림 항목과 연관된 연락처의 {@code android.provider.BaseColumns#_ID} 값입니다.
        • - {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY}: 이 -스트림 항목과 연관된 연락처의 {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} + {@code android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY}: 이 +스트림 항목과 연관된 연락처의 {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} 값입니다.
        • - {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}: 이 -스트림 항목과 연관된 원시 연락처의 {@code android.provider.BaseColumns#_ID} + {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID}: 이 +스트림 항목과 연관된 원시 연락처의 {@code android.provider.BaseColumns#_ID} 값입니다.
        @@ -1887,19 +1887,19 @@ XML 파일 res/xml/syncadapter.xml을 가리킵니다. 그런가 {@code android.provider.ContactsContract.StreamItemsColumns#TEXT}
        - 스트림 항목의 텍스트로, 항목의 소스가 게시한 콘텐츠 또는 -스트림 항목을 생성하는 작업의 설명 중 하나입니다. 이 열에는 -{@link android.text.Html#fromHtml(String) fromHtml()}가 렌더링할 수 있는 모든 서식과 포함된 리소스 이미지가 -들어있을 수 있습니다. 제공자는 긴 콘텐츠를 + 스트림 항목의 텍스트로, 항목의 소스가 게시한 콘텐츠 또는 +스트림 항목을 생성하는 작업의 설명 중 하나입니다. 이 열에는 +{@link android.text.Html#fromHtml(String) fromHtml()}가 렌더링할 수 있는 모든 서식과 포함된 리소스 이미지가 +들어있을 수 있습니다. 제공자는 긴 콘텐츠를 자르거나 생략할 수 있지만, 가능하면 태그를 손상시키는 것은 피하려 듭니다.
        {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP}
        - 스트림 항목이 삽입되거나 업데이트된 시간이 들어있는 텍스트 문자열로, 형식은 -epoch 이후 밀리초 형태를 취합니다. 이 열을 관리할 책임은 -스트림 항목을 삽입 또는 업데이트하는 애플리케이션에 있으며, 이것은 연락처 제공자가 자동으로 + 스트림 항목이 삽입되거나 업데이트된 시간이 들어있는 텍스트 문자열로, 형식은 +epoch 이후 밀리초 형태를 취합니다. 이 열을 관리할 책임은 +스트림 항목을 삽입 또는 업데이트하는 애플리케이션에 있으며, 이것은 연락처 제공자가 자동으로 유지 관리하지 않습니다.
        @@ -1911,18 +1911,18 @@ epoch 이후 밀리초 형태를 취합니다. 이 열을 관리할 책 리소스를 연결하십시오.

        - {@code android.provider.ContactsContract.StreamItems} 테이블에도 + {@code android.provider.ContactsContract.StreamItems} 테이블에도 동기화 어댑터가 독점적으로 사용하는 {@code android.provider.ContactsContract.StreamItemsColumns#SYNC1}에서 -{@code android.provider.ContactsContract.StreamItemsColumns#SYNC4}까지의 열이 +{@code android.provider.ContactsContract.StreamItemsColumns#SYNC4}까지의 열이 들어있습니다.

        소셜 스트림 사진

        - {@code android.provider.ContactsContract.StreamItemPhotos} 테이블은 스트림 항목과 연관된 -사진을 저장합니다. 테이블의 + {@code android.provider.ContactsContract.StreamItemPhotos} 테이블은 스트림 항목과 연관된 +사진을 저장합니다. 테이블의 {@code android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID} 열은 -{@code android.provider.ContactsContract.StreamItems} 테이블의 {@code android.provider.BaseColumns#_ID} 열에 있는 값과 -연결됩니다. 사진 참조는 +{@code android.provider.ContactsContract.StreamItems} 테이블의 {@code android.provider.BaseColumns#_ID} 열에 있는 값과 +연결됩니다. 사진 참조는 다음 열의 테이블에 저장됩니다.

        @@ -1931,21 +1931,21 @@ epoch 이후 밀리초 형태를 취합니다. 이 열을 관리할 책
        사진의 바이너리 표현으로, 제공자가 저장하고 표시하기 위해 크기를 조정한 것입니다. - 이 열은 사진을 저장하는 데 사용한 연락처 제공자의 이전 버전과 -호환됩니다. 그러나 현재 버전에서는 -이 열을 사진 저장에 사용하면 안 됩니다. 대신, -{@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} 또는 + 이 열은 사진을 저장하는 데 사용한 연락처 제공자의 이전 버전과 +호환됩니다. 그러나 현재 버전에서는 +이 열을 사진 저장에 사용하면 안 됩니다. 대신, +{@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} 또는 {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI}( -다음 항목에서 두 가지 모두 설명)를 사용하여 사진을 파일로 저장합니다. 지금 이 열에는 +다음 항목에서 두 가지 모두 설명)를 사용하여 사진을 파일로 저장합니다. 지금 이 열에는 사진의 미리 보기가 들어있어 읽기 작업에 사용할 수 있습니다.
        {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID}
        - 원시 연락처에 대한 사진의 숫자 식별자입니다. 이 값을 -상수 {@link android.provider.ContactsContract.DisplayPhoto#CONTENT_URI DisplayPhoto.CONTENT_URI}에 추가하여 -하나의 사진 파일을 가리키는 콘텐츠 URI를 가져온 다음, + 원시 연락처에 대한 사진의 숫자 식별자입니다. 이 값을 +상수 {@link android.provider.ContactsContract.DisplayPhoto#CONTENT_URI DisplayPhoto.CONTENT_URI}에 추가하여 +하나의 사진 파일을 가리키는 콘텐츠 URI를 가져온 다음, {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) openAssetFileDescriptor()}를 호출하여 사진 파일에 대한 핸들을 가져옵니다.
        @@ -1965,91 +1965,91 @@ openAssetFileDescriptor()}를 호출하면 사진 파일에 대한 핸들을 가
        • 이 테이블에는 추가 액세스 권한이 필요합니다. 여기서 읽기 작업을 수행하려면 애플리케이션에 -{@code android.Manifest.permission#READ_SOCIAL_STREAM} 권한이 있어야 합니다. 여기서 수정 작업을 수행하려면 +{@code android.Manifest.permission#READ_SOCIAL_STREAM} 권한이 있어야 합니다. 여기서 수정 작업을 수행하려면 애플리케이션에 {@code android.Manifest.permission#WRITE_SOCIAL_STREAM} 권한이 있어야 합니다.
        • - {@code android.provider.ContactsContract.StreamItems} 테이블의 경우, 각 원시 연락처에 저장되는 -행 개수가 제한되어 있습니다. 이 한계에 도달하면, + {@code android.provider.ContactsContract.StreamItems} 테이블의 경우, 각 원시 연락처에 저장되는 +행 개수가 제한되어 있습니다. 이 한계에 도달하면, 연락처 제공자가 새 스트림 항목 열에 필요한 공간을 만들어야 합니다. -이때 가장 오래된 {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP}가 -있는 행부터 자동으로 삭제하는 방법을 씁니다. 이 한계를 -가져오려면, 콘텐츠 URI -{@code android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI}에 쿼리를 발행합니다. 콘텐츠 -URI를 뺀 나머지 모든 인수는 null로 설정한 채 두면 됩니다. 이 쿼리는 -행이 하나 들어 있는 커서를 반환하며, +이때 가장 오래된 {@code android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP}가 +있는 행부터 자동으로 삭제하는 방법을 씁니다. 이 한계를 +가져오려면, 콘텐츠 URI +{@code android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI}에 쿼리를 발행합니다. 콘텐츠 +URI를 뺀 나머지 모든 인수는 null로 설정한 채 두면 됩니다. 이 쿼리는 +행이 하나 들어 있는 커서를 반환하며, {@code android.provider.ContactsContract.StreamItems#MAX_ITEMS} 열 하나가 수반됩니다.

        - {@code android.provider.ContactsContract.StreamItems.StreamItemPhotos} 클래스는 -스트림 항목 하나의 사진 행을 포함하는 {@code android.provider.ContactsContract.StreamItemPhotos}의 + {@code android.provider.ContactsContract.StreamItems.StreamItemPhotos} 클래스는 +스트림 항목 하나의 사진 행을 포함하는 {@code android.provider.ContactsContract.StreamItemPhotos}의 하위 테이블을 정의합니다.

        소셜 스트림 상호 작용

        - 연락처 제공자가 기기 연락처 애플리케이션과 함께 관리하는 소셜 스트림 데이터는 -소셜 네트워킹 시스템과 + 연락처 제공자가 기기 연락처 애플리케이션과 함께 관리하는 소셜 스트림 데이터는 +소셜 네트워킹 시스템과 기존 연락처를 연결하는 강력한 방법을 제공합니다. 사용할 수 있는 기능은 다음과 같습니다.

        • - 소셜 네트워킹 서비스를 동기화 어댑터로 연락처 제공자에 동기화함으로써, -사용자 연락처의 최근 활동을 검색하고 이를 -{@code android.provider.ContactsContract.StreamItems} 및 + 소셜 네트워킹 서비스를 동기화 어댑터로 연락처 제공자에 동기화함으로써, +사용자 연락처의 최근 활동을 검색하고 이를 +{@code android.provider.ContactsContract.StreamItems} 및 {@code android.provider.ContactsContract.StreamItemPhotos} 테이블에 저장해 두어 나중에 사용할 수 있습니다.
        • - 정기 동기화 외에도 사용자가 볼 연락처를 선택하면 동기화 어댑터를 트리거하여 -추가 데이터를 검색하게 할 수 있습니다. 이렇게 하면 동기화 어댑터가 + 정기 동기화 외에도 사용자가 볼 연락처를 선택하면 동기화 어댑터를 트리거하여 +추가 데이터를 검색하게 할 수 있습니다. 이렇게 하면 동기화 어댑터가 해당 연락처의 고해상도 사진과 가장 최근 스트림 항목을 검색할 수 있습니다.
        • - 기기 연락처 애플리케이션과 연락처 제공자에 알림을 등록하면, -연락처가 열람될 때 인텐트를 수신하고, -그 시점에 개발자의 서비스로부터 연락처의 상태를 업데이트할 수 있습니다. 이 방법을 사용하면 동기화 어댑터로 + 기기 연락처 애플리케이션과 연락처 제공자에 알림을 등록하면, +연락처가 열람될 때 인텐트를 수신하고, +그 시점에 개발자의 서비스로부터 연락처의 상태를 업데이트할 수 있습니다. 이 방법을 사용하면 동기화 어댑터로 완전 동기화를 수행하는 것보다 빠르고 대역폭도 적게 사용합니다.
        • - 사용자는 기기의 연락처 애플리케이션을 보면서 여러분의 소셜 네트워킹 서비스에 -연락처를 추가할 수 있습니다. 이는 "연락처 초대" 기능으로 사용할 수 있습니다. -연락처 초대 기능은 기존 연락처를 네트워크에 추가하는 액티비티와 -기기의 연락처 애플리케이션을 제공하는 XML 파일, + 사용자는 기기의 연락처 애플리케이션을 보면서 여러분의 소셜 네트워킹 서비스에 +연락처를 추가할 수 있습니다. 이는 "연락처 초대" 기능으로 사용할 수 있습니다. +연락처 초대 기능은 기존 연락처를 네트워크에 추가하는 액티비티와 +기기의 연락처 애플리케이션을 제공하는 XML 파일, 애플리케이션의 세부 정보가 포함된 연락처 제공자를 조합하여 활성화합니다.

        - 연락처 제공자로 스트림 항목을 정기 동기화하는 방법은 -다른 동기화와 같습니다. 동기화에 관한 자세한 내용은 -연락처 제공자 동기화 어댑터 섹션을 참조하십시오. 알림을 등록하고 연락처를 초대하는 방법은 + 연락처 제공자로 스트림 항목을 정기 동기화하는 방법은 +다른 동기화와 같습니다. 동기화에 관한 자세한 내용은 +연락처 제공자 동기화 어댑터 섹션을 참조하십시오. 알림을 등록하고 연락처를 초대하는 방법은 다음 두 섹션에서 다룰 것입니다.

        소셜 네트워킹 보기를 처리하기 위한 등록

        - 동기화 어댑터를 등록하여 사용자가 동기화 어댑터에서 관리하는 연락처를 볼 때 알림을 + 동기화 어댑터를 등록하여 사용자가 동기화 어댑터에서 관리하는 연락처를 볼 때 알림을 수신하는 방법:

        1. - 프로젝트의 res/xml/ 디렉터리에 contacts.xml 파일을 + 프로젝트의 res/xml/ 디렉터리에 contacts.xml 파일을 만듭니다. 이미 이 파일이 있다면 이 절차를 건너뛰어도 됩니다.
        2. - 이 파일에서, + 이 파일에서, <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"> 요소를 추가합니다. 이 요소가 이미 존재한다면 이 절차를 건너뛰어도 됩니다.
        3. - 사용자가 기기의 연락처 애플리케이션에서 + 사용자가 기기의 연락처 애플리케이션에서 연락처 세부 정보 페이지를 열면 알림을 보내는 서비스를 등록하려면, -viewContactNotifyService="serviceclass" 속성을 요소에 추가합니다. -이 요소에서 serviceclass는 기기의 연락처 애플리케이션에서 인텐트를 수신하는 서비스의 -완전히 정규화된 클래스 이름입니다. 알림 서비스의 경우, -{@link android.app.IntentService}를 확장하는 클래스를 사용하여 서비스가 인텐트를 수신하도록 -허용합니다. 수신되는 인텐트의 데이터에는 -사용자가 클릭한 원시 연락처의 콘텐츠 URI가 들어있습니다. 알림 서비스에서 동기화 어댑터에 바인딩한 다음 동기화 어댑터를 호출하여 +viewContactNotifyService="serviceclass" 속성을 요소에 추가합니다. +이 요소에서 serviceclass는 기기의 연락처 애플리케이션에서 인텐트를 수신하는 서비스의 +완전히 정규화된 클래스 이름입니다. 알림 서비스의 경우, +{@link android.app.IntentService}를 확장하는 클래스를 사용하여 서비스가 인텐트를 수신하도록 +허용합니다. 수신되는 인텐트의 데이터에는 +사용자가 클릭한 원시 연락처의 콘텐츠 URI가 들어있습니다. 알림 서비스에서 동기화 어댑터에 바인딩한 다음 동기화 어댑터를 호출하여 원시 연락처의 데이터를 업데이트할 수 있습니다.
        @@ -2058,31 +2058,31 @@ URI를 뺀 나머지 모든 인수는 null로 설정한 채 두면

        1. - 프로젝트의 res/xml/ 디렉터리에 contacts.xml 파일을 + 프로젝트의 res/xml/ 디렉터리에 contacts.xml 파일을 만듭니다. 이미 이 파일이 있다면 이 절차를 건너뛰어도 됩니다.
        2. - 이 파일에서, + 이 파일에서, <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"> 요소를 추가합니다. 이 요소가 이미 존재한다면 이 절차를 건너뛰어도 됩니다.
        3. - 사용자가 기기의 연락처 애플리케이션에서 스트림 항목을 클릭했을 때 -처리할 액티비티를 등록하려면, -viewStreamItemActivity="activityclass" 속성을 요소에 추가합니다. -이 요소에서 activityclass는 기기의 연락처 애플리케이션에서 인텐트를 수신하는 액티비티의 + 사용자가 기기의 연락처 애플리케이션에서 스트림 항목을 클릭했을 때 +처리할 액티비티를 등록하려면, +viewStreamItemActivity="activityclass" 속성을 요소에 추가합니다. +이 요소에서 activityclass는 기기의 연락처 애플리케이션에서 인텐트를 수신하는 액티비티의 완전히 정규화된 클래스 이름입니다.
        4. - 사용자가 기기의 연락처 애플리케이션에서 스트림 사진을 클릭했을 때 + 사용자가 기기의 연락처 애플리케이션에서 스트림 사진을 클릭했을 때 처리할 액티비티를 등록하려면, viewStreamItemPhotoActivity="activityclass" 속성을 요소에 추가합니다. -이 요소에서 activityclass는 기기의 연락처 애플리케이션에서 인텐트를 수신하는 액티비티의 +이 요소에서 activityclass는 기기의 연락처 애플리케이션에서 인텐트를 수신하는 액티비티의 완전히 정규화된 클래스 이름입니다.

        - <ContactsAccountType> 요소는 + <ContactsAccountType> 요소는 <ContactsAccountType> 요소 섹션에 자세히 설명되어 있습니다.

        @@ -2091,17 +2091,17 @@ URI를 뺀 나머지 모든 인수는 null로 설정한 채 두면

        소셜 네트워킹 서비스로 상호 작용

        - 사용자는 소셜 네트워킹 사이트에 연락처를 초대할 때 -기기의 연락처 애플리케이션을 떠나지 않아도 됩니다. 대신, 개발자가 기기의 연락처 앱에 액티비티 중 하나로 연락처를 초대하는 인텐트를 + 사용자는 소셜 네트워킹 사이트에 연락처를 초대할 때 +기기의 연락처 애플리케이션을 떠나지 않아도 됩니다. 대신, 개발자가 기기의 연락처 앱에 액티비티 중 하나로 연락처를 초대하는 인텐트를 보내게 할 수 있습니다. 이렇게 설정하는 방법은 다음과 같습니다.

        1. - 프로젝트의 res/xml/ 디렉터리에 contacts.xml 파일을 + 프로젝트의 res/xml/ 디렉터리에 contacts.xml 파일을 만듭니다. 이미 이 파일이 있다면 이 절차를 건너뛰어도 됩니다.
        2. - 이 파일에서, + 이 파일에서, <ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android"> 요소를 추가합니다. 이 요소가 이미 존재한다면 이 절차를 건너뛰어도 됩니다.
        3. @@ -2113,25 +2113,25 @@ URI를 뺀 나머지 모든 인수는 null로 설정한 채 두면 inviteContactActionLabel="@string/invite_action_label"
      - activityclass 값은 인텐트를 수신해야 하는 액티비티의 + activityclass 값은 인텐트를 수신해야 하는 액티비티의 완전히 정규화된 클래스 이름입니다. invite_action_label -값은 기기의 연락처 애플리케이션에 있는 연결 추가 메뉴에 +값은 기기의 연락처 애플리케이션에 있는 연결 추가 메뉴에 표시되는 텍스트 문자열입니다.

      - 참고: ContactsSource는 + 참고: ContactsSourceContactsAccountType에 대하여 이제 사용하지 않는 태그 이름입니다.

      contacts.xml 참조

      - contacts.xml 파일에는 XML 요소가 들어있어 개발자의 동기화 어댑터와 -애플리케이션, 연락처 애플리케이션과 연락처 제공자 사이의 상호 작용을 제어합니다. 이런 + contacts.xml 파일에는 XML 요소가 들어있어 개발자의 동기화 어댑터와 +애플리케이션, 연락처 애플리케이션과 연락처 제공자 사이의 상호 작용을 제어합니다. 이런 요소는 다음 섹션에 설명되어 있습니다.

      <ContactsAccountType> 요소

      - <ContactsAccountType>요 요소는 개발자의 애플리케이션과 + <ContactsAccountType>요 요소는 개발자의 애플리케이션과 연락처 애플리케이션 사이의 상호 작용을 제어합니다. 이 요소에는 다음 구문이 있습니다.

      @@ -2161,12 +2161,12 @@ URI를 뺀 나머지 모든 인수는 null로 설정한 채 두면
           설명:
       

      - 사용자가 연락처 중 하나를 소셜 네트워크에 초대하고, -소셜 네트워킹 스트림이 업데이트되면 사용자에게 알리는 등의 작업을 허용하는 + 사용자가 연락처 중 하나를 소셜 네트워크에 초대하고, +소셜 네트워킹 스트림이 업데이트되면 사용자에게 알리는 등의 작업을 허용하는 Android 구성 요소와 UI 레이블을 선언합니다.

      - 속성 접두사 android:는 + 속성 접두사 android:<ContactsAccountType>의 속성에는 필요하지 않다는 점을 눈여겨보십시오.

      @@ -2175,48 +2175,48 @@ Android 구성 요소와 UI 레이블을 선언합니다.

      {@code inviteContactActivity}
      - 사용자가 기기의 연락처 애플리케이션에서 -연결 추가를 선택했을 때 활성화하고자 하는 + 사용자가 기기의 연락처 애플리케이션에서 +연결 추가를 선택했을 때 활성화하고자 하는 애플리케이션 액티비티의 완전히 정규화된 클래스 이름입니다.
      {@code inviteContactActionLabel}
      - 연결 추가 메뉴의 + 연결 추가 메뉴의 {@code inviteContactActivity}에서 지정된 액티비티에 대해 표시되는 텍스트 문자열입니다. - 예를 들어, 문자열 "제 네트워크를 팔로우하세요"를 사용할 수 있습니다. 이 레이블에 대한 문자열 리소스 + 예를 들어, 문자열 "제 네트워크를 팔로우하세요"를 사용할 수 있습니다. 이 레이블에 대한 문자열 리소스 식별자를 사용할 수 있습니다.
      {@code viewContactNotifyService}
      - 사용자가 연락처를 볼 때 알림을 수신해야 하는 -애플리케이션 서비스의 완전히 정규화된 클래스 이름입니다. 이 알림은 -기기의 연락처 애플리케이션이 전송합니다. 이것을 사용하면 개발자의 애플리케이션이 데이터 집약적인 작업을 필요할 때까지 -연기할 수 있습니다. 예를 들어, 개발자의 애플리케이션은 -연락처의 고해상도 사진과 가장 최근 소셜 스트림 항목을 읽어서 표시함으로써 -이 알림에 응답할 수 있습니다. 이 기능은 -소셜 스트림 상호 작용에 상세히 설명되어 있습니다. 알림 서비스의 예시를 + 사용자가 연락처를 볼 때 알림을 수신해야 하는 +애플리케이션 서비스의 완전히 정규화된 클래스 이름입니다. 이 알림은 +기기의 연락처 애플리케이션이 전송합니다. 이것을 사용하면 개발자의 애플리케이션이 데이터 집약적인 작업을 필요할 때까지 +연기할 수 있습니다. 예를 들어, 개발자의 애플리케이션은 +연락처의 고해상도 사진과 가장 최근 소셜 스트림 항목을 읽어서 표시함으로써 +이 알림에 응답할 수 있습니다. 이 기능은 +소셜 스트림 상호 작용에 상세히 설명되어 있습니다. 알림 서비스의 예시를 보려면 SampleSyncAdapter - 샘플 앱에 있는 NotifierService.java 파일을 + 샘플 앱에 있는 NotifierService.java 파일을 확인합니다.
      {@code viewGroupActivity}
      - 그룹 정보를 표시할 수 있는 애플리케이션 액티비티의 -완전히 정규화된 클래스 이름입니다. 사용자가 기기의 연락처 애플리케이션에서 그룹 레이블을 클릭하면, + 그룹 정보를 표시할 수 있는 애플리케이션 액티비티의 +완전히 정규화된 클래스 이름입니다. 사용자가 기기의 연락처 애플리케이션에서 그룹 레이블을 클릭하면, 이 액티비티의 UI가 표시됩니다.
      {@code viewGroupActionLabel}
      - 사용자가 개발자의 애플리케이션에서 그룹을 살펴볼 수 있도록 해주는 UI 제어에 대해 + 사용자가 개발자의 애플리케이션에서 그룹을 살펴볼 수 있도록 해주는 UI 제어에 대해 연락처 애플리케이션이 표시하는 레이블입니다.

      - 예를 들어, 기기에 Google+ 애플리케이션을 설치하고 -Google+를 연락처 애플리케이션과 동기화하면, Google+ 서클이 -연락처 애플리케이션의 그룹 탭에 표시되는 것을 볼 수 있습니다. Google+ 서클을 -클릭하면 해당 서클에서 "그룹"으로 표시된 사람들을 볼 수 있습니다. 이 표시의 맨 위에 -Google+ 아이콘이 표시되며, 이것을 클릭하면 제어가 -Google+ 앱으로 전환됩니다. 연락처 애플리케이션은 이 작업을 -{@code viewGroupActivity}로 수행하며, Google+ 아이콘을 + 예를 들어, 기기에 Google+ 애플리케이션을 설치하고 +Google+를 연락처 애플리케이션과 동기화하면, Google+ 서클이 +연락처 애플리케이션의 그룹 탭에 표시되는 것을 볼 수 있습니다. Google+ 서클을 +클릭하면 해당 서클에서 "그룹"으로 표시된 사람들을 볼 수 있습니다. 이 표시의 맨 위에 +Google+ 아이콘이 표시되며, 이것을 클릭하면 제어가 +Google+ 앱으로 전환됩니다. 연락처 애플리케이션은 이 작업을 +{@code viewGroupActivity}로 수행하며, Google+ 아이콘을 {@code viewGroupActionLabel}의 값으로 사용합니다.

      @@ -2225,19 +2225,19 @@ Google+ 앱으로 전환됩니다. 연락처 애플리케이션은 이 작업을

      {@code viewStreamItemActivity}
      - 사용자가 원시 연락처의 스트림 항목을 클릭할 때 기기의 연락처 애플리케이션이 시작하는 + 사용자가 원시 연락처의 스트림 항목을 클릭할 때 기기의 연락처 애플리케이션이 시작하는 애플리케이션 액티비티의 완전히 정규화된 클래스 이름입니다.
      {@code viewStreamItemPhotoActivity}
      - 사용자가 원시 연락처 스트림 항목의 사진을 클릭할 때 -기기의 연락처 애플리케이션이 시작하는 애플리케이션 액티비티의 + 사용자가 원시 연락처 스트림 항목의 사진을 클릭할 때 +기기의 연락처 애플리케이션이 시작하는 애플리케이션 액티비티의 완전히 정규화된 클래스 이름입니다.

      <ContactsDataKind> 요소

      - <ContactsDataKind> 요소는 연락처 애플리케이션 UI에서 애플리케이션의 사용자 지정 데이터 행 표시를 + <ContactsDataKind> 요소는 연락처 애플리케이션 UI에서 애플리케이션의 사용자 지정 데이터 행 표시를 제어합니다. 이 요소에는 다음 구문이 있습니다.

      @@ -2255,11 +2255,11 @@ Google+ 앱으로 전환됩니다. 연락처 애플리케이션은 이 작업을
           설명:
       

      - 이 요소를 사용하여 연락처 애플리케이션이 사용자 지정 데이터 행의 콘텐츠를 -원시 연락처 세부 정보의 일부로 표시하게 합니다. <ContactsAccountType>의 각 <ContactsDataKind> 하위 요소는 -동기화 어댑터가 {@link android.provider.ContactsContract.Data}에 추가하는 -사용자 지정 데이터 행의 유형을 나타냅니다. 개발자가 사용하는 사용자 지정 MIME 유형 하나마다 -<ContactsDataKind> 요소를 하나씩 추가합니다. 데이터를 + 이 요소를 사용하여 연락처 애플리케이션이 사용자 지정 데이터 행의 콘텐츠를 +원시 연락처 세부 정보의 일부로 표시하게 합니다. <ContactsAccountType>의 각 <ContactsDataKind> 하위 요소는 +동기화 어댑터가 {@link android.provider.ContactsContract.Data}에 추가하는 +사용자 지정 데이터 행의 유형을 나타냅니다. 개발자가 사용하는 사용자 지정 MIME 유형 하나마다 +<ContactsDataKind> 요소를 하나씩 추가합니다. 데이터를 표시하는 것을 원치 않는 사용자 지정 데이터 행이 있으면, 이 요소를 추가하지 않아도 됩니다.

      @@ -2268,35 +2268,35 @@ Google+ 앱으로 전환됩니다. 연락처 애플리케이션은 이 작업을

      {@code android:mimeType}
      - {@link android.provider.ContactsContract.Data} 테이블에서 -사용자 지정 데이터 행 유형 중 하나로 지정한 사용자 지정 MIME 유형입니다. 예를 들어, -vnd.android.cursor.item/vnd.example.locationstatus 값은 연락처의 마지막으로 알려진 위치를 기록하는 + {@link android.provider.ContactsContract.Data} 테이블에서 +사용자 지정 데이터 행 유형 중 하나로 지정한 사용자 지정 MIME 유형입니다. 예를 들어, +vnd.android.cursor.item/vnd.example.locationstatus 값은 연락처의 마지막으로 알려진 위치를 기록하는 데이터 행에 대한 사용자 지정 MIME 유형이 될 수 있습니다.
      {@code android:icon}
      - 연락처 애플리케이션이 개발자의 데이터 옆에 표시하는 + 연락처 애플리케이션이 개발자의 데이터 옆에 표시하는 Android 드로어블 리소스 -입니다. 이 리소스를 사용하여 사용자에게 +입니다. 이 리소스를 사용하여 사용자에게 데이터 출처가 개발자의 서비스임을 나타내는 것입니다.
      {@code android:summaryColumn}
      - 데이터 행에서 검색한 두 개 값 중에서 첫 번째 값에 대한 열 이름입니다. 이 값은 -이 데이터 행에 대한 항목의 첫 번째 줄로 표시됩니다. 첫 번째 줄은 -데이터 요약으로 사용되는 것이 본 목적이지만, 이것은 선택 사항입니다. + 데이터 행에서 검색한 두 개 값 중에서 첫 번째 값에 대한 열 이름입니다. 이 값은 +이 데이터 행에 대한 항목의 첫 번째 줄로 표시됩니다. 첫 번째 줄은 +데이터 요약으로 사용되는 것이 본 목적이지만, 이것은 선택 사항입니다. android:detailColumn도 참조하십시오.
      {@code android:detailColumn}
      데이터 행에서 검색한 두 개 값 중에서 두 번째 값에 대한 열 이름입니다. 이 값은 -이 데이터 행에 대한 항목의 두 번째 줄로 표시됩니다. +이 데이터 행에 대한 항목의 두 번째 줄로 표시됩니다. {@code android:summaryColumn}도 참조하십시오.

      추가 연락처 제공자 기능

      - 이전 섹션에서 설명한 주요 기능 외에도 연락처 제공자는 연락처 데이터를 다루는 데 + 이전 섹션에서 설명한 주요 기능 외에도 연락처 제공자는 연락처 데이터를 다루는 데 유용한 기능을 많이 제공합니다. 예를 들면 다음과 같습니다.

        @@ -2305,52 +2305,52 @@ Android 드로

      연락처 그룹

      - 연락처 제공자는 관련된 연락처 컬렉션에 -그룹 데이터로 레이블을 붙이기로 선택할 수 있습니다. 사용자 계정과 연관된 서버에서 -그룹을 관리하고자 하는 경우, 계정의 계정 유형에 대한 동기화 어댑터가 -연락처 제공자와 서버 사이에서 그룹 데이터를 전송해야 합니다. 사용자가 해당 서버에 새 연락처를 추가하고 + 연락처 제공자는 관련된 연락처 컬렉션에 +그룹 데이터로 레이블을 붙이기로 선택할 수 있습니다. 사용자 계정과 연관된 서버에서 +그룹을 관리하고자 하는 경우, 계정의 계정 유형에 대한 동기화 어댑터가 +연락처 제공자와 서버 사이에서 그룹 데이터를 전송해야 합니다. 사용자가 해당 서버에 새 연락처를 추가하고 이 연락처를 새 그룹에 넣으면, 동기화 어댑터가 해당 새 그룹을 -{@link android.provider.ContactsContract.Groups} 테이블에 추가해야 합니다. 원시 연락처가 속한 그룹(또는 여러 그룹)은 -{@link android.provider.ContactsContract.Data} 테이블에 저장되며, 이때 +{@link android.provider.ContactsContract.Groups} 테이블에 추가해야 합니다. 원시 연락처가 속한 그룹(또는 여러 그룹)은 +{@link android.provider.ContactsContract.Data} 테이블에 저장되며, 이때 {@link android.provider.ContactsContract.CommonDataKinds.GroupMembership} MIME 유형을 사용합니다.

      - 개발자가 서버에서 가져온 원시 연락처 데이터를 연락처 제공자에 추가할 -동기화 어댑터를 디자인하는 중이고 그룹은 사용하지 않는다면, -제공자 쪽에 데이터를 표시하라고 지시해야 합니다. 사용자가 기기에 계정을 추가했을 때 실행되는 코드에서 -연락처 제공자가 계정에 추가하는{@link android.provider.ContactsContract.Settings} 행을 -업데이트하십시오. 이 행에서 + 개발자가 서버에서 가져온 원시 연락처 데이터를 연락처 제공자에 추가할 +동기화 어댑터를 디자인하는 중이고 그룹은 사용하지 않는다면, +제공자 쪽에 데이터를 표시하라고 지시해야 합니다. 사용자가 기기에 계정을 추가했을 때 실행되는 코드에서 +연락처 제공자가 계정에 추가하는{@link android.provider.ContactsContract.Settings} 행을 +업데이트하십시오. 이 행에서 {@link android.provider.ContactsContract.SettingsColumns#UNGROUPED_VISIBLE -Settings.UNGROUPED_VISIBLE} 열의 값을 1로 설정합니다. 이렇게 하면 연락처 제공자가 +Settings.UNGROUPED_VISIBLE} 열의 값을 1로 설정합니다. 이렇게 하면 연락처 제공자가 개발자의 연락처 데이터를 항상 표시하게 되고, 이는 그룹을 사용하지 않더라도 관계 없습니다.

      연락처 사진

      {@link android.provider.ContactsContract.Data} 테이블은 {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE -Photo.CONTENT_ITEM_TYPE} MIME 유형으로 사진을 행에 저장합니다. 이 행의 -{@link android.provider.ContactsContract.RawContactsColumns#CONTACT_ID} 열은 +Photo.CONTENT_ITEM_TYPE} MIME 유형으로 사진을 행에 저장합니다. 이 행의 +{@link android.provider.ContactsContract.RawContactsColumns#CONTACT_ID} 열은 행이 속한 원시 연락처의 {@code android.provider.BaseColumns#_ID} 열과 연결됩니다. - 클래스 {@link android.provider.ContactsContract.Contacts.Photo}는 -연락처 기본 사진의 사진 정보가 들어있는 {@link android.provider.ContactsContract.Contacts} 하위 테이블을 정의합니다. -연락처의 기본 사진은 연락처 기본 원시 연락처의 기본 사진입니다. 마찬가지로, + 클래스 {@link android.provider.ContactsContract.Contacts.Photo}는 +연락처 기본 사진의 사진 정보가 들어있는 {@link android.provider.ContactsContract.Contacts} 하위 테이블을 정의합니다. +연락처의 기본 사진은 연락처 기본 원시 연락처의 기본 사진입니다. 마찬가지로, {@link android.provider.ContactsContract.RawContacts.DisplayPhoto} 클래스는 원시 연락처의 기본 사진의 사진 정보가 들어있는 {@link android.provider.ContactsContract.RawContacts} 하위 테이블을 정의합니다.

      - {@link android.provider.ContactsContract.Contacts.Photo} 및 -{@link android.provider.ContactsContract.RawContacts.DisplayPhoto}에 대한 참조 문서에 -사진 정보를 검색하는 예시가 들어있습니다. 원시 연락처에 대한 기본 미리 보기를 검색하는 데 쓰이는 -편의 클래스는 없습니다. 하지만 -{@link android.provider.ContactsContract.Data} 테이블에 쿼리를 보내 원시 연락처의 -{@code android.provider.BaseColumns#_ID}, + {@link android.provider.ContactsContract.Contacts.Photo} 및 +{@link android.provider.ContactsContract.RawContacts.DisplayPhoto}에 대한 참조 문서에 +사진 정보를 검색하는 예시가 들어있습니다. 원시 연락처에 대한 기본 미리 보기를 검색하는 데 쓰이는 +편의 클래스는 없습니다. 하지만 +{@link android.provider.ContactsContract.Data} 테이블에 쿼리를 보내 원시 연락처의 +{@code android.provider.BaseColumns#_ID}, {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE Photo.CONTENT_ITEM_TYPE}, 및 {@link android.provider.ContactsContract.Data#IS_PRIMARY} 열을 선택하면 해당 원시 연락처의 기본 사진 행을 찾을 수 있습니다.

      - 한 사람의 소셜 스트림 데이터에도 사진이 포함되어 있을 수 있습니다. 이런 사진은 -{@code android.provider.ContactsContract.StreamItemPhotos} 테이블에 저장되며, 이 내용은 + 한 사람의 소셜 스트림 데이터에도 사진이 포함되어 있을 수 있습니다. 이런 사진은 +{@code android.provider.ContactsContract.StreamItemPhotos} 테이블에 저장되며, 이 내용은 소셜 스트림 사진에 더 자세하게 설명되어 있습니다.

      diff --git a/docs/html-intl/intl/ko/guide/topics/providers/content-provider-basics.jd b/docs/html-intl/intl/ko/guide/topics/providers/content-provider-basics.jd index 953f92ab3026c90aae71207b530e6062ae9804e0..0f58b792a24f6467bd91523867bfb077ffa52104 100644 --- a/docs/html-intl/intl/ko/guide/topics/providers/content-provider-basics.jd +++ b/docs/html-intl/intl/ko/guide/topics/providers/content-provider-basics.jd @@ -119,11 +119,11 @@ page.title=콘텐츠 제공자 기본 정보

      - 콘텐츠 제공자는 데이터의 중앙 리포지토리로의 액세스를 관리합니다. + 콘텐츠 제공자는 데이터의 중앙 리포지토리로의 액세스를 관리합니다. 제공자는 Android 애플리케이션의 일부이며, 이는 종종 나름의 UI를 제공하여 데이터에 작용하도록 합니다. - 그러나 콘텐츠 제공자는 기본적으로 다른 애플리케이션이 사용하도록 만들어진 것입니다. -이들은 제공자 클라이언트 개체를 사용하여 제공자에 액세스합니다. -제공자와 제공자 클라이언트가 결합되면 데이터에 하나의 일관적인 표준 인터페이스를 제공하여 + 그러나 콘텐츠 제공자는 기본적으로 다른 애플리케이션이 사용하도록 만들어진 것입니다. +이들은 제공자 클라이언트 개체를 사용하여 제공자에 액세스합니다. +제공자와 제공자 클라이언트가 결합되면 데이터에 하나의 일관적인 표준 인터페이스를 제공하여 이것이 프로세스간 통신과 보안 데이터 액세스도 처리합니다.

      @@ -139,14 +139,14 @@ page.title=콘텐츠 제공자 기본 정보

      개요

      - 콘텐츠 제공자는 외부 애플리케이션에 데이터를 표시하며, 이때 데이터는 -관계형 데이터베이스에서 찾을 수 있는 테이블과 유사한 하나 이상의 테이블로서 표시됩니다. -한 행은 제공자가 수집하는 어떤 유형의 데이터 인스턴스를 나타내며, + 콘텐츠 제공자는 외부 애플리케이션에 데이터를 표시하며, 이때 데이터는 +관계형 데이터베이스에서 찾을 수 있는 테이블과 유사한 하나 이상의 테이블로서 표시됩니다. +한 행은 제공자가 수집하는 어떤 유형의 데이터 인스턴스를 나타내며, 행 안의 각 열은 인스턴스에 대해 수집된 개별적인 데이터를 나타냅니다.

      - 예를 들어 Android 플랫폼 안에 내장된 여러 제공자 중에 사용자 사전이라는 것이 있습니다. -이것은 사용자가 보관하고 싶어하는 비표준 단어의 철자를 저장합니다. 표 1은 이 제공자의 테이블에서 + 예를 들어 Android 플랫폼 안에 내장된 여러 제공자 중에 사용자 사전이라는 것이 있습니다. +이것은 사용자가 보관하고 싶어하는 비표준 단어의 철자를 저장합니다. 표 1은 이 제공자의 테이블에서 데이터가 어떤 형태를 띨 수 있는지를 나타낸 것입니다.

      @@ -197,39 +197,39 @@ page.title=콘텐츠 제공자 기본 정보

      - 표 1에서, 각 행은 일반적인 사전에 나오지 않는 단어의 인스턴스를 -나타냅니다. 각 열은 해당 단어에 대한 일부 데이터를 나타냅니다. 예를 들어 + 표 1에서, 각 행은 일반적인 사전에 나오지 않는 단어의 인스턴스를 +나타냅니다. 각 열은 해당 단어에 대한 일부 데이터를 나타냅니다. 예를 들어 단어가 처음 나온 로케일 등을 들 수 있습니다. 열 헤더는 제공자에 저장된 -열 이름입니다. 행의 로케일을 참조하려면 그 행의 locale 열을 참조합니다. +열 이름입니다. 행의 로케일을 참조하려면 그 행의 locale 열을 참조합니다. 이 제공자의 경우, _ID 열은 제공자가 자동으로 유지하는 "기본 키" 열 역할을 합니다.

      - 참고: 제공자에 기본 키가 꼭 있어야 하는 것은 아니고, -기본 키가 있는 경우 _ID를 열 이름으로 사용하지 않아도 됩니다. 그러나 제공자의 데이터를 -{@link android.widget.ListView}에 바인딩하려면 + 참고: 제공자에 기본 키가 꼭 있어야 하는 것은 아니고, +기본 키가 있는 경우 _ID를 열 이름으로 사용하지 않아도 됩니다. 그러나 제공자의 데이터를 +{@link android.widget.ListView}에 바인딩하려면 열 이름 중 하나는_ID여야 합니다. 이 요구 사항은 쿼리 결과 표시 섹션에 자세히 설명되어 있습니다.

      제공자 액세스

      - 애플리케이션은 콘텐츠 제공자로부터의 데이터에 -{@link android.content.ContentResolver} 클라이언트 개체로 액세스합니다. -이 개체에는 제공자 개체 내의 같은 이름을 가진 메서드를 호출하는 메서드가 있습니다. -이는 {@link android.content.ContentProvider}의 구체적인 하위 클래스 중 하나의 인스턴스입니다. -{@link android.content.ContentResolver} 메서드는 + 애플리케이션은 콘텐츠 제공자로부터의 데이터에 +{@link android.content.ContentResolver} 클라이언트 개체로 액세스합니다. +이 개체에는 제공자 개체 내의 같은 이름을 가진 메서드를 호출하는 메서드가 있습니다. +이는 {@link android.content.ContentProvider}의 구체적인 하위 클래스 중 하나의 인스턴스입니다. +{@link android.content.ContentResolver} 메서드는 영구적 저장소의 기본적인 "CRUD"(생성, 검색, 업데이트 및 삭제) 기능을 제공합니다.

      클라이언트 애플리케이션의 프로세스 내에 있는 {@link android.content.ContentResolver} 개체와 - 제공자를 소유하는 애플리케이션 내의 {@link android.content.ContentProvider} 개체가 + 제공자를 소유하는 애플리케이션 내의 {@link android.content.ContentProvider} 개체가 자동으로 프로세스간 통신을 처리합니다. -{@link android.content.ContentProvider} 또한 +{@link android.content.ContentProvider} 또한 콘텐츠 제공자의 데이터 리포지토리와 외부에 테이블로 표시되는 데이터 모습 사이에서 추상화 계층 역할을 합니다.

      - 참고: 제공자에 액세스하려면 보통은 애플리케이션이 -제공자의 매니페스트 파일에 있는 특정 권한을 요청해야 합니다. 이것은 + 참고: 제공자에 액세스하려면 보통은 애플리케이션이 +제공자의 매니페스트 파일에 있는 특정 권한을 요청해야 합니다. 이것은 콘텐츠 제공자 권한 섹션에 더 자세히 설명되어 있습니다.

      @@ -237,7 +237,7 @@ page.title=콘텐츠 제공자 기본 정보 {@link android.content.ContentResolver#query ContentResolver.query()}를 호출하면 됩니다. {@link android.content.ContentResolver#query query()} 메서드는 사용자 사전 제공자가 정의한 {@link android.content.ContentProvider#query ContentProvider.query()} 메서드를 -호출합니다. 다음 몇 줄의 코드는 +호출합니다. 다음 몇 줄의 코드는 {@link android.content.ContentResolver#query ContentResolver.query()} 호출을 나타낸 것입니다.

      @@ -292,26 +292,26 @@ query(Uri,projection,selection,selectionArgs,sortOrder)}에 대한 인수가 SQL
               sortOrder
               ORDER BY col,col,...
               
      -            sortOrder는 반환된 
      +            sortOrder는 반환된
       {@link android.database.Cursor} 내에 행이 나타나는 순서를 지정합니다.
               
           
       
       

      콘텐츠 URI

      - 콘텐츠 URI는 제공자에서 데이터를 식별하는 URI입니다. + 콘텐츠 URI는 제공자에서 데이터를 식별하는 URI입니다. 콘텐츠 URI에는 전체 제공자의 상징적인 이름(제공자의 권한)과 -테이블을 가리키는 이름(경로)이 포함됩니다. +테이블을 가리키는 이름(경로)이 포함됩니다. 제공자 내의 테이블에 액세스하기 위해 클라이언트 메서드를 호출하는 경우, 그 테이블에 대한 콘텐츠 URI는 인수 중 하나입니다.

      앞선 몇 줄의 코드에서 상수 -{@link android.provider.UserDictionary.Words#CONTENT_URI}에 +{@link android.provider.UserDictionary.Words#CONTENT_URI}에 사용자 사전의 "단어" 테이블의 콘텐츠 URI가 들어있습니다. {@link android.content.ContentResolver} 개체가 이 URI의 권한을 구문 분석한 다음, 이를 이용해 제공자를 "확인"합니다. 즉 이 권한을 알려진 제공자로 이루어진 시스템 테이블과 비교하는 것입니다. - -그러면 {@link android.content.ContentResolver}가 쿼리 인수를 + +그러면 {@link android.content.ContentResolver}가 쿼리 인수를 올바른 제공자에게 발송할 수 있습니다.

      @@ -331,20 +331,20 @@ content://user_dictionary/words 이것을 콘텐츠 URI로 식별합니다.

      - 대다수의 제공자에서는 URI의 맨 끝에 ID 값을 추가하면 -테이블 내 하나의 행에 액세스할 수 있게 해줍니다. 예를 들어 _ID가 + 대다수의 제공자에서는 URI의 맨 끝에 ID 값을 추가하면 +테이블 내 하나의 행에 액세스할 수 있게 해줍니다. 예를 들어 _ID가 사용자 사전의 4인 행을 검색하려면, 이 콘텐츠 URI를 사용하면 됩니다.

       Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
       

      - 일련의 행을 검색한 다음 그 중 하나를 업데이트하거나 삭제하고자 하는 경우 종종 ID 값을 + 일련의 행을 검색한 다음 그 중 하나를 업데이트하거나 삭제하고자 하는 경우 종종 ID 값을 이용하곤 합니다.

      - 참고: {@link android.net.Uri}와 -{@link android.net.Uri.Builder} 클래스에는 문자열에서 잘 구성된(Well-Formed) URI 개체를 구성하기 위한 편의 메서드가 들어 있습니다. + 참고: {@link android.net.Uri}와 +{@link android.net.Uri.Builder} 클래스에는 문자열에서 잘 구성된(Well-Formed) URI 개체를 구성하기 위한 편의 메서드가 들어 있습니다. {@link android.content.ContentUris}에는 URI에 ID 값을 추가하기 위한 편의 메서드가 들어 있습니다. 이전 조각은 {@link android.content.ContentUris#withAppendedId withAppendedId()}를 사용하여 UserDictionary 콘텐츠 URI에 ID를 추가합니다. @@ -358,10 +358,10 @@ withAppendedId()}를 사용하여 UserDictionary 콘텐츠 URI에 ID를 추가 방법을 설명합니다.

      - 명확히 나타내기 위해 이 섹션의 코드 조각은 -{@link android.content.ContentResolver#query ContentResolver.query()}를 "UI 스레드"에서 호출합니다. + 명확히 나타내기 위해 이 섹션의 코드 조각은 +{@link android.content.ContentResolver#query ContentResolver.query()}를 "UI 스레드"에서 호출합니다. 그러나 실제 코드의 경우 쿼리는 별도의 스레드에서 비동기식으로 수행해야 합니다. 이를 위한 한 가지 방식으로 -{@link android.content.CursorLoader} +{@link android.content.CursorLoader} 클래스를 쓰는 것을 들 수 있습니다. 이 내용은 로더 가이드에 더 자세히 설명되어 있습니다. 또한, 이 코드 줄은 조각일 뿐이며 애플리케이션을 전체적으로 표시한 것이 아닙니다. @@ -380,32 +380,32 @@ withAppendedId()}를 사용하여 UserDictionary 콘텐츠 URI에 ID를 추가

      읽기 액세스 권한 요청

      제공자에서 데이터를 검색하려면 애플리케이션에 해당 제공자에 대한 "읽기 액세스 권한"이 필요합니다. - 런타임에는 이 권한을 요청할 수 없습니다. 대신 이 권한이 필요하다는 것을 매니페스트에 나타내야 합니다. 이때, + 런타임에는 이 권한을 요청할 수 없습니다. 대신 이 권한이 필요하다는 것을 매니페스트에 나타내야 합니다. 이때, <uses-permission> 요소와 제공자가 정의한 정확한 권한 이름을 사용하면 됩니다. - 매니페스트에서 이 요소를 지정하는 것은 사실상 애플리케이션을 위해 이 권한을 "요청"하는 것과 + 매니페스트에서 이 요소를 지정하는 것은 사실상 애플리케이션을 위해 이 권한을 "요청"하는 것과 같습니다. 사용자가 애플리케이션을 설치할 때면, 이 요청을 암시적으로 허용하게 됩니다.

      - 사용 중인 제공자에 대한 읽기 액세스 권한의 정확한 이름과 해당 제공자가 사용하는 + 사용 중인 제공자에 대한 읽기 액세스 권한의 정확한 이름과 해당 제공자가 사용하는 다른 액세스 권한의 이름을 찾아보려면 제공자의 문서를 살펴보십시오.

      - 제공자에 액세스하는 데 있어 권한이 어떤 역할을 하는지는 + 제공자에 액세스하는 데 있어 권한이 어떤 역할을 하는지는 콘텐츠 제공자 권한 섹션에 더 자세하게 설명되어 있습니다.

      - 사용자 사전 제공자는 -android.permission.READ_USER_DICTIONARY 권한을 자신의 매니페스트 파일에 정의합니다. 따라서 해당 제공자에서 + 사용자 사전 제공자는 +android.permission.READ_USER_DICTIONARY 권한을 자신의 매니페스트 파일에 정의합니다. 따라서 해당 제공자에서 읽기 작업을 하고자 하는 애플리케이션은 반드시 이 권한을 요청해야 합니다.

      쿼리 구성

      - 제공자에서 데이터를 검색할 때 다음 단계는 쿼리를 구성하는 것입니다. 다음의 첫 번째 조각은 + 제공자에서 데이터를 검색할 때 다음 단계는 쿼리를 구성하는 것입니다. 다음의 첫 번째 조각은 사용자 사전 제공자에 액세스하는 데 필요한 몇 가지 변수를 정의한 것입니다.

      @@ -426,9 +426,9 @@ String[] mSelectionArgs = {""};
       
       

      - 다음 조각은 사용자 사전 제공자를 예시로 사용하여 + 다음 조각은 사용자 사전 제공자를 예시로 사용하여 {@link android.content.ContentResolver#query ContentResolver.query()}를 - 사용하는 방법을 나타낸 것입니다. 제공자 클라이언트 쿼리는 SQL 쿼리와 비슷하며, + 사용하는 방법을 나타낸 것입니다. 제공자 클라이언트 쿼리는 SQL 쿼리와 비슷하며, 반환할 열 집합과 선택 기준 집합, 그리고 정렬 순서가 이 안에 들어 있습니다.

      @@ -438,13 +438,13 @@ String[] mSelectionArgs = {""};

      검색할 행을 나타내는 식은 선택 절과 선택 인수로 분할되어 있습니다. 선택 절은 논리와 부울 식, 열 이름과 값 -(변수 mSelectionClause)을 조합한 것입니다. -값 대신 대체 가능한 매개변수 ?를 지정하면, +(변수 mSelectionClause)을 조합한 것입니다. +값 대신 대체 가능한 매개변수 ?를 지정하면, 쿼리 메서드가 그 값을 선택 인수 배열에서 검색합니다(변수 mSelectionArgs).

      - 다음 조각의 경우, 사용자가 단어를 입력하지 않으면 선택 절이 -null로 설정되고, 쿼리는 제공자 안의 모든 단어를 반환합니다. + 다음 조각의 경우, 사용자가 단어를 입력하지 않으면 선택 절이 +null로 설정되고, 쿼리는 제공자 안의 모든 단어를 반환합니다. 사용자가 단어를 입력하면 선택 절은 UserDictionary.Words.WORD + " = ?"로 설정되며 선택 인수의 첫 번째 요소가 사용자가 입력한 단어로 설정됩니다.

      @@ -514,7 +514,7 @@ SELECT _ID, word, locale FROM words WHERE word = <userinput> ORDER BY word

      악의적인 입력에 대한 보호

      - 콘텐츠 제공자가 관리하는 데이터가 SQL 데이터베이스에 있는 경우, + 콘텐츠 제공자가 관리하는 데이터가 SQL 데이터베이스에 있는 경우, 원시 SQL 문에 외부의 신뢰할 수 없는 데이터를 포함시키면 SQL 삽입을 초래할 수 있습니다.

      @@ -526,17 +526,17 @@ String mSelectionClause = "var = " + mUserInput;

      이렇게 하면 사용자로 하여금 여러분의 SQL 문에 악의적인 SQL을 연결할 수 있도록 허용합니다. - 예를 들어 사용자가 mUserInput에 대해 "nothing; DROP TABLE *;"을 입력할 수 있습니다. -그러면 그 결과로 선택 절 var = nothing; DROP TABLE *;이 나옵니다. -선택 절이 일종의 SQL 문으로 취급되었기 때문에 제공자가 기본 SQLite 데이터베이스에서 테이블을 -모두 삭제하는 결과를 낳을 수도 있습니다(제공자가 SQL 삽입 + 예를 들어 사용자가 mUserInput에 대해 "nothing; DROP TABLE *;"을 입력할 수 있습니다. +그러면 그 결과로 선택 절 var = nothing; DROP TABLE *;이 나옵니다. +선택 절이 일종의 SQL 문으로 취급되었기 때문에 제공자가 기본 SQLite 데이터베이스에서 테이블을 +모두 삭제하는 결과를 낳을 수도 있습니다(제공자가 SQL 삽입 시도를 잡아내도록 설정된 경우는 예외입니다).

      - 이 문제를 피하려면 ?를 대체 가능한 매개변수로 사용하는 선택 절과, + 이 문제를 피하려면 ?를 대체 가능한 매개변수로 사용하는 선택 절과, 별도의 선택 인수 배열을 사용하면 됩니다. 이렇게 하면, 사용자 입력이 SQL 문의 일부로 해석되기보다 쿼리에 직접 바인딩됩니다. - 이것은 SQL로 취급되지 않기 때문에 사용자 입력이 악의적인 SQL을 삽입할 수 없습니다. + 이것은 SQL로 취급되지 않기 때문에 사용자 입력이 악의적인 SQL을 삽입할 수 없습니다. 사용자 입력을 포함하는 데 연결을 사용하는 대신 다음 선택 절을 사용합니다.

      @@ -558,35 +558,35 @@ String[] selectionArgs = {""};
       selectionArgs[0] = mUserInput;
       

      - ?를 대체 가능한 매개변수로 사용하는 선택 절과 -선택 인수 배열을 사용하는 것이 선택을 지정하는 데 선호되는 방법입니다. + ?를 대체 가능한 매개변수로 사용하는 선택 절과 +선택 인수 배열을 사용하는 것이 선택을 지정하는 데 선호되는 방법입니다. 이는 제공자가 SQL 데이터베이스 기반이 아닐 때에도 마찬가지입니다.

      쿼리 결과 표시

      - {@link android.content.ContentResolver#query ContentResolver.query()} + {@link android.content.ContentResolver#query ContentResolver.query()} 클라이언트 메서드는 언제나 쿼리 선택 기준과 일치하는 행에 대해 쿼리 프로젝션이 지정한 열을 포함하는 -{@link android.database.Cursor}를 반환합니다. +{@link android.database.Cursor}를 반환합니다. {@link android.database.Cursor} 개체가 자신이 포함한 행과 열에 무작위 읽기 액세스를 제공합니다. - {@link android.database.Cursor} 메서드를 사용하면 행을 결과에서 반복할 수 있고, + {@link android.database.Cursor} 메서드를 사용하면 행을 결과에서 반복할 수 있고, 각 열의 데이터 유형을 결정하며 열에서 데이터를 꺼내거나 결과의 다른 속성을 검토할 수도 있습니다. 일부 {@link android.database.Cursor} 구현은 제공자의 데이터가 변경될 경우, -{@link android.database.Cursor}가 변경될 때 관찰자 개체 내의 메서드를 트리거하는 경우 +{@link android.database.Cursor}가 변경될 때 관찰자 개체 내의 메서드를 트리거하는 경우 또는 두 가지가 한 번에 발생할 경우 자동으로 개체를 업데이트합니다.

      - 참고: 제공자는 쿼리를 수행하는 개체의 성격을 근거로 -열에 대한 액세스를 제한할 수 있습니다. 예를 들어 연락처 제공자는 동기화 어댑터로의 몇몇 열에 대한 액세스를 제한합니다. + 참고: 제공자는 쿼리를 수행하는 개체의 성격을 근거로 +열에 대한 액세스를 제한할 수 있습니다. 예를 들어 연락처 제공자는 동기화 어댑터로의 몇몇 열에 대한 액세스를 제한합니다. 이렇게 해야 액티비티 또는 서비스에 열을 반환하지 않기 때문입니다.

      - 선택 기준에 일치하는 행이 없으면, 제공자는 -{@link android.database.Cursor} 개체를 반환합니다. 이 개체의 + 선택 기준에 일치하는 행이 없으면, 제공자는 +{@link android.database.Cursor} 개체를 반환합니다. 이 개체의 {@link android.database.Cursor#getCount Cursor.getCount()}는 0(빈 커서)입니다.

      - 내부 오류가 발생하는 경우, 쿼리 결과는 특정 제공자에 따라 달라집니다. + 내부 오류가 발생하는 경우, 쿼리 결과는 특정 제공자에 따라 달라집니다. null을 반환하기로 선택할 수도 있고, {@link java.lang.Exception}을 발생시킬 수도 있습니다.

      @@ -595,9 +595,9 @@ selectionArgs[0] = mUserInput; 연결하는 것입니다.

      - 다음 조각은 이전 조각으로부터 코드를 계속 이어가는 것입니다. + 다음 조각은 이전 조각으로부터 코드를 계속 이어가는 것입니다. 이는 해당 쿼리가 검색한 {@link android.database.Cursor}가 들어 있는 -{@link android.widget.SimpleCursorAdapter} 개체를 생성하며, 이 개체를 +{@link android.widget.SimpleCursorAdapter} 개체를 생성하며, 이 개체를 {@link android.widget.ListView}에 대한 어댑터로 설정합니다.

      @@ -626,7 +626,7 @@ mWordList.setAdapter(mCursorAdapter);
       

      참고: {@link android.database.Cursor}로 {@link android.widget.ListView}를 뒷받침하려면, 커서에 _ID라는 열이 포함되어야 합니다. - 이것 때문에 이전에 표시된 쿼리가 "단어" 테이블에 대하여 _ID 열을 + 이것 때문에 이전에 표시된 쿼리가 "단어" 테이블에 대하여 _ID 열을 검색하며, {@link android.widget.ListView}가 이를 표시하지 않더라도 무관합니다. 이 제한은 대부분의 제공자에 각 테이블에 대한 _ID 열이 있는 이유를 설명해주기도 합니다. @@ -635,7 +635,7 @@ mWordList.setAdapter(mCursorAdapter);

      쿼리 결과에서 데이터 가져오기

      - 쿼리 결과를 단순히 표시만 하는 것보다 이를 다른 작업에 사용할 수 있습니다. + 쿼리 결과를 단순히 표시만 하는 것보다 이를 다른 작업에 사용할 수 있습니다. 예를 들어, 사용자 사전에서 철자를 검색한 다음 이것을 다른 제공자 내에서 찾아볼 수 있습니다. 이렇게 하려면, {@link android.database.Cursor}에서 행을 계속 반복하면 됩니다.

      @@ -672,10 +672,10 @@ if (mCursor != null) { }

      - {@link android.database.Cursor} 구현에는 -여러 개의 "가져오기" 메서드가 들어 있어 개체로부터 여러 가지 유형의 데이터를 검색합니다. 예를 들어 이전 조각에서는 -{@link android.database.Cursor#getString getString()}을 사용합니다. -여기에는 해당 열의 데이터 유형을 나타내는 값을 반환하는 + {@link android.database.Cursor} 구현에는 +여러 개의 "가져오기" 메서드가 들어 있어 개체로부터 여러 가지 유형의 데이터를 검색합니다. 예를 들어 이전 조각에서는 +{@link android.database.Cursor#getString getString()}을 사용합니다. +여기에는 해당 열의 데이터 유형을 나타내는 값을 반환하는 {@link android.database.Cursor#getType getType()} 메서드도 있습니다.

      @@ -683,33 +683,33 @@ if (mCursor != null) {

      콘텐츠 제공자 권한

      - 제공자의 애플리케이션은 해당 제공자의 데이터에 액세스하려면 다른 애플리케이션이 반드시 가지고 있어야 하는 -권한을 지정할 수 있습니다. 이와 같은 권한을 통해 사용자는 한 애플리케이션이 어느 데이터에 액세스하려 시도할지 -알 수 있습니다. 다른 애플리케이션은 제공자의 요구 사항을 근거로 해당 제공자에 액세스하기 위해 필요한 + 제공자의 애플리케이션은 해당 제공자의 데이터에 액세스하려면 다른 애플리케이션이 반드시 가지고 있어야 하는 +권한을 지정할 수 있습니다. 이와 같은 권한을 통해 사용자는 한 애플리케이션이 어느 데이터에 액세스하려 시도할지 +알 수 있습니다. 다른 애플리케이션은 제공자의 요구 사항을 근거로 해당 제공자에 액세스하기 위해 필요한 권한을 요청합니다. 최종 사용자는 애플리케이션을 설치할 때 요청된 권한을 보게 됩니다.

      - 제공자의 애플리케이션이 아무 권한도 지정하지 않은 경우, 다른 애플리케이션은 해당 제공자의 -데이터에 액세스할 수 없습니다. 그러나 제공자의 애플리케이션 내에 있는 구성 요소는 + 제공자의 애플리케이션이 아무 권한도 지정하지 않은 경우, 다른 애플리케이션은 해당 제공자의 +데이터에 액세스할 수 없습니다. 그러나 제공자의 애플리케이션 내에 있는 구성 요소는 지정된 권한과 무관하게 항상 읽기 및 쓰기 액세스 권한을 모두 가지고 있습니다.

      - 이전에 언급한 것과 같이 사용자 사전 제공자에서 데이터를 검색하려면 + 이전에 언급한 것과 같이 사용자 사전 제공자에서 데이터를 검색하려면 android.permission.READ_USER_DICTIONARY 권한이 필요합니다. 이 제공자에게는 데이터 삽입, 업데이트 또는 삭제에 각각 별도의 android.permission.WRITE_USER_DICTIONARY 권한이 있습니다.

      - 제공자에 액세스하는 데 필요한 권한을 얻으려면 애플리케이션은 + 제공자에 액세스하는 데 필요한 권한을 얻으려면 애플리케이션은 자신의 매니페스트 파일에 있는 <uses-permission> -으로 그러한 권한을 요청합니다. Android 패키지 관리자가 애플리케이션을 설치하는 경우, +으로 그러한 권한을 요청합니다. Android 패키지 관리자가 애플리케이션을 설치하는 경우, 사용자는 애플리케이션이 요청하는 권한을 모두 승인해야 합니다. 사용자가 이를 모두 승인하면 패키지 관리자가 설치를 계속하지만, 사용자가 이를 승인하지 않으면 패키지 관리자는 설치를 중단합니다.

      - + 다음 <uses-permission> 요소는 사용자 사전 제공자에 읽기 액세스 권한을 요청하는 것입니다.

      @@ -717,7 +717,7 @@ if (mCursor != null) { <uses-permission android:name="android.permission.READ_USER_DICTIONARY">

      - 제공자 액세스 권한이 미치는 영향은 + 제공자 액세스 권한이 미치는 영향은 보안 및 권한 가이드에 좀 더 자세히 설명되어 있습니다.

      @@ -725,15 +725,15 @@ if (mCursor != null) {

      데이터 삽입, 업데이트 및 삭제

      - 제공자로부터 데이터를 검색하는 것과 같은 방식으로, 데이터를 수정할 때에도 제공자 클라이언트와 제공자의 + 제공자로부터 데이터를 검색하는 것과 같은 방식으로, 데이터를 수정할 때에도 제공자 클라이언트와 제공자의 {@link android.content.ContentProvider} 사이의 상호작용을 사용합니다. - {@link android.content.ContentResolver}의 메서드를 호출하면서 -{@link android.content.ContentProvider}의 상응하는 메서드로 전달된 인수를 사용합니다. + {@link android.content.ContentResolver}의 메서드를 호출하면서 +{@link android.content.ContentProvider}의 상응하는 메서드로 전달된 인수를 사용합니다. 제공자와 제공자의 클라이언트가 보안과 프로세스간 통신을 자동으로 처리합니다.

      데이터 삽입

      - 데이터를 제공자 안으로 삽입하려면, + 데이터를 제공자 안으로 삽입하려면, {@link android.content.ContentResolver#insert ContentResolver.insert()} 메서드를 호출합니다. 이 메서드는 제공자에 새로운 행을 삽입하고 해당 열에 대한 콘텐츠 URI를 반환합니다. 이 조각은 사용자 사전 제공자에 새 단어를 삽입하는 방법을 나타낸 것입니다. @@ -763,8 +763,8 @@ mNewUri = getContentResolver().insert(

      새로운 행에 대한 데이터는 단일 행 커서와 형태가 유사한 단일 {@link android.content.ContentValues} 개체로 -이동합니다. 이 개체 내의 열은 모두 같은 데이터 유형을 가지지 않아도 됩니다. -또한 아예 값을 지정하고 싶지 않은 경우라면 열을 null로 설정할 수 있습니다. +이동합니다. 이 개체 내의 열은 모두 같은 데이터 유형을 가지지 않아도 됩니다. +또한 아예 값을 지정하고 싶지 않은 경우라면 열을 null로 설정할 수 있습니다. 이때 {@link android.content.ContentValues#putNull ContentValues.putNull()}을 사용하면 됩니다.

      @@ -790,11 +790,11 @@ content://user_dictionary/words/<id_value>

      데이터 업데이트

      - 행을 업데이트하려면 업데이트된 값과 함께 {@link android.content.ContentValues} 개체를 사용합니다. + 행을 업데이트하려면 업데이트된 값과 함께 {@link android.content.ContentValues} 개체를 사용합니다. 이때 값은 삽입할 때와 똑같고, 선택 기준은 쿼리할 때와 같습니다. 사용하는 클라이언트 메서드는 -{@link android.content.ContentResolver#update ContentResolver.update()}입니다. -값을 추가하는 것은 업데이트 중인 열에 대한 {@link android.content.ContentValues} 개체에만 하면 됩니다. +{@link android.content.ContentResolver#update ContentResolver.update()}입니다. +값을 추가하는 것은 업데이트 중인 열에 대한 {@link android.content.ContentValues} 개체에만 하면 됩니다. 열의 콘텐츠를 삭제하려면, 값을 null로 설정하십시오.

      @@ -827,13 +827,13 @@ mRowsUpdated = getContentResolver().update( );

      - + {@link android.content.ContentResolver#update ContentResolver.update()}를 호출하는 경우에는 사용자 입력도 삭제해야 합니다. 이 내용에 관해 자세히 알아보려면 악의적인 입력에 대한 보호 섹션을 읽어 보십시오.

      데이터 삭제

      - 행을 삭제하는 것은 행 데이터를 검색하는 것과 비슷합니다. 즉, 삭제하고자 하는 행에 대한 선택 기준을 지정하면 + 행을 삭제하는 것은 행 데이터를 검색하는 것과 비슷합니다. 즉, 삭제하고자 하는 행에 대한 선택 기준을 지정하면 클라이언트 메서드가 삭제된 행 수를 반환하는 식입니다. 다음 조각은 앱 ID가 "user"와 일치하는 행을 삭제합니다. 메서드가 삭제된 행 수를 반환합니다. @@ -857,14 +857,14 @@ mRowsDeleted = getContentResolver().delete( );

      - {@link android.content.ContentResolver#delete ContentResolver.delete()}를 + {@link android.content.ContentResolver#delete ContentResolver.delete()}를 호출하는 경우에는 사용자 입력도 삭제해야 합니다. 이 내용에 관해 자세히 알아보려면 악의적인 입력에 대한 보호 섹션을 읽어 보십시오.

      제공자 데이터 유형

      - 콘텐츠 제공자는 아주 다양한 데이터 유형을 제공할 수 있습니다. + 콘텐츠 제공자는 아주 다양한 데이터 유형을 제공할 수 있습니다. 사용자 사전 제공자는 텍스트만 제공하지만, 제공자는 다음과 같은 형식도 제공할 수 있습니다.

        @@ -883,29 +883,29 @@ mRowsDeleted = getContentResolver().delete(

      제공자가 종종 사용하는 또 다른 데이터 유형은 64KB 바이트 배열로 구현되는 BLOB(Binary Large OBject)입니다. - 이용 가능한 데이터 유형을 확인하려면 + 이용 가능한 데이터 유형을 확인하려면 {@link android.database.Cursor} 클래스 "가져오기" 메서드를 살펴보면 됩니다.

      제공자 내의 각 열에 대한 데이터 유형은 보통 자신의 문서에 목록으로 나열되어 있습니다. - 사용자 사전 제공자의 데이터 유형은 제공자의 계약 클래스 + 사용자 사전 제공자의 데이터 유형은 제공자의 계약 클래스 {@link android.provider.UserDictionary.Words}의 참조 문서에 나열되어 있습니다(계약 클래스는 계약 클래스 섹션에 설명되어 있습니다). - @link android.database.Cursor#getType + {@link android.database.Cursor#getType Cursor.getType()}을 호출해서도 데이터 유형을 결정할 수 있습니다.

      - 제공자는 스스로 정의하는 각 콘텐츠 URI의 MIME 데이터 유형 정보도 유지관리합니다. -MIME 유형 정보를 사용하면 애플리케이션이 제공자가 제공하는 데이터를 처리할 수 있을지 알아낼 수도 있고, -MIME 유형을 근거로 처리 유형을 선택할 수도 있습니다. + 제공자는 스스로 정의하는 각 콘텐츠 URI의 MIME 데이터 유형 정보도 유지관리합니다. +MIME 유형 정보를 사용하면 애플리케이션이 제공자가 제공하는 데이터를 처리할 수 있을지 알아낼 수도 있고, +MIME 유형을 근거로 처리 유형을 선택할 수도 있습니다. MIME 유형이 필요한 시점은 주로 복잡한 데이터 구조 또는 파일이 들어 있는 제공자를 다룰 때입니다. 예를 들어 연락처 제공자 내의 {@link android.provider.ContactsContract.Data} 테이블은 MIME 유형을 사용하여 각 행에 저장된 연락처 데이터의 유형에 레이블을 붙입니다. - 콘텐츠 URI에 상응하는 MIME 유형을 가져오려면 + 콘텐츠 URI에 상응하는 MIME 유형을 가져오려면 {@link android.content.ContentResolver#getType ContentResolver.getType()}을 호출하십시오.

      - MIME 유형 참조 섹션에서 표준 및 사용자 지정 MIME 유형의 + MIME 유형 참조 섹션에서 표준 및 사용자 지정 MIME 유형의 두 가지를 모두 설명하고 있습니다.

      @@ -922,13 +922,13 @@ MIME 유형이 필요한 시점은 주로 복잡한 데이터 구조 또는 파 {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}로 이를 적용할 수 있습니다.
    • - 비동기식 쿼리: 쿼리는 별도의 스레드에서 수행해야 합니다. 이 작업을 수행하는 한 가지 방법으로 -{@link android.content.CursorLoader} 개체를 사용하는 것이 있습니다. 이 사용 방법은 + 비동기식 쿼리: 쿼리는 별도의 스레드에서 수행해야 합니다. 이 작업을 수행하는 한 가지 방법으로 +{@link android.content.CursorLoader} 개체를 사용하는 것이 있습니다. 이 사용 방법은 로더 가이드에 있는 예시에서 설명합니다.
    • - 인텐트를 통한 데이터 액세스: + 인텐트를 통한 데이터 액세스: 인텐트를 제공자에 직접 보낼 수는 없지만, 인텐트를 제공자의 애플리케이션에 보낼 수는 있습니다. 보통은 이것이 제공자의 데이터를 수정하기에 가장 좋습니다.
    • @@ -938,23 +938,23 @@ MIME 유형이 필요한 시점은 주로 복잡한 데이터 구조 또는 파

      일괄 액세스

      - 제공자에 일괄 액세스를 하면 많은 수의 행을 삽입할 때, 같은 메서드 호출 내에서 여러 개의 테이블에 여러 행을 삽입할 때 + 제공자에 일괄 액세스를 하면 많은 수의 행을 삽입할 때, 같은 메서드 호출 내에서 여러 개의 테이블에 여러 행을 삽입할 때 또는 전반적으로, 프로세스 경계를 가로질러 일련의 작업을 수행하는 경우(원자성 작업) 유용합니다.

      "일괄 모드"로 제공자에 액세스하려면 -{@link android.content.ContentProviderOperation} 개체의 배열을 생성한 다음 이를 콘텐츠 제공자에게 +{@link android.content.ContentProviderOperation} 개체의 배열을 생성한 다음 이를 콘텐츠 제공자에게 {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}로 - 발송하면 됩니다. + 발송하면 됩니다. 이 메서드에는 특정한 콘텐츠 URI보다는 콘텐츠 제공자의 권한을 전달합니다. -이렇게 하면 배열 내의 각 {@link android.content.ContentProviderOperation} 개체가 +이렇게 하면 배열 내의 각 {@link android.content.ContentProviderOperation} 개체가 서로 다른 테이블에 대해 작용하도록 할 수 있습니다. {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}를 호출하면 일련의 결과를 반환합니다.

      {@link android.provider.ContactsContract.RawContacts} 계약 클래스의 설명에 - 일괄 삽입을 설명하는 코드 조각이 포함되어 있습니다. + 일괄 삽입을 설명하는 코드 조각이 포함되어 있습니다. 연락처 관리자 샘플 애플리케이션에는 ContactAdder.java 소스 파일의 일괄 액세스 예시가 포함되어 있습니다. @@ -963,31 +963,31 @@ MIME 유형이 필요한 시점은 주로 복잡한 데이터 구조 또는 파

      인텐트를 통한 데이터 액세스

      - 인텐트는 콘텐츠 제공자에 간접 액세스를 제공할 수 있습니다. 애플리케이션에 액세스 권한이 없는데도 -사용자에게 제공자 내의 데이터에 액세스 권한을 허가하려면, 권한을 가지고 있는 애플리케이션에서 결과 인텐트를 다시 가져오거나 + 인텐트는 콘텐츠 제공자에 간접 액세스를 제공할 수 있습니다. 애플리케이션에 액세스 권한이 없는데도 +사용자에게 제공자 내의 데이터에 액세스 권한을 허가하려면, 권한을 가지고 있는 애플리케이션에서 결과 인텐트를 다시 가져오거나 권한이 있는 애플리케이션을 활성화한 다음 사용자에게 그 애플리케이션에서 작업하도록 하면 됩니다.

      임시 권한으로 액세스 얻기

      - 적절한 액세스 권한이 없더라도 콘텐츠 제공자 내의 데이터에 액세스할 수는 있습니다. + 적절한 액세스 권한이 없더라도 콘텐츠 제공자 내의 데이터에 액세스할 수는 있습니다. 권한을 가지고 있는 애플리케이션에 인텐트를 보내 "URI" 권한이 들어 있는 결과 인텐트를 돌려받으면 됩니다. 이들 권한은 특정 콘텐츠 URI에 대한 권한으로, 이를 수신하는 액티비티가 완료될 때까지 유지됩니다. @@ -1005,27 +1005,27 @@ MIME 유형이 필요한 시점은 주로 복잡한 데이터 구조 또는 파

    - 참고: 이와 같은 플래그는 콘텐츠 URI에 권한이 들어 있는 제공자에 일반적인 읽기 또는 쓰기 액세스 + 참고: 이와 같은 플래그는 콘텐츠 URI에 권한이 들어 있는 제공자에 일반적인 읽기 또는 쓰기 액세스 권한을 부여하지는 않습니다. 이 액세스는 URI 자체에만 해당됩니다.

    - 제공자는 자신의 매니페스트 내의 콘텐츠 URI에 대한 URI 권한을 정의합니다. 이때 + 제공자는 자신의 매니페스트 내의 콘텐츠 URI에 대한 URI 권한을 정의합니다. 이때 <provider> - 요소의 + 요소의 android:grantUriPermission - 속성을 사용하며, + 속성을 사용하며, <provider> - 요소의 + 요소의 <grant-uri-permission> - 하위 요소도 사용합니다. + 하위 요소도 사용합니다. URI 권한 메커니즘은 "URI 권한" 섹션의 보안 및 권한 가이드에 자세히 설명되어 있습니다.

    예를 들어, {@link android.Manifest.permission#READ_CONTACTS} 권한이 없더라도 -연락처 제공자 내의 연락처에 대한 데이터를 검색할 수 있습니다. -이 작업을 하면 좋은 예로, 연락처에 기재된 사람의 생일에 전자 축하 카드를 보내주는 애플리케이션을 들 수 있습니다. -{@link android.Manifest.permission#READ_CONTACTS}를 요청하면 +연락처 제공자 내의 연락처에 대한 데이터를 검색할 수 있습니다. +이 작업을 하면 좋은 예로, 연락처에 기재된 사람의 생일에 전자 축하 카드를 보내주는 애플리케이션을 들 수 있습니다. +{@link android.Manifest.permission#READ_CONTACTS}를 요청하면 사용자의 연락처 전체와 해당 정보 일체에 대한 액세스를 부여하므로, 그 대신 애플리케이션에서 어느 연락처를 사용할지 사용자가 직접 제어하도록 해주는 편이 낫습니다. 이렇게 하려면, 다음 절차를 사용합니다.

    @@ -1043,13 +1043,13 @@ startActivityForResult()} 메서드를 사용해서
  • 선택 액티비티에서 사용자가 업데이트할 연락처를 선택합니다. - 이렇게 되면 선택 액티비티가 + 이렇게 되면 선택 액티비티가 {@link android.app.Activity#setResult setResult(resultcode, intent)} -를 호출하여 애플리케이션에 돌려줄 인텐트를 설정합니다. -이 인텐트에 사용자가 선택한 연락처의 콘텐츠 URI와 "추가" 플래그 -{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}이 들어 있습니다. -이러한 플래그가 URI에 앱으로의 권한을 허가하여 콘텐츠 URI가 가리킨 연락처에 대한 데이터를 읽을 수 있도록 합니다. -그런 다음 선택 액티비티는 {@link android.app.Activity#finish()}를 호출하여 +를 호출하여 애플리케이션에 돌려줄 인텐트를 설정합니다. +이 인텐트에 사용자가 선택한 연락처의 콘텐츠 URI와 "추가" 플래그 +{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}이 들어 있습니다. +이러한 플래그가 URI에 앱으로의 권한을 허가하여 콘텐츠 URI가 가리킨 연락처에 대한 데이터를 읽을 수 있도록 합니다. +그런 다음 선택 액티비티는 {@link android.app.Activity#finish()}를 호출하여 애플리케이션에 제어를 반환합니다.
  • @@ -1067,7 +1067,7 @@ startActivityForResult()} 메서드를 사용해서

    다른 애플리케이션 사용

    - 개발자에게 액세스 권한이 없는 데이터를 사용자가 수정할 수 있도록 허용하는 간단한 방법은 + 개발자에게 액세스 권한이 없는 데이터를 사용자가 수정할 수 있도록 허용하는 간단한 방법은 해당 권한을 가지고 있는 애플리케이션을 활성화한 다음 사용자에게 그곳에서 작업하도록 해주는 것입니다.

    @@ -1082,18 +1082,18 @@ startActivityForResult()} 메서드를 사용해서

    계약 클래스

    계약 클래스는 애플리케이션이 콘텐츠 URI, 열 이름, 인텐트 작업 및 콘텐츠 제공자의 다른 기능과 -작업할 수 있게 도와주는 상수를 정의합니다. 계약 클래스는 제공자와 함께 자동으로 포함되지 않습니다. +작업할 수 있게 도와주는 상수를 정의합니다. 계약 클래스는 제공자와 함께 자동으로 포함되지 않습니다. 해당 제공자의 개발자가 이를 정의한 다음 다른 개발자가 사용할 수 있도록 해야 합니다. - Android 플랫폼 내에 포함된 제공자는 대부분 패키지 + Android 플랫폼 내에 포함된 제공자는 대부분 패키지 {@link android.provider} 안에 상응하는 계약 클래스를 가지고 있습니다.

    예를 들어, 사용자 사전 제공자에는 콘텐츠 URI와 열 이름 상수가 들어 있는 -{@link android.provider.UserDictionary} 계약 클래스가 있습니다. +{@link android.provider.UserDictionary} 계약 클래스가 있습니다. "단어" 테이블에 대한 콘텐츠 URI는 상수 {@link android.provider.UserDictionary.Words#CONTENT_URI UserDictionary.Words.CONTENT_URI}에 정의됩니다. - {@link android.provider.UserDictionary.Words} 클래스에도 -열 이름 상수가 들어 있으며, 이는 이 가이드의 예시 조각에서 사용됩니다. + {@link android.provider.UserDictionary.Words} 클래스에도 +열 이름 상수가 들어 있으며, 이는 이 가이드의 예시 조각에서 사용됩니다. 예를 들어 쿼리 프로젝션은 다음과 같이 정의될 수 있습니다.

    @@ -1106,7 +1106,7 @@ String[] mProjection =
     

    또 다른 계약 클래스는 연락처 제공자의 {@link android.provider.ContactsContract}입니다. - 이 클래스에 대한 참조 문서에는 예시 코드 조각이 포함되어 있습니다. + 이 클래스에 대한 참조 문서에는 예시 코드 조각이 포함되어 있습니다. 이것의 하위 클래스 중 하나인 {@link android.provider.ContactsContract.Intents.Insert}는 인텐트와 인텐트 데이터의 상수가 들어 있는 계약 클래스입니다.

    @@ -1129,7 +1129,7 @@ String[] mProjection = 해당 URI를 사용하는 쿼리가 HTML 태그가 들어 있는 텍스트를 반환할 것이라는 뜻입니다.

    - 사용자 지정 MIME 유형 문자열은 "공급업체별" MIME 유형이라고도 불리며 + 사용자 지정 MIME 유형 문자열은 "공급업체별" MIME 유형이라고도 불리며 이쪽의 유형하위 유형 값이 더 복잡합니다. 유형 값은 경우에 따라 항상 다음과 같습니다.

    @@ -1184,13 +1184,13 @@ content://com.example.trains/Line2/5
     vnd.android.cursor.item/vnd.example.line2
     

    - 대부분의 콘텐츠 제공자는 자신이 사용하는 MIME 유형에 대한 계약 클래스 상수를 정의합니다. + 대부분의 콘텐츠 제공자는 자신이 사용하는 MIME 유형에 대한 계약 클래스 상수를 정의합니다. 예를 들어, 연락처 제공자 계약 클래스 {@link android.provider.ContactsContract.RawContacts}는 단일 연락처 행의 MIME 유행에 대한 상수 {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE}을 정의합니다.

    - 한 행에 대한 콘텐츠 URI는 + 한 행에 대한 콘텐츠 URI는 콘텐츠 URI 섹션에 설명되어 있습니다.

    diff --git a/docs/html-intl/intl/ko/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/ko/guide/topics/providers/content-provider-creating.jd index 6757194a9f288242f1e2179adbf6e82f8197eb3b..af7b584c6257aeec38adc8c66aed5623cbdf60be 100644 --- a/docs/html-intl/intl/ko/guide/topics/providers/content-provider-creating.jd +++ b/docs/html-intl/intl/ko/guide/topics/providers/content-provider-creating.jd @@ -95,16 +95,16 @@ page.title= 콘텐츠 제공자 생성

    - 콘텐츠 제공자는 데이터의 중앙 리포지토리로의 액세스를 관리합니다. Android 애플리케이션에서는 + 콘텐츠 제공자는 데이터의 중앙 리포지토리로의 액세스를 관리합니다. Android 애플리케이션에서는 제공자를 하나 이상의 클래스로, 매니페스트 파일에 있는 요소와 함께 구현합니다. - 클래스 중 하나가 하위 클래스 -{@link android.content.ContentProvider}를 구현하며, -이것이 제공자와 다른 애플리케이션 사이의 인터페이스입니다. 콘텐츠 제공자는 다른 애플리케이션에 데이터를 사용할 수 있게 해주도록 만들어져 있지만, -물론 애플리케이션 내에 사용자로 하여금 제공자가 관리하는 데이터를 쿼리하고 수정할 수 있게 허용하는 + 클래스 중 하나가 하위 클래스 +{@link android.content.ContentProvider}를 구현하며, +이것이 제공자와 다른 애플리케이션 사이의 인터페이스입니다. 콘텐츠 제공자는 다른 애플리케이션에 데이터를 사용할 수 있게 해주도록 만들어져 있지만, +물론 애플리케이션 내에 사용자로 하여금 제공자가 관리하는 데이터를 쿼리하고 수정할 수 있게 허용하는 액티비티가 있을 수도 있습니다.

    - 이 주제의 나머지 부분은 콘텐츠 제공자를 구축하기 위한 기본 단계 목록과 + 이 주제의 나머지 부분은 콘텐츠 제공자를 구축하기 위한 기본 단계 목록과 사용할 API 목록으로 이루어져 있습니다.

    @@ -124,12 +124,12 @@ page.title= 콘텐츠 제공자 생성
  • 검색 프레임워크를 사용한 사용자 지정 검색 제안을 제공하고자 하는 경우
  • - 용도가 본인의 애플리케이션 안에서로 완전히 한정되어 있는 경우에는 + 용도가 본인의 애플리케이션 안에서로 완전히 한정되어 있는 경우에는 제공자가 SQLite 데이터베이스를 사용하도록 하지 않아도 됩니다.

  • - 아직 읽지 않았다면, 지금 바로 + 아직 읽지 않았다면, 지금 바로 콘텐츠 제공자 기본 정보를 읽고 제공자에 대해 자세히 알아보십시오.
  • @@ -146,8 +146,8 @@ page.title= 콘텐츠 제공자 생성
    일반적으로 사진, 오디오 또는 동영상과 같은 -파일에 들어가는 데이터입니다. 이런 파일을 애플리케이션의 비공개 -공간에 저장합니다. 제공자는 다른 애플리케이션으로부터 온 파일 요청에 응답하여 +파일에 들어가는 데이터입니다. 이런 파일을 애플리케이션의 비공개 +공간에 저장합니다. 제공자는 다른 애플리케이션으로부터 온 파일 요청에 응답하여 해당 파일로의 핸들을 제공할 수 있습니다.
    @@ -155,9 +155,9 @@ page.title= 콘텐츠 제공자 생성
    일반적으로 데이터베이스, 배열 또는 유사 구조에 들어가는 데이터입니다. - 이 데이터를 행과 열로 이루어진 테이블과 호환되는 형식으로 저장합니다. -행은 사람이나 인벤토리의 항목과 같은 엔티티를 나타냅니다. -열은 해당 엔티티에 대한 몇 가지 데이터, 예를 들어 사람 이름이나 항목 가격 등을 나타냅니다. + 이 데이터를 행과 열로 이루어진 테이블과 호환되는 형식으로 저장합니다. +행은 사람이나 인벤토리의 항목과 같은 엔티티를 나타냅니다. +열은 해당 엔티티에 대한 몇 가지 데이터, 예를 들어 사람 이름이나 항목 가격 등을 나타냅니다. 이 유형의 데이터를 저장하는 보편적인 방법은 SQLite 데이터베이스 안에 저장하는 것이지만, 모든 유형의 영구적인 저장소를 사용해도 됩니다. Android 시스템에서 사용할 수 있는 저장소 유형에 대해 자세히 알아보려면, @@ -172,11 +172,11 @@ page.title= 콘텐츠 제공자 생성 ContentProvider 클래스 구현 섹션을 참조하십시오.
  • - 제공자의 권한 문자열, 그 콘텐츠 URI 및 열 이름을 정의합니다. + 제공자의 권한 문자열, 그 콘텐츠 URI 및 열 이름을 정의합니다. 제공자 애플리케이션이 인텐트를 처리하게 하려면, 인텐트 작업과 추가 데이터 및 -플래그도 정의합니다. 데이터에 액세스하기를 원하는 애플리케이션에 요구할 권한도 -정의합니다. 이 모든 값은 별도의 계약 클래스에서 상수로 정의하는 것을 고려해보는 -것이 좋습니다. 이 클래스를 나중에 다른 개발자에게 노출할 수 있습니다. +플래그도 정의합니다. 데이터에 액세스하기를 원하는 애플리케이션에 요구할 권한도 +정의합니다. 이 모든 값은 별도의 계약 클래스에서 상수로 정의하는 것을 고려해보는 +것이 좋습니다. 이 클래스를 나중에 다른 개발자에게 노출할 수 있습니다. 콘텐츠 URI에 관한 자세한 정보는 콘텐츠 URI 설계 섹션을 참조하십시오. 인텐트에 관한 자세한 정보는 @@ -193,8 +193,8 @@ page.title= 콘텐츠 제공자 생성

    데이터 저장소 설계

    - 콘텐츠 제공자는 구조화된 형식으로 저장된 데이터로의 인터페이스입니다. -인터페이스를 생성하기 전에 우선 데이터 저장 방식부터 결정해야 합니다. + 콘텐츠 제공자는 구조화된 형식으로 저장된 데이터로의 인터페이스입니다. +인터페이스를 생성하기 전에 우선 데이터 저장 방식부터 결정해야 합니다. 데이터는 원하는 형식 아무 것으로나 저장할 수 있으며 그런 다음에 필요에 따라 해당 데이터를 읽고 쓸 인터페이스를 설계합니다.

    @@ -203,26 +203,26 @@ page.title= 콘텐츠 제공자 생성

    • Android 시스템에는 Android 자체 제공자가 테이블 지향적 데이터를 -저장하는 데 사용하는 SQLite 데이터베이스 API가 포함됩니다. +저장하는 데 사용하는 SQLite 데이터베이스 API가 포함됩니다. {@link android.database.sqlite.SQLiteOpenHelper} 클래스는 데이터베이스를 생성할 수 있게 돕고, {@link android.database.sqlite.SQLiteDatabase} 클래스는 데이터베이스 액세스를 위한 기본 클래스입니다.

      - 리포지토리를 구현하기 위해 데이터베이스를 사용하지 않아도 된다는 점을 기억하십시오. -제공자는 외부에 테이블 집합으로 나타나 관계적 데이터베이스와 비슷해 보이지만, + 리포지토리를 구현하기 위해 데이터베이스를 사용하지 않아도 된다는 점을 기억하십시오. +제공자는 외부에 테이블 집합으로 나타나 관계적 데이터베이스와 비슷해 보이지만, 이것은 제공자의 내부 구현에 필요한 것은 아닙니다.

    • 파일 데이터를 저장하는 데 있어 Android에는 다양한 파일 지향적 API가 있습니다. 파일 저장소에 관해 자세히 알아보려면 -데이터 저장소 주제를 읽어 보십시오. -음악이나 동영상 등 미디어 관련 데이터를 제공하는 제공자를 설계하는 경우, +데이터 저장소 주제를 읽어 보십시오. +음악이나 동영상 등 미디어 관련 데이터를 제공하는 제공자를 설계하는 경우, 제공자가 테이블 데이터와 파일을 조합 할 수 있습니다.
    • - 네트워크 기반 데이터를 다루는 경우, {@link java.net} 및 -{@link android.net} 내의 클래스를 사용하십시오. 네트워크 기반 데이터를 + 네트워크 기반 데이터를 다루는 경우, {@link java.net} 및 +{@link android.net} 내의 클래스를 사용하십시오. 네트워크 기반 데이터를 데이터베이스와 같은 로컬 데이터 스토어와 동기화한 다음, 해당 데이터를 테이블이나 파일로 제공할 수도 있습니다. 샘플 동기화 어댑터 샘플 애플리케이션이 이런 유형의 동기화를 보여줍니다. @@ -237,7 +237,7 @@ page.title= 콘텐츠 제공자 생성
      • 테이블 데이터는 언제나 제공자가 유지관리하는 "기본 키" 열을 -각 행의 고유한 숫자 값으로 보유하고 있어야 합니다. 이 값을 사용하여 해당 행을 다른 테이블의 +각 행의 고유한 숫자 값으로 보유하고 있어야 합니다. 이 값을 사용하여 해당 행을 다른 테이블의 관련 행에 연결시킬 수 있습니다(이를 "외래 키"로 사용). 이 열에는 어느 이름이든 사용할 수 있지만 {@link android.provider.BaseColumns#_ID BaseColumns._ID}를 사용하는 것이 가장 좋습니다. 왜냐하면 제공자 쿼리 결과를 @@ -246,8 +246,8 @@ page.title= 콘텐츠 제공자 생성
      • 비트맵 이미지나 파일 지향적 데이터의 매우 큰 조각을 제공하려면 -테이블 안에 직접 저장하기보다는 파일에 데이터를 저장한 뒤 -간접적으로 제공합니다. 이렇게 하는 경우, 제공자의 사용자들에게 데이터에 액세스하려면 +테이블 안에 직접 저장하기보다는 파일에 데이터를 저장한 뒤 +간접적으로 제공합니다. 이렇게 하는 경우, 제공자의 사용자들에게 데이터에 액세스하려면 {@link android.content.ContentResolver} 파일 메서드를 사용해야 한다고 알려야 합니다.
      • @@ -256,12 +256,12 @@ page.title= 콘텐츠 제공자 생성 프로토콜 버퍼 또는 JSON 구조를 저장할 수 있습니다.

        - BLOB를 사용하여 스키마에 종속되지 않은 테이블을 구현할 수도 있습니다. + BLOB를 사용하여 스키마에 종속되지 않은 테이블을 구현할 수도 있습니다. 이 유형의 테이블에서는, 기본 키 열, MIME 유형 열 및 하나 이상의 일반적인 열을 BLOB로 정의합니다. - -BLOB 열에 있는 데이터의 의미는 MIME 유형 열에 있는 값으로 나타냅니다. -이렇게 하면 같은 테이블에 여러 가지 행 유형을 저장할 수 있습니다. 연락처 제공자의 "데이터" 테이블 -{@link android.provider.ContactsContract.Data}가 + +BLOB 열에 있는 데이터의 의미는 MIME 유형 열에 있는 값으로 나타냅니다. +이렇게 하면 같은 테이블에 여러 가지 행 유형을 저장할 수 있습니다. 연락처 제공자의 "데이터" 테이블 +{@link android.provider.ContactsContract.Data}가 스키마에 종속되지 않은 테이블의 한 가지 예입니다.

      • @@ -269,11 +269,11 @@ BLOB 열에 있는 데이터의 의미는 MIME 유형 열에 있는 값으로

        콘텐츠 URI 설계

        - 콘텐츠 URI는 제공자에서 데이터를 식별하는 URI입니다. + 콘텐츠 URI는 제공자에서 데이터를 식별하는 URI입니다. 콘텐츠 URI에는 전체 제공자의 상징적인 이름(제공자의 권한)과 -테이블 또는 파일을 가리키는 이름(경로)이 포함됩니다. -선택 항목 ID 부분은 테이블 내의 개별적인 행을 가리킵니다. -{@link android.content.ContentProvider}의 모든 데이터 액세스 메서드는 +테이블 또는 파일을 가리키는 이름(경로)이 포함됩니다. +선택 항목 ID 부분은 테이블 내의 개별적인 행을 가리킵니다. +{@link android.content.ContentProvider}의 모든 데이터 액세스 메서드는 콘텐츠 URI를 인수로 가집니다. 이를 통해 액세스할 테이블, 행 또는 파일을 결정할 수 있습니다.

        @@ -283,9 +283,9 @@ BLOB 열에 있는 데이터의 의미는 MIME 유형 열에 있는 값으로

        권한 설계

        - 제공자에는 보통 하나의 권한이 있으며, 이것이 Android 내부 이름 역할을 합니다. + 제공자에는 보통 하나의 권한이 있으며, 이것이 Android 내부 이름 역할을 합니다. 다른 제공자와의 충돌을 피하려면, 제공자 권한의 기반으로 인터넷 도메인 소유권(역방향)을 -사용해야 합니다. 이 권장 사항은 Android 패키지 이름에도 적용되므로, +사용해야 합니다. 이 권장 사항은 Android 패키지 이름에도 적용되므로, 제공자 권한을 제공자가 들어 있는 패키지의 이름 확장자로 정의해도 됩니다. 예를 들어, Android 패키지 이름이 com.example.<appname>라면, 제공자에게 @@ -293,40 +293,40 @@ BLOB 열에 있는 데이터의 의미는 MIME 유형 열에 있는 값으로

        경로 구조 설계

        - 개발자는 보통 권한으로부터 콘텐츠 URI를 생성할 때 개별적인 테이블을 가리키는 + 개발자는 보통 권한으로부터 콘텐츠 URI를 생성할 때 개별적인 테이블을 가리키는 경로를 추가하는 방식을 사용합니다. 예를 들어, table1table2라는 테이블이 있다면, 이전 예시의 권한을 조합하여 -콘텐츠 URIcom.example.<appname>.provider/table1와 +콘텐츠 URIcom.example.<appname>.provider/table1com.example.<appname>.provider/table2를 도출합니다. - + 경로는 하나의 세그먼트에 국한되지 않으며, 경로의 각 수준에 대한 테이블이 아니어도 됩니다.

        콘텐츠 URI ID 처리

        - 규칙에 의하면, 제공자는 URI 맨 끝에서 행에 대한 ID 값이 있는 콘텐츠 URI를 허용하여 -테이블 내 하나의 행으로의 액세스를 제공합니다. 또한 규칙에 의해 제공자는 -이 ID 값을 테이블의 _ID 열에 일치시켜야 하며, + 규칙에 의하면, 제공자는 URI 맨 끝에서 행에 대한 ID 값이 있는 콘텐츠 URI를 허용하여 +테이블 내 하나의 행으로의 액세스를 제공합니다. 또한 규칙에 의해 제공자는 +이 ID 값을 테이블의 _ID 열에 일치시켜야 하며, 일치한 행에 대하여 요청된 액세스 허가를 수행해야 합니다.

        - 이 규칙은 제공자에 액세스하는 앱을 위한 공통 설계 패턴을 세우는 데 유용합니다. + 이 규칙은 제공자에 액세스하는 앱을 위한 공통 설계 패턴을 세우는 데 유용합니다. 앱이 제공자에 대한 쿼리를 수행하고 그 결과로 나온 {@link android.database.Cursor}를 {@link android.widget.ListView}에 {@link android.widget.CursorAdapter}를 사용하여 표시합니다. - {@link android.widget.CursorAdapter}의 정의에 따르면 + {@link android.widget.CursorAdapter}의 정의에 따르면 {@link android.database.Cursor} 안의 열 중 하나는 _ID여야 합니다.

        - 그러면 사용자가 데이터를 살펴보거나 수정하기 위하여 + 그러면 사용자가 데이터를 살펴보거나 수정하기 위하여 UI에서 표시된 여러 행 중 하나를 선택합니다. 앱은 {@link android.widget.ListView}를 지원하는 {@link android.database.Cursor}에서 해당하는 열을 가져오고, 해당 열에 대한 _ID 값을 가져와서 -콘텐츠 URI에 추가하고, 제공자에 액세스 요청을 전송합니다. 그런 다음 제공자는 +콘텐츠 URI에 추가하고, 제공자에 액세스 요청을 전송합니다. 그런 다음 제공자는 사용자가 선택한 바로 그 행에 대해 쿼리 또는 수정 작업을 수행할 수 있습니다.

        콘텐츠 URI 패턴

        - 수신되는 콘텐츠 URI에 대해 어떤 조치를 취할지 선택하는 데 도움이 되도록 하기 위해 제공자 API에 -편의 클래스 {@link android.content.UriMatcher}가 -포함되어 있습니다. 이는 콘텐츠 URI "패턴"을 정수값으로 매핑합니다. 이 정수값은 특정 패턴에 일치하는 + 수신되는 콘텐츠 URI에 대해 어떤 조치를 취할지 선택하는 데 도움이 되도록 하기 위해 제공자 API에 +편의 클래스 {@link android.content.UriMatcher}가 +포함되어 있습니다. 이는 콘텐츠 URI "패턴"을 정수값으로 매핑합니다. 이 정수값은 특정 패턴에 일치하는 콘텐츠 URI 또는 여러 URI에 대해 원하는 작업을 선택하는 데 switch 문에서 사용할 수 있습니다.

        @@ -341,8 +341,8 @@ UI에서 표시된 여러 행 중 하나를 선택합니다. 앱은 {@link andro

      - 콘텐츠 URI 처리의 설계와 코딩에 대한 예시로서 임의의 제공자를 들어 보겠습니다. -이 제공자에는 권한 com.example.app.provider가 있고 + 콘텐츠 URI 처리의 설계와 코딩에 대한 예시로서 임의의 제공자를 들어 보겠습니다. +이 제공자에는 권한 com.example.app.provider가 있고 이 권한이 테이블을 가리키는 다음 콘텐츠 URI를 인식합니다.

        @@ -350,11 +350,11 @@ UI에서 표시된 여러 행 중 하나를 선택합니다. 앱은 {@link andro content://com.example.app.provider/table1: table1이라는 테이블입니다.
      • - content://com.example.app.provider/table2/dataset1: + content://com.example.app.provider/table2/dataset1: dataset1이라는 테이블입니다.
      • - content://com.example.app.provider/table2/dataset2: + content://com.example.app.provider/table2/dataset2: dataset2라는 테이블입니다.
      • @@ -363,7 +363,7 @@ UI에서 표시된 여러 행 중 하나를 선택합니다. 앱은 {@link andro

      제공자는 추가된 행 ID가 있으면 이런 콘텐츠 URI도 인식합니다. -예를 들어, table3에서 1이 식별한 행에 대한 +예를 들어, table3에서 1이 식별한 행에 대한 content://com.example.app.provider/table3/1이 이에 해당됩니다.

      @@ -385,7 +385,7 @@ UI에서 표시된 여러 행 중 하나를 선택합니다. 앱은 {@link andro table3에 대한 콘텐츠 URI와 일치하지 않습니다.

  • - content://com.example.app.provider/table3/#: + content://com.example.app.provider/table3/#: table3의 단일 행에 대한 콘텐츠 URI와 일치합니다. 예를 들어, 6이 식별한 행에 대한 content://com.example.app.provider/table3/6이 이에 해당됩니다. @@ -393,8 +393,8 @@ UI에서 표시된 여러 행 중 하나를 선택합니다. 앱은 {@link andro

    다음 코드 조각은 {@link android.content.UriMatcher} 작업에서 메서드의 작용 원리를 나타낸 것입니다. - 이 코드는 테이블에 대한 콘텐츠 URI 패턴 content://<authority>/<path>와 -단일 행에 대한 콘텐츠 URI 패턴 content://<authority>/<path>/<id>를 사용하여 + 이 코드는 테이블에 대한 콘텐츠 URI 패턴 content://<authority>/<path>와 +단일 행에 대한 콘텐츠 URI 패턴 content://<authority>/<path>/<id>를 사용하여 단일 행에 대한 URI와 전체 테이블에 대한 URI를 서로 다르게 처리합니다.

    @@ -468,7 +468,7 @@ public class ExampleProvider extends ContentProvider { }

    - 또 다른 클래스, {@link android.content.ContentUris}가 + 또 다른 클래스, {@link android.content.ContentUris}가 콘텐츠 URI의 id 부분을 다루기 위한 편의 메서드를 제공합니다. 클래스 {@link android.net.Uri}와 {@link android.net.Uri.Builder}에는 기존 {@link android.net.Uri} 개체를 구문 분석하고 새로운 개체를 구축하기 위한 편의 메서드가 포함되어 있습니다. @@ -478,15 +478,15 @@ public class ExampleProvider extends ContentProvider {

    ContentProvider 클래스 구현

    {@link android.content.ContentProvider} 인스턴스는 -다른 애플리케이션으로부터의 요청을 처리하여 구조화된 데이터 세트로의 액세스를 관리합니다. -모든 형태의 액세서가 궁극적으로 {@link android.content.ContentResolver}를 호출하며, +다른 애플리케이션으로부터의 요청을 처리하여 구조화된 데이터 세트로의 액세스를 관리합니다. +모든 형태의 액세서가 궁극적으로 {@link android.content.ContentResolver}를 호출하며, 그러면 이것이 액세스 권한을 얻기 위해 구체적인 {@link android.content.ContentProvider} 메서드를 호출합니다.

    필수 메서드

    - 추상 클래스 {@link android.content.ContentProvider}는 -개발자가 나름의 구체적인 하위 클래스의 일부분으로 구현해야만 하는 여섯 가지 추상 메서드를 정의합니다. 이와 같은 메서드는 모두 -({@link android.content.ContentProvider#onCreate() onCreate()}는 예외) + 추상 클래스 {@link android.content.ContentProvider}는 +개발자가 나름의 구체적인 하위 클래스의 일부분으로 구현해야만 하는 여섯 가지 추상 메서드를 정의합니다. 이와 같은 메서드는 모두 +({@link android.content.ContentProvider#onCreate() onCreate()}는 예외) 콘텐츠 제공자에 액세스하려 시도 중인 클라이언트 애플리케이션이 호출합니다.

    @@ -503,8 +503,8 @@ query()} {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}
    - 제공자에 새로운 행을 삽입합니다. 인수를 사용하여 대상 테이블을 선택하고 -사용할 열 값을 가져옵니다. + 제공자에 새로운 행을 삽입합니다. 인수를 사용하여 대상 테이블을 선택하고 +사용할 열 값을 가져옵니다. 새로 삽입된 행에 대한 콘텐츠 URI를 반환합니다.
    @@ -512,7 +512,7 @@ query()} update()}
    - 제공자 내의 기존 행을 업데이트합니다. 인수를 사용하여 + 제공자 내의 기존 행을 업데이트합니다. 인수를 사용하여 업데이트할 테이블과 행을 선택하고 업데이트한 열 값을 가져옵니다. 업데이트한 행 개수를 반환합니다.
    @@ -526,20 +526,20 @@ update()} {@link android.content.ContentProvider#getType(Uri) getType()}
    - 콘텐츠 URI에 상응하는 MIME 유형을 반환합니다. 이 메서드는 + 콘텐츠 URI에 상응하는 MIME 유형을 반환합니다. 이 메서드는 콘텐츠 제공자 MIME 유형 섹션에 더 자세하게 설명되어 있습니다.
    {@link android.content.ContentProvider#onCreate() onCreate()}
    - 제공자를 초기화합니다. Android 시스템은 제공자를 생성한 직후 -이 메서드를 호출합니다. + 제공자를 초기화합니다. Android 시스템은 제공자를 생성한 직후 +이 메서드를 호출합니다. {@link android.content.ContentResolver} 개체가 제공자에 액세스하려고 시도할 때까지는 제공자가 생성된 것이 아니라는 점을 유의하십시오.

    - 이와 같은 메서드에는 동일하게 이름 붙여진 + 이와 같은 메서드에는 동일하게 이름 붙여진 {@link android.content.ContentResolver} 메서드와 같은 서명이 있다는 것을 눈여겨 보십시오.

    @@ -548,8 +548,8 @@ update()}

    • 이런 메서드는 모두({@link android.content.ContentProvider#onCreate() onCreate()}는 예외) - 한꺼번에 여러 스레드가 호출할 수 있으므로, 스레드로부터 안전해야 합니다. -다중 스레드에 대한 자세한 내용은 + 한꺼번에 여러 스레드가 호출할 수 있으므로, 스레드로부터 안전해야 합니다. +다중 스레드에 대한 자세한 내용은 프로세스 및 스레드 주제를 참조하십시오.
    • @@ -560,16 +560,16 @@ onCreate()}에서는 긴 작업을 수행하는 것을 삼가는 것이 좋습 섹션에서 더욱 자세히 논의합니다.
    • - 이와 같은 메서드는 반드시 구현해야 하는 것이지만, -예상되는 데이터 유형을 반환하는 것 외에 달리 코드가 해야 할 일은 없습니다. + 이와 같은 메서드는 반드시 구현해야 하는 것이지만, +예상되는 데이터 유형을 반환하는 것 외에 달리 코드가 해야 할 일은 없습니다. 예를 들어 몇몇 테이블에 다른 애플리케이션이 데이터를 삽입하지 못하도록 방지하려고 합니다. 이렇게 하려면, -{@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}로의 +{@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}로의 호출을 무시하고 0을 반환하면 됩니다.

    query() 메서드 구현

    - + {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) ContentProvider.query()} 메서드는 {@link android.database.Cursor} 개체를 반환해야 하고, 그렇지 못할 경우 {@link java.lang.Exception}을 발생시킵니다. SQLite 데이터베이스를 데이터 저장소로 사용하는 경우, @@ -587,7 +587,7 @@ ContentProvider.query()} 메서드는 {@link android.database.Cursor} 개체를

    Android 시스템이 프로세스 경계를 가로질러 {@link java.lang.Exception}을 - 통신으로 전달할 수 있어야 한다는 점을 유의하십시오. Android가 이 작업을 할 수 있는 경우는 + 통신으로 전달할 수 있어야 한다는 점을 유의하십시오. Android가 이 작업을 할 수 있는 경우는 쿼리 오류 처리에 유용할 수 있는 다음과 같은 예외에 해당될 때입니다.

      @@ -608,16 +608,16 @@ ContentProvider.query()} 메서드는 {@link android.database.Cursor} 개체를

      - 이 메서드가 새 행에 대한 콘텐츠 URI를 반환하는 것이 정상입니다. 이것을 구성하려면 새 행의 -_ID(또는 다른 기본 키) 값을 테이블의 콘텐츠 URI에 추가하며, 이때 + 이 메서드가 새 행에 대한 콘텐츠 URI를 반환하는 것이 정상입니다. 이것을 구성하려면 새 행의 +_ID(또는 다른 기본 키) 값을 테이블의 콘텐츠 URI에 추가하며, 이때 {@link android.content.ContentUris#withAppendedId(Uri, long) withAppendedId()}를 사용합니다.

      delete() 메서드 구현

      {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} 메서드의 경우 - 데이터 저장소에서 물리적으로 행을 삭제하지 않아도 됩니다. -제공자와 동기화 어댑터를 함께 사용하고 있는 경우, -삭제된 행을 완전히 제거하기보다는 "삭제" 플래그로 표시하는 방법을 고려해볼 만합니다. + 데이터 저장소에서 물리적으로 행을 삭제하지 않아도 됩니다. +제공자와 동기화 어댑터를 함께 사용하고 있는 경우, +삭제된 행을 완전히 제거하기보다는 "삭제" 플래그로 표시하는 방법을 고려해볼 만합니다. 동기화 어댑터가 삭제된 행을 확인한 다음, 이를 제공자에서 삭제하기 전에 우선 서버에서 제거합니다.

      Update() 메서드 구현

      @@ -633,20 +633,20 @@ ContentProvider.query()}가 사용하는 것과 같은 selection

      onCreate() 메서드 구현

      Android 시스템은 제공자를 시작할 때 {@link android.content.ContentProvider#onCreate() -onCreate()}를 호출합니다. 이 메서드에서는 빠르게 실행되는 초기화만 수행해야 하며, +onCreate()}를 호출합니다. 이 메서드에서는 빠르게 실행되는 초기화만 수행해야 하며, 데이터베이스 생성과 데이터 로딩은 제공자가 실제로 데이터에 대한 요청을 받을 때까지 미뤄두어야 합니다. - + {@link android.content.ContentProvider#onCreate() onCreate()}에서 긴 작업을 수행하면 제공자의 시동 속도가 느려집니다. 이 때문에 제공자에서 다른 애플리케이션으로 전달되는 응답도 따라서 느려집니다.

      예를 들어, SQLite 데이터베이스를 사용하는 경우 -{@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()}에서 +{@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()}에서 새로운 {@link android.database.sqlite.SQLiteOpenHelper} 개체를 생성하고, 그런 다음 데이터베이스를 처음 열 때 SQL 테이블을 생성할 수 있습니다. 이를 용이하게 하기 위해 {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase -getWritableDatabase()}를 처음 호출하면 이것이 자동으로 +getWritableDatabase()}를 처음 호출하면 이것이 자동으로 {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) SQLiteOpenHelper.onCreate()} 메서드를 호출합니다.

      @@ -776,7 +776,7 @@ protected static final class MainDatabaseHelper extends SQLiteOpenHelper {

      텍스트, HTML 또는 JPEG와 같은 보편적인 유형의 데이터라면 -{@link android.content.ContentProvider#getType(Uri) getType()}이 +{@link android.content.ContentProvider#getType(Uri) getType()}이 해당 데이터에 대한 표준 MIME 유형을 반환하는 것이 정상입니다. 이러한 표준 유형의 전체 목록은 IANA MIME 미디어 유형 웹사이트에서 확인할 수 있습니다. @@ -807,17 +807,17 @@ MIME 형식을 반환해야 합니다. 개발자가 <name><type>을 제공합니다. <name> 값은 전체적으로 고유해야 하고, <type> 값은 상응하는 URI 패턴에 고유해야 -합니다. <name>으로 좋은 예는 회사 이름이나 -애플리케이션의 Android 패키지 이름을 들 수 있습니다. -<type>으로 좋은 예는 URI와 연관된 테이블을 식별하는 +합니다. <name>으로 좋은 예는 회사 이름이나 +애플리케이션의 Android 패키지 이름을 들 수 있습니다. +<type>으로 좋은 예는 URI와 연관된 테이블을 식별하는 문자열을 들 수 있습니다.

    - 예를 들어 어떤 제공자의 권한이 -com.example.app.provider이고, 이것이 + 예를 들어 어떤 제공자의 권한이 +com.example.app.provider이고, 이것이 table1이라는 테이블을 노출하는 경우, table1의 여러 행에 대한 MIME 유형은 다음과 같습니다.

    @@ -833,8 +833,8 @@ vnd.android.cursor.item/vnd.com.example.provider.table1
     

    제공자가 파일을 제공하는 경우, {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}를 구현합니다. - 이 메서드는 제공자가 주어진 콘텐츠 URI에 대해 반환할 수 있는 파일에 대한 MIME 유형의 {@link java.lang.String} 배열을 반환합니다. -제공하는 MIME 유형을 MIME 유형 필터 인수 기준으로 필터링해야 + 이 메서드는 제공자가 주어진 콘텐츠 URI에 대해 반환할 수 있는 파일에 대한 MIME 유형의 {@link java.lang.String} 배열을 반환합니다. +제공하는 MIME 유형을 MIME 유형 필터 인수 기준으로 필터링해야 클라이언트가 처리하고자 하는 MIME 유형만 반환할 수 있습니다.

    @@ -850,16 +850,16 @@ ContentProvider.getStreamTypes()} 메서드가 다음과 같은 배열을 반환 { "image/jpeg", "image/png", "image/gif"}

    - 앱이 .jpg 파일에만 관심이 있는 경우에는 + 앱이 .jpg 파일에만 관심이 있는 경우에는 필터 문자열 *\/jpeg으로 {@link android.content.ContentResolver#getStreamTypes(Uri, String) - ContentResolver.getStreamTypes()}를 호출할 수 있습니다. 그러면 + ContentResolver.getStreamTypes()}를 호출할 수 있습니다. 그러면 {@link android.content.ContentProvider#getStreamTypes(Uri, String) ContentProvider.getStreamTypes()}가 다음과 같이 반환하는 것이 정상입니다.

     {"image/jpeg"}
     

    - 제공자가 필터 문자열에서 요청한 MIME 유형 중 제공하는 것이 없는 경우, + 제공자가 필터 문자열에서 요청한 MIME 유형 중 제공하는 것이 없는 경우, {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}가 null을 반환하는 것이 정상입니다.

    @@ -868,76 +868,76 @@ ContentProvider.getStreamTypes()} 메서드가 다음과 같은 배열을 반환

    계약 클래스 구현

    - 계약 클래스는 public final 클래스로, 이 안에 URI, 열 이름, MIME 유형의 -상수 정의 및 제공자에 관련된 다른 메타 데이터가 들어 있습니다. + 계약 클래스는 public final 클래스로, 이 안에 URI, 열 이름, MIME 유형의 +상수 정의 및 제공자에 관련된 다른 메타 데이터가 들어 있습니다. 이 클래스는 URI, 열 이름 등의 실제 값에 변경된 내용이 있더라도 - 제공자에 올바르게 액세스할 수 있도록 보장하여 제공자와 + 제공자에 올바르게 액세스할 수 있도록 보장하여 제공자와 다른 애플리케이션 사이의 계약을 확립합니다.

    - 계약 클래스가 개발자에게 유용한 이유는 또 있습니다. 이 클래스는 보통 자신의 상수 이름으로 -니모닉 이름을 가지기 때문에 개발자가 열 이름 또는 URI에 잘못된 값을 사용할 가능성이 덜합니다. -이것도 클래스의 일종이기 때문에 Javadoc 문서를 포함할 수 있습니다. + 계약 클래스가 개발자에게 유용한 이유는 또 있습니다. 이 클래스는 보통 자신의 상수 이름으로 +니모닉 이름을 가지기 때문에 개발자가 열 이름 또는 URI에 잘못된 값을 사용할 가능성이 덜합니다. +이것도 클래스의 일종이기 때문에 Javadoc 문서를 포함할 수 있습니다. Eclipse와 같은 통합 개발 환경은 계약 클래스의 상수 이름을 자동 완성하고 해당 상수에 대한 Javadoc을 표시할 수 있습니다.

    - 개발자가 애플리케이션에서 계약 클래스의 클래스 파일에 액세스할 수는 없지만 + 개발자가 애플리케이션에서 계약 클래스의 클래스 파일에 액세스할 수는 없지만 여러분이 제공하는 .jar 파일에서 이를 애플리케이션 안으로 정적으로 컴파일링할 수 있습니다.

    - {@link android.provider.ContactsContract} 클래스와 + {@link android.provider.ContactsContract} 클래스와 이에 중첩된 클래스가 계약 클래스의 예시입니다.

    콘텐츠 제공자 권한 구현

    Android 시스템의 모든 측면에 대한 권한과 액세스는 보안 및 권한 주제에 설명되어 있습니다. - 데이터 저장소 주제에서도 + 데이터 저장소 주제에서도 다양한 유형의 저장소에 적용되는 보안 및 권한을 설명하고 있습니다. 간략히 말해 요점은 다음과 같습니다.

    • - 기본적으로, 기기의 내부 저장소에 저장된 데이터 파일은 + 기본적으로, 기기의 내부 저장소에 저장된 데이터 파일은 본인의 애플리케이션과 제공자 전용입니다.
    • - 본인이 생성한 {@link android.database.sqlite.SQLiteDatabase} 데이터베이스는 + 본인이 생성한 {@link android.database.sqlite.SQLiteDatabase} 데이터베이스는 본인의 애플리케이션과 제공자만의 비공개 데이터입니다.
    • 기본적으로 외부 저장소에 저장하는 데이터 파일은 공개이고 -누구나 읽을 수 있습니다. 외부 저장소에 있는 파일로의 액세스를 제공하는 데 콘텐츠 제공자를 쓸 수는 +누구나 읽을 수 있습니다. 외부 저장소에 있는 파일로의 액세스를 제공하는 데 콘텐츠 제공자를 쓸 수는 없습니다. 다른 애플리케이션이 다른 API 호출을 사용하여 해당 파일을 읽고 쓸 수 있기 때문입니다.
    • 기기의 내부 저장소에 있는 파일 또는 SQLite 데이터베이스를 열거나 생성하기 위한 메서드 호출은 -다른 모든 애플리케이션에 읽기 및 쓰기 액세스 권한을 허가할 가능성이 있습니다. +다른 모든 애플리케이션에 읽기 및 쓰기 액세스 권한을 허가할 가능성이 있습니다. 내부 파일이나 데이터베이스를 제공자의 리포지토리로 사용하고 -"누구나 읽을 수 있는" 또는 "누구나 쓸 수 있는" 액세스를 부여하면 -매니페스트에서 제공자에 대해 설정한 권한이 데이터를 보호하지 못합니다. +"누구나 읽을 수 있는" 또는 "누구나 쓸 수 있는" 액세스를 부여하면 +매니페스트에서 제공자에 대해 설정한 권한이 데이터를 보호하지 못합니다. 내부 저장소 안에 있는 파일과 데이터베이스에 대한기본 액세스는 "비공개"이며, 제공자의 리포지토리가 이것을 변경하면 안 됩니다.

    - 데이터로의 액세스를 제어하기 위해 콘텐츠 제공자 권한을 쓰고자 하는 경우, -데이터를 내부 파일, SQLite 데이터베이스 또는 "클라우드"(예: 원격 서버) 안의 + 데이터로의 액세스를 제어하기 위해 콘텐츠 제공자 권한을 쓰고자 하는 경우, +데이터를 내부 파일, SQLite 데이터베이스 또는 "클라우드"(예: 원격 서버) 안의 내부 파일로 저장해야 하고, 파일과 데이터베이스를 애플리케이션만의 비공개로 유지해야 합니다.

    권한 구현

    - 기본 데이터가 비공개라고 하더라도 모든 애플리케이션이 제공자를 읽고 제공자에 쓸 수 있습니다. + 기본 데이터가 비공개라고 하더라도 모든 애플리케이션이 제공자를 읽고 제공자에 쓸 수 있습니다. 기본적으로 제공자에는 권한이 설정되어 있지 않기 때문입니다. 이를 변경하려면, <provider> 요소의 속성이나 하위 요소를 사용하여 -매니페스트 파일에 있는 제공자의 권한을 설정합니다. 권한은 제공자 전체에 적용되도록 설정할 수도 있고, +매니페스트 파일에 있는 제공자의 권한을 설정합니다. 권한은 제공자 전체에 적용되도록 설정할 수도 있고, 특정 테이블에, 또는 심지어 특정 레코드에 적용되게 할 수도 있고 세 가지 모두를 택할 수도 있습니다.

    - 제공자에 대한 권한은 매니페스트 파일에 있는 하나 이상의 + 제공자에 대한 권한은 매니페스트 파일에 있는 하나 이상의 - <permission> 요소로 정의합니다. + <permission> 요소로 정의합니다. 제공자에 고유한 권한을 설정하려면 android:name 속성에 Java 스타일 범위를 사용합니다. 예를 들어 읽기 권한의 이름을 @@ -945,7 +945,7 @@ Eclipse와 같은 통합 개발 환경은 계약 클래스의 상수 이름을

    - 다음 목록은 제공자 권한의 범위를 설명한 것입니다. + 다음 목록은 제공자 권한의 범위를 설명한 것입니다. 제공자 전체에 적용되는 권한부터 시작하여 점차 세분화된 권한이 됩니다. 보다 세부화된 권한이 범위가 큰 것보다 우선합니다.

    @@ -954,9 +954,9 @@ Eclipse와 같은 통합 개발 환경은 계약 클래스의 상수 이름을 단일 읽기-쓰기 제공자 수준 권한
    - 제공자 전체로의 읽기와 쓰기 액세스 양쪽 모두를 제어하는 하나의 권한으로, + 제공자 전체로의 읽기와 쓰기 액세스 양쪽 모두를 제어하는 하나의 권한으로, - <provider> 요소의 + <provider> 요소의 android:permission 속성으로 지정됩니다.
    @@ -978,14 +978,14 @@ Eclipse와 같은 통합 개발 환경은 계약 클래스의 상수 이름을 경로 수준 권한
    - 제공자의 콘텐츠 URI에 대한 읽기, 쓰기 또는 읽기/쓰기 권한입니다. 제어하고자 하는 각 URI를 직접 지정하되, -이때 + 제공자의 콘텐츠 URI에 대한 읽기, 쓰기 또는 읽기/쓰기 권한입니다. 제어하고자 하는 각 URI를 직접 지정하되, +이때 - <provider> 요소의 + <provider> 요소의 - <path-permission> 하위 요소를 사용합니다. 지정하는 콘텐츠 URI마다 -읽기/쓰기 권한, 읽기 권한 또는 쓰기 권한을 하나씩 지정하거나 셋 모두를 지정할 수 있습니다. -읽기 및 쓰기 권한이 읽기/쓰기 권한보다 우선합니다. + <path-permission> 하위 요소를 사용합니다. 지정하는 콘텐츠 URI마다 +읽기/쓰기 권한, 읽기 권한 또는 쓰기 권한을 하나씩 지정하거나 셋 모두를 지정할 수 있습니다. +읽기 및 쓰기 권한이 읽기/쓰기 권한보다 우선합니다. 또한, 경로 수준 권한이 제공자 수준 권한보다 우선합니다.
    @@ -993,18 +993,18 @@ Eclipse와 같은 통합 개발 환경은 계약 클래스의 상수 이름을
    애플리케이션에 임시 액세스를 허용하는 권한 수준입니다. -해당 애플리케이션에 일반적으로 요구되는 권한이 없더라도 무관합니다. +해당 애플리케이션에 일반적으로 요구되는 권한이 없더라도 무관합니다. 임시 액세스 기능은 매니페스트에서 요청해야 하는 -권한과 애플리케이션 개수를 줄여줍니다. 임시 권한을 사용하는 경우, -제공자에 대하여 "영구" 권한을 필요로하는 애플리케이션은 +권한과 애플리케이션 개수를 줄여줍니다. 임시 권한을 사용하는 경우, +제공자에 대하여 "영구" 권한을 필요로하는 애플리케이션은 모든 데이터에 지속적으로 액세스하는 것들뿐입니다.

    - 이메일 제공자와 앱을 구현할 때 필요한 권한을 예로 들어 보겠습니다. -외부 이미지 뷰어 애플리케이션으로 하여금 제공자에서 보낸 사진 첨부 파일을 -표시하도록 허용하고자 한다고 가정합니다. 권한을 요구하지 않고 이미지 뷰어에 필수 액세스를 부여하려면, -사진에 대한 콘텐츠 URI에 해단되는 임시 권한을 설정하십시오. + 이메일 제공자와 앱을 구현할 때 필요한 권한을 예로 들어 보겠습니다. +외부 이미지 뷰어 애플리케이션으로 하여금 제공자에서 보낸 사진 첨부 파일을 +표시하도록 허용하고자 한다고 가정합니다. 권한을 요구하지 않고 이미지 뷰어에 필수 액세스를 부여하려면, +사진에 대한 콘텐츠 URI에 해단되는 임시 권한을 설정하십시오. 사용자가 사진을 표시하기를 원할 때 앱이 사진의 콘텐츠 URI와 권한 플래그를 포함하는 인텐트를 -이미지 뷰어에 보내도록 이메일 앱을 설계합니다. 그러면 해당 이미지 뷰어가 +이미지 뷰어에 보내도록 이메일 앱을 설계합니다. 그러면 해당 이미지 뷰어가 이메일 제공자에 사진 검색을 쿼리할 수 있으며, 이 뷰어에 제공자에 대한 정상적인 읽기 권한이 없더라도 무방합니다.

    @@ -1017,29 +1017,29 @@ Eclipse와 같은 통합 개발 환경은 계약 클래스의 상수 이름을 <grant-uri-permission> 하위 요소를 - <provider> 요소에 추가하면 됩니다. 임시 권한을 사용하는 경우, + <provider> 요소에 추가하면 됩니다. 임시 권한을 사용하는 경우, 제공자에서 콘텐츠 URI에 대한 지원을 제거할 때마다 {@link android.content.Context#revokeUriPermission(Uri, int) - Context.revokeUriPermission()}을 호출해야 합니다. + Context.revokeUriPermission()}을 호출해야 합니다. 그러면 콘텐츠 URI가 임시 권한과 연관됩니다.

    속성의 값에 따라 제공자에 액세스 가능한 정도가 결정됩니다. - 속성이 true로 설정되어 있는 경우라면 -시스템이 제공자 전체에 임시 권한을 허용하며, 제공자 수준 또는 + 속성이 true로 설정되어 있는 경우라면 +시스템이 제공자 전체에 임시 권한을 허용하며, 제공자 수준 또는 경로 수준 권한에서 요구하는 다른 모든 권한을 재정의합니다.

    - 이 플래그가 false로 설정되면, 반드시 + 이 플래그가 false로 설정되면, 반드시 <grant-uri-permission> 하위 요소를 - <provider> 요소에 추가해야 합니다. 각 하위 요소는 임시 권한을 허용한 + <provider> 요소에 추가해야 합니다. 각 하위 요소는 임시 권한을 허용한 콘텐츠 URI(하나 또는 여러 개)를 나타냅니다.

    애플리케이션에 임시 액세스를 위임하려면, 인텐트에 {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} 또는 -{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} 플래그, 또는 둘 모두가 들어 있어야 합니다. 이들은 +{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} 플래그, 또는 둘 모두가 들어 있어야 합니다. 이들은 {@link android.content.Intent#setFlags(int) setFlags()} 메서드로 설정됩니다.

    @@ -1087,7 +1087,7 @@ android:authorities}) 권한

    - 제공자의 데이터에 액세스하기 위해 다른 애플리케이션이 + 제공자의 데이터에 액세스하기 위해 다른 애플리케이션이 반드시 가지고 있어야 하는 권한을 나타내는 속성입니다.
    • @@ -1108,7 +1108,7 @@ android:authorities})

    - 각종 권한과 그에 상응하는 속성은 + 각종 권한과 그에 상응하는 속성은 콘텐츠 제공자 권한 구현 섹션에 자세히 설명되어 있습니다.

    @@ -1117,7 +1117,7 @@ android:authorities}) 시작 및 제어 속성
    - 이와 같은 속성은 Android 시스템이 제공자를 시작하는 방법과 시점, + 이와 같은 속성은 Android 시스템이 제공자를 시작하는 방법과 시점, 제공자의 프로세스 특징과 기타 런타임 설정 등을 결정합니다.
    • @@ -1130,12 +1130,12 @@ android:authorities})
    • - android:initOrder: 같은 프로세스 내의 다른 제공자와 비교하여 + android:initOrder: 같은 프로세스 내의 다른 제공자와 비교하여 이 제공자가 시작되어야 하는 순서입니다.
    • - android:multiProcess: 클라이언트를 호출하는 것과 + android:multiProcess: 클라이언트를 호출하는 것과 같은 프로세스에서 시스템이 제공자를 시작할 수 있게 해주는 플래그입니다.
    • @@ -1145,7 +1145,7 @@ android:authorities})
    • - android:syncable: 제공자의 데이터가 + android:syncable: 제공자의 데이터가 서버에 있는 데이터와 동기화될 예정임을 나타내는 플래그입니다.
    @@ -1165,7 +1165,7 @@ android:authorities})
  • android:icon: 제공자의 아이콘이 들어 있는 드로어블 리소스입니다. - 이 아이콘은 + 이 아이콘은 설정 > > 모두에 있는 앱 목록에서 제공자의 레이블 옆에 표시됩니다.
  • @@ -1187,28 +1187,28 @@ android:authorities})

    인텐트 및 데이터 액세스

    애플리케이션이 콘텐츠 제공자에 간접적으로 액세스하려면 {@link android.content.Intent}를 사용하면 됩니다. - 이 애플리케이션은 {@link android.content.ContentResolver} 또는 -{@link android.content.ContentProvider}의 메서드 중 어느 하나도 호출하지 않습니다. -대신, 액티비티를 시작하는 인텐트를 전송합니다. 이 인텐트는 제공자가 소유한 애플리케이션의 일부인 경우가 많습니다. -대상 액티비티가 데이터를 자체 UI에서 검색하고 표시하는 역할을 맡습니다. + 이 애플리케이션은 {@link android.content.ContentResolver} 또는 +{@link android.content.ContentProvider}의 메서드 중 어느 하나도 호출하지 않습니다. +대신, 액티비티를 시작하는 인텐트를 전송합니다. 이 인텐트는 제공자가 소유한 애플리케이션의 일부인 경우가 많습니다. +대상 액티비티가 데이터를 자체 UI에서 검색하고 표시하는 역할을 맡습니다. 인텐트의 동작에 따라 대상 액티비티가 사용자에게 프롬프트를 표시하여 제공자의 데이터를 수정하도록 할 수도 있습니다. 인텐트에는 대상 액티비티가 UI에 표시하는 "추가" 데이터가 들어 있을 수도 있습니다. -그러면 사용자에게 이 데이터를 변경할 수 있는 옵션이 주어지고, 그런 다음 이를 사용하여 +그러면 사용자에게 이 데이터를 변경할 수 있는 옵션이 주어지고, 그런 다음 이를 사용하여 제공자 내의 데이터를 수정할 수 있습니다.

    - 데이터 무결성을 보장하는 데 유용한 것을 원하면 인텐트 액세스를 사용하는 것이 좋습니다. -엄격하게 정의된 비즈니스 논리에 따라 데이터가 삽입, 업데이트되고 삭제되는 것이 제공자를 크게 좌우할 수도 있습니다. -이런 경우에 해당되면, 다른 애플리케이션에 데이터를 직접 수정하도록 허용하면 데이터가 잘못되는 + 데이터 무결성을 보장하는 데 유용한 것을 원하면 인텐트 액세스를 사용하는 것이 좋습니다. +엄격하게 정의된 비즈니스 논리에 따라 데이터가 삽입, 업데이트되고 삭제되는 것이 제공자를 크게 좌우할 수도 있습니다. +이런 경우에 해당되면, 다른 애플리케이션에 데이터를 직접 수정하도록 허용하면 데이터가 잘못되는 결과를 초래할 수 있습니다. 개발자들에게 인텐트 액세스 사용을 허용하려면, 그 내용을 철저히 기록해두어야 합니다. - 개발자들에게 자기 애플리케이션의 UI를 사용한 인텐트 액세스가 + 개발자들에게 자기 애플리케이션의 UI를 사용한 인텐트 액세스가 코드로 데이터를 수정하려 시도하는 것보다 나은 이유를 설명해주십시오.

    제공자의 데이터를 수정하고자 하는 수신되는 인텐트 처리도 다른 인텐트 처리와 다를 바가 없습니다. - 인텐트 사용에 대한 자세한 내용은 + 인텐트 사용에 대한 자세한 내용은 인텐트 및 인텐트 필터 주제를 읽으면 확인할 수 있습니다.

    diff --git a/docs/html-intl/intl/ko/guide/topics/providers/content-providers.jd b/docs/html-intl/intl/ko/guide/topics/providers/content-providers.jd index ce98840e16db4c15449dfdaf84fe94bcc9282f7e..8671f7b71f91b7db2fb2551817dda8fce690175a 100644 --- a/docs/html-intl/intl/ko/guide/topics/providers/content-providers.jd +++ b/docs/html-intl/intl/ko/guide/topics/providers/content-providers.jd @@ -47,31 +47,31 @@ page.title=콘텐츠 제공자

    - 콘텐츠 제공자는 구조화된 데이터 세트로의 액세스를 관리합니다. -데이터를 캡슐화하여 데이터 보안을 정의하는 데 필요한 메커니즘을 제공하기도 합니다. + 콘텐츠 제공자는 구조화된 데이터 세트로의 액세스를 관리합니다. +데이터를 캡슐화하여 데이터 보안을 정의하는 데 필요한 메커니즘을 제공하기도 합니다. 콘텐츠 제공자는 한 프로세스의 데이터에 다른 프로세스에서 실행 중인 코드를 연결하는 표준 인터페이스입니다.

    - 콘텐츠 제공자 내의 데이터에 액세스하고자 하는 경우, + 콘텐츠 제공자 내의 데이터에 액세스하고자 하는 경우, 애플리케이션의 {@link android.content.Context}에 있는 {@link android.content.ContentResolver} 개체를 사용하여 클라이언트로서 제공자와 통신을 주고받으면 됩니다. - {@link android.content.ContentResolver} 개체가 제공자 개체와 통신하며, 이 개체는 -{@link android.content.ContentProvider}를 구현하는 클래스의 인스턴스입니다. + {@link android.content.ContentResolver} 개체가 제공자 개체와 통신하며, 이 개체는 +{@link android.content.ContentProvider}를 구현하는 클래스의 인스턴스입니다. 제공자 개체가 클라이언트로부터 데이터 요청을 받아 요청된 작업을 수행하며 결과를 반환합니다.

    데이터를 다른 애플리케이션과 공유할 생각이 없으면 나름의 제공자를 개발하지 않아도 됩니다. 그러나, 자체 애플리케이션에서 사용자 지정 검색 제안을 제공하려면 나름의 제공자가 꼭 필요합니다. - 또한, 복잡한 데이터나 파일을 자신의 애플리케이션에서 다른 애플리케이션으로 복사하여 붙여넣고자 하는 경우에도 + 또한, 복잡한 데이터나 파일을 자신의 애플리케이션에서 다른 애플리케이션으로 복사하여 붙여넣고자 하는 경우에도 나름의 제공자가 필요합니다.

    - Android 자체에 오디오, 동영상, 이미지 및 개인 연락처 정보 등의 데이터를 관리하는 콘텐츠 제공자가 -포함되어 있습니다. 그중 몇 가지를 목록으로 나열한 것을 + Android 자체에 오디오, 동영상, 이미지 및 개인 연락처 정보 등의 데이터를 관리하는 콘텐츠 제공자가 +포함되어 있습니다. 그중 몇 가지를 목록으로 나열한 것을 android.provider - 패키지에 대한 참조 문서에서 확인할 수 있습니다. 이와 같은 제공자는 몇 가지 제약이 있지만, + 패키지에 대한 참조 문서에서 확인할 수 있습니다. 이와 같은 제공자는 몇 가지 제약이 있지만, 어느 Android 애플리케이션에나 액세스할 수 있습니다.

    다음 주제에서는 콘텐츠 제공자에 대해 좀 더 자세히 설명합니다. diff --git a/docs/html-intl/intl/ko/guide/topics/providers/document-provider.jd b/docs/html-intl/intl/ko/guide/topics/providers/document-provider.jd index e356e22d17c9b76358bd8271a00e09df5b61c70d..665a72a755cfeabbfbc75e6f5c4f067b15bc7856 100644 --- a/docs/html-intl/intl/ko/guide/topics/providers/document-provider.jd +++ b/docs/html-intl/intl/ko/guide/topics/providers/document-provider.jd @@ -75,96 +75,96 @@ StorageClient

  • -

    Android 4.4(API 레벨 19)에서는 저장소 액세스 프레임워크(SAF)를 처음 도입하게 되었습니다. SAF는 -사용자가 선호하는 문서 저장소 제공자 전체를 걸쳐 문서, 이미지 및 각종 다른 파일을 -탐색하고 여는 작업을 간편하게 만들어줍니다. 표준형의, 사용하기 쉬운 UI로 +

    Android 4.4(API 레벨 19)에서는 저장소 액세스 프레임워크(SAF)를 처음 도입하게 되었습니다. SAF는 +사용자가 선호하는 문서 저장소 제공자 전체를 걸쳐 문서, 이미지 및 각종 다른 파일을 +탐색하고 여는 작업을 간편하게 만들어줍니다. 표준형의, 사용하기 쉬운 UI로 사용자가 각종 앱과 제공자에 걸쳐 일관된 방식으로 파일을 탐색하고 최근 내용에 액세스할 수 있게 해줍니다.

    -

    클라우드 또는 로컬 저장소 서비스가 이 에코시스템에 참가하려면 자신의 서비스를 캡슐화하는 -{@link android.provider.DocumentsProvider}를 구현하면 됩니다. -제공자의 문서에 액세스해야 하는 클라이언트 앱의 경우 단 몇 줄의 코드만으로 +

    클라우드 또는 로컬 저장소 서비스가 이 에코시스템에 참가하려면 자신의 서비스를 캡슐화하는 +{@link android.provider.DocumentsProvider}를 구현하면 됩니다. +제공자의 문서에 액세스해야 하는 클라이언트 앱의 경우 단 몇 줄의 코드만으로 SAF와 통합할 수 있습니다.

    SAF에는 다음과 같은 항목이 포함됩니다.

    • 문서 제공자—일종의 콘텐츠 제공자로 -저장소 서비스(예: Google Drive 등)로 하여금 자신이 관리하는 파일을 드러내도록 허용합니다. 문서 제공자는 -{@link android.provider.DocumentsProvider} 클래스의 하위 클래스로 구현됩니다. -문서 제공자 스키마는 기존의 파일 계층을 근거로 하지만, -문서 제공자가 데이터를 저장하는 물리적인 방법은 개발자가 선택하기 나름입니다. -Android 플랫폼에는 내장된 문서 제공자가 여러 개 있습니다. +저장소 서비스(예: Google Drive 등)로 하여금 자신이 관리하는 파일을 드러내도록 허용합니다. 문서 제공자는 +{@link android.provider.DocumentsProvider} 클래스의 하위 클래스로 구현됩니다. +문서 제공자 스키마는 기존의 파일 계층을 근거로 하지만, +문서 제공자가 데이터를 저장하는 물리적인 방법은 개발자가 선택하기 나름입니다. +Android 플랫폼에는 내장된 문서 제공자가 여러 개 있습니다. 예를 들어 다운로드, 이미지 및 비디오 등입니다.
    • 클라이언트 앱—일종의 사용자 지정 앱으로 {@link android.content.Intent#ACTION_OPEN_DOCUMENT} 및/또는 -{@link android.content.Intent#ACTION_CREATE_DOCUMENT} 인텐트를 호출하고, +{@link android.content.Intent#ACTION_CREATE_DOCUMENT} 인텐트를 호출하고, 문서 제공자가 반환하는 파일을 수신합니다.
    • -
    • 선택기—일종의 시스템 UI로 사용자가 클라이언트 앱의 +
    • 선택기—일종의 시스템 UI로 사용자가 클라이언트 앱의 검색 기준을 만족하는 모든 문서 제공자에서 문서에 액세스할 수 있도록 해줍니다.

    SAF가 제공하는 기능을 몇 가지 예로 들면 다음과 같습니다.

    • 사용자들로 하여금 하나의 앱만이 아니라 모든 문서 제공자에서 콘텐츠를 탐색할 수 있게 해줍니다.
    • -
    • 여러분의 앱이 문서 제공자가 소유한 문서에 대한 장기적, 영구적 액세스 권한을 가질 수 있도록 -해줍니다. 이 액세스 권한을 통해 사용자가 제공자에 있는 파일을 추가, 편집, +
    • 여러분의 앱이 문서 제공자가 소유한 문서에 대한 장기적, 영구적 액세스 권한을 가질 수 있도록 +해줍니다. 이 액세스 권한을 통해 사용자가 제공자에 있는 파일을 추가, 편집, 저장 및 삭제할 수 있습니다.
    • -
    • 여러 개의 사용자 계정을 지원하며 USB 저장소 제공자와 같은 임시 루트도 지원합니다. +
    • 여러 개의 사용자 계정을 지원하며 USB 저장소 제공자와 같은 임시 루트도 지원합니다. 이는 드라이브가 연결되어 있을 때만 나타납니다.

    개요

    -

    SAF는 {@link android.provider.DocumentsProvider} 클래스의 -하위 클래스인 콘텐츠 제공자를 중심으로 둘러싸고 있습니다. 데이터는 문서 제공자 내에서 일반적인 파일 계층으로 +

    SAF는 {@link android.provider.DocumentsProvider} 클래스의 +하위 클래스인 콘텐츠 제공자를 중심으로 둘러싸고 있습니다. 데이터는 문서 제공자 내에서 일반적인 파일 계층으로 구조화됩니다.

    data model

    -

    그림 1. 문서 제공자 데이터 모델입니다. 루트 하나가 하나의 문서를 가리키며, +

    그림 1. 문서 제공자 데이터 모델입니다. 루트 하나가 하나의 문서를 가리키며, 이는 다시 트리 전체의 팬아웃을 시작합니다.

    다음 내용을 참고하십시오.

      -
    • 각 문서 제공자는 하나 이상의 "루트"를 보고합니다. +
    • 각 문서 제공자는 하나 이상의 "루트"를 보고합니다. 이는 문서 트리 속을 탐색할 시작 지점입니다. -각 루트에는 고유한 {@link android.provider.DocumentsContract.Root#COLUMN_ROOT_ID}가 있으며, -이는 해당 루트 아래의 콘텐츠를 나타내는 문서(디렉터리)를 +각 루트에는 고유한 {@link android.provider.DocumentsContract.Root#COLUMN_ROOT_ID}가 있으며, +이는 해당 루트 아래의 콘텐츠를 나타내는 문서(디렉터리)를 가리킵니다. -루트는 설계상 동적으로 만들어져 있어 여러 개의 계정, 임시 USB 저장소 기기 +루트는 설계상 동적으로 만들어져 있어 여러 개의 계정, 임시 USB 저장소 기기 또는 사용자 로그인/로그아웃 등과 같은 경우를 지원하도록 되어 있습니다.
    • -
    • 각 루트 아래에 문서가 하나씩 있습니다. 해당 문서는 1부터 N까지의 문서를 가리키는데, +
    • 각 루트 아래에 문서가 하나씩 있습니다. 해당 문서는 1부터 N까지의 문서를 가리키는데, 이는 각각 1부터 N의 문서를 가리킬 수 있습니다.
    • -
    • 각 저장소의 백엔드가 -개별적인 파일과 디렉터리를 고유한 -{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID}로 -참조하여 드러냅니다.문서 ID는 고유해야 하며 한 번 발행되고 나면 변경되지 않습니다. +
    • 각 저장소의 백엔드가 +개별적인 파일과 디렉터리를 고유한 +{@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID}로 +참조하여 드러냅니다.문서 ID는 고유해야 하며 한 번 발행되고 나면 변경되지 않습니다. 이들은 기기 재부팅을 통괄하여 영구적인 URI 허가에 사용되기 때문입니다.
    • -
    • 문서는 열 수 있는 파일이거나(특정 MIME 유형으로), +
    • 문서는 열 수 있는 파일이거나(특정 MIME 유형으로), 추가 문서가 들어있는 디렉터리일 수 있습니다( {@link android.provider.DocumentsContract.Document#MIME_TYPE_DIR} MIME 유형으로).
    • -
    • 각 문서는 서로 다른 기능을 가지고 있을 수 있습니다. 이는 -{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS COLUMN_FLAGS}에서 설명한 것과 같습니다. - 예를 들어 {@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE}, -{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE} 및 -{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_THUMBNAIL} 등입니다. -같은 {@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID}가 +
    • 각 문서는 서로 다른 기능을 가지고 있을 수 있습니다. 이는 +{@link android.provider.DocumentsContract.Document#COLUMN_FLAGS COLUMN_FLAGS}에서 설명한 것과 같습니다. + 예를 들어 {@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_WRITE}, +{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE} 및 +{@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_THUMBNAIL} 등입니다. +같은 {@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID}가 여러 디렉터리에 포함되어 있을 수도 있습니다.

    제어 흐름

    -

    위에서 언급한 바와 같이, 문서 제공자 데이터 모델은 일반적인 -파일 계층을 기반으로 합니다. 그러나, 데이터를 물리적으로 저장하는 방식은 마음대로 선택할 수 있습니다. 다만 -{@link android.provider.DocumentsProvider} API를 통해 액세스할 수 있기만 하면 됩니다. +

    위에서 언급한 바와 같이, 문서 제공자 데이터 모델은 일반적인 +파일 계층을 기반으로 합니다. 그러나, 데이터를 물리적으로 저장하는 방식은 마음대로 선택할 수 있습니다. 다만 +{@link android.provider.DocumentsProvider} API를 통해 액세스할 수 있기만 하면 됩니다. 예를 들어, 데이터를 저장하기 위해 태그 기반 클라우드 저장소를 사용해도 됩니다.

    -

    그림 2는 사진 앱이 SAF를 사용하여 저장된 데이터에 액세스할 수 있는 방법을 +

    그림 2는 사진 앱이 SAF를 사용하여 저장된 데이터에 액세스할 수 있는 방법을 예시로 나타낸 것입니다.

    app

    @@ -174,31 +174,31 @@ Android 플랫폼에는 내장된 문서 제공자가 여러 개 있습니다.
    • SAF에서는 제공자와 클라이언트가 직접 상호 작용하지 않습니다. - 클라이언트가 파일과 상호 작용하기 위한 권한을 요청합니다(다시 말해, + 클라이언트가 파일과 상호 작용하기 위한 권한을 요청합니다(다시 말해, 파일을 읽고, 편집하고 생성 또는 삭제할 권한을 말합니다).
    • -
    • 상호 작용은 애플리케이션(이 예시에서는 주어진 사진 앱)이 인텐트 -{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 또는 {@link android.content.Intent#ACTION_CREATE_DOCUMENT}를 실행시키면 시작합니다. 이 인텐트에는 -기준을 한층 더 정밀하게 하기 위한 필터가 포함될 수 있습니다. 예를 들어, "열 수 있는 파일 중에서 +
    • 상호 작용은 애플리케이션(이 예시에서는 주어진 사진 앱)이 인텐트 +{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 또는 {@link android.content.Intent#ACTION_CREATE_DOCUMENT}를 실행시키면 시작합니다. 이 인텐트에는 +기준을 한층 더 정밀하게 하기 위한 필터가 포함될 수 있습니다. 예를 들어, "열 수 있는 파일 중에서 '이미지' MIME 유형을 가진 파일을 모두 주세요"라고 할 수 있습니다.
    • -
    • 인텐트가 실행되면 시스템 선택기가 각각의 등록된 제공자로 이동하여 사용자에게 +
    • 인텐트가 실행되면 시스템 선택기가 각각의 등록된 제공자로 이동하여 사용자에게 일치하는 콘텐츠 루트를 보여줍니다.
    • -
    • 선택기는 사용자에게 문서에 액세스하는 데 쓰는 표준 인터페이스를 부여합니다. 이는 -기본 문서 제공자 사이에 큰 차이가 있더라도 무관합니다. 예를 들어, 그림 2는 +
    • 선택기는 사용자에게 문서에 액세스하는 데 쓰는 표준 인터페이스를 부여합니다. 이는 +기본 문서 제공자 사이에 큰 차이가 있더라도 무관합니다. 예를 들어, 그림 2는 Google Drive 제공자, USB 제공자와 클라우드 제공자를 나타낸 것입니다.
    -

    그림 3은 이미지를 검색 중인 사용자가 Google Drive 계정을 선택한 +

    그림 3은 이미지를 검색 중인 사용자가 Google Drive 계정을 선택한 선택기를 나타낸 것입니다.

    picker

    그림 3. 선택기

    -

    사용자가 Google Drive를 선택하면 이미지가 그림 4에 나타난 것처럼 -표시됩니다. 그때부터 사용자는 제공자와 클라이언트 앱이 지원하는 방식이라면 어떤 식으로든 +

    사용자가 Google Drive를 선택하면 이미지가 그림 4에 나타난 것처럼 +표시됩니다. 그때부터 사용자는 제공자와 클라이언트 앱이 지원하는 방식이라면 어떤 식으로든 이들 이미지와 상호 작용할 수 있게 됩니다.

    picker

    @@ -207,45 +207,45 @@ Google Drive 제공자, USB 제공자와 클라우드 제공자를 나타낸 것

    클라이언트 앱 작성

    -

    Android 4.3 이하에서는 앱이 또 다른 앱에서 파일을 검색할 수 있도록 하려면 +

    Android 4.3 이하에서는 앱이 또 다른 앱에서 파일을 검색할 수 있도록 하려면 {@link android.content.Intent#ACTION_PICK} - 또는 {@link android.content.Intent#ACTION_GET_CONTENT}와 같은 인텐트를 호출해야만 했습니다. 그런 다음 -파일을 선택할 앱을 하나 선택하고, 선택한 앱이 사용자 인터페이스를 제공하여야 사용자가 + 또는 {@link android.content.Intent#ACTION_GET_CONTENT}와 같은 인텐트를 호출해야만 했습니다. 그런 다음 +파일을 선택할 앱을 하나 선택하고, 선택한 앱이 사용자 인터페이스를 제공하여야 사용자가 이용 가능한 파일 중에서 탐색하고 선택할 수 있었습니다.

    -

    Android 4.4 이상에는 -{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 인텐트를 사용할 수 있다는 추가 옵션이 있습니다. -이는 시스템이 제어하는 선택기를 표시하여 사용자가 다른 앱에서 이용할 수 있게 만든 파일을 -모두 탐색할 수 있게 해줍니다. 이 하나의 UI로부터 +

    Android 4.4 이상에는 +{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 인텐트를 사용할 수 있다는 추가 옵션이 있습니다. +이는 시스템이 제어하는 선택기를 표시하여 사용자가 다른 앱에서 이용할 수 있게 만든 파일을 +모두 탐색할 수 있게 해줍니다. 이 하나의 UI로부터 사용자는 지원되는 모든 앱에서 파일을 선택할 수 있는 것입니다.

    -

    {@link android.content.Intent#ACTION_OPEN_DOCUMENT}는 -{@link android.content.Intent#ACTION_GET_CONTENT}를 +

    {@link android.content.Intent#ACTION_OPEN_DOCUMENT}는 +{@link android.content.Intent#ACTION_GET_CONTENT}를 대체할 목적으로 만들어진 것이 아닙니다. 어느 것을 사용해야 할지는 각자의 앱에 필요한 것이 무엇인지에 좌우됩니다.

      -
    • 앱이 단순히 데이터를 읽고/가져오기만을 바란다면 -{@link android.content.Intent#ACTION_GET_CONTENT}를 사용하십시오. +
    • 앱이 단순히 데이터를 읽고/가져오기만을 바란다면 +{@link android.content.Intent#ACTION_GET_CONTENT}를 사용하십시오. 이 방식을 사용하면 앱은 이미지 파일과 같은 데이터 사본을 가져오게 됩니다.
    • -
    • 앱이 문서 제공자가 보유한 문서에 장기적, 영구적 액세스 권한을 가지기를 바라는 경우 +
    • 앱이 문서 제공자가 보유한 문서에 장기적, 영구적 액세스 권한을 가지기를 바라는 경우 {@link android.content.Intent#ACTION_OPEN_DOCUMENT}를 사용하십시오. - 일례로 사용자들에게 문서 제공자에 저장된 이미지를 편집할 수 있게 해주는 + 일례로 사용자들에게 문서 제공자에 저장된 이미지를 편집할 수 있게 해주는 사진 편집 앱을 들 수 있겠습니다.
    -

    이 섹션에서는 -{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 및 +

    이 섹션에서는 +{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 및 {@link android.content.Intent#ACTION_CREATE_DOCUMENT} 인텐트를 근거로 클라이언트 앱을 작성하는 방법을 설명합니다.

    -다음 조각에서는 {@link android.content.Intent#ACTION_OPEN_DOCUMENT}를 -사용하여 이미지 파일이 들어 있는 문서 제공자를 +다음 조각에서는 {@link android.content.Intent#ACTION_OPEN_DOCUMENT}를 +사용하여 이미지 파일이 들어 있는 문서 제공자를 검색합니다.

    private static final int READ_REQUEST_CODE = 42;
    @@ -277,7 +277,7 @@ public void performFileSearch() {
     
  • 앱이 {@link android.content.Intent#ACTION_OPEN_DOCUMENT} 인텐트를 실행시키면 이는 일치하는 문서 제공자를 모두 표시하는 선택기를 시작합니다.
  • -
  • {@link android.content.Intent#CATEGORY_OPENABLE} 카테고리를 +
  • {@link android.content.Intent#CATEGORY_OPENABLE} 카테고리를 인텐트에 추가하면 결과를 필터링하여 이미지 파일 등 열 수 있는 문서만 표시합니다.
  • {@code intent.setType("image/*")} 문으로 한층 더 필터링을 수행하여 @@ -286,10 +286,10 @@ MIME 데이터 유형이 이미지인 문서만 표시하도록 합니다.
  • 결과 처리

    -

    사용자가 선택기에서 문서를 선택하면 -{@link android.app.Activity#onActivityResult onActivityResult()}가 호출됩니다. +

    사용자가 선택기에서 문서를 선택하면 +{@link android.app.Activity#onActivityResult onActivityResult()}가 호출됩니다. 선택한 문서를 가리키는 URI는 {@code resultData} -매개변수 안에 들어있습니다. 이 URI를 {@link android.content.Intent#getData getData()}를 사용하여 추출합니다. +매개변수 안에 들어있습니다. 이 URI를 {@link android.content.Intent#getData getData()}를 사용하여 추출합니다. 일단 이것을 가지게 되면 이를 사용하여 사용자가 원하는 문서를 검색하면 됩니다. 예:

    @@ -318,7 +318,7 @@ public void onActivityResult(int requestCode, int resultCode,

    문서 메타데이터 살펴보기

    -

    문서의 URI를 얻은 다음에는 그 문서의 메타데이터에 액세스할 수 있습니다. 이 +

    문서의 URI를 얻은 다음에는 그 문서의 메타데이터에 액세스할 수 있습니다. 이 조각은 해당 URI가 나타내는 문서의 메타데이터를 가져와 다음과 같이 기록합니다.

    public void dumpImageMetaData(Uri uri) {
    @@ -365,7 +365,7 @@ public void onActivityResult(int requestCode, int resultCode,
     
     

    문서 열기

    -

    문서의 URI를 얻은 다음에는 문서를 열 수도 있고 원하는 대로 무엇이든 +

    문서의 URI를 얻은 다음에는 문서를 열 수도 있고 원하는 대로 무엇이든 할 수 있습니다.

    비트맵

    @@ -382,14 +382,14 @@ public void onActivityResult(int requestCode, int resultCode, }
    -

    이 작업을 UI 스레드에서 해서는 안 된다는 점을 유의하십시오. 이것은 배경에서 하되, -{@link android.os.AsyncTask}를 사용합니다. 비트맵을 열고 나면 이를 +

    이 작업을 UI 스레드에서 해서는 안 된다는 점을 유의하십시오. 이것은 배경에서 하되, +{@link android.os.AsyncTask}를 사용합니다. 비트맵을 열고 나면 이를 {@link android.widget.ImageView}로 표시할 수 있습니다.

    InputStream 가져오기

    -

    다음은 URI에서 {@link java.io.InputStream}을 가져오는 방법을 예시로 나타낸 것입니다. 이 조각에서 +

    다음은 URI에서 {@link java.io.InputStream}을 가져오는 방법을 예시로 나타낸 것입니다. 이 조각에서 파일의 줄이 문자열로 읽히고 있습니다.

    private String readTextFromUri(Uri uri) throws IOException {
    @@ -409,9 +409,9 @@ public void onActivityResult(int requestCode, int resultCode,
     
     

    새 문서 생성하기

    -

    개발자의 앱은 문서 제공자에서 새 문서를 생성할 수 있습니다. 이때 +

    개발자의 앱은 문서 제공자에서 새 문서를 생성할 수 있습니다. 이때 {@link android.content.Intent#ACTION_CREATE_DOCUMENT} - 인텐트를 사용하면 됩니다. 파일을 생성하려면 인텐트에 MIME 유형과 파일 이름을 부여하고, + 인텐트를 사용하면 됩니다. 파일을 생성하려면 인텐트에 MIME 유형과 파일 이름을 부여하고, 고유한 요청 코드로 이를 시작하면 됩니다. 나머지는 여러분 대신 알아서 해드립니다.

    @@ -440,15 +440,15 @@ private void createFile(String mimeType, String fileName) { }
    -

    새 문서를 생성하고 나면 -{@link android.app.Activity#onActivityResult onActivityResult()}에서 URI를 가져와 거기에 계속해서 +

    새 문서를 생성하고 나면 +{@link android.app.Activity#onActivityResult onActivityResult()}에서 URI를 가져와 거기에 계속해서 쓸 수 있습니다.

    문서 삭제하기

    -

    어느 문서에 대한 URI가 있고 해당 문서의 +

    어느 문서에 대한 URI가 있고 해당 문서의 {@link android.provider.DocumentsContract.Document#COLUMN_FLAGS Document.COLUMN_FLAGS} -에 +에 {@link android.provider.DocumentsContract.Document#FLAG_SUPPORTS_DELETE SUPPORTS_DELETE}가 들어 있는 경우, 해당 문서를 삭제할 수 있습니다. 예:

    @@ -459,9 +459,9 @@ DocumentsContract.deleteDocument(getContentResolver(), uri);

    문서 편집하기

    준비된 텍스트 문서를 편집하는 데 SAF를 사용할 수 있습니다. -이 조각은 -{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 인텐트를 실행하며 -{@link android.content.Intent#CATEGORY_OPENABLE} 카테고리를 사용해 +이 조각은 +{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 인텐트를 실행하며 +{@link android.content.Intent#CATEGORY_OPENABLE} 카테고리를 사용해 열 수 있는 문서만 표시하도록 합니다. 이것을 한층 더 필터링하여 텍스트 파일만 표시하게 하려면 다음과 같이 합니다.

    @@ -486,10 +486,10 @@ private static final int EDIT_REQUEST_CODE = 44;
     

    다음으로, {@link android.app.Activity#onActivityResult onActivityResult()} -(결과 처리 참조)에서 코드를 호출하여 편집 작업을 수행하도록 하면 됩니다. +(결과 처리 참조)에서 코드를 호출하여 편집 작업을 수행하도록 하면 됩니다. 다음 조각은 {@link android.content.ContentResolver}에서 {@link java.io.FileOutputStream} -을 가져온 것입니다. 이것은 기본적으로 "쓰기" 모드를 사용합니다. -필요한 최소 수량의 액세스만을 요청하는 것이 가장 좋으니 쓰기만 필요하다면 +을 가져온 것입니다. 이것은 기본적으로 "쓰기" 모드를 사용합니다. +필요한 최소 수량의 액세스만을 요청하는 것이 가장 좋으니 쓰기만 필요하다면 읽기/쓰기를 요청하지 마십시오.

    private void alterDocument(Uri uri) {
    @@ -512,16 +512,16 @@ private static final int EDIT_REQUEST_CODE = 44;
     
     

    권한 유지

    -

    앱이 읽기 또는 쓰기 작업에 대한 파일을 열면 시스템이 앱에 해당 파일에 대한 URI 권한 허가를 +

    앱이 읽기 또는 쓰기 작업에 대한 파일을 열면 시스템이 앱에 해당 파일에 대한 URI 권한 허가를 부여합니다. 이것은 사용자의 장치를 다시 시작할 때까지 유지됩니다. -하지만 만일 앱이 이미지 편집 앱이고, 사용자가 여러분의 앱에서 바로 편집한 5개의 이미지에 -액세스할 수 있도록 하고자 한다고 가정해봅시다. 사용자의 기기가 재시작되면 -여러분이 사용자에게 시스템 선택기를 다시 보내 해당 파일을 검색하도록 해야 할 텐데, +하지만 만일 앱이 이미지 편집 앱이고, 사용자가 여러분의 앱에서 바로 편집한 5개의 이미지에 +액세스할 수 있도록 하고자 한다고 가정해봅시다. 사용자의 기기가 재시작되면 +여러분이 사용자에게 시스템 선택기를 다시 보내 해당 파일을 검색하도록 해야 할 텐데, 이것은 물론 이상적인 것과는 거리가 멉니다.

    이런 일이 일어나지 않도록 방지하기 위해 시스템이 앱에 부여한 권한을 유지할 수 있습니다. -여러분의 앱은 시스템이 제공하는 유지 가능한 URI 권한 허가를 -효율적으로 "받아들입니다". 이렇게 하면 사용자가 여러분의 앱을 통해 파일에 지속적인 액세스 권한을 가질 수 있으며, +여러분의 앱은 시스템이 제공하는 유지 가능한 URI 권한 허가를 +효율적으로 "받아들입니다". 이렇게 하면 사용자가 여러분의 앱을 통해 파일에 지속적인 액세스 권한을 가질 수 있으며, 이는 기기가 다시 시작되더라도 관계 없습니다.

    @@ -531,65 +531,65 @@ private static final int EDIT_REQUEST_CODE = 44; // Check for the freshest data. getContentResolver().takePersistableUriPermission(uri, takeFlags);
    -

    마지막 한 단계가 남았습니다. 여러분의 앱이 액세스한 가장 최근의 URI를 -저장해두었을 수 있지만, 이는 더 이상 유효하지 않을 수 있습니다. 또 다른 앱이 문서를 -삭제하거나 수정했을 수 있기 때문입니다. 따라서, 항상 -{@code getContentResolver().takePersistableUriPermission()}을 +

    마지막 한 단계가 남았습니다. 여러분의 앱이 액세스한 가장 최근의 URI를 +저장해두었을 수 있지만, 이는 더 이상 유효하지 않을 수 있습니다. 또 다른 앱이 문서를 +삭제하거나 수정했을 수 있기 때문입니다. 따라서, 항상 +{@code getContentResolver().takePersistableUriPermission()}을 호출하여 최신 데이터를 확인해야 합니다.

    사용자 지정 문서 제공자 작성하기

    -파일용 저장소 서비스를 제공하는 앱을 개발 중인 경우(예를 들어 -클라우드 저장 서비스 등), SAF를 통해 파일을 사용할 수 있도록 하려면 사용자 지정 문서 제공자를 +파일용 저장소 서비스를 제공하는 앱을 개발 중인 경우(예를 들어 +클라우드 저장 서비스 등), SAF를 통해 파일을 사용할 수 있도록 하려면 사용자 지정 문서 제공자를 작성하면 됩니다. 이 섹션에서는 이렇게 하는 방법을 설명합니다.

    매니페스트

    -

    사용자 지정 문서 제공자를 구현하려면 애플리케이션의 매니페스트에 다음과 같은 항목을 +

    사용자 지정 문서 제공자를 구현하려면 애플리케이션의 매니페스트에 다음과 같은 항목을 추가하십시오.

    • API 레벨 19 이상의 대상.
    • -
    • 사용자 지정 저장소 제공자를 선언하는 <provider> +
    • 사용자 지정 저장소 제공자를 선언하는 <provider> 요소.
    • -
    • 제공자의 이름은 그 클래스 이름이며 여기에 패키지 이름도 포함됩니다. +
    • 제공자의 이름은 그 클래스 이름이며 여기에 패키지 이름도 포함됩니다. 예: com.example.android.storageprovider.MyCloudProvider
    • -
    • 권한의 이름, 이는 패키지 이름과 같으며(이 예시에서는 +
    • 권한의 이름, 이는 패키지 이름과 같으며(이 예시에서는 com.example.android.storageprovider)여기에 콘텐츠 제공자 유형을 더합니다 (documents). 예: {@code com.example.android.storageprovider.documents}
    • android:exported 속성을 "true"로 설정. 제공자를 내보내 다른 앱이 볼 수 있도록 해야 합니다.
    • -
    • android:grantUriPermissions 속성을 -"true"로 설정. 이렇게 설정하면 시스템이 여러분의 제공자 안에 있는 콘텐츠에 액세스하도록 다른 앱에 -권한을 허가할 수 있게 해줍니다. 특정 문서에 대한 권한 부여를 유지하는 방법에 대한 논의는 +
    • android:grantUriPermissions 속성을 +"true"로 설정. 이렇게 설정하면 시스템이 여러분의 제공자 안에 있는 콘텐츠에 액세스하도록 다른 앱에 +권한을 허가할 수 있게 해줍니다. 특정 문서에 대한 권한 부여를 유지하는 방법에 대한 논의는 권한 유지를 참조하십시오.
    • {@code MANAGE_DOCUMENTS} 권한. 기본적으로 제공자는 누구나 이용할 수 있습니다. - 이 권한을 추가하면 여러분의 제공자를 시스템에 제한하게 됩니다. + 이 권한을 추가하면 여러분의 제공자를 시스템에 제한하게 됩니다. 이 제한은 보안상 매우 중요합니다.
    • -
    • {@code android:enabled} 속성을 리소스 파일에서 정의한 부울 값으로 -설정합니다. 이 속성의 목적은 Android 4.3 이하에서 실행되는 기기에서 제공자를 비활성화하는 데 있습니다. -예를 들어 {@code android:enabled="@bool/atLeastKitKat"} 등입니다. 이 속성을 +
    • {@code android:enabled} 속성을 리소스 파일에서 정의한 부울 값으로 +설정합니다. 이 속성의 목적은 Android 4.3 이하에서 실행되는 기기에서 제공자를 비활성화하는 데 있습니다. +예를 들어 {@code android:enabled="@bool/atLeastKitKat"} 등입니다. 이 속성을 매니페스트에 추가하는 것 이외에도 다음과 같은 작업을 해야 합니다.
        -
      • {@code res/values/} 아래의 {@code bool.xml} 리소스 파일에 +
      • {@code res/values/} 아래의 {@code bool.xml} 리소스 파일에 이 라인을 추가합니다.
        <bool name="atLeastKitKat">false</bool>
      • -
      • {@code res/values-v19/} 아래의 {@code bool.xml} 리소스 파일에 +
      • {@code res/values-v19/} 아래의 {@code bool.xml} 리소스 파일에 이 라인을 추가합니다.
        <bool name="atLeastKitKat">true</bool>
    • -{@code android.content.action.DOCUMENTS_PROVIDER} 동작을 포함한 인텐트 필터가 있어야 +{@code android.content.action.DOCUMENTS_PROVIDER} 동작을 포함한 인텐트 필터가 있어야 시스템이 제공자를 검색할 때 여러분의 제공자가 선택기에 나타날 수 있습니다.
    @@ -619,31 +619,31 @@ getContentResolver().takePersistableUriPermission(uri, takeFlags);

    Android 4.3 이하에서 실행되는 기기 지원

    -{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 인텐트는 -Android 4.4 이상에서 실행되는 기기에서만 사용할 수 있습니다. -애플리케이션이 {@link android.content.Intent#ACTION_GET_CONTENT}를 지원하도록 하여 -Android 4.3 이하에서 실행되는 기기에도 적용되도록 하려면 Android 4.4 이상에서 실행되는 기기용 매니페스트에 있는 +{@link android.content.Intent#ACTION_OPEN_DOCUMENT} 인텐트는 +Android 4.4 이상에서 실행되는 기기에서만 사용할 수 있습니다. +애플리케이션이 {@link android.content.Intent#ACTION_GET_CONTENT}를 지원하도록 하여 +Android 4.3 이하에서 실행되는 기기에도 적용되도록 하려면 Android 4.4 이상에서 실행되는 기기용 매니페스트에 있는 {@link android.content.Intent#ACTION_GET_CONTENT} - 인텐트 필터를 비활성화해야 합니다. -문서 제공자와 {@link android.content.Intent#ACTION_GET_CONTENT}는 상호 배타적인 것으로 -간주해야 합니다. 둘을 모두 동시에 지원하는 경우, 앱이 시스템 선택기 UI에 + 인텐트 필터를 비활성화해야 합니다. +문서 제공자와 {@link android.content.Intent#ACTION_GET_CONTENT}는 상호 배타적인 것으로 +간주해야 합니다. 둘을 모두 동시에 지원하는 경우, 앱이 시스템 선택기 UI에 두 번 나타나 저장된 데이터에 액세스할 두 가지 서로 다른 방법을 제안하게 됩니다. 이렇게 되면 사용자에게 혼동을 주게 되겠죠.

    -

    다음은 Android 버전 4.4 이상에서 실행되는 기기용 -{@link android.content.Intent#ACTION_GET_CONTENT} 인텐트 필터를 +

    다음은 Android 버전 4.4 이상에서 실행되는 기기용 +{@link android.content.Intent#ACTION_GET_CONTENT} 인텐트 필터를 비활성화하는 데 권장되는 방법입니다.

      -
    1. {@code res/values/} 아래의 {@code bool.xml} 리소스 파일에 +
    2. {@code res/values/} 아래의 {@code bool.xml} 리소스 파일에 이 라인을 추가합니다.
      <bool name="atMostJellyBeanMR2">true</bool>
    3. -
    4. {@code res/values-v19/} 아래의 {@code bool.xml} 리소스 파일에 +
    5. {@code res/values-v19/} 아래의 {@code bool.xml} 리소스 파일에 이 라인을 추가합니다.
      <bool name="atMostJellyBeanMR2">false</bool>
    6. -액티비티 -별칭을 추가하여 버전 4.4(API 레벨 19) 이상을 대상으로 한 {@link android.content.Intent#ACTION_GET_CONTENT} +액티비티 +별칭을 추가하여 버전 4.4(API 레벨 19) 이상을 대상으로 한 {@link android.content.Intent#ACTION_GET_CONTENT} 인텐트 필터를 비활성화합니다. 예:
      @@ -666,13 +666,13 @@ Android 4.3 이하에서 실행되는 기기에도 적용되도록 하려면 And
       

    계약

    -

    사용자 지정 제공자를 작성할 때면 일반적으로 수반되는 작업 중 하나가 -계약 클래스를 구현하는 것입니다. 이는 +

    사용자 지정 제공자를 작성할 때면 일반적으로 수반되는 작업 중 하나가 +계약 클래스를 구현하는 것입니다. 이는 -콘텐츠 제공자 개발자 가이드에서 설명한 것과 같습니다. 계약 클래스는 {@code public final} 클래스로, -이 안에 URI에 대한 상수 정의, 열 이름, MIME 유형 및 제공자에 관련된 -다른 메타 데이터가 들어 있습니다. SAF가 -이와 같은 계약 클래스를 대신 제공해주므로 직접 쓰지 않아도 +콘텐츠 제공자 개발자 가이드에서 설명한 것과 같습니다. 계약 클래스는 {@code public final} 클래스로, +이 안에 URI에 대한 상수 정의, 열 이름, MIME 유형 및 제공자에 관련된 +다른 메타 데이터가 들어 있습니다. SAF가 +이와 같은 계약 클래스를 대신 제공해주므로 직접 쓰지 않아도 됩니다.

      @@ -680,7 +680,7 @@ Android 4.3 이하에서 실행되는 기기에도 적용되도록 하려면 And
    • {@link android.provider.DocumentsContract.Root}
    -

    예를 들어 다음은 여러분의 문서 제공자가 문서 또는 루트에 대해 쿼리된 경우 +

    예를 들어 다음은 여러분의 문서 제공자가 문서 또는 루트에 대해 쿼리된 경우 커서로 반환할 수 있는 열을 나타낸 것입니다.

    private static final String[] DEFAULT_ROOT_PROJECTION =
    @@ -696,7 +696,7 @@ private static final String[] DEFAULT_DOCUMENT_PROJECTION = new
     
     

    하위 클래스 DocumentsProvider

    -

    사용자 지정 문서 제공자를 작성하기 위한 다음 단계는 +

    사용자 지정 문서 제공자를 작성하기 위한 다음 단계는 추상 클래스 {@link android.provider.DocumentsProvider}를 하위 클래스로 만드는 것입니다. 최소한 다음과 같은 메서드를 구현해야 합니다.

    @@ -710,22 +710,22 @@ private static final String[] DEFAULT_DOCUMENT_PROJECTION = new
  • {@link android.provider.DocumentsProvider#openDocument openDocument()}
  • -

    꼭 구현해야만 하는 메서드는 이들뿐이지만, 개발자 여러분이 구현하고자 하는 메서드는 이보다 -훨씬 많을 수도 있습니다. 자세한 내용은{@link android.provider.DocumentsProvider} +

    꼭 구현해야만 하는 메서드는 이들뿐이지만, 개발자 여러분이 구현하고자 하는 메서드는 이보다 +훨씬 많을 수도 있습니다. 자세한 내용은{@link android.provider.DocumentsProvider} 를 참조하십시오.

    QueryRoots 구현

    {@link android.provider.DocumentsProvider#queryRoots -queryRoots()} 구현은 반드시 {@link android.database.Cursor}를 반환해야 하며, -이는 문서 제공자의 모든 루트 디렉터리를 가리켜야 합니다. 이때 +queryRoots()} 구현은 반드시 {@link android.database.Cursor}를 반환해야 하며, +이는 문서 제공자의 모든 루트 디렉터리를 가리켜야 합니다. 이때 {@link android.provider.DocumentsContract.Root}에서 정의한 열을 사용합니다.

    -

    다음 조각에서 {@code projection} 매개변수는 +

    다음 조각에서 {@code projection} 매개변수는 발신자가 돌려받고자 하는 특정 필드를 나타냅니다. 이 조각은 새 커서를 생성하며 -그에 하나의 행을 추가합니다. 하나의 루트, -다운로드 또는 이미지와 같은 최상위 레벨 디렉터리가 해당됩니다. 대부분의 제공자에는 루트가 하나뿐입니다. 하나 이상이 있을 수도 있습니다. -예를 들어 사용자 계정이 여러 개인 경우가 있습니다. 그런 경우에는 커서에 두 번째 행을 +그에 하나의 행을 추가합니다. 하나의 루트, +다운로드 또는 이미지와 같은 최상위 레벨 디렉터리가 해당됩니다. 대부분의 제공자에는 루트가 하나뿐입니다. 하나 이상이 있을 수도 있습니다. +예를 들어 사용자 계정이 여러 개인 경우가 있습니다. 그런 경우에는 커서에 두 번째 행을 추가하면 됩니다.

    @@ -778,13 +778,13 @@ public Cursor queryRoots(String[] projection) throws FileNotFoundException {
     
     

    {@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()} - 구현은 반드시 {@link android.database.Cursor}를 반환해야 하며, -이는 지정된 디렉터리 내의 모든 파일을 가리켜야 합니다. 이때 + 구현은 반드시 {@link android.database.Cursor}를 반환해야 하며, +이는 지정된 디렉터리 내의 모든 파일을 가리켜야 합니다. 이때 {@link android.provider.DocumentsContract.Document}에서 정의한 열을 사용합니다.

    -

    이 메서드는 선택기 UI에서 애플리케이션 루트를 선택하는 경우 호출됩니다. -이는 해당 루트 아래 디렉터리의 하위 문서를 가져옵니다. 이것은 루트에서뿐만 아니라 파일 계층의 어느 레벨에서나 -호출할 수 있습니다. 이 조각은 요청한 열로 새 커서를 만든 다음, +

    이 메서드는 선택기 UI에서 애플리케이션 루트를 선택하는 경우 호출됩니다. +이는 해당 루트 아래 디렉터리의 하위 문서를 가져옵니다. 이것은 루트에서뿐만 아니라 파일 계층의 어느 레벨에서나 +호출할 수 있습니다. 이 조각은 요청한 열로 새 커서를 만든 다음, 상위 디렉터리에 있는 모든 직속 하위에 대한 정보를 커서에 추가합니다. 하위는 이미지, 또 다른 디렉터리가 될 수도 있고 어느 파일이라도 될 수 있습니다.

    @@ -808,13 +808,13 @@ public Cursor queryChildDocuments(String parentDocumentId, String[] projection,

    {@link android.provider.DocumentsProvider#queryDocument queryDocument()} - 구현은 반드시 {@link android.database.Cursor}를 반환해야 하며, + 구현은 반드시 {@link android.database.Cursor}를 반환해야 하며, 이는 지정된 파일을 가리켜야 합니다. 이때 {@link android.provider.DocumentsContract.Document}에서 정의한 열을 사용합니다.

    {@link android.provider.DocumentsProvider#queryDocument queryDocument()} - 메서드는 -{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}에서 + 메서드는 +{@link android.provider.DocumentsProvider#queryChildDocuments queryChildDocuments()}에서 전달된 것과 같은 정보를 반환하지만, 특정한 파일에만 해당됩니다.

    @@ -832,12 +832,12 @@ public Cursor queryDocument(String documentId, String[] projection) throws

    OpenDocument 구현

    -

    지정된 파일을 나타내는 +

    지정된 파일을 나타내는 {@link android.os.ParcelFileDescriptor}를 반환하려면 {@link android.provider.DocumentsProvider#openDocument openDocument()}를 구현해야 합니다. 다른 앱들이 반환된 {@link android.os.ParcelFileDescriptor}를 - 사용하여 데이터를 스트리밍할 수 있습니다. 시스템은 사용자가 파일을 선택하고 -클라이언트 앱이 이에 대한 액세스를 요청하면서 -{@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()}를 사용할 때 이 메서드를 호출합니다. + 사용하여 데이터를 스트리밍할 수 있습니다. 시스템은 사용자가 파일을 선택하고 +클라이언트 앱이 이에 대한 액세스를 요청하면서 +{@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()}를 사용할 때 이 메서드를 호출합니다. 예를 들면 다음과 같습니다.

    @Override
    @@ -885,8 +885,8 @@ public ParcelFileDescriptor openDocument(final String documentId,
     

    보안

    여러분의 문서 제공자가 암호로 보호된 클라우드 저장소 서비스이고 -여러분은 사용자가 파일을 공유하기 전에 우선 로그인부터 하도록 확실히 해두고 싶다고 가정합니다. -사용자가 로그인되지 않은 경우 앱은 어떻게 해야 합니까? 해법은 +여러분은 사용자가 파일을 공유하기 전에 우선 로그인부터 하도록 확실히 해두고 싶다고 가정합니다. +사용자가 로그인되지 않은 경우 앱은 어떻게 해야 합니까? 해법은 {@link android.provider.DocumentsProvider#queryRoots queryRoots()} 구현에서 루트를 반환하지 않는 것입니다. 다시 말해, 텅 빈 루트 커서를 반환하는 것입니다.

    @@ -901,11 +901,11 @@ public Cursor queryRoots(String[] projection) throws FileNotFoundException {

    또 다른 단계는 {@code getContentResolver().notifyChange()}를 호출하는 것입니다. -{@link android.provider.DocumentsContract}를 기억하십니까? 이것을 사용하는 이유는 -바로 이 URI를 만들기 위해서입니다. 다음 조각은 사용자의 로그인 상태가 변경될 때마다 -시스템이 문서 제공자의 루트를 쿼리하도록 지시하고 있습니다. 사용자가 로그인되어 있지 않은 상태에서 -{@link android.provider.DocumentsProvider#queryRoots queryRoots()}를 호출하면 -위에서 나타낸 것과 같이 빈 커서를 반환합니다. 이렇게 하면 사용자가 제공자에 로그인되었을 때만 +{@link android.provider.DocumentsContract}를 기억하십니까? 이것을 사용하는 이유는 +바로 이 URI를 만들기 위해서입니다. 다음 조각은 사용자의 로그인 상태가 변경될 때마다 +시스템이 문서 제공자의 루트를 쿼리하도록 지시하고 있습니다. 사용자가 로그인되어 있지 않은 상태에서 +{@link android.provider.DocumentsProvider#queryRoots queryRoots()}를 호출하면 +위에서 나타낸 것과 같이 빈 커서를 반환합니다. 이렇게 하면 사용자가 제공자에 로그인되었을 때만 제공자의 문서를 사용할 수 있도록 보장할 수 있습니다.

    private void onLoginButtonClick() {
    diff --git a/docs/html-intl/intl/ko/guide/topics/resources/accessing-resources.jd b/docs/html-intl/intl/ko/guide/topics/resources/accessing-resources.jd
    index be9dd6bb0b20db8d2403d236add7e6614659f14f..f323280f9d78ebdc0c814ed21c254b4952f1b0fe 100644
    --- a/docs/html-intl/intl/ko/guide/topics/resources/accessing-resources.jd
    +++ b/docs/html-intl/intl/ko/guide/topics/resources/accessing-resources.jd
    @@ -7,7 +7,7 @@ parent.link=index.html
     

    간략히 보기

      -
    • 리소스는 {@code R.java}의 정수를 사용하는 코드, 예를 들어 +
    • 리소스는 {@code R.java}의 정수를 사용하는 코드, 예를 들어 {@code R.drawable.myimage}에서 참조할 수 있습니다.
    • 리소스는 특수 XML 구문을 사용하는 리소스, 예를 들어 {@code @drawable/myimage}에서 참조할 수 있습니다.
    • @@ -42,25 +42,25 @@ parent.link=index.html -

      일단 어떤 리소스를 애플리케이션에 제공한 다음에는(리소스 제공에서 논의), -해당 리소스의 리소스 ID를 참조함으로써 이를 적용할 수 있습니다. 모든 리소스 ID는 +

      일단 어떤 리소스를 애플리케이션에 제공한 다음에는(리소스 제공에서 논의), +해당 리소스의 리소스 ID를 참조함으로써 이를 적용할 수 있습니다. 모든 리소스 ID는 {@code aapt} 도구가 자동으로 생성하는 프로젝트의 {@code R} 클래스에서 정의됩니다.

      애플리케이션이 컴파일링되면, {@code aapt}가 {@code R} 클래스를 생성하며, 이 클래스 안에 {@code -res/} 디렉터리에 있는 모든 리소스의 -리소스 ID가 들어있습니다. 각 리소스 유형에는 {@code R} 하위 클래스가 있고(예: 모든 드로어블 리소스에 대한 +res/} 디렉터리에 있는 모든 리소스의 +리소스 ID가 들어있습니다. 각 리소스 유형에는 {@code R} 하위 클래스가 있고(예: 모든 드로어블 리소스에 대한 {@code R.drawable}), 해당 유형의 각 리소스에는 정적 -정수가 있습니다(예: {@code R.drawable.icon}). 이 정수가 +정수가 있습니다(예: {@code R.drawable.icon}). 이 정수가 리소스를 검색하는 데 사용할 수 있는 리소스 ID입니다.

      -

      {@code R} 클래스가 리소스 ID가 지정되는 곳이기는 하지만, 리소스 ID를 찾기 위해 +

      {@code R} 클래스가 리소스 ID가 지정되는 곳이기는 하지만, 리소스 ID를 찾기 위해 이곳을 볼 필요는 전혀 없습니다. 하나의 리소스 ID는 항상 다음과 같이 구성됩니다.

      • 리소스 유형: 각 리소스는 "유형"으로 그룹화됩니다. 예: {@code string}, {@code drawable} 및 {@code layout} 다양한 유형에 관한 자세한 정보는 리소스 유형을 참조하십시오.
      • -
      • 리소스 이름: -리소스가 단순 값(예: 문자열 등)일 경우, +
      • 리소스 이름: +리소스가 단순 값(예: 문자열 등)일 경우, 확장자를 제외한 파일 이름이나 XML {@code android:name} 속성 값 중 하나입니다.
      @@ -69,14 +69,14 @@ string}, {@code drawable} 및 {@code layout} 다양한 유형에 관한 자세
    • 코드 내부에서: {@code R} 클래스의 하위 클래스에서 정적 정수를 사용합니다. 예:
      R.string.hello
      -

      {@code string}은 리소스 유형이고 {@code hello}는 리소스 이름입니다. 리소스 ID를 이 형식으로 제공하면 리소스에 액세스할 수 있는 -Android API가 많습니다. +

      {@code string}은 리소스 유형이고 {@code hello}는 리소스 이름입니다. 리소스 ID를 이 형식으로 제공하면 리소스에 액세스할 수 있는 +Android API가 많습니다. 코드 내 리소스 액세스를 참조하십시오.

    • -
    • XML 내부에서: {@code R} 클래스에서 정의된 +
    • XML 내부에서: {@code R} 클래스에서 정의된 리소스 ID에 상응하기도 하는 특수 XML 구문을 사용합니다. 예:
      @string/hello
      -

      {@code string}은 리소스 유형이고 {@code hello}는 리소스 이름입니다. 이 +

      {@code string}은 리소스 유형이고 {@code hello}는 리소스 이름입니다. 이 구문은 리소스로 값을 제공할 것으로 예상되는 어느 곳에서나 XML 리소스 형태로 사용할 수 있습니다. XML에서 리소스 액세스를 참조하십시오.

    @@ -94,20 +94,20 @@ imageView.setImageResource(R.drawable.myimage);

    {@link -android.content.res.Resources}에서 메서드를 사용하는 개별 리소스를 검색할 수도 있으며, 이는 +android.content.res.Resources}에서 메서드를 사용하는 개별 리소스를 검색할 수도 있으며, 이는 {@link android.content.Context#getResources()}로 인스턴스를 가져올 수 있습니다.

    -

    이미지나 문자열과 같은 애플리케이션 리소스는 항상 코드에서 외부화해야 합니다. -그래야 이들을 독립적으로 유지관리할 수 있습니다. 특정 기기 구성에 대한 대체 리소스도 -제공해야 합니다. 이것은 특별하게 명명한 리소스 디렉터리에 그룹화하는 방법을 씁니다. Android는 -런타임에 현재 구성을 근거로 적절한 리소스를 사용합니다. 예를 들어 -여러 가지 화면 크기에 따라 여러 가지 UI 레이아웃을 제공하거나 언어 설정에 따라 +

    이미지나 문자열과 같은 애플리케이션 리소스는 항상 코드에서 외부화해야 합니다. +그래야 이들을 독립적으로 유지관리할 수 있습니다. 특정 기기 구성에 대한 대체 리소스도 +제공해야 합니다. 이것은 특별하게 명명한 리소스 디렉터리에 그룹화하는 방법을 씁니다. Android는 +런타임에 현재 구성을 근거로 적절한 리소스를 사용합니다. 예를 들어 +여러 가지 화면 크기에 따라 여러 가지 UI 레이아웃을 제공하거나 언어 설정에 따라 각기 다른 문자열을 제공하고자 할 수 있습니다.

    애플리케이션 리소스를 외부화하면 프로젝트 {@code R} 클래스에서 발생하는 리소스 ID로 액세스할 수 있습니다. 애플리케이션에서 리소스를 사용하는 방법은 리소스 -액세스에서 설명합니다. 이 문서에서는 Android 프로젝트에서 리소스를 그룹화하는 방법과 특정 기기 구성에 대한 +액세스에서 설명합니다. 이 문서에서는 Android 프로젝트에서 리소스를 그룹화하는 방법과 특정 기기 구성에 대한 대체 리소스를 제공하는 법을 보여드립니다.

    @@ -75,10 +75,10 @@ MyProject/ ) 포함하는 것을 볼 수 있습니다. 리소스 디렉터리 이름은 중요하며 표1에 설명되어 있습니다.

    -

    참고: Mipmap 폴더를 사용하는 자세한 방법은 +

    참고: Mipmap 폴더를 사용하는 자세한 방법은 프로젝트 관리 개요를 참조하십시오.

    -

    표 1. 프로젝트 +

    표 1. 프로젝트 {@code res/} 디렉터리 내부에서 지원하는 리소스 디렉터리입니다.

    @@ -89,13 +89,13 @@ MyProject/ - - @@ -126,8 +126,8 @@ MyProject/ - @@ -139,32 +139,32 @@ MyProject/ - - @@ -184,21 +184,21 @@ assets/} 디렉터리에 몇몇 리소스를 저장해두는 것을 고려해
    animator/속성 + 속성 애니메이션을 정의하는 XML 파일입니다.
    anim/tween + tween 애니메이션을 정의하는 XML 파일입니다 (속성 애니메이션도 이 디렉터리에 저장할 수 있지만 두 가지 유형을 구분하기 위해 속성 애니메이션에는 {@code animator/} 디렉터리가 기본 설정됩니다 ).
    mipmap/각기 다른 시작 관리자 아이콘 밀도에 대한 드로어블 파일입니다. -{@code mipmap/} 폴더로 시작 관리자 아이콘을 관리하는 자세한 방법은 + 각기 다른 시작 관리자 아이콘 밀도에 대한 드로어블 파일입니다. +{@code mipmap/} 폴더로 시작 관리자 아이콘을 관리하는 자세한 방법은 프로젝트 관리 개요를 참조하십시오.
    menu/옵션 메뉴, 컨텍스트 메뉴 또는 하위 + 옵션 메뉴, 컨텍스트 메뉴 또는 하위 메뉴 등과 같은 애플리케이션 메뉴를 정의하는 XML입니다. 메뉴 리소스를 참조하십시오.
    raw/

    원시 형태로 저장하기 위한 임의의 파일입니다. 원시 +

    원시 형태로 저장하기 위한 임의의 파일입니다. 원시 {@link java.io.InputStream}으로 이런 리소스를 열려면 리소스 ID, {@code R.raw.filename}으로 {@link android.content.res.Resources#openRawResource(int) Resources.openRawResource()}를 호출합니다.

    -

    그러나 원본 파일 이름과 파일 계층에 액세스해야 하는 경우, +

    그러나 원본 파일 이름과 파일 계층에 액세스해야 하는 경우, ({@code res/raw/}가 아니라) {@code -assets/} 디렉터리에 몇몇 리소스를 저장해두는 것을 고려해 볼 수 있습니다. {@code assets/}에 있는 파일에는 +assets/} 디렉터리에 몇몇 리소스를 저장해두는 것을 고려해 볼 수 있습니다. {@code assets/}에 있는 파일에는 리소스 ID가 주어지지 않으므로, 이들을 읽는 유일한 방법은 {@link android.content.res.AssetManager}를 사용하는 것뿐입니다.

    values/

    문자열, 정수 및 색과 같은 단순 값이 들어있는 XML 파일입니다.

    -

    다른 {@code res/} 하위 디렉터리에 있는 XML 리소스 파일은 XML 파일 이름을 근거로 +

    다른 {@code res/} 하위 디렉터리에 있는 XML 리소스 파일은 XML 파일 이름을 근거로 하나의 리소스를 정의하는 반면, {@code values/} 디렉터리에 있는 파일은 여러 개의 리소스를 설명합니다. -이 디렉터리 안에 있는 파일의 경우, {@code <resources>} 요소의 각 하위 요소가 리소스를 하나씩 -정의합니다. 예를 들어 {@code <string>} 요소는 +이 디렉터리 안에 있는 파일의 경우, {@code <resources>} 요소의 각 하위 요소가 리소스를 하나씩 +정의합니다. 예를 들어 {@code <string>} 요소는 {@code R.string} 리소스를 생성하고 {@code <color>} 요소는 {@code R.color} 리소스를 생성합니다.

    각 리소스가 자체 XML 요소로 정의되므로, 원하는 대로 파일을 정의하고 하나의 파일에 여러 가지 리소스 유형을 -배정할 수 있습니다. 하지만 명확히 하려면 여러 가지 파일에 +배정할 수 있습니다. 하지만 명확히 하려면 여러 가지 파일에 각기 고유한 리소스를 배치하는 것이 좋을 수도 있습니다. 예를 들어, 다음은 이 디렉터리에서 생성할 수 있는 리소스를 위한 파일 이름 명명법입니다.

      @@ -176,7 +176,7 @@ assets/} 디렉터리에 몇몇 리소스를 저장해두는 것을 고려해
    • 스타일을 위한 styles.xml

    문자열 리소스, -스타일 리소스 및 +스타일 리소스자세한 리소스 유형을 참조하십시오.

    xml/ 런타임에 읽을 수 있는 임의의 XML 파일로, 이때 {@link -android.content.res.Resources#getXml(int) Resources.getXML()}을 호출하는 방법을 씁니다. 다양한 XML 구성 파일을 여기에 저장해야 합니다. 예를 들어 +android.content.res.Resources#getXml(int) Resources.getXML()}을 호출하는 방법을 씁니다. 다양한 XML 구성 파일을 여기에 저장해야 합니다. 예를 들어 검색 가능한 구성 등이 이에 해당됩니다.
    -

    주의: 리소스 파일을 +

    주의: 리소스 파일을 {@code res/} 디렉터리에 직접 저장하면 절대로 안 됩니다. 컴파일러 오류를 초래하게 됩니다.

    특정 유형의 리소스에 관한 자세한 정보는 리소스 유형 문서를 참조하십시오.

    표1에 정의된 하위 디렉터리에 저장하는 리소스는 "기본" -리소스입니다. 다시 말해, 이러한 리소스가 애플리케이션의 기본 디자인과 콘텐츠를 정의한다는 뜻입니다. +리소스입니다. 다시 말해, 이러한 리소스가 애플리케이션의 기본 디자인과 콘텐츠를 정의한다는 뜻입니다. 그러나, 여러 가지 유형의 Android 구동 기기는 각기 다른 유형의 리소스를 호출할 수도 있습니다. -예를 들어 어느 기기의 화면이 보통보다 큰 편이라면, 추가적인 화면 공간의 이점을 활용할 수 있는 +예를 들어 어느 기기의 화면이 보통보다 큰 편이라면, 추가적인 화면 공간의 이점을 활용할 수 있는 다른 레이아웃 리소스를 제공해야 합니다. 또는, 기기에 다른 언어 설정이 있을 경우 해당 텍스트를 사용자 인터페이스에 번역하는 다른 문자열 리소스를 제공해야 합니다. 여러 가지 기기 구성에 여러 가지 리소스를 제공하려면, @@ -215,10 +215,10 @@ android.content.res.Resources#getXml(int) Resources.getXML()}을 호출하는 그림 1. 서로 다른 두 개의 기기로, 서로 다른 레이아웃 리소스를 사용합니다.

    -

    거의 모든 애플리케이션이 특정 기기 구성을 지원하는 -대체 리소스를 제공해야 합니다. 예를 들어 여러 가지 화면 밀도에 맞는 대체 드로어블 리소스를 -포함시켜야 하며 여러 가지 언어에 맞게 대체 문자열 리소스도 포함시켜야 합니다. Android는 런타임에 -현재 기기 구성을 감지하고 애플리케이션에 대해 적절한 리소스를 +

    거의 모든 애플리케이션이 특정 기기 구성을 지원하는 +대체 리소스를 제공해야 합니다. 예를 들어 여러 가지 화면 밀도에 맞는 대체 드로어블 리소스를 +포함시켜야 하며 여러 가지 언어에 맞게 대체 문자열 리소스도 포함시켜야 합니다. Android는 런타임에 +현재 기기 구성을 감지하고 애플리케이션에 대해 적절한 리소스를 로드합니다.

    리소스 세트에 대하여 구성별로 적절한 대체를 지정하려면 다음과 같이 합니다.

    @@ -231,13 +231,13 @@ android.content.res.Resources#getXml(int) Resources.getXML()}을 호출하는
  • {@code <qualifier>}는 리소스를 사용할 개별 구성을 지정하는 이름입니다(표2에 정의).
  • -

    하나 이상의 {@code <qualifier>}를 추가할 수 있습니다. 각기 대시로 +

    하나 이상의 {@code <qualifier>}를 추가할 수 있습니다. 각기 대시로 구분합니다.

    주의: 여러 한정자를 추가할 때는 -표2에 나열된 것과 같은 순서로 배치해야 합니다. 한정자의 순서가 잘못 지정되면 +표2에 나열된 것과 같은 순서로 배치해야 합니다. 한정자의 순서가 잘못 지정되면 해당 리소스가 무시됩니다.

    -
  • 해당되는 각 대체 리소스를 이 새 디렉터리에 저장하십시오. 이 리소스 파일은 기본 리소스 파일과 +
  • 해당되는 각 대체 리소스를 이 새 디렉터리에 저장하십시오. 이 리소스 파일은 기본 리소스 파일과 똑같은 이름을 지정해야 합니다.
  • @@ -254,21 +254,21 @@ res/

    {@code hdpi} 한정자는 해당 디렉터리의 리소스가 -고화질 화면 기기용이라는 것을 나타냅니다. 각 드로어블 디렉터리의 이미지는 특정 화면 화질에 맞추어 +고화질 화면 기기용이라는 것을 나타냅니다. 각 드로어블 디렉터리의 이미지는 특정 화면 화질에 맞추어 크기가 지정되었으나 파일 이름은 똑같습니다. 이렇게 하면 {@code icon.png} 또는 {@code -background.png} 이미지를 참조하는 데 사용하는 리소스 ID는 항상 같지만 Android가 각 리소스 중에서 현재 기기에 가장 잘 일치하는 -버전을 선택하게 됩니다. 이때 리소스 디렉터리 이름의 한정자를 기기 구성 정보와 +background.png} 이미지를 참조하는 데 사용하는 리소스 ID는 항상 같지만 Android가 각 리소스 중에서 현재 기기에 가장 잘 일치하는 +버전을 선택하게 됩니다. 이때 리소스 디렉터리 이름의 한정자를 기기 구성 정보와 비교하는 방법을 씁니다.

    -

    Android는 여러 가지 구성 한정자를 지원하며 한 디렉터리 이름에 -여러 개의 한정자를 추가할 수 있습니다. 각 한정자를 대시로 구분하면 됩니다. 표 2는 -유효한 구성 한정자를 우선 순위대로 나열한 것입니다. 리소스 디렉터리에 여러 개의 -한정자를 사용하는 경우, 해당 한정자를 디렉터리 이름에 추가할 때 이 표에 나열된 것과 같은 +

    Android는 여러 가지 구성 한정자를 지원하며 한 디렉터리 이름에 +여러 개의 한정자를 추가할 수 있습니다. 각 한정자를 대시로 구분하면 됩니다. 표 2는 +유효한 구성 한정자를 우선 순위대로 나열한 것입니다. 리소스 디렉터리에 여러 개의 +한정자를 사용하는 경우, 해당 한정자를 디렉터리 이름에 추가할 때 이 표에 나열된 것과 같은 순서로 추가해야 합니다.

    -

    표 2. 구성 한정자 +

    표 2. 구성 한정자 이름입니다.

    @@ -285,7 +285,7 @@ background.png} 이미지를 참조하는 데 사용하는 리소스 ID는 항 등. @@ -312,19 +312,19 @@ android.content.res.Configuration#mnc}를 참조하십시오. 이 구성 필드 등. @@ -368,22 +368,22 @@ supportsRtl}을 {@code "true"}로 설정하고 화면의 기본 크기로, 사용 가능한 화면 영역의 가장 짧은 치수가 +나타냅니다. 구체적으로 기기의 smallestWidth는 해당 화면의 이용 가능한 높이와 너비의 +가장 짧은 치수를 말합니다(이것을 화면에 대한 "가능한 한 가장 좁은 너비"로 생각해도 됩니다). 이 한정자를 사용하면 +화면의 현재 방향에 관계 없이 애플리케이션이 해당 UI에서 이용 가능한 너비 중 최소 {@code <N>}dps를 확보하도록 할 수 있습니다.

    -

    예를 들어, 레이아웃에 언제나 +

    예를 들어, 레이아웃에 언제나 600dp 이상의 화면 최소 치수가 필요하다면, 이 한정자를 사용하여 레이아웃 리소스, {@code -res/layout-sw600dp/}를 만들 수 있습니다. 시스템이 이러한 리소스를 사용하는 것은 사용 가능한 화면의 최소 치수가 적어도 600dp가 -되는 경우뿐이며, 이때 600dp라는 크기가 사용자 쪽에서 보기에 높이이든 너비이든 +res/layout-sw600dp/}를 만들 수 있습니다. 시스템이 이러한 리소스를 사용하는 것은 사용 가능한 화면의 최소 치수가 적어도 600dp가 +되는 경우뿐이며, 이때 600dp라는 크기가 사용자 쪽에서 보기에 높이이든 너비이든 관계 없습니다. 이 smallestWidth는 기기의 고정된 화면 크기 특성입니다. 기기의 smallestWidth는 화면 방향이 변경되어도 바뀌지 않습니다.

    기기의 smallestWidth는 화면 장식과 시스템 UI를 감안합니다. 예를 들어, 화면 상에서 최소 너비의 축 주변 공간을 차지하는 영구 UI 요소가 있다면, -시스템은 smallestWidth를 실제 화면 크기보다 작게 선언합니다. -이것은 개발자의 UI가 사용할 수 없는 화면 픽셀이기 때문입니다. 따라서 개발자가 사용하는 값은 -레이아웃에서 요구하는 실제 최소 치수여야 합니다(일반적으로 이 값은 화면의 현재 방향과 관계없이 +시스템은 smallestWidth를 실제 화면 크기보다 작게 선언합니다. +이것은 개발자의 UI가 사용할 수 없는 화면 픽셀이기 때문입니다. 따라서 개발자가 사용하는 값은 +레이아웃에서 요구하는 실제 최소 치수여야 합니다(일반적으로 이 값은 화면의 현재 방향과 관계없이 레이아웃이 지원하는 "최소 너비"가 됩니다.).

    다음의 몇몇 값은 보편적인 화면 크기에 대하여 사용할 수 있습니다.

      @@ -398,16 +398,16 @@ res/layout-sw600dp/}를 만들 수 있습니다. 시스템이 이러한 리소
    • 600x1024mdpi (7인치 태블릿) 등의 화면에는 600을 사용합니다.
    • 720x1280mdpi (10인치 태블릿) 등의 화면에는 720을 사용합니다.
    -

    애플리케이션이 -smallestWidth 한정자의 여러 값이 포함된 여러 리소스 디렉터리를 제공하면, 시스템은 +

    애플리케이션이 +smallestWidth 한정자의 여러 값이 포함된 여러 리소스 디렉터리를 제공하면, 시스템은 기기의 smallestWidth에 가장 가까운(그러나 이를 초과하지 않는) 값을 사용합니다.

    API 레벨 13에서 추가되었습니다.

    이외에도 애플리케이션과 호환되는 최소한의 smallestWidth를 선언하는 {@code -android:requiresSmallestWidthDp} 속성과 +android:requiresSmallestWidthDp} 속성과 기기의 smallestWidth 값을 보유한 {@link -android.content.res.Configuration#smallestScreenWidthDp} +android.content.res.Configuration#smallestScreenWidthDp} 구성 필드도 참조하십시오.

    -

    여러 가지 화면에 맞는 디자인과 한정자 사용에 관한 자세한 정보는 +

    여러 가지 화면에 맞는 디자인과 한정자 사용에 관한 자세한 정보는 다중 화면 지원 개발자 가이드를 참조하십시오.

    @@ -421,21 +421,21 @@ android.content.res.Configuration#smallestScreenWidthDp} 등. @@ -449,25 +449,25 @@ android.content.res.Configuration#smallestScreenWidthDp} 등. @@ -482,39 +482,39 @@ android.content.res.Configuration#smallestScreenWidthDp} @@ -530,9 +530,9 @@ xlarge} 한정자가 태그되어 있지만 기기는 일반 크기 화면일
  • {@code notlong}: QVGA, HVGA 및 VGA 등의 길지 않은 화면
  • API 레벨 4에서 추가되었습니다.

    -

    이것은 순전히 화면 비율에만 기초합니다("긴" 화면이 더 넓습니다). 이는 +

    이것은 순전히 화면 비율에만 기초합니다("긴" 화면이 더 넓습니다). 이는 화면 방향과 관계가 없습니다.

    -

    {@link android.content.res.Configuration#screenLayout}도 참조하십시오. +

    {@link android.content.res.Configuration#screenLayout}도 참조하십시오. 이것은 화면이 긴 화면인지 여부를 나타냅니다.

    @@ -549,10 +549,10 @@ xlarge} 한정자가 태그되어 있지만 기기는 일반 크기 화면일
  • {@code land}: 기기가 가로 방향(수평)입니다.
  • -

    이것은 사용자가 화면을 돌리는 경우 애플리케이션 수명 중에 -변경될 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 +

    이것은 사용자가 화면을 돌리는 경우 애플리케이션 수명 중에 +변경될 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 참조하십시오.

    -

    {@link android.content.res.Configuration#orientation} 구성 필드도 참조하십시오. +

    {@link android.content.res.Configuration#orientation} 구성 필드도 참조하십시오. 이는 현재 기기 방향을 나타냅니다.

    @@ -569,21 +569,21 @@ xlarge} 한정자가 태그되어 있지만 기기는 일반 크기 화면일
    • {@code car}: 기기가 차량용 도크에서 표시되고 있습니다.
    • {@code desk}: 기기가 데스크용 도크에서 표시되고 있습니다.
    • -
    • {@code television}: 기기가 텔레비전에서 표시되고 있으며, -UI가 큰 화면에 있고 사용자가 여기에서 멀리 떨어져 있는 -"텐 풋(ten foot)" 환경을 제공하고 있습니다. 이는 주로 DPAD 또는 +
    • {@code television}: 기기가 텔레비전에서 표시되고 있으며, +UI가 큰 화면에 있고 사용자가 여기에서 멀리 떨어져 있는 +"텐 풋(ten foot)" 환경을 제공하고 있습니다. 이는 주로 DPAD 또는 기타 비-포인터 상호 작용 주변을 가리킵니다.
    • -
    • {@code appliance}: 기기가 가전 제품 역할을 하고 있으며, 디스플레이 +
    • {@code appliance}: 기기가 가전 제품 역할을 하고 있으며, 디스플레이 화면이 없습니다.
    • {@code watch}: 기기에 디스플레이 화면이 있고 손목에 착용됩니다.

    API 레벨 8에서 추가되었고, 텔레비전은 API 13에서, 시계는 API 20에서 추가되었습니다.

    -

    기기가 도크에 삽입되거나 제거될 때 앱이 응답하는 방식에 관한 정보는 -도킹 상태 및 유형 +

    기기가 도크에 삽입되거나 제거될 때 앱이 응답하는 방식에 관한 정보는 +도킹 상태 및 유형 판별과 모니터링을 읽어보십시오.

    -

    이것은 사용자가 기기를 도크에 놓는 경우 애플리케이션 수명 중에 +

    이것은 사용자가 기기를 도크에 놓는 경우 애플리케이션 수명 중에 변경될 수 있습니다. 이러한 모드 중 몇 가지는 {@link -android.app.UiModeManager}를 사용하여 활성화 또는 비활성화할 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 +android.app.UiModeManager}를 사용하여 활성화 또는 비활성화할 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 참조하십시오.

    @@ -599,9 +599,9 @@ android.app.UiModeManager}를 사용하여 활성화 또는 비활성화할 수
  • {@code notnight}: 주간
  • API 레벨 8에서 추가되었습니다.

    -

    이것은 야간 모드가 자동 모드인 상태(기본)에서 애플리케이션의 수명 중에 -변경될 수 있습니다. 이 경우 모드는 하루 중 시간대를 기반으로 변경됩니다. 이 모드는 -{@link android.app.UiModeManager}를 사용하여 활성화 또는 비활성화할 수 있습니다. 이것이 런타임 중 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 +

    이것은 야간 모드가 자동 모드인 상태(기본)에서 애플리케이션의 수명 중에 +변경될 수 있습니다. 이 경우 모드는 하루 중 시간대를 기반으로 변경됩니다. 이 모드는 +{@link android.app.UiModeManager}를 사용하여 활성화 또는 비활성화할 수 있습니다. 이것이 런타임 중 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 참조하십시오.

    @@ -623,33 +623,33 @@ android.app.UiModeManager}를 사용하여 활성화 또는 비활성화할 수
  • {@code mdpi}: 중밀도(일반적인 HVGA에서) 화면, 약 160dpi.
  • {@code hdpi}: 고밀도 화면, 약 240dpi.
  • -
  • {@code xhdpi}: 초고밀도 화면, 약 320dpi. API 레벨 8에서 +
  • {@code xhdpi}: 초고밀도 화면, 약 320dpi. API 레벨 8에서 추가되었습니다.
  • -
  • {@code xxhdpi}: 슈퍼 초고밀도 화면, 약 480dpi. API 레벨 16에서 +
  • {@code xxhdpi}: 슈퍼 초고밀도 화면, 약 480dpi. API 레벨 16에서 추가되었습니다.
  • -
  • {@code xxxhdpi}: 울트라 슈퍼 초고밀도 화면 사용(시작 관리자 아이콘만 해당, -다중 화면 지원의 -참고를 참조하십시오), 약 640dpi. API 레벨 18에서 +
  • {@code xxxhdpi}: 울트라 슈퍼 초고밀도 화면 사용(시작 관리자 아이콘만 해당, +다중 화면 지원의 +참고를 참조하십시오), 약 640dpi. API 레벨 18에서 추가되었습니다.
  • -
  • {@code nodpi}: 이것은 기기 밀도에 일치하도록 크기를 조정하고자 하지 않는 비트맵 리소스에 +
  • {@code nodpi}: 이것은 기기 밀도에 일치하도록 크기를 조정하고자 하지 않는 비트맵 리소스에 사용할 수 있습니다.
  • -
  • {@code tvdpi}: Mdpi와 hdpi 사이 어딘가에 해당되는 화면, 약 213dpi. 이것은 -"기본" 밀도 그룹으로 간주되지 않습니다. 이는 대체로 텔레비전용으로 만들어진 것이며 -대부분의 앱에는 필요하지 않는 것이 정상입니다. mdpi 및 hdpi만 제공하면 대부분의 앱에는 충분하고 +
  • {@code tvdpi}: Mdpi와 hdpi 사이 어딘가에 해당되는 화면, 약 213dpi. 이것은 +"기본" 밀도 그룹으로 간주되지 않습니다. 이는 대체로 텔레비전용으로 만들어진 것이며 +대부분의 앱에는 필요하지 않는 것이 정상입니다. mdpi 및 hdpi만 제공하면 대부분의 앱에는 충분하고 시스템이 필요에 따라 크기를 조정해줍니다. 이 한정자는 API 레벨 13과 함께 도입되었습니다.
  • -

    여섯 가지 기본 밀도간에 3:4:6:8:12:16 비율 척도가 있습니다(tvdpi 밀도는 +

    여섯 가지 기본 밀도간에 3:4:6:8:12:16 비율 척도가 있습니다(tvdpi 밀도는 무시). 그러므로 ldpi의 9x9 비트맵은 mdpi에서 12x12이고, hdpi에서 18x18, xhdpi에서 24x24 등, 이런 식으로 적용됩니다.

    -

    이미지 리소스가 텔레비전이나 특정 기기에서 제대로 보이지 않는다고 결정하고 +

    이미지 리소스가 텔레비전이나 특정 기기에서 제대로 보이지 않는다고 결정하고 tvdpi 리소스를 사용하려 할 경우, 배율은 1.33*mdpi입니다. 예를 들어, mdpi 화면의 100px x 100px 이미지는 tvdpi에서 133px x 133px가 되어야 합니다.

    -

    참고: 밀도 한정자를 사용하더라도 해당 리소스가 그 밀도의 화면 -전용이라는 뜻은 아닙니다. 현재 기기 구성과 더욱 잘 맞는 한정자가 포함된 대체 리소스를 -제공하지 않으면, +

    참고: 밀도 한정자를 사용하더라도 해당 리소스가 그 밀도의 화면 +전용이라는 뜻은 아닙니다. 현재 기기 구성과 더욱 잘 맞는 한정자가 포함된 대체 리소스를 +제공하지 않으면, 시스템이 가장 잘 일치하는 리소스를 사용합니다.

    -

    다양한 화질을 처리하는 방법과 -Android가 현재 화질에 맞춰 비트맵을 축소하는 방법에 관한 자세한 정보는 다중 화면 +

    다양한 화질을 처리하는 방법과 +Android가 현재 화질에 맞춰 비트맵을 축소하는 방법에 관한 자세한 정보는 다중 화면 지원을 참조하십시오.

    @@ -662,10 +662,10 @@ Android가 현재 화질에 맞춰 비트맵을 축소하는 방법에 관한
    @@ -678,25 +678,25 @@ Android가 현재 화질에 맞춰 비트맵을 축소하는 방법에 관한 @@ -710,13 +710,13 @@ android.content.res.Configuration#keyboardHidden}을 참조하십시오. 이 필 @@ -729,13 +729,13 @@ android.content.res.Configuration#keyboardHidden}을 참조하십시오. 이 필 @@ -749,13 +749,13 @@ android.content.res.Configuration#keyboardHidden}을 참조하십시오. 이 필 @@ -792,11 +792,11 @@ orientation" described above.

    참고: 일부 구성 한정자는 Android -1.0 이후부터 추가되었으므로 모든 Android 버전이 모든 한정자를 지원하는 것은 아닙니다. 새로운 한정자를 사용하면 암시적으로 -플랫폼 버전 한정자도 추가하므로 구형 기기가 이를 무시하게 됩니다. 예를 들어 -w600dp 한정자를 사용하면 자동적으로 v13 한정자를 포함합니다. -사용 가능한 너비 한정자가 API 레벨 13부터 새로 도입되었기 때문입니다. 문제를 애초에 피하려면, 항상 -기본 리소스를 한 세트 포함하세요(한정자 없는 리소스 한 세트). 자세한 정보는 +1.0 이후부터 추가되었으므로 모든 Android 버전이 모든 한정자를 지원하는 것은 아닙니다. 새로운 한정자를 사용하면 암시적으로 +플랫폼 버전 한정자도 추가하므로 구형 기기가 이를 무시하게 됩니다. 예를 들어 +w600dp 한정자를 사용하면 자동적으로 v13 한정자를 포함합니다. +사용 가능한 너비 한정자가 API 레벨 13부터 새로 도입되었기 때문입니다. 문제를 애초에 피하려면, 항상 +기본 리소스를 한 세트 포함하세요(한정자 없는 리소스 한 세트). 자세한 정보는 리소스와 연관된 최선의 기기 호환성 제공 을 참조하십시오.

    @@ -808,7 +808,7 @@ orientation" described above.

    • 한 가지 리소스 세트에 여러 개의 한정자를 사용할 수 있으며, 이를 대시로 구분하면 됩니다. 예를 들어, -drawable-en-rUS-land는 수평 방향의 +drawable-en-rUS-land는 수평 방향의 US-English 기기에 적용합니다.
    • 한정자는 표2에 나열된 순서를 따라야 합니다. 예: @@ -817,25 +817,25 @@ US-English 기기에 적용합니다.
    • 맞는 배열: drawable-port-hdpi/
    -
  • 대체 리소스 디렉터리는 중첩될 수 없습니다. 예를 들어, +
  • 대체 리소스 디렉터리는 중첩될 수 없습니다. 예를 들어, res/drawable/drawable-en/는 있을 수 없습니다.
  • -
  • 값은 대소문자를 구분하지 않습니다. 리소스 컴파일러가 처리 전에 디렉터리 이름을 -소문자로 바꿔 대소문자를 구분하지 않는 +
  • 값은 대소문자를 구분하지 않습니다. 리소스 컴파일러가 처리 전에 디렉터리 이름을 +소문자로 바꿔 대소문자를 구분하지 않는 파일 시스템에서 문제를 일으키지 않도록 방지합니다. 이름에 대문자가 있는 것은 오로지 가독성을 향상하기 위해서입니다.
  • -
  • 각 한정자 유형마다 한 개의 값만 지원됩니다. 예를 들어, 스페인과 프랑스에 -같은 드로어블 파일을 사용하고자 하는 경우 디렉터리 이름이 -drawable-rES-rFR/이면 안 됩니다. 대신 +
  • 각 한정자 유형마다 한 개의 값만 지원됩니다. 예를 들어, 스페인과 프랑스에 +같은 드로어블 파일을 사용하고자 하는 경우 디렉터리 이름이 +drawable-rES-rFR/이면 안 됩니다. 대신 drawable-rES/drawable-rFR/ 같이 적절한 파일이 포함된 두 개의 리소스 디렉터리가 필요합니다. -그러나 두 위치에서 같은 파일을 실제로 복제할 필요는 없습니다. 대신 +그러나 두 위치에서 같은 파일을 실제로 복제할 필요는 없습니다. 대신 리소스에 별명을 만들면 됩니다. 아래의 별명 리소스 생성을 참조하십시오.
  • -

    이런 한정자로 이름을 지은 디렉터리에 대체 리소스를 저장하고 나면 +

    이런 한정자로 이름을 지은 디렉터리에 대체 리소스를 저장하고 나면 Android가 현재 기기 구성에 기초하여 애플리케이션에 자동으로 리소스를 적용합니다. 리소스가 요청될 때마다 Android가 요청한 리소스 파일이 들어있는 -대체 리소스 디렉터리를 확인하고, 그런 다음 가장 잘 일치하는 -리소스를 찾습니다(아래에서 논함). 특정 기기 구성에 일치하는 대체 리소스가 없는 경우, +대체 리소스 디렉터리를 확인하고, 그런 다음 가장 잘 일치하는 +리소스를 찾습니다(아래에서 논함). 특정 기기 구성에 일치하는 대체 리소스가 없는 경우, Android는 상응하는 기본 리소스(구성 한정자를 포함하지 않는 특정 리소스 유형에 대한 리소스 세트 )를 사용합니다.

    @@ -844,31 +844,31 @@ Android는 상응하는 기본 리소스(구성 한정자를 포함하지 않는

    별명 리소스 생성

    -

    어떤 리소스를 하나 이상의 기기 구성에서 사용하고자 하는 경우(그렇지만 -이를 기본 리소스를 제공하는 것은 원치 않는 경우), 같은 리소스를 하나 이상의 대체 리소스 디렉터리에 -넣지 않아도 됩니다. 대신, 기본 리소스 디렉터리에 저장된 리소스에 대해 별명 역할을 하는 -대체 +

    어떤 리소스를 하나 이상의 기기 구성에서 사용하고자 하는 경우(그렇지만 +이를 기본 리소스를 제공하는 것은 원치 않는 경우), 같은 리소스를 하나 이상의 대체 리소스 디렉터리에 +넣지 않아도 됩니다. 대신, 기본 리소스 디렉터리에 저장된 리소스에 대해 별명 역할을 하는 +대체 리소스를 만들면 됩니다(경우에 따라).

    -

    참고: 모든 리소스가 다른 리소스에 대한 -별명을 생성할 수 있는 메커니즘을 제공하는 것은 아닙니다. 특히, {@code xml/} 디렉터리의 애니메이션, 메뉴, 원시 및 기타 지정되지 않은 +

    참고: 모든 리소스가 다른 리소스에 대한 +별명을 생성할 수 있는 메커니즘을 제공하는 것은 아닙니다. 특히, {@code xml/} 디렉터리의 애니메이션, 메뉴, 원시 및 기타 지정되지 않은 리소스는 이 기능을 제공하지 않습니다.

    -

    예를 들어, 애플리케이션 아이콘 {@code icon.png}이 있고 서로 다른 로케일에서 이 아이콘의 고유 버전이 -필요한 경우가 있습니다. 그러나 두 로케일, English-Canadian과 French-Canadian은 같은 버전을 -사용해야 합니다. 같은 이미지를 English-Canadian과 French-Canadian 양쪽 -모두에 대한 리소스 디렉터리에 복사해야 한다고 생각할 수 있지만, 실은 +

    예를 들어, 애플리케이션 아이콘 {@code icon.png}이 있고 서로 다른 로케일에서 이 아이콘의 고유 버전이 +필요한 경우가 있습니다. 그러나 두 로케일, English-Canadian과 French-Canadian은 같은 버전을 +사용해야 합니다. 같은 이미지를 English-Canadian과 French-Canadian 양쪽 +모두에 대한 리소스 디렉터리에 복사해야 한다고 생각할 수 있지만, 실은 그렇지 않습니다. 대신, 두 로케일에서 사용하는 이미지를 {@code icon_ca.png}( -{@code icon.png} 이외에 어떤 이름이든 가능)로 저장하고 이를 +{@code icon.png} 이외에 어떤 이름이든 가능)로 저장하고 이를 기본 {@code res/drawable/} 디렉터리에 넣으면 됩니다. 그런 다음 {@code icon.xml} 파일을 {@code icon_ca.png} 리소스를 참조하는 {@code -res/drawable-en-rCA/} 및 {@code res/drawable-fr-rCA/}로 생성합니다. 이때, {@code <bitmap>} 요소를 사용하면 됩니다. 이렇게 하면 +res/drawable-en-rCA/} 및 {@code res/drawable-fr-rCA/}로 생성합니다. 이때, {@code <bitmap>} 요소를 사용하면 됩니다. 이렇게 하면 PNG 파일 버전 하나와 그것을 가리키는 작은 XML 파일 두 개만 저장할 수 있습니다. (XML 파일 예시는 아래와 같습니다.)

    드로어블

    -

    기존 드로어블에 별명을 생성하려면 {@code <bitmap>} 요소를 사용합니다. +

    기존 드로어블에 별명을 생성하려면 {@code <bitmap>} 요소를 사용합니다. 예를 들면 다음과 같습니다.

    @@ -896,13 +896,13 @@ R.drawable.icon_ca} 리소스({@code res/drawable/}에 저장됨)의 별명인 
     

    파일을 {@code main.xml}로 저장하면, {@code R.layout.main}으로 참조할 수 있지만 실제로는 {@code R.layout.main_ltr} - 리소스의 별명인 리소스로 + 리소스의 별명인 리소스로 컴파일링됩니다.

    문자열 및 기타 단순 값

    -

    기존 문자열에 별명을 생성하려면 원하는 문자열의 리소스 ID를 +

    기존 문자열에 별명을 생성하려면 원하는 문자열의 리소스 ID를 새 문자열의 값으로 사용하면 됩니다. 예:

    @@ -915,7 +915,7 @@ R.drawable.icon_ca} 리소스({@code res/drawable/}에 저장됨)의 별명인 
     
     

    이제 {@code R.string.hi} 리소스는 {@code R.string.hello}의 별명입니다.

    -

    기타 단순 값도 같은 방식으로 +

    기타 단순 값도 같은 방식으로 동작합니다. 예를 들면 색상은 다음과 같습니다.

    @@ -931,50 +931,50 @@ R.drawable.icon_ca} 리소스({@code res/drawable/}에 저장됨)의 별명인 
     
     

    리소스와 연관된 최선의 기기 호환성 제공

    -

    애플리케이션이 여러 기기 구성을 지원하게 하려면, +

    애플리케이션이 여러 기기 구성을 지원하게 하려면, 언제나 애플리케이션이 사용하는 각 유형의 리소스에 기본 리소스를 제공하는 것이 매우 중요합니다.

    예를 들어 애플리케이션이 여러 언어를 지원할 경우, 항상 언어 및 지역 한정자 없이 {@code -values/} 디렉터리(여기에 문자열 저장)를 포함시켜야 합니다. 그렇게 하지 않고 언어와 지역 한정자가 있는 디렉터리에 -모든 문자열을 넣으면, 문자열이 지원하지 않는 언어로 설정된 기기에서 애플리케이션을 -실행하면 작동이 중단됩니다. 그러나 기본 -{@code values/} 리소스를 제공하는 한은 애플리케이션이 제대로 실행됩니다(사용자가 이해하지 못하는 +values/} 디렉터리(여기에 문자열 저장)를 포함시켜야 합니다. 그렇게 하지 않고 언어와 지역 한정자가 있는 디렉터리에 +모든 문자열을 넣으면, 문자열이 지원하지 않는 언어로 설정된 기기에서 애플리케이션을 +실행하면 작동이 중단됩니다. 그러나 기본 +{@code values/} 리소스를 제공하는 한은 애플리케이션이 제대로 실행됩니다(사용자가 이해하지 못하는 언어로라도 작동합니다. 작동 중단보다 낫습니다.)

    -

    마찬가지로 화면 방향에 기초하여 여러 가지 레이아웃 리소스를 제공하는 경우 +

    마찬가지로 화면 방향에 기초하여 여러 가지 레이아웃 리소스를 제공하는 경우 하나의 방향을 기본값으로 선택해야 합니다. 예를 들어 가로 방향에는 {@code -layout-land/}로, 세로 방향에는 {@code layout-port/}로 레이아웃 리소스를 제공하는 대신 하나를 기본으로 남겨두십시오. +layout-land/}로, 세로 방향에는 {@code layout-port/}로 레이아웃 리소스를 제공하는 대신 하나를 기본으로 남겨두십시오. 가로 방향에 {@code layout/}, 세로 방향에 {@code layout-port/}와 같은 식으로 하면 됩니다.

    -

    애플리케이션이 예상치 못한 구성에서 실행될 수 있을 뿐만 아니라 -Android의 새 버전에서 이전 버전에서는 지원하지 않는 구성 한정자를 추가할 수도 있으므로, -기본 리소스를 제공하는 것이 중요합니다. 새 리소스 한정자를 사용하지만, +

    애플리케이션이 예상치 못한 구성에서 실행될 수 있을 뿐만 아니라 +Android의 새 버전에서 이전 버전에서는 지원하지 않는 구성 한정자를 추가할 수도 있으므로, +기본 리소스를 제공하는 것이 중요합니다. 새 리소스 한정자를 사용하지만, Android 이전 버전과 코드 호환성은 유지한 경우, 그 후 Android 이전 버전이 -애플리케이션을 실행하면 새로운 한정자로 이름을 지정한 리소스를 사용할 수 없으므로 기본 리소스를 제공하지 않으면 +애플리케이션을 실행하면 새로운 한정자로 이름을 지정한 리소스를 사용할 수 없으므로 기본 리소스를 제공하지 않으면 애플리케이션 작동이 중단됩니다. 예를 들어, {@code -minSdkVersion}이 4로 설정되고 야간 모드(API 레벨 8에서 추가된 {@code night} 또는 {@code notnight})를 사용하는 모든 드로어블 리소스를 한정할 경우, API 레벨 4 기기는 -드로어블 리소스에 액세스하지 못하고 사용이 중단됩니다. 이 경우, -{@code notnight}를 기본 리소스로 제공하는 것이 좋습니다. 그래야 해당 한정자를 배제하고 +minSdkVersion}이 4로 설정되고 야간 모드(API 레벨 8에서 추가된 {@code night} 또는 {@code notnight})를 사용하는 모든 드로어블 리소스를 한정할 경우, API 레벨 4 기기는 +드로어블 리소스에 액세스하지 못하고 사용이 중단됩니다. 이 경우, +{@code notnight}를 기본 리소스로 제공하는 것이 좋습니다. 그래야 해당 한정자를 배제하고 드로어블 리소스가 {@code drawable/} 또는 {@code drawable-night/}이 됩니다.

    -

    그러므로 최선의 기기 호환성을 제공하려면 언제나 -애플리케이션에서 반드시 제대로 수행해야 하는 리소스에 대해 기본 리소스를 제공하십시오. 그런 다음 구성 한정자를 사용하여 +

    그러므로 최선의 기기 호환성을 제공하려면 언제나 +애플리케이션에서 반드시 제대로 수행해야 하는 리소스에 대해 기본 리소스를 제공하십시오. 그런 다음 구성 한정자를 사용하여 특정 기기 구성에 대해 대체 리소스를 생성하면 됩니다.

    -

    이 규칙에는 한 가지 예외가 있습니다. 애플리케이션의 {@code minSdkVersion} 이 4 이상이면 -화면 밀도 한정자로 대체 드로어블 리소스를 제공할 때 기본 드로어블 -리소스가 없어도 됩니다. 기본 -드로어블 리소스가 없더라도 Android가 대체 화면 화질 중에서 가장 잘 맞는 리소스를 찾고 -필요에 따라 비트맵을 축소합니다. 그러나 모든 유형의 기기에서 최상의 경험을 제공하려면, +

    이 규칙에는 한 가지 예외가 있습니다. 애플리케이션의 {@code minSdkVersion} 이 4 이상이면 +화면 밀도 한정자로 대체 드로어블 리소스를 제공할 때 기본 드로어블 +리소스가 없어도 됩니다. 기본 +드로어블 리소스가 없더라도 Android가 대체 화면 화질 중에서 가장 잘 맞는 리소스를 찾고 +필요에 따라 비트맵을 축소합니다. 그러나 모든 유형의 기기에서 최상의 경험을 제공하려면, 모든 세 가지 유형의 밀도에 대해 대체 드로어블을 제공해야 합니다.

    Android가 가장 잘 일치하는 리소스를 찾는 방법

    -

    개발자가 자신이 대체를 제공하는 리소스를 요청하면 Android가 런타임에 어느 대체 리소스를 -사용할지 현대 기기 구성에 따라 여러 가지로 선택합니다. Android가 -대체 리소스를 선택하는 방법을 보여주기 위해 다음 드로어블 디렉터리에 각각 같은 이미지의 +

    개발자가 자신이 대체를 제공하는 리소스를 요청하면 Android가 런타임에 어느 대체 리소스를 +사용할지 현대 기기 구성에 따라 여러 가지로 선택합니다. Android가 +대체 리소스를 선택하는 방법을 보여주기 위해 다음 드로어블 디렉터리에 각각 같은 이미지의 서로 다른 버전이 들어있다고 가정하겠습니다.

    @@ -997,16 +997,16 @@ drawable-port-notouch-12key/
     기본 텍스트 입력 메서드 = 12key
     

    -

    Android는 기기 구성을 이용 가능한 대체 리소스와 비교하여, +

    Android는 기기 구성을 이용 가능한 대체 리소스와 비교하여, {@code drawable-en-port}에서 드로어블을 선택합니다.

    -

    시스템은 다음과 같은 논리에 따라 +

    시스템은 다음과 같은 논리에 따라 어느 리소스를 사용할지 결정합니다.

    -

    그림 2. Android가 가장 잘 일치하는 리소스를 찾는 방법을 나타낸 +

    그림 2. Android가 가장 잘 일치하는 리소스를 찾는 방법을 나타낸 흐름도입니다.

    @@ -1024,23 +1024,23 @@ drawable-en-notouch-12key/ drawable-port-ldpi/ drawable-port-notouch-12key/
    -

    예외: 화면 픽셀 밀도 한정자 하나만은 충돌을 이유로 제거되지 -않습니다. 기기의 화면 밀도가 hdpi라도, +

    예외: 화면 픽셀 밀도 한정자 하나만은 충돌을 이유로 제거되지 +않습니다. 기기의 화면 밀도가 hdpi라도, 현 시점에서는 모든 화면 밀도가 일치로 간주되므로 drawable-port-ldpi/를 제거하지 않습니다. - 자세한 정보는 다중 화면 + 자세한 정보는 다중 화면 지원 문서에서 이용하실 수 있습니다.

  • 목록(표2)에서 (그 다음으로) 우선 순위가 가장 높은 한정자를 선택합니다 (MCC부터 시작하여 아래로 내려가십시오).
  • 리소스 디렉터리 중에 이 한정자를 포함한 것이 있나요?
    • -
    • 없는 경우, 2단계로 돌아가 다음 한정자를 살펴보십시오 (이 예시의 경우 +
    • 없는 경우, 2단계로 돌아가 다음 한정자를 살펴보십시오 (이 예시의 경우 언어 한정자에 도달할 때까지 답은 "없습니다"입니다).
    • 있는 경우, 4단계로 계속 진행합니다.
    -
  • 이 한정자를 포함하지 않는 디렉터리를 제거합니다. 이 예시에서는 시스템이 +
  • 이 한정자를 포함하지 않는 디렉터리를 제거합니다. 이 예시에서는 시스템이 언어 한정자를 포함하지 않는 디렉터리를 모두 제거합니다.
  •  drawable/
    @@ -1050,15 +1050,15 @@ drawable-en-notouch-12key/
     drawable-port-ldpi/
     drawable-port-notouch-12key/
     
    -

    예외: 문제의 한정자가 화면 픽셀 밀도라면, -Android는 기기 화면 밀도와 가장 가깝게 일치하는 옵션을 선택합니다. +

    예외: 문제의 한정자가 화면 픽셀 밀도라면, +Android는 기기 화면 밀도와 가장 가깝게 일치하는 옵션을 선택합니다. 일반적으로, Android는 작은 원본 이미지를 확대하는 것보다 -큰 원본 이미지를 축소하는 것을 선호합니다. 다중 화면 +큰 원본 이미지를 축소하는 것을 선호합니다. 다중 화면 지원을 참조하십시오.

    -
  • 뒤로 돌아가 디렉터리가 한 개만 남을 때까지 2, 3 및 4단계를 반복합니다. 이 예시에서, 일치하는 것이 있는 다음 한정자는 -화면 방향입니다. +
  • 뒤로 돌아가 디렉터리가 한 개만 남을 때까지 2, 3 및 4단계를 반복합니다. 이 예시에서, 일치하는 것이 있는 다음 한정자는 +화면 방향입니다. 그러므로 화면 방향을 지정하지 않는 리소스가 제거됩니다.
     drawable-en/
    @@ -1069,26 +1069,26 @@ drawable-en-port/
       
  • -

    이 절차는 요청된 각 리소스에 대해 실행하지만, 시스템이 몇 가지 측면을 추가로 -최적화합니다. 그러한 최적화 가운데에는 일단 기기 구성을 알게 되고 나면 절대 일치할 가능성이 없는 -대체 리소스를 시스템이 제거할 수 있다는 점도 있습니다. 예를 들어, 구성 언어가 -영어("en")이고 영어 이외의 다른 언어 한정자로 설정된 리소스 디렉터리는 +

    이 절차는 요청된 각 리소스에 대해 실행하지만, 시스템이 몇 가지 측면을 추가로 +최적화합니다. 그러한 최적화 가운데에는 일단 기기 구성을 알게 되고 나면 절대 일치할 가능성이 없는 +대체 리소스를 시스템이 제거할 수 있다는 점도 있습니다. 예를 들어, 구성 언어가 +영어("en")이고 영어 이외의 다른 언어 한정자로 설정된 리소스 디렉터리는 절대 확인된 리소스 풀에 포함되지 않습니다( 언어 한정자가 포함되지 않는 리소스 디렉터리는 여전히 포함됩니다).

    화면 크기 한정자에 기초하여 리소스를 선택할 때 시스템은 가장 잘 일치하는 리소스가 없다면 현재 화면보다 작은 화면에 지정된 리소스를 사용합니다 -(예를 들어, 큰 화면은 필요에 따라 일반 크기 화면 리소스를 사용합니다). 그러나 +(예를 들어, 큰 화면은 필요에 따라 일반 크기 화면 리소스를 사용합니다). 그러나 이용 가능한 리소스가 현재 화면보다 리소스뿐이라면, 시스템은 이를 사용하지 않고, 기기 구성에 일치하는 리소스가 없으면 애플리케이션 사용이 중단됩니다 (예를 들어 모든 레이아웃 리소스가 {@code xlarge} 한정자에 태그되어 있지만, 기기가 보통 크기 화면일 경우).

    -

    참고: 한정자의 우선 순위(표 2 참조)가 기기와 정확하게 일치하는 -한정자 수보다 더 중요합니다. 예를 들어 위의 4단계에서 +

    참고: 한정자의 우선 순위(표 2 참조)가 기기와 정확하게 일치하는 +한정자 수보다 더 중요합니다. 예를 들어 위의 4단계에서 목록의 마지막 선택에 기기와 정확히 일치하는 한정자가 세 개 포함되어 있지만(방향, 터치 스크린 -유형 및 입력 메서드), drawable-en에는 일치하는 매개변수가 -하나뿐입니다(언어). 다만, 언어가 이러한 다른 한정자보다 우선 순위가 높기 때문에 +유형 및 입력 메서드), drawable-en에는 일치하는 매개변수가 +하나뿐입니다(언어). 다만, 언어가 이러한 다른 한정자보다 우선 순위가 높기 때문에 drawable-port-notouch-12key는 탈락합니다.

    애플리케이션에서 리소스를 사용하는 것에 대한 자세한 정보는 리소스 액세스로 계속 진행하여 알아보십시오.

    diff --git a/docs/html-intl/intl/ko/guide/topics/resources/runtime-changes.jd b/docs/html-intl/intl/ko/guide/topics/resources/runtime-changes.jd index a5e7f5bbad8830f0bcaa45cb2d6ffd0f3b77f3aa..720601fb999a327cfb4da3e566fe31cd2ed4a28c 100644 --- a/docs/html-intl/intl/ko/guide/topics/resources/runtime-changes.jd +++ b/docs/html-intl/intl/ko/guide/topics/resources/runtime-changes.jd @@ -22,41 +22,41 @@ page.tags=액티비티, 수명 주기

    몇몇 기기 구성은 런타임 중에 변경될 수 있습니다 -(예: 화면 방향, 키보드 가용성 및 언어 등). 그러한 변경이 일어나는 경우, -Android는 실행 중인 +(예: 화면 방향, 키보드 가용성 및 언어 등). 그러한 변경이 일어나는 경우, +Android는 실행 중인 {@link android.app.Activity}를 다시 시작합니다({@link android.app.Activity#onDestroy()} 호출, 뒤이어 {@link -android.app.Activity#onCreate(Bundle) onCreate()} 호출). 이런 동작은 여러분이 제공한 +android.app.Activity#onCreate(Bundle) onCreate()} 호출). 이런 동작은 여러분이 제공한 대체 리소스로 애플리케이션을 자동으로 다시 로딩함으로써 새로운 기기 구성에 애플리케이션이 적응하는 것을 돕도록 설계되었습니다(예: 다양한 화면 방향과 크기에 대한 다양한 레이아웃).

    -

    다시 시작을 적절히 처리하려면 액티비티가 정상적인 +

    다시 시작을 적절히 처리하려면 액티비티가 정상적인 액티비티 -수명 주기를 통해 이전 상태를 복원하는 것이 중요합니다. 여기에서 Android는 -{@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()}를 호출한 다음에 액티비티를 소멸시켜 -애플리케이션 상태에 대한 데이터를 저장할 수 있습니다. 그러면 +수명 주기를 통해 이전 상태를 복원하는 것이 중요합니다. 여기에서 Android는 +{@link android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()}를 호출한 다음에 액티비티를 소멸시켜 +애플리케이션 상태에 대한 데이터를 저장할 수 있습니다. 그러면 {@link android.app.Activity#onCreate(Bundle) onCreate()} 또는 {@link android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()} 중에 상태를 복원할 수 있습니다.

    -

    애플리케이션이 애플리케이션 상태를 그대로 유지한 채 스스로 다시 시작할 수 있는지 시험해 보려면, -구성 변경을 일으켜보아야 합니다(예를 들어 화면 방향 변경 등). 이는 애플리케이션에서 여러 가지 작업을 수행하는 -동안 해봅니다. 애플리케이션이 언제든 사용자 데이터나 상태를 손실하지 않고 -다시 시작할 수 있어야 합니다. 그래야 구성 변경과 같은 이벤트를 처리할 수 있기 때문입니다. 그렇지 않으면 -사용자가 걸려오는 전화를 받은 다음 한참 후에 애플리케이션으로 돌아오면 애플리케이션 프로세스가 이미 +

    애플리케이션이 애플리케이션 상태를 그대로 유지한 채 스스로 다시 시작할 수 있는지 시험해 보려면, +구성 변경을 일으켜보아야 합니다(예를 들어 화면 방향 변경 등). 이는 애플리케이션에서 여러 가지 작업을 수행하는 +동안 해봅니다. 애플리케이션이 언제든 사용자 데이터나 상태를 손실하지 않고 +다시 시작할 수 있어야 합니다. 그래야 구성 변경과 같은 이벤트를 처리할 수 있기 때문입니다. 그렇지 않으면 +사용자가 걸려오는 전화를 받은 다음 한참 후에 애플리케이션으로 돌아오면 애플리케이션 프로세스가 이미 소멸되어 있을 수 있습니다. 액티비티 상태를 복원하는 방법을 배우려면, 액티비티 수명 주기에 관해 읽어보십시오.

    -

    하지만, 애플리케이션을 다시 시작하고 상당량의 데이터를 복원하면 비용도 많이 들고 -불량한 사용자 환경이 만들어지는 상황에 직면할 수도 있습니다. 그러한 상황이라면, +

    하지만, 애플리케이션을 다시 시작하고 상당량의 데이터를 복원하면 비용도 많이 들고 +불량한 사용자 환경이 만들어지는 상황에 직면할 수도 있습니다. 그러한 상황이라면, 두 가지 다른 옵션이 있습니다.

    1. 구성 변경 중에 객체 보존하기 -

      구성이 변경되는 중에 액티비티가 다시 시작될 수 있게 허용하되, 액티비티의 새 인스턴스에 상태 +

      구성이 변경되는 중에 액티비티가 다시 시작될 수 있게 허용하되, 액티비티의 새 인스턴스에 상태 저장 객체를 넣습니다.

    2. 구성 변경 직접 처리하기 -

      특정 구성 변경 중에 시스템이 액티비티를 다시 시작하도록 하지 못하게 방지하되, -구성이 실제로 변경되면 콜백을 수신하도록 하여 필요에 따라 액티비티를 수동으로 업데이트할 수 +

      특정 구성 변경 중에 시스템이 액티비티를 다시 시작하도록 하지 못하게 방지하되, +구성이 실제로 변경되면 콜백을 수신하도록 하여 필요에 따라 액티비티를 수동으로 업데이트할 수 있도록 합니다.

    @@ -64,30 +64,30 @@ android.app.Activity#onRestoreInstanceState(Bundle) onRestoreInstanceState()}

    구성 변경 중에 객체 보존하기

    -

    액티비티를 다시 시작하려면 많은 수의 데이터 세트를 복구해야 하는 경우, 네트워크 연결을 -다시 설정하거나 다른 집약적 작업을 수행한 다음 완전히 다시 시작하십시오. -구성 변경 때문에 사용자 환경이 느려질 수 있습니다. 또한, 액티비티 상태를 완전히 복원하려면 +

    액티비티를 다시 시작하려면 많은 수의 데이터 세트를 복구해야 하는 경우, 네트워크 연결을 +다시 설정하거나 다른 집약적 작업을 수행한 다음 완전히 다시 시작하십시오. +구성 변경 때문에 사용자 환경이 느려질 수 있습니다. 또한, 액티비티 상태를 완전히 복원하려면 {@link android.os.Bundle}을 사용할 수도 있습니다. 이것은 시스템이 개발자 대신 {@link -android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} 콜백으로 저장해두는 것입니다. 이것은 대형 객체(예: 비트맵)를 담도록 -디자인된 것이 아니며 이 안의 데이터는 반드시 직렬화했다가 다시 역직렬화해야 합니다. 이렇게 하면 -메모리를 아주 많이 소모할 수 있으며 구성 변경이 느려질 수 있습니다. 이와 같은 상황에서는 +android.app.Activity#onSaveInstanceState(Bundle) onSaveInstanceState()} 콜백으로 저장해두는 것입니다. 이것은 대형 객체(예: 비트맵)를 담도록 +디자인된 것이 아니며 이 안의 데이터는 반드시 직렬화했다가 다시 역직렬화해야 합니다. 이렇게 하면 +메모리를 아주 많이 소모할 수 있으며 구성 변경이 느려질 수 있습니다. 이와 같은 상황에서는 액티비티를 다시 초기화해야 한다는 부담을 해결하기 위해 액티비티가 구성 변경으로 인해 다시 시작되었을 때 {@link -android.app.Fragment}를 보존하면 됩니다. 이 프래그먼트에는 +android.app.Fragment}를 보존하면 됩니다. 이 프래그먼트에는 보존하고자 하는 상태 저장 객체에 대한 참조를 담을 수 있습니다.

    -

    Android 시스템이 구성 변경으로 인하여 액티비티를 종료시킬 때, 액티비티에서 보존하기로 표시해둔 -프래그먼트는 소멸되지 않습니다. 그러한 프래그먼트를 액티비티에 추가하면 +

    Android 시스템이 구성 변경으로 인하여 액티비티를 종료시킬 때, 액티비티에서 보존하기로 표시해둔 +프래그먼트는 소멸되지 않습니다. 그러한 프래그먼트를 액티비티에 추가하면 상태 저장 객체를 보존할 수 있습니다.

    런타임 구성 변경 중에 상태 저장 객체를 프래그먼트에 보존해두는 방법은 다음과 같습니다.

      -
    1. {@link android.app.Fragment} 클래스를 확장하고 상태 저장 +
    2. {@link android.app.Fragment} 클래스를 확장하고 상태 저장 객체에 참조를 선언합니다.
    3. 프래그먼트가 생성되면 {@link android.app.Fragment#setRetainInstance(boolean)}를 호출합니다.
    4. 해당 프래그먼트를 액티비티에 추가합니다.
    5. -
    6. {@link android.app.FragmentManager}를 사용하여 액티비티가 다시 시작될 때 프래그먼트를 +
    7. {@link android.app.FragmentManager}를 사용하여 액티비티가 다시 시작될 때 프래그먼트를 검색합니다.
    @@ -117,16 +117,16 @@ public class RetainedFragment extends Fragment { }
    -

    주의: 어느 객체든 저장할 수 있지만, +

    주의: 어느 객체든 저장할 수 있지만, {@link android.app.Activity}에 묶여 있는 객체는 절대로 전달하면 안 됩니다. 예를 들어 {@link android.graphics.drawable.Drawable}, {@link android.widget.Adapter}, {@link android.view.View} - 또는 {@link android.content.Context}와 연관된 기타 모든 객체가 이에 해당됩니다. 이런 것을 전달하면, -원래 액티비티 인스턴스의 모든 보기와 리소스를 몽땅 누출시킵니다. (리소스 누출이란 -애플리케이션이 리소스에 대한 보유권을 유지하고 있어 가비지 수집의 대상이 될 수 없고, 따라서 엄청난 양의 메모리가 + 또는 {@link android.content.Context}와 연관된 기타 모든 객체가 이에 해당됩니다. 이런 것을 전달하면, +원래 액티비티 인스턴스의 모든 보기와 리소스를 몽땅 누출시킵니다. (리소스 누출이란 +애플리케이션이 리소스에 대한 보유권을 유지하고 있어 가비지 수집의 대상이 될 수 없고, 따라서 엄청난 양의 메모리가 손실된다는 뜻입니다.)

    -

    그런 다음 {@link android.app.FragmentManager}를 사용하여 프래그먼트를 액티비티에 추가합니다. -프래그먼트에서 데이터 객체를 가져오려면 런타임 구성 변경 중에 액티비티가 다시 시작될 때 +

    그런 다음 {@link android.app.FragmentManager}를 사용하여 프래그먼트를 액티비티에 추가합니다. +프래그먼트에서 데이터 객체를 가져오려면 런타임 구성 변경 중에 액티비티가 다시 시작될 때 가져오면 됩니다. 예를 들어, 액티비티를 다음과 같이 정의합니다.

    @@ -165,10 +165,10 @@ public class MyActivity extends Activity {
     }
     
    -

    이 예시에서 {@link android.app.Activity#onCreate(Bundle) onCreate()}는 프래그먼트를 추가하거나 -이에 대한 참조를 복원합니다. {@link android.app.Activity#onCreate(Bundle) onCreate()} 또한 -프래그먼트 인스턴스 안에 상태 저장 객체를 저장합니다. -{@link android.app.Activity#onDestroy() onDestroy()}는 보존된 +

    이 예시에서 {@link android.app.Activity#onCreate(Bundle) onCreate()}는 프래그먼트를 추가하거나 +이에 대한 참조를 복원합니다. {@link android.app.Activity#onCreate(Bundle) onCreate()} 또한 +프래그먼트 인스턴스 안에 상태 저장 객체를 저장합니다. +{@link android.app.Activity#onDestroy() onDestroy()}는 보존된 프래그먼트 인스턴스 내부의 상태 저장 객체를 업데이트합니다.

    @@ -177,26 +177,26 @@ public class MyActivity extends Activity {

    구성 변경 직접 처리하기

    -

    애플리케이션이 특정 구성 변경 중에 리소스를 업데이트하지 않아도 되고 -그와 동시에 성능 한계가 있어 액티비티 다시 시작을 피해야 하는 경우, -액티비티가 구성 변경을 알아서 처리한다고 선언하면 됩니다. +

    애플리케이션이 특정 구성 변경 중에 리소스를 업데이트하지 않아도 되고 +그와 동시에 성능 한계가 있어 액티비티 다시 시작을 피해야 하는 경우, +액티비티가 구성 변경을 알아서 처리한다고 선언하면 됩니다. 이렇게 하면 시스템이 액티비티를 다시 시작하지 않도록 방지할 수 있습니다.

    -

    참고: 구성 변경을 직접 처리하면 대체 리소스를 사용하는 것이 -훨씬 더 까다로워질 수 있습니다. 시스템이 개발자 대신 자동으로 이를 적용해주지 않기 -때문입니다. 이 기법은 구성 변경으로 인한 재시작을 반드시 피해야만 하는 경우 최후의 수단으로서만 +

    참고: 구성 변경을 직접 처리하면 대체 리소스를 사용하는 것이 +훨씬 더 까다로워질 수 있습니다. 시스템이 개발자 대신 자동으로 이를 적용해주지 않기 +때문입니다. 이 기법은 구성 변경으로 인한 재시작을 반드시 피해야만 하는 경우 최후의 수단으로서만 고려해야 하며 대부분의 애플리케이션에는 권장하지 않습니다.

    -

    액티비티가 구성 변경을 직접 처리한다고 선언하려면, 매니페스트 파일의 적절한 {@code <activity>} 요소를 편집하여 +

    액티비티가 구성 변경을 직접 처리한다고 선언하려면, 매니페스트 파일의 적절한 {@code <activity>} 요소를 편집하여 처리하고자 하는 구성을 나타내는 값이 있는 {@code -android:configChanges} 속성을 포함하도록 +android:configChanges} 속성을 포함하도록 합니다. 가능한 값은 {@code -android:configChanges} 속성에 대한 관련 문서에 목록으로 나열되어 있습니다(가장 보편적으로 사용되는 값은 화면 방향이 변경될 때 다시 시작을 방지하는 {@code "orientation"}과 +android:configChanges} 속성에 대한 관련 문서에 목록으로 나열되어 있습니다(가장 보편적으로 사용되는 값은 화면 방향이 변경될 때 다시 시작을 방지하는 {@code "orientation"}과 키보드 가용성이 변경될 때 다시 시작을 방지하는 {@code "keyboardHidden"} -입니다). 이 속성에는 여러 개의 구성 값을 선언할 수 있습니다. 각각을 +입니다). 이 속성에는 여러 개의 구성 값을 선언할 수 있습니다. 각각을 파이프 {@code |} 문자로 구분하면 됩니다.

    -

    예를 들어 다음 매니페스트 코드는 화면 방향 변경과 키보드 가용성 변경을 둘 다 +

    예를 들어 다음 매니페스트 코드는 화면 방향 변경과 키보드 가용성 변경을 둘 다 처리하는 액티비티를 선언하는 것입니다.

    @@ -205,29 +205,29 @@ android:configChanges} 속성에 대한 관련 문서에 목록으로 나열
               android:label="@string/app_name">
     
    -

    이제 이러한 구성 중 하나가 변경되어도 {@code MyActivity}는 다시 시작하지 않습니다. +

    이제 이러한 구성 중 하나가 변경되어도 {@code MyActivity}는 다시 시작하지 않습니다. 그 대신, {@code MyActivity}가 {@link -android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}로의 호출을 받습니다. 이 메서드는 -{@link android.content.res.Configuration} 객체로 전달되며, 이는 새 기기 구성을 -나타냅니다. {@link android.content.res.Configuration}의 필드를 읽어보면 -새 구성을 판별할 수 있고 적절한 변경을 할 수 있습니다. 그러려면 인터페이스에 사용된 리소스를 -업데이트하면 됩니다. 이 메서드가 -호출되면, 액티비티의 {@link android.content.res.Resources} 객체가 -업데이트되어 새 구성에 기반한 리소스를 반환하며, 따라서 시스템이 액티비티를 다시 시작하지 않아도 +android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}로의 호출을 받습니다. 이 메서드는 +{@link android.content.res.Configuration} 객체로 전달되며, 이는 새 기기 구성을 +나타냅니다. {@link android.content.res.Configuration}의 필드를 읽어보면 +새 구성을 판별할 수 있고 적절한 변경을 할 수 있습니다. 그러려면 인터페이스에 사용된 리소스를 +업데이트하면 됩니다. 이 메서드가 +호출되면, 액티비티의 {@link android.content.res.Resources} 객체가 +업데이트되어 새 구성에 기반한 리소스를 반환하며, 따라서 시스템이 액티비티를 다시 시작하지 않아도 UI의 요소를 손쉽게 재설정할 수 있게 됩니다.

    -

    주의: Android 3.2(API 레벨 13)부터 기기가 -세로 방향 및 가로 방향 사이를 전환할 때 "화면 크기"도 -같이 변경됩니다. 따라서, +

    주의: Android 3.2(API 레벨 13)부터 기기가 +세로 방향 및 가로 방향 사이를 전환할 때 "화면 크기"도 +같이 변경됩니다. 따라서, API 레벨 13 이상({@code minSdkVersion}{@code targetSdkVersion} 속성에서 선언한 내용에 따름)을 대상으로 개발하는 경우 방향 변경으로 인한 런타임 다시 시작을 방지하고자 하면, {@code "orientation"} 값 외에 {@code "screenSize"} 값도 포함시켜야 합니다. 다시 말해, {@code -android:configChanges="orientation|screenSize"}를 선언해야 합니다. 하지만, 애플리케이션이 API 레벨 12 이하를 -대상으로 하는 경우라면 애플리케이션이 언제든 이 구성 변경을 알아서 처리합니다(이 구성 변경은 +android:configChanges="orientation|screenSize"}를 선언해야 합니다. 하지만, 애플리케이션이 API 레벨 12 이하를 +대상으로 하는 경우라면 애플리케이션이 언제든 이 구성 변경을 알아서 처리합니다(이 구성 변경은 액티비티를 다시 시작하지 않습니다. 이는 Android 3.2 이상 기기에서 실행되는 경우에도 마찬가지입니다).

    예를 들어, 다음 {@link -android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} 구현은 +android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} 구현은 현재 기기의 방향을 확인합니다.

    @@ -244,36 +244,36 @@ public void onConfigurationChanged(Configuration newConfig) {
     }
     
    -

    {@link android.content.res.Configuration} 객체는 변경된 것만이 아니라 현재 -구성 전체를 나타냅니다. 대부분의 경우에는 구성이 정확히 어떻게 -변경되었는지에는 관심이 없고 처리 중인 구성에 대체 리소스를 제공하는 모든 리소스를 그저 +

    {@link android.content.res.Configuration} 객체는 변경된 것만이 아니라 현재 +구성 전체를 나타냅니다. 대부분의 경우에는 구성이 정확히 어떻게 +변경되었는지에는 관심이 없고 처리 중인 구성에 대체 리소스를 제공하는 모든 리소스를 그저 재할당하기만 하면 됩니다. 예를 들어 이제 {@link android.content.res.Resources} 객체가 업데이트되었으니 {@link android.widget.ImageView#setImageResource(int) -setImageResource()}가 있는 모든 -{@link android.widget.ImageView}와 +setImageResource()}가 있는 모든 +{@link android.widget.ImageView}와 새 구성에 대한 적절한 리소스를 재설정할 수 있습니다(리소스 제공에 설명된 바와 같음).

    {@link -android.content.res.Configuration} 필드에서 가져온 값이 -{@link android.content.res.Configuration} 클래스에서 가져온 특정 상수와 일치하는 정수라는 점을 눈여겨 보십시오. 각 필드에 +android.content.res.Configuration} 필드에서 가져온 값이 +{@link android.content.res.Configuration} 클래스에서 가져온 특정 상수와 일치하는 정수라는 점을 눈여겨 보십시오. 각 필드에 어느 상수를 써야 하는지에 대한 관련 문서는 {@link android.content.res.Configuration} 참조에 있는 적절한 필드를 참조하십시오.

    -

    명심할 점: 액티비티가 직접 구성 변경을 처리한다고 선언하는 경우, -대체를 제공하는 모든 요소에 대해 본인이 직접 책임을 지게 됩니다. 액티비티가 직접 -방향 변경을 처리하고 가로 및 세로 방향 사이에서 바뀌어야 하는 이미지가 있는 경우, +

    명심할 점: 액티비티가 직접 구성 변경을 처리한다고 선언하는 경우, +대체를 제공하는 모든 요소에 대해 본인이 직접 책임을 지게 됩니다. 액티비티가 직접 +방향 변경을 처리하고 가로 및 세로 방향 사이에서 바뀌어야 하는 이미지가 있는 경우, 각 리소스를 각 요소에 재할당해야 하며 이를 {@link android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()} 중에 수행해야 합니다.

    -

    이러한 구성 변경을 기반으로 애플리케이션을 업데이트하지 않아도 되는 경우, +

    이러한 구성 변경을 기반으로 애플리케이션을 업데이트하지 않아도 되는 경우, 대신 {@link -android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}를 구현하지 않으면 됩니다. 이런 -경우, 구성 변경 전에 쓰였던 리소스가 모두 그대로 사용되고 액티비티의 다시 시작만 -피한 것이 됩니다. 그러나, 애플리케이션은 -언제든 종료되고 이전 상태를 그대로 유지한 채 다시 시작될 수 있어야 합니다 정상적인 액티비티 -수명 주기 중에 상태 유지에서의 탈출 방안으로 이 기법을 고려해서는 안 됩니다. 이는 애플리케이션이 -다시 시작되지 않도록 방지할 수 없는, 다른 구성 변경도 여럿 있어서일뿐만 아니라, 사용자가 -애플리케이션을 떠났을 경우 해당 사용자가 다시 돌아오기 전에 소멸되는 것과 같은 이벤트를 처리해야 하기 때문이라는 +android.app.Activity#onConfigurationChanged(Configuration) onConfigurationChanged()}를 구현하지 않으면 됩니다. 이런 +경우, 구성 변경 전에 쓰였던 리소스가 모두 그대로 사용되고 액티비티의 다시 시작만 +피한 것이 됩니다. 그러나, 애플리케이션은 +언제든 종료되고 이전 상태를 그대로 유지한 채 다시 시작될 수 있어야 합니다 정상적인 액티비티 +수명 주기 중에 상태 유지에서의 탈출 방안으로 이 기법을 고려해서는 안 됩니다. 이는 애플리케이션이 +다시 시작되지 않도록 방지할 수 없는, 다른 구성 변경도 여럿 있어서일뿐만 아니라, 사용자가 +애플리케이션을 떠났을 경우 해당 사용자가 다시 돌아오기 전에 소멸되는 것과 같은 이벤트를 처리해야 하기 때문이라는 이유도 있습니다.

    액티비티 내에서 처리할 수 있는 구성 변경이 무엇인지에 대한 자세한 내용은 {@code diff --git a/docs/html-intl/intl/ko/guide/topics/ui/controls.jd b/docs/html-intl/intl/ko/guide/topics/ui/controls.jd index bf873980beb6abafb46104bf285714f04e62bc0f..9561ba05771ba4e2a6f29caea9a5b14014c04d9a 100644 --- a/docs/html-intl/intl/ko/guide/topics/ui/controls.jd +++ b/docs/html-intl/intl/ko/guide/topics/ui/controls.jd @@ -7,11 +7,11 @@ parent.link=index.html -

    입력 제어는 앱의 사용자 인터페이스에 있는 대화형 구성 요소입니다. +

    입력 제어는 앱의 사용자 인터페이스에 있는 대화형 구성 요소입니다. Android는 버튼, 텍스트 필드, 찾기 막대, 확인란, 확대 버튼, 전환 버튼 등과 같이 UI에서 사용할 수 있도록 매우 다양한 제어를 제공합니다.

    -

    UI에 입력 제어를 추가하려면 단순히 XML 레이아웃에 XML 요소를 하나 추가하기만 하면 됩니다. +

    UI에 입력 제어를 추가하려면 단순히 XML 레이아웃에 XML 요소를 하나 추가하기만 하면 됩니다. 다음은 텍스트 필드와 버튼이 있는 레이아웃을 예시로 나타낸 것입니다.

    @@ -33,16 +33,16 @@ UI에서 사용할 수 있도록 매우 다양한 제어를 제공합니다.

    </LinearLayout>
    -

    각 입력 제어는 특정한 입력 이벤트를 지원하므로, 사용자가 텍스트를 입력할 때 또는 버튼을 터치할 때 +

    각 입력 제어는 특정한 입력 이벤트를 지원하므로, 사용자가 텍스트를 입력할 때 또는 버튼을 터치할 때 이벤트를 처리할 수 있게 해줍니다.

    보편적인 제어

    -

    다음은 앱에서 사용할 수 있는 몇 가지 보편적인 제어를 목록으로 나열한 것입니다. 링크를 따라가면 각 제어에 대해 +

    다음은 앱에서 사용할 수 있는 몇 가지 보편적인 제어를 목록으로 나열한 것입니다. 링크를 따라가면 각 제어에 대해 좀 더 자세히 알아볼 수 있습니다.

    참고: Android는 여기에 나열된 것보다 몇 가지 더 많은 제어를 제공합니다. - 더 많은 내용을 알아보려면 {@link android.widget} 패키지를 탐색해보십시오. + 더 많은 내용을 알아보려면 {@link android.widget} 패키지를 탐색해보십시오. 앱에 특정한 종류의 입력 제어가 필요한 경우, 나름의 사용자 지정 구성 요소를 직접 구축해도 됩니다.

    -

    이동통신 국가 코드(MCC)에 선택적으로 이동통신 네트워크 코드(MNC)가 이어지는 형태로, +

    이동통신 국가 코드(MCC)에 선택적으로 이동통신 네트워크 코드(MNC)가 이어지는 형태로, 기기의 SIM 카드에서 가져옵니다. 예를 들어, mcc310은 모든 이동통신사를 포함한 미국이고, mcc310-mnc004는 Verizon을 사용하는 미국, mcc208-mnc00은 Orange를 사용하는 프랑스입니다.

    @@ -293,11 +293,11 @@ background.png} 이미지를 참조하는 데 사용하는 리소스 ID는 항 SIM 카드에서 가져옵니다.

    MCC만 단독으로 사용할 수도 있습니다(예를 들어, 애플리케이션에 국가별 합법적 리소스를 포함하는 경우). 언어에 기초해서만 지정해야 할 경우, -언어 및 지역 한정자를 대신 사용합니다(아래에 설명). MCC와 +언어 및 지역 한정자를 대신 사용합니다(아래에 설명). MCC와 MNC 한정자를 사용할 경우, 조심해서 사용하고 예상한 대로 작동하는지 테스트해야 합니다.

    또한, 구성 필드 {@link android.content.res.Configuration#mcc}와 {@link -android.content.res.Configuration#mnc}를 참조하십시오. 이 구성 필드는 각각 이동통신 국가 코드와 +android.content.res.Configuration#mnc}를 참조하십시오. 이 구성 필드는 각각 이동통신 국가 코드와 이동통신 네트워크 코드를 나타냅니다.

    언어는 두 글자의 ISO -639-1 언어 코드로 정의되고, +639-1 언어 코드로 정의되고, 뒤이어 두 글자의 ISO 3166-1-alpha-2 지역 코드가 선택적으로 따라옵니다(소문자 "{@code r}" 뒤에 붙음).

    - 코드는 대소문자를 구별하지 않습니다. {@code r} 접두사는 + 코드는 대소문자를 구별하지 않습니다. {@code r} 접두사는 지역 부분을 구별하기 위해 사용합니다. 지역만 지정할 수는 없습니다.

    -

    사용자가 시스템 설정에서 언어를 변경할 경우 +

    사용자가 시스템 설정에서 언어를 변경할 경우 애플리케이션 수명 중에 변경될 수 있습니다. 런타임에서 애플리케이션에 어떤 영향을 미치는지 자세히 알아보려면 런타임 변경 처리를 참조하십시오.

    다른 여러 언어에 맞게 애플리케이션을 지역화하기 위한 전체 지침은 지역화를 참조하십시오.

    -

    또한, 현재 로케일을 나타내는 {@link android.content.res.Configuration#locale} 구성 필드도 +

    또한, 현재 로케일을 나타내는 {@link android.content.res.Configuration#locale} 구성 필드도 참조하십시오.

    -

    리소스를 사용해야 하는 {@code dp} 단위에서 최소 이용 가능한 화면 너비를 지정합니다. -이는 <N> 값이 정의합니다. 이 구성 -값은 현재 실제 너비에 맞추기 위해 화면 방향이 가로와 세로 사이를 오가며 바뀔 때 +

    리소스를 사용해야 하는 {@code dp} 단위에서 최소 이용 가능한 화면 너비를 지정합니다. +이는 <N> 값이 정의합니다. 이 구성 +값은 현재 실제 너비에 맞추기 위해 화면 방향이 가로와 세로 사이를 오가며 바뀔 때 변경됩니다.

    애플리케이션이 이 구성에 대해 서로 다른 값이 포함된 여러 개의 리소스 디렉터리를 제공하면, -시스템은 기기의 현재 화면 너비에 가장 가까운(그러나 이를 초과하지 않는) -값을 사용합니다. 이 값은 -화면 장식을 감안한 것이므로, 기기의 왼쪽이나 오른쪽 가장자리에 -영구 UI 요소가 있을 경우, 기기는 +시스템은 기기의 현재 화면 너비에 가장 가까운(그러나 이를 초과하지 않는) +값을 사용합니다. 이 값은 +화면 장식을 감안한 것이므로, 기기의 왼쪽이나 오른쪽 가장자리에 +영구 UI 요소가 있을 경우, 기기는 이러한 UI 요소를 감안하여 애플리케이션의 이용 가능한 공간을 줄여서 실제 화면 크기보다 작은 너비 값을 사용합니다.

    API 레벨 13에서 추가되었습니다.

    현재 화면 너비를 보유한 {@link android.content.res.Configuration#screenWidthDp} 구성 필드도 참조하십시오.

    -

    여러 가지 화면에 맞는 디자인과 한정자 사용에 관한 자세한 정보는 +

    여러 가지 화면에 맞는 디자인과 한정자 사용에 관한 자세한 정보는 다중 화면 지원 개발자 가이드를 참조하십시오.

    -

    리소스가 사용되어야 하는 최소한의 사용 가능한 화면 높이를 "dp" 단위로 나타냅니다. -이는 <N> 값이 정의합니다. 이 구성 -값은 현재 실제 높이에 맞추기 위해 화면 방향이 가로와 세로 사이를 오가며 바뀔 때 +

    리소스가 사용되어야 하는 최소한의 사용 가능한 화면 높이를 "dp" 단위로 나타냅니다. +이는 <N> 값이 정의합니다. 이 구성 +값은 현재 실제 높이에 맞추기 위해 화면 방향이 가로와 세로 사이를 오가며 바뀔 때 변경됩니다.

    애플리케이션이 이 구성에 대해 서로 다른 값이 포함된 여러 개의 리소스 디렉터리를 제공하면, -시스템은 기기의 현재 화면 높이에 가장 가까운(그러나 이를 초과하지 않는) -값을 사용합니다. 이 값은 -화면 장식을 감안한 것이므로, 기기의 상단이나 하단 가장자리에 -영구 UI 요소가 있을 경우, 기기는 +시스템은 기기의 현재 화면 높이에 가장 가까운(그러나 이를 초과하지 않는) +값을 사용합니다. 이 값은 +화면 장식을 감안한 것이므로, 기기의 상단이나 하단 가장자리에 +영구 UI 요소가 있을 경우, 기기는 이러한 UI 요소를 감안하여 애플리케이션의 이용 가능한 공간을 줄여서 - 실제 화면 크기보다 작은 높이 값을 사용합니다. -상태 표시줄에 고정되지 않은 화면 장식(예를 들어 -전화 상태 표시줄은 전체 화면에서 숨길 수 있음)은 여기에서 감안하지 않았고, -제목 표시줄이나 작업 모음 등의 창 장식도 감안되지 않았으므로, 애플리케이션 입장에서는 자신이 지정한 것보다 어느 정도 작은 공간을 + 실제 화면 크기보다 작은 높이 값을 사용합니다. +상태 표시줄에 고정되지 않은 화면 장식(예를 들어 +전화 상태 표시줄은 전체 화면에서 숨길 수 있음)은 여기에서 감안하지 않았고, +제목 표시줄이나 작업 모음 등의 창 장식도 감안되지 않았으므로, 애플리케이션 입장에서는 자신이 지정한 것보다 어느 정도 작은 공간을 받아들일 대비를 해야 합니다.

    API 레벨 13에서 추가되었습니다.

    현재 화면 너비를 보유한 {@link android.content.res.Configuration#screenHeightDp} 구성 필드도 참조하십시오.

    -

    여러 가지 화면에 맞는 디자인과 한정자 사용에 관한 자세한 정보는 +

    여러 가지 화면에 맞는 디자인과 한정자 사용에 관한 자세한 정보는 다중 화면 지원 개발자 가이드를 참조하십시오.

      -
    • {@code small}: 저밀도 QVGA 화면과 비슷한 +
    • {@code small}: 저밀도 QVGA 화면과 비슷한 크기의 화면입니다. 작은 화면의 최소 레이아웃 크기는 -약 320x426 dp단위입니다. 이 화면의 예시로는 QVGA 저밀도 및 VGA 고밀도가 +약 320x426 dp단위입니다. 이 화면의 예시로는 QVGA 저밀도 및 VGA 고밀도가 있습니다.
    • -
    • {@code normal}: 중밀도 HVGA 화면과 +
    • {@code normal}: 중밀도 HVGA 화면과 비슷한 크기의 화면입니다. 정상 화면의 - 최소 레이아웃 크기는 약 320x470 dp 단위입니다. 이 화면의 예로는 + 최소 레이아웃 크기는 약 320x470 dp 단위입니다. 이 화면의 예로는 WQVGA 저밀도, HVGA 중밀도, WVGA 고밀도 등이 있습니다.
    • -
    • {@code large}: 중밀도 VGA 화면과 +
    • {@code large}: 중밀도 VGA 화면과 비슷한 크기의 화면입니다. 큰 화면의 최소 레이아웃 크기는 약 480x640 dp 단위입니다. 이 화면의 예시로는 VGA 및 WVGA 중밀도 화면이 있습니다.
    • -
    • {@code xlarge}: 일반적인 중밀도 HVGA 화면보다 상당히 큰 화면을 +
    • {@code xlarge}: 일반적인 중밀도 HVGA 화면보다 상당히 큰 화면을 말합니다. 초대형 화면의 - 최소 레이아웃 크기는 약 720x960 dp 단위입니다. 대부분의 경우, 초대형 화면 기기는 -주머니에 넣어 다니기에 너무 큽니다. 따라서 태블릿 스타일의 기기일 가능성이 + 최소 레이아웃 크기는 약 720x960 dp 단위입니다. 대부분의 경우, 초대형 화면 기기는 +주머니에 넣어 다니기에 너무 큽니다. 따라서 태블릿 스타일의 기기일 가능성이 높습니다. API 레벨 9에서 추가되었습니다.
    -

    참고: 크기 한정자를 사용하더라도 해당 리소스가 그 크기의 화면 -전용이라는 뜻은 아닙니다. 현재 기기 구성과 더욱 잘 맞는 한정자가 포함된 대체 리소스를 -제공하지 않으면, +

    참고: 크기 한정자를 사용하더라도 해당 리소스가 그 크기의 화면 +전용이라는 뜻은 아닙니다. 현재 기기 구성과 더욱 잘 맞는 한정자가 포함된 대체 리소스를 +제공하지 않으면, 시스템이 가장 잘 일치하는 리소스를 사용합니다.

    주의: 모든 리소스가 현재 화면보다 크기 한정자를 사용하는 경우, 시스템은 리소스를 사용하지 않으며 애플리케이션은 런타임에 작동이 중단됩니다(예를 들어, 모든 레이아웃 리소스에 {@code xlarge} 한정자가 태그되어 있지만 기기는 일반 크기 화면일 경우 ).

    API 레벨 4에서 추가되었습니다.

    - -

    자세한 정보는 다중 화면 + +

    자세한 정보는 다중 화면 지원을 참조하십시오.

    -

    {@link android.content.res.Configuration#screenLayout} 구성 필드도 참조하십시오. -이것은 화면이 소형, 일반 크기 또는 +

    {@link android.content.res.Configuration#screenLayout} 구성 필드도 참조하십시오. +이것은 화면이 소형, 일반 크기 또는 대형인지를 나타냅니다.

    • {@code notouch}: 기기에 터치 스크린이 없습니다.
    • -
    • {@code finger}: 기기에 터치 스크린이 있으며 이를 +
    • {@code finger}: 기기에 터치 스크린이 있으며 이를 사용자의 손가락을 사용한 방향 지시 상호 작용을 통해 쓰도록 되어 있습니다.
    -

    {@link android.content.res.Configuration#touchscreen} 구성 필드도 참조하십시오. +

    {@link android.content.res.Configuration#touchscreen} 구성 필드도 참조하십시오. 이는 기기에서 사용되는 터치 스크린의 유형을 나타냅니다.

      -
    • {@code keysexposed}: 기기에서 키보드를 사용할 수 있습니다. 키보드에 -소프트웨어 키보드가 활성화되어 있으면(이럴 가능성이 큽니다), 하드웨어 키보드가 사용자에게 노출되어 있지 -않거나 기기에 하드웨어 키보드가 없더라도 이 리소스를 사용할 수 있습니다. 소프트웨어 -키보드가 제공되어 있지 않거나 비활성화되어 있는 경우 이것은 하드웨어 키보드가 노출되어 있을 때에만 +
    • {@code keysexposed}: 기기에서 키보드를 사용할 수 있습니다. 키보드에 +소프트웨어 키보드가 활성화되어 있으면(이럴 가능성이 큽니다), 하드웨어 키보드가 사용자에게 노출되어 있지 +않거나 기기에 하드웨어 키보드가 없더라도 이 리소스를 사용할 수 있습니다. 소프트웨어 +키보드가 제공되어 있지 않거나 비활성화되어 있는 경우 이것은 하드웨어 키보드가 노출되어 있을 때에만 사용할 수 있습니다.
    • -
    • {@code keyshidden}: 기기에서 하드웨어 키보드를 사용할 수 있지만 +
    • {@code keyshidden}: 기기에서 하드웨어 키보드를 사용할 수 있지만 숨겨져 있고 이에 더하여 기기에 소프트웨어 키보드가 활성화되어 있지 않습니다.
    • -
    • {@code keyssoft}: 기기에 활성화된 소프트웨어 키보드가 있습니다(표시 여부는 +
    • {@code keyssoft}: 기기에 활성화된 소프트웨어 키보드가 있습니다(표시 여부는 무관).

    keysexposed 리소스를 제공하지만 keyssoft -리소스는 제공하지 않는다면, 시스템은 소프트웨어 키보드가 활성화되어 있는 동안은 키보드가 보이는지 여부와 관계없이 keysexposed +리소스는 제공하지 않는다면, 시스템은 소프트웨어 키보드가 활성화되어 있는 동안은 키보드가 보이는지 여부와 관계없이 keysexposed 리소스를 사용합니다.

    -

    이것은 사용자가 하드웨어 키보드를 여는 경우 애플리케이션 수명 중에 -변경될 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 +

    이것은 사용자가 하드웨어 키보드를 여는 경우 애플리케이션 수명 중에 +변경될 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 참조하십시오.

    또한, 구성 필드 {@link android.content.res.Configuration#hardKeyboardHidden}과 {@link -android.content.res.Configuration#keyboardHidden}을 참조하십시오. 이 필드는 각각 하드웨어 키보드의 가시성과 +android.content.res.Configuration#keyboardHidden}을 참조하십시오. 이 필드는 각각 하드웨어 키보드의 가시성과 모든 종류의 키보드(소프트웨어 포함)의 가시성을 나타냅니다.

    • {@code nokeys}: 기기에 텍스트 입력을 위한 하드웨어 키가 없습니다.
    • -
    • {@code qwerty}: 기기에 하드웨어 쿼티 키보드가 있습니다(이것이 +
    • {@code qwerty}: 기기에 하드웨어 쿼티 키보드가 있습니다(이것이 사용자 에게 표시되는지 여부는 무관).
    • -
    • {@code 12key}: 기기에 하드웨어 12-키 키보드가 있습니다(이것이 사용자에게 표시되는지 여부는 +
    • {@code 12key}: 기기에 하드웨어 12-키 키보드가 있습니다(이것이 사용자에게 표시되는지 여부는 무관).
    -

    {@link android.content.res.Configuration#keyboard} 구성 필드도 참조하십시오. +

    {@link android.content.res.Configuration#keyboard} 구성 필드도 참조하십시오. 이는 기본 텍스트 입력 메서드를 사용할 수 있는지 여부를 나타냅니다.

    • {@code navexposed}: 사용자가 탐색 키를 사용할 수 있습니다.
    • -
    • {@code navhidden}: 탐색 키를 사용할 수 없습니다(예: 닫힌 뚜껑 뒤에 있는 +
    • {@code navhidden}: 탐색 키를 사용할 수 없습니다(예: 닫힌 뚜껑 뒤에 있는 경우).
    -

    이것은 사용자가 탐색 키를 드러내는 경우 애플리케이션 수명 중에 -변경될 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 +

    이것은 사용자가 탐색 키를 드러내는 경우 애플리케이션 수명 중에 +변경될 수 있습니다. 이것이 런타임에 애플리케이션에 어떤 영향을 미치는지 알아보려면 런타임 변경 처리를 참조하십시오.

    -

    {@link android.content.res.Configuration#navigationHidden} 구성 +

    {@link android.content.res.Configuration#navigationHidden} 구성 필드도 참조하십시오. 이는 탐색 키가 숨겨져 있는지 여부를 나타냅니다.

      -
    • {@code nonav}: 기기에 터치 스크린을 제외하고 다른 탐색 기능이 +
    • {@code nonav}: 기기에 터치 스크린을 제외하고 다른 탐색 기능이 없습니다.
    • {@code dpad}: 기기에 탐색용 방향 패드(d-pad)가 있습니다.
    • {@code trackball}: 기기에 탐색용 트랙볼이 있습니다.
    • {@code wheel}: 기기에 탐색용 방향 휠이 있습니다.
    -

    {@link android.content.res.Configuration#navigation} 구성 필드도 참조하십시오. +

    {@link android.content.res.Configuration#navigation} 구성 필드도 참조하십시오. 이는 사용 가능한 탐색 메서드의 유형을 나타냅니다.

    @@ -69,7 +69,7 @@ UI에서 사용할 수 있도록 매우 다양한 제어를 제공합니다.

    - diff --git a/docs/html-intl/intl/ko/guide/topics/ui/declaring-layout.jd b/docs/html-intl/intl/ko/guide/topics/ui/declaring-layout.jd index 78832368b222416cd099770bcfb96ecabf180ccd..97f9083d6a5712ebdd964c6ca017f21361648fac 100644 --- a/docs/html-intl/intl/ko/guide/topics/ui/declaring-layout.jd +++ b/docs/html-intl/intl/ko/guide/topics/ui/declaring-layout.jd @@ -34,14 +34,14 @@ page.tags=view,viewgroup

    참고 항목

      -
    1. 간단한 사용자 +
    2. 간단한 사용자 인터페이스 구축
    3. 레이아웃은 사용자 인터페이스에 대한 시각적 구조를 정의합니다. 예컨대 액티비티 또는 앱 위젯에 대한 UI가 이에 해당됩니다. 레이아웃을 선언하는 데에는 다음과 같은 두 가지 방법이 있습니다.

        -
      • UI 요소를 XML로 선언. Android가 위젯과 레이아웃 등과 같이 +
      • UI 요소를 XML로 선언. Android가 위젯과 레이아웃 등과 같이 보기 클래스와 하위 클래스에 상응하는 간단한 XML 어휘를 제공합니다.
      • 런타임에 레이아웃 요소를 인스턴트화. 애플리케이션이 프로그래밍 방법으로 보기 및 ViewGroup객체를 만들 수 있습니다(그리고 그 속성을 조작하기도 합니다).
      • @@ -55,26 +55,26 @@ page.tags=view,viewgroup
      • Eclipse용 ADT 플러그인이 XML의 레이아웃 미리보기를 제공합니다. — XML 파일이 열린 상태에서 레이아웃 탭을 선택하십시오.
      • -
      • 또한, -계층 뷰어 도구로 -레이아웃 디버깅도 시도해 보아야 합니다.—이것은 레이아웃 속성 값을 드러내고, -내부 여백/여백 표시기가 있는 와이어프레임을 그리며 개발자가 에뮬레이터 또는 기기에서 디버깅하는 동안 +
      • 또한, +계층 뷰어 도구로 +레이아웃 디버깅도 시도해 보아야 합니다.—이것은 레이아웃 속성 값을 드러내고, +내부 여백/여백 표시기가 있는 와이어프레임을 그리며 개발자가 에뮬레이터 또는 기기에서 디버깅하는 동안 완전히 렌더링된 보기를 제공합니다.
      • layoutopt 도구를 사용하면 레이아웃과 계층을 비효율성 또는 다른 문제에 대하여 재빨리 분석할 수 있게 해줍니다.
      • -

        UI를 XML로 선언하는 것의 이점은 이렇게 하면 애플리케이션을 그 행동을 제어하는 코드로부터 따로 표시하기가 더 좋다는 것입니다. UI 설명은 애플리케이션 코드의 외부에 있습니다. 이는 다시 말해 소스 코드를 수정하고 다시 컴파일링하지 않아도 이를 수정 또는 변경할 수 있다는 뜻입니다. 예를 들어, 서로 다른 화면 방향, 사로 다른 기기 화면 크기 및 서로 다른 언어에 대해 XML 레이아웃을 생성할 수 있습니다. 이외에도 레이아웃을 XML로 선언하면 UI의 구조를 시각화하기가 더 쉬우므로 문제를 디버깅하기도 더 쉽습니다. 따라서, 이 문서는 레이아웃을 XML로 선언하는 방법을 가르치는 데 주안점을 두고 있습니다. 런타임에 보기 객체를 인스턴트화하는 것에 흥미가 있는 경우, -{@link android.view.ViewGroup} 및 +

        UI를 XML로 선언하는 것의 이점은 이렇게 하면 애플리케이션을 그 행동을 제어하는 코드로부터 따로 표시하기가 더 좋다는 것입니다. UI 설명은 애플리케이션 코드의 외부에 있습니다. 이는 다시 말해 소스 코드를 수정하고 다시 컴파일링하지 않아도 이를 수정 또는 변경할 수 있다는 뜻입니다. 예를 들어, 서로 다른 화면 방향, 사로 다른 기기 화면 크기 및 서로 다른 언어에 대해 XML 레이아웃을 생성할 수 있습니다. 이외에도 레이아웃을 XML로 선언하면 UI의 구조를 시각화하기가 더 쉬우므로 문제를 디버깅하기도 더 쉽습니다. 따라서, 이 문서는 레이아웃을 XML로 선언하는 방법을 가르치는 데 주안점을 두고 있습니다. 런타임에 보기 객체를 인스턴트화하는 것에 흥미가 있는 경우, +{@link android.view.ViewGroup} 및 {@link android.view.View} 클래스 참조를 참조하십시오.

        -

        일반적으로 UI 요소를 선언하는 데 쓰이는 XML 어휘는 클래스와 메서드 명명을 충실히 따릅니다. 여기에서 요소 이름은 클래스 이름에 상응하며 속성 이름은 메서드에 상응합니다. 사실 이러한 일치성은 아주 직접적인 경우가 잦아 어느 XML 속성이 클래스 메서드에 상응하는지를 추측할 수 있고, 어느 클래스가 주어진 XML 요소에 상응하는지도 추측할 수 있습니다. 다만 모든 어휘가 다 같지는 않다는 점을 유의하십시오. 몇몇 경우에는 명명에 약간의 차이점이 있습니다. 예를 들어, -EditText 요소에는 text 속성이 있으며 이는 +

        일반적으로 UI 요소를 선언하는 데 쓰이는 XML 어휘는 클래스와 메서드 명명을 충실히 따릅니다. 여기에서 요소 이름은 클래스 이름에 상응하며 속성 이름은 메서드에 상응합니다. 사실 이러한 일치성은 아주 직접적인 경우가 잦아 어느 XML 속성이 클래스 메서드에 상응하는지를 추측할 수 있고, 어느 클래스가 주어진 XML 요소에 상응하는지도 추측할 수 있습니다. 다만 모든 어휘가 다 같지는 않다는 점을 유의하십시오. 몇몇 경우에는 명명에 약간의 차이점이 있습니다. 예를 들어, +EditText 요소에는 text 속성이 있으며 이는 EditText.setText()에 상응합니다.

        팁: 여러 가지 레이아웃 유형에 대해서는 보편적인 -레이아웃 객체를 참조하십시오. 여러 가지 레이아웃을 구축하는 데 대한 튜토리얼 모음도 있습니다. +레이아웃 객체를 참조하십시오. 여러 가지 레이아웃을 구축하는 데 대한 튜토리얼 모음도 있습니다. Hello 보기 튜토리얼 가이드를 참조하십시오.

        XML 쓰기

        @@ -100,20 +100,20 @@ EditText 요소에는 text 속성이 있으며 이는 </LinearLayout> -

        레이아웃을 XML로 선언하고 나면 그 파일을 Android 프로젝트의 res/layout/ 디렉터리 내에 +

        레이아웃을 XML로 선언하고 나면 그 파일을 Android 프로젝트의 res/layout/ 디렉터리 내에 .xml 확장자로 저장하여 적절하게 컴파일링되도록 합니다.

        레이아웃 XML 파일의 구문에 대한 자세한 정보는 레이아웃 리소스 문서에서 확인할 수 있습니다.

        XML 리소스 로딩

        -

        애플리케이션을 컴파일링하는 경우, 각 XML 레이아웃 파일이 -{@link android.view.View} 리소스 안에 컴파일링됩니다. 애플리케이션 코드로부터 가져온 레이아웃 리소스는 -{@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} 콜백 +

        애플리케이션을 컴파일링하는 경우, 각 XML 레이아웃 파일이 +{@link android.view.View} 리소스 안에 컴파일링됩니다. 애플리케이션 코드로부터 가져온 레이아웃 리소스는 +{@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} 콜백 구현에 로딩해야 합니다. -이렇게 하려면 {@link android.app.Activity#setContentView(int) setContentView()}를 호출한 다음, 이를 +이렇게 하려면 {@link android.app.Activity#setContentView(int) setContentView()}를 호출한 다음, 이를 R.layout.layout_file_name 형태로 레이아웃 리소스의 참조에 전달합니다. - 예를 들어, XML 레이아웃이 main_layout.xml로 저장된 경우, 이것을 액티비티에 대해 로딩하려면 + 예를 들어, XML 레이아웃이 main_layout.xml로 저장된 경우, 이것을 액티비티에 대해 로딩하려면 다음과 같이 하면 됩니다.

         public void onCreate(Bundle savedInstanceState) {
        @@ -122,8 +122,8 @@ public void onCreate(Bundle savedInstanceState) {
         }
         
        -

        액티비티 내의 onCreate() 콜백 메서드는 액티비티가 시작될 때 -Android 프레임워크가 호출합니다(수명 주기에 대한 논의는 +

        액티비티 내의 onCreate() 콜백 메서드는 액티비티가 시작될 때 +Android 프레임워크가 호출합니다(수명 주기에 대한 논의는 액티비티 문서에서 확인하십시오).

        @@ -134,24 +134,24 @@ Android 프레임워크가 호출합니다(수명 주기에 대한 논의는 몇몇 속성은 보기 객체에만 특화되어 있지만(예를 들어, TextView는 textSize 속성을 지원), 이와 같은 속성은 이 클래스를 확장할 수 있는 모든 보기 객체가 상속하기도 합니다. 모든 보기 객체에 공통으로 쓰이는 것도 몇 가지 있습니다. 왜냐하면 이들은 루트 보기 클래스에서 상속된 것이기 때문입니다(예: -id 속성). 그리고 나머지 속성은 "레이아웃 매개변수"로 간주됩니다. -이들은 보기 객체의 특정한 레이아웃 방향을 설명하는 것으로, 이는 해당 객체의 상위 VeiwGroup 객체에서 +id 속성). 그리고 나머지 속성은 "레이아웃 매개변수"로 간주됩니다. +이들은 보기 객체의 특정한 레이아웃 방향을 설명하는 것으로, 이는 해당 객체의 상위 VeiwGroup 객체에서 정의된 바에 따릅니다.

        ID

        모든 보기 객체에는 연관된 정수 ID가 있을 수 있습니다. 이는 트리 내에서 해당 보기를 고유하게 식별하기 위한 것입니다. -애플리케이션이 컴파일링되면 이 ID가 정수로 참조되지만, ID는 -일반적으로 레이아웃 XML 파일에 문자열로 할당되며, id 속성으로 쓰입니다. +애플리케이션이 컴파일링되면 이 ID가 정수로 참조되지만, ID는 +일반적으로 레이아웃 XML 파일에 문자열로 할당되며, id 속성으로 쓰입니다. 이것은 모든 보기 객체에 공통적인 XML 속성으로 ({@link android.view.View} 클래스가 정의) 이것을 매우 자주 사용하게 됩니다. ID에 대한, XML 태그 내에 있는 구문은 다음과 같습니다.

        android:id="@+id/my_button"
        -

        문자열 시작 부분에 있는 앳 기호(@)는 XML 파서가 ID 문자열의 나머지를 구문 분석하고 확장하여 -ID 리소스로 식별해야 한다는 것을 나타냅니다. 더하기 기호(+)는 이것이 새 리소스 이름이며, -이것을 반드시 생성하여 우리 리소스에 추가해야 한다는 것을 뜻합니다(R.java 파일에서). Android 프레임워크는 다른 ID 리소스도 아주 많이 -제공합니다. Android 리소스 ID를 참조할 때에는 더하기 기호는 필요하지 않지만 +

        문자열 시작 부분에 있는 앳 기호(@)는 XML 파서가 ID 문자열의 나머지를 구문 분석하고 확장하여 +ID 리소스로 식별해야 한다는 것을 나타냅니다. 더하기 기호(+)는 이것이 새 리소스 이름이며, +이것을 반드시 생성하여 우리 리소스에 추가해야 한다는 것을 뜻합니다(R.java 파일에서). Android 프레임워크는 다른 ID 리소스도 아주 많이 +제공합니다. Android 리소스 ID를 참조할 때에는 더하기 기호는 필요하지 않지만 android 패키지 네임스페이스를 다음과 같이 반드시 추가해야 합니다.

        android:id="@android:id/empty"

        android 패키지 네임스페이스를 제자리에 넣으면 이제 ID를 로컬 리소스 클래스에서가 아니라 android.R @@ -174,54 +174,54 @@ Button myButton = (Button) findViewById(R.id.my_button);

    -

    {@link android.widget.RelativeLayout}을 생성할 때에는 보기 객체의 ID를 정의하는 것이 중요합니다. -관계 레이아웃에서는 형제 보기가 또 다른 형제 보기와 관련된 자신의 레이아웃을 정의할 수 있으며, +

    {@link android.widget.RelativeLayout}을 생성할 때에는 보기 객체의 ID를 정의하는 것이 중요합니다. +관계 레이아웃에서는 형제 보기가 또 다른 형제 보기와 관련된 자신의 레이아웃을 정의할 수 있으며, 이를 고유한 ID로 참조하게 됩니다.

    -

    ID는 트리 전체를 통틀어 고유할 필요는 없지만, 트리에서 검색하고 있는 부분 내에서는 -고유해야 합니다(이것이 트리 전체인 경우가 잦으므로, 가급적이면 완전히 +

    ID는 트리 전체를 통틀어 고유할 필요는 없지만, 트리에서 검색하고 있는 부분 내에서는 +고유해야 합니다(이것이 트리 전체인 경우가 잦으므로, 가급적이면 완전히 고유한 것을 쓰는 것이 가장 좋습니다).

    레이아웃 매개변수

    -

    layout_something이라는 XML 레이아웃 속성이 +

    layout_something이라는 XML 레이아웃 속성이 보기가 상주하는 ViewGroup에 대해 적절한 보기의 레이아웃 매개변수를 정의합니다.

    모든 ViewGroup 클래스가 중첩된 클래스를 하나씩 구현하며 이것이 {@link -android.view.ViewGroup.LayoutParams}를 확장합니다. 이 하위 클래스에는 -각 하위 보기의 크기와 위치를 보기 그룹에 적절한 방식으로 정의하는 -속성 유형이 들어 있습니다. 그림 1에서 볼 수 있듯이, 상위 보기 그룹이 +android.view.ViewGroup.LayoutParams}를 확장합니다. 이 하위 클래스에는 +각 하위 보기의 크기와 위치를 보기 그룹에 적절한 방식으로 정의하는 +속성 유형이 들어 있습니다. 그림 1에서 볼 수 있듯이, 상위 보기 그룹이 각 하위 보기의 레이아웃 매개변수를 정의합니다(하위 보기 그룹 포함).

    -

    그림 1. 각 보기와 연관된 레이아웃 매개변수가 +

    그림 1. 각 보기와 연관된 레이아웃 매개변수가 있는 보기 계층을 시각화한 것입니다.

    -

    모든 LayoutParams 하위 클래스에는 설정 값에 대한 각기 자신만의 구문이 있다는 점을 -눈여겨 보십시오. 각 하위 요소는 자신의 상위에 적합한 LayoutParams를 정의해야 합니다. +

    모든 LayoutParams 하위 클래스에는 설정 값에 대한 각기 자신만의 구문이 있다는 점을 +눈여겨 보십시오. 각 하위 요소는 자신의 상위에 적합한 LayoutParams를 정의해야 합니다. 다만 이것은 자신의 하위에 대해 각기 다른 LayoutParams도 정의할 수 있습니다.

    -

    모든 보기 그룹에는 너비와 높이가 포함되며(layout_width 및 -layout_height), 각 보기는 이들을 반드시 정의해야 합니다. 선택 사항으로 +

    모든 보기 그룹에는 너비와 높이가 포함되며(layout_width 및 +layout_height), 각 보기는 이들을 반드시 정의해야 합니다. 선택 사항으로 여백과 테두리도 포함하는 LayoutParams도 많습니다.

    -

    너비와 높이는 정확한 치수로 지정할 수 있습니다. 다만 이것은 자주 하지 -않는 것이 좋습니다. 그보다는 다음과 같은 상수 중 하나를 사용하여 너비 또는 높이를 설정하는 경우가 +

    너비와 높이는 정확한 치수로 지정할 수 있습니다. 다만 이것은 자주 하지 +않는 것이 좋습니다. 그보다는 다음과 같은 상수 중 하나를 사용하여 너비 또는 높이를 설정하는 경우가 더 많습니다.

      -
    • wrap_content 보기에 콘텐츠에 필요한 치수대로 알아서 +
    • wrap_content 보기에 콘텐츠에 필요한 치수대로 알아서 크기를 조정하라고 합니다.
    • match_parent (다른 이름은 fill_parent 로, API 레벨 8 이전에 해당) 보기에 상위 보기 그룹이 허용하는 한 최대한으로 커지라고 합니다.
    -

    일반적으로 픽셀과 같이 절대적인 단위를 사용하여 레이아웃 너비와 높이를 지정하는 것은 -권장하지 않습니다. 그 대신, 밀도 독립적인 픽셀 단위와 같이 상대적인 측정치를 +

    일반적으로 픽셀과 같이 절대적인 단위를 사용하여 레이아웃 너비와 높이를 지정하는 것은 +권장하지 않습니다. 그 대신, 밀도 독립적인 픽셀 단위와 같이 상대적인 측정치를 사용하는 것(dp), wrap_content, 또는 -match_parent등이 더 낫습니다. 이렇게 하면 +match_parent등이 더 낫습니다. 이렇게 하면 애플리케이션이 다양한 기기 화면 크기에 걸쳐서도 적절하게 표시되도록 보장하는 데 도움이 되기 때문입니다. -허용된 측정 유형은 +허용된 측정 유형은 사용 가능한 리소스에 정의되어 있습니다.

    @@ -229,23 +229,23 @@ android.view.ViewGroup.LayoutParams}를 확장합니다. 이 하위 클래스에

    레이아웃 위치

    보기의 모양은 직사각형입니다. 보기에는 위치가 있으며, 이는 - 한 쌍의 왼쪽상단 좌표, 그리고 두 개의 치수가 너비와 높이를 나타내는 + 한 쌍의 왼쪽상단 좌표, 그리고 두 개의 치수가 너비와 높이를 나타내는 형식으로 표현됩니다. 위치와 치수의 단위는 픽셀입니다.

    - 보기의 위치를 검색할 수 있습니다. -{@link android.view.View#getLeft()} 및 {@link android.view.View#getTop()} 메서드를 호출하면 됩니다. 전자는 보기를 -나타내는 직사각형의 왼쪽, 즉 X 좌표를 반환합니다. 후자는 보기를 -나타내는 직사각형의 상단, 즉 Y 좌표를 반환합니다. 이들 메서드는 둘 다 -보기의 위치를 해당 보기의 상위와 관련지어 반환합니다. 예를 들어, -getLeft()가 20을 반환하는 경우 이는 해당 보기가 그 보기의 바로 상위의 왼쪽 가장자리에서 + 보기의 위치를 검색할 수 있습니다. +{@link android.view.View#getLeft()} 및 {@link android.view.View#getTop()} 메서드를 호출하면 됩니다. 전자는 보기를 +나타내는 직사각형의 왼쪽, 즉 X 좌표를 반환합니다. 후자는 보기를 +나타내는 직사각형의 상단, 즉 Y 좌표를 반환합니다. 이들 메서드는 둘 다 +보기의 위치를 해당 보기의 상위와 관련지어 반환합니다. 예를 들어, +getLeft()가 20을 반환하는 경우 이는 해당 보기가 그 보기의 바로 상위의 왼쪽 가장자리에서 오른쪽으로 20픽셀 떨어진 곳에 있다는 뜻입니다.

    - 이외에도 불필요한 계산을 피하기 위해 여러 가지 편의 메서드가 제공됩니다. + 이외에도 불필요한 계산을 피하기 위해 여러 가지 편의 메서드가 제공됩니다. 구체적으로 {@link android.view.View#getRight()} 및 {@link android.view.View#getBottom()}을 들 수 있습니다. 이들 메서드는 해당 보기를 나타내는 직사각형의 오른쪽과 하단 가장자리의 좌표를 반환합니다. 예를 들어 {@link android.view.View#getRight()}를 @@ -255,46 +255,46 @@ android.view.ViewGroup.LayoutParams}를 확장합니다. 이 하위 클래스에

    크기, 안쪽 여백 및 여백

    - 보기의 크기는 너비와 높이로 표현됩니다. 사실 하나의 보기는 + 보기의 크기는 너비와 높이로 표현됩니다. 사실 하나의 보기는 두 쌍의 너비 및 높이 값을 소유합니다.

    - 첫 번째 쌍을 측정된 너비 및 -측정된 높이라고 합니다. 이들 치수는 보기가 -상위 내에서 얼마나 커지고자 하는지를 정의합니다. 측정된 + 첫 번째 쌍을 측정된 너비 및 +측정된 높이라고 합니다. 이들 치수는 보기가 +상위 내에서 얼마나 커지고자 하는지를 정의합니다. 측정된 치수를 가져오려면 {@link android.view.View#getMeasuredWidth()} 및 {@link android.view.View#getMeasuredHeight()}를 호출하면 됩니다.

    - 두 번째 쌍은 단순히 너비높이라고 일컬으며, -때로는 그리기 너비그리기 높이로 부를 때도 있습니다. 이러한 -치수는 그리기 시간 및 레이아웃 후에 보기가 화면에 표시되는 실제 크기를 -정의합니다. 이들 값은 측정된 너비 및 높이와 달라도 되지만 -꼭 달라야 하는 것은 아닙니다. 너비와 높이를 가져오려면 + 두 번째 쌍은 단순히 너비높이라고 일컬으며, +때로는 그리기 너비그리기 높이로 부를 때도 있습니다. 이러한 +치수는 그리기 시간 및 레이아웃 후에 보기가 화면에 표시되는 실제 크기를 +정의합니다. 이들 값은 측정된 너비 및 높이와 달라도 되지만 +꼭 달라야 하는 것은 아닙니다. 너비와 높이를 가져오려면 {@link android.view.View#getWidth()} 및 {@link android.view.View#getHeight()}를 호출하면 됩니다.

    - 보기의 치수를 측정하려면 보기는 자신의 안쪽 여백을 감안합니다. 안쪽 여백은 + 보기의 치수를 측정하려면 보기는 자신의 안쪽 여백을 감안합니다. 안쪽 여백은 보기의 왼쪽, 상단, 오른쪽 및 하단 부분에 대해 픽셀로 표시됩니다. - 안쪽 여백은 정해진 픽셀 수를 사용하여 보기의 콘텐츠를 오프셋하는 데 쓰일 수도 -있습니다. 예를 들어 왼쪽 안쪽 여백을 2로 설정하면 해당 보기의 콘텐츠를 왼쪽 가장자리에서 -오른쪽으로 2픽셀 밀어냅니다. 안쪽 여백을 설정할 때에는 -{@link android.view.View#setPadding(int, int, int, int)} 메서드를 사용하면 되고, 이를 쿼리하려면 -{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()}, + 안쪽 여백은 정해진 픽셀 수를 사용하여 보기의 콘텐츠를 오프셋하는 데 쓰일 수도 +있습니다. 예를 들어 왼쪽 안쪽 여백을 2로 설정하면 해당 보기의 콘텐츠를 왼쪽 가장자리에서 +오른쪽으로 2픽셀 밀어냅니다. 안쪽 여백을 설정할 때에는 +{@link android.view.View#setPadding(int, int, int, int)} 메서드를 사용하면 되고, 이를 쿼리하려면 +{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()}, {@link android.view.View#getPaddingRight()} 및 {@link android.view.View#getPaddingBottom()}을 사용하면 됩니다.

    - 보기가 안쪽 여백을 정의할 수는 있지만, 여백에 대한 지원은 전혀 제공하지 -않습니다. 다만 보기 그룹이 그와 같은 지원을 제공합니다. 자세한 정보는 -{@link android.view.ViewGroup} 및 + 보기가 안쪽 여백을 정의할 수는 있지만, 여백에 대한 지원은 전혀 제공하지 +않습니다. 다만 보기 그룹이 그와 같은 지원을 제공합니다. 자세한 정보는 +{@link android.view.ViewGroup} 및 {@link android.view.ViewGroup.MarginLayoutParams}를 참조하십시오.

    -

    치수에 대한 자세한 정보는 +

    치수에 대한 자세한 정보는 치수 값을 참조하십시오.

    @@ -320,13 +320,13 @@ div.layout.first {

    보편적인 레이아웃

    -

    {@link android.view.ViewGroup} 클래스의 각 하위 클래스는 각기 고유한 방식으로 자신 안에 -중첩한 보기를 표시합니다. 아래는 Android 플랫폼에서 기본 제공되는, 보다 보편적인 레이아웃 유형을 +

    {@link android.view.ViewGroup} 클래스의 각 하위 클래스는 각기 고유한 방식으로 자신 안에 +중첩한 보기를 표시합니다. 아래는 Android 플랫폼에서 기본 제공되는, 보다 보편적인 레이아웃 유형을 몇 가지 나타낸 것입니다.

    -

    참고: 하나 이상의 레이아웃을 또 다른 레이아웃에 중첩하여 -UI 디자인을 이룰 수도 있지만, 레이아웃 계층을 가능한 한 얕게 유지하도록 -애써야 합니다. 중첩된 레이아웃이 적을수록 레이아웃이 더욱 빠르게 그려집니다(가로로 넓은 보기 계층이 +

    참고: 하나 이상의 레이아웃을 또 다른 레이아웃에 중첩하여 +UI 디자인을 이룰 수도 있지만, 레이아웃 계층을 가능한 한 얕게 유지하도록 +애써야 합니다. 중첩된 레이아웃이 적을수록 레이아웃이 더욱 빠르게 그려집니다(가로로 넓은 보기 계층이 깊은 보기 계층보다 낫습니다).

    알림 우선 순위

    - 원한다면, 알림에 우선 순위를 설정할 수 있습니다. 우선 순위는 + 원한다면, 알림에 우선 순위를 설정할 수 있습니다. 우선 순위는 기기 UI에 알림 표시 방식을 암시하는 역할을 합니다. 알림 우선 순위를 설정하려면, {@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) NotificationCompat.Builder.setPriority()}를 호출하고 {@link -android.support.v4.app.NotificationCompat} 우선 순위 상수 중 하나에 전달합니다. +android.support.v4.app.NotificationCompat} 우선 순위 상수 중 하나에 전달합니다. 우선 순위 수준은 {@link android.support.v4.app.NotificationCompat#PRIORITY_MIN}(-2)에서 {@link android.support.v4.app.NotificationCompat#PRIORITY_MAX}(2)까지 다섯 개가 있습니다. 별도의 설정이 없을 경우, @@ -185,10 +185,10 @@ android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT}(0)으로 설정됩

    단순 알림 만들기

    - 다음 조각은 사용자가 알림을 클릭하면 알리는 + 다음 조각은 사용자가 알림을 클릭하면 알리는 액티비티를 지정하는 단순한 알림을 나타냅니다. 이 코드는 -{@link android.support.v4.app.TaskStackBuilder} 객체를 생성하고 이를 사용하여 -해당 작업의 {@link android.app.PendingIntent}를 생성합니다. 이 패턴은 +{@link android.support.v4.app.TaskStackBuilder} 객체를 생성하고 이를 사용하여 +해당 작업의 {@link android.app.PendingIntent}를 생성합니다. 이 패턴은 액티비티를 시작할 때 탐색 보존 섹션에서 자세히 설명합니다.

    @@ -225,13 +225,13 @@ mNotificationManager.notify(mId, mBuilder.build());

    알림에 확장 레이아웃 적용

    - 확장된 보기에 알림을 나타나게 하려면, + 확장된 보기에 알림을 나타나게 하려면, 먼저 원하는 일반 보기 옵션으로 {@link android.support.v4.app.NotificationCompat.Builder} 객체를 생성합니다. 다음에는 확장된 레이아웃 객체의 인수로 {@link android.support.v4.app.NotificationCompat.Builder#setStyle Builder.setStyle()}을 호출합니다.

    - 확장 알림은 Android 4.1 이전 플랫폼에서 사용할 수 없다는 것을 명심하십시오. + 확장 알림은 Android 4.1 이전 플랫폼에서 사용할 수 없다는 것을 명심하십시오. Android 4.1 이하 플랫폼에서 알림을 처리하는 방법은 처리 호환성 섹션을 참조하십시오.

    @@ -264,7 +264,7 @@ mBuilder.setStyle(inBoxStyle);

    처리 호환성

    - + 알림 기능을 설정하는 메서드가 지원 라이브러리 클래스 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder}에 있더라도 모든 알림 기능을 특정 버전에서 사용할 수 있는 것은 아닙니다. 예를 들어, 확장 알림에 따라 달라지는 작업 버튼은 Android @@ -294,13 +294,13 @@ NotificationCompat.Builder}를 이용해서 알림을 생성합니다. 또한, 사용자가 알림을 클릭하면 알림을 시작시키는 방식으로 모든 사용자에게 {@link android.app.Activity}에서 알림 기능을 사용할 수 있게 합니다. 이를 위해, -{@link android.app.Activity}를 위한 {@link android.app.PendingIntent}를 생성합니다. +{@link android.app.Activity}를 위한 {@link android.app.PendingIntent}를 생성합니다. {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}를 호출하여 알림에 {@link android.app.PendingIntent}를 추가합니다.

  • 이제 알림에서 사용하고자 하는 확장 알림 기능을 추가합니다. 또한, 사용자가 알림을 클릭하면 시작되는 -{@link android.app.Activity}에서 개발자가 추가한 모든 기능을 +{@link android.app.Activity}에서 개발자가 추가한 모든 기능을 사용할 수 있어야 합니다.
  • @@ -310,18 +310,18 @@ setContentIntent()}를 호출하여 알림에 {@link android.app.PendingIntent}

    알림 관리

    - 같은 유형의 이벤트에서 알림을 여러 번 발행해야 할 경우, + 같은 유형의 이벤트에서 알림을 여러 번 발행해야 할 경우, 완전히 새로운 알림을 만드는 것은 삼가야 합니다. 대신, 일부 값을 변경하거나 추가하거나, 두 가지 조치를 모두 취하여 이전 알림을 업데이트하는 것이 좋습니다.

    예를 들어, Gmail은 읽지 않은 메시지 개수를 올리고 각 이메일의 요약을 알림에 추가하여 -새 이메일 도착을 알립니다. 이것을 일명 -알림을 "쌓는다"고 하며, 이는 +새 이메일 도착을 알립니다. 이것을 일명 +알림을 "쌓는다"고 하며, 이는 알림 디자인 가이드에 자세히 설명되어 있습니다.

    - 참고: 이 Gmail 기능에는 "받은편지함" 확장 레이아웃이 필요한데, + 참고: 이 Gmail 기능에는 "받은편지함" 확장 레이아웃이 필요한데, 이것은 Android 4.1부터 이용할 수 있는 확장 알림 기능의 일부입니다.

    @@ -331,16 +331,16 @@ setContentIntent()}를 호출하여 알림에 {@link android.app.PendingIntent}

    알림이 업데이트되도록 설정하려면, {@link android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()}를 호출하여 알림 ID와 함께 발행합니다. - 알림을 발행한 후에 업데이트하려면, -{@link android.support.v4.app.NotificationCompat.Builder} 객체를 업데이트하거나 생성하고, -{@link android.app.Notification} 객체를 구축하고, -이전에 사용한 것과 같은 ID로 {@link android.app.Notification}을 발행합니다. 이전 알림이 + 알림을 발행한 후에 업데이트하려면, +{@link android.support.v4.app.NotificationCompat.Builder} 객체를 업데이트하거나 생성하고, +{@link android.app.Notification} 객체를 구축하고, +이전에 사용한 것과 같은 ID로 {@link android.app.Notification}을 발행합니다. 이전 알림이 여전히 표시되는 경우, 시스템은 -{@link android.app.Notification} 객체의 콘텐츠에서 알림을 업데이트합니다. 이전 알림을 무시할 경우, +{@link android.app.Notification} 객체의 콘텐츠에서 알림을 업데이트합니다. 이전 알림을 무시할 경우, 대신 새로운 알림이 생성됩니다.

    - 다음 코드 조각은 발생한 이벤트 개수를 반영하여 + 다음 코드 조각은 발생한 이벤트 개수를 반영하여 업데이트된 알림을 나타낸 것입니다. 이것은 알림을 쌓아 요약을 표시합니다.

    @@ -385,7 +385,7 @@ numMessages = 0;
     이 메서드도 현재 진행 중인 알림을 삭제합니다.
         
         
  • - {@link android.app.NotificationManager#cancelAll() cancelAll()}을 호출합니다. + {@link android.app.NotificationManager#cancelAll() cancelAll()}을 호출합니다. 이것은 이전에 발행한 알림을 모두 제거합니다.
  • @@ -393,9 +393,9 @@ numMessages = 0;

    액티비티를 시작할 때 탐색 보존

    - 알림에서 {@link android.app.Activity}를 시작할 때는 사용자의 예상 탐색 경험을 -보존해야 합니다. '뒤로'를 클릭하면 사용자를 애플리케이션의 정상 작업 흐름을 거쳐 메인 스크린으로 보내고, - '최근'을 클릭하면 + 알림에서 {@link android.app.Activity}를 시작할 때는 사용자의 예상 탐색 경험을 +보존해야 합니다. '뒤로'를 클릭하면 사용자를 애플리케이션의 정상 작업 흐름을 거쳐 메인 스크린으로 보내고, + '최근'을 클릭하면 {@link android.app.Activity}를 별개의 작업으로 표시합니다. 탐색 경험을 보존하려면 새 작업에서 {@link android.app.Activity}를 시작해야 합니다. 새로운 작업을 부여하기 위한 {@link android.app.PendingIntent} 설정 방법은 시작하는 @@ -406,19 +406,19 @@ numMessages = 0; 정규 액티비티

    - 애플리케이션의 정상적 작업 흐름의 일부인 {@link android.app.Activity}를 + 애플리케이션의 정상적 작업 흐름의 일부인 {@link android.app.Activity}를 시작합니다. 이 상황에서 {@link android.app.PendingIntent}를 설정하여 새 작업을 시작하고 애플리케이션의 정상적인 '뒤로' 동작을 재현하는 백 스택으로 {@link android.app.PendingIntent}를 제공합니다.

    - Gmail 앱에서 보낸 알림이 이것을 잘 보여줍니다. 하나의 이메일 메시지에 대한 -알림을 클릭하면 메시지 자체를 보게 됩니다. 뒤로를 터치하면 + Gmail 앱에서 보낸 알림이 이것을 잘 보여줍니다. 하나의 이메일 메시지에 대한 +알림을 클릭하면 메시지 자체를 보게 됩니다. 뒤로를 터치하면 알림에서 들어간 것이 아니라 메인 스크린에서 Gmail에 들어간 것처럼 Gmail을 통해 메인 스크린으로 돌아갑니다.

    - 이것은 알림을 터치하기만 하면 어느 애플리케이션에 있든 관계 없이 발생하는 -일입니다. 예를 들어, Gmail에서 메시지를 작성하다가 + 이것은 알림을 터치하기만 하면 어느 애플리케이션에 있든 관계 없이 발생하는 +일입니다. 예를 들어, Gmail에서 메시지를 작성하다가 한 이메일에 대한 알림을 클릭하면 해당 이메일로 바로 이동합니다. 뒤로 를 터치하면 작성 중인 메시지가 아니라 받은편지함과 메인 스크린으로 돌아갑니다. @@ -429,18 +429,18 @@ Gmail에 들어간 것처럼 Gmail을 통해 메인 스크린으로 돌아갑니

    {@link android.app.Activity}가 알림에서 시작될 경우 사용자에게는 이것만 보입니다. - {@link android.app.Activity}는 알림 자체에서 표시하기 어려운 정보를 제공하므로 -어떤 면에서는 알림을 확장하는 셈입니다. 이 상황에서는, -{@link android.app.PendingIntent}를 설정하고 새로운 작업에서 시작합니다. -시작된 {@link android.app.Activity}는 -애플리케이션 액티비티 흐름의 일부가 아니므로 백 스택을 생성하지 않아도 됩니다. 뒤로를 클릭하면 사용자는 여전히 + {@link android.app.Activity}는 알림 자체에서 표시하기 어려운 정보를 제공하므로 +어떤 면에서는 알림을 확장하는 셈입니다. 이 상황에서는, +{@link android.app.PendingIntent}를 설정하고 새로운 작업에서 시작합니다. +시작된 {@link android.app.Activity}는 +애플리케이션 액티비티 흐름의 일부가 아니므로 백 스택을 생성하지 않아도 됩니다. 뒤로를 클릭하면 사용자는 여전히 메인 스크린으로 돌아갑니다.

    정규 액티비티 PendingIntent 설정

    - 직접 진입 + 직접 진입 {@link android.app.Activity}를 시작하는 {@link android.app.PendingIntent}를 설정하려면 다음과 같은 단계를 따르십시오.

      @@ -448,7 +448,7 @@ Gmail에 들어간 것처럼 Gmail을 통해 메인 스크린으로 돌아갑니 매니페스트에서 애플리케이션의 {@link android.app.Activity} 계층을 정의합니다.
      1. - Android 4.0.3 이전에 대한 지원을 추가합니다. 이렇게 하려면 + Android 4.0.3 이전에 대한 지원을 추가합니다. 이렇게 하려면 <meta-data> 요소를 @@ -506,39 +506,39 @@ Gmail에 들어간 것처럼 Gmail을 통해 메인 스크린으로 돌아갑니 TaskStackBuilder.create()}를 호출하여 스택 빌더를 생성합니다.
      2. - + {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}을 호출하여 스택 빌더를 백 스택에 추가합니다. 매니페스트에서 정의한 계층의 각 {@link android.app.Activity}의 경우, 백 스택에 -{@link android.app.Activity}를 시작하는 {@link android.content.Intent} 객체가 포함됩니다. 이 메서드는 새로운 작업에서 +{@link android.app.Activity}를 시작하는 {@link android.content.Intent} 객체가 포함됩니다. 이 메서드는 새로운 작업에서 스택을 시작하는 플래그도 추가합니다.

        - 참고: + 참고: {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}에 대한 인수가 -시작된 {@link android.app.Activity}의 참조이기는 하지만, 이 메서드 호출은 +시작된 {@link android.app.Activity}의 참조이기는 하지만, 이 메서드 호출은 {@link android.app.Activity}를 시작하는 {@link android.content.Intent}를 추가하지 않습니다. 대신, 그 부분은 다음 단계에서 해결합니다.

      3. - -{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}를 호출하여 {@link android.app.Activity}를 시작하는 {@link android.content.Intent}를 + +{@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}를 호출하여 {@link android.app.Activity}를 시작하는 {@link android.content.Intent}를 추가합니다. 첫 번째 단계에서 생성한 {@link android.content.Intent}를 {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}에 대한 인수로 전달합니다.
      4. - 필요할 경우 + 필요할 경우 {@link android.support.v4.app.TaskStackBuilder#editIntentAt TaskStackBuilder.editIntentAt()}을 호출하여 스택에서{@link android.content.Intent} 객체에 대한 인수를 추가합니다. 이것은 사용자가 '뒤로'를 사용하여 탐색할 때 대상{@link android.app.Activity}가 의미 있는 데이터를 표시하도록 보장하기 위해 때때로 필요한 절차입니다.
      5. - 이 백 스택에 대한 {@link android.app.PendingIntent}를 가져옵니다. 이때 + 이 백 스택에 대한 {@link android.app.PendingIntent}를 가져옵니다. 이때 {@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}를 호출하는 방법을 씁니다. - 그러면 이 {@link android.app.PendingIntent}를 + 그러면 이 {@link android.app.PendingIntent}를 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}에 대한 인수로 사용할 수 있습니다.
      6. @@ -569,21 +569,21 @@ mNotificationManager.notify(id, builder.build());

        특수 액티비티 PendingIntent 설정

        - 다음 섹션에서는 특수 액티비티 + 다음 섹션에서는 특수 액티비티 {@link android.app.PendingIntent}를 설정하는 법을 설명합니다.

        - 특수 {@link android.app.Activity}에는 백 스택이 필요하지 않습니다. 따라서 매니페스트에서 이것의 -{@link android.app.Activity} 계층을 정의하지 않아도 되고, -백 스택을 구축하기 위해 -{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}을 -호출하지 않아도 됩니다. 대신 매니페스트를 사용하여 {@link android.app.Activity} 작업 옵션을 설정하고, -{@link android.app.PendingIntent}를 생성하십시오. 이때 + 특수 {@link android.app.Activity}에는 백 스택이 필요하지 않습니다. 따라서 매니페스트에서 이것의 +{@link android.app.Activity} 계층을 정의하지 않아도 되고, +백 스택을 구축하기 위해 +{@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}을 +호출하지 않아도 됩니다. 대신 매니페스트를 사용하여 {@link android.app.Activity} 작업 옵션을 설정하고, +{@link android.app.PendingIntent}를 생성하십시오. 이때 {@link android.app.PendingIntent#getActivity getActivity()}를 호출하는 방법을 씁니다.

        1. - 매니페스트에서 다음 속성을 {@link android.app.Activity}에 대한 + 매니페스트에서 다음 속성을 {@link android.app.Activity}에 대한 <activity> 요소에 추가합니다.
          @@ -597,10 +597,10 @@ mNotificationManager.notify(id, builder.build()); android:taskAffinity=""
          - 이것은 개발자가 코드에서 설정하는 -{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} 플래그와 더불어 -이 {@link android.app.Activity}가 -애플리케이션의 기본 작업으로 들어가지 않게 보장합니다. 애플리케이션의 기본 유사성을 + 이것은 개발자가 코드에서 설정하는 +{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} 플래그와 더불어 +이 {@link android.app.Activity}가 +애플리케이션의 기본 작업으로 들어가지 않게 보장합니다. 애플리케이션의 기본 유사성을 가지고 있는 기존 작업은 모두 영향을 받지 않습니다.
          @@ -629,23 +629,23 @@ mNotificationManager.notify(id, builder.build()); 알림을 구축 및 발행합니다.
          1. - + {@link android.app.Activity}를 시작하는 {@link android.content.Intent}를 생성합니다.
          2. - {@link android.app.Activity}가 새로운, 빈 작업에서 시작되도록 설정합니다. 이때 -{@link android.content.Intent#setFlags setFlags()}를 + {@link android.app.Activity}가 새로운, 빈 작업에서 시작되도록 설정합니다. 이때 +{@link android.content.Intent#setFlags setFlags()}를 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} - 및 + 및 {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK} 플래그와 함께 호출하면 됩니다.
          3. {@link android.content.Intent}에 필요한 다른 모든 옵션을 설정합니다.
          4. - {@link android.app.PendingIntent}를 {@link android.content.Intent}로부터 + {@link android.app.PendingIntent}를 {@link android.content.Intent}로부터 생성합니다. 이때 {@link android.app.PendingIntent#getActivity getActivity()}를 호출하면 됩니다. - 그러면 이 {@link android.app.PendingIntent}를 + 그러면 이 {@link android.app.PendingIntent}를 {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}에 대한 인수로 사용할 수 있습니다.
          5. @@ -687,24 +687,24 @@ mNotificationManager.notify(id, builder.build());

            알림에서 진행 상태 표시

            - 알림에는 사용자에게 진행 중인 작업의 상태를 보여주는 -애니메이션 진행 표시기를 포함할 수 있습니다. 작업이 얼마나 걸릴지, 주어진 시점에 어느 정도 완료되었는지를 추정할 수 있는 경우 -표시기의 "확정적" 형태(진행률 표시줄)를 -사용하십시오. 작업의 길이를 추정할 수 없으면, 표시기의 + 알림에는 사용자에게 진행 중인 작업의 상태를 보여주는 +애니메이션 진행 표시기를 포함할 수 있습니다. 작업이 얼마나 걸릴지, 주어진 시점에 어느 정도 완료되었는지를 추정할 수 있는 경우 +표시기의 "확정적" 형태(진행률 표시줄)를 +사용하십시오. 작업의 길이를 추정할 수 없으면, 표시기의 "비확정적" 형태(액티비티 표시기)를 사용하십시오.

            - 진행 상태 표시기는 + 진행 상태 표시기는 {@link android.widget.ProgressBar} 클래스의 플랫폼 구현으로 표시됩니다.

            - Android 4.0부터 시작되는 플랫폼에서 진행 상태 표시기를 사용하려면, -{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}를 호출하십시오. 이전 -버전의 경우, 개발자 나름의 사용자 지정 알림 레이아웃을 생성해야 하며 여기에 + Android 4.0부터 시작되는 플랫폼에서 진행 상태 표시기를 사용하려면, +{@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}를 호출하십시오. 이전 +버전의 경우, 개발자 나름의 사용자 지정 알림 레이아웃을 생성해야 하며 여기에 {@link android.widget.ProgressBar} 보기가 포함되어 있어야 합니다.

            - 다음 섹션은 + 다음 섹션은 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}를 사용하여 알림의 진행 상태를 표시하는 법을 설명합니다.

            @@ -712,15 +712,15 @@ mNotificationManager.notify(id, builder.build());

            확정적인 진행률 표시줄을 표시하려면 {@link android.support.v4.app.NotificationCompat.Builder#setProgress -setProgress(max, progress, false)}를 호출하여 표시줄을 알림에 추가하고, 그 다음에 알림을 발행합니다. 작업이 진행되는 동안 -progress를 증가시키고 알림을 업데이트합니다. 작업이 끝날 무렵 -progressmax와 같아야 합니다. +setProgress(max, progress, false)}를 호출하여 표시줄을 알림에 추가하고, 그 다음에 알림을 발행합니다. 작업이 진행되는 동안 +progress를 증가시키고 알림을 업데이트합니다. 작업이 끝날 무렵 +progressmax와 같아야 합니다. {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}를 호출하는 보편적인 방법은 max를 100에 설정하고 작업에 대한 "완료 비율" 값에 따라 progress를 증가시키는 것입니다.

            - 작업이 완료되면 진행률 표시줄이 표시되는 상태로 둘 수도 있고, 제거할 수도 있습니다. 어느 경우를 택하더라도 + 작업이 완료되면 진행률 표시줄이 표시되는 상태로 둘 수도 있고, 제거할 수도 있습니다. 어느 경우를 택하더라도 알림 텍스트를 업데이트하여 작업이 완료되었다고 표시하는 것을 잊지 마십시오. 진행률 표시줄을 제거하려면, {@link android.support.v4.app.NotificationCompat.Builder#setProgress @@ -773,15 +773,15 @@ new Thread(

            비확정적 액티비티 표시기를 표시하려면, {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}으로 알림에 표시기를 추가하고(처음의 인수 두 개는 무시합니다) -, 알림을 발행합니다. 그 결과로 +, 알림을 발행합니다. 그 결과로 진행률 표시줄과 같은 스타일의 표시기가 나타납니다. 다만 이것은 애니메이션이 계속 진행 중입니다.

            - 작업을 시작할 때 알림을 발행합니다. 애니메이션은 -알림을 수정할 때까지 실행됩니다. 작업이 완료되면, + 작업을 시작할 때 알림을 발행합니다. 애니메이션은 +알림을 수정할 때까지 실행됩니다. 작업이 완료되면, {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}를 호출하고 알림을 업데이트하여 액티비티 표시기를 제거합니다. - 이 작업은 항상 해야 합니다. 하지 않으면, 작업이 완료되더라도 애니메이션이 계속 실행됩니다. 또한, + 이 작업은 항상 해야 합니다. 하지 않으면, 작업이 완료되더라도 애니메이션이 계속 실행됩니다. 또한, 알림 텍스트를 변경하여 작업이 완료되었음을 나타내는 것을 잊지 마십시오.

            @@ -806,19 +806,19 @@ mNotifyManager.notify(0, mBuilder.build());

            알림 메타데이터

            -

            알림은 +

            알림은 다음 {@link android.support.v4.app.NotificationCompat.Builder} 메서드로 할당된 메타데이터에 따라 정렬할 수 있습니다.

              -
            • {@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()}는 +
            • {@link android.support.v4.app.NotificationCompat.Builder#setCategory(java.lang.String) setCategory()}는 기기가 우선 순위 모드일 때 앱 알림을 처리하는 방법을 시스템에 전달합니다 (예를 들어, 알림이 수신 전화나 채팅 메시지, 알람 등을 나타낼 경우).
            • -
            • {@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()}는 -우선 순위 필드가 포함된 알림을 {@code PRIORITY_MAX} 또는 {@code PRIORITY_HIGH}로 설정하고, +
            • {@link android.support.v4.app.NotificationCompat.Builder#setPriority(int) setPriority()}는 +우선 순위 필드가 포함된 알림을 {@code PRIORITY_MAX} 또는 {@code PRIORITY_HIGH}로 설정하고, 알림에 소리나 진동이 포함되어 있을 경우 작은 부동 창에 나타나게 합니다.
            • -
            • {@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()}을 -사용하면 알림에 사람 목록을 추가할 수 있게 해줍니다. 개발자의 앱은 이 신호를 사용하여 -시스템에 지정된 사람들로부터 받은 알림을 함께 그룹화해야 한다고 알리거나, 이런 사람들로부터 받은 알림을 +
            • {@link android.support.v4.app.NotificationCompat.Builder#addPerson(java.lang.String) addPerson()}을 +사용하면 알림에 사람 목록을 추가할 수 있게 해줍니다. 개발자의 앱은 이 신호를 사용하여 +시스템에 지정된 사람들로부터 받은 알림을 함께 그룹화해야 한다고 알리거나, 이런 사람들로부터 받은 알림을 더욱 중요한 것으로 순위를 높일 수 있습니다.
            @@ -832,10 +832,10 @@ mNotifyManager.notify(0, mBuilder.build());

            헤드업 알림

            Android 5.0(API 레벨 21)에서는 알림을 작은 부동 창에 나타낼 수 있습니다 -(다른 말로 헤드업 알림이라고 부릅니다). 이것은 기기가 활성 상태일 때(즉, -기기가 잠금 해제 상태이며 화면에 켜져 있는 경우) 해당됩니다. 이와 같은 알림은 -외견상 일반적인 알림의 소형 형태와 비슷해 보이지만, -해드업 알림에서는 작업 버튼도 표시한다는 점이 다릅니다. 사용자는 현재 앱을 떠나지 않고도 +(다른 말로 헤드업 알림이라고 부릅니다). 이것은 기기가 활성 상태일 때(즉, +기기가 잠금 해제 상태이며 화면에 켜져 있는 경우) 해당됩니다. 이와 같은 알림은 +외견상 일반적인 알림의 소형 형태와 비슷해 보이지만, +해드업 알림에서는 작업 버튼도 표시한다는 점이 다릅니다. 사용자는 현재 앱을 떠나지 않고도 헤드업 알림에 조치를 취하거나 이를 무시할 수 있습니다.

            헤드업 알림을 트리거할 수 있는 조건의 예시를 몇 가지 소개하면 다음과 같습니다.

            @@ -843,55 +843,55 @@ mNotifyManager.notify(0, mBuilder.build());
            • 사용자 액티비티가 전체 화면 모드이거나(앱이 {@link android.app.Notification#fullScreenIntent}를 사용할 경우)
            • -
            • 알림의 우선 순위가 높고 +
            • 알림의 우선 순위가 높고 벨소리나 진동을 사용할 경우

            잠금 화면 알림

            -

            Android 5.0 (API 레벨 21) 릴리스부터 알림이 잠금 화면에도 -나타날 수 있게 되었습니다. 앱은 이 기능을 사용하면 미디어 재생 제어와 다른 보편적인 작업을 -제공할 수 있습니다. 사용자는 설정을 통해 잠금 화면에 알림 표시 여부를 선택할 수 있고, +

            Android 5.0 (API 레벨 21) 릴리스부터 알림이 잠금 화면에도 +나타날 수 있게 되었습니다. 앱은 이 기능을 사용하면 미디어 재생 제어와 다른 보편적인 작업을 +제공할 수 있습니다. 사용자는 설정을 통해 잠금 화면에 알림 표시 여부를 선택할 수 있고, 개발자는 앱의 알림이 잠금 화면에 표시될지 여부를 지정할 수 있습니다.

            가시성 설정

            -

            보안 잠금 화면에 알림이 얼마나 상세하게 표시될 것인지 그 수준을 앱이 제어할 수 -있습니다. {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()}를 호출하고 +

            보안 잠금 화면에 알림이 얼마나 상세하게 표시될 것인지 그 수준을 앱이 제어할 수 +있습니다. {@link android.support.v4.app.NotificationCompat.Builder#setVisibility(int) setVisibility()}를 호출하고 다음 값 중 하나를 지정합니다.

              -
            • {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}은 +
            • {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}은 알림의 전체 콘텐츠를 표시합니다.
            • -
            • {@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET}은 +
            • {@link android.support.v4.app.NotificationCompat#VISIBILITY_SECRET}은 이 알림의 어떤 부분도 화면에 표시하지 않습니다.
            • -
            • {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE}은 +
            • {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE}은 알림 아이콘과 콘텐츠 제목 등의 기본 정보는 표시하지만 알림의 전체 콘텐츠는 숨깁니다.

            {@link android.support.v4.app.NotificationCompat#VISIBILITY_PRIVATE}으로 설정하면 , -알림 콘텐츠의 대체 버전을 제공할 수도 있습니다. 이렇게 하면 특정 세부 사항만 숨깁니다. 예를 들어, -SMS 앱에서 3개의 새 문자 메시지가 있습니다.라고 표시하면서도 -문자 메시지의 내용과 발신자는 숨길 수 있습니다. 이 대체 알림을 제공하려면, 우선 대체 알림을 생성합니다. 이때 -{@link android.support.v4.app.NotificationCompat.Builder}를 사용합니다. 비공개 알림 객체를 -생성하는 경우, 대체 알림을 이에 첨부할 때 +알림 콘텐츠의 대체 버전을 제공할 수도 있습니다. 이렇게 하면 특정 세부 사항만 숨깁니다. 예를 들어, +SMS 앱에서 3개의 새 문자 메시지가 있습니다.라고 표시하면서도 +문자 메시지의 내용과 발신자는 숨길 수 있습니다. 이 대체 알림을 제공하려면, 우선 대체 알림을 생성합니다. 이때 +{@link android.support.v4.app.NotificationCompat.Builder}를 사용합니다. 비공개 알림 객체를 +생성하는 경우, 대체 알림을 이에 첨부할 때 {@link android.support.v4.app.NotificationCompat.Builder#setPublicVersion(android.app.Notification) setPublicVersion()} 메서드를 통합니다.

            잠금 화면에서 미디어 재생 제어

            -

            Android 5.0(API 레벨 21)의 잠금 화면에서는 더 이상 -{@link android.media.RemoteControlClient}를 기반으로 한 미디어 제어를 표시하지 않습니다. 이는 사용되지 않고 있기 때문입니다. 대신, -{@link android.app.Notification.MediaStyle} 템플릿을 +

            Android 5.0(API 레벨 21)의 잠금 화면에서는 더 이상 +{@link android.media.RemoteControlClient}를 기반으로 한 미디어 제어를 표시하지 않습니다. 이는 사용되지 않고 있기 때문입니다. 대신, +{@link android.app.Notification.MediaStyle} 템플릿을 {@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()} 메서드와 함께 사용하십시오. 이 메서드는 작업을 클릭할 수 있는 아이콘으로 변환해줍니다.

            -

            참고: 이 템플릿과 {@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()} -메서드는 지원 라이브러리에 포함되어 있지 않으므로 이 기능은 Android 5.0 이상에서만 +

            참고: 이 템플릿과 {@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()} +메서드는 지원 라이브러리에 포함되어 있지 않으므로 이 기능은 Android 5.0 이상에서만 실행됩니다.

            -

            Android 5.0의 잠금 화면에서 미디어 재생 제어를 표시하려면, -위에 설명한 바와 같이 가시성을 {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}으로 설정합니다. 그런 다음 다음 샘플 코드에서 설명한 바와 같이 작업을 추가하고 +

            Android 5.0의 잠금 화면에서 미디어 재생 제어를 표시하려면, +위에 설명한 바와 같이 가시성을 {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}으로 설정합니다. 그런 다음 다음 샘플 코드에서 설명한 바와 같이 작업을 추가하고 {@link android.app.Notification.MediaStyle} 템플릿을 설정합니다.

            @@ -914,7 +914,7 @@ Notification notification = new Notification.Builder(context) .build();
    -

    참고: {@link android.media.RemoteControlClient}를 +

    참고: {@link android.media.RemoteControlClient}를 사용하지 않게 된 것은 미디어 제어에 이외에도 더 많은 영향을 미칩니다. 미디어 세션을 관리하고 재생을 제어하기 위한 새 API에 관한 자세한 정보는 미디어 재생 제어를 참조하십시오.

    @@ -923,57 +923,57 @@ Notification notification = new Notification.Builder(context)

    사용자 지정 알림 레이아웃

    - 알림 프레임워크를 사용하면 사용자 지정 레이아웃을 정의할 수 있습니다. + 알림 프레임워크를 사용하면 사용자 지정 레이아웃을 정의할 수 있습니다. 사용자 지정 레이아웃은 {@link android.widget.RemoteViews} 객체에서 알림의 외관을 정의합니다. 사용자 지정 레이아웃 알림은 일반적인 알림과 비슷하지만, 이들은 XML 레이아웃 파일에서 정의한 {@link android.widget.RemoteViews}에 기초합니다.

    - 사용자 지정 알림 레이아웃에 사용할 수 있는 높이는 알림 보기에 따라 다릅니다. 일반 + 사용자 지정 알림 레이아웃에 사용할 수 있는 높이는 알림 보기에 따라 다릅니다. 일반 보기 레이아웃은 64dp로 제한되어 있으며 확장 보기 레이아웃은 256dp로 제한되어 있습니다.

    - 사용자 지정 레이아웃을 정의하려면 -XML 레이아웃 파일을 팽창하는 {@link android.widget.RemoteViews} 객체를 인스턴트화하는 것부터 시작합니다. 그런 다음, + 사용자 지정 레이아웃을 정의하려면 +XML 레이아웃 파일을 팽창하는 {@link android.widget.RemoteViews} 객체를 인스턴트화하는 것부터 시작합니다. 그런 다음, -{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}과 같은 메서드를 호출하는 대신 -{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}를 호출합니다. 사용자 지정 알림에서 +{@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}과 같은 메서드를 호출하는 대신 +{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}를 호출합니다. 사용자 지정 알림에서 콘텐츠 세부 정보를 설정하려면 {@link android.widget.RemoteViews}의 메서드를 사용하여 보기의 하위 요소에 대한 값을 설정합니다.

    1. - 알림에 대한 XML 레이아웃은 별도의 파일에 생성하십시오. 파일 이름은 원하는 대로 + 알림에 대한 XML 레이아웃은 별도의 파일에 생성하십시오. 파일 이름은 원하는 대로 아무 것이나 사용해도 좋지만, 확장자는 .xml을 사용해야 합니다.
    2. - 앱에서 {@link android.widget.RemoteViews} 메서드를 사용하여 알림의 아이콘과 텍스트를 -정의합니다. 이 {@link android.widget.RemoteViews} 객체를 -{@link android.support.v4.app.NotificationCompat.Builder} 안에 넣으십시오. -{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}를 호출하면 됩니다. 배경 -{@link android.graphics.drawable.Drawable}을 + 앱에서 {@link android.widget.RemoteViews} 메서드를 사용하여 알림의 아이콘과 텍스트를 +정의합니다. 이 {@link android.widget.RemoteViews} 객체를 +{@link android.support.v4.app.NotificationCompat.Builder} 안에 넣으십시오. +{@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}를 호출하면 됩니다. 배경 +{@link android.graphics.drawable.Drawable}을 {@link android.widget.RemoteViews} 객체에서 설정하는 것은 삼가하십시오. 텍스트 색상을 읽을 수 없게 될 수도 있습니다.

    - {@link android.widget.RemoteViews} 클래스에도 개발자가 손쉽게 사용할 수 있는 여러 가지 메서드가 포함되어 있습니다. 이를 이용해 -{@link android.widget.Chronometer} 또는 {@link android.widget.ProgressBar}를 + {@link android.widget.RemoteViews} 클래스에도 개발자가 손쉽게 사용할 수 있는 여러 가지 메서드가 포함되어 있습니다. 이를 이용해 +{@link android.widget.Chronometer} 또는 {@link android.widget.ProgressBar}를 알림의 레이아웃에 추가하면 됩니다. 알림의 사용자 지정 레이아웃 생성에 관한 자세한 정보는 {@link android.widget.RemoteViews} 참조 문서를 참조하십시오.

    - 주의: 사용자 지정 레이아웃을 사용하는 경우, -사용자 지정 레이아웃이 다양한 기기 방향과 해상도에서 작동하는지 각별히 주의를 기울여 확인하십시오. 이 조언은 -모든 보기 레이아웃에 공통적으로 적용되지만, 특히 알림에 중요한 의미를 지닙니다. -알림 창에서는 공간이 굉장히 제한되어 있기 때문입니다. 사용자 지정 레이아웃을 너무 복잡하게 만들지 마시고, + 주의: 사용자 지정 레이아웃을 사용하는 경우, +사용자 지정 레이아웃이 다양한 기기 방향과 해상도에서 작동하는지 각별히 주의를 기울여 확인하십시오. 이 조언은 +모든 보기 레이아웃에 공통적으로 적용되지만, 특히 알림에 중요한 의미를 지닙니다. +알림 창에서는 공간이 굉장히 제한되어 있기 때문입니다. 사용자 지정 레이아웃을 너무 복잡하게 만들지 마시고, 여러 가지 구성에서 테스트하는 것을 잊지 마십시오.

    사용자 지정 알림 텍스트에 스타일 리소스 사용

    - 사용자 지정 알림의 텍스트에는 항상 스타일 리소스를 사용하십시오. 알림의 배경 색상은 기기와 버전별로 다를 수 있습니다. -스타일 리소스를 사용하면 이러한 차이를 -감안하는 데 도움이 됩니다. Android 2.3부터 시스템은 -표준 알림 레이아웃 텍스트의 스타일을 정의했습니다. Android 2.3 이상을 대상으로 하는 + 사용자 지정 알림의 텍스트에는 항상 스타일 리소스를 사용하십시오. 알림의 배경 색상은 기기와 버전별로 다를 수 있습니다. +스타일 리소스를 사용하면 이러한 차이를 +감안하는 데 도움이 됩니다. Android 2.3부터 시스템은 +표준 알림 레이아웃 텍스트의 스타일을 정의했습니다. Android 2.3 이상을 대상으로 하는 애플리케이션에서와 같은 스타일을 사용하면 텍스트가 디스플레이 배경에서도 잘 보이도록 할 수 있습니다.

    diff --git a/docs/html-intl/intl/ko/guide/topics/ui/overview.jd b/docs/html-intl/intl/ko/guide/topics/ui/overview.jd index eb288f1532aeb034a95444bc271f11f29db89074..72e5692e80e46d046276cfe749539a4d8f44e42f 100644 --- a/docs/html-intl/intl/ko/guide/topics/ui/overview.jd +++ b/docs/html-intl/intl/ko/guide/topics/ui/overview.jd @@ -3,9 +3,9 @@ page.title=UI 개요

    Android 앱의 모든 사용자 인터페이스 요소는 {@link android.view.View}와 -{@link android.view.ViewGroup} 개체를 사용하여 구축합니다. {@link android.view.View}는 사용자가 상호 작용할 수 있는 무언가를 -화면에 그리는 객체입니다. {@link android.view.ViewGroup}은 -인터페이스 레이아웃을 정의하기 위해 다른 {@link android.view.View}(및{@link android.view.ViewGroup}) 객체를 +{@link android.view.ViewGroup} 개체를 사용하여 구축합니다. {@link android.view.View}는 사용자가 상호 작용할 수 있는 무언가를 +화면에 그리는 객체입니다. {@link android.view.ViewGroup}은 +인터페이스 레이아웃을 정의하기 위해 다른 {@link android.view.View}(및{@link android.view.ViewGroup}) 객체를 보유하는 객체입니다.

    Android는 공통 입력 제어(버튼 및 텍스트 필드)와 다양한 레이아웃 모델(선형 또는 관계 레이아웃)을 제공하는 {@link android.view.View}와 {@link @@ -16,30 +16,30 @@ android.view.ViewGroup} 하위 클래스의

    사용자 인터페이스 레이아웃

    앱의 각 구성 요소에 대한 사용자 인터페이스는 그림 1에서 나타난 바와 같이 {@link -android.view.View}와 {@link android.view.ViewGroup} 객체의 계층으로 정의됩니다. 각 보기 그룹은 -하위 보기를 체계화하는 투명한 컨테이너이고, -하위 보기는 UI의 일부분을 그리는 제어나 다른 위젯일 수 있습니다. -이 계층 트리는 개발자에게 필요한 만큼 단순하거나 복잡하게 +android.view.View}와 {@link android.view.ViewGroup} 객체의 계층으로 정의됩니다. 각 보기 그룹은 +하위 보기를 체계화하는 투명한 컨테이너이고, +하위 보기는 UI의 일부분을 그리는 제어나 다른 위젯일 수 있습니다. +이 계층 트리는 개발자에게 필요한 만큼 단순하거나 복잡하게 만들 수 있습니다(다만 단순한 것이 성능에는 가장 좋습니다).

    -

    그림 1. 보기 계층을 나타낸 것으로, 이것이 +

    그림 1. 보기 계층을 나타낸 것으로, 이것이 UI 레이아웃을 정의합니다.

    -

    레이아웃을 선언하려면 코드의 {@link android.view.View} 객체를 인스턴트화하고 트리를 구축하기 시작하면 되지만, -레이아웃을 정의하는 가장 쉽고 효과적인 방법은 XML 파일을 사용하는 것입니다. +

    레이아웃을 선언하려면 코드의 {@link android.view.View} 객체를 인스턴트화하고 트리를 구축하기 시작하면 되지만, +레이아웃을 정의하는 가장 쉽고 효과적인 방법은 XML 파일을 사용하는 것입니다. XML은 HTML과 유사한, 인간이 읽을 수 있는 레이아웃 구조를 제공합니다.

    -

    보기의 XML 요소 이름은 해당 요소가 나타내는 각각의 Android 클래스를 따릅니다. 말하자면 +

    보기의 XML 요소 이름은 해당 요소가 나타내는 각각의 Android 클래스를 따릅니다. 말하자면 <TextView> 요소가 UI에서 {@link android.widget.TextView} 위젯을 생성하고, -<LinearLayout> 요소는 {@link android.widget.LinearLayout} 보기 +<LinearLayout> 요소는 {@link android.widget.LinearLayout} 보기 그룹을 생성하는 것입니다.

    예를 들어, 텍스트 보기와 버튼 하나가 있는 단순한 수직 레이아웃은 이런 모습을 띱니다.

     <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -              android:layout_width="fill_parent" 
    +              android:layout_width="fill_parent"
                   android:layout_height="fill_parent"
                   android:orientation="vertical" >
         <TextView android:id="@+id/text"
    @@ -53,19 +53,19 @@ XML은 HTML과 유사한, 인간이 읽을 수 있는 레이아웃 구조를 제
     </LinearLayout>
     
    -

    앱에 레이아웃 리소스를 로드하면 Android가 레이아웃의 각 노드를 초기화하여 -추가 동작을 정의하거나, 객체 상태를 쿼리 또는 레이아웃을 수정하는 데 쓸 수 있는 런타임 객체로 +

    앱에 레이아웃 리소스를 로드하면 Android가 레이아웃의 각 노드를 초기화하여 +추가 동작을 정의하거나, 객체 상태를 쿼리 또는 레이아웃을 수정하는 데 쓸 수 있는 런타임 객체로 초기화합니다.

    -

    UI 레이아웃 생성에 대한 완전한 가이드는 XML +

    UI 레이아웃 생성에 대한 완전한 가이드는 XML 레이아웃을 참조하십시오. - +

    사용자 인터페이스 구성 요소

    UI를 구축할 때 모두 {@link android.view.View} 및 {@link -android.view.ViewGroup} 객체를 사용해야 하는 것은 아닙니다. Android가 표준형 UI 레이아웃을 제공하는 앱 구성 요소를 여러 개 제공하고 있으니, -개발자 여러분은 이에 대한 콘텐츠만 정의하면 됩니다. 이와 같은 UI 구성 요소에는 각각 +android.view.ViewGroup} 객체를 사용해야 하는 것은 아닙니다. Android가 표준형 UI 레이아웃을 제공하는 앱 구성 요소를 여러 개 제공하고 있으니, +개발자 여러분은 이에 대한 콘텐츠만 정의하면 됩니다. 이와 같은 UI 구성 요소에는 각각 고유한 API 세트가 있습니다. 이들은 작업 모음, 대화상태 알림 등 각각 다른 문서에서 설명하였습니다.

    diff --git a/docs/html-intl/intl/ko/guide/topics/ui/settings.jd b/docs/html-intl/intl/ko/guide/topics/ui/settings.jd index 36204e03ecf5efbdf65db34b2189e755581bff00..01b62ed6783a277c7bc49841a052a631b3e5e340 100644 --- a/docs/html-intl/intl/ko/guide/topics/ui/settings.jd +++ b/docs/html-intl/intl/ko/guide/topics/ui/settings.jd @@ -65,13 +65,13 @@ page.tags=preference,preferenceactivity,preferencefragment -

    애플리케이션에는 종종 설정이 포함되어 있어 사용자가 앱 기능과 행동을 수정할 수 있게 해줍니다. 예를 들어 -몇몇 앱은 사용자에게 알림을 활성화할지 여부를 지정하거나 애플리케이션이 +

    애플리케이션에는 종종 설정이 포함되어 있어 사용자가 앱 기능과 행동을 수정할 수 있게 해줍니다. 예를 들어 +몇몇 앱은 사용자에게 알림을 활성화할지 여부를 지정하거나 애플리케이션이 클라우드와 데이터를 동기화할 빈도를 지정할 수 있게 해줍니다.

    -

    자신의 앱에 설정을 제공하고자 하는 경우, Android의 -{@link android.preference.Preference} API를 사용하여 다른 Android 앱(시스템 설정 포함)의 사용자 환경과 -일관성을 유지하는 인터페이스를 구축할 수 있게 해야 합니다. 이 문서에서는 +

    자신의 앱에 설정을 제공하고자 하는 경우, Android의 +{@link android.preference.Preference} API를 사용하여 다른 Android 앱(시스템 설정 포함)의 사용자 환경과 +일관성을 유지하는 인터페이스를 구축할 수 있게 해야 합니다. 이 문서에서는 {@link android.preference.Preference} API를 사용하여 앱 설정을 구축하는 방법을 설명합니다.

    @@ -81,8 +81,8 @@ page.tags=preference,preferenceactivity,preferencefragment -

    그림 1. Android 메시지 앱의 설정에서 가져온 -스크린샷입니다. {@link android.preference.Preference}가 정의한 항목을 선택하면 +

    그림 1. Android 메시지 앱의 설정에서 가져온 +스크린샷입니다. {@link android.preference.Preference}가 정의한 항목을 선택하면 인터페이스가 열려 설정을 변경할 수 있게 됩니다.

    @@ -90,24 +90,24 @@ page.tags=preference,preferenceactivity,preferencefragment

    개요

    -

    사용자 인터페이스를 구축할 때에는 {@link android.view.View} 객체를 사용하지만, 설정은 그 대신 -{@link android.preference.Preference} 클래스의 다양한 하위 클래스를 사용하여 구축합니다. +

    사용자 인터페이스를 구축할 때에는 {@link android.view.View} 객체를 사용하지만, 설정은 그 대신 +{@link android.preference.Preference} 클래스의 다양한 하위 클래스를 사용하여 구축합니다. 이와 같은 하위 클래스는 XML 파일에서 선언합니다.

    -

    {@link android.preference.Preference} 객체는 하나의 설정을 이루는 기본 -단위입니다. 각각의 {@link android.preference.Preference}는 목록의 항목으로 +

    {@link android.preference.Preference} 객체는 하나의 설정을 이루는 기본 +단위입니다. 각각의 {@link android.preference.Preference}는 목록의 항목으로 나타나며 사용자가 설정을 수정하기에 적절한 UI를 제공합니다. 예를 들어 {@link android.preference.CheckBoxPreference}는 확인란을 표시하는 목록 항목을 만들고, {@link android.preference.ListPreference}는 선택 목록이 있는 대화를 여는 항목을 만듭니다.

    -

    각각의 {@link android.preference.Preference}를 추가할 때마다 상응하는 키-값 쌍이 있어 +

    각각의 {@link android.preference.Preference}를 추가할 때마다 상응하는 키-값 쌍이 있어 시스템이 이를 사용하여 해당 설정을 앱의 설정에 대한 기본 {@link android.content.SharedPreferences} -파일에 저장합니다. 사용자가 설정을 변경하면 시스템이 -{@link android.content.SharedPreferences} 파일에 있는 상응하는 값을 개발자 대신 업데이트합니다. 개발자가 직접 -연관된 {@link android.content.SharedPreferences} 파일과 상호 작용을 해야 하는 경우는 +파일에 저장합니다. 사용자가 설정을 변경하면 시스템이 +{@link android.content.SharedPreferences} 파일에 있는 상응하는 값을 개발자 대신 업데이트합니다. 개발자가 직접 +연관된 {@link android.content.SharedPreferences} 파일과 상호 작용을 해야 하는 경우는 사용자의 설정을 기반으로 앱의 동작을 결정하기 위해 값을 읽어야 할 때뿐입니다.

    -

    각 설정에 대하여 {@link android.content.SharedPreferences}에 저장된 값은 다음과 같은 +

    각 설정에 대하여 {@link android.content.SharedPreferences}에 저장된 값은 다음과 같은 데이터 유형 중 한 가지를 취할 수 있습니다.

      @@ -119,31 +119,31 @@ android.preference.ListPreference}는 선택 목록이 있는 대화를 여는
    • String {@link java.util.Set}
    -

    앱의 설정 UI는 -{@link android.view.View} 객체 대신 -{@link android.preference.Preference} 객체를 사용하여 구축되기 때문에, 목록 설정을 표시하려면 특수 {@link android.app.Activity} 또는 +

    앱의 설정 UI는 +{@link android.view.View} 객체 대신 +{@link android.preference.Preference} 객체를 사용하여 구축되기 때문에, 목록 설정을 표시하려면 특수 {@link android.app.Activity} 또는 {@link android.app.Fragment} 하위 클래스를 사용해야 합니다.

      -
    • 앱이 Android 3.0 이전 버전(API 레벨 10 이하)을 지원하는 경우, 액티비티를 구축할 때 +
    • 앱이 Android 3.0 이전 버전(API 레벨 10 이하)을 지원하는 경우, 액티비티를 구축할 때 {@link android.preference.PreferenceActivity} 클래스의 확장으로 구축해야 합니다.
    • -
    • Android 3.0 이후의 경우에는 대신 기존의 {@link android.app.Activity}를 -사용해야 합니다. 이것은 앱 설정을 표시하는 {@link android.preference.PreferenceFragment}를 호스팅합니다. -하지만, 여러 개의 설정 그룹이 있는 경우 {@link android.preference.PreferenceActivity}를 사용하여 +
    • Android 3.0 이후의 경우에는 대신 기존의 {@link android.app.Activity}를 +사용해야 합니다. 이것은 앱 설정을 표시하는 {@link android.preference.PreferenceFragment}를 호스팅합니다. +하지만, 여러 개의 설정 그룹이 있는 경우 {@link android.preference.PreferenceActivity}를 사용하여 대형 화면에 맞는 창 두 개짜리 레이아웃을 만들 수도 있습니다.

    {@link android.preference.PreferenceActivity}와 {@link -android.preference.PreferenceFragment}의 인스턴스를 설정하는 방법은 기본 설정 액티비티 만들기기본 설정 +android.preference.PreferenceFragment}의 인스턴스를 설정하는 방법은 기본 설정 액티비티 만들기기본 설정 프래그먼트 사용하기에 관련된 섹션에서 논합니다.

    기본 설정

    앱에 대한 설정은 모두 {@link -android.preference.Preference} 클래스의 특정 하위 클래스로 표현됩니다. 각 하위 클래스에 핵심 속성이 한 세트씩 포함되어 있어 -설정의 제목과 기본 값 등과 같은 것을 지정할 수 있게 해줍니다. 각 하위 클래스는 또한 자신만의 -특수 속성과 사용자 인터페이스도 제공합니다. 예를 들어, 그림 1에서는 메시지 앱의 설정에서 +android.preference.Preference} 클래스의 특정 하위 클래스로 표현됩니다. 각 하위 클래스에 핵심 속성이 한 세트씩 포함되어 있어 +설정의 제목과 기본 값 등과 같은 것을 지정할 수 있게 해줍니다. 각 하위 클래스는 또한 자신만의 +특수 속성과 사용자 인터페이스도 제공합니다. 예를 들어, 그림 1에서는 메시지 앱의 설정에서 가져온 스크린샷을 나타낸 것입니다. 설정 화면에 있는 각 목록 항목은 각기 서로 다른 {@link android.preference.Preference} 객체로 지원됩니다.

    @@ -151,11 +151,11 @@ android.preference.Preference} 객체로 지원됩니다.

    {@link android.preference.CheckBoxPreference}
    -
    활성화되었거나 비활성화된 설정에 대한 확인란이 있는 항목을 표시합니다. 저장된 값은 +
    활성화되었거나 비활성화된 설정에 대한 확인란이 있는 항목을 표시합니다. 저장된 값은 부울입니다(확인란이 선택된 경우 true).
    {@link android.preference.ListPreference}
    -
    무선 버튼 목록이 있는 대화를 엽니다. 저장된 값은 +
    무선 버튼 목록이 있는 대화를 엽니다. 저장된 값은 지원되는 값 유형(위에 목록으로 나열) 중 어느 것이라도 될 수 있습니다.
    {@link android.preference.EditTextPreference}
    @@ -166,36 +166,36 @@ java.lang.String}입니다.

    다른 모든 하위 클래스와 이에 상응하는 속성의 목록을 보려면 {@link android.preference.Preference} 클래스를 참조하십시오.

    -

    물론 기본 제공 클래스만으로는 필요한 것을 모두 충족할 수 없고 앱에 무언가 좀 더 특수한 것이 +

    물론 기본 제공 클래스만으로는 필요한 것을 모두 충족할 수 없고 앱에 무언가 좀 더 특수한 것이 필요할 수도 있습니다. 예를 들어 플랫폼은 현재 숫자나 날짜를 선택할 수 있는 {@link -android.preference.Preference} 클래스를 제공하지 않습니다. 따라서 개발자 나름대로 +android.preference.Preference} 클래스를 제공하지 않습니다. 따라서 개발자 나름대로 {@link android.preference.Preference} 하위 클래스를 정의해야 할 수도 있습니다. 이 작업을 수행하는 데 유용한 내용인 사용자 지정 기본 설정 구축하기에 관한 섹션을 참조하십시오.

    XML로 기본 설정 정의하기

    -

    새로운 {@link android.preference.Preference} 객체를 런타임에 인스턴트화하는 것도 가능하지만, +

    새로운 {@link android.preference.Preference} 객체를 런타임에 인스턴트화하는 것도 가능하지만, 설정 목록을 정의할 때에는 {@link android.preference.Preference} -객체의 계층과 함께 XML을 사용해야 합니다. 설정 컬렉션을 정의하는 데 XM 파일을 사용하는 것이 선호되는 이유는 이 파일이 -읽기 쉬운 구조를 제공하여 업데이트가 단순하기 때문입니다. 또한, 앱의 설정은 보통 +객체의 계층과 함께 XML을 사용해야 합니다. 설정 컬렉션을 정의하는 데 XM 파일을 사용하는 것이 선호되는 이유는 이 파일이 +읽기 쉬운 구조를 제공하여 업데이트가 단순하기 때문입니다. 또한, 앱의 설정은 보통 미리 정의되어 있습니다. 다만 개발자도 여전히 런타임에 설정 컬렉션을 수정할 수 있습니다.

    -

    각 {@link android.preference.Preference} 하위 클래스는 클래스 이름에 일치하는 XML 요소로 +

    각 {@link android.preference.Preference} 하위 클래스는 클래스 이름에 일치하는 XML 요소로 선언하면 됩니다. 예를 들면 {@code <CheckBoxPreference>}가 이에 해당됩니다.

    -

    이 XML 파일은 반드시 {@code res/xml/} 디렉터리에 저장해야 합니다. 파일의 이름은 무엇이든 원하는 대로 지정할 수 있지만, -일반적으로는 {@code preferences.xml}이라고 명명합니다. 파일은 하나만 필요한 것이 보통입니다. -왜냐하면 계층에 있는 분기(자신만의 설정 목록을 엶)는 +

    이 XML 파일은 반드시 {@code res/xml/} 디렉터리에 저장해야 합니다. 파일의 이름은 무엇이든 원하는 대로 지정할 수 있지만, +일반적으로는 {@code preferences.xml}이라고 명명합니다. 파일은 하나만 필요한 것이 보통입니다. +왜냐하면 계층에 있는 분기(자신만의 설정 목록을 엶)는 {@link android.preference.PreferenceScreen}의 중첩된 인스턴스를 사용하여 선언되기 때문입니다.

    -

    참고: 설정에 다중 창 레이아웃을 만들고자 하는 경우, +

    참고: 설정에 다중 창 레이아웃을 만들고자 하는 경우, 각 프래그먼트에 대해 별도의 XML 파일이 필요합니다.

    XML 파일의 루트 노드는 반드시 {@link android.preference.PreferenceScreen <PreferenceScreen>} 요소여야 합니다. 바로 이 요소 내에 각 {@link -android.preference.Preference}를 추가하는 것입니다. -{@link android.preference.PreferenceScreen <PreferenceScreen>} 요소 내에 추가하는 각 하위는 설정 목록에서 +android.preference.Preference}를 추가하는 것입니다. +{@link android.preference.PreferenceScreen <PreferenceScreen>} 요소 내에 추가하는 각 하위는 설정 목록에서 각기 항목 하나씩으로 나타납니다.

    예:

    @@ -224,11 +224,11 @@ android.preference.ListPreference}가 하나씩 있습니다. 두 항목 모두
    {@code android:key}
    -
    이 속성은 데이터 값을 유지하는 기본 설정에 필수입니다. 이것은 고유키(문자)를 +
    이 속성은 데이터 값을 유지하는 기본 설정에 필수입니다. 이것은 고유키(문자)를 나타내며, 시스템이 이것을 사용하여 이 설정의 값을 {@link -android.content.SharedPreferences}에 저장합니다. -

    이 속성이 필요하지 않은 인스턴스는 기본 설정이 -{@link android.preference.PreferenceCategory} 또는 {@link android.preference.PreferenceScreen}인 경우, 또는 +android.content.SharedPreferences}에 저장합니다. +

    이 속성이 필요하지 않은 인스턴스는 기본 설정이 +{@link android.preference.PreferenceCategory} 또는 {@link android.preference.PreferenceScreen}인 경우, 또는 기본 설정이 {@link android.content.Intent}를 호출할 것을 나타내거나({@code <intent>} 요소로) {@link android.app.Fragment}를 표시하도록 지정하는 경우({@code android:fragment} 속성으로)뿐입니다.

    @@ -236,7 +236,7 @@ android:fragment} 속성으로)뿐입니다.

    이것은 설정에 대하여 사용자가 볼 수 있는 이름을 제공합니다.
    {@code android:defaultValue}
    이것은 시스템이 {@link -android.content.SharedPreferences} 파일에 설정해야 하는 초기 값을 나타냅니다. 모든 설정에 기본 값을 제공해야 +android.content.SharedPreferences} 파일에 설정해야 하는 초기 값을 나타냅니다. 모든 설정에 기본 값을 제공해야 합니다.
    @@ -248,21 +248,21 @@ android.preference.Preference}(및 각각의 하위 클래스) 관련 문서를

    그림 2. 제목이 있는 설정 카테고리입니다.
    1. 카테고리는 {@link -android.preference.PreferenceCategory <PreferenceCategory>} 요소가 지정합니다.
    2. 제목은 +android.preference.PreferenceCategory <PreferenceCategory>} 요소가 지정합니다.
    2. 제목은 {@code android:title} 속성으로 지정합니다.

    -

    설정 목록이 약 10개 항목을 초과하면 제목을 추가하여 -설정 그룹을 정의하거나, 해당 그룹을 별도의 +

    설정 목록이 약 10개 항목을 초과하면 제목을 추가하여 +설정 그룹을 정의하거나, 해당 그룹을 별도의 화면에 표시하는 것이 좋을 수도 있습니다. 이러한 옵션은 다음 섹션에 설명되어 있습니다.

    설정 그룹 만들기

    -

    10개 이상의 설정 목록을 제시하는 경우, 사용자가 -이들을 둘러보고 이해하며 처리하는 데 어려움을 겪을 수 있습니다. 이 문제를 해결하려면 -설정의 일부 또는 모두를 그룹으로 나누어 사실상 하나의 긴 목록을 여러 개의 더 짧은 목록으로 +

    10개 이상의 설정 목록을 제시하는 경우, 사용자가 +이들을 둘러보고 이해하며 처리하는 데 어려움을 겪을 수 있습니다. 이 문제를 해결하려면 +설정의 일부 또는 모두를 그룹으로 나누어 사실상 하나의 긴 목록을 여러 개의 더 짧은 목록으로 바꿔주면 됩니다. 관련된 설정 그룹 하나를 나타낼 때에는 다음과 같은 두 가지 방식 중 하나를 택하면 됩니다.

    -

    이와 같은 그룹화 기법 중 하나 또는 둘 모두를 사용하여 앱의 설정을 조직화할 수 있습니다. 어느 것을 -사용할지, 설정을 어떻게 나눌지 결정할 때에는 Android +

    이와 같은 그룹화 기법 중 하나 또는 둘 모두를 사용하여 앱의 설정을 조직화할 수 있습니다. 어느 것을 +사용할지, 설정을 어떻게 나눌지 결정할 때에는 Android 디자인의 설정 가이드에 있는 지침을 따라야 합니다.

    제목 사용하기

    -

    여러 개의 설정 그룹 사이에 구분선과 제목을 제공하고자 하는 경우(그림 2에 표시된 것과 같이), +

    여러 개의 설정 그룹 사이에 구분선과 제목을 제공하고자 하는 경우(그림 2에 표시된 것과 같이), 각 {@link android.preference.Preference} 객체 그룹을 {@link android.preference.PreferenceCategory} 내부에 배치합니다.

    @@ -285,7 +285,7 @@ android.preference.PreferenceCategory} 내부에 배치합니다.

     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    -    <PreferenceCategory 
    +    <PreferenceCategory
             android:title="@string/pref_sms_storage_title"
             android:key="pref_key_storage_settings">
             <CheckBoxPreference
    @@ -293,12 +293,12 @@ android.preference.PreferenceCategory} 내부에 배치합니다.

    android:summary="@string/pref_summary_auto_delete" android:title="@string/pref_title_auto_delete" android:defaultValue="false"... /> - <Preference + <Preference android:key="pref_key_sms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_sms_delete"... /> - <Preference + <Preference android:key="pref_key_mms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" @@ -311,13 +311,13 @@ android.preference.PreferenceCategory} 내부에 배치합니다.

    보조 화면 사용하기

    -

    설정 그룹 여러 개를 보조 화면에 배치하고자 하는 경우(그림 3에 표시된 것과 같이), 해당 +

    설정 그룹 여러 개를 보조 화면에 배치하고자 하는 경우(그림 3에 표시된 것과 같이), 해당 {@link android.preference.Preference} 객체 그룹을 {@link android.preference.PreferenceScreen} 안에 배치합니다.

    그림 3. 설정 보조 화면입니다. {@code -<PreferenceScreen>} 요소가 +<PreferenceScreen>} 요소가 항목을 만들며, 이 항목이 선택되면 별도의 목록이 열려 중첩된 설정을 표시합니다.

    예:

    @@ -352,7 +352,7 @@ android.preference.PreferenceScreen} 안에 배치합니다.

    인텐트 사용하기

    -

    어떤 경우에는 기본 설정 항목을 사용하여 설정 화면 대신 여러 가지 액티비티를 +

    어떤 경우에는 기본 설정 항목을 사용하여 설정 화면 대신 여러 가지 액티비티를 열고자 할 수도 있습니다. 예를 들어 웹 브라우저를 열어 웹 페이지를 보는 것이 이에 해당됩니다. 사용자가 기본 설정 항목을 선택할 때 {@link android.content.Intent}를 호출하도록 하려면, {@code <intent>} 요소를 상응하는 {@code <Preference>} 요소의 하위로 추가하면 됩니다.

    @@ -392,18 +392,18 @@ android.content.Intent#setComponent setComponent()} 메서드를 따릅니다.설정을 액티비티에서 표시하려면 {@link android.preference.PreferenceActivity} 클래스를 확장하면 됩니다. 이것은 일반적인 {@link android.app.Activity} 클래스 확장의 일종입니다. 이는 {@link -android.preference.Preference} 객체의 계층에 기반한 설정 목록을 표시합니다. {@link android.preference.PreferenceActivity}는 +android.preference.Preference} 객체의 계층에 기반한 설정 목록을 표시합니다. {@link android.preference.PreferenceActivity}는 사용자가 변경 작업을 하면 각 {@link android.preference.Preference}와 연관된 설정을 유지합니다.

    -

    참고: Android 3.0 이상에 맞춰 애플리케이션을 개발하는 경우, -대신 {@link android.preference.PreferenceFragment}를 사용해야 합니다. 다음 섹션의 +

    참고: Android 3.0 이상에 맞춰 애플리케이션을 개발하는 경우, +대신 {@link android.preference.PreferenceFragment}를 사용해야 합니다. 다음 섹션의 기본 설정 프래그먼트 사용하기 관련 내용을 참조하십시오.

    여기서 기억해야 할 가장 중요한 점은 {@link android.preference.PreferenceActivity#onCreate onCreate()} 콜백 중에 보기 레이아웃을 로딩해서는 안 된다는 것입니다. 그 대신 {@link -android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 호출하여 -XML 파일에서 선언한 기본 설정을 액티비티에 추가합니다. 예를 들어 다음은 기능적인 +android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 호출하여 +XML 파일에서 선언한 기본 설정을 액티비티에 추가합니다. 예를 들어 다음은 기능적인 {@link android.preference.PreferenceActivity}에 필요한 가장 최소한의 코드를 나타낸 것입니다.

    @@ -416,11 +416,11 @@ public class SettingsActivity extends PreferenceActivity {
     }
     
    -

    사실 이 코드만으로 몇몇 앱에는 충분합니다. 사용자가 기본 설정을 수정하자마자 -시스템이 해당 변경을 기본 {@link android.content.SharedPreferences} 파일에 저장하여, -사용자의 설정을 확인해야 할 때 다른 애플리케이션 구성 요소가 이를 읽을 수 있도록 하기 때문입니다. 하지만 +

    사실 이 코드만으로 몇몇 앱에는 충분합니다. 사용자가 기본 설정을 수정하자마자 +시스템이 해당 변경을 기본 {@link android.content.SharedPreferences} 파일에 저장하여, +사용자의 설정을 확인해야 할 때 다른 애플리케이션 구성 요소가 이를 읽을 수 있도록 하기 때문입니다. 하지만 대다수의 앱은 기본 설정에 일어나는 변경을 수신 대기하기 위해 약간의 코드가 더 필요합니다. -{@link android.content.SharedPreferences} 파일에 일어나는 변경을 수신 대기하는 데 관한 +{@link android.content.SharedPreferences} 파일에 일어나는 변경을 수신 대기하는 데 관한 자세한 정보는 기본 설정 읽기에 관한 섹션을 참조하십시오.

    @@ -430,17 +430,17 @@ public class SettingsActivity extends PreferenceActivity {

    Android 3.0(API 레벨 11) 이상에 맞춰 개발하는 경우, {@link android.preference.PreferenceFragment}를 사용하여 {@link android.preference.Preference} -객체 목록을 표시해야 합니다. {@link android.preference.PreferenceFragment}는 모든 액티비티에 추가할 수 있습니다. 즉, +객체 목록을 표시해야 합니다. {@link android.preference.PreferenceFragment}는 모든 액티비티에 추가할 수 있습니다. 즉, {@link android.preference.PreferenceActivity}를 사용하지 않아도 됩니다.

    -

    프래그먼트는 액티비티만 -사용하는 것에 비해 애플리케이션에 보다 유연한 아키텍처를 제공하며, 이는 구축하는 +

    프래그먼트는 액티비티만 +사용하는 것에 비해 애플리케이션에 보다 유연한 아키텍처를 제공하며, 이는 구축하는 액티비티의 종류와 무관하게 적용됩니다. 따라서 설정 표시를 제어하는 데에는 {@link android.preference.PreferenceFragment}를 {@link android.preference.PreferenceActivity} 대신 사용하는 방안을 권장합니다(가능한 경우).

    {@link android.preference.PreferenceFragment} 구현은 매우 간단합니다. -{@link android.preference.PreferenceFragment#onCreate onCreate()} 메서드를 정의하여 기본 설정 파일을 +{@link android.preference.PreferenceFragment#onCreate onCreate()} 메서드를 정의하여 기본 설정 파일을 {@link android.preference.PreferenceFragment#addPreferencesFromResource addPreferencesFromResource()}로 로딩하도록 하기만 하면 됩니다. 예:

    @@ -457,7 +457,7 @@ public static class SettingsFragment extends PreferenceFragment { }
    -

    그런 다음 이 프래그먼트를 {@link android.app.Activity}에 추가하기만 하면 되고, 이는 다른 모든 +

    그런 다음 이 프래그먼트를 {@link android.app.Activity}에 추가하기만 하면 되고, 이는 다른 모든 {@link android.app.Fragment}에서와 마찬가지입니다. 예:

    @@ -474,24 +474,24 @@ public class SettingsActivity extends Activity {
     }
     
    -

    참고: {@link android.preference.PreferenceFragment}에는 자신만의 +

    참고: {@link android.preference.PreferenceFragment}에는 자신만의 {@link android.content.Context} 객체가 없습니다. {@link android.content.Context} -객체가 필요한 경우, {@link android.app.Fragment#getActivity()}를 호출하면 됩니다. 하지만, -{@link android.app.Fragment#getActivity()}를 호출하는 것은 프래그먼트가 액티비티에 첨부되어 있는 경우만으로 국한시켜야 한다는 점을 유의하십시오. 프래그먼트가 +객체가 필요한 경우, {@link android.app.Fragment#getActivity()}를 호출하면 됩니다. 하지만, +{@link android.app.Fragment#getActivity()}를 호출하는 것은 프래그먼트가 액티비티에 첨부되어 있는 경우만으로 국한시켜야 한다는 점을 유의하십시오. 프래그먼트가 아직 첨부되지 않았거나 수명 주기가 끝날 무렵 분리된 경우, {@link android.app.Fragment#getActivity()}가 null을 반환합니다.

    설정 기본 값

    -

    여러분이 만드는 기본 설정은 애플리케이션에 중요한 동작을 정의하는 경우가 많을 것입니다. 따라서 -연관된 {@link android.content.SharedPreferences} 파일을 -각 {@link android.preference.Preference}에 대한 기본 값으로 초기화하여 사용자가 애플리케이션을 처음 열 때 +

    여러분이 만드는 기본 설정은 애플리케이션에 중요한 동작을 정의하는 경우가 많을 것입니다. 따라서 +연관된 {@link android.content.SharedPreferences} 파일을 +각 {@link android.preference.Preference}에 대한 기본 값으로 초기화하여 사용자가 애플리케이션을 처음 열 때 적용하는 것이 중요합니다.

    가장 먼저 해야 할 일은 XML 파일 내의 각 {@link android.preference.Preference} -객체에 대해 기본 값을 지정하는 것입니다. 이때 {@code android:defaultValue} 속성을 사용합니다. 이 값은 상응하는 +객체에 대해 기본 값을 지정하는 것입니다. 이때 {@code android:defaultValue} 속성을 사용합니다. 이 값은 상응하는 {@link android.preference.Preference} 객체에 대해 적절한 어느 데이터 유형이라도 될 수 있습니다. 예:

    @@ -507,8 +507,8 @@ android.preference.Preference} ... /> -

    그런 다음, 애플리케이션의 기본 액티비티에 있는 {@link android.app.Activity#onCreate onCreate()} -메서드로부터—또한 사용자가 애플리케이션에 처음으로 들어올 통로가 될 수 있는 +

    그런 다음, 애플리케이션의 기본 액티비티에 있는 {@link android.app.Activity#onCreate onCreate()} +메서드로부터—또한 사용자가 애플리케이션에 처음으로 들어올 통로가 될 수 있는 다른 모든 액티비티도 포함—{@link android.preference.PreferenceManager#setDefaultValues setDefaultValues()}를 호출합니다.

    @@ -516,9 +516,9 @@ setDefaultValues()}를 호출합니다.

    PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false); -

    이것을 {@link android.app.Activity#onCreate onCreate()} 중에 호출하면 -애플리케이션이 기본 설정으로 적절히 초기화되도록 보장할 수 있습니다. 이것은 애플리케이션이 -몇 가지 동작을 결정하기 위해 읽어야 할 수도 있습니다(예를 들어 셀룰러 네트워크에서 데이터를 +

    이것을 {@link android.app.Activity#onCreate onCreate()} 중에 호출하면 +애플리케이션이 기본 설정으로 적절히 초기화되도록 보장할 수 있습니다. 이것은 애플리케이션이 +몇 가지 동작을 결정하기 위해 읽어야 할 수도 있습니다(예를 들어 셀룰러 네트워크에서 데이터를 다운로드할지 여부 등).

    이 메서드는 다음과 같은 세 개의 인수를 취합니다.

    @@ -526,73 +526,73 @@ PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
  • 애플리케이션 {@link android.content.Context}.
  • 기본 값을 설정하고자 하는 기본 설정 XML 파일에 대한 리소스 ID입니다.
  • 기본 값을 한 번 이상 설정해야 하는지 여부를 나타내는 부울 값입니다. -

    false인 경우, 시스템은 이 메서드가 전에 한 번도 호출된 적이 없을 경우에만 +

    false인 경우, 시스템은 이 메서드가 전에 한 번도 호출된 적이 없을 경우에만 기본 값을 설정합니다(아니면 기본 값을 공유한 기본 설정 파일에 있는 {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} 가 안전합니다).

  • -

    세 번째 인수를 false로 설정해 두는 한 이 메서드를 액티비티가 시작될 때마다 -안전하게 호출할 수 있으며, 그렇게 해도 사용자의 저장된 기본 설정을 기본값으로 초기화하여 -재정의하지 않습니다. 하지만 이를 true로 설정하면, 이전의 모든 값을 +

    세 번째 인수를 false로 설정해 두는 한 이 메서드를 액티비티가 시작될 때마다 +안전하게 호출할 수 있으며, 그렇게 해도 사용자의 저장된 기본 설정을 기본값으로 초기화하여 +재정의하지 않습니다. 하지만 이를 true로 설정하면, 이전의 모든 값을 기본 값으로 재정의하게 됩니다.

    기본 설정 헤더 사용하기

    -

    드문 경우지만 설정을 디자인할 때 첫 화면에는 -보조 화면 목록만 표시하도록 하고자 할 수도 있습니다(예: 시스템 설정 앱, -그림 4와 5 참조). 그러한 디자인을 Android 3.0 이상을 대상으로 개발하는 경우, Android 3.0에 있는 -새로운 "헤더" 기능을 사용해야 합니다. 이것이 중첩된 +

    드문 경우지만 설정을 디자인할 때 첫 화면에는 +보조 화면 목록만 표시하도록 하고자 할 수도 있습니다(예: 시스템 설정 앱, +그림 4와 5 참조). 그러한 디자인을 Android 3.0 이상을 대상으로 개발하는 경우, Android 3.0에 있는 +새로운 "헤더" 기능을 사용해야 합니다. 이것이 중첩된 {@link android.preference.PreferenceScreen} 요소를 사용하여 보조 화면을 구축하는 방안을 대신합니다.

    헤더를 사용하여 설정을 구축하려면 다음과 같이 해야 합니다.

    1. 각 설정 그룹을 별개의 {@link -android.preference.PreferenceFragment} 인스턴스로 구분합니다. 다시 말해, 설정 그룹마다 별도의 XML 파일이 하나씩 있어야 한다는 +android.preference.PreferenceFragment} 인스턴스로 구분합니다. 다시 말해, 설정 그룹마다 별도의 XML 파일이 하나씩 있어야 한다는 뜻입니다.
    2. -
    3. 각 설정 그룹을 목록으로 나열하는 XML 헤더 파일을 생성하고 어느 프래그먼트에 +
    4. 각 설정 그룹을 목록으로 나열하는 XML 헤더 파일을 생성하고 어느 프래그먼트에 상응하는 설정 목록이 들어있는지 선언합니다.
    5. {@link android.preference.PreferenceActivity} 클래스를 확장하여 설정을 호스팅하도록 합니다.
    6. {@link -android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 콜백을 구현하여 헤더 파일을 +android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 콜백을 구현하여 헤더 파일을 나타냅니다.
    -

    이 디자인을 사용하는 데 있어 커다란 이점은 {@link android.preference.PreferenceActivity}가 +

    이 디자인을 사용하는 데 있어 커다란 이점은 {@link android.preference.PreferenceActivity}가 (앱이) 대형 화면에서 실행될 때 그림 4에서 나타낸 것과 같이 창 두 개짜리 레이아웃을 자동으로 표시한다는 것입니다.

    -

    애플리케이션이 Android 3.0 이전 버전을 지원한다 하더라도 애플리케이션이 -{@link android.preference.PreferenceFragment}를 사용하여 -신형 기기에서 창 두 개짜리 표시를 지원하도록 하면서도 구형 기기에서는 일반적인 다중 화면 계층을 -여전히 지원하도록 할 수도 있습니다(기본 설정 헤더로 +

    애플리케이션이 Android 3.0 이전 버전을 지원한다 하더라도 애플리케이션이 +{@link android.preference.PreferenceFragment}를 사용하여 +신형 기기에서 창 두 개짜리 표시를 지원하도록 하면서도 구형 기기에서는 일반적인 다중 화면 계층을 +여전히 지원하도록 할 수도 있습니다(기본 설정 헤더로 이전 버전 지원하기를 참조하십시오).

    -

    그림 4. 헤더가 있는 창 두 개짜리 레이아웃입니다.
    1. 헤더는 -XML 헤더 파일로 정의됩니다.
    2. 각 설정 그룹은 -{@link android.preference.PreferenceFragment}가 정의하며, 이는 헤더 파일에 있는 {@code <header>} 요소가 +

    그림 4. 헤더가 있는 창 두 개짜리 레이아웃입니다.
    1. 헤더는 +XML 헤더 파일로 정의됩니다.
    2. 각 설정 그룹은 +{@link android.preference.PreferenceFragment}가 정의하며, 이는 헤더 파일에 있는 {@code <header>} 요소가 지정합니다.

    -

    그림 5. 설정 헤더가 있는 핸드셋 기기입니다. 항목을 선택하면 -연관된 {@link android.preference.PreferenceFragment}가 헤더를 +

    그림 5. 설정 헤더가 있는 핸드셋 기기입니다. 항목을 선택하면 +연관된 {@link android.preference.PreferenceFragment}가 헤더를 대체합니다.

    헤더 파일 만들기

    -

    헤더 목록에 있는 각 설정 그룹은 루트 {@code <preference-headers>} +

    헤더 목록에 있는 각 설정 그룹은 루트 {@code <preference-headers>} 요소 안에 있는 {@code <header>} 요소 하나로 나타냅니다. 예:

     <?xml version="1.0" encoding="utf-8"?>
     <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one" />
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" >
    @@ -607,12 +607,12 @@ android.preference.PreferenceFragment} 예를 선언하며 이는 사용자가 
     
     

    {@code <extras>} 요소를 사용하면 키-값 쌍을 {@link android.os.Bundle} 내의 프래그먼트에 전달할 수 있게 해줍니다. 이 프래그먼트가 인수를 검색하려면 {@link -android.app.Fragment#getArguments()}를 호출하면 됩니다. 인수를 프래그먼트에 전달하는 데에는 여러 가지 이유가 있을 수 있지만, +android.app.Fragment#getArguments()}를 호출하면 됩니다. 인수를 프래그먼트에 전달하는 데에는 여러 가지 이유가 있을 수 있지만, 한 가지 중요한 이유를 예로 들면 각 그룹에 대해 {@link -android.preference.PreferenceFragment}의 같은 하위 클래스를 재사용하고, 이 인수를 사용하여 해당 프래그먼트가 로딩해야 하는 +android.preference.PreferenceFragment}의 같은 하위 클래스를 재사용하고, 이 인수를 사용하여 해당 프래그먼트가 로딩해야 하는 기본 설정 XML 파일이 무엇인지 나타낼 수 있다는 점입니다.

    -

    예를 들어 다음은 여러 가지 설정 그룹에 재사용할 수 있는 프래그먼트입니다. 이것은 +

    예를 들어 다음은 여러 가지 설정 그룹에 재사용할 수 있는 프래그먼트입니다. 이것은 각 헤더가 {@code "settings"} 키로 {@code <extra>} 인수를 정의하는 경우를 나타낸 것입니다.

    @@ -636,7 +636,7 @@ public static class SettingsFragment extends PreferenceFragment {
     

    헤더 표시하기

    기본 설정 헤더를 표시하려면 {@link -android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 콜백 메서드를 구현하고 +android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 콜백 메서드를 구현하고 {@link android.preference.PreferenceActivity#loadHeadersFromResource loadHeadersFromResource()}를 호출해야 합니다. 예:

    @@ -654,56 +654,56 @@ android.preference.PreferenceFragment}를 엽니다.

    참고: 기본 설정 헤더를 사용하는 경우, {@link android.preference.PreferenceActivity}의 하위 클래스가 {@link -android.preference.PreferenceActivity#onCreate onCreate()} 메서드를 구현하지 않아도 됩니다. 액티비티에 대한 필수 작업은 +android.preference.PreferenceActivity#onCreate onCreate()} 메서드를 구현하지 않아도 됩니다. 액티비티에 대한 필수 작업은 헤더를 로딩하는 것뿐이기 때문입니다.

    기본 설정 헤더로 이전 버전 지원하기

    -

    애플리케이션이 Android 3.0 이전 버전을 지원하는 경우에도 여전히 헤더를 사용하여 -Android 3.0 이상에서 창 두 개짜리 레이아웃을 제공하도록 할 수 있습니다. 개발자가 해야 할 일은 추가로 기본 설정 XML 파일을 +

    애플리케이션이 Android 3.0 이전 버전을 지원하는 경우에도 여전히 헤더를 사용하여 +Android 3.0 이상에서 창 두 개짜리 레이아웃을 제공하도록 할 수 있습니다. 개발자가 해야 할 일은 추가로 기본 설정 XML 파일을 생성하는 것뿐입니다. 이 파일은 마치 헤더 항목처럼 동작하는 기본적인 {@link android.preference.Preference -<Preference>} 요소를 사용합니다(이것을 이전 Android 버전이 사용하도록 +<Preference>} 요소를 사용합니다(이것을 이전 Android 버전이 사용하도록 할 예정).

    하지만 새로운 {@link android.preference.PreferenceScreen}을 여는 대신 각 {@link -android.preference.Preference <Preference>} 요소가 {@link android.content.Intent}를 하나씩 -{@link android.preference.PreferenceActivity}에 전송합니다. 이것이 로딩할 XML 파일이 무엇인지를 +android.preference.Preference <Preference>} 요소가 {@link android.content.Intent}를 하나씩 +{@link android.preference.PreferenceActivity}에 전송합니다. 이것이 로딩할 XML 파일이 무엇인지를 나타냅니다.

    -

    예를 들어 다음은 Android 3.0 이상에서 사용되는 기본 설정 헤더에 대한 -XML 파일입니다({@code res/xml/preference_headers.xml}).

    +

    예를 들어 다음은 Android 3.0 이상에서 사용되는 기본 설정 헤더에 대한 +XML 파일입니다({@code res/xml/preference_headers.xml}).

     <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsFragmentOne"
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one" />
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsFragmentTwo"
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" />
     </preference-headers>
     
    -

    그리고 다음은, Android 3.0 이전 버전에 같은 헤더를 제공하는 기본 설정 +

    그리고 다음은, Android 3.0 이전 버전에 같은 헤더를 제공하는 기본 설정 파일입니다({@code res/xml/preference_headers_legacy.xml}).

     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    -    <Preference 
    +    <Preference
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one"  >
    -        <intent 
    +        <intent
                 android:targetPackage="com.example.prefs"
                 android:targetClass="com.example.prefs.SettingsActivity"
                 android:action="com.example.prefs.PREFS_ONE" />
         </Preference>
    -    <Preference 
    +    <Preference
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" >
    -        <intent 
    +        <intent
                 android:targetPackage="com.example.prefs"
                 android:targetClass="com.example.prefs.SettingsActivity"
                 android:action="com.example.prefs.PREFS_TWO" />
    @@ -711,13 +711,13 @@ XML 파일입니다({@code res/xml/preference_headers.xml}).

    </PreferenceScreen>
    -

    {@code <preference-headers>}에 대한 지원이 Android 3.0에서 추가되었기 때문에 시스템이 +

    {@code <preference-headers>}에 대한 지원이 Android 3.0에서 추가되었기 때문에 시스템이 {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()}를 {@link -android.preference.PreferenceActivity}에서 호출하는 것은 Android 3.0 이상에서 실행될 때뿐입니다. "레거시" 헤더 파일을 -로딩하려면({@code preference_headers_legacy.xml}) 반드시 Android +android.preference.PreferenceActivity}에서 호출하는 것은 Android 3.0 이상에서 실행될 때뿐입니다. "레거시" 헤더 파일을 +로딩하려면({@code preference_headers_legacy.xml}) 반드시 Android 버전을 확인해야 하며, 해당 버전이 Android 3.0 이전인 경우({@link android.os.Build.VERSION_CODES#HONEYCOMB}), {@link -android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 호출하여 +android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 호출하여 레거시 헤더 파일을 로딩해야 합니다. 예:

    @@ -739,8 +739,8 @@ public void onBuildHeaders(List<Header> target) {
     }
     
    -

    이제 남은 할 일이라고는 {@link android.content.Intent}를 처리하는 것뿐입니다. 이것은 -액티비티로 전달되어 어느 기본 설정 파일을 로딩해야 하는지 식별하는 데 쓰입니다. 그럼 이제 인텐트의 작업을 검색하여 기본 설정 XML의 +

    이제 남은 할 일이라고는 {@link android.content.Intent}를 처리하는 것뿐입니다. 이것은 +액티비티로 전달되어 어느 기본 설정 파일을 로딩해야 하는지 식별하는 데 쓰입니다. 그럼 이제 인텐트의 작업을 검색하여 기본 설정 XML의 {@code <intent>} 태그에서 사용한 알려진 작업 문자열에 비교해보겠습니다.

    @@ -765,8 +765,8 @@ public void onCreate(Bundle savedInstanceState) {
     

    {@link -android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 연이어 호출하면 -모든 기본 설정을 하나의 목록에 쌓게 된다는 점을 유의하십시오. 따라서 이것은 'Else-if' 문이 있는 조건을 변경하여 딱 한 번만 +android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()}를 연이어 호출하면 +모든 기본 설정을 하나의 목록에 쌓게 된다는 점을 유의하십시오. 따라서 이것은 'Else-if' 문이 있는 조건을 변경하여 딱 한 번만 호출하도록 주의해야 합니다.

    @@ -775,15 +775,15 @@ android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesF

    기본 설정 읽기

    -

    기본적으로 앱의 기본 설정은 모두 +

    기본적으로 앱의 기본 설정은 모두 애플리케이션 내의 어디서든 정적 메서드 {@link android.preference.PreferenceManager#getDefaultSharedPreferences PreferenceManager.getDefaultSharedPreferences()}를 호출하면 액세스할 수 있는 파일에 저장됩니다. 이것은 {@link android.content.SharedPreferences} 객체를 반환하며, 여기에 {@link -android.preference.PreferenceActivity}에서 사용한 {@link android.preference.Preference} 객체와 +android.preference.PreferenceActivity}에서 사용한 {@link android.preference.Preference} 객체와 연관된 모든 키-값 쌍이 들어있습니다.

    -

    예를 들어 다음은 기본 설정 값 중 하나를 애플리케이션 내의 다른 모든 액티비티에서 읽는 방법을 +

    예를 들어 다음은 기본 설정 값 중 하나를 애플리케이션 내의 다른 모든 액티비티에서 읽는 방법을 나타낸 것입니다.

    @@ -795,17 +795,17 @@ String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN,
     
     

    기본 설정 변경 수신 대기

    -

    사용자가 기본 설정 중 하나를 변경하자마자 이에 대해 알림을 받는 것이 좋은 데에는 몇 가지 -이유가 있습니다. 기본 설정 중 어느 하나에라도 변경이 발생했을 때 콜백을 받으려면, +

    사용자가 기본 설정 중 하나를 변경하자마자 이에 대해 알림을 받는 것이 좋은 데에는 몇 가지 +이유가 있습니다. 기본 설정 중 어느 하나에라도 변경이 발생했을 때 콜백을 받으려면, {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener -SharedPreference.OnSharedPreferenceChangeListener} 인터페이스를 구현하고 +SharedPreference.OnSharedPreferenceChangeListener} 인터페이스를 구현하고 {@link android.content.SharedPreferences} 객체에 대한 수신기를 등록합니다. 이때 {@link android.content.SharedPreferences#registerOnSharedPreferenceChangeListener registerOnSharedPreferenceChangeListener()}를 호출하면 됩니다.

    이 인터페이스에는 콜백 메서드가 {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged -onSharedPreferenceChanged()} 하나뿐이며, 인터페이스를 액티비티의 일부분으로 구현하는 것이 +onSharedPreferenceChanged()} 하나뿐이며, 인터페이스를 액티비티의 일부분으로 구현하는 것이 가장 쉬운 방법일 공산이 큽니다. 예:

    @@ -825,19 +825,19 @@ public class SettingsActivity extends PreferenceActivity
     }
     
    -

    이 예시에서 메서드는 변경된 설정이 알려진 기본 설정 키에 대한 것인지 여부를 확인합니다. 이것은 -{@link android.preference.PreferenceActivity#findPreference findPreference()}를 호출하여 -변경된 {@link android.preference.Preference} 객체를 가져오는데, 이렇게 해야 항목의 요약을 수정하여 +

    이 예시에서 메서드는 변경된 설정이 알려진 기본 설정 키에 대한 것인지 여부를 확인합니다. 이것은 +{@link android.preference.PreferenceActivity#findPreference findPreference()}를 호출하여 +변경된 {@link android.preference.Preference} 객체를 가져오는데, 이렇게 해야 항목의 요약을 수정하여 사용자의 선택에 대한 설명이 되도록 할 수 있습니다. 다시 말해, 설정이 {@link android.preference.ListPreference} 또는 다른 다중 선택 설정인 경우, 설정이 변경되어 현재 상태를 표시하도록 하면 {@link -android.preference.Preference#setSummary setSummary()}를 호출해야 한다는 뜻입니다(예를 들어 +android.preference.Preference#setSummary setSummary()}를 호출해야 한다는 뜻입니다(예를 들어 그림 5에 표시된 절전 모드 설정과 같음).

    -

    참고: Android 디자인 문서의 설정 관련 내용에서 설명한 바와 같이, 사용자가 기본 설정을 변경할 때마다 -{@link android.preference.ListPreference}의 요약을 업데이트하는 것을 권장합니다. 이렇게 하여 현재 설정을 +

    참고: Android 디자인 문서의 설정 관련 내용에서 설명한 바와 같이, 사용자가 기본 설정을 변경할 때마다 +{@link android.preference.ListPreference}의 요약을 업데이트하는 것을 권장합니다. 이렇게 하여 현재 설정을 나타내는 것입니다.

    -

    액티비티에서 적절한 수명 주기 관리를 수행하려면 +

    액티비티에서 적절한 수명 주기 관리를 수행하려면 {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener}를 등록하고 등록 해제하는 작업은 각각 {@link android.app.Activity#onResume} 및 {@link android.app.Activity#onPause} 콜백 중에 수행하는 것을 권장합니다.

    @@ -859,14 +859,14 @@ protected void onPause() {

    주의: {@link android.content.SharedPreferences#registerOnSharedPreferenceChangeListener -registerOnSharedPreferenceChangeListener()}를 호출하면 -현재의 경우, 기본 설정 관리자가 수신기에 대한 강력한 참조를 저장하지 않습니다. 반드시 수신기에 대한 강력한 -참조를 저장해야 합니다. 그렇지 않으면 가비지 수집의 대상이 될 가능성이 높습니다. 권장 사항으로는 -수신기를 객체의 인스턴스 데이터 안에 보관하는 것을 추천합니다. 이 객체는 +registerOnSharedPreferenceChangeListener()}를 호출하면 +현재의 경우, 기본 설정 관리자가 수신기에 대한 강력한 참조를 저장하지 않습니다. 반드시 수신기에 대한 강력한 +참조를 저장해야 합니다. 그렇지 않으면 가비지 수집의 대상이 될 가능성이 높습니다. 권장 사항으로는 +수신기를 객체의 인스턴스 데이터 안에 보관하는 것을 추천합니다. 이 객체는 수신기를 필요로 하는 기간만큼 오래 존재할 것이 확실해야 합니다.

    -

    예를 들어 다음 코드에서 발신자는 수신기에 대한 참조를 -보관하지 않습니다. 그 결과 해당 수신기가 가비지 수집의 대상이 되며 +

    예를 들어 다음 코드에서 발신자는 수신기에 대한 참조를 +보관하지 않습니다. 그 결과 해당 수신기가 가비지 수집의 대상이 되며 향후 언젠가 알 수 없는 시점에 고장을 일으키게 될 것입니다.

    @@ -879,7 +879,7 @@ prefs.registerOnSharedPreferenceChangeListener(
     });
     
    -

    대신, 수신기에 대한 참조를 수신기가 필요한 기간만큼 오래 존재할 것이 확실한 객체의 +

    대신, 수신기에 대한 참조를 수신기가 필요한 기간만큼 오래 존재할 것이 확실한 객체의 인스턴스 데이터 필드에 저장하십시오.

    @@ -895,19 +895,19 @@ prefs.registerOnSharedPreferenceChangeListener(listener);
     

    네트워크 사용량 관리하기

    -

    Android 4.0부터 시스템의 설정 애플리케이션을 사용하면 사용자가 -애플리케이션이 전경과 배경에 있는 동안 각각 얼마나 많은 네트워크 데이터를 사용하는지 알아볼 수 있게 되었습니다. 그런 다음 -사용자는 각각의 앱에 대해 배경 데이터 사용을 비활성화할 수 있습니다. 사용자가 여러분의 앱이 배경에서 -데이터에 액세스하는 기능을 비활성화하는 사태를 피하려면 데이터 연결을 효율적으로 사용하고 +

    Android 4.0부터 시스템의 설정 애플리케이션을 사용하면 사용자가 +애플리케이션이 전경과 배경에 있는 동안 각각 얼마나 많은 네트워크 데이터를 사용하는지 알아볼 수 있게 되었습니다. 그런 다음 +사용자는 각각의 앱에 대해 배경 데이터 사용을 비활성화할 수 있습니다. 사용자가 여러분의 앱이 배경에서 +데이터에 액세스하는 기능을 비활성화하는 사태를 피하려면 데이터 연결을 효율적으로 사용하고 사용자가 애플리케이션 설정을 통하여 앱의 데이터 사용량을 미세 조정할 수 있도록 허용해야 합니다.

    -

    예를 들어 사용자에게 앱의 데이터 동기화 빈도를 제어하도록 허용할 수 있습니다. 앱이 Wi-Fi에 있을 때에만 -업로드/다운로드를 수행하도록 할지 여부, 앱이 로밍 중에 데이터를 사용하도록 할지 여부 등을 이렇게 조절합니다. 사용자가 -이러한 제어 기능을 사용할 수 있게 되면 시스템 설정에서 설정한 한도에 가까워지고 -있을 때 앱의 데이터 액세스를 비활성화할 가능성이 낮아집니다. 그 대신 앱이 사용하는 데이터 양을 +

    예를 들어 사용자에게 앱의 데이터 동기화 빈도를 제어하도록 허용할 수 있습니다. 앱이 Wi-Fi에 있을 때에만 +업로드/다운로드를 수행하도록 할지 여부, 앱이 로밍 중에 데이터를 사용하도록 할지 여부 등을 이렇게 조절합니다. 사용자가 +이러한 제어 기능을 사용할 수 있게 되면 시스템 설정에서 설정한 한도에 가까워지고 +있을 때 앱의 데이터 액세스를 비활성화할 가능성이 낮아집니다. 그 대신 앱이 사용하는 데이터 양을 정밀하게 제어할 수 있기 때문입니다.

    -

    일단 필요한 기본 설정을 {@link android.preference.PreferenceActivity}에 +

    일단 필요한 기본 설정을 {@link android.preference.PreferenceActivity}에 추가하여 앱의 데이터 습관을 제어하도록 했으면, 다음으로 매니페스트 파일에 있는 {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE}에 대한 인텐트 필터를 추가해야 합니다. 예:

    @@ -920,10 +920,10 @@ android.content.Intent#ACTION_MANAGE_NETWORK_USAGE}에 대한 인텐트 필터 </activity>
    -

    이 인텐트 필터는 이것이 애플리케이션의 데이터 사용량을 제어하는 액티비티라는 -사실을 시스템에 나타내는 역할을 합니다. 따라서, 사용자가 시스템의 설정 앱에서 여러분의 앱이 -얼마나 많은 데이터를 사용하는지 알아볼 때면 애플리케이션 설정 보기 버튼을 사용할 수 있어 -{@link android.preference.PreferenceActivity}를 시작하게 됩니다. 그러면 사용자는 +

    이 인텐트 필터는 이것이 애플리케이션의 데이터 사용량을 제어하는 액티비티라는 +사실을 시스템에 나타내는 역할을 합니다. 따라서, 사용자가 시스템의 설정 앱에서 여러분의 앱이 +얼마나 많은 데이터를 사용하는지 알아볼 때면 애플리케이션 설정 보기 버튼을 사용할 수 있어 +{@link android.preference.PreferenceActivity}를 시작하게 됩니다. 그러면 사용자는 앱이 사용할 데이터 양을 미세하게 조정할 수 있습니다.

    @@ -934,22 +934,22 @@ android.content.Intent#ACTION_MANAGE_NETWORK_USAGE}에 대한 인텐트 필터

    사용자 지정 기본 설정 구축하기

    -

    Android 프레임워크에는 다양한 {@link android.preference.Preference} 하위 클래스가 포함되어 있어 -여러 가지 설정 유형에 맞게 UI를 구축할 수 있습니다. -하지만, 기본 제공 솔루션이 없는 설정이 필요하게 되는 경우도 있습니다. 예를 들어 숫자 선택기 또는 -날짜 선택기 등이 이에 해당됩니다. 그러한 경우에는 사용자 지정 기본 설정을 만들어야 합니다. 이때 +

    Android 프레임워크에는 다양한 {@link android.preference.Preference} 하위 클래스가 포함되어 있어 +여러 가지 설정 유형에 맞게 UI를 구축할 수 있습니다. +하지만, 기본 제공 솔루션이 없는 설정이 필요하게 되는 경우도 있습니다. 예를 들어 숫자 선택기 또는 +날짜 선택기 등이 이에 해당됩니다. 그러한 경우에는 사용자 지정 기본 설정을 만들어야 합니다. 이때 {@link android.preference.Preference} 클래스 또는 다른 하위 클래스 중 하나를 확장하는 방법을 씁니다.

    -

    {@link android.preference.Preference} 클래스를 확장하는 경우, 다음과 같이 +

    {@link android.preference.Preference} 클래스를 확장하는 경우, 다음과 같이 몇 가지 중요한 해야 할 일이 있습니다.

    • 사용자가 설정을 선택하면 나타나는 사용자 인터페이스를 지정합니다.
    • 필요에 따라 설정의 값을 저장합니다.
    • -
    • {@link android.preference.Preference}가 보이게 되면 +
    • {@link android.preference.Preference}가 보이게 되면 이를 현재(또는 기본) 값으로 초기화합니다.
    • 시스템이 요청하는 경우 기본 값을 제공합니다.
    • -
    • {@link android.preference.Preference}가 나름의 UI(예: 대화)를 제공하는 경우, 상태를 +
    • {@link android.preference.Preference}가 나름의 UI(예: 대화)를 제공하는 경우, 상태를 저장하고 복원하여 수명 주기 변경을 처리할 수 있도록 합니다(예: 사용자가 화면을 돌리는 경우).
    @@ -959,27 +959,27 @@ android.content.Intent#ACTION_MANAGE_NETWORK_USAGE}에 대한 인텐트 필터

    사용자 인터페이스 지정하기

    -

    {@link android.preference.Preference} 클래스를 직접 확장하는 경우, -{@link android.preference.Preference#onClick()}을 구현하여 사용자가 -항목을 선택할 때 일어날 동작을 정의해야 합니다. 그러나, 대부분의 사용자 지정 설정은 {@link android.preference.DialogPreference}를 확장하여 +

    {@link android.preference.Preference} 클래스를 직접 확장하는 경우, +{@link android.preference.Preference#onClick()}을 구현하여 사용자가 +항목을 선택할 때 일어날 동작을 정의해야 합니다. 그러나, 대부분의 사용자 지정 설정은 {@link android.preference.DialogPreference}를 확장하여 대화를 표시하도록 합니다. 이렇게 하면 절차가 단순해집니다. {@link android.preference.DialogPreference}를 확장하는 경우에는 클래스 생성자 중에 반드시 {@link -android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()}를 호출하여 +android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()}를 호출하여 대화에 대한 레이아웃을 지정해야 합니다.

    예를 들어 다음은 레이아웃을 선언하는 사용자 지정 {@link -android.preference.DialogPreference}와 기본 +android.preference.DialogPreference}와 기본 긍정적 및 부정적 대화 버튼에 대한 텍스트를 지정하는 생성자입니다.

     public class NumberPickerPreference extends DialogPreference {
         public NumberPickerPreference(Context context, AttributeSet attrs) {
             super(context, attrs);
    -        
    +
             setDialogLayoutResource(R.layout.numberpicker_dialog);
             setPositiveButtonText(android.R.string.ok);
             setNegativeButtonText(android.R.string.cancel);
    -        
    +
             setDialogIcon(null);
         }
         ...
    @@ -992,21 +992,21 @@ public class NumberPickerPreference extends DialogPreference {
     
     

    설정에 대한 값은 언제든 저장할 수 있습니다. {@link android.preference.Preference} 클래스의 {@code persist*()} 메서드 중 하나를 호출하기만 하면 됩니다. 예를 들어 설정의 값이 정수인 경우 {@link -android.preference.Preference#persistInt persistInt()}를, 부울을 저장하려면 +android.preference.Preference#persistInt persistInt()}를, 부울을 저장하려면 {@link android.preference.Preference#persistBoolean persistBoolean()}을 호출하십시오.

    -

    참고: 각각의 {@link android.preference.Preference}는 데이터 유형 하나씩만 -저장할 수 있으므로, 사용자 지정 +

    참고: 각각의 {@link android.preference.Preference}는 데이터 유형 하나씩만 +저장할 수 있으므로, 사용자 지정 {@link android.preference.Preference}에서 사용한 데이터 유형에 적절한 {@code persist*()} 메서드를 사용해야 합니다.

    설정을 유지하기로 선택하는 시점은 확장하는 지점이 {@link android.preference.Preference} 클래스인지에 좌우될 수 있습니다. {@link -android.preference.DialogPreference}를 확장하면 값을 유지하는 것은 대화가 긍정적인 결과로 인해 +android.preference.DialogPreference}를 확장하면 값을 유지하는 것은 대화가 긍정적인 결과로 인해 닫히는 경우만으로 국한해야 합니다(사용자가 "확인(OK)" 버튼을 선택하는 경우).

    {@link android.preference.DialogPreference}가 닫히면 시스템이 {@link -android.preference.DialogPreference#onDialogClosed onDialogClosed()} 메서드를 호출합니다. 이 메서드에는 -부울 인수가 포함되어 있어 사용자의 결과가 "긍정적"인지 아닌지를 나타냅니다. 이 값이 +android.preference.DialogPreference#onDialogClosed onDialogClosed()} 메서드를 호출합니다. 이 메서드에는 +부울 인수가 포함되어 있어 사용자의 결과가 "긍정적"인지 아닌지를 나타냅니다. 이 값이 true인 경우, 사용자가 긍정적 버튼을 선택한 것이고 새 값을 저장해야 합니다. 예:

    @@ -1020,29 +1020,29 @@ protected void onDialogClosed(boolean positiveResult) { }
    -

    이 예시에서 mNewValue는 설정의 현재 값을 보유한 클래스 -구성원입니다. {@link android.preference.Preference#persistInt persistInt()}를 호출하면 -{@link android.content.SharedPreferences} 파일에 대한 값을 저장합니다(이 +

    이 예시에서 mNewValue는 설정의 현재 값을 보유한 클래스 +구성원입니다. {@link android.preference.Preference#persistInt persistInt()}를 호출하면 +{@link android.content.SharedPreferences} 파일에 대한 값을 저장합니다(이 {@link android.preference.Preference}에 대하여 XML 파일에 지정된 키를 자동으로 사용합니다).

    현재 값 초기화하기

    -

    시스템이 {@link android.preference.Preference}를 화면에 추가하는 경우, 이는 -{@link android.preference.Preference#onSetInitialValue onSetInitialValue()}를 호출하여 -설정에 유지된 값이 있는지 없는지를 알립니다. 유지된 값이 없는 경우, 이 호출은 기본 값을 +

    시스템이 {@link android.preference.Preference}를 화면에 추가하는 경우, 이는 +{@link android.preference.Preference#onSetInitialValue onSetInitialValue()}를 호출하여 +설정에 유지된 값이 있는지 없는지를 알립니다. 유지된 값이 없는 경우, 이 호출은 기본 값을 제공합니다.

    -

    {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} 메서드는 -부울 값 restorePersistedValue를 전달하여 해당 설정에 대해 이미 어떤 값이 유지되었는지 -아닌지를 나타냅니다. 만일 이것이 true라면, 유지된 값을 검색하되 +

    {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} 메서드는 +부울 값 restorePersistedValue를 전달하여 해당 설정에 대해 이미 어떤 값이 유지되었는지 +아닌지를 나타냅니다. 만일 이것이 true라면, 유지된 값을 검색하되 {@link android.preference.Preference} 클래스의 {@code getPersisted*()} 메서드 중 하나를 호출하는 방법을 써야 합니다. 예를 들어 정수 값이라면 {@link -android.preference.Preference#getPersistedInt getPersistedInt()}를 사용합니다. 보통은 -유지된 값을 검색하여, UI에 이전에 저장된 값을 반영하여 이를 적절하게 업데이트할 수 +android.preference.Preference#getPersistedInt getPersistedInt()}를 사용합니다. 보통은 +유지된 값을 검색하여, UI에 이전에 저장된 값을 반영하여 이를 적절하게 업데이트할 수 있도록 하는 것이 좋습니다.

    -

    restorePersistedValuefalse인 경우, +

    restorePersistedValuefalse인 경우, 두 번째 인수로 전달된 기본 값을 사용해야 합니다.

    @@ -1059,22 +1059,22 @@ protected void onSetInitialValue(boolean restorePersistedValue, Object defaultVa
     }
     
    -

    각 {@code getPersisted*()} 메서드는 기본 값을 나타내는 인수를 취하여 -사실은 유지된 값이 전혀 없거나 키 자체가 존재하지 않는 경우 사용하도록 합니다. 위의 +

    각 {@code getPersisted*()} 메서드는 기본 값을 나타내는 인수를 취하여 +사실은 유지된 값이 전혀 없거나 키 자체가 존재하지 않는 경우 사용하도록 합니다. 위의 예시에서는 혹시 {@link android.preference.Preference#getPersistedInt getPersistedInt()}가 유지된 값을 반환할 수 없는 경우에 사용하도록 기본 값을 나타내는 데 로컬 상수를 사용하였습니다.

    -

    주의: {@code getPersisted*()} 메서드에서는 -defaultValue를 기본 값으로 사용하면 안 됩니다. 이것의 값은 +

    주의: {@code getPersisted*()} 메서드에서는 +defaultValue를 기본 값으로 사용하면 안 됩니다. 이것의 값은 restorePersistedValuetrue이면 항상 null이기 때문입니다.

    기본 값 제공하기

    {@link android.preference.Preference} 클래스의 인스턴스가 기본 값을 나타내는 경우 -({@code android:defaultValue} 속성으로), 시스템은 +({@code android:defaultValue} 속성으로), 시스템은 값을 검색하기 위해 객체를 인스턴트화할 때 {@link android.preference.Preference#onGetDefaultValue -onGetDefaultValue()}를 호출합니다. 이 메서드를 구현해야 +onGetDefaultValue()}를 호출합니다. 이 메서드를 구현해야 시스템이 {@link android.content.SharedPreferences}에 있는 기본 값을 저장할 수 있습니다. 예:

    @@ -1085,9 +1085,9 @@ protected Object onGetDefaultValue(TypedArray a, int index) { }
    -

    이 메서드 인수가 여러분에게 필요한 모든 것을 제공합니다. 즉 속성 배열과 -{@code android:defaultValue}의 위치로, 이는 반드시 검색해야 합니다. 이 메서드를 -반드시 구현하여 속성에서 기본 값을 추출해야만 하는 이유는 값이 정의되지 않은 경우, 속성에 대한 +

    이 메서드 인수가 여러분에게 필요한 모든 것을 제공합니다. 즉 속성 배열과 +{@code android:defaultValue}의 위치로, 이는 반드시 검색해야 합니다. 이 메서드를 +반드시 구현하여 속성에서 기본 값을 추출해야만 하는 이유는 값이 정의되지 않은 경우, 속성에 대한 로컬 기본 값을 꼭 지정해야 하기 때문입니다.

    @@ -1095,25 +1095,25 @@ protected Object onGetDefaultValue(TypedArray a, int index) {

    기본 설정의 상태 저장 및 복원하기

    레이아웃에서의 {@link android.view.View}와 마찬가지로 {@link android.preference.Preference} -하위 클래스가 액티비티 또는 프래그먼트가 재시작했을 때 -그 상태를 저장하고 복원하는 역할을 맡습니다(예를 들어 사용자가 화면을 돌리는 경우 등). -{@link android.preference.Preference} 클래스의 상태를 적절하게 저장하고 복원하려면, +하위 클래스가 액티비티 또는 프래그먼트가 재시작했을 때 +그 상태를 저장하고 복원하는 역할을 맡습니다(예를 들어 사용자가 화면을 돌리는 경우 등). +{@link android.preference.Preference} 클래스의 상태를 적절하게 저장하고 복원하려면, 수명 주기 콜백 메서드 {@link android.preference.Preference#onSaveInstanceState onSaveInstanceState()} 및 {@link android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}를 구현해야 합니다.

    -

    {@link android.preference.Preference}의 상태를 정의하는 것은 -{@link android.os.Parcelable} 인터페이스를 구현하는 객체입니다. Android 프레임워크는 +

    {@link android.preference.Preference}의 상태를 정의하는 것은 +{@link android.os.Parcelable} 인터페이스를 구현하는 객체입니다. Android 프레임워크는 그러한 객체를 제공하여 상태 객체를 정의하는 데 일종의 시작 지점으로 사용하도록 하고 있습니다. 즉 {@link android.preference.Preference.BaseSavedState} 클래스가 이에 해당됩니다.

    -

    {@link android.preference.Preference} 클래스가 자신의 상태를 저장하는 방법을 정의하려면 -{@link android.preference.Preference.BaseSavedState} 클래스를 확장해야 합니다. 아주 약간의 메서드를 재정의하고 +

    {@link android.preference.Preference} 클래스가 자신의 상태를 저장하는 방법을 정의하려면 +{@link android.preference.Preference.BaseSavedState} 클래스를 확장해야 합니다. 아주 약간의 메서드를 재정의하고 {@link android.preference.Preference.BaseSavedState#CREATOR} 객체를 정의해야 합니다.

    -

    대부분의 앱에서는 다음과 같은 구현을 복사한 다음, -{@code value}를 처리하는 줄만 변경하면 됩니다. 이는 {@link android.preference.Preference} 하위 클래스가 정수보다는 데이터 +

    대부분의 앱에서는 다음과 같은 구현을 복사한 다음, +{@code value}를 처리하는 줄만 변경하면 됩니다. 이는 {@link android.preference.Preference} 하위 클래스가 정수보다는 데이터 유형을 저장하는 경우 해당됩니다.

    @@ -1154,11 +1154,11 @@ private static class SavedState extends BaseSavedState {
     }
     
    -

    위의 {@link android.preference.Preference.BaseSavedState} 구현을 앱에 -추가하고 나면(주로 {@link android.preference.Preference} 하위 클래스의 하위 클래스로), 이제 +

    위의 {@link android.preference.Preference.BaseSavedState} 구현을 앱에 +추가하고 나면(주로 {@link android.preference.Preference} 하위 클래스의 하위 클래스로), 이제 {@link android.preference.Preference#onSaveInstanceState onSaveInstanceState()} 및 {@link -android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} 메서드를 구현해야 합니다. 이것은 +android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} 메서드를 구현해야 합니다. 이것은 {@link android.preference.Preference} 하위 클래스를 위한 것입니다.

    예:

    @@ -1194,7 +1194,7 @@ protected void onRestoreInstanceState(Parcelable state) { // Cast state to custom BaseSavedState and pass to superclass SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); - + // Set this Preference's widget to reflect the restored state mNumberPicker.setValue(myState.value); } diff --git a/docs/html-intl/intl/ko/guide/topics/ui/ui-events.jd b/docs/html-intl/intl/ko/guide/topics/ui/ui-events.jd index b059bd24de48a07c770a94d0c06b579f3ddf4902..427051c8ac24ba6b37a8a543d507c44695ba6315 100644 --- a/docs/html-intl/intl/ko/guide/topics/ui/ui-events.jd +++ b/docs/html-intl/intl/ko/guide/topics/ui/ui-events.jd @@ -16,67 +16,67 @@ parent.link=index.html -

    Android에는 사용자와 애플리케이션의 상호 작용으로부터 이벤트를 가로채는 방법이 여러 가지 있습니다. -사용자 인터페이스 내의 이벤트가 관련된 경우, 이러한 방식은 이벤트를 사용자가 상호 작용하는 +

    Android에는 사용자와 애플리케이션의 상호 작용으로부터 이벤트를 가로채는 방법이 여러 가지 있습니다. +사용자 인터페이스 내의 이벤트가 관련된 경우, 이러한 방식은 이벤트를 사용자가 상호 작용하는 특정 보기 객체로부터 캡처하는 것입니다. 이에 필요한 수단은 보기 클래스가 제공합니다.

    -

    레이아웃을 작성하는 데 사용하게 되는 여러 가지 보기 클래스 안을 보면 UI 이벤트에 유용해 보이는 공개 콜백 -메서드가 여러 개 있는 것이 눈에 띕니다. 이러한 메서드는 해당 객체에서 각각의 작업이 발생할 때 Android 프레임워크가 -호출하는 것입니다. 예를 들어 보기(예: 버튼)를 하나 터치하면 -해당 객체에서 onTouchEvent() 메서드가 호출됩니다. 그러나 이것을 가로채려면 클래스를 확장하고 -메서드를 재정의해야 합니다. 다만 그런 이벤트를 처리하기 위해 모든 보기 객체를 -다 확장하는 것은 타당성이 없습니다. 이 때문에 보기 클래스에 -일련의 중첩된 인터페이스가 있고 거기에 훨씬 쉽게 정의할 수 있는 콜백에 있습니다. 이와 같은 +

    레이아웃을 작성하는 데 사용하게 되는 여러 가지 보기 클래스 안을 보면 UI 이벤트에 유용해 보이는 공개 콜백 +메서드가 여러 개 있는 것이 눈에 띕니다. 이러한 메서드는 해당 객체에서 각각의 작업이 발생할 때 Android 프레임워크가 +호출하는 것입니다. 예를 들어 보기(예: 버튼)를 하나 터치하면 +해당 객체에서 onTouchEvent() 메서드가 호출됩니다. 그러나 이것을 가로채려면 클래스를 확장하고 +메서드를 재정의해야 합니다. 다만 그런 이벤트를 처리하기 위해 모든 보기 객체를 +다 확장하는 것은 타당성이 없습니다. 이 때문에 보기 클래스에 +일련의 중첩된 인터페이스가 있고 거기에 훨씬 쉽게 정의할 수 있는 콜백에 있습니다. 이와 같은 인터페이스를 일명 이벤트 수신기라고 하는데, 이것이 UI와 사용자 상호 작용을 캡처하는 데 아주 적합합니다.

    -

    사용자 상호 작용을 수신 대기하는 데에는 이벤트 수신기를 사용하는 것이 좀 더 보편적이지만, 사용자 지정 -구성 요소를 구축하기 위해 보기 클래스를 확장하고자 하는 상황이 올 수도 있습니다. +

    사용자 상호 작용을 수신 대기하는 데에는 이벤트 수신기를 사용하는 것이 좀 더 보편적이지만, 사용자 지정 +구성 요소를 구축하기 위해 보기 클래스를 확장하고자 하는 상황이 올 수도 있습니다. 어쩌면 {@link android.widget.Button} -클래스를 확장하여 무언가 더 복잡한 것을 만들고자 할 수도 있습니다. 이런 경우, 클래스에 대한 기본 이벤트 행동을 클래스 +클래스를 확장하여 무언가 더 복잡한 것을 만들고자 할 수도 있습니다. 이런 경우, 클래스에 대한 기본 이벤트 행동을 클래스 이벤트 처리기를 사용하여 정의할 수 있습니다.

    이벤트 수신기

    -

    이벤트 수신기란 {@link android.view.View} 클래스 내에 있는 일종의 인터페이스로, 이 안에 하나의 -콜백 메서드가 들어있습니다. 이러한 메서드는 수신기가 등록된 보기가 UI 안의 항목과 사용자의 상호 작용으로 인하여 트리거되었을 때 +

    이벤트 수신기란 {@link android.view.View} 클래스 내에 있는 일종의 인터페이스로, 이 안에 하나의 +콜백 메서드가 들어있습니다. 이러한 메서드는 수신기가 등록된 보기가 UI 안의 항목과 사용자의 상호 작용으로 인하여 트리거되었을 때 Android 프레임워크가 호출하는 것입니다.

    이벤트 수신기 인터페이스에 포함된 콜백 메서드는 다음과 같습니다.

    onClick()
    -
    {@link android.view.View.OnClickListener}에서 온 것입니다. +
    {@link android.view.View.OnClickListener}에서 온 것입니다. 이것이 호출되는 것은 사용자가 항목을 터치하거나 -(터치 모드에 있을 때), 탐색 키 또는 트랙볼을 사용하여 해당 항목에 초점을 맞추고 있으면서 +(터치 모드에 있을 때), 탐색 키 또는 트랙볼을 사용하여 해당 항목에 초점을 맞추고 있으면서 적절한 "엔터" 키를 누르거나 트랙볼을 꾹 누를 때입니다.
    onLongClick()
    -
    {@link android.view.View.OnLongClickListener}에서 온 것입니다. -이것이 호출되는 것은 사용자가 항목을 길게 누르거나(터치 모드에 있을 때), -탐색 키 또는 트랙볼을 사용하여 해당 항목에 초점을 맞추고 있으면서 +
    {@link android.view.View.OnLongClickListener}에서 온 것입니다. +이것이 호출되는 것은 사용자가 항목을 길게 누르거나(터치 모드에 있을 때), +탐색 키 또는 트랙볼을 사용하여 해당 항목에 초점을 맞추고 있으면서 적절한 "엔터" 키를 누르거나 트랙볼을 꾹 누를 때입니다(일 초간).
    onFocusChange()
    -
    {@link android.view.View.OnFocusChangeListener}에서 온 것입니다. +
    {@link android.view.View.OnFocusChangeListener}에서 온 것입니다. 이것이 호출되는 것은 사용자가 탐색 키 또는 트랙볼을 사용하여 항목 쪽으로 이동하거나 항목에서 멀어질 때입니다.
    onKey()
    -
    {@link android.view.View.OnKeyListener}에서 온 것입니다. +
    {@link android.view.View.OnKeyListener}에서 온 것입니다. 이것이 호출되는 것은 사용자가 항목에 초점을 맞추고 있으면서 기기에 있는 하드웨어 키를 누르거나 키에서 손을 떼는 경우입니다.
    onTouch()
    -
    {@link android.view.View.OnTouchListener}에서 온 것입니다. -이것이 호출되는 것은 사용자가 터치 이벤트로서의 자격을 만족하는 작업을 수행하는 경우로, 여기에 +
    {@link android.view.View.OnTouchListener}에서 온 것입니다. +이것이 호출되는 것은 사용자가 터치 이벤트로서의 자격을 만족하는 작업을 수행하는 경우로, 여기에 누르기, 손 떼기와 화면에서 이루어지는 모든 움직임 동작(항목의 경계 내에서)이 포함됩니다.
    onCreateContextMenu()
    -
    {@link android.view.View.OnCreateContextMenuListener}에서 온 것입니다. -이것을 호출하는 것은 컨텍스트 메뉴가 구축되는 중일 때입니다(정체된 "롱 클릭"의 결과로). +
    {@link android.view.View.OnCreateContextMenuListener}에서 온 것입니다. +이것을 호출하는 것은 컨텍스트 메뉴가 구축되는 중일 때입니다(정체된 "롱 클릭"의 결과로). 메뉴 개발자 가이드에 있는 컨텍스트 메뉴 관련 논의를 참조하십시오.
    -

    이러한 메서드는 각자의 인터페이스 안에 거주하는 유일한 주민입니다. 이러한 메서드 중 하나를 -정의하고 이벤트를 처리하려면 액티비티 내의 중첩된 인터페이스를 구현하거나 익명의 클래스로 정의하면 됩니다. -그런 다음 구현의 인스턴스 하나를 -각각의 View.set...Listener() 메서드에 전달하십시오 (예: -{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}를 +

    이러한 메서드는 각자의 인터페이스 안에 거주하는 유일한 주민입니다. 이러한 메서드 중 하나를 +정의하고 이벤트를 처리하려면 액티비티 내의 중첩된 인터페이스를 구현하거나 익명의 클래스로 정의하면 됩니다. +그런 다음 구현의 인스턴스 하나를 +각각의 View.set...Listener() 메서드에 전달하십시오 (예: +{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}를 호출한 다음 이를 {@link android.view.View.OnClickListener OnClickListener}의 구현에 전달합니다).

    아래의 예시는 버튼에 대하여 온-클릭 수신기를 등록하는 방법을 나타낸 것입니다.

    @@ -117,57 +117,57 @@ public class ExampleActivity extends Activity implements OnClickListener { }
    -

    위의 예시에서 onClick() 콜백에는 -반환 값이 없지만 다른 이벤트 수신기 메서드 중에는 부울 값을 반환해야만 하는 것도 있다는 점을 유의하십시오. 그 이유는 이벤트에 따라 +

    위의 예시에서 onClick() 콜백에는 +반환 값이 없지만 다른 이벤트 수신기 메서드 중에는 부울 값을 반환해야만 하는 것도 있다는 점을 유의하십시오. 그 이유는 이벤트에 따라 다릅니다. 이런 필수 사항이 적용되는 몇몇 메서드의 경우, 이유는 다음과 같습니다.

      -
    • {@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()} - -이것은 부울 값을 반환하여 이벤트를 완전히 사용하였으며 더 이상 이를 담지 않아도 되는지 여부를 나타냅니다. -다시 말해, 을 반환하면 이벤트를 처리했으며 여기에서 중단해야 한다는 것을 의미하며 -거짓을 반환하면 이벤트가 아직 미처리 상태이며/거나 이 이벤트를 다른 +
    • {@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()} - +이것은 부울 값을 반환하여 이벤트를 완전히 사용하였으며 더 이상 이를 담지 않아도 되는지 여부를 나타냅니다. +다시 말해, 을 반환하면 이벤트를 처리했으며 여기에서 중단해야 한다는 것을 의미하며 +거짓을 반환하면 이벤트가 아직 미처리 상태이며/거나 이 이벤트를 다른 온-클릭 수신기로 계속 진행해야 할지 나타내는 것입니다.
    • -
    • {@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()} - +
    • {@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()} - 이것은 부울 값을 반환하여 이벤트를 완전히 사용하였으며 더 이상 이를 담지 않아도 되는지 여부를 나타냅니다. - 다시 말해, 을 반환하면 이벤트를 처리했으며 여기에서 중단해야 한다는 것을 의미하며 -거짓을 반환하면 이벤트가 아직 미처리 상태이며/거나 이 이벤트를 다른 + 다시 말해, 을 반환하면 이벤트를 처리했으며 여기에서 중단해야 한다는 것을 의미하며 +거짓을 반환하면 이벤트가 아직 미처리 상태이며/거나 이 이벤트를 다른 온-키 수신기로 계속 진행해야 할지 나타내는 것입니다.
    • -
    • {@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()} - -이것은 부울 값을 반환하여 수신기가 이 이벤트를 사용하는지 아닌지를 나타냅니다. 여기서 중요한 점은 -이 이벤트에는 서로 연달아 발생하는 여러 개의 작업이 있을 수 있다는 것입니다. 그러므로 '아래로' 작업 이벤트를 수신했을 때 거짓을 반환하면, -해당 이벤트를 사용하지 않았으며 이 이벤트로부터 이어지는 이후의 작업에 -흥미가 없음을 나타내는 것이 됩니다. 따라서 이 이벤트 내의 다른 모든 작업에 대해 +
    • {@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()} - +이것은 부울 값을 반환하여 수신기가 이 이벤트를 사용하는지 아닌지를 나타냅니다. 여기서 중요한 점은 +이 이벤트에는 서로 연달아 발생하는 여러 개의 작업이 있을 수 있다는 것입니다. 그러므로 '아래로' 작업 이벤트를 수신했을 때 거짓을 반환하면, +해당 이벤트를 사용하지 않았으며 이 이벤트로부터 이어지는 이후의 작업에 +흥미가 없음을 나타내는 것이 됩니다. 따라서 이 이벤트 내의 다른 모든 작업에 대해 호출되지 않습니다(예: 손가락 동작 또는 최종적인 '위로' 작업 이벤트 등).
    -

    하드웨어 키 이벤트는 항상 현재 초점의 중심에 있는 보기로 전달된다는 점을 명심하십시오. 이들은 보기 계층의 맨 위에서 시작하여 -아래 방향으로 발송되어 적절한 목적지에 도달할 때까지 계속합니다. 보기(또는 보기의 하위)에 +

    하드웨어 키 이벤트는 항상 현재 초점의 중심에 있는 보기로 전달된다는 점을 명심하십시오. 이들은 보기 계층의 맨 위에서 시작하여 +아래 방향으로 발송되어 적절한 목적지에 도달할 때까지 계속합니다. 보기(또는 보기의 하위)에 현재 초점이 맞춰져 있으면, 이벤트가 {@link android.view.View#dispatchKeyEvent(KeyEvent) -dispatchKeyEvent()} 메서드를 통과하여 이동하는 것을 확인할 수 있습니다. 보기를 통해 키 이벤트를 캡처하는 대신, 액티비티 내부의 모든 이벤트를 {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}및 +dispatchKeyEvent()} 메서드를 통과하여 이동하는 것을 확인할 수 있습니다. 보기를 통해 키 이벤트를 캡처하는 대신, 액티비티 내부의 모든 이벤트를 {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}을 사용하여 수신할 수도 있습니다.

    -

    또한, 애플리케이션에 대한 텍스트 입력의 경우 대다수의 기기에는 소프트웨어 입력 메서드만 있다는 사실을 -명심하십시오. 그러한 메서드는 반드시 키 기반이 아니어도 됩니다. 음성 입력, 손글씨 등을 사용하는 것도 있습니다. 입력 -메서드가 키보드 같은 인터페이스를 표시하더라도 일반적으로 -{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()} 이벤트군을 트리거하지는 않습니다. 특정 키 누름을 -제어해야만 하는 UI는 절대 구축하면 안 됩니다. 이렇게 하면 애플리케이션이 하드웨어 키보드가 있는 -기기에만 한정됩니다. 특히, 사용자가 리턴 키를 누르면 입력의 유효성을 검사하는 데 이와 같은 메서드에 -의존해서는 안 됩니다. 대신, {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}과 같은 작업을 사용하여 애플리케이션이 반응할 것으로 기대되는 방식에 해당되는 -입력 메서드를 신호하여 의미 있는 방식으로 UI를 변경할 수 있게 하는 것이 좋습니다. 소프트웨어 입력 메서드가 +

    또한, 애플리케이션에 대한 텍스트 입력의 경우 대다수의 기기에는 소프트웨어 입력 메서드만 있다는 사실을 +명심하십시오. 그러한 메서드는 반드시 키 기반이 아니어도 됩니다. 음성 입력, 손글씨 등을 사용하는 것도 있습니다. 입력 +메서드가 키보드 같은 인터페이스를 표시하더라도 일반적으로 +{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()} 이벤트군을 트리거하지는 않습니다. 특정 키 누름을 +제어해야만 하는 UI는 절대 구축하면 안 됩니다. 이렇게 하면 애플리케이션이 하드웨어 키보드가 있는 +기기에만 한정됩니다. 특히, 사용자가 리턴 키를 누르면 입력의 유효성을 검사하는 데 이와 같은 메서드에 +의존해서는 안 됩니다. 대신, {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}과 같은 작업을 사용하여 애플리케이션이 반응할 것으로 기대되는 방식에 해당되는 +입력 메서드를 신호하여 의미 있는 방식으로 UI를 변경할 수 있게 하는 것이 좋습니다. 소프트웨어 입력 메서드가 어떻게 작동할지 임의로 추정하지 마시고, 이미 서식 지정된 텍스트를 애플리케이션에 제공해줄 것이라 믿으면 됩니다.

    -

    참고: Androids는 우선 이벤트 처리기부터 호출하고, 그 다음에 클래스 정의로부터 가져온 -적절한 기본 처리기를 두 번째로 호출합니다. 따라서, 이와 같은 이벤트 수신기에서 을 반환하면 이벤트가 -다른 이벤트 수신기로 전파되는 것을 중지시킬 뿐만 아니라 보기에 있는 +

    참고: Androids는 우선 이벤트 처리기부터 호출하고, 그 다음에 클래스 정의로부터 가져온 +적절한 기본 처리기를 두 번째로 호출합니다. 따라서, 이와 같은 이벤트 수신기에서 을 반환하면 이벤트가 +다른 이벤트 수신기로 전파되는 것을 중지시킬 뿐만 아니라 보기에 있는 기본 이벤트 처리기로의 콜백도 차단하게 됩니다. 따라서 을 반환하는 경우 해당 이벤트를 종료하고 싶은 것인지 확신해야 합니다.

    이벤트 처리기

    -

    보기에서 사용자 지정 구성 요소를 구축하는 경우, 기본 이벤트 처리기로 사용될 콜백 메서드를 +

    보기에서 사용자 지정 구성 요소를 구축하는 경우, 기본 이벤트 처리기로 사용될 콜백 메서드를 여러 개 정의할 수 있게 됩니다. 사용자 지정 -구성 요소에 대한 문서를 보면 이벤트 처리에 사용되는 몇 가지 보편적인 콜백을 확인할 수 있습니다. +구성 요소에 대한 문서를 보면 이벤트 처리에 사용되는 몇 가지 보편적인 콜백을 확인할 수 있습니다. 다음은 그 몇 가지 예입니다.

    • {@link android.view.View#onKeyDown} - 새로운 키 이벤트가 발생하면 호출합니다.
    • @@ -176,68 +176,68 @@ dispatchKeyEvent()} 메서드를 통과하여 이동하는 것을 확인
    • {@link android.view.View#onTouchEvent} - 터치 스크린 동작 이벤트가 발생하면 호출합니다.
    • {@link android.view.View#onFocusChanged} - 보기가 초점을 취하거나 이를 잃으면 호출합니다.
    -

    개발자 여러분이 알아두어야 하는 다른 메서드가 몇 가지 더 있습니다. 이들은 보기 클래스의 일부분이 아니지만, -이벤트를 처리할 수 있는 방식에 직접적으로 영향을 미칠 수 있는 것들입니다. 그러니, 레이아웃 안에서 좀 더 복잡한 이벤트를 관리하는 경우, +

    개발자 여러분이 알아두어야 하는 다른 메서드가 몇 가지 더 있습니다. 이들은 보기 클래스의 일부분이 아니지만, +이벤트를 처리할 수 있는 방식에 직접적으로 영향을 미칠 수 있는 것들입니다. 그러니, 레이아웃 안에서 좀 더 복잡한 이벤트를 관리하는 경우, 이와 같은 다른 메서드도 고려하십시오.

    • {@link android.app.Activity#dispatchTouchEvent(MotionEvent) - Activity.dispatchTouchEvent(MotionEvent)} - 이것을 사용하면 {@link + Activity.dispatchTouchEvent(MotionEvent)} - 이것을 사용하면 {@link android.app.Activity}로 하여금 모든 터치 이벤트가 창으로 발송되기 전에 이들을 가로채도록 할 수 있습니다.
    • {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent) ViewGroup.onInterceptTouchEvent(MotionEvent)} - 이것을 사용하면 {@link android.view.ViewGroup}으로 하여금 이벤트가 하위 보기로 발송되는 것을 지켜보도록 할 수 있습니다.
    • {@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) - ViewParent.requestDisallowInterceptTouchEvent(boolean)} - 이것을 -호출하는 것은 상위 보기에 {@link + ViewParent.requestDisallowInterceptTouchEvent(boolean)} - 이것을 +호출하는 것은 상위 보기에 {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}가 있는 터치 이벤트를 가로채면 안 된다고 나타낼 때입니다.

    터치 모드

    -사용자가 방향 키 또는 트랙볼을 사용하여 사용자 인터페이스를 탐색하고 있는 경우, -조치 가능한 항목(예: 버튼)에 초점을 맞춰 어느 것이 입력을 허용할지 사용자가 -볼 수 있도록 해야 합니다. 하지만 기기에 터치 기능이 있고 사용자가 -인터페이스를 터치하여 인터페이스와의 상호 작용을 시작하는 경우라면, 더 이상 항목을 강조 표시하거나 -특정 보기에 초점을 맞추지 않아도 됩니다. 따라서 "터치 모드"라고 불리는 상호 작용에 대한 -모드가 따로 있습니다. +사용자가 방향 키 또는 트랙볼을 사용하여 사용자 인터페이스를 탐색하고 있는 경우, +조치 가능한 항목(예: 버튼)에 초점을 맞춰 어느 것이 입력을 허용할지 사용자가 +볼 수 있도록 해야 합니다. 하지만 기기에 터치 기능이 있고 사용자가 +인터페이스를 터치하여 인터페이스와의 상호 작용을 시작하는 경우라면, 더 이상 항목을 강조 표시하거나 +특정 보기에 초점을 맞추지 않아도 됩니다. 따라서 "터치 모드"라고 불리는 상호 작용에 대한 +모드가 따로 있습니다.

    -터치 기능이 있는 기기의 경우, 사용자가 화면을 터치하면 기기가 터치 모드에 -진입하게 됩니다. 이 시점부터는 -{@link android.view.View#isFocusableInTouchMode}가 참인 보기에만 초점을 맞출 수 있습니다. 예를 들어 텍스트 편집 위젯이 이에 해당됩니다. -버튼처럼 터치할 수 있는 다른 보기의 경우 터치해도 주의를 끌 수 없으며 이를 누르면 그저 +터치 기능이 있는 기기의 경우, 사용자가 화면을 터치하면 기기가 터치 모드에 +진입하게 됩니다. 이 시점부터는 +{@link android.view.View#isFocusableInTouchMode}가 참인 보기에만 초점을 맞출 수 있습니다. 예를 들어 텍스트 편집 위젯이 이에 해당됩니다. +버튼처럼 터치할 수 있는 다른 보기의 경우 터치해도 주의를 끌 수 없으며 이를 누르면 그저 온-클릭 수신기를 실행시키기만 합니다.

    -사용자가 방향 키를 누르거나 트랙볼로 스크롤 동작을 할 때마다 기기가 -터치 모드를 종료하고 초점을 맞출 보기를 찾습니다. 이제 사용자는 사용자 인터페이스와 +사용자가 방향 키를 누르거나 트랙볼로 스크롤 동작을 할 때마다 기기가 +터치 모드를 종료하고 초점을 맞출 보기를 찾습니다. 이제 사용자는 사용자 인터페이스와 상호 작용을 재개해도 되며, 화면을 터치하지 않아도 됩니다.

    -터치 모드 상태는 시스템 전체를 통틀어 유지됩니다(모든 창과 액티비티 포함). -현재 상태를 쿼리하려면 +터치 모드 상태는 시스템 전체를 통틀어 유지됩니다(모든 창과 액티비티 포함). +현재 상태를 쿼리하려면 {@link android.view.View#isInTouchMode}를 호출하여 기기가 현재 터치 모드에 있는지 확인하면 됩니다.

    초점 처리하기

    -

    프레임워크가 사용자 입력에 응답하여 일상적인 초점 이동을 처리합니다. -여기에는 보기가 제거되거나 숨겨지는 것, 또는 새 보기를 사용할 수 있게 됨에 따라 -초점을 변경하는 것이 포함됩니다. 보기는 초점을 취하고자 하는 의향을 -{@link android.view.View#isFocusable()} 메서드를 통해 나타냅니다. 보기가 초점을 취할 수 있는지 여부를 변경하려면 -{@link android.view.View#setFocusable(boolean) setFocusable()}을 호출합니다. 터치 모드에 있는 경우, -어느 보기가 {@link android.view.View#isFocusableInTouchMode()}로 초점을 취하는 것을 허용하는지 여부를 쿼리할 수 있습니다. +

    프레임워크가 사용자 입력에 응답하여 일상적인 초점 이동을 처리합니다. +여기에는 보기가 제거되거나 숨겨지는 것, 또는 새 보기를 사용할 수 있게 됨에 따라 +초점을 변경하는 것이 포함됩니다. 보기는 초점을 취하고자 하는 의향을 +{@link android.view.View#isFocusable()} 메서드를 통해 나타냅니다. 보기가 초점을 취할 수 있는지 여부를 변경하려면 +{@link android.view.View#setFocusable(boolean) setFocusable()}을 호출합니다. 터치 모드에 있는 경우, +어느 보기가 {@link android.view.View#isFocusableInTouchMode()}로 초점을 취하는 것을 허용하는지 여부를 쿼리할 수 있습니다. 이것은 {@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}로 변경하면 됩니다.

    -

    초점 이동은 주어진 방향에서 가장 가까운 이웃을 찾아내는 알고리즘을 기반으로 -합니다. 드문 일이지만 기본 알고리즘이 개발자가 의도한 행동과 일치하지 않는 -경우도 있습니다. 이러한 상황이라면, 레이아웃 파일에서 다음과 같은 XML 속성을 +

    초점 이동은 주어진 방향에서 가장 가까운 이웃을 찾아내는 알고리즘을 기반으로 +합니다. 드문 일이지만 기본 알고리즘이 개발자가 의도한 행동과 일치하지 않는 +경우도 있습니다. 이러한 상황이라면, 레이아웃 파일에서 다음과 같은 XML 속성을 사용하여 명시적 재정의를 제공하면 됩니다. nextFocusDown, nextFocusLeft, nextFocusRight, 및 -nextFocusUp입니다. 이와 같은 속성 중 한 가지를 초점이 떠나고 있는 보기에 -추가합니다. 속성의 값을 초점을 +nextFocusUp입니다. 이와 같은 속성 중 한 가지를 초점이 떠나고 있는 보기에 +추가합니다. 속성의 값을 초점을 맞춰야 할 보기의 ID가 되도록 정의합니다. 예:

     <LinearLayout
    @@ -252,18 +252,18 @@ dispatchKeyEvent()} 메서드를 통과하여 이동하는 것을 확인
     </LinearLayout>
     
    -

    보통은 이런 수직 레이아웃에서 첫 버튼부터 위로 이동하면 아무 데도 갈 수 없고, -두 번째 버튼에서 아래로 이동해도 마찬가지입니다. 이제 맨 위 버튼이 맨 아래 버튼을 다음과 같이 -정의했습니다. nextFocusUp (반대쪽도 마찬가지) 따라서 이동 초점은 위에서 아래로 갔다가 +

    보통은 이런 수직 레이아웃에서 첫 버튼부터 위로 이동하면 아무 데도 갈 수 없고, +두 번째 버튼에서 아래로 이동해도 마찬가지입니다. 이제 맨 위 버튼이 맨 아래 버튼을 다음과 같이 +정의했습니다. nextFocusUp (반대쪽도 마찬가지) 따라서 이동 초점은 위에서 아래로 갔다가 아래에서 위로 순환하게 됩니다.

    -

    보기를 UI에서 초점을 맞출 수 있는 것으로 선언하고자 하는 경우(일반적으로는 그렇지 않음), -보기에 레이아웃 선언에서 android:focusable XML 속성을 추가합니다. -이 값을 으로 설정합니다. 터치 모드에 있을 때에도 보기를 초점을 맞출 수 있는 것으로 +

    보기를 UI에서 초점을 맞출 수 있는 것으로 선언하고자 하는 경우(일반적으로는 그렇지 않음), +보기에 레이아웃 선언에서 android:focusable XML 속성을 추가합니다. +이 값을 으로 설정합니다. 터치 모드에 있을 때에도 보기를 초점을 맞출 수 있는 것으로 선언할 수 있습니다. android:focusableInTouchMode를 사용하면 됩니다.

    특정 보기에 초점을 맞추기를 요청하려면, {@link android.view.View#requestFocus()}를 호출하십시오.

    -

    초점 이벤트를 수신 대기하려면(어떤 보기에 초점이 맞춰지거나 이를 잃는 경우 알림을 받으려면), -{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}를 사용하면 됩니다. +

    초점 이벤트를 수신 대기하려면(어떤 보기에 초점이 맞춰지거나 이를 잃는 경우 알림을 받으려면), +{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}를 사용하면 됩니다. 이는 위의 이벤트 수신기 섹션에서 이야기한 바와 같습니다.

    @@ -282,7 +282,7 @@ dispatchKeyEvent()} 메서드를 통과하여 이동하는 것을 확인 the framework will take care of measuring, laying out, and drawing the tree as appropriate. - +

    Note: 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 diff --git a/docs/html-intl/intl/ko/index.jd b/docs/html-intl/intl/ko/index.jd index 01c85873c6c6497d88225d6744e0c5dd6f6bc671..b459df7a6694a87e1629f713ed5a043387647cb0 100644 --- a/docs/html-intl/intl/ko/index.jd +++ b/docs/html-intl/intl/ko/index.jd @@ -5,49 +5,36 @@ page.customHeadTag= - -

    -
    -
    - -

    Android N Developer Preview

    -

    - Get ready for the next version of Android! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. +

    +
    -
    무선 버튼 확인란과 비슷하지만, 예외가 있다면 그룹 내에서 하나만 선택할 수 있다는 점입니다.{@link android.widget.RadioGroup RadioGroup} + {@link android.widget.RadioGroup RadioGroup}
    {@link android.widget.RadioButton RadioButton}
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    기기다운로드/체크섬
    Nexus 5X
    "bullhead"
    bullhead-ota-npd35k-b8cfbd80.zip
    - MD5: 15fe2eba9b01737374196bdf0a792fe9
    - SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283 -
    Nexus 6
    "shamu"
    shamu-ota-npd35k-078e6fa5.zip
    - MD5: e8b12f7721c53af9a450f7058928a5fc
    - SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a -
    Nexus 6P
    "angler"
    angler-ota-npd35k-88457699.zip
    - MD5: 3fac09fef759dde26e57cb80b20b6477
    - SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c -
    Nexus 9
    "volantis"
    volantis-ota-npd35k-51dbae76.zip
    - MD5: 58312c4a5971818ef5c77a3f446003da
    - SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921 -
    Nexus 9G
    "volantisg"
    volantisg-ota-npd35k-834f047f.zip
    - MD5: 92b7d1fa252f7394e70f957c72d4aac8
    - SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361 -
    Nexus Player
    "fugu"
    fugu-ota-npd35k-6ac91298.zip
    - MD5: 1461622ad53ea842b2722fa7b49b8172
    - SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931 -
    Pixel C
    "ryu"
    ryu-ota-npd35k-a0b2347f.zip
    - MD5: c60117f3640cc6db12386fd632289c7d
    - SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3 -
    General Mobile 4G(Android One)
    "seed"
    seed_l8150-ota-npd35k-09897a1d.zip
    - MD5: a55cf94f7cce0393ec6c0b35041766b7
    - SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a -
    - - - - - - - - - diff --git a/docs/html-intl/intl/ko/preview/download.jd b/docs/html-intl/intl/ko/preview/download.jd deleted file mode 100644 index 802420b85aaae66601855dcc424ce08ea4fc8abd..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/download.jd +++ /dev/null @@ -1,543 +0,0 @@ -page.title=기기에서 테스트 -meta.tags="preview", "nexus","system image" -page.tags="preview", "androidn" -page.image=images/cards/card-n-downloads_2x.png - -@jd:body - -
    - - - - -
    - - - -

    - 새로운 플랫폼에서 앱을 실행하고 테스트하려면 Android N -런타임 환경을 설정해야 합니다. 다음 두 가지 방법 중 하나를 사용할 수 있습니다. -

    - -
      -
    • 지원되는 하드웨어 기기에서 Android N 설치
    • -
    • Android N이 실행되는 Android 에뮬레이터 설정
    • -
    - -

    - 새로운 플랫폼에서 앱에 대한 기본적인 호환성 테스트를 수행할 환경이 필요한 경우, -최신 APK와 하드웨어 기기 또는 -에뮬레이터만 있으면 됩니다. 기본 테스트를 위해 전체 개발 환경을 -업데이트할 필요가 없습니다. -

    - -

    - Android N을 대상으로 하도록 앱을 수정하거나 새로운 Android N API를 사용하고 싶다면, -Android N을 지원하도록 -업데이트된 개발 환경을 설정해야 합니다. 자세한 내용은 Android N용 개발 -설정을 참조하세요. -

    - - -

    하드웨어 기기 설정

    - -

    - N Developer Preview는 전화에서 태블릿, TV에 이르기까지 앱을 테스트하는 데 사용할 수 있는 -다양한 하드웨어 기기의 시스템 업데이트를 제공합니다. -

    - -

    - 지원되는 기기에 액세스할 수 있다면, 다음 방법 중 하나를 사용하여 Developer Preview 마일스톤 빌드로 -업데이트할 수 있습니다. -

    - -
      -
    • Android 베타 프로그램을 통해 -자동 OTA 시스템 업데이트에 기기를 등록합니다. 기기를 등록하면 N Developer Preview에서 -모든 마일스톤 빌드에 대해 정기적으로 OTA 업데이트를 받을 수 있습니다. 다양한 N Developer Preview 릴리스를 통해 현재 -환경을 매끄럽게 전환할 수 있으므로 -이 방법을 권장합니다.
    • -
    • Developer Preview 시스템 이미지를 다운로드하고 기기를 플래시합니다. - 수동으로 플래시하는 기기에는 OTA 업데이트가 자동으로 제공되지 않지만, -Android 베타 프로그램에 기기를 등록하면 OTA 업데이트를 받을 수 있습니다.
    • -
    - -

    자동 OTA 업데이트에 기기 등록

    - -

    - 지원되는 기기에 액세스할 수 있다면(아래 다운로드 표 -참조), -해당 기기를 Android 베타 프로그램에 등록해서 Android 프리뷰 버전에 대해 OTA 업데이트를 받을 수 있습니다. 이 업데이트는 -자동으로 다운로드되고 공식 시스템 업데이트처럼 -기기를 업데이트합니다. -

    - -

    - 언제든 기기의 등록을 해제할 수 있습니다. 기기는 -해당 기기에 사용 가능한 가장 최신의 Android 프로덕션 버전에 대한 OTA 업데이트를 받게 됩니다(예: Android 6.0 Marshmallow). - 업데이트 시 기기가 완전히 초기화되므로 -기기의 사용자 데이터는 삭제됩니다. 따라서 기기 등록을 해제하기 전에 반드시 중요한 -데이터를 백업해야 합니다. -

    - -

    - 자세한 정보를 확인하고 기기를 등록하려면 -Android 베타 프로그램 웹사이트를 참조하세요. -

    - -

    참고: - 등록을 해제하면 기기가 완전히 초기화됩니다. 중요한 데이터를 -먼저 백업하세요. -

    - -

    수동 기기 플래시

    - -

    - 언제든 최신 Developer Preview 시스템 이미지를 다운로드하고 -기기에 수동으로 플래시할 수 있습니다. 아래 표를 참조하여 기기 테스트용 시스템 이미지를 -다운로드하세요. 기기 수동 플래시는 -테스트 환경을 정확히 제어해야 하거나 자동 테스트 등을 위해 자주 재설치해야 하는 경우 -유용합니다. -

    - -

    - 기기에 시스템 이미지를 설치하면 기기에서 모든 데이터가 -삭제되므로 데이터를 먼저 백업하는 것이 좋습니다. -

    - -

    - 기기 데이터를 백업하고 아래에서 기기에 맞는 시스템 이미지를 다운로드한 뒤, -developers.google.com/android의 -지침에 따라 기기에 이미지를 플래시합니다. -

    - -

    - 수동으로 플래시한 시스템 이미지는 최신 -Developer Preview 마일스톤 빌드에 대한 OTA 업데이트를 자동으로 -수신하지는 않습니다. 각 Developer Preview 마일스톤에서 환경을 최신으로 유지하고 새 시스템 이미지를 -플래시하세요. -

    - -

    - 기기를 수동으로 플래시한 후 OTA 업데이트를 받으시려면 -Android -베타 프로그램에 기기를 등록하기만 하면 됩니다. 언제든 기기를 등록하고 다음 Preview -업데이트를 무선으로 받을 수 있습니다. -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    기기다운로드/체크섬
    Nexus 5X
    "bullhead"
    bullhead-npd35k-factory-5ba40535.tgz
    - MD5: b6c5d79a21815ee21db41822dcf61e9f
    - SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c -
    Nexus 6
    "shamu"
    shamu-npd35k-factory-a33bf20c.tgz
    - MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab
    - SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c -
    Nexus 6P
    "angler"
    angler-npd35k-factory-81c341d5.tgz
    - MD5: e93de7949433339856124c3729c15ebb
    - SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd -
    Nexus 9
    "volantis"
    volantis-npd35k-factory-2b50e19d.tgz
    - MD5: 565be87ebb2d5937e2abe1a42645864b
    - SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1 -
    Nexus 9G
    "volantisg"
    volantisg-npd35k-factory-2e89ebe6.tgz
    - MD5: a8464e15c6683fe2afa378a63e205fda
    - SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678 -
    Nexus Player
    "fugu"
    fugu-npd35k-factory-1de74874.tgz
    - MD5: c0dbb7db671f61b2785da5001cedefcb
    - SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873 -
    Pixel C
    "ryu"
    ryu-npd35k-factory-b4eed85d.tgz
    - MD5: bdcb6f770e753668b5fadff2a6678e0d
    - SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2 -
    General Mobile 4G(Android One)
    "seed"
    seed_l8150-npd35k-factory-5ab1212b.tgz
    - MD5: 7d34a9774fdd6e025d485ce6cfc23c4c
    - SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5 -
    Sony Xperia Z3
    (D6603 및 D6653)
    다운로드: Xperia Companion
    - 자세한 내용은 Xperia Z3용 Android N Developer Preview 체험을 참조하세요. -
    - -

    기기에서 Preview 제거

    - -

    - 기기에서 Preview를 제거하려면 -다음 중 한 가지 방법을 사용할 수 있습니다.

    -
      -
    • 공장 사양 시스템 이미지를 획득한 다음 기기에 수동으로 -플래시합니다. -
        -
      • Nexus 기기와 Pixel C 기기의 경우, -Nexus 기기용 -공장 이미지 페이지에서 다운로드하세요.
      • -
      • 다른 기기의 경우, 기기 제조업체에 직접 -문의하세요. 또는, Android 베타 프로그램에서 지원되는 -기기라면 -이 프로그램에 기기를 등록한 다음 등록을 해제할 수 있습니다(아래 참조).
      • -
      -
    • -
    • Android 베타 프로그램에서 기기 등록을 해제합니다. 기기가 -Android 베타 -프로그램에 등록되었다면 기기와 관계없이 프로그램에서 기기를 해제하기만 하면 됩니다. -

      - 기기는 해당 기기에 사용 가능한 가장 최신의 Android 프로덕션 버전에 -대한 OTA 업데이트를 받게 됩니다(예: Android 6.0 Marshmallow). - 업데이트 시 기기가 완전히 초기화되므로 기기의 사용자 데이터는 -삭제됩니다. 따라서 기기 등록을 해제하기 전에 반드시 중요한 데이터를 -백업해야 합니다. -

      -
    • -
    - -

    참고: - 프로그램이 끝나기 전에 Developer Preview 시스템 이미지를 제거하는 경우, -기기를 완전히 초기화해야 하고 기기에서 모든 사용자 데이터를 -삭제해야 합니다. -

    - - -

    에뮬레이터 설정

    - -

    Android 에뮬레이터를 사용하여 Android N Preview를 실행하려면 -Android N Preview SDK를 다운로드하고 에뮬레이터용 가상 기기를 -생성해야 합니다.

    - -

    먼저 다음과 같이 Android N Preview SDK를 다운로드합니다. Android -N용 개발 설정 -시 이미 다운로드했다면 이 부분은 건너뛸 수 있습니다. - -

      -
    1. Android Studio에서 Settings 대화 상자를 -엽니다(Windows/Linux의 경우 File > Settings, Mac의 경우 -Android Studio > Preferences). 왼쪽 창에서 -Appearance & Behavior > -System Settings > Android SDK를 선택합니다. - -
    2. SDK Platforms 탭을 클릭한 다음, -Android N Preview 체크박스를 선택합니다.
    3. - -
    4. SDK Tools 탭을 클릭한 다음, -Android SDK Build Tools, Android SDK -Platform-Tools, Android SDK Tools 체크박스를 -선택합니다. -
    5. - -
    6. OK를 클릭하고 설치할 패키지의 -사용권 계약에 동의합니다. -
    7. -
    - -

    이제 Android SDK Built-Tools 24.0 0 rc1, -Platform-Tools 24.0.0 rc1SDK Tools -25.0.9를 다운로드했습니다. SDK 도구를 25.0.9로 업데이트하지 않으면 -Android N에서 x86_64 시스템 이미지를 실행할 수 없습니다.

    - - -

    이제 Android N 시스템 이미지로 가상 기기를 생성합니다.

    - -
      -
    1. Tools > Android > -AVD Manager를 선택하여 AVD Manager를 엽니다.
    2. -
    3. Create Virtual Device를 클릭합니다.
    4. -
    5. Nexus 5X, Nexus 6P, Nexus 9, Android TV 등의 기기를 선택하고 -Next를 클릭합니다.
    6. -
    7. N 시스템 이미지(x86 -ABI)를 선택하고 Next를 클릭합니다. - (현재는 x86 시스템 이미지만 Android N Preview용 Android 에뮬레이터에서 -지원됩니다.) -
    8. 나머지 AVD 구성을 완료하고 -Finish를 클릭합니다.
    9. -
    - -

    이제 Android N Preview AVD에서 Android 에뮬레이터를 시작할 수 있습니다.

    - -

    -Android 에뮬레이터에서 최상의 경험을 얻으려면 -Android Studio 2.1 이상의 버전을 사용해야 합니다. 이러한 버전에서는 Android Studio 1.5의 에뮬레이터에 비해 -더욱 빠른 성능을 제공하는 Android Emulator 2.0이 -지원됩니다.

    - -

    가상 기기 생성에 대한 자세한 내용은 가상 기기 관리를 참조하세요. -

    - - - - - - - - - - - - - - -
    - -
    - - - - diff --git a/docs/html-intl/intl/ko/preview/download_mp2.jd b/docs/html-intl/intl/ko/preview/download_mp2.jd deleted file mode 100644 index ff9dd7eab8d74d8958f7c13303b3845169466aa9..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/download_mp2.jd +++ /dev/null @@ -1,360 +0,0 @@ -page.title=다운로드 -page.image=images/cards/card-download_16-9_2x.png - -@jd:body - -
    - - - - -
    - -
    -
    -

    이 문서의 내용

    -
      -
    1. 미리 보기 SDK
    2. -
    3. 개발자 관련 문서
    4. -
    5. 하드웨어 시스템 이미지
    6. -
    - -

    Legacy downloads

    -
      -
    1. Developer Preview Archive
    2. -
    -
    -
    - - -

    - Android M 미리 보기 SDK에는 개발 도구, Android 시스템 파일 및 라이브러리 파일이 포함되어 있어 앱을 테스트하고 플랫폼의 다음 릴리스에 도입되는 새 API를 테스트하는 데 유용합니다. - 이 문서에서는 미리 보기의 다운로드할 수 있는 구성 요소를 가져와 앱을 테스트하는 방법에 대해 설명합니다. - -

    - - -

    미리 보기 SDK

    - -

    - 미리 보기 SDK는 Android SDK Manager를 통해 다운로드할 수 있습니다. 미리 보기 SDK를 다운로드하고 구성하는 데 관한 자세한 정보는 미리 보기 SDK 설정하기를 참조하십시오. - -

    - - -

    개발자 관련 문서

    - -

    - 개발자 관련 문서 다운로드 패키지에서는 자세한 API 참조 정보와 미리 보기에 대한 API 차이점 보고서를 제공합니다. -

    - - - - - - - - - - -
    DescriptionDownload / Checksums
    Android M Preview 2
    Developer Docs
    m-preview-2-developer-docs.zip
    - MD5: 1db6fff9c722b0339757e1cdf43663a8
    - SHA-1: 5a4ae88d644e63824d21b0e18f8e3977a7665157 -
    - - -

    하드웨어 시스템 이미지

    - -

    - 이러한 시스템 이미지를 사용하면 물리적인 기기에서 플랫폼의 미리 보기 버전을 설치하여 테스트할 수 있게 해줍니다. - 이러한 이미지 중 한 가지로 기기를 구성하면, 앱을 설치하고 테스트하여 앱이 플랫폼의 다음 버전에서 어떤 성능을 보일지 확인할 수 있습니다. - 기기에 시스템 이미지를 설치하는 과정은기기에서 모든 데이터를 제거하므로, 시스템 이미지를 설치하기에 앞서 데이터를 백업하는 것이 좋습니다. - - -

    - -

    - 경고: 다음 Android 시스템 이미지는 미리 보기이며 사정에 따라 변동될 수 있습니다. 이러한 시스템 이미지를 사용할 때에는 Android SDK 미리 보기 라이선스 계약을 따라야 합니다. - Android 미리 보기 시스템 이미지는 안정된 릴리스가 아니며, 오류나 결함이 들어있을 수 있고 이 때문에 컴퓨터 시스템, 기기 및 데이터에 손상을 초래할 수 있습니다. - - 미리 보기 Android 시스템 이미지는 공장 OS와 같은 테스트를 거치며 전화기 및 설치된 서비스와 애플리케이션의 작동이 중단되는 결과를 낳을 수 있습니다. - - -

    - - - - - - - - - - - - - - - - - - - - - - - - -
    DeviceDownload / Checksums
    Nexus 5 (GSM/LTE)
    "hammerhead"
    hammerhead-MPZ79M-preview-b1f4bde4.tgz
    - MD5: 2ca9f18bf47a061b339bab52647ceb0d
    - SHA-1: b1f4bde447eccbf8ce5d9b8b8ba954e3eac8e939 -
    Nexus 6
    "shamu"
    shamu-MPZ79M-preview-e1024040.tgz
    - MD5: 24a2118da340b9afedfbdfc026f6ff81
    - SHA-1: e10240408859d5188c4aae140e1c539130ba614b -
    Nexus 9
    "volantis"
    volantis-MPZ79M-preview-9f305342.tgz
    - MD5: 9edabf0a4c61b247f1cbb9dfdc0a899e
    - SHA-1: 9f30534216f10899a6a75495fc7e92408ea333a7 -
    Nexus Player
    "fugu"
    fugu-MPZ79N-preview-fb63af98.tgz
    - MD5: e8d081137a20b66df595ee69523314b5
    - SHA-1: fb63af98302dd97be8de9313734d389ccdcce250 -
    - -

    기기에 이미지 설치

    - -

    - 기기 이미지를 테스트용으로 사용하려면, 이를 호환되는 기기에 설치해야만 합니다. 시스템 이미지를 설치하려면 아래의 지침을 따르십시오. - -

    - -
      -
    1. 여기 목록에 나열된 시스템 이미지 중 하나를 다운로드하여 압축을 해제합니다.
    2. -
    3. 기기에서 보존하고자 하는 데이터를 모두 백업합니다.
    4. -
    5. 이미지를 기기에 플래시하려면 developers.google.com/android에 있는 지침을 따릅니다. - -
    6. -
    - -

    - 참고: 일단 개발 기기에 미리 보기 시스템 이미지를 플래시하고 나면 이것은 OTA(over-the-air) 업데이트를 통해 다음 미리 보기 릴리스에 맞춰 자동으로 업그레이드됩니다. - -

    - -

    기기를 공장 사양으로 되돌리기

    - -

    - 미리 보기의 설치를 제거하고 기기를 공장 사양으로 되돌리고자 하는 경우, developers.google.com/android를 방문하여 기기에 플래시하고자 하는 이미지를 다운로드하십시오. - - 해당 페이지에 있는 지침을 따라 기기에 이미지를 플래시하면 됩니다. - -

    - -
    - -
    - - - - diff --git a/docs/html-intl/intl/ko/preview/features/afw.jd b/docs/html-intl/intl/ko/preview/features/afw.jd deleted file mode 100644 index 4c06451e329c6e7b986989fbb6f5e809c3debeed..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/features/afw.jd +++ /dev/null @@ -1,552 +0,0 @@ -page.title=Android for Work 업데이트 -page.metaDescription=Android N의 새로운 Android for Work API와 기능. -page.keywords="android for work", "android N", "enterprise", "QR code" - -@jd:body - - - -

    이 문서에서는 Android N에서 제공되는 새로운 Android for Work 기능을 -설명합니다.

    - -

    QR 코드 프로비저닝

    - -

    - 이제 Android for Work는 기업에서 업무용으로 지급하는 기기를 프로비저닝할 때 QR 코드 사용을 - 지원합니다. 이제는 설치 마법사를 통해 QR 코드를 스캔하여 기기를 - 프로비저닝할 수 있습니다. -

    - -

    작업 프로필 보안 인증 질문

    - -

    - 프로필 소유자는 작업 프로필에서 작동하는 앱에 대한 보안 인증 질문을 - 지정하도록 사용자에게 요구할 수 있습니다. 시스템에서는 사용자가 업무용 앱을 열려고 할 때 - 보안 인증 질문을 표시합니다. 사용자가 보안 인증 질문에 올바로 - 답하면 작업 프로필의 잠금이 해제되고 필요하다면 작업 프로필의 암호가 - 해독됩니다. -

    - -

    - 프로필 소유자가 {@link - android.app.admin.DevicePolicyManager#ACTION_SET_NEW_PASSWORD} 인텐트를 보내면 -, 보안 인증 질문을 설정하라는 메시지가 사용자에게 표시됩니다. 또한, 프로필 소유자는 - 사용자에게 기기 잠금을 설정하도록 하는 ACTION_SET_NEW_PARENT_PROFILE_PASSWORD 인텐트를 - 보낼 수 있습니다. -

    - -

    - 프로필 소유자는 작업 프로필 보안 인증 질문의 비밀번호 정책을 다른 기기 - 비밀번호의 정책과는 다르게 설정하도록 선택할 수 있습니다. 예를 들어, 기기 보안 질문 응답의 최소 길이는 다른 암호에 요구되는 -길이와 -다를 수 있습니다. 프로필 소유자는 {@link - android.app.admin.DevicePolicyManager#setPasswordQuality - setPasswordQuality()} 및 {@link - android.app.admin.DevicePolicyManager#setPasswordMinimumLength - setPasswordMinimumLength()}와 같은 - 일반적인 {@link android.app.admin.DevicePolicyManager} - 메서드를 사용하여 보안 질문 정책을 설정합니다. 프로필 소유자는 새 DevicePolicyManager.getParentProfileInstance() - 메서드에 의해 반환되는 {@link android.app.admin.DevicePolicyManager} 인스턴스를 - 사용하여 기기 잠금을 - 설정할 수도 있습니다. 그 밖에도, 프로필 소유자는 {@link android.app.admin.DevicePolicyManager} - 클래스의 새로운 setOrganizationColor() 및 - setOrganizationName() 메서드를 사용하여 작업 프로필 보안 인증 질문에 대한 자격 증명 화면을 - 사용자 지정할 수 있습니다. -

    - -

    - 새로운 메서드와 상수에 대한 자세한 내용은 - N Preview SDK 참조DevicePolicyManager 참조 페이지를 참조하십시오. -

    - -

    앱에 대한 액세스 비활성화

    - -

    - 기기 소유자 및 프로필 소유자는 새 DevicePolicyManager.setPackagesSuspended() - 메서드를 호출하여 패키지에 대한 액세스를 일시적으로 중단할 수 - 있습니다. 소유자는 이 메서드를 똑같이 사용하여 해당 패키지를 다시 활성화할 수 있습니다. -

    - -

    - 패키지가 일시 중단된 동안에는 액티비티를 시작할 수 없고, 패키지에 대한 - 알림이 억제되고, 개요 화면에서 앱 항목이 숨겨집니다. - 일시 중단된 패키지는 개요 화면에 표시되지 않고 - (toast와 snackbar를 포함한) 대화 상자를 표시할 수 없습니다. 이들 패키지는 또한 오디오를 - 재생하거나 기기를 진동시킬 수도 없습니다. -

    - -

    - 현재 사용할 수 없는 앱임을 표시하기 위해 -, 런처는 뚜렷이 구별되는 UI를 일시 중단된 앱에 적용해야 합니다. 예를 들어, 앱 아이콘이 회색으로 표시되도록 할 수 - 있습니다. 런처는 앱이 일시 중단된 상태인지 - 확인하기 위해 새 DevicePolicyManager.getPackageSuspended() 메서드를 호출할 수 있습니다. -

    - -

    작업 모드 전환

    - -

    - 듀얼 프로필 기기에서는 사용자가 작업 모드를 설정하거나 해제할 수 있습니다. 작업 모드가 - 해제된 중에는 관리된 프로필이 일시적으로 종료됩니다. 프로필 - 소유자 앱을 포함하여 작업 프로필 앱, 백그라운드 동기화 및 알림이 모두 - 비활성화됩니다. 작업 프로필이 비활성화된 중에는 사용자가 - 업무용 앱을 실행할 수 없음을 미리 알려주기 위한 영구적인 상태 아이콘이 - 표시됩니다. 시스템 런처는 업무용 앱과 위젯에 액세스할 수 없음을 - 나타냅니다. -

    - -

    상시 접속 VPN

    - -

    - 기기 소유자 및 프로필 소유자는 항상 지정된 VPN을 통해 업무용 앱을 - 네트워크에 연결하도록 요구할 수 있습니다. 소유자가 이 요구 사항을 설정하면 - 기기는 부팅 시 해당 VPN을 자동으로 시작합니다. -

    - -

    - 소유자는 새 DevicePolicyManager.setAlwaysOnVpnPackage() 메서드를 호출하여 VPN을 사용하도록 요구할 수 - 있습니다. 소유자가 - VPN 요구 사항을 설정했는지 확인하려면 새 - DevicePolicyManager.GetAlwaysOnVpnPackage() 메서드를 호출하십시오. -

    - -

    - 시스템에서 앱 상호 작용 없이 VPN 서비스를 직접 바인딩할 수 있으므로, - VPN 클라이언트는 상시 접속 VPN에 대해 새로운 진입점을 처리해야 합니다. 이전과 마찬가지로, - {@link android.net.VpnService android.net.VpnService} 작업과 일치하는 인텐트 필터를 사용하여 활성 서비스를 - 찾을 수 있습니다. -

    - -

    - 사용자는 Settings > More > - VPN 화면을 사용하여 {@link - android.net.VpnService}를 구현하는 상시 접속 VPN 클라이언트를 수동으로 설정할 수 있습니다. -

    - -

    연락처와 작업 프로필 통합

    - -

    - 프로필 소유자는 기본 사용자의 업무용 연락처에 대한 로컬 검색 및 디렉터리 조회를 - 허용할 수 있습니다. 예를 들어, 사용자는 개인 다이얼러 또는 연락처 애플리케이션에서 - 개인용 및 업무용 디렉터리 연락처에 모두 액세스할 수 있습니다(프로필 - 관리자가 허용한 경우). -

    - -

    - Contact Provider를 활용하는 개발자는, 정책에 따라 허용되는 경우 -, Enterprise Contacts API를 사용하여 기본 사용자의 작업 프로필 디렉터리 항목에 액세스할 수 - 있습니다. -

    - -
      -
    • ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Phone.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Email.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Callable.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Directory.ENTERPRISE_CONTENT_URI -
    • - -
    • ContactsContract.Directory.isEntepriseDirectoryId() -
    • -
    - -

    - 프로필 소유자는 다음과 같은 새로운 메서드를 사용하여 기본 사용자의 업무용 연락처를 표시할지 -여부를 제어할 수 있습니다. -

    - -
      -
    • - DevicePolicyManager.setCrossProfileContactsSearchDisabled() -
    • - -
    • - DevicePolicyManager.getCrossProfileContactsSearchDisabled() -
    • -
    - -

    원격 재부팅

    - -

    - 기기 소유자는 기기를 원격으로 재부팅할 수 있습니다. 경우에 따라, 구내의 공공 장소에 배치되어 있는 - 기기는 전원 버튼에 액세스하지 못하게 되어 있습니다. 기기를 - 재부팅해야 하는 경우 관리자가 새 - DevicePolicyManager.reboot() 메서드를 사용하여 재부팅할 수 있습니다. -

    - -

    데이터 로밍 비활성화

    - -

    - 기기 소유자는 새로운 {@link - android.os.UserManager} 사용자 제한 DISALLOW_DATA_ROAMING을 사용하여 데이터 로밍을 비활성화할 수 있습니다. -

    - -

    엔터프라이즈 프로세스 로깅

    - -

    - 기기 소유자는 앱 실행, adb 액티비티 및 화면 잠금 해제를 비롯한 기기 액티비티를 - 원격으로 추적하여 의심스러운 액티비티를 식별할 수 있습니다. 프로세스 - 로그는 사용자 동의를 받을 필요가 없습니다. 로그를 검색하기 위해, 기기 소유자는 DevicePolicyManager.setSecurityLoggingEnabled()를 사용하여 - 기기 로깅을 활성화할 수 있습니다. -

    - -

    - API 변경 사항에는 다음이 포함됩니다. -

    - -
      - -
    • - 새로운 클래스 android.app.admin.SecurityLog와 이 클래스의 - 메서드 -
    • - -
    • - void DevicePolicyManager.setSecurityLoggingEnabled() -
    • - -
    • - boolean DevicePolicyManager.isSecurityLoggingEnabled() -
    • - -
    • - List<SecurityEvent> - DevicePolicyManager.retrieveSecurityLogs() -
    • - -
    • - List<SecurityEvent> - DevicePolicyManager.retrievePreRebootSecurityLogs() -
    • - -
    • - void DeviceAdminReceiver.onSecurityLogsAvailable() -
    • -
    - -

    원격 버그 보고서

    - -

    - 기기 소유자는 기기 상태 덤프 파일이 포함된 버그 보고서를 - 원격으로 트리거하고 검색할 수 있으며, 이를 통해 알려진 문제나 손상된 기기에 대한 - 포렌식 조사를 수행할 수 있습니다. 버그 보고서는 그 본질상 세세한 내용까지 담고 있으므로, - 사용자 동의를 받아야 합니다. -

    - -

    - Android N에서는 이 기능을 지원하기 위해 다음과 같은 API를 포함합니다. 자세한 - 내용은 N Preview SDK - 참조를 확인하세요. -

    - -
      -
    • - DevicePolicyManager.requestBugreport() -
    • - -
    • - DeviceAdminReceiver.onBugreportFailed() -
    • - -
    • - DeviceAdminReceiver.onBugreportShared() -
    • - -
    • - DeviceAdminReceiver.onBugreportSharingDeclined() -
    • - -
    • - DeviceAdminReceiver.BUGREPORT_FAILURE_FAILED_COMPLETING -
    • - -
    • - DeviceAdminReceiver.BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE -
    • -
    - -

    클라이언트 인증서 제거

    - -

    - 프로필 소유자와 기기 소유자는 이제 새 DevicePolicyManager.removeKeyPair() - 메서드를 호출하여, {@link android.app.admin.DevicePolicyManager#installKeyPair - installKeyPair()}를 통해 설치된 클라이언트 인증서를 - 제거할 수 있습니다. -

    - -

    설치 시 클라이언트 인증서에 대한 - 액세스 권한 부여

    - -

    - 프로필 소유자나 기기 소유자가 인증서 관리 권한을 - 타사 앱에 부여할 경우, 해당 앱은 소유자의 간섭을 전혀 받지 않고도 인증서에 - 액세스 권한을 부여할 수 있습니다. -

    - -

    - 인증서 관리를 위한 기존 API가 확장되었으며 다음을 포함합니다. -

    - -
      -
    • DevicePolicyManager.installKeyPair() -
    • -
    - -

    시스템 UI 정책 투명성

    - -

    - 사용자 환경에 영향을 미치는 정책이나 사용자 Settings를 제한하는 정책은 - 사용자에게 완전히 공개되며, 프로필 소유자와 기기 소유자는 해당 정책에 대한 책임을 - 회사의 IT 부서로 돌릴 수 있습니다. Settings에 일관되게 표시되는 “Action - not allowed” 메시지 외에도, IT 관리자는 - 다음과 같은 새로운 {@link android.app.admin.DevicePolicyManager} 메서드를 사용하여 기기 설정에서 조직별 지원 메시지를 - 설정할 수 있습니다. -

    - -
      -
    • - DevicePolicyManager.setShortSupportMessage() -
    • - -
    • - DevicePolicyManager.setLongSupportMessage() -
    • -
    - -

    앱 제한 관리 향상

    - -

    - 기기 소유자나 프로필 소유자는 새 DevicePolicyManager.setApplicationRestrictionsManagingPackage() - 메서드를 통해 다른 애플리케이션이 앱 제한을 - 관리하도록 할 수 - 있습니다. 지정된 애플리케이션은 이 권한이 부여되었는지 -여부를 확인하기 위해 DevicePolicyManager.isCallerApplicationRestrictionsManagingPackage()를 호출할 -수 있습니다. -

    - -

    - 앱 제한을 관리하도록 지정된 애플리케이션은 해당 사용자 또는 프로필 내에 있는 어떤 패키지에 대해서도 {@link - android.app.admin.DevicePolicyManager#setApplicationRestrictions - setApplicationRestrictions()} 및 {@link - android.app.admin.DevicePolicyManager#getApplicationRestrictions - getApplicationRestrictions()}를 호출할 수 있습니다. -

    - -

    위치 해제 스위치

    - -

    - 사용자는 개인용 앱에서 위치 정보에 계속 액세스하는 동안에도 - 업무용 앱의 위치 권한을 비활성화할 수 있습니다. 사용자는 - Location Settings에 있는 별개의 위치 액세스 스위치를 사용하여 작업 프로필에서 실행 중인 - 앱의 위치 업데이트 또는 마지막 위치 쿼리를 거부할 수 있습니다. -

    - -

    - 최상위 수준 위치 해제 스위치를 사용하면 기본 프로필과 관리된 프로필에 - 대해 모두 위치 액세스를 비활성화할 수 있습니다. -

    - -

    사용자 지정 프로비저닝

    - -

    - 애플리케이션은 기업 색상과 로고를 사용하여 프로필 소유자 및 기기 소유자 프로비저닝 - 흐름을 사용자 지정할 수 있습니다. -

    - -
    -
    - DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR -
    - -
    - 흐름 색상을 사용자 지정합니다. -
    - -
    - DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI -
    - -
    - 기업 로고를 사용하여 흐름을 사용자 지정합니다. -
    -
    - -

    다중 Wi-Fi CA 인증서

    - -

    - 프로필 소유자와 기기 소유자는 주어진 Wi-Fi 구성에 대해 다중 CA 인증서를 설정할 수 - 있습니다. SSID가 동일한 별개의 액세스 지점에 대해 - 별개의 CA가 기업 Wi-Fi 네트워크에 있는 경우, IT 관리자가 새 메서드 setCaCertificates()를 사용하여 - 모든 관련 CA를 Wi-Fi 구성에 포함시킬 수 - 있습니다. -

    - -

    - 추가되는 API는 다음과 같습니다. -

    - -
      -
    • - WifiEnterpriseConfig.setCaCertificates() -
    • - -
    • - WifiEnterpriseConfig.getCaCertificates() -
    • -
    - -

    사용자 지정 잠금 화면 메시지

    - -

    - 기기 소유자는 잠금 화면에 표시될 소유자 정보를 제공할 수 있습니다. - 이 정보는 사용자 잠금 화면 메시지(설정되어 있는 경우)보다 - 우선합니다. 새 {@link android.app.admin.DevicePolicyManager} 메서드는 다음과 같습니다. -

    - -
      -
    • - setDeviceOwnerLockScreenInfo() -
    • - -
    • - getDeviceOwnerLockScreenInfo() -
    • -
    - -

    작업 프로필 연결 서비스

    - -

    - 프로필 소유자는 호출 백엔드(호출 계정)용으로 - 작업별 {@link android.telecom.ConnectionService}를 사용하는 업무용 다이얼러 애플리케이션을 - 지정할 수 있습니다. 업무용 다이얼러는 업무 전용 통화 기록을 - 유지 관리하고 업무용 연락처에만 의존합니다. 사용자는 전화 걸기 애플리케이션에 상관없이 일관된 통화 UI - 환경을 사용합니다. 업무 통화 계정으로 수신되는 업무 통화는 - 개인 통화 계정으로 수신되는 개인용 통화와 - 구분됩니다. -

    - -

    - 다이얼러는 새 플래그 - android.telecom.Call.PROPERTY_WORK_CALL을 검사하여 통화가 -업무 통화인지 결정합니다. 통화가 업무 통화인 경우, 다이얼러는 작업 배지를 추가하는 등의 방법으로 - 이를 표시해야 합니다. -

    - -

    배경 화면 잠금

    - -

    - 새 사용자 제한(DISALLOW_SET_WALLPAPER)에 따라 사용자는 - 배경 화면을 변경할 수 없습니다. 그래도 기기 소유자나 프로필 소유자는 - 배경 화면을 변경할 수 있지만, 자신이 관리하는 사용자나 프로필의 - 배경 화면만 변경할 수 있을 뿐입니다. 예를 들어, 프로필 소유자는 상위 사용자의 배경 화면은 - 변경할 수 없지만, 기본 프로필에 있는 프로필 소유자나 기기 소유자는 - 변경할 수 있습니다. 배경 화면을 변경하고 싶은 프로필 소유자나 기기 소유자는 - 자신이 관리하는 사용자 또는 프로필에 - 배경 화면이 있는지({@link android.app.WallpaperManager#isWallpaperSupported - isWallpaperSupported()}), 그리고 이를 변경하도록 허용되는지 여부를 확인해야 합니다(새 메서드 - WallpaperManager.isWallpaperSettingAllowed() 사용). -

    - -

    사용자 아이콘 잠금

    - -

    - 새 사용자 제한(DISALLOW_SET_USER_ICON)에 따라 사용자는 - 사용자 아이콘을 변경할 수 없습니다. 그래도 사용자의 기기 소유자나 프로필 소유자는 - 아이콘을 변경할 수 있습니다. 하지만, 프로필 소유자는 자신이 관리하는 프로필에 대한 사용자 아이콘만 - 변경할 수 있을 뿐입니다. -

    - -

    기기 상태 모니터링

    - -

    - 기기 소유자나 프로필 소유자는 새 - HardwarePropertiesManager 인터페이스를 사용하여 CPU나 GPU의 온도, CPU 사용량 등, 기기 상태에 대한 - 정보를 검색할 수 있습니다. 새 - 모니터링 인터페이스는 원격 위치에서 지켜보는 사람이 없이 작동하는 기기를 - 모니터링하는 데 특히 유용합니다. -

    diff --git a/docs/html-intl/intl/ko/preview/features/background-optimization.jd b/docs/html-intl/intl/ko/preview/features/background-optimization.jd deleted file mode 100644 index 3bbc4745e9e8f35ba25f33d700d653b5b8596e88..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/features/background-optimization.jd +++ /dev/null @@ -1,391 +0,0 @@ -page.title=백그라운드 최적화 -page.metaDescription=암시적 브로드캐스트에 대한 새로운 제한. -page.keywords="android N", "implicit broadcasts", "job scheduler" -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

    - 백그라운드 프로세스는 메모리와 배터리를 많이 소모할 수 있습니다. 예를 들어, 암시적 브로드캐스트는 -이 브로드캐스트를 수신하도록 등록된 많은 백그라운드 프로세스를 시작할 수 있지만 -해당 프로세스가 많은 작업을 수행하지 못할 경우가 있습니다. 이로 인해 기기 성능과 - 사용자 환경에 모두 상당한 영향을 미칠 수 있습니다. -

    - -

    - 이 문제를 완화하기 위해, Android N은 다음과 같은 제한을 -적용합니다. -

    - -
      -
    • 브로드캐스트를 수신하도록 매니페스트에 등록되어 있더라도, Preview를 대상으로 하는 앱은 {@link - android.net.ConnectivityManager#CONNECTIVITY_ACTION} - 브로드캐스트를 수신하지 않습니다. 실행 중인 앱은 {@link android.content.Context#registerReceiver Context.registerReceiver()}로 -{@link android.content.BroadcastReceiver}를 등록하여 -여전히 기본 스레드에서 {@code CONNECTIVITY_CHANGE}를 수신할 - 수 있습니다. -
    • - -
    • 앱은 {@link - android.hardware.Camera#ACTION_NEW_PICTURE} 또는 {@link - android.hardware.Camera#ACTION_NEW_VIDEO} 브로드캐스트를 송수신할 수 없습니다. 이 최적화는 Preview를 대상으로 - 하는 앱뿐 아니라 모든 앱에 영향을 미칩니다. -
    • -
    - -

    - 앱이 이들 인텐트 중 하나라도 사용하는 경우에는, -Android N 기기를 올바로 대상으로 삼을 수 있도록 이들 인텐트에 대한 종속성을 최대한 빨리 제거해야 합니다. - Android 프레임워크는 이러한 암시적 브로드캐스트의 - 필요성을 줄이기 위한 여러 가지 해결책을 제공합니다. 예를 들어, {@link android.app.job.JobScheduler} -및 - {@code GcmNetworkManager}는 지정된 -조건(예: 비 데이터 통신 네트워크에 연결)이 충족될 경우 네트워크 작업을 -예약할 수 있는 강력한 메커니즘을 제공합니다. 이제 {@link android.app.job.JobScheduler}를 -사용하여 콘텐츠 제공자의 변경에 대응할 수도 있습니다. {@link android.app.job.JobInfo} -객체는 {@link android.app.job.JobScheduler}가 -작업 예약에 사용하는 매개변수를 캡슐화합니다. 작업 조건이 충족되면 시스템은 -이 작업을 앱의 {@link android.app.job.JobService}에서 실행합니다. -

    - -

    - 이 문서에서는 대체 메서드(예: {@link android.app.job.JobScheduler})를 -사용하여 이러한 새로운 제한에 맞게 앱을 적용하는 방법에 대해 -배워보겠습니다. -

    - -

    - CONNECTIVITY_ACTION에 대한 제한 -

    - -

    - Android N을 대상으로 하는 앱은 {@link - android.net.ConnectivityManager#CONNECTIVITY_ACTION} 브로드캐스트를 수신하지 않으며(이 브로드캐스트를 수신하도록 매니페스트에 등록하는 경우), 이 -브로드캐스트에 의존하는 프로세스는 -시작되지 않습니다. 이 경우에는 기기가 고정 요금제 네트워크에 연결될 때, -네트워크 변경 사항을 수신하려는 앱이나 대량의 네트워크 액티비티를 -수행하려는 앱에 문제가 생길 수 있습니다. 이 제한을 해결하기 위한 여러 가지 -해결책이 Android 프레임워크에 이미 있지만, 올바른 해결책을 선택하는 것은 -앱의 용도에 따라 다릅니다. -

    - -

    - 참고: {@link android.content.Context#registerReceiver Context.registerReceiver()}로 - 등록된 {@link android.content.BroadcastReceiver}는 앱이 - 실행되는 중에 계속해서 이 브로드캐스트를 수신합니다. -

    - -

    - 고정 요금제 연결에서 네트워크 작업 예약 -

    - -

    - {@link android.app.job.JobInfo.Builder JobInfo.Builder} 클래스를 -사용하여 {@link android.app.job.JobInfo} 객체를 빌드하는 경우, {@link - android.app.job.JobInfo.Builder#setRequiredNetworkType - setRequiredNetworkType()} 메서드를 적용하고 {@link android.app.job.JobInfo - JobInfo.NETWORK_TYPE_UNMETERED}를 작업 매개변수로 전달합니다. 다음의 코드 샘플에서는 기기가 비 데이터 통신 -네트워크에 연결되어 충전 중일 때 실행할 서비스를 -예약합니다. -

    - -
    -public static final int MY_BACKGROUND_JOB = 0;
    -...
    -public static void scheduleJob(Context context) {
    -  JobScheduler js =
    -      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    -  JobInfo job = new JobInfo.Builder(
    -    MY_BACKGROUND_JOB,
    -    new ComponentName(context, MyJobService.class))
    -      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
    -      .setRequiresCharging(true)
    -      .build();
    -  js.schedule(job);
    -}
    -
    - -

    - 작업의 조건이 충족되면, 앱은 -{@link android.app.job.JobService#onStartJob onStartJob()} 메서드를 지정된 {@code JobService.class}에서 실행하기 위한 콜백을 -수신합니다. {@link - android.app.job.JobScheduler} 구현의 더 많은 예를 보려면, JobScheduler 샘플 앱을 참조하세요. -

    - -

    - GMSCore 서비스를 사용하고 Android 5.0(API 레벨 21) 이하를 대상으로 하는 앱은 -{@code GcmNetworkManager}를 사용하고 {@code Task.NETWORK_STATE_UNMETERED}를 -지정할 수 있습니다. -

    - -

    - 앱이 실행되는 중에 네트워크 연결 모니터링 -

    - -

    - 실행 중인 앱은 등록된 {@link android.content.BroadcastReceiver}로 {@code CONNECTIVITY_CHANGE}를 여전히 수신할 수 -있습니다. 하지만 {@link - android.net.ConnectivityManager} API는 지정된 네트워크 조건이 충족될 경우에만 콜백을 요청하는 - 더욱 강력한 메서드를 제공합니다. -

    - -

    - {@link android.net.NetworkRequest} 객체는 {@link android.net.NetworkCapabilities}의 -관점에서 네트워크 콜백의 매개변수를 정의합니다. {@link - android.net.NetworkRequest.Builder NetworkRequest.Builder} 클래스로 {@link android.net.NetworkRequest} 객체를 -생성합니다. 이어서 {@link - android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, - android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()} -이 {@link android.net.NetworkRequest} 객체를 시스템에 전달합니다. 네트워크 조건이 충족되면, 앱은 {@link - android.net.ConnectivityManager.NetworkCallback} 클래스에 정의된 {@link android.net.ConnectivityManager.NetworkCallback#onAvailable - onAvailable()} 메서드를 -실행하기 위한 콜백을 -수신합니다. -

    - -

    - 앱이 종료되거나 앱이 {@link android.net.ConnectivityManager#unregisterNetworkCallback - unregisterNetworkCallback()}을 호출할 때까지 계속해서 -콜백을 수신합니다. -

    - -

    - NEW_PICTURE 및 NEW_VIDEO에 대한 제한 -

    - -

    - Android N에서 앱은 {@link - android.hardware.Camera#ACTION_NEW_PICTURE} 또는 {@link - android.hardware.Camera#ACTION_NEW_VIDEO} 브로드캐스트를 송수신할 수 없습니다. 이 제한은 새로운 이미지나 - 동영상을 처리하기 위해 여러 앱을 깨워야 하는 경우, 성능 및 사용자 환경에 - 미치는 영향을 줄여줍니다. Android N은 - {@link android.app.job.JobInfo} 및 {@link - android.app.job.JobParameters}를 확장하여 대체 해결책을 제공합니다. -

    - -

    - 새로운 JobInfo 메서드 -

    - -

    - 콘텐츠 URI 변경에 대한 작업을 트리거하기 위해, Android N은 - 다음과 같은 메서드로 {@link android.app.job.JobInfo} API를 확장합니다. -

    - -
    -
    - {@code JobInfo.TriggerContentUri()} -
    - -
    - 콘텐츠 URI 변경에 대한 작업을 트리거하는 데 필요한 매개변수를 캡슐화합니다. -
    - -
    - {@code JobInfo.Builder.addTriggerContentUri()} -
    - -
    - {@code TriggerContentUri} 객체를 {@link - android.app.job.JobInfo}에 전달합니다. {@link android.database.ContentObserver}는 -캡슐화된 콘텐츠 URI를 모니터링합니다. 하나의 작업과 연관된 여러 {@code - TriggerContentUri} 객체가 있는 경우, 콘텐츠 URI 중 하나에서만 변경이 보고되더라도 시스템이 -콜백을 제공합니다. -
    - -
    - 지정된 URI의 하위 항목이 하나라도 변경되면, {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} 플래그를 -추가하여 작업을 트리거합니다. 이 플래그는 -{@link - android.content.ContentResolver#registerContentObserver - registerContentObserver()}로 전달된 {@code notifyForDescendants} 매개변수에 해당합니다. -
    -
    - -

    - 참고: {@code TriggerContentUri()}는 {@link android.app.job.JobInfo.Builder#setPeriodic - setPeriodic()} 또는 {@link android.app.job.JobInfo.Builder#setPersisted - setPersisted()}와 -조합으로 사용될 수 없습니다. 콘텐츠 변경을 계속해서 모니터링하려면, 앱의 {@link - android.app.job.JobService}가 가장 최근 콜백의 처리를 완료하기 전에 새로운 -{@link android.app.job.JobInfo}를 예약하세요. -

    - -

    - 다음 샘플 코드에서는 콘텐츠 URI, {@code MEDIA_URI}의 -변경을 시스템이 보고할 때 트리거할 작업을 예약합니다. -

    - -
    -public static final int MY_BACKGROUND_JOB = 0;
    -...
    -public static void scheduleJob(Context context) {
    -  JobScheduler js =
    -          (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    -  JobInfo.Builder builder = new JobInfo.Builder(
    -          MY_BACKGROUND_JOB,
    -          new ComponentName(context, MediaContentJob.class));
    -  builder.addTriggerContentUri(
    -          new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    -          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
    -  js.schedule(builder.build());
    -}
    -
    -

    - 지정된 콘텐츠 URI에서의 변경을 시스템이 보고할 때, -앱이 콜백을 수신하고 {@link android.app.job.JobParameters} 객체가 -{@code MediaContentJob.class}의 {@link android.app.job.JobService#onStartJob onStartJob()}메서드에 -전달됩니다. -

    - -

    - 새로운 JobParameter 메서드 -

    - -

    - 또한, Android N에서는 어떤 콘텐츠 기관과 - URI가 해당 작업을 트리거했는지에 대한 유용한 정보를 앱이 - 수신할 수 있도록 {@link android.app.job.JobParameters}를 확장합니다. -

    - -
    -
    - {@code Uri[] getTriggeredContentUris()} -
    - -
    - 작업을 트리거한 URI의 배열을 반환합니다. 작업을 트리거한 -URI가 없거나(예: 시한 또는 기타 이유로 인해 작업이 트리거된 경우) 또는 -변경된 URI의 수가 50보다 크면 {@code - null}이 됩니다. -
    - -
    - {@code String[] getTriggeredContentAuthorities()} -
    - -
    - 작업을 트리거한 콘텐츠 기관의 문자열 배열을 반환합니다. - 반환된 배열이 {@code null}이 아닌 경우, {@code getTriggeredContentUris()}를 -사용하여 변경된 URI의 세부정보를 검색합니다. -
    -
    - -

    - 다음 샘플 코드에서는 {@link - android.app.job.JobService#onStartJob JobService.onStartJob()} 메서드를 재정의하고 -, 작업을 트리거한 콘텐츠 기관과 URI를 기록합니다. -

    - -
    -@Override
    -public boolean onStartJob(JobParameters params) {
    -  StringBuilder sb = new StringBuilder();
    -  sb.append("Media content has changed:\n");
    -  if (params.getTriggeredContentAuthorities() != null) {
    -      sb.append("Authorities: ");
    -      boolean first = true;
    -      for (String auth :
    -          params.getTriggeredContentAuthorities()) {
    -          if (first) {
    -              first = false;
    -          } else {
    -             sb.append(", ");
    -          }
    -           sb.append(auth);
    -      }
    -      if (params.getTriggeredContentUris() != null) {
    -          for (Uri uri : params.getTriggeredContentUris()) {
    -              sb.append("\n");
    -              sb.append(uri);
    -          }
    -      }
    -  } else {
    -      sb.append("(No content)");
    -  }
    -  Log.i(TAG, sb.toString());
    -  return true;
    -}
    -
    - -

    - 추가적인 앱 최적화 -

    - -

    - 저용량 메모리 기기나 저용량 메모리 조건에서 -앱이 실행되도록 최적화하면 성능과 사용자 환경을 개선할 수 있습니다. 백그라운드 서비스에 대한 종속성과 정적으로 등록된 - 암시적 브로드캐스트 수신기에 대한 종속성을 제거하면 해당 기기에서 앱을 - 더욱 빨리 실행할 수 있습니다. Android N은 이러한 문제 중 일부를 줄이기 위한 - 조치를 취하고 있지만, 백그라운드 - 프로세스를 전혀 사용하지 않고 앱이 실행되도록 - 최적화하는 것이 좋습니다. -

    - -

    - Android N에서는 백그라운드 프로세스를 -비활성화하고 앱 동작을 테스트하는 데 사용할 수 있는 몇 가지 추가적인 ADB(Android 디버그 브리지) 명령을 도입했습니다. -

    - -
      -
    • 암시적 브로드캐스트와 백그라운드 서비스를 사용할 -수 없는 조건을 시뮬레이션하려면 다음 명령을 입력합니다. -
    • - -
    • -
      -{@code $ adb shell cmd appops set <package> RUN_IN_BACKGROUND ignore}
      -
      -
    • - -
    • 암시적 브로드캐스트와 백그라운드 서비스를 다시 활성화하려면 -다음 명령을 입력합니다. -
    • - -
    • -
      -{@code $ adb shell cmd appops set <package> RUN_IN_BACKGROUND allow}
      -
      -
    • -
    diff --git a/docs/html-intl/intl/ko/preview/features/icu4j-framework.jd b/docs/html-intl/intl/ko/preview/features/icu4j-framework.jd deleted file mode 100644 index f626bff6bde951cce2705fa8b505bf32c575e670..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/features/icu4j-framework.jd +++ /dev/null @@ -1,159 +0,0 @@ -page.title=ICU4J Android 프레임워크 API -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

    - ICU4J는 오픈 소스이며 널리 사용되는 Java 라이브러리 세트로, 소프트웨어 애플리케이션에 유니코드와 -세계화 지원을 제공합니다. Android N은 -Android 프레임워크에서 앱 개발자가 -{@code android.icu} 패키지에서 사용할 수 있는 ICU4J API의 하위 세트를 노출합니다. 이 API는 -기기의 현지화 데이터를 사용합니다. 따라서 ICU4J 라이브러리를 APK로 컴파일하지 않고 -프레임워크에서 호출하여APK -풋프린트를 줄일 수 있습니다. (이 경우, Android N 이하 버전의 Android를 -실행하는 사용자가 ICU4J 라이브러리를 포함한 앱 버전을 다운로드할 수 있도록 -여러 버전의 -APK를 제공해야 할 수도 있습니다.) -

    - -

    - 이 문서에서는 먼저 이 라이브러리 지원에 필요한 최소 -Android API 레벨과 관련된 몇 가지 기본 정보를 제공합니다. 그 후, -각 Android에서 ICU4J를 구현하는 데 무엇이 필요한지 설명합니다. 마지막으로, -Android 프레임워크에서 ICU4J API를 사용하는 방법을 설명합니다. -

    - -

    ICU4J와의 관계

    - -

    - Android N은 -com.ibm.icu가 아니라 android.icu 패키지를 통해 ICU4J API의 하위 세트를 노출합니다. -Android 프레임워크는 여러 가지 이유로 -ICU4J API를 노출하지 않을 수 있습니다. 예컨대 Android N은 -일부 사용 중단된 API나 ICU 팀에서 안정적이라고 선언하지 않은 API를 -노출하지 않습니다. ICU 팀이 이후 API의 사용을 중단하면, Android도 -이를 사용 중단됨으로 표시하지만 계속 포함합니다. -

    - -

    표 1. -Android N에서 사용된 ICU 및 CLDR 버전.

    - - - - - - - - - - - -
    Android API 레벨ICU 버전CLDR 버전
    Android N5628
    - -

    중요한 참고 사항:

    - -
      -
    • ICU4J Android 프레임워크 API에는 모든 ICU4J API가 포함되지 않습니다.
    • -
    • NDK 개발자는 Android ICU4C가 지원되지 않는다는 것을 알아야 합니다.
    • -
    • Android 프레임워크의 API는 Android의 -리소스로 -현지화 지원을 대체하지 못합니다.
    • -
    - -

    com.ibm.icu에서 android.icu 패키지로 마이그레이션

    - -

    - 앱에서 이미 ICU4J API를 사용하고 있고 -android.icu API가 요구사항을 충족한다면 -프레임워크 API로 마이그레이션할 때 Java 가져오기를 -com.ibm.icu에서 android.icu로 변경해야 합니다. 그러면 APK에서 -ICU4J 파일 사본을 삭제할 수 있습니다. -

    - -

    - 참고: ICU4J 프레임워크 API는 {@code com.ibm.icu} 대신 {@code android.icu} -네임스페이스를 사용합니다. 이는 자체 {@code com.ibm.icu} 라이브러리가 포함된 APK에서 -네임스페이스 충돌을 피하기 위해서입니다. -

    - -

    - 다른 Android SDK API에서 android.icu API로 마이그레이션 -

    - -

    - javaandroid 패키지의 일부 클래스는 -ICU4J의 클래스와 같습니다. 그러나 ICU4J는 종종 더욱 폭넓은 -표준과 언어를 지원합니다. -

    -

    시작하기 위한 몇 가지 예시는 다음과 같습니다.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    클래스대체
    java.lang.Character android.icu.lang.UCharacter
    java.text.BreakIterator android.icu.text.BreakIterator
    java.text.DecimalFormat android.icu.text.DecimalFormat
    java.util.Calendar -android.icu.util.Calendar
    android.text.BidiFormatter - android.icu.text.Bidi -
    android.text.format.DateFormat - android.icu.text.DateFormat -
    android.text.format.DateUtils android.icu.text.DateFormat -android.icu.text.RelativeDateTimeFormatter -
    - -

    라이선스

    - -

    - ICU4J는 ICU 라이선스에 따라 배포됩니다. 자세한 내용은 ICU - 사용자 가이드를 참조하세요. -

    diff --git a/docs/html-intl/intl/ko/preview/features/multilingual-support.jd b/docs/html-intl/intl/ko/preview/features/multilingual-support.jd deleted file mode 100644 index 6b3e9994f9160c086f0a3119959287b05833030c..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/features/multilingual-support.jd +++ /dev/null @@ -1,221 +0,0 @@ -page.title=언어 및 로케일 -page.tags=androidn -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

    Android N에서는 다국어 사용자를 위한 지원이 개선되었으므로 -이러한 사용자가 이제 설정에서 여러 로케일을 선택할 수 있습니다. Android N은 -지원되는 로케일 수를 대폭 확대하고 -시스템이 리소스를 결정하는 방식을 변경하여 이 기능을 제공합니다. 새로 도입된 리소스 결정 방법은 -더욱 안정적이고 기존 APK와 호환되도록 설계되어 있지만 -예상치 못한 동작이 없는지 신중히 살펴봐야 합니다. 예를 들어, -앱이 예상 언어로 기본 설정되어 있는지 테스트해야 합니다. 또한, -앱이 여러 언어를 지원한다면 -원하는 대로 작동하는지 확인해야 합니다. 마지막으로 -앱이 지원하도록 명시하지 않은 언어를 무리 없이 처리하는지 확인해야 합니다.

    - -

    이 문서에서는 -Android N 이전의 리소스 결정 전략을 설명한 뒤에, Android N의 개선된 -리소스 결정 전략을 설명합니다. 마지막으로 -더 많은 다국어 사용자를 지원하기 위해 확장된 로케일을 활용하는 방법을 설명합니다.

    - -

    언어 리소스 결정에서의 과제

    - -

    Android N 이전의 Android에서는 - 앱과 시스템 로케일을 매칭하지 못하는 경우가 가끔 있었습니다.

    - -

    예를 들어, 다음과 같은 상황이라고 가정해 봅시다.

    -
      -
    • 앱의 기본 언어가 {@code en_US}(미국 영어)인데 -, {@code es_ES} - 리소스 파일에 스페인어 문자열도 현지화했습니다.
    • -
    • 기기는 {@code es_MX}로 설정되어 있습니다.
    • - -

      Java 코드가 문자열을 참조할 때 -앱에서 {@code es_ES} 아래에 스페인어 리소스를 현지화했더라도, 시스템은 기본({@code en_US}) 리소스 파일로부터 문자열을 -로드합니다. 그 이유는 시스템이 -정확한 일치 항목을 찾을 수 없을 때 해당 로케일에서 국가 코드를 -제거하여 리소스를 계속 찾기 때문입니다. 마지막으로, 일치 항목을 찾지 못한 경우 시스템은 기본값({@code en_US})으로 다시 -돌아갑니다.

      - - -

      또한, 앱에서 전혀 지원하지 않는 언어(예: 프랑스어)를 사용자가 선택하면 시스템은 기본값을 {@code en_US}로 -설정합니다. 예를 들면 다음과 같습니다.

      - -

      -표 1. 정확한 로케일 일치가 없는 경우 리소스 결정. -

      - - - - - - - - - - - - - -
      사용자 설정앱 리소스리소스 결정
      fr_CH -기본값(en)
      -de_DE
      -es_ES
      -fr_FR
      -it_IT
      -
      -fr_CH 시도 => 실패
      -fr 시도 => 실패
      -기본값(en) 사용 -
      - - -

      이 예시에서 시스템은 -사용자가 영어를 이해할 수 있는지 여부와 관계없이 영어 문자열을 표시합니다. 현재 이러한 동작이 상당히 -일반적입니다. Android N은 이런 -결과가 나타나는 빈도를 상당히 낮추었습니다.

      - -

      리소스 결정 전략 개선

      -

      Android N은 더욱 안정적인 리소스 결정을 사용하고 -자동으로 더욱 알맞은 대안책을 찾습니다. 그러나 결정 속도를 높이고 -관리성을 개선하려면 가장 일반적인 상위 방언에 리소스를 저장해야 합니다. - 예를 들어, 전에 {@code es-US} 디렉터리에 -스페인어 리소스를 저장했다면 남미 스페인어가 있는 {@code es-419} 디렉터리로 이동합니다. - 마찬가지로 {@code en-GB}란 폴더에 리소스 문자열이 있다면 -폴더 이름을 {@code en-001}(국제 영어)로 변경합니다. -en-GB 문자열의 가장 일반적인 상위 리소스는 {@code en-001}이기 때문입니다. - 다음은 이러한 방법이 -성능과 리소스 결정의 신뢰성을 개선하는 이유를 설명하는 예시입니다.

      - -

      리소스 결정 예시

      - -

      Android N의 경우, 표 1의 사례는 -다르게 결정됩니다.

      - -

      -표 2. 정확한 로케일 일치가 없을 경우 -개선된 결정 전략.

      - - - - - - - - - - - - -
      사용자 설정앱 리소스리소스 결정
        -
      1. fr_CH
      2. -
      -
      -기본값(en)
      -de_DE
      -es_ES
      -fr_FR
      -it_IT
      -
      -fr_CH 시도 => 실패
      -fr 시도 => 실패
      -Fr의 하위 리소스 시도 => fr_FR
      -fr_FR 사용 -
      - - -

      이제 사용자는 영어 대신 프랑스어 리소스를 보게 됩니다. 이 예시에서는 -Android N에서 프랑스어 문자열을 {@code fr_FR} -이 아니라 {@code fr}에 저장해야 하는 이유를 알 수 있습니다. 이러한 동작을 통해 가장 가까운 상위 방언과 일치시켜서 -더욱 빠르고 예측 가능하게 결정합니다.

      - -

      Android는 이러한 결정 논리를 개선했을 뿐만 아니라 -선택 가능한 언어를 더 많이 제공합니다. 위의 예시에 이탈리아어가 추가 사용자 언어로 지정되었지만 -앱에서 프랑스어를 지정하지 않는 경우를 적용해 보겠습니다.

      - -

      -표 3. 앱이 사용자의 두 번째 선호 로케일 설정에만 일치할 때 -리소스 결정.

      - - - - - - - - - - - - - - -
      사용자 설정앱 리소스리소스 결정
        -
      1. fr_CH
      2. -
      3. it_CH
      4. -
      -
      -기본값(en)
      -de_DE
      -es_ES
      -it_IT
      -
      -fr_CH 시도 => 실패
      -fr 시도 => 실패
      -fr의 하위 리소스 시도 => 실패
      -it_CH 시도 => 실패
      -it 시도 => 실패
      -it의 하위 리소스 시도 => it_IT
      -it_IT 사용 -
      -

      앱이 프랑스어를 지원하지 않지만 -사용자는 여전히 자신이 이해하는 언어를 볼 수 있습니다.

      - - -

      추가 로케일 지원을 위한 앱 설계

      -

      LocaleList API

      - -

      Android N에서는 앱이 사용자가 지정한 언어 목록을 직접 쿼리할 수 있는 새로운 API {@code LocaleList.getDefault()}가 -추가되었습니다. 이 API는 -앱 동작을 더욱 정교하게 해주고 - 콘텐츠 표시를 더 최적화해 줍니다. 예를 들어, 검색 시 -사용자 설정에 따라 여러 언어로 결과를 표시할 수 있습니다. 브라우저 앱은 -사용자가 이미 알고 있는 언어로 -번역 페이지를 제공하지 않고, 키보드 앱은 모든 적절한 레이아웃을 자동 활성화할 수 있습니다.

      - -

      포맷터

      - -

      Android 6.0(API 레벨 23)까지 Android는 많은 공통 언어(en, es, ar, fr, ru)에 대해 -1~2개의 로케일만 -지원했습니다. 각 언어의 변종은 몇 개뿐이기 때문에 -리소스 파일에 하드코딩된 문자열로 몇 개의 숫자와 날짜를 저장하는 것만으로 -충분했습니다. 그러나 Android에서 지원되는 로케일 세트가 확장되면서 -단일 로케일 내에서조차 -날짜, 시간, 통화 및 유사 정보에 -큰 차이가 생길 수 있게 되었습니다. 형식 하드코딩은 -최종 사용자에게 혼란을 줄 수 있습니다. 그러므로 Android N을 개발할 때는 -숫자와 날짜 문자열을 하드코딩하는 대신 포맷터를 사용하도록 하세요.

      - -

      가장 좋은 예시로는 아랍어가 있습니다. Android N에서 아랍어 지원이 -{@code ar_EG} 1개에서 27개 아랍어 로케일로 확장되었습니다. 이러한 로케일은 대부분의 리소스를 공유할 수 있지만 -어떤 로케일은 ASCII 숫자를 선호하고 어떤 로케일은 네이티브 숫자를 선호합니다. 예를 들어, -"4자리 PIN 선택"과 같은 숫자 변수가 포함된 문장을 생성하려면 -아래와 같이 포맷터를 사용합니다.

      - -
       format(locale, "Choose a %d-digit PIN", 4)
      diff --git a/docs/html-intl/intl/ko/preview/features/notification-updates.jd b/docs/html-intl/intl/ko/preview/features/notification-updates.jd deleted file mode 100644 index 480eda0a042c2d2e9d75bda936d152c3c7d03bfc..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/features/notification-updates.jd +++ /dev/null @@ -1,393 +0,0 @@ -page.title=알림 -page.tags=알림 -helpoutsWidget=true -page.image=/preview/images/notifications-card.png - -trainingnavtop=true - -@jd:body - -
      -
      - - -

      이 문서의 내용

      -
        -
      1. 직접 회신
      2. -
      3. 묶음 알림
      4. -
      5. 사용자 지정 뷰
      6. -
      7. 메시지 스타일
      8. -
      - -
      -
      - -

      Android N에서는 가시성과 상호 작용이 뛰어난 알림을 -앱이 게시할 수 있도록 여러 가지 새로운 API를 도입했습니다.

      - -

      Android N에서는 핸드셋에서 인라인 회신을 지원하기 위해 기존의 {@link android.support.v4.app.RemoteInput} -알림 API를 확장합니다. 이 기능을 사용하면 앱을 방문하지 않고도 알림 창에서 -신속하게 응답할 수 있습니다.

      - -

      - Android N에서는 또한 비슷한 알림을 묶어서 단일 알림으로 -표시할 수도 있습니다. 이것이 가능하도록, Android N에서는 기존의 {@link - android.support.v4.app.NotificationCompat.Builder#setGroup - NotificationCompat.Builder.setGroup()} 메서드를 사용합니다. 사용자가 각 알림을 확장할 수 있으며, 각 알림에 대해 회신 및 -닫기와 같은 동작을 알림 창에서 개별적으로 수행할 -수 있습니다. -

      - -

      마지막으로, Android N에서는 또한 앱의 사용자 지정된 알림 -뷰에서 시스템 장식을 활용할 수 있는 새 API를 추가합니다. 이들 API는 표준 템플릿을 통해 알림 뷰가 -일관된 프레젠테이션을 공유하도록 보장해 -줍니다.

      - -

      이 문서에서는 새 알림 기능을 앱에서 사용할 때 고려해야 -하는 몇 가지 주요 변경 사항을 중점적으로 다룹니다.

      - -

      직접 회신

      - -

      Android N에 있는 직접 회신 기능을 사용하여, 사용자가 문자 -메시지에 신속하게 응답하거나 알림 인터페이스 내에서 직접 -작업 목록을 업데이트할 수 있습니다. 핸드헬드에서 인라인 회신 동작은 알림에 연결된 추가적인 -버튼으로 나타납니다. 사용자가 키보드를 통해 회신하면 -시스템은 여러분이 알림 동작에 지정했던 -인텐트에 텍스트 응답을 첨부하고 이 인텐트를 - 핸드헬드 앱으로 보냅니다. - - - -

      - 그림 1. Android N이 Reply - 동작 버튼을 추가합니다. -

      - -

      인라인 회신 동작 추가

      - -

      직접 회신을 지원하는 알림 동작을 만들려면: -

      - -
        -
      1. 알림 동작에 추가할 수 있는 {@link android.support.v4.app.RemoteInput.Builder}의 -인스턴스를 -만듭니다. 이 클래스의 생성자는 시스템이 텍스트 입력의 키로 - 사용하는 문자열을 수락합니다. 나중에 핸드헬드 앱은 이 키를 사용하여 입력 텍스트를 -검색합니다. - -
        -// Key for the string that's delivered in the action's intent.
        -private static final String KEY_TEXT_REPLY = "key_text_reply";
        -String replyLabel = getResources().getString(R.string.reply_label);
        -RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
        -        .setLabel(replyLabel)
        -        .build();
        -
        -
      2. -
      3. addRemoteInput()을 사용하여 {@link android.support.v4.app.RemoteInput} -객체를 동작에 첨부합니다. - -
        -// Create the reply action and add the remote input.
        -Notification.Action action =
        -        new Notification.Action.Builder(R.drawable.ic_reply_icon,
        -                getString(R.string.label), replyPendingIntent)
        -                .addRemoteInput(remoteInput)
        -                .build();
        -
        -
      4. - -
      5. 동작을 알림에 적용하고 알림을 발생합니다. - -
        -// Build the notification and add the action.
        -Notification newMessageNotification =
        -        new Notification.Builder(mContext)
        -                .setSmallIcon(R.drawable.ic_message)
        -                .setContentTitle(getString(R.string.title))
        -                .setContentText(getString(R.string.content))
        -                .addAction(action))
        -                .build();
        -
        -// Issue the notification.
        -NotificationManager notificationManager =
        -        NotificationManager.from(mContext);
        -notificationManager.notify(notificationId, newMessageNotification);
        -
        -
        -
      6. - -
      - - -

      시스템이 사용자에게 알림 동작이 트리거될 때 응답을 입력하라는 -메시지를 표시합니다.

      - - -

      - 그림 2. 사용자가 알림 창에서 텍스트를 입력합니다. -

      - -

      - 인라인 회신에서 사용자 입력을 검색 -

      - -

      - 회신 동작의 인텐트에 선언하셨던 액티비티에 대해 알림 - 인터페이스로부터 사용자 입력을 수신하려면: -

      - -
        -
      1. 알림 동작의 인텐트를 입력 매개변수로서 전달하여 {@link android.support.v4.app.RemoteInput#getResultsFromIntent - getResultsFromIntent()}를 - 호출합니다. 이 메서드는 텍스트 응답이 포함된 {@link android.os.Bundle}을 - 반환합니다. - -
        -Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        -
        -
      2. - -
      3. ({@link - android.support.v4.app.RemoteInput.Builder} 생성자에 제공된) 결과 키를 사용하여 번들에 쿼리를 수행합니다. 다음 코드 조각에서처럼, 메서드를 만들어 이 프로세스를 -완료하고 입력 텍스트를 -검색할 수 있습니다. - -
        -// Obtain the intent that started this activity by calling
        -// Activity.getIntent() and pass it into this method to
        -// get the associated string.
        -
        -private CharSequence getMessageText(Intent intent) {
        -    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        -    if (remoteInput != null) {
        -        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
        -    }
        -    return null;
        - }
        -
        -
      4. - -
      5. 이전 알림에 대해 제공했던 것과 동일한 알림 ID를 - 사용하여, 다른 알림을 작성하고 발급합니다. 사용자에게 성공적으로 회신했음을 -알려주기 위해 알림 인터페이스에서 -알림 표시기가 사라집니다. 이 새로운 알림으로 작업할 때, 수신기의 -{@code onReceive()} 메서드로 전달되는 컨텍스트를 사용하세요. - -
        -// Build a new notification, which informs the user that the system
        -// handled their interaction with the previous notification.
        -Notification repliedNotification =
        -        new Notification.Builder(context)
        -                .setSmallIcon(R.drawable.ic_message)
        -                .setContentText(getString(R.string.replied))
        -                .build();
        -
        -// Issue the new notification.
        -NotificationManager notificationManager =
        -        NotificationManager.from(context);
        -notificationManager.notify(notificationId, repliedNotification);
        -
        -
      6. -
      - -

      - 채팅과 같은 대화형 앱의 경우, 검색된 텍스트를 처리할 때 - 추가 컨텍스트를 포함하는 것이 유용할 수 있습니다. 예를 들어, 이들 앱은 여러 줄의 채팅 기록을 -표시할 수 있습니다. 사용자가 {@link - android.support.v4.app.RemoteInput}을 통해 응답하는 경우, -{@code setRemoteInputHistory()} 메서드를 사용하여 회신 기록을 업데이트할 수 있습니다. -

      - -

      - 앱이 원격 입력을 수신한 후에는 알림이 업데이트되거나 - 취소되어야 합니다. 사용자가 Direct Reply를 사용하여 원격 업데이트에 -회신할 때는 알림을 -취소하지 마세요. 그 대신, 사용자의 회신을 표시하도록 알림을 업데이트하세요. -{@code MessagingStyle}을 사용하는 알림의 경우, 회신을 최신 메시지로서 -추가해야 합니다. 다른 템플릿을 사용할 경우 사용자의 -회신을 원격 입력 기록에 추가할 수 있습니다. -

      - -

      묶음 알림

      - -

      Android N에서는 일련의 알림을 표시하기 위한 새로운 방식을 -개발자에게 제공합니다. 묶음 알림. 이것은 -Android Wear의 알림 -스택 기능과 유사합니다. 예를 들어, 수신된 메시지에 대해 앱이 알림을 생성하는 경우, -둘 이상의 메시지가 수신되면 그 알림을 하나의 -단일 그룹으로 묶습니다. 기존의 -{@link android.support.v4.app.NotificationCompat.Builder#setGroup -Builder.setGroup()} 메서드를 사용하여 유사한 알림을 묶을 수 있습니다.

      - -

      - 알림 그룹은 이 그룹을 구성하는 알림을 계층 구조로 만듭니다. - 계층 구조의 맨 위는 그룹의 요약 정보가 표시되는 상위 -알림입니다. 사용자는 알림 그룹을 점진적으로 확장할 수 있으며, 시스템은 -사용자가 더 깊이 파고들수록 더 많은 정보를 -표시합니다. 사용자가 번들을 확장하면 시스템은 모든 하위 알림에 대해 -더 많은 정보를 표시하며, 사용자가 이들 알림 중 하나를 확장하면 -시스템은 알림의 전체 콘텐츠를 표시합니다. -

      - - -

      - 그림 3. 사용자는 알림 그룹을 점진적으로 확장할 수 - 있습니다. -

      - -

      - 참고: 동일 앱이 4개 이상의 알림을 보내면서 -그룹화를 지정하지 않으면, -시스템에서 이들 알림을 자동으로 그룹화합니다. -

      - -

      알림을 그룹에 추가하는 방법을 알아보려면 -각 -알림을 그룹에 추가를 참조하세요.

      - - -

      묶음 알림의 모범 사례

      -

      이 섹션에서는 이전 버전의 Android 플랫폼에서 -사용되었던 {@link android.app.Notification.InboxStyle InboxStyle} -알림 대신에 알림 그룹을 사용할 때의 지침을 -제공합니다.

      - -

      묶음 알림을 사용하는 경우

      - -

      자신의 사용 사례에서 다음의 모든 조건이 충족되는 경우에만 -알림 그룹을 사용해야 합니다.

      - -
        -
      • 하위 알림은 완전한 알림이며 그룹 요약이 필요 없이 -개별적으로 표시될 수 있습니다.
      • -
      • 하위 알림을 개별적으로 표시하는 경우 이점이 있습니다. 예를 들면 다음과 같습니다. - -
      • -
          -
        • 알림이 실행 가능하며, 각 하위 알림에 맞는 동작이 있습니다.
        • -
        • 사용자가 읽고 싶어하는 하위 알림에 더 많은 정보가 있습니다.
        • -
        -
      - -

      알림 그룹의 사용 사례에 대한 좋은 예로는, 수신 메시지의 -목록을 표시하는 메시징 앱이나 수신된 이메일의 목록을 표시하는 -이메일 앱이 있습니다.

      - -

      -단일 알림이 바람직한 사례의 예로는, 한 사람이 보낸 -개별 메시지나 1줄 텍스트 항목의 목록 표시가 -있습니다. 이를 수행하기 위해 -({@link android.app.Notification.InboxStyle InboxStyle} 또는 -{@link android.app.Notification.BigTextStyle BigTextStyle})을 사용할 -수 있습니다. -

      - -

      묶음 알림 표시

      - -

      - 그룹에 하나의 하위 항목만 포함되어 있더라도 앱은 -항상 그룹 요약을 게시해야 합니다. 하나의 알림만 포함된 경우에는 시스템이 요약을 -억제하고 하위 알림을 직접 표시합니다. 이렇게 하면 사용자가 그룹의 -하위 항목을 스와이프할 때 시스템이 일관된 경험을 제공할 수 -있습니다. -

      - -

      - 참고: 이 버전의 Android N에서는 아직 단일 하위 -항목이 포함된 알림 그룹에 대해 요약을 억제하지 않습니다. 이 -기능은 이후 버전의 Android N에 추가될 것입니다. -

      - -

      피킹 알림

      - -

      시스템은 -일반적으로 하위 알림을 그룹으로 표시하지만, -이 알림이 일시적으로 헤드업 알림으로 -나타나도록 설정할 수 있습니다. 이 기능을 사용하면 가장 최근의 하위 항목과 이에 -관련된 동작에 즉시 액세스할 수 있으므로 특히 유용합니다. -

      - - -

      이전 버전과의 호환성

      - -

      - Android 5.0(API 레벨 21) 이후로, 알림 그룹과 -원격 입력은 Android Wear 기기를 지원하기 위한 {@link - android.app.Notification} API의 일부였습니다. 이미 이들 API로 알림을 작성한 경우 수행할 조치는, -앱 동작이 위에 설명된 지침과 일치하는지 확인하고 {@code - setRemoteInputHistory()} 구현을 -고려하는 것입니다. -

      - -

      - 이전 버전과의 호환성을 지원하기 위해, -지원 라이브러리의 {@link android.support.v4.app.NotificationCompat} -클래스로 동일한 API를 사용할 수 있으며, 이전 Android 버전에서 작동하는 알림을 작성할 -수 있습니다. 핸드헬드와 태블릿에서는 요약 알림만 사용자에게 보이므로, -앱은 해당 그룹의 전체 정보 콘텐츠에 대해 받은편지함 -스타일이나 이와 동등한 알림 표시를 계속 가져야 합니다. Android -Wear 기기에서는 구형 플랫폼 레벨에서도 -사용자가 모든 하위 알림을 볼 수 있으므로, API 레벨에 상관없이 하위 알림을 -작성해야 합니다. -

      - -

      사용자 지정 뷰

      -

      Android N부터는 알림 뷰를 사용자 지정할 수 있으며 -알림 헤더, 동작 및 확장 가능한 레이아웃과 같은 시스템 장식을 계속 -획득할 수 있습니다.

      - -

      이 기능을 활성화하기 위해, Android N에서는 다음과 -같은 API를 추가하여 사용자 지정 뷰의 스타일을 지정합니다.

      - -
      -
      -{@code DecoratedCustomViewStyle()}
      -
      미디어 알림 이외의 스타일 -알림.
      -
      -{@code DecoratedMediaCustomViewStyle()}
      -
      스타일 미디어 알림.
      -
      - -

      이 새로운 API를 사용하려면, {@code setStyle()} 메서드를 호출하여, -원하는 사용자 지정 뷰 스타일에 전달합니다.

      - -

      이 조각에서는 -{@code DecoratedCustomViewStyle()} 메서드로 사용자 지정 알림 객체를 구성하는 방법을 보여줍니다.

      - -
      -Notification notification = new Notification.Builder()
      -           .setSmallIcon(R.drawable.ic_stat_player)
      -           .setLargeIcon(albumArtBitmap))
      -           .setCustomContentView(contentView);
      -           .setStyle(new Notification.DecoratedCustomViewStyle())
      -           .build();
      -
      -
      - -

      메시징 스타일

      -

      - Android N에서는 알림 메시지의 스타일을 사용자 지정하기 위한 새로운 API를 도입했습니다. - MessageStyle 클래스를 사용하면 대화 제목, 추가 메시지 및 알림에 대한 콘텐츠 뷰를 비롯하여 -알림 메시지에 표시되는 여러 가지 레이블을 -변경할 수 있습니다. -

      - -

      - 다음 코드 조각에서는 - MessageStyle 클래스를 사용하여 알림 스타일을 사용자 지정하는 방법을 보여 줍니다. -

      - -
      -  Notification notification = new Notification.Builder()
      -             .setStyle(new Notification.MessagingStyle("Me")
      -                 .setConversationTitle("Team lunch")
      -                 .addMessage("Hi", timestamp1, null) // Pass in null for user.
      -                 .addMessage("What's up?", timestamp2, "Coworker")
      -                 .addMessage("Not much", timestamp3, null)
      -                 .addMessage("How about lunch?", timestamp4, "Coworker"));
      -
      diff --git a/docs/html-intl/intl/ko/preview/index.jd b/docs/html-intl/intl/ko/preview/index.jd deleted file mode 100644 index 4b0ccc594670164244157e79500178a1de414e7c..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/index.jd +++ /dev/null @@ -1,131 +0,0 @@ -page.title=Android N Developer Preview -page.tags="preview","developer" -meta.tags="preview", "android" -fullpage=true -forcelocalnav=true -header.hide=1 -footer.hide=1 -@jd:body - - - -
      -
      -
      - -
      -

      Android N Developer Preview

      -

      - Android N을 맞이할 준비를 하세요! - Nexus와 다른 기기에서 앱을 테스트하세요. 전력과 메모리를 절약하는 새로운 시스템 -동작을 지원하세요. - 다중 창 UI, -직접 회신 알림 등으로 앱을 확장하세요. -

      - - - - 시작하기 - -
      -
      - -
      -
      -
      -
      -
      -
      -
      - - - - - -
      -

      최신

      -
      -
      - -
      -

      리소스

      -
      - 앱을 Android N에서 사용할 수 있도록 준비하는 데 유용한 중요 정보입니다. -
      - -
      - -
      -
      - diff --git a/docs/html-intl/intl/ko/preview/license.jd b/docs/html-intl/intl/ko/preview/license.jd deleted file mode 100644 index 875ec853750d29c706526bafe5f84c1b0056e12a..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/license.jd +++ /dev/null @@ -1,145 +0,0 @@ -page.title=라이선스 계약 - -@jd:body - -

      -Android SDK Preview를 시작하려면 우선 다음과 같은 사용 약관에 동의해야 합니다. -아래에 설명한 바와 같이, 이것은 Android SDK의 프리뷰 버전이며 변경될 가능성이 있고 이를 사용하는 위험 부담은 계약자 본인에게 있음을 유의하십시오. Android SDK Preview는 안정된 릴리스가 아니며, 오류나 결함이 들어있을 수 있고 이 때문에 컴퓨터 시스템, 기기 및 데이터에 심각한 손상을 초래할 수 있습니다. -

      - -

      -이것은 Android SDK Preview 라이선스 계약서입니다(이하 "라이선스 계약"). -

      -
      -1. 개요 - -1.1 Android SDK Preview(본 라이선스 계약에서는 "Preview"라고 칭하며, 구체적으로 Android 시스템 파일, 패키지 API 및 Preview 라이브러리 파일이 사용 가능한 경우와 사용 가능해진 경우 이들 파일을 포함한 것임)는 본 라이선스 계약 조건에 따라 계약자에게 사용을 허여합니다. 본 라이선스 계약은 Preview 사용과 관련하여 계약자와 Google 간에 법적 구속력이 있는 계약을 체결합니다. - -1.2 "Android"는 기기를 위한 Android 소프트웨어 스택을 의미합니다. 이는 http://source.android.com/ URL에 위치하며 수시로 업데이트되는 Android 오픈 소스 프로젝트에서 제공됩니다. - -1.3 "Android 호환"은 (i) Android 호환성 웹사이트(http://source.android.com/compatibility)에서 찾을 수 있고 간혹 업데이트되는 Android 호환성 정의 문서를 준수하며; (ii) Android CTS(Compatibility Test Suite)를 성공적으로 통과한 모든 Android 구현을 의미합니다. - -1.4 "Google"은 미국 1600 Amphitheatre Parkway, Mountain View, CA 94043에 본사를 두고 있는 델라웨어주 법인인 Google Inc.를 의미합니다. - -2. 라이선스 계약에 동의 - -2.1 이 Preview를 사용하려면, 먼저 라이선스 계약에 동의해야 합니다. 이 라이선스 계약에 동의하지 않고 Preview를 사용해서는 안 됩니다. - -2.2 수락을 클릭하거나 Preview를 사용, 또는 이 두 행위를 모두 수행하면 본 라이선스 계약 조건에 동의하는 것으로 간주됩니다. - -2.3 미국법 또는 현재 거주 중이거나 Preview를 사용하는 국가를 포함하여 다른 국가의 법에 따라 Preview를 받는 것이 금지된 경우, Preview를 사용할 수 없으며 본 라이선스 계약을 수락할 수 없습니다. - -2.4 회사 또는 단체 내에서 내부적으로 Preview를 사용하며 고용주 또는 기타 단체를 대신하여 본 라이선스 계약 준수에 동의하는 경우, 계약자의 고용주나 그 단체에 본 라이선스 계약에 대한 구속력을 부여할 수 있는 모든 법적 권한을 계약자가 갖고 있음을 진술하고 보증합니다. 구속력을 부여할 수 있는 법적 권한이 없을 경우, 고용주 또는 기타 단체를 대신하여 본 라이선스 계약에 동의하거나 Preview를 사용할 수 없습니다. - -3. Google의 Preview 라이선스 - -3.1 본 라이선스 계약의 조건에 따라 Google은 계약자에게 한정적이며 전 세계적으로 무료로 사용이 가능하고 양도할 수 없고 비독점적이며 2차 라이선스를 불허하는 Preview 사용 라이선스를 부여합니다. 이 라이선스 하에서 계약자는 Android 플랫폼에서 실행되는 애플리케이션을 개발하는 경우에만 Preview를 사용할 수 있습니다. - -3.2 이 Preview를 사용하여 다른 플랫폼용 애플리케이션을 개발하거나(Android 비호환 구현 포함) 다른 SDK를 개발할 수 없습니다. 물론 이 Preview가 이러한 목적에 사용되지 않는 경우 Android의 비호환 구현을 포함한 다른 플랫폼용 애플리케이션을 자유롭게 개발할 수 있습니다. - -3.3 계약자는 Preview에 존재하는 지적 재산권을 포함하여 Preview에 대한 모든 법적인 권리, 소유권 및 이익이 Google 또는 제3자에게 있음에 동의합니다. "지적 재산권"은 모든 특허법, 저작권법, 영업비밀법, 상표법 하의 모든 권리 및 기타 모든 소유권을 의미합니다. Google은 계약자에게 명시적으로 부여하지 않은 모든 권리를 보유합니다. - -3.4 본 라이선스 계약에 명시적으로 허용된 용도 외에는 Preview를 사용할 수 없습니다. 해당 제3자 라이선스 요건이 허용하는 범위를 제외하고 계약자는 Preview의 파생 제품이나 Preview의 일부분을 (a) 복사(백업 목적 제외), 수정, 개작, 재배포, 역컴파일, 리버스 엔지니어링, 분해하거나 이를 통해 파생물을 생성하거나 (b) 개인 컴퓨터를 제외한 모바일 단말기 또는 기타 모든 하드웨어 기기에 Preview의 일부를 로드하거나, Preview의 일부를 다른 소프트웨어와 결합하거나 Preview의 일부가 통합된 일체의 소프트웨어나 기기를 배포해서는 안 됩니다. - -3.5 오픈 소스 소프트웨어 라이선스에 의거한 Preview 구성요소의 사용, 재생산, 배포에는 본 라이선스 계약이 아닌, 해당 오픈 소스 소프트웨어 라이선스의 조건이 적용됩니다. 계약자는 허용된 모든 권한 하에서 그러한 오픈 소스 소프트웨어 라이선스에 관해 충실한 피허가자로서의 자세를 견지할 것이며 그러한 권한을 종료, 일시 중단 또는 침해하는 행위를 삼갈 것을 동의합니다. - -3.6 계약자는 Google이 제공하는 Preview의 형태 및 특성이 사전 통지 없이 변경될 수 있음에 동의하며, 이전 버전의 Preview에서 개발된 애플리케이션이 이후 버전의 Preview와 호환되지 않을 수 있음에 동의합니다. 계약자는 계약자 또는 사용자에게 사전 통지 없이 Preview(또는 Preview에 포함된 기능) 제공을 (영구적 또는 일시적으로) 중단할 수 있는 권한이 Google에게 있음에 동의합니다. - -3.7 본 라이선스 계약은 계약자에게 Google의 상표명, 상표, 서비스 표시, 로고, 도메인 이름, 기타 독특한 브랜드 특징에 대한 사용 권한을 부여하지 않습니다. - -3.8 계약자는 Preview에 부착되어 있거나 포함되어 있는 모든 소유권 고지 사항(저작권 및 상표 고지 사항 포함)을 제거, 변경 또는 불분명하게 만들지 않을 것에 동의합니다. - -4. 계약자의 Preview 사용 - -4.1 Google은 본 라이선스 계약의 어떤 조항도 계약자(또는 계약자의 사용 허가자)가 Preview를 사용하여 개발한 소프트웨어 애플리케이션에 대한 권리, 소유권 또는 이익, 그리고 해당 애플리케이션에 존재하는 모든 지적 재산권을 부여하지 않는다는 점에 동의합니다. - -4.2 계약자는 (a) 본 라이선스 계약 그리고 (b) 모든 준거법, 규정 또는 관련 관할권 내에서 일반적으로 수용되는 관행 또는 지침(미국 또는 기타 관련 국가로/에서의 데이터 또는 소프트웨어 수출과 관련된 모든 법률 포함)에서 허용하는 용도에 한하여 Preview를 사용하고 애플리케이션을 작성하는 것에 동의합니다. - -4.3 계약자는 일반 대중 사용자를 대상으로 Preview를 사용하여 애플리케이션을 개발하는 경우, 해당 사용자의 프라이버시 및 법적 권리를 보호하는 것에 동의합니다. 사용자가 계약자에게 사용자 이름, 비밀번호 또는 기타 로그인 정보나 개인 정보를 제공하는 경우, 계약자는 제공된 정보가 자신의 애플리케이션에 제공된다는 사실을 사용자에게 알려야 하며, 반드시 법적으로 적절한 개인정보 보호정책 고지 및 보호를 해당 사용자에게 제공해야 합니다. 애플리케이션에서 사용자가 제공한 개인 정보나 민감한 정보를 저장하는 경우, 이를 안전하게 처리해야 합니다. 사용자들이 애플리케이션에 Google 계정 정보를 제공하는 경우, 애플리케이션은 해당 사용자의 Google 계정에 액세스하는 목적으로만, 그리고 각 사용자가 허용한 범위 내의 한정된 목적으로만 이러한 정보를 사용해야 합니다. - -4.4 계약자는 Google 또는 기타 모든 타사의 서버, 네트워크 또는 기타 모든 재산 또는 서비스를 허가 없이 방해, 교란, 손상 또는 액세스하는 애플리케이션의 개발 또는 배포를 포함한 하등의 행위에 Preview를 이용하지 않을 것임을 동의합니다. - -4.5 계약자는 자신이 Android 및/또는 Android용 애플리케이션을 통해 생성, 전송 또는 표시하는 모든 데이터, 콘텐츠 또는 리소스 그리고 그로 인한 결과(Google이 입을 수 있는 모든 피해나 손실 포함)에 대해 전적으로 책임이 있다는 것(그리고 Google은 계약자 또는 모든 제3자에 대한 책임이 없다는 것)에 동의합니다. - -4.6 계약자는 본 라이선스 계약, 모든 해당 제3자 계약 또는 서비스 약관, 또는 모든 준거법 또는 규정에 의거한 계약자 의무 위반, 그리고 그로 인한 결과(Google 또는 제3자가 입을 수 있는 모든 피해나 손실 포함)에 전적으로 책임이 있다는 것(그리고 Google은 계약자 또는 모든 제3자에 대한 책임이 없다는 것)에 동의합니다. - -4.7 이 Preview는 현재 개발 단계에 있으며, 계약자의 테스트와 피드백은 그러한 개발 과정에 중요한 부분을 차지합니다. Preview를 사용함으로써 계약자는 일부 기능의 구현은 아직 개발 중인 상태이며 Preview가 안정된 릴리스처럼 완벽하게 기능할 것이라 믿고 사용해서는 안 된다는 점을 인지하는 것으로 간주합니다. 계약자는 이 Preview를 사용한 애플리케이션을 공개적으로 배포 또는 배송하지 않기로 동의합니다. 이 Preview는 공식 Android SDK가 출시된 이후에는 더 이상 지원되지 않기 때문입니다. - -5. 계약자의 개발자 자격 증명 - -5.1 계약자는 Google이 발급했거나 자신이 선택한 모든 개발자 자격 증명에 대한 기밀성을 유지할 책임이 있으며 계약자의 개발자 자격 증명 하에 개발된 모든 애플리케이션에 대한 전적인 책임이 있음에 동의합니다. - -6. 개인정보 보호정책 및 정보 - -6.1 Preview를 지속적으로 혁신하고 개선하기 위해, Google은 고유 식별자, 관련 IP 주소, 소프트웨어 버전 번호, Preview에서 사용 중인 도구 및/또는 서비스와 도구의 사용법에 대한 정보를 포함하되 이에 국한되지 않고 소프트웨어에서 특정 사용량 통계 정보를 수집할 수 있습니다. 그러한 정보를 수집하기 전에 Preview는 계약자에게 이를 통지하고 동의를 구할 것입니다. 계약자가 동의하지 않을 경우 정보를 수집하지 않습니다. - -6.2 수집된 데이터는 모두 취합된 형태로 Preview 개선을 위해 검토되며, Google의 개인정보 보호정책에 따라 유지 관리됩니다. 이 정보는 http://www.google.com/policies/privacy/를 참조하십시오. - -7. 제3자 애플리케이션 - -7.1 제3자가 개발한 애플리케이션을 실행하거나 제3자가 제공한 데이터, 콘텐츠 또는 리소스에 액세스하기 위해 Preview를 사용하는 경우, 계약자는 Google이 그러한 애플리케이션, 데이터, 콘텐츠 또는 리소스에 대한 책임이 없음에 동의합니다. 계약자는 그러한 제3자 애플리케이션을 통해 자신이 액세스한 모든 데이터, 콘텐츠 또는 리소스에 대한 책임은 그것을 만든 사람에게 있음에 동의합니다. 또한 계약자가 그러한 모든 제3자 애플리케이션, 데이터, 콘텐츠 또는 리소스를 사용하거나 액세스함으로써 비롯된 모든 피해나 손실에 대한 책임이 Google에게 없음에 동의합니다. - -7.2 그러한 제3자 애플리케이션을 통해 계약자에게 제공된 데이터, 콘텐츠 그리고 리소스는 그것을 제공한 제공자(또는 제공자를 대신하는 기타 개인 또는 기업)가 소유한 지적 재산권에 의해 보호될 수 있음을 유의해야 합니다. 그러한 데이터, 콘텐츠 또는 리소스(전부 또는 일부)를 수정, 임대, 리스, 대여, 판매, 배포하거나 이를 기반으로 파생물을 생성해서는 안 됩니다. 단, 관련 소유자로부터 그러한 작업을 수행해도 좋다는 허락을 받은 경우에는 예외입니다. - -7.3 계약자는 그러한 제3자 애플리케이션, 데이터, 콘텐츠 또는 리소스의 사용은 계약자와 관련 제3자 간에 체결하는 별도의 계약 조건의 적용을 받는다는 것을 인정합니다. - -8. Google API 사용 - -8.1 Google API - -8.1.1 Google에서 데이터를 검색하기 위해 API를 사용하는 경우, 그러한 데이터가 Google 또는 데이터를 제공하는 당사자(또는 당사자를 대신하는 기타 개인 또는 기업)가 소유한 지적 재산권에 의해 보호될 수 있음을 인정합니다. 그러한 API를 사용하는 경우, 추가적인 서비스 약관의 적용을 받을 수 있습니다. 관련 서비스 약관에 허용되지 않은 한, 그러한 데이터(전부 또는 일부)를 변경, 임대, 리스, 대여, 판매, 배포하거나 이를 기반으로 파생물을 생성해서는 안 됩니다. - -8.1.2 Google에서 사용자 데이터를 검색하기 위해 API를 사용하는 경우, 계약자는 사용자로부터 명시적인 동의를 얻은 경우에 한하여, 그리고 해당 사용자가 허용한 범위 내의 한정된 목적으로만 데이터를 검색해야 합니다. - -9. 라이선스 계약 종료 - -9.1 본 라이선스 계약은 계약자 또는 Google에 의해 아래와 같은 조건 하에 종료될 때까지 계속 적용됩니다. - -9.2 계약자가 라이선스 계약을 종료하고자 하는 경우, Preview 및 관련 개발자 자격 증명 일체의 사용을 중단하는 것으로 그러한 의사를 피력할 수 있습니다. - -9.3 Google은 언제든 이유 여하를 불문하고 계약자에게 통고하여 라이선스 계약을 종료할 수 있습니다. - -9.4 본 라이선스 계약은 통보 또는 여타의 행위 없이도 자동으로 종료됩니다. 이에 해당되려면 다음과 같은 조건이 수반되어야 합니다. -(A) Google이 계약자가 거주하는 국가 또는 계약자가 서비스를 사용하는 지역에서 Preview 또는 Preview의 특정 부분 제공을 중지하는 경우 및 -(B) Google이 Android SDK의 최종 릴리스 버전을 발행하는 경우. - -9.5 본 라이선스 계약이 종료되면 라이선스 계약으로 계약자에게 허용한 라이선스가 취소되며, 이에 따라 계약자는 Preview 사용을 즉시 모두 중단해야 하고 제 10, 11, 12 및 14절의 조항이 기한 없이 유지됩니다. - -10. 면책 조항 - -10.1 계약자는 Preview 이용에 대한 위험 부담이 전적으로 본인에게 있으며, Google이 일체의 보증 없이 Preview를 "있는 그대로" 그리고 "이용 가능한" 상태로 제공한다는 것을 분명히 이해하고 동의합니다. - -10.2 Preview 이용 및 이용 과정에서 다운로드하거나 얻게 되는 모든 자료를 사용하는 것은 본인의 재량에 따르며 이에 대한 위험 부담이 전적으로 본인에게 있으며, 그러한 사용으로 인해 발생하는 컴퓨터 시스템 또는 다른 기기의 손상 또는 데이터 손실에 대한 책임은 전적으로 본인에게 있습니다. 전술한 조항을 제한하지 않는 범위 내에서 계약자는 미리 보기가 안정된 릴리스가 아니며 오류, 결함 및 보안 취약성이 포함되어 있을 수 있어 그 결과로 중대한 손상을 유발할 수 있다는 점을 이해하는 것으로 간주합니다. 여기에는 계약자의 컴퓨터 시스템 또는 기타 기기의 완전하고 돌이킬 수 없는 손실도 포함됩니다. - -10.3 더 나아가, Google은 상품성, 특정 목적에 대한 적합성 및 비침해의 묵시적 보증 등을 포함하되 이에 국한되지 않고 명시적이든 묵시적이든 모든 종류의 보증 및 조건을 명시적으로 부인합니다. - -11. 책임 한계 - -11.1 계약자는 계약자에게 발생할 수 있는 직접, 간접, 부수적, 특별, 결과적 또는 징벌적 손해에 대해 그 어떤 책임 이론에 근거해서도 Google, 해당 자회사, 계열사 및 사용 허가자가 어떠한 책임도 지지 아니함을 분명히 이해하고 동의합니다. 이러한 손해에는 Google 또는 해당 대리자가 이러한 손실 발생 가능성에 대해 통지를 받았거나 이러한 사항을 인식했는지에 상관없이 모든 데이터 손실이 포함됩니다. - -12. 면책 - -12.1 법률에 의해 허용되는 최대한의 범위 안에서 계약자는 (a) 미리 보기 사용, (b) 계약자가 미리 보기에서 개발한 일체의 애플리케이션에서 초래된 모든 사람의 저작권, 상표, 영업비밀, 트레이드 드레스, 특허 또는 기타 지적 재산권의 침해, 또는 어떤 사람의 명예를 훼손하거나 초상권 또는 개인정보 보호정책을 침해함 또는 (C)계약자 본인이 본 라이선스 계약을 위반함으로써 발생하거나 생기는 모든 청구, 조치, 소송 또는 절차, 그리고 모든 손실, 책임, 손해, 경비(합리적인 변호사 비용 포함)로부터 Google을 옹호하고, 면책시키고, Google이 손해를 입지 않도록 하는 데 동의합니다. - -13. 라이선스 계약 변경 - -13.1 미리 보기의 새로운 버전을 배포할 때, Google은 본 라이선스 계약의 내용을 변경할 수 있습니다. 그러한 변경이 이뤄진 경우, Google은 미리 보기가 제공되는 웹사이트에 새로운 라이선스 계약 버전을 게재할 것입니다. - -14. 일반 법적 조건 - -14.1 본 라이선스 계약은 계약자와 Google 간의 모든 법적 계약을 구성하며, 계약자의 미리 보기 사용을 규제하고(별도의 서면 계약을 통해 Google이 계약자에게 제공하는 모든 서비스는 제외), 미리 보기와 관련하여 이전에 계약자와 Google이 맺은 모든 계약을 완전히 대체합니다. - -14.2 계약자는 Google이 라이선스 계약에 포함된(또는 관련 법률에 의해 Google이 향유하는) 법적 권리 또는 구제수단을 행사하거나 집행하지 않더라도, Google이 권리를 공식적으로 포기한 것으로 간주하지 않으며, Google이 계속해서 그러한 권리 또는 구제수단을 이용할 수 있음에 동의합니다. - -14.3 본 라이선스 계약의 조항이 무효라고 이 사안에 관한 판결을 할 수 있는 관할권을 가진 법원이 판결할 경우, 그 조항은 라이선스 계약의 나머지 조항에 영향을 미치지 않는 형태로 라이선스 계약에서 제거됩니다. 본 라이선스 계약의 나머지 조항은 여전히 유효하며 집행 가능합니다. - -14.4 계약자는 Google이 모회사가 되는 회사 그룹에 속한 각 회사가 본 라이선스 계약의 제3수익자이며, 그러한 다른 회사들이 그들에게 이익(또는 유리한 권리)을 부여하는 본 라이선스 계약의 모든 조항을 직접 행사하고 적용할 수 있는 권리를 가진다는 데 동의합니다. 그 외에는 다른 어떤 개인이나 회사도 본 라이선스 계약의 제3수익자가 될 수 없습니다. - -14.5 수출 규제. Preview는 미국의 수출법과 규정의 적용을 받습니다. 계약자는 Preview에 적용되는 모든 국내 및 국제 수출법과 규정을 준수해야 합니다. 그러한 법에는 수출 대상국, 최종 사용자 및 최종 용도에 대한 제한이 포함됩니다. - -14.6 계약자 또는 Google은 상대 당사자의 사전 서면 승인 없이 본 라이선스 계약에서 부여된 권리를 제3자에게 양도하거나 이전할 수 없으며, 그러한 승인 없이 이루어진 양도 시도는 모두 무효입니다. 계약자는 Google의 사전 승인 없이 본 라이선스 계약 상의 책임 또는 의무를 위임할 수 없습니다. - -14.7 본 라이선스 계약, 그리고 본 라이선스 계약 상의 계약자와 Google의 관계는 법률 조항 간의 충돌과는 무관하게 캘리포니아주법에 의한 규제를 받습니다. 계약자와 Google은 본 라이선스 계약으로부터 발생하는 모든 법적 문제 해결을 캘리포니아주 산타 클라라(Santa Clara) 카운티 내에 소재한 전속 관할 법원에 의뢰하는 것에 동의합니다. 위 규정에도 불구하고, 계약자는 Google이 여전히 모든 관할권에서 강제 구제책(또는 동등한 유형의 긴급 법적 구제)을 신청할 수 있음에 동의합니다. - - -
      \ No newline at end of file diff --git a/docs/html-intl/intl/ko/preview/overview.jd b/docs/html-intl/intl/ko/preview/overview.jd deleted file mode 100644 index 0b1441396110bcd6149f0d84ba8a1aac42b90072..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/overview.jd +++ /dev/null @@ -1,440 +0,0 @@ -page.title=프로그램 개요 -page.metaDescription=앱에서 차기 버전의 Android를 사용할 수 있도록 준비하세요. -page.image=images/cards/card-n-overview_2x.png -meta.tags="preview", "developer", "android" -page.tags="preview", "developer", "android" - -@jd:body - - -

      - Android N Developer Preview에 오신 것을 환영합니다. 이 프로그램은 차기 버전의 Android에 대해 앱을 테스트하고 최적화하는 데 필요한 모든 것을 제공합니다. - - 이 프로그램은 무료이고, N Developer Preview 도구를 다운로드하기만 하면 바로 시작할 수 있습니다. - -

      - - - - - - - -
      -
      -
      -
      -
      - 하드웨어 및 에뮬레이터 이미지 -
      - -

      - 다양한 기기 또는 에뮬레이터에서 앱을 실행하고 테스트하세요. - -

      -
      - -
      -
      - 최신 플랫폼 코드 -
      - -

      - Preview 동안 월별 업데이트를 제공할 예정이며 따라서 여러분은 항상 최신 플랫폼 변경에 대해 테스트할 수 있습니다. -

      -
      - -
      -
      - 개발자 문제에 우선 순위 부여 -
      - -

      - Google에서는 처음 몇 주 동안 개발자가 보고한 문제에 우선 순위를 부여할 예정이므로, -가능한 빨리 테스트하고 피드백을 보내 주세요. -

      -
      - -
      - -
      - - -
      -
      - 새로운 동작 및 기능 -
      - -

      - 새로운 플랫폼 동작을 지원하고 새로운 기능으로 개발하려면 작업을 일찍 시작하세요. -

      -
      - -
      -
      - OTA를 통한 업데이트 제공 -
      - -

      - Android 베타 프로그램을 통해 지원되는 모든 기기에 대해 원활한 OTA 업데이트가 제공됩니다. - 플래시가 필요 없습니다. -

      -
      - -
      -
      - 피드백 및 지원 -
      - -

      - Google의 Issue Tracker를 사용해 문제를 보고하고 피드백을 보내 주세요. - N 개발자 커뮤니티에서는 다른 개발자들과 의견을 주고받을 수 있습니다. - - -

      -
      -
      -
      -
      - - - -

      일정 및 업데이트

      - - -

      - N Developer Preview의 운영 기간은 2016년 3월 9일부터 2016년 3분기로 예정된 AOSP 및 OEM에 대한 Android N 최종 공개 릴리스 때까지입니다. - -

      - -

      - 개발 단계의 중요 마일스톤에 다다를 때마다 개발 및 테스트 환경을 위한 업데이트가 제공될 것입니다. - 일반적으로는 매월(4~6주 간격) 업데이트를 제공할 예정입니다. - 마일스톤은 다음과 같습니다. -

      - -
        -
      • Preview 1(최초 릴리스, 알파)
      • -
      • Preview 2(증분 업데이트, 알파)
      • -
      • Preview 3(증분 업데이트, 베타)
      • -
      • Preview 4(최종 API 및 공식 SDK, Play 게시)
      • -
      • Preview 5(최종 테스트를 위한 거의 최종 시스템 이미지)
      • -
      • AOSP 및 에코시스템에 최종 릴리스
      • -
      - -

      - 각 업데이트에는 SDK 도구, 프리뷰 시스템 이미지, 에뮬레이터, 참조 문서 및 API 차이 등이 포함됩니다. - -

      - -

      - 첫 3단계 프리뷰 마일스톤에서는 현재 앱의 호환성 문제를 확인하고 새 플랫폼을 대상으로 하는 데 필요한 마이그레이션 또는 주요 작업을 계획하는 데 도움이 되는 조기 테스트 및 개발 환경을 제공합니다. - - - 이 기간은 기능과 API 및 파일 호환성 문제에 대한 피드백을 제공하는 우선 순위 기간입니다. 이 모든 경우에 대해 Issue Tracker를 사용하세요. - - - 업데이트 과정에서 일부 API가 변경될 수 있습니다. -

      - -

      - Preview 4 및 5에서는 개발에 사용할 최종 N API 및 SDK와 최종 버전에 가까운 시스템 이미지에 액세스할 수 있으며, 시스템 동작과 기능을 테스트할 수 있습니다. - - 이 시점에서 Android N은 표준 API 레벨을 제공합니다. - 레거시 앱의 최종 호환성 테스트를 시작할 수 있으며 N API 또는 기능을 사용하는 새 코드를 개선할 수 있습니다. - -

      - -

      - 또한 Preview 4부터는 공식 API 레벨에서 Android N이 실행되는 기기(예: Android 베타 프로그램에 옵트인한 소비자 기기)에 앱을 게시할 수 있습니다. - - Google Play 알파 및 베타 채널에 먼저 게시할 수 있으므로, Play 스토어에 광범위하게 배포하기 전에 Android 베타 소비자를 통해 앱을 테스트할 수 있습니다. - - - -

      - -

      - Android N에서 테스트와 개발을 수행하는 동안, 프리뷰 업데이트가 출시되는 것에 맞춰 개발 환경을 최신 상태로 유지할 것을 적극 권장합니다. - - 이 과정을 손쉽게 진행하기 위해 테스트 기기를 Android 베타 프로그램에 등록하고 각 마일스톤에서 OTA 업데이트를 받을 수 있습니다. - - 또는 업데이트된 프리뷰 이미지를 수동으로 다운로드하고 플래시할 수도 있습니다. - -

      - -

      - 프리뷰 업데이트가 제공될 때마다 Android 개발자 블로그, 이 사이트 및 Android N 개발자 커뮤니티를 통해서 알려드릴 것입니다. - - -

      - - -

      N Developer Preview에 포함된 내용

      - -

      - N Developer Preview에는 -기존 앱을 다양한 화면 크기, 네트워크 기술, CPU/GPU 칩셋 -및 하드웨어 아키텍처에서 테스트하는 데 필요한 모든 것이 포함되어 있습니다. -

      - -

      SDK 도구

      - -

      이러한 구성 요소는 Android Studio에서 SDK Manager를 통해 다운로드할 수 있습니다.

      - -
        -
      • N Developer Preview SDK 및 도구 -
      • N Developer Preview 에뮬레이터 시스템 이미지(32비트 및 64비트) -
      • N Developer Preview Android TV용 에뮬레이터 시스템 이미지(32비트) -
      • N Developer Preview 지원 라이브러리(새로운 앱 템플릿용) -
      - -

      - 필요에 따라 각 마일스톤에서 이러한 개발 도구를 업데이트할 것입니다. -

      - -

      하드웨어 시스템 이미지

      - -

      - N Developer Preview에는 물리적 기기에서 테스트하고 개발할 때 사용할 수 있는 다른 하드웨어 시스템 이미지와 Nexus가 포함되어 있습니다. - 하드웨어 이미지의 전체 목록을 보려면 기기 이미지 페이지를 참조하세요. - -

      - -

      - 각 마일스톤 때마다 이들 기기에 대한 업데이트된 시스템 이미지가 제공될 것입니다. 업데이트된 시스템 이미지를 필요한 만큼 자주 다운로드하여 테스트 기기에 수동으로 플래시할 수 있습니다. - - 이것은 기기를 여러 번 다시 플래시해야 하는 자동화된 테스트 환경에 특히 유용합니다. - - -

      - -

      참고: - 수동으로 플래시된 기기는 지난 해 프리뷰와 마찬가지로 OTA 업데이트를 받지 못합니다. - 올해에는 Android 베타 프로그램에 기기를 등록해야만 OTA 업데이트를 받을 수 있습니다. 자세한 내용은 다음 섹션을 참조하세요. - -

      - -

      Android 베타 프로그램을 통한 OTA 업데이트

      - -

      - Android N에서는 프로그램에 등록한 기기에 Android N의 최신 프리뷰 업데이트를 자동으로 직접 전송해 주는 OTA(Over-the-Air) 업데이트 프로그램을 새로 도입했습니다. - - 이 프로그램은 무료이고 Google 계정에 등록된 지원 기기를 가지고 계신 사람이라면 누구나 사용할 수 있습니다. - -

      - -

      - 프로그램에 등록하려면 Android 베타 프로그램 사이트를 방문하세요. - 계정에 등록된 기기 중에서 Android 베타에 등록할 수 있는 기기를 모두 확인할 수 있습니다. - - -

      - -
        -
      1. Android N 업데이트를 받을 기기를 선택합니다. -
      2. Enroll을 클릭하고 사용 약관을 읽고 동의한 후, OK를 클릭합니다. -
      - -

      - 등록을 마치면 곧바로 기기에서 업데이트를 수신합니다. 대부분의 경우, Android N으로 전환하기 위해 데이터를 완전히 초기화할 필요는 없지만, 잃고 싶지 않은 데이터가 있다면 기기를 등록하기 전에 이 데이터를 백업하는 것이 좋습니다. - - - -

      - -

      - 업데이트가 기기에 전송되면, 가급적 빨리 업데이트를 다운로드하고 설치하는 것이 좋습니다. - 시스템 UI, 동작, API 및 기능의 최신 변경사항에 맞춰 기기를 최신으로 유지할 수 있습니다. - -

      - -

      - Developer Preview가 마무리되면, 귀하의 등록된 기기가 공식 Android N 릴리스 업데이트를 받게 됩니다. - -

      - -

      - Android 베타 사이트에서 언제든지 Android 베타 프로그램으로부터 기기 등록을 해제할 수 있습니다. - 등록을 해제하기 전에 기기에서 데이터를 백업하세요. - -

      - -

      참고: - 등록을 해제하면 Android 6.0 Marshmallow의 최신 버전(기기 등록 전에 설치한 버전이 아닐 수도 있음)으로 기기가 공장 초기화됩니다. - - - 클린 설치를 위해서 연락처, 메시지, 사진 등의 데이터가 기기에서 지워집니다. - - -

      - -

      문서 및 샘플 코드

      - -

      - Developer Preview 사이트에서 다음과 같은 문서 리소스를 이용할 수 있으며, -Android N에 대해 익히는 데 유용합니다. -

      - -
        -
      • Android -N용 개발 설정에는 -시작하는 데 필요한 단계별 지침이 포함되어 있습니다.
      • -
      • 동작 변경 사항에서는 테스트할 주요 영역을 알려줍니다. -
      • -
      • 새 API에 관련된 문서 중에는 API 개요, 다운로드 가능한 API 참조 그리고 다중 창 지원, 묶음 알림, 다중 로케일 지원 등과 같은 주요 기능에 대한 상세 개발자 가이드도 포함되어 있습니다. - - - -
      • 샘플 코드에서는 권한과 새로운 기타 기능을 지원하는 방법을 보여줍니다. - -
      • 릴리스 노트를 -보면 N Developer Preview의 현재 버전에 대한 변경 사항과 차이점 보고서 등 관련 정보를 -확인할 수 있습니다. -
      - -

      다운로드 가능한 API 참조

      - -

      - 초기 프리뷰 업데이트 중에, 최신 Android N 플랫폼용 API 참조를 별도의 zip 아카이브로 다운로드할 수 있습니다. - - 이 참조 다운로드에는 또한 API 23 및 이전 업데이트에서 API 변경사항을 확인하는 데 유용한 차이점 보고서도 포함되어 있습니다. - - -

      - -

      - Android N API가 최종 버전이고 공식 API 레벨이 할당되면, 저희가 https://developer.android.com에서 온라인으로 API 참조를 제공해 드릴 것입니다. - -

      - -

      - 지원 리소스 -

      - -

      - N Developer Preview에서 테스트와 개발을 수행하면서 다음 채널을 활용하여 문제를 보고하고 피드백을 제공해 주세요. - -

      - -
        -
      • N Developer Preview Issue Tracker기본 피드백 채널입니다. - Issue Tracker를 통해 버그, 성능 문제 및 전반적인 피드백을 보고할 수 있습니다. - 또한, 알려진 문제를 확인하고 해결 방법을 찾을 수 있습니다. - - 여러분이 보고한 문제가 분류되어 Android 엔지니어링 팀에게 검토하도록 보내질 때마다 알림을 받으실 것입니다. -
      • -
      • Android N 개발자 커뮤니티는 -일종의 Google+ 커뮤니티로, -여기에서 여러분은 Android N으로 작업하는 다른 개발자들과 소통할 수 있습니다. 서로의 의견이나 아이디어를 나누고 Android N 관련 질문에 대한 대답을 찾을 수도 있습니다. -저희는 커뮤니티를 조정하고 필요에 따라 답변과 지침을 -제공할 것입니다.
      • -
      - -

      대상 지정, 프리뷰 API 및 게시

      - -

      - N Developer Preview에서는 표준 API 레벨이 없는 개발 전용 시스템 및 Android -라이브러리를 제공합니다. 앱을 테스트하기 위해 호환성 동작에서 옵트아웃하려는 경우(적극 권장), Android N의 프리뷰 버전을 대상으로 지정하면 됩니다. 앱의 targetSdkVersion“N”으로 지정하세요. - - - - -

      - -

      - Android N Developer Preview에서는 프리뷰 API를 제공합니다. 이 API는 최종 SDK가 출시될 때까지는 공식 버전이 아닙니다. 현재 최종 SDK 릴리스는 2016년 3분기로 예정되어 있습니다. - - 즉, 시간이 지나면서 특히 프로그램 시작 후 초기 몇 주 동안에는 사소한 API 변경이 있을 수 있습니다. - - Android N Developer Preview를 업데이트할 때마다 변경 사항을 요약하여 제공해 드릴 것입니다. - -

      - -

      - 참고: 프리뷰 API는 변경될 수 있지만, 기본 시스템 동작은 안정적이며 지금 바로 테스트가 가능한 상태입니다. - - -

      - -

      - Google Play에서는 N Developer Preview를 대상으로 하는 앱의 게시를 금지합니다. - Android N 최종 SDK를 사용할 수 있게 되면 공식 Android N API 레벨을 대상으로 지정하고, 알파 및 베타 릴리스 채널을 통해 Google Play에 앱을 게시할 수 있습니다. - - 그때까지는 Android N을 대상으로 하는 앱을 테스터에게 배포하려는 경우, 이메일이나 여러분의 사이트에서 직접 다운로드를 통해 하면 됩니다. - - -

      - -

      - AOSP 및 OEM에 대한 Android N 전체 릴리스는 2016년 3분기로 예정되어 있습니다. 이때 Android N을 대상으로 하는 여러분의 앱을 Google Play의 공개 릴리스 채널에 게시할 수 있습니다. - - -

      - - -

      시작 방법

      - -

      - Android N으로 앱 테스트를 시작하려면: -

      - -
        -
      1. API 개요동작 변경 사항을 검토하여 새로운 사항과 이 사항이 여러분의 앱에 미치는 영향을 파악합니다. - - 특히, 새로운 알림 기능과 다중 창 지원에 대해 알아봅니다. - -
      2. -
      3. Preview SDK 설정 및 테스트 기기 구성 지침에 따라 자신의 환경을 설정합니다. -
      4. -
      5. 플래시 -지침에 따라 자신의 기기용 최신 Android N Developer Preview 시스템 이미지를 플래시합니다.
      6. -
      7. API 참조와 -Android N 샘플을 검토하여 새로운 API 기능과 앱에서 -그러한 기능을 사용하는 방법에 대해 좀 더 자세히 파악합니다. -
      8. Android N 개발자 -커뮤니티에 가입하여 최신 소식을 알아보고, 새 플랫폼으로 작업하는 -다른 개발자들과 이야기를 나눕니다.
      9. -
      - -

      - Android N Developer Preview 프로그램에 참가해 주셔서 대단히 감사합니다! -

      diff --git a/docs/html-intl/intl/ko/preview/preview_toc.cs b/docs/html-intl/intl/ko/preview/preview_toc.cs deleted file mode 100644 index 116b8556cad9b23585df269a839f3f406344afdb..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/preview_toc.cs +++ /dev/null @@ -1,75 +0,0 @@ - \ No newline at end of file diff --git a/docs/html-intl/intl/ko/preview/setup-sdk.jd b/docs/html-intl/intl/ko/preview/setup-sdk.jd deleted file mode 100644 index 03727a3320dbe48b67b7d9bbdf21cb0bd8cc644a..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/setup-sdk.jd +++ /dev/null @@ -1,187 +0,0 @@ -page.title=Preview 설정 -meta.keywords="preview", "android" -page.tags="preview", "developer preview" -page.image=images/cards/card-n-sdk_2x.png - -@jd:body - - - - -

      Android N Preview용 앱을 개발하려면, 이 페이지의 설명에 따라 -개발자 환경을 약간 업데이트해야 합니다.

      - -

      Android N 시스템 이미지에서 앱의 호환성을 간단히 -테스트하려면, 가이드에 따라 Android N 기기에서 테스트를 수행하세요.

      - - - - -

      Android Studio 2.1 가져오기

      - -

      Android N 플랫폼에는 Java 8 언어 기능에 대한 지원이 추가되었으며, 여기에는 Jack이라는 새 컴파일러가 필요합니다. - 현재는 Android Studio 2.1에서만 최신 버전의 Jack이 지원됩니다. 따라서 Java 8 언어 기능을 사용하려면, Android Studio 2.1을 사용하여 앱을 빌드해야 합니다. - - - 그렇지 않은 경우, Jack 컴파일러를 사용할 필요가 없지만 Android N 플랫폼에 대해 컴파일하려면 아래의 설명에 따라 JDK 8로 업데이트해야 합니다. - -

      - -

      Android Studio가 이미 설치된 경우 Help > Check for Update(Mac의 경우, Android Studio > Check for Updates)를 클릭하여 Android Studio 2.1 이상이 설치되어 있는지 확인해야 합니다. - -

      - -

      설치되어 있지 않은 경우 여기서 Android Studio 2.1을 다운로드하세요. -

      - - -

      N Preview SDK 가져오기

      - -

      Android N API를 사용한 개발을 시작하려면, 다음과 같이 Android N Preview SDK를 Android Studio에 설치해야 합니다. -

      - -
        -
      1. Tools > Android > SDK Manager를 클릭하여 SDK Manager를 엽니다. -
      2. - -
      3. SDK Platforms 탭에서 Android N Preview 체크박스를 선택합니다. -
      4. - -
      5. SDK Tools 탭을 클릭한 다음, -Android SDK Build Tools, Android SDK -Platform-Tools, Android SDK Tools 체크박스를 -선택합니다. -
      6. - -
      7. OK를 클릭한 다음, 설치해야 하는 패키지의 -사용권 계약에 동의합니다. -
      8. -
      - -

      N Preview 참조 문서 가져오기

      - -

      - Android N API에 대한 자세한 내용은 N Preview 참조 문서에서 볼 수 있으며, 이 문서는 다음 표에서 다운로드할 수 있습니다. - - 이 패키지에는 요약된 오프라인 버전의 Android 개발자 웹사이트가 포함되어 있고, Android N API용의 업데이트된 API 참조 문서와 API 차이점 보고서가 포함되어 있습니다. - - -

      - - - - - - - - - - -
      문서체크섬
      - n-preview-3-docs.zip - MD5: 19bcfd057a1f9dd01ffbb3d8ff7b8d81
      - SHA-1: 9224bd4445cd7f653c4c294d362ccb195a2101e7 -
      - - - -

      Java 8 JDK 가져오기

      - -

      Android N 플랫폼에 대해 앱을 컴파일하고 Android Studio 2.1에서 일부 도구를 사용하려면 Java 8 개발자 키트(JDK 8)를 설치해야 합니다. - 따라서 아직 최신 버전이 없는 경우, 지금 JDK 8을 다운로드하세요. -

      - -

      그런 다음 Android Studio에서 다음과 같이 JDK 버전을 설정합니다.

      - -
        -
      1. Android Studio에서 Android 프로젝트를 열고 File > Project Structure를 선택하여 Project Structure 대화 상자를 엽니다. - - (또는, File > Other Settings > Default Project Structure를 선택하여 모든 프로젝트에 대해 기본값을 설정할 수 있습니다.) - - -
      2. -
      3. 대화 상자의 왼쪽 패널에서 SDK Location을 클릭합니다. -
      4. -
      5. JDK Location 필드에, -Java 8 JDK의 위치를 입력한 다음(오른쪽의 버튼을 클릭하여 -파일 탐색), OK를 클릭합니다. -
      6. -
      - - - - -

      프로젝트 업데이트 또는 생성

      - -

      - Android N API를 사용하려면, 프로젝트를 적절하게 구성해야 합니다. -

      - -

      Java 8 언어 기능을 사용할 계획인 경우에는, -Java 8 언어 기능에서 지원되는 Java 8 기능과 -Jack 컴파일러로 프로젝트를 구성하는 방법에 대해서도 -읽어봐야 합니다.

      - - -

      기존 프로젝트 업데이트

      - -

      자신의 모듈에 대한 -build.gradle파일을 열고 다음과 같이 값을 -업데이트합니다. -

      - -
      -android {
      -  compileSdkVersion 'android-N'
      -  buildToolsVersion '24.0.0-rc3'
      -  ...
      -
      -  defaultConfig {
      -     minSdkVersion 'N'
      -     targetSdkVersion 'N'
      -     ...
      -  }
      -  ...
      -}
      - - -

      새 프로젝트 생성

      - - -

      Android N Preview SDK를 사용한 개발에서 새 프로젝트를 만들려면:

      - -
        -
      1. File > New Project를 클릭하고 -Target Android Devices 페이지가 나올 때까지 단계를 따릅니다. -
      2. -
      3. 이 페이지에서 Phone and Tablet 옵션을 선택합니다.
      4. -
      5. Phone and Tablet 옵션 아래의 Minimum -SDK 옵션 목록에서 -N: Android API 23, N Preview (Preview)를 선택합니다.
      6. -
      - - -

      다음 단계

      - - - diff --git a/docs/html-intl/intl/ko/preview/support.jd b/docs/html-intl/intl/ko/preview/support.jd deleted file mode 100644 index 3f8372172eaf76ab7b787ef6d3e941d5ff6bd47a..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/ko/preview/support.jd +++ /dev/null @@ -1,1188 +0,0 @@ -page.title=지원 및 릴리스 노트 -meta.keywords="preview", "android" -page.tags="preview", "developer preview" -page.image=images/cards/card-n-support_2x.png - -@jd:body - - - - -

      - Android N Developer Preview를 사용하여 개발과 테스트를 수행할 때 두 가지 기본 지원 채널을 사용할 수 있습니다. - 기기별 버그, 시스템 버그 및 Google 앱 버그의 경우 https://developer.android.com/preview/bug에 버그를 제출하세요. - 기타 앱의 문제는 개발자에게 직접 문의하세요. - -

      - -

      Android N을 사용하는 다른 개발자들과 문제 또는 아이디어를 논의하려면 Developer Preview Google+ 커뮤니티에 가입하세요. -

      - -

      Developer Preview 3

      - -
      -
      -
      -

      - 날짜: 2016년 5월
      - 빌드: NPD35K
      - 에뮬레이터 지원: x86 및 ARM(32비트/64비트)
      - Google Play 서비스: 8.4
      -

      -
      -
      -
      - -

      일반 권고 사항

      - -

      - 이 Developer Preview 릴리스는 앱 개발자 및 기타 얼리 어댑터를 위한 것이며, 일상적인 용도로 사용하거나, 개발 또는 호환성 테스트에 사용할 수 있습니다. - - 이 릴리스에 대한 다음과 같은 일반적인 참고 사항을 숙지하시기 바랍니다. - -

      - -
        -
      • 이 릴리스에서는 지원되는 기기에서 다양한 안정성 문제가 있을 수 있습니다. - 사용자는 커널 패닉 및 작동 중단 등의 시스템 불안정 문제를 겪을 수 있습니다. - -
      • - -
      • 일부 앱의 경우 새로운 플랫폼 버전에서 예상과 다르게 작동할 수 있습니다. - 여기에는 Google 앱뿐만 아니라 다른 앱도 포함됩니다. -
      • - -
      • Developer Preview 3는 Nexus 5X, Nexus 6, Nexus 6P 및 Pixel C 기기에서 CTS(Compatibility Test Suite) 승인을 받았습니다. - CTS 승인 빌드를 사용하는 앱은 이들 기기에서 정상적으로 작동해야 합니다(예: Android Pay). - - -
      • - -
      • Developer Preview 3는 지원되는 모든 기기에서 사용할 수 있습니다. - 이러한 기기로는 Nexus 5X, Nexus 6, Nexus 6P, Nexus 9, Nexus Player, Pixel C, General Mobile 4G(Android One) 뿐만 아니라 Sony Xperia Z3(D6603 및 D6653 모델)가 포함됩니다. - - - -
      • -
      - - -

      DP3의 새로운 기능

      - -

      Android용 VR 모드

      - -

      - Android N에서는 개발자가 사용자를 위한 고품질 모바일 VR 환경을 만들 수 있도록 새로운 VR 모드에 대한 플랫폼 지원과 최적화 기능을 추가했습니다. - VR 앱 전용 CPU 코어에 대한 액세스를 비롯하여, 다수의 성능 개선 사항이 있습니다. - - 지능적 머리 추적과 VR용으로 작동하는 스테레오 알림 기능을 앱 내에서 이용할 수 있습니다. - 가장 중요한 점은, 지연 시간이 매우 짧은 그래픽을 Android N이 제공한다는 사실입니다. - -

      - -

      - 자세한 내용은 Android용 Google VR SDK를 참조하세요. -

      - -

      지속적인 성능 모드

      - -

      - Android N에는 지속적인 성능 모드를 위한 지원 기능(선택 사항)이 포함되어 있으며, 이 모드를 통해 OEM들은 장시간 실행되는 애플리케이션의 기기 성능에 대한 힌트를 제공할 수 있습니다. - - 앱 개발자는 이런 힌트를 사용하여 장기간에 걸쳐 기기 성능을 예측 가능하고 일관된 수준으로 유지하기 위해 애플리케이션을 적절히 조정할 수 있습니다. - - 앱 개발자는 Developer Preview에 있는 이 새 API를 Nexus 6P 기기에서만 시험해 볼 수 있습니다. - -

      - -

      Multiprocess WebView

      - -

      - Android N의 버전 51부터는 개발자 옵션 "Multiprocess WebView"가 활성화된 경우, WebView는 별도의 샌드박싱된 프로세스에서 웹 콘텐츠를 실행합니다. - - WebView 팀은 향후 Android 버전에서 Multiprocess WebView를 지원하기 전에 N에서의 호환성 및 런타임 성능에 대한 피드백을 기다리고 있습니다. - - 이 버전에서는 시작 시간, 총 메모리 사용량 및 소프트웨어 렌더링 성능에 관련된 성능 저하가 예상됩니다. - -

      - -

      - 다중 프로세스 모드에서 예상치 못한 문제를 발견할 경우 이에 대해 알려주시기 바랍니다. - 버그 제출을 통해 WebView 팀에 연락하세요. - -

      - -

      Keyboard Shortcuts Helper

      - -

      - Android N에서는 사용자가 Meta+/ 키를 눌러 Keyboard Shortcuts 화면을 트리거할 수 있으며, 이 화면에는 시스템과 해당 앱에서 둘다 사용할 수 있는 모든 바로 가기가 표시됩니다. - - 개발자는 자신의 바로 가기를 추가하거나 앱에서 Shortcuts 화면을 트리거할 수 있습니다. - 자세한 내용은 Keyboard Shortcuts Helper를 참조하세요. - -

      - -

      FrameMetrics API

      - -

      - DP3에서는 새로운 FrameMetrics API를 추가했으며, 이를 통해 앱은 애플리케이션의 현재 창에 대한 프레임 타이밍 정보를 전송하기 위해 스트리밍 PubSub API를 노출함으로써 앱의 UI 렌더링 성능을 모니터링할 수 있습니다. FrameMetricsListener를 사용하면 USB 연결 없이 프로덕션 환경에서 상호 작용 수준의 UI 성능을 더욱 정밀하게 측정할 수 있습니다. - - - - - -

      - -

      기능 및 API 변경 사항

      - -
      -
      - 런처 바로 가기 및 런처 바로 가기 API -
      - -
      - 이 기능은 향후 Android 릴리스로 미루기로 결정되었습니다. 차기 Developer Preview부터는 런처 바로 가기 API(ShortcutManager 등)가 공개 Android N API에서 삭제될 계획입니다. - - -
      - -
      - 페이지 로드 전에 WebView Javascript 실행 -
      - -
      - Android N을 대상으로 하는 앱부터는 새 페이지가 로드될 때 Javascript 컨텍스트가 초기화됩니다. - 현재는 새 {@link android.webkit.WebView} 인스턴스에 로드된 첫 페이지에 대해 컨텍스트가 이월됩니다. - - Javascript를 {@link android.webkit.WebView}에 삽입하려는 개발자는 페이지 로드가 시작된 후에 스크립트를 실행해야 합니다. - - -
      - -
      - 비보안 출발지에서의 WebView Geolocation -
      - -
      - Android N을 대상으로 하는 앱부터는 보안 출발지(HTTPS를 통함)에서만 Geolocation API가 허용됩니다. - 이 정책은 사용자가 비보안 연결을 사용하는 경우 사용자의 개인 정보를 보호할 목적으로 설계되었습니다. - -
      - -
      - Data Saver -
      - -
      - Developer Preview 3부터는 앱이 인텐트를 사용하여 시스템 대화 상자를 표시할 수 있습니다. 사용자는 이 대화 상자를 통해 Data Saver 면제 허용 목록에 앱을 직접 추가할 수 있습니다. - - 자세한 내용은 Data Saver 문서를 참조하세요. - -
      - -
      - 번호 차단 -
      - -
      - 권한 없는 사용자가 번호를 차단하거나 차단 해제하려고 시도하면 이제 {@link java.lang.SecurityException}이 발생하고 작업이 실패합니다. - (이전에는 작업에서 {@link java.lang.UnsupportedOperationException}을 발생시켰습니다.) - -
      - -
      - Quick Settings 타일 API - -
      - -
      - 이제 시스템에서는 액티비티의 메타데이터를 사용하여 타일 모드를 결정합니다. - (이전에는 TileService.onTileAdded()의 반환 값으로 타일 모드가 결정되었습니다.) - 자세한 내용은 다운로드 가능한 API 참조에서 TileService.META_DATA_ACTIVE_TILE을 참조하세요. - -
      -
      - -

      개발자가 보고한 문제의 수정 사항

      - -

      - 다음을 비롯하여 개발자가 보고한 여러 문제가 수정되었습니다. -

      - -
        -
      • 노래가 하나 끝난 후 블루투스 오디오 재생이 중단됨(버그 206889) -
      • - -
      • Pixel C가 지속적으로 작동 중단됨(버그 206962) -
      • - -
      • 시계 및 알림 메시지의 알림 문제(버그 203094) -
      • - -
      • USB C 케이블을 통해 MacBook Pro에 연결된 경우 Pixel C가 재부팅됨(버그 205432) - -
      • - -
      • 캘린더가 하루 오프셋됨(버그 203002) -
      • - -
      • TelephonyManager.getAllCellInfo가 잘못된 데이터를 반환함(버그 203022) -
      • - -
      • Nexus 6P, 블루투스의 연결이 계속 끊김(버그 208062) -
      • -
      - -

      수정된 문제의 전체 목록을 보려면 Issue Tracker를 참조하세요. -

      - -

      알려진 문제

      - -

      접근성

      - -
        -
      • 피치가 최대 수준에 가깝게 설정된 경우 TTS 출력을 들을 수 없습니다. -
      • - -
      • 확대 제스처 및 설정을 비롯한 접근성 기능 및 설정은 사용자가 작업 프로필을 추가하는 경우 중단될 수 있습니다. - 접근성 상태는 사용자가 관련 설정을 다음 번에 터치할 때 복구됩니다. - -
      • -
      - -

      카메라

      - -
        -
      • 카메라 앱이 불안정한 작동을 보였습니다. 이 앱은 다양한 경우(예: 다중 창 모드에서 실행되는 경우) 작동이 중단될 수 있습니다. - -
      • - -
      • 파노라마 모드에서 셔터를 계속해서 누르면 카메라 앱의 작동이 중단될 수 있습니다. - -
      • -
      - -

      오디오

      -
        -
      • 플랫폼의 오디오 플레이어 문제로 인해 일부 앱이 정상적으로 작동하지 않습니다. - 예를 들어, Skype 및 기타 앱이 이 문제의 영향을 받습니다. -
      • -
      - -

      연결

      - - -
        -
      • 블루투스 저전력(Bluetooth Low Energy, BLE) 주변 역할 기기가 서비스를 알리고 있는데 BLE 중앙 역할 기기가 연결되면, 주변 역할 기기가 즉각적으로 연결을 해제합니다. - - -
      • - -
      • 화면이 꺼지면 Wi-Fi 연결이 끊길 수 있습니다. -
      • - -
      • RFCOMM 연결이 불안정하며, 이로 인해 데이터 손상 및 연결 자주 끊김이 발생할 수 있습니다. - -
      • - -
      • 일부 제한된 백그라운드 시나리오 중에, 활성 네트워크 상태({@link android.net.NetworkInfo#getState NetworkInfo.getState()} 및 {@link android.net.NetworkInfo#getDetailedState NetworkInfo.getDetailedState()})가 잘못된 값을 반환할 수 있습니다. - - - -
      • -
      - - -

      - 런처 -

      - -
        -
      • 화면이 꺼졌다가 켜진 후 기본 런처의 All Apps 트레이가 응답하지 않을 수 있습니다. - 홈 화면으로 돌아간 후 All Apps 트레이를 다시 실행하면 이 문제가 해결될 수 있습니다. - -
      • -
      - -

      - 키보드 -

      - -
        -
      • Android 6.0 이전 버전이 실행되는 기기를 N Developer Preview로 업데이트하는 경우, Google 키보드가 최신 그림 이모티콘 및 소리 설정과 같은 기본 설정 데이터를 유지하지 않습니다. - - -
      • - -
      • Google Indic Managed Keyboard는 불안정할 수 있습니다. -
      • - -
      • 비밀번호 필드에 텍스트를 입력할 때 사용자가 러시아어를 입력 언어로 선택할 수 있지만 키보드는 계속 영어를 유지합니다. - 이로 인해 사용자가 러시아어 언어로 암호를 입력할 수 없습니다. - -
      • -
      - -

      - 로케일 및 언어 -

      - -
        -
      • 오른쪽에서 왼쪽으로 읽기(RTL) 로케일을 사용하는 경우, 기기를 재시작한 후 예기치 않게 왼쪽에서 오른쪽으로 읽기(LTR) 표시로 시스템이 전환될 수 있습니다. - -
      • -
      - -

      미디어

      - -
        -
      • HD 비디오 재생 문제를 비롯하여, Nexus 9 및 Nexus Player에서 미디어 재생이 불안정할 수 있습니다. - -
      • -
      - -

      - 다중 창 모드 -

      - -
        -
      • 다중 창 모드에서 방향을 변경하면 기기가 작동을 멈출 수 있습니다. -
      • - -
      • 현재 여러 앱에서 다중 창 모드와 관련하여 문제가 있습니다. -
          -
        • Settings > Display > Screen brightness를 다중 창에 도킹하면 시스템 UI의 작동이 중단될 수 있습니다. - -
        • - -
        • 카메라 앱을 다중 창 모드에서 실행하면 작동이 중단될 수 있습니다. -
        • - -
        • YouTube를 다중 창 모드에서 실행하면 작동이 중단될 수 있습니다. Storage > Apps > YouTube에서 YouTube 앱 데이터를 지워서 이 문제를 수정할 수 있습니다. - - -
        • -
        -
      • -
      - -

      - Google Play 서비스 -

      - -
        -
      • Google Play 서비스를 통해 Google Cast를 사용하는 앱의 경우, ASCII 범위에 속하지 않는 글자 및 숫자를 사용하는 시스템 로케일을 사용자가 선택하면 앱이 불안정해질 수 있습니다. - - -
      • -
      - -

      - Android for Work 및 Google Apps Device Policy -

      - -
        -
      • 사용자가 "device policy status" 화면이 고정된 상태로 기기의 잠금을 해제할 경우, Device Policy 앱의 작동이 중단될 수 있습니다. - -
      • - -
      • 파일 기반 암호화가 설정된 채로 작업 프로필을 설정하고, Work를 끈 후에 사용자가 다시 한 번 더 기본 프로필 화면 잠금을 해제하여 Work 앱에 액세스해야 합니다. - - -
      • - -
      • 보안 패턴 잠금을 제거하고 업무용 앱/개인 앱을 다중 창에서 열면 기기가 재부팅됩니다. - -
      • - -
      • DISALLOW_VPN_CONFIG를 설정하면 Device Policy Client에 의해 설정되는 상시 접속 VPN 모드에 동의 대화 상자가 나타납니다. - -
      • - -
      • VPN이 상시 접속 VPN 모드에서 연결될 때까지는 트래픽이 잠기지 않습니다. -
      • -
      - -

      - 외부 저장소 -

      - -
        -
      • 사용자가 앱을 내부 저장소에서 채택 가능 외부 저장소(SD 카드 또는 USB를 통해 연결된 기기 포함)로 이동하면 앱이 불안정해질 수 있습니다. - - -
      • -
      - -

      - Google Play에서의 화면 확대/축소 및 다중 APK -

      - -
        -
      • Android N이 실행되는 기기에서 Google Play 서비스 9.0.83은 안정적인 화면 밀도 대신 현재 화면 밀도를 잘못 보고합니다. - 이러한 기기에서 화면 확대/축소가 활성화된 경우, 이로 인해 Google Play는 더 작은 화면용으로 설계된 다중 APK 앱의 버전을 선택할 수가 있습니다. - - 이 문제는 차기 버전의 Google Play 서비스에서 수정되었으며, 나중에 Developer Preview 릴리스에 포함될 것입니다. - - -
      • - -
      • Android N이 실행되는 기기에서 현재 Google Play 서비스 9.0.83은 Vulkan 버전이 아닌 Vulkan 지원을 보고합니다. - 이로 인해 Google Play는 더 높은 버전이 지원되는 기기에서 더 낮은 Vulkan 지원용으로 설계된 다중 APK 앱의 버전을 선택할 수가 있습니다. - - 현재 Google Play Store에서는 Vulkan 버전 대상 지정을 사용하는 앱의 업로드를 허용하지 않습니다. - 이 지원은 향후에 Google Play Store에 추가될 예정이고 차기 버전의 Google Play 서비스에서 수정되어 나중에 Developer Preview 릴리스에 포함될 것입니다. Google Play 서비스 9.0.83 버전을 사용하는 모든 N 기기는 기본 Vulkan 지원을 대상으로 하는 앱의 버전을 계속해서 수신합니다. - - - - -
      • -
      - -

      알림

      - -
        -
      • MessagingStyle에서는 "null"(본인 자신) 발신자인 알림을 표시하지 않습니다. -
      • -
      - -

      개발자 도구

      - -
        -
      • - JDWP 디버깅을 사용하는 중에 adb의 연결이 가끔씩 끊길 수 있습니다. -
      • -
      - - - - - - - - - - - -

      Developer Preview 2

      - -
      -
      -
      -

      - 날짜: 2016년 4월
      - 빌드: NPC91K, NPC91O
      - 에뮬레이터 지원: x86 및 ARM(32비트/64비트)
      - Google Play 서비스: 8.4
      -

      -
      -
      -
      - -

      DP2의 새로운 기능

      - -
        -
      • Vulkan에 대한 플랫폼 지원. Vulkan은 새로운 3D 렌더링 API이며, 낮은 오버헤드의 명시적 GPU(Graphics Processor Unit, 그래픽 처리 장치) 컨트롤을 제공하고 그리기 호출이 잦은 애플리케이션에 향상된 성능을 제공합니다. - - 자세한 내용은 문서를 참조하세요. - -
      • - -
      • 피부 색조를 지원하는 새로운 사람 그림 이모티콘 및 새로운 유니코드 9 문자 모양. - 피부 색조 및 새로운 그림 이모티콘은 키보드에 의해 이들 기능에 대한 지원이 색상표에 구축될 때까지는 표시되지 않습니다. - 시스템에서 제공하지 않는 글꼴을 사용하지 않는 한, 앱은 이러한 새로운 그림 이모티콘을 활용하기 위해 어떠한 작업도 수행할 필요가 없습니다. - IME 개발자는 새로운 그림 이모티콘에 대한 지원을 포함시켜야 합니다. - -
      • - -
      • - 런처 바로 가기 API: - 앱은 ShortcutManager를 사용하여 해당 앱 내부의 시작점에 대한 바로 가기를 런처로 전송할 수 있습니다. - -
      • - -
      • - 다중 창: - 이제 액티비티에 대해 최소 높이와 최소 너비를 별도로 지정할 수 있습니다. - 또한, 여러 가지 API 이름이 약간 변경되었습니다. -
      • -
      - -

      개발자가 보고한 문제의 수정 사항

      - -

      - 다음을 비롯하여 개발자가 보고한 여러 문제가 수정되었습니다. -

      - -
        -
      • 숨겨진 SSID 또는 비-브로드캐스트 Wi-Fi에 연결할 수 없음(버그 203116) -
      • - -
      • 마이크 음소거 상태가 액티비티 간에 유지됨(버그 205922) -
      • - -
      • 다중 창의 포커스를 변경하면 YouTube가 일시 중지됨(버그 203424) -
      • - -
      • 열려 있는 액티비티를 직접 회신으로 닫을 수 있음(버그 204411) -
      • - -
      • 다양한 안정성 문제 수정 -
      • -
      - -

      일반 권고 사항

      - -

      - 이 Developer Preview 릴리스는 앱 개발자 전용이며, 호환성 테스트 및 조기 개발 용도로만 사용하도록 설계되었습니다. - - 이 릴리스에 대한 다음과 같은 일반적인 참고 사항을 숙지하시기 바랍니다. -

      - -
        - -
      • 개발 도구 구성 요소 및 지원 라이브러리가 DP2 릴리스에 대해 업데이트되었습니다. - DP2용으로 개발하기 전에 Preview 개발 환경을 업데이트해야 합니다. - 개발 환경을 설정하는 방법에 대한 지침은 Preview 설정을 참조하세요. - - -
      • - -
      • 이 릴리스의 경우 모든 기기에서 다양한 안정성 및 성능 문제가 있으므로 전화 또는 태블릿에서 일상적으로 사용하는 데 적합하지 않으며, 특히 개발자가 아닌 일반 사용자가 사용하기에 적합치 않습니다. - - -
      • - -
      • 배터리 수명 및 성능은 이 릴리스에서 아직 최적화되지 않았습니다. - - -
          -
        • 시스템 및 앱 성능이 주기적으로 느려지고 저하되는 것으로 확인되었으며, 기기가 가끔씩 응답을 멈출 수 있습니다. - 이러한 문제는 장기 사용 시 더 심해질 수 있습니다. - -
        • - -
        • 이 릴리스에서 화면을 켜고 끄는 과정에서 배터리 수명이 감소할 수 있습니다. - -
        • -
        -
      • - -
      • 일부 앱의 경우 Developer Preview 2에서 정상적으로 작동하지 않을 수 있습니다. 여기에는 Google 앱뿐만 아니라 다른 앱도 포함됩니다. - -
      • - -
      • 이 조기 빌드는 CTS(Compatibility Test Suite) 승인을 받지 않았습니다. - CTS 승인을 받은 빌드를 사용하는 앱은 작동하지 않습니다(예: Android Pay). - -
      • - -
      • 이 프리뷰 릴리스에서는 Nexus 5X, Nexus 6, Nexus 6P, Nexus 9 및 Pixel C 뿐만 아니라 General Mobile 4G(Android One) 기기를 지원합니다. - - Nexus Player 지원은 곧 추가될 것입니다. -
      • - - -
      • TestDPC는 DP1 및 DP2 사이의 API 변경 사항을 처리하도록 업데이트되었습니다. - -
      • -
      - -

      알려진 문제

      - -

      성능 및 배터리

      - -
        -
      • 시스템 및 앱 성능이 주기적으로 느려지고 저하되는 것으로 확인되었으며, 기기가 가끔씩 응답을 멈출 수 있습니다. - 이러한 문제는 장기 사용 시 더 심해질 수 있습니다. - -
      • -
      - -

      Google 계정

      - -
        -
      • 경우에 따라 AccountManagerService와 관련된 문제가 있을 수 있으며, 이로 인해 Google 계정에 로그인하지 못할 수 있습니다. - -
      • -
      - -

      시스템 업데이트

      - -
        -
      • DP2로 업데이트한 후 즉시 기기가 재시작될 수 있습니다. -
      • -
      - -

      접근성

      - -
        -
      • 피치가 최대 수준에 가깝게 설정된 경우 TTS(텍스트 음성 변환) 출력을 듣는 데 문제가 있습니다. - -
      • -
      - -

      블루투스

      - -
        -
      • 블루투스 저전력(LE) GATT 특성이 잘못된 쓰기 유형을 사용하며 원격 기기로 전송되지 않습니다. - 이에 따라 예를 들면 일부 피트니스 기기가 작동하지 않습니다. - -
      • -
      - -

      설정 마법사

      - -
        -
      • "Your Google Account"에서 새 기기(또는 새롭게 초기화된 기기)의 데이터를 복원하는 옵션이 설정 마법사에서 작동하지 않습니다. - 설정 마법사에서 "다른 Android 기기"를 선택하여 기존 기기의 데이터를 복원하거나, 기존 기기를 새 기기로 설정해야 합니다. - - -
      • -
      - -

      OEM 잠금 해제

      - -
        -
      • 일부 기기에서, DP2를 실행하는 동안 "Developer Options"에서 Enable OEM unlock이 비활성화됩니다. -
        - 해결 방법: www.google.com/android/beta를 방문하여 Android 베타 프로그램에 옵트인합니다(아직 옵트인하지 않은 경우). - - 그런 다음 옵트아웃하고 다운그레이드 OTA를 수락합니다. - 옵트아웃하면 기기가 Android 6.0으로 다운그레이드됩니다. 이제 "Developer Options"에서 Enable OEM unlock을 선택할 수 있을 것입니다. - - 기기를 다운그레이드하면 개인 데이터가 삭제되지만, 부트로더의 잠금을 해제하는 경우에도 이 데이터가 삭제됩니다. - -
      • -
      - -

      Android for Work

      - -
        -
      • 작업 보안 인증 질문 -
          -
        • N으로 마이그레이션한 후나 사용자가 작업 프로필을 생성한 후에, 사용자가 자신의 패턴, PIN 또는 비밀번호를 변경하거나 작업 인증 질문을 설정할 때까지는 작업 프로필에서 키 저장소에 키를 생성할 수 없습니다. - - -
        • - -
        • 직접 부팅 모드에서 비밀번호 제한을 기기에 적용하면, 기기가 잠겨 있는 경우에도 작업 프로필의 잠금이 해제됩니다. - - 이로 인해 작업 프로필이 기기 잠금 화면으로 보호되어야 하는 경우에도 작업 프로필에 액세스할 수 있게 됩니다. - -
        • -
        -
      • - -
      • 상시 접속 VPN -
          -
        • 상시 접속 VPN 모드가 설정되었는데도 VPN을 사용할 수 없는 경우, 앱이 일반 네트워크를 통해 연결합니다. - VPN 연결을 사용할 수 없는 경우 앱은 오프라인이어야 합니다. - -
        • - -
        • 상시 접속 모드가 설정된 경우 사용자가 보안 잠금 화면의 잠금을 해제한 후에도, 기기가 직접 부팅 모드로 재부팅된 후 VPN 연결이 설정되지 않습니다. - - -
        • -
        -
      • - -
      • 패키지 일시 중단 -
          -
        • 기기 관리자는 예상치 못한 동작(예: "Telephone disabled" 대화 상자가 표시되어 있는데도 전화가 걸림)을 초래할 수 있는 중대한 시스템 패키지를 일시 중단시킬 수 있습니다. - - -
        • -
        -
      • - -
      • 기타 -
          -
        • {@link android.os.UserManager#DISALLOW_MOUNT_PHYSICAL_MEDIA}가 true로 설정된 경우, 사용자가 SD 카드와 같은 물리적 미디어를 삽입하면 Settings 앱이 실행 시에 작동을 멈춥니다. - - -
        • - -
        • 작업 프로필의 첫 번째 체크인은 완료되는 데 몇 분 정도 걸립니다. - -
        • -
        -
      • -
      - -

      Vulkan

      - -
        -
      • Nexus 5X/6P
      • -
          -
        • 바인딩 번호와 0이 아닌 첫 번째 바인딩 번호 사이에 격차가 있는 경우 {@code vkCreateGraphicsPipeline()}이 실패합니다. -
        • -
        • 투영된 텍스처 좌표에서 Vulkan이 잘못된 샘플링 동작을 보입니다.
        • -
        • multithreadCmdBuffer 샘플에서 N-DP2 드라이버와 함께 실행되는 경우 {@code vkCmdClearColorImage()}가 작동을 중단합니다. -
        • -
        • {@code vkGetPhysicalDeviceFormatProperties()}의 반환 값은 결과로 0 값을 취하는 {@code VkFormatProperties::linearTilingFeatures}의 값을 설정하지 않습니다. - -
        • -
        • Vulkan 부동 소수점 프레임 버퍼 첨부 파일이 올바르게 처리되지 않습니다.
        • -
        -
      • Nexus Player
      • -
          -
        • SPIR-V 셰이더가 드라이버 어설션을 트리거할 수 있습니다.
        • -
        • 일부 파이프라인 구성에서는 {@code vkCreateGraphicsPipeline()}이 작동을 중단할 수 있습니다. -
        • -
        -
      - -

      기기별 문제

      - -
      -
      - Android One -
      - -
      - 기기가 슬롯 1에서 슬롯 2 SIM으로 전환된 경우 데이터 연결이 실패합니다. -
      - -
      - Pixel C -
      - -
      - 음성 검색 "Always On" 옵션을 전환할 수 없습니다. -
      - -
      - Nexus 6 -
      - -
      - HDR+ 사진을 제외하고, 세로 방향의 카메라 사진이 손상됩니다. - -
      - -
      - Nexus Player -
      - -
      - Nexus Player에서 Netflix HD 콘텐츠의 재생이 실패할 수 있습니다. -
      - -
      - 동적 비디오 해상도 변경에 의존하는 모든 애플리케이션이 Nexus Player에서 실패할 수 있습니다. - -
      - -
      - VP9 비디오 코덱을 사용하는 모든 애플리케이션이 Nexus Player에서 실패할 수 있습니다. -
      -
      - - - -

      Developer Preview 1

      - -
      -
      -
      -

      - 날짜: 2016년 3월
      - 빌드: NPC56P, NPC56R, 업데이트됨: NPC56W, NPC56X
      - 에뮬레이터 지원: x86 및 ARM(32비트/64비트)
      - Google Play 서비스: 8.4
      -

      -
      -
      -
      - -

      일반 권고 사항

      - -

      - 이 Developer Preview 릴리스는 앱 개발자 전용이며, 호환성 테스트 및 조기 개발 용도로만 사용하도록 설계되었습니다. - 이 릴리스에 대한 - 다음과 같은 일반적인 참고 사항을 숙지하시기 바랍니다. -

      -
        -
      • 이 릴리스의 경우 모든 기기에서 다양한 안정성 및 성능 문제가 있으므로 전화 또는 태블릿에서 일상적으로 사용하는 데 적합하지 않으며, 특히 개발자가 아닌 일반 사용자가 사용하기에 적합치 않습니다. - - -
      • - -
      • 시스템 및 앱 성능이 주기적으로 느려지고 저하되는 것으로 확인되었으며, 기기가 가끔씩 응답을 멈출 수 있습니다. - 이러한 문제는 장기 사용 시 더 심해질 수 있습니다. - -
      • - -
      • 이 릴리스에서 화면을 켜고 끄는 과정에서 배터리 수명이 감소할 수 있습니다. - -
      • - -
      • 일부 앱의 경우 Developer Preview 1에서 정상적으로 작동하지 않을 수 있습니다. -여기에는 Google 앱뿐만 아니라 다른 앱도 포함됩니다. -
      • - -
      • 이 조기 빌드는 CTS(Compatibility Test Suite) 승인을 받지 않았습니다. CTS 승인을 받은 빌드를 사용하는 앱은 작동하지 않습니다(예: Android Pay). - -
      • - -
      • 이 프리뷰 릴리스에서는 Nexus 5X, Nexus 6, Nexus 6P, Nexus 9, Nexus Player 및 Pixel C 뿐만 아니라 General Mobile 4G(Android One) 기기를 지원합니다. - - -
      • -
      - -

      플랫폼 문제

      - -

      성능 및 배터리

      - -
        -
      • 시스템 및 앱 성능이 주기적으로 느려지고 저하되는 것으로 확인되었으며, 기기가 가끔씩 응답을 멈출 수 있습니다. - 이러한 문제는 장기 사용 시 더 심해질 수 있습니다. - -
      • - -
      • 이 릴리스에서 화면을 켜고 끄는 과정에서 배터리 수명이 감소할 수 있습니다. - -
      • -
      -

      다이얼러

      - -
        -
      • Dialer 앱이 직접 부팅을 지원하지 않습니다. 이 문제는 N Developer Preview에서 나중에 해결될 것입니다. - -
      • - -
      • 음성사서함 재생이 작동하지 않습니다. -
      • -
      - -

      마이크

      - -
        -
      • 앱 및 재부팅에 걸쳐 시스템이 마이크 음소거 상태를 잘못 유지할 수 있습니다. 앱에서 마이크를 음소거하고 그 상태가 유지되는 경우, 마이크 음소거 컨트롤이 있는 앱을 열고 마이크의 음소거를 해제하세요.
      • -
      - -

      시스템 UI

      - -
        -
      • 시스템 UI에서 새로운 문자열이나 수정된 일부 문자열이 모든 언어로 번역되어 있지 않습니다. - -
      • - -
      • Overview UI는 여전히 개발 중에 있으므로 변경될 수 있습니다. 예를 들어, 사용자가 앱 사이를 전환할 때 나타나는 타이머를 저희가 삭제할 계획입니다. - - -
      • - -
      • 설정 컨트롤 및 토글이 느리거나 응답이 없는 것으로 나타날 수 있습니다. -
      • - -
      • 알림의 시각적 디자인이 변경될 수 있습니다. -
      • - -
      • Gmail 앱에서, 알림 번들에 포함된 이메일의 직접 아카이빙 기능이 제대로 작동하지 않습니다. - -
      • -
      - -

      Android for Work

      - -
        -
      • 작업 보안 인증 질문 -
          -
        • N으로 마이그레이션한 후나 사용자가 작업 프로필을 생성한 후에, 사용자가 자신의 패턴, PIN 또는 비밀번호를 변경하거나 작업 인증 질문을 설정할 때까지는 작업 프로필에서 키 저장소에 키를 생성할 수 없습니다. - - -
        • - -
        • 직접 부팅 모드에서 비밀번호 제한을 기기에 적용하면, 기기가 잠겨 있는 경우에도 작업 프로필의 잠금이 해제됩니다. - - 이로 인해 작업 프로필이 기기 잠금 화면으로 보호되어야 하는 경우에도 작업 프로필에 액세스할 수 있게 됩니다. - -
        • - -
        • 사용자가 잘못된 비밀번호와 PIN을 입력하면, 시스템이 정보 메시지를 표시하지 않고 그 대신 입력 필드의 내용을 지웁니다. - - 이 문제는 패턴 또는 지문 입력에는 영향을 주지 않습니다. -
        • - -
        • 태블릿에서 작업 인증 질문에 표시되는 배경이 비정상적으로 작습니다. - -
        • - -
        • N Developer Preview에 번들로 제공되는 Google Apps Device Policy의 버전은 아직 작업 프로필 보안 인증 질문 기능을 지원하지 않습니다. - - - 개발자는 그 대신 TestDPC를 사용하여 이 기능을 테스트해야 합니다. - -
        • -
        -
      • - -
      • 상시 접속 VPN -
          -
        • 상시 접속 VPN 모드가 설정되었는데 VPN을 사용할 수 없는 경우, 상시 접속 정책에 대한 예외로 지정되지 않은 앱은 일반 네트워크를 통해 연결됩니다. - - 상시 접속 VPN 정책에 대한 예외로 지정되지 않은 한, VPN 연결을 사용할 수 없는 경우 앱은 오프라인이어야 합니다. - -
            -
          • 상시 접속 모드가 설정된 경우 사용자가 보안 잠금 화면의 잠금을 해제한 후에도, 기기가 직접 부팅 모드로 재부팅된 후 VPN 연결이 설정되지 않습니다. - - -
          • -
          -
        • -
        -
      • - -
      • 향상된 연락처 -
          -
        • 블루투스 PBAP/MAP 기기가 업무용 연락처에 대해 발신번호를 표시하지 않습니다. - Preview의 차기 릴리스에서 이 문제를 해결합니다. -
        • -
        -
      • - -
      • 작업 모드 -
          -
        • Google Now 런처가 작업 모드의 켜짐 또는 꺼짐 여부를 표시하지 않습니다. - 이 런처는 또한 앱 일시 중단 상태도 표시하지 않습니다. -
        • - -
        • 사용자가 작업 모드를 껏다가 켠 후, 시스템이 더 이상 작업 프로필 앱 위젯(예: 캘린더)을 표시하지 않습니다. - -
        • -
        -
      • - -
      • 패키지 일시 중단 -
      • - -
      • 기기 관리자는 예상치 못한 동작(예: "Telephone disabled" 대화 상자가 표시되어 있는데도 전화가 걸림)을 초래할 수 있는 중대한 시스템 패키지를 일시 중단시킬 수 있습니다. - - -
      • - -
      • 기타 -
          -
        • {@link android.os.UserManager#DISALLOW_MOUNT_PHYSICAL_MEDIA}가 true로 설정된 경우, 사용자가 SD 카드와 같은 물리적 미디어를 삽입하면 Settings 앱이 실행 시에 작동을 멈춥니다. - - -
        • - -
        • 사용자가 앱을 제거한 후 다시 설치하면 {@code DPM.setPackagesSuspended} 상태가 유지되지 않습니다. - 제거/재설치에 후 앱이 일시 중단 상태를 유지해야 하거나, 일시 중단된 앱이 제거가 불가능해야 합니다. - - -
        • - -
        • 작업 프로필의 첫 번째 체크인은 완료되는 데 몇 분 정도 걸립니다. - 이로 인해 기기가 Play EMM API에서 보일 때까지 보통 때보다 더 오래 걸릴 수 있습니다. - -
        • - -
        • 작업 프로필 앱으로부터 전송되는 알림은 개인 프로필에 설치된 알림 수신자에게는 표시되지 않습니다. - 따라서 시스템에서 알림이 예상대로 표시되지 않습니다. - -
        • - -
        -
      • -
      - -

      키보드

      - -
        -
      • 키보드 및 Android 기기 간의 블루투스 페어링이 불안정할 수 있습니다. -
      • -
      - -

      비디오

      - -
        -
      • 비디오 재생이 지연되고 끊김 현상이 나타날 수 있습니다.
      • -
      - -

      Wi-Fi

      - -
        -
      • API 특수 사례 동작을 변경시킬 수도 있는 일부 리팩터링이 Wi-Fi에 발생했습니다. - 특히, 특정 네트워크에 연결하려고 시도하는 애플리케이션이나 네트워크에 재연결하려고 시도하는 애플리케이션은 테스트를 다시 거쳐야 합니다. - -
      • - -
      • 레거시 DHCP 클라이언트가 플랫폼에서 제거되었습니다. 플랫폼이 지원하는 유일한 DHCP 클라이언트는 M에 추가된 DHCP 클라이언트뿐입니다. - -
      • -
      - -

      직접 부팅

      - -
        -
      • 최초 잠금 해제가 수행될 때까지는 NFC가 작동하지 않습니다. -
          -
        • 블루투스가 활성화된 전화가 재시작될 때, 블루투스가 자동으로 켜지지 않습니다. - 블루투스를 수동으로 다시 활성화해야 합니다. -
        • - -
        • 어떤 경우에는, 전화 및 메시지가 온 경우 기본 벨소리가 울리지 않을 수 있습니다. - 이 동작은 차기 N Preview 릴리스에서 수정되었습니다. 단, 한 가지 예외가 있으며 이에 대한 내용과 해결 방법은 다음과 같습니다. - -
        • - -
        • 직접 부팅 모드로 설정된 이후 최소 한 번 이상 부팅되었지만 완전히 초기화되지 않은 기기에서는 기본 알림 벨소리가 울리지 않습니다. - - 사용자가 Settings에서 벨소리를 수동으로 선택하여 이 문제를 해결할 수 있습니다. - -
        • - -
        • N Developer Preview 빌드가 실행되는 기기에서는 기본적으로 직접 부팅이 활성화되지 않습니다. - 테스트 및 개발에 직접 부팅을 활성화하려면 Developer Options로 이동하고 Convert to File Encryption을 탭하세요. - - 이 Developer Preview에서는 파일 기반 암호화를 위해 기기를 다시 파티셔닝하고 다시 포맷하려면 공장 초기화를 수행해야 합니다. - -
        • -
        -
      • -
      - -

      PIP for Android TV

      - -
        -
      • Recents UI에서의 PIP 통합은 완료되지 않았으며, 변경될 수 있습니다. - -
          -
        • PIP 창의 애니메이션이 매끄럽지 않습니다. 향후 프리뷰 릴리스에서 이 문제가 개선될 것입니다. - -
        • -
        -
      • - -
      • 향후 프리뷰 릴리스에서 PIP의 시각적 디자인과 레이아웃 맞춤이 개선될 것입니다. - -
      • -
      - -

      버그 보고서

      - -
        -
      • 버그 보고서가 항상 성공적으로 완료되는 것은 아닙니다. 그 해결 방법으로, 내부 저장소에 있는 버그 보고서 문서 제공자를 통해 버그 보고서에 액세스할 수 있는 경우도 있습니다. - - -
      • -
      - -

      분할 화면 다중 창

      - -
        -
      • 분할 화면 모드로 전환하면 앱이 작동을 중단하고 예기치 않은 UI 동작이 발생할 수 있습니다. - 이는 앱 개발자가 수정해야 하는 앱 문제입니다. - -
      • - -
      • 앱이 N 이전 버전의 Android 플랫폼을 대상으로 하는 경우, 이 앱이 분할 화면에서 작동하지 않을 수 있으며, 알림 메시지가 여러 번 나타날 수 있습니다. - -
      • - -
      • 방향이 고정된 상태로 앱을 사용하는 중에 Overview 버튼을 길게 누르면 예기치 않은 앱 동작이 발생할 수 있습니다. - -
      • - -
      • 크기를 조정하는 중에 앱이 깜박일 수 있습니다. -
      • - -
      • 애니메이션은 아직 최종 버전이 아닙니다. -
      • -
      - -

      입력 방법

      - -
        -
      • Use system language가 설정된 경우 예기치 않게 Google 키보드가 일반 Google 키보드로 다시 돌아가지만, 시스템 언어 기본 설정에 선택된 언어를 Google 키보드가 지원하지 않습니다. - - Google 키보드는 미국식 영어로 돌아가야 합니다. - -

        - Google 키보드에서 지원하는 언어를 최소 하나 이상 추가하여 이 문제를 해결할 수 있습니다. - -

        -
      • -
      - -

      접근성

      - -
        -
      • 알림, Quick Settings 타일 및 다중 창 표시를 비롯한 여러 기능에 대한 문제가 음성 안내 지원(TalkBack)에서 발생합니다. 이러한 문제로 인해 시스템 작동이 중단되거나 음성 안내 지원에서 음성 피드백이 제공되지 않을 수 있습니다. - - 향후 프리뷰 릴리스에서 이러한 문제가 해결될 것입니다. - -
      • -
      - -

      기기별 참고 사항 및 문제

      - -

      Nexus Player

      -
        -
      • 이 프리뷰 릴리스에서는 비디오 재생, 앱 호환성 및 안정성 문제가 Nexus Player에 있을 수 있습니다. - -
      • -
      - -

      Pixel C

      -
        -
      • 다중 창 크기를 조정하면 작동이 중단될 수 있습니다.
      • -
      - -

      Nexus 9

      -
        -
      • Android 베타 프로그램을 통해 OTA(Over-The-Air) 업데이트를 받은 후에 Nexus 9 기기가 시작되지 않을 수 있습니다. - 이 문제로부터 복구하기 위해 OTA 이미지를 수동으로 설치해 보실 수 있습니다. - 자세한 내용은 기기 OTA 이미지 적용을 참조하세요. - -
      • -
      - diff --git a/docs/html-intl/intl/ko/preview/features/direct-boot.jd b/docs/html-intl/intl/ko/training/articles/direct-boot.jd similarity index 98% rename from docs/html-intl/intl/ko/preview/features/direct-boot.jd rename to docs/html-intl/intl/ko/training/articles/direct-boot.jd index 981c3e08089897dd48763211d3f230500f6c1dc0..e58a4f98019b54b57d223a217531bee3d5ee8ee7 100644 --- a/docs/html-intl/intl/ko/preview/features/direct-boot.jd +++ b/docs/html-intl/intl/ko/training/articles/direct-boot.jd @@ -5,8 +5,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
      -
      +
      +

      이 문서의 내용

      1. 직접 부팅 시 실행하기 위한 액세스 요청
      2. @@ -18,7 +18,7 @@ page.image=images/cards/card-nyc_2x.jpg
      -

      기기에 전원이 들어와 있지만 사용자가 기기의 잠금을 해제하지 않았을 경우 Android N은 안전한 +

      기기에 전원이 들어와 있지만 사용자가 기기의 잠금을 해제하지 않았을 경우 Android N은 안전한 직접 부팅 모드에서 실행됩니다. 이를 지원하기 위해 시스템에서 다음과 같은 두 가지 데이터 저장소 위치를 제공합니다.

      @@ -125,7 +125,7 @@ ACTION_BOOT_COMPLETED} 메시지를 수신할 수 있습니다. 이 메시지는

      기존 데이터 마이그레이션

      직접 부팅 모드를 사용하도록 사용자가 자신의 기기를 업데이트하는 경우, -여러분이 기존 데이터를 기기 암호화 저장소로 마이그레이션해야 할 수도 있습니다. +여러분이 기존 데이터를 기기 암호화 저장소로 마이그레이션해야 할 수도 있습니다. Context.moveSharedPreferencesFrom()Context.moveDatabaseFrom()을 사용하여 자격 증명 암호화 저장소와 기기 암호화 저장소 간에 기본 설정과 데이터베이스 데이터를 마이그레이션합니다.

      diff --git a/docs/html-intl/intl/ko/preview/features/scoped-folder-access.jd b/docs/html-intl/intl/ko/training/articles/scoped-directory-access.jd similarity index 93% rename from docs/html-intl/intl/ko/preview/features/scoped-folder-access.jd rename to docs/html-intl/intl/ko/training/articles/scoped-directory-access.jd index 2fe02b12f35f96e751ce08470ce9bed4b6dd8468..f2ce6500327d5efd166a120f33b50e4e00aa15d6 100644 --- a/docs/html-intl/intl/ko/preview/features/scoped-folder-access.jd +++ b/docs/html-intl/intl/ko/training/articles/scoped-directory-access.jd @@ -4,8 +4,8 @@ page.tags=androidn @jd:body -
      -
      +
      +

      이 문서의 내용

      1. 외부 저장소 디렉터리 액세스
      2. @@ -71,8 +71,8 @@ startActivityForResult(intent, request_code);

        시스템이 외부 디렉터리에 액세스 권한을 부여하고자 시도하고, 필요에 따라 단순화된 UI를 사용하는 사용자의 액세스를 확인합니다.

        - +

        그림 1. Pictures 디렉터리에 액세스를 요청하는 애플리케이션.

        @@ -138,8 +138,8 @@ startActivityForResult(intent, request_code); 사용자 환경을 저해하는 결과를 낳습니다. 사용자가 요청을 거부하는데 앱이 다시 액세스를 요청하면, UI에 Don't ask again 체크박스가 표시됩니다.

        - +

        그림 1. 이동식 미디어에 대해 다시 액세스 요청을 하는 애플리케이션.

        diff --git a/docs/html-intl/intl/ko/preview/features/security-config.jd b/docs/html-intl/intl/ko/training/articles/security-config.jd similarity index 99% rename from docs/html-intl/intl/ko/preview/features/security-config.jd rename to docs/html-intl/intl/ko/training/articles/security-config.jd index 7e3f951cc6dd61007505db0b61988ae24d76115b..414c139b7808741e5c362eee4c7c5771fb491bd3 100644 --- a/docs/html-intl/intl/ko/preview/features/security-config.jd +++ b/docs/html-intl/intl/ko/training/articles/security-config.jd @@ -4,8 +4,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
        -
        +
        +

        이 문서의 내용

          diff --git a/docs/html-intl/intl/ko/training/basics/activity-lifecycle/index.jd b/docs/html-intl/intl/ko/training/basics/activity-lifecycle/index.jd index e66e8d19c372e537e6f9611c933254fa687de76f..4fd4af25afd435ee71a506d7460bfe32b5879896 100644 --- a/docs/html-intl/intl/ko/training/basics/activity-lifecycle/index.jd +++ b/docs/html-intl/intl/ko/training/basics/activity-lifecycle/index.jd @@ -35,11 +35,11 @@ startpage=true

        사용자가 앱을 탐색하고, 앱에서 나가고, 앱으로 다시 돌아가면, 앱의 -{@link android.app.Activity} 인스턴스는 +{@link android.app.Activity} 인스턴스는 수명 주기 안에서 서로 다른 상태 간에 전환됩니다. 예를 들어 액티비티가 처음 시작되는 경우, 시스템의 전면에 표시되어 사용자의 포커스를 받습니다. 이 과정에서 Android 시스템은 사용자 인터페이스 및 다른 구성요소에 설정된 -액티비티에 대해 일련의 수명 주기 메서드를 호출합니다. 사용자가 다른 액티비티를 시작하거나 다른 앱으로 전환하는 +액티비티에 대해 일련의 수명 주기 메서드를 호출합니다. 사용자가 다른 액티비티를 시작하거나 다른 앱으로 전환하는 작업을 수행하면, 백그라운드(액티비티가 더 이상 보이지 않지만 인스턴스와 해당 상태는 그대로 유지되는 상태)로 전환되면서 시스템은 액티비티에 대해 또 다른 수명 주기 메서드 세트를 호출합니다.

        @@ -55,7 +55,7 @@ android.app.Activity} 인스턴스가 수신하는 중요한 수명 주기 콜 사용자가 원하는 작업을 하고, 액티비티가 필요로 하지 않을 때 시스템 리소스 소비를 방지하는 방법에 대해서도 설명합니다.

        과정

        - +
        액티비티 시작하기
        액티비티 수명 주기의 기본사항, 사용자가 앱을 시작하는 방법, 그리고 기본 액티비티 생성 작업을 수행하는 @@ -68,5 +68,5 @@ android.app.Activity} 인스턴스가 수신하는 중요한 수명 주기 콜
        액티비티 재생성하기
        액티비티가 소멸되면 어떤 동작이 발생하는지, 그리고 필요 시 액티비티 상태를 재구축하는 방법에 대해 설명합니다.
        -
        + diff --git a/docs/html-intl/intl/ko/training/basics/activity-lifecycle/pausing.jd b/docs/html-intl/intl/ko/training/basics/activity-lifecycle/pausing.jd index b0497cda4da119df526e2431dc1ce08f1d9687ac..98e2afd3f4d926abc6022ff4cf2ca4d50aeccfd3 100644 --- a/docs/html-intl/intl/ko/training/basics/activity-lifecycle/pausing.jd +++ b/docs/html-intl/intl/ko/training/basics/activity-lifecycle/pausing.jd @@ -8,13 +8,13 @@ trainingnavtop=true
        - +

        이 과정에서 다루는 내용

        1. 액티비티 일지정지하기
        2. 액티비티 재개하기
        - +

        필독 항목

        -

        일반적인 앱 사용 중에 가끔 다른 +

        일반적인 앱 사용 중에 가끔 다른 비주얼 구성요소로 인해 전면의 액티비티가 일시정지되는 경우가 있습니다. 예를 들어, 대화 상자 스타일과 같은 반투명 액티비티가 열리면, 그 이전 액티비티는 일시정지됩니다. 액티비티가 부분적으로 보이지만 현재 포커스 내에 있지 않는 한 일시정지된 상태로 유지됩니다.

        @@ -59,7 +59,7 @@ android.app.Activity#onPause()}에 대한 호출을 수신하는 경우, 이는

        액티비티 일지정지하기

        - +

        시스템이 액티비티에 대해 {@link android.app.Activity#onPause()}를 호출하면, 이는 엄밀해 말해 액티비티가 여전히 부분적으로 보일 수 있음을 의미하지만, 대개의 경우 사용자가 액티비티를 떠나 곧 정지 상태로 전환될 것임을 나타냅니다. 일반적으로 다음 작업을 수행할 때 diff --git a/docs/html-intl/intl/ko/training/basics/activity-lifecycle/recreating.jd b/docs/html-intl/intl/ko/training/basics/activity-lifecycle/recreating.jd index 79fb92bbdc7d9cf619e17a6ab6a393db2e3583c4..2408cac248bb1c20fcffaaf53a6577f54a3cbe2f 100644 --- a/docs/html-intl/intl/ko/training/basics/activity-lifecycle/recreating.jd +++ b/docs/html-intl/intl/ko/training/basics/activity-lifecycle/recreating.jd @@ -8,13 +8,13 @@ trainingnavtop=true

        - +

        이 과정에서 다루는 내용

        1. 액티비티 상태 저장하기
        2. 액티비티 상태 복원하기
        - +

        필독 항목

        -
        +

        기기 상태 변경을 모니터링하는 가장 간단한 방법은 모니터링하는 각 상태에 대해 {@link android.content.BroadcastReceiver}를 만들어 각각을 애플리케이션 매니페스트에 등록하는 것입니다. 그러면 각 리시버 내에서 현재 기기 상태를 기반으로 반복 알람의 일정을 간단히 변경할 수 있습니다.

        @@ -31,10 +31,10 @@ previous.link=connectivity-monitoring.html

        이 방법의 부작용은 리시버 중 하나라도 실행되면 매번 앱이 기기의 절전 모드를 해제시킨다는 것입니다.

        더 나은 방법은 런타임 때 브로드캐스트 리시버를 사용 중지 또는 사용하도록 설정하는 것입니다. 이렇게 하면 매니페스트에 선언한 리시버를 필요할 때만 시스템 이벤트에 의해 실행되는 수동적인 알람으로 사용할 수 있습니다.

        - -

        효율성 향상을 위한 상태 변화 수신기의 전환 및 단계적 연결

        - + +

        효율성 향상을 위한 상태 변화 수신기의 전환 및 단계적 연결

        +

        {@link android.content.pm.PackageManager}를 사용하여 아래에서 표시된 대로 모든 사용 또는 사용 중지하기 원하는 브로드캐스트 리시버를 포함하여 매니페스트 내에 정의된 모든 요소의 사용 가능 상태를 전환할 수 있습니다.

        ComponentName receiver = new ComponentName(context, myReceiver.class);
        diff --git a/docs/html-intl/intl/ko/training/multiscreen/adaptui.jd b/docs/html-intl/intl/ko/training/multiscreen/adaptui.jd
        index cb7b66c90238b040394f383e39cd0c295928be65..a8d2fc16939f5214812ffc3f88788178935cfa99 100644
        --- a/docs/html-intl/intl/ko/training/multiscreen/adaptui.jd
        +++ b/docs/html-intl/intl/ko/training/multiscreen/adaptui.jd
        @@ -10,9 +10,9 @@ previous.link=screendensities.html
         
         
         
        -
        -
        - +
        +
        +

        강의 목표

          @@ -27,17 +27,17 @@ previous.link=screendensities.html - +

          다운로드

          - +
          샘플 앱 다운로드 -

          NewsReader.zip

          -
          - - -
        -
        +

        NewsReader.zip

        +
        + + +
        +

        현재 애플리케이션이 표시하는 레이아웃에 따라 UI 플로가 달라질 수 있습니다. 예를 들어 애플리케이션이 이중 창 모드로 되어 있는 경우에는 왼쪽 창에 있는 항목을 클릭하면 오른쪽 창에 콘텐츠가 표시되고, 단일 창 모드로 되어 있는 경우에는 콘텐츠가 해당 창에 표시됩니다(다른 액티비티에서).

        @@ -56,7 +56,7 @@ public class NewsReaderActivity extends FragmentActivity { setContentView(R.layout.main_layout); View articleView = findViewById(R.id.article); - mIsDualPane = articleView != null && + mIsDualPane = articleView != null && articleView.getVisibility() == View.VISIBLE; } } @@ -116,7 +116,7 @@ public void onCreate(Bundle savedInstanceState) { else { /* use list navigation (spinner) */ actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST); - SpinnerAdapter adap = new ArrayAdapter(this, + SpinnerAdapter adap = new ArrayAdapter(this, R.layout.headline_item, CATEGORIES); actionBar.setListNavigationCallbacks(adap, handler); } @@ -168,7 +168,7 @@ public class HeadlinesFragment extends ListFragment { public class HeadlinesFragment extends ListFragment { ... @Override - public void onItemClick(AdapterView<?> parent, + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (null != mHeadlineSelectedListener) { mHeadlineSelectedListener.onHeadlineSelected(position); diff --git a/docs/html-intl/intl/ko/training/multiscreen/index.jd b/docs/html-intl/intl/ko/training/multiscreen/index.jd index dd152aea410aa8d7c59a19f30996bf8ae35e3003..0a30f92abaab5c90fd47beee5f9ba4951a23e956 100644 --- a/docs/html-intl/intl/ko/training/multiscreen/index.jd +++ b/docs/html-intl/intl/ko/training/multiscreen/index.jd @@ -7,10 +7,10 @@ next.link=screensizes.html @jd:body -
        -
        - -

        요구사항과 선행조건

        +
        +
        + +

        요구사항과 선행조건

        • Android 1.6 이상(샘플 앱의 경우 2.1 이상)
        • @@ -27,17 +27,17 @@ href="{@docRoot}tools/support-library/index.html">호환성 라이브러리 - -

          다운로드

          - -
          + +

          다운로드

          + +
          샘플 앱 다운로드 -

          NewsReader.zip

          -
          - -
          -
        - +

        NewsReader.zip

        +
        + +
        +
        +

        Android는 소형 휴대전화에서부터 대형 TV에 이르기까지 다양한 화면 크기의 수많은 기기 유형을 지원합니다. 따라서 애플리케이션이 모든 화면 크기와 호환되어 최대한 많은 사용자가 사용할 수 있도록 디자인하는 것이 중요합니다.

        하지만 다양한 기기 유형과 호환되는 것만으로는 충분하지 않습니다. 각 화면 크기에 따라 사용자 상호작용에 유리한 점과 불리한 점이 다릅니다. 따라서 사용자에게 만족을 주고 깊은 인상을 심어주려면 애플리케이션이 단지 여러 화면을 지원하는 데 그치지 않고 화면 구성별로 사용자 환경을 최적화해야 합니다.

        @@ -48,17 +48,17 @@ href="{@docRoot}tools/support-library/index.html">호환성 라이브러리

        참고: 이 강의 및 강의와 관련된 샘플은 호환성 라이브러리를 사용하며 이는 Android 3.0 이하 버전에서 {@link android.app.Fragment} API를 사용하기 위해서입니다. 이 강의에서 API를 모두 사용하려면 라이브러리를 다운로드하여 애플리케이션에 추가해야 합니다.

        - - -

        강의

        - -
        -
        다양한 화면 크기 지원
        -
        이 강의에서는 여러 다양한 화면 크기에 조정되는 레이아웃을 디자인하는 방법(유연한 보기 크기, {@link android.widget.RelativeLayout}, 화면 크기 및 방향 한정자, 별칭 필터 및 나인-패치 비트맵 사용하기)을 안내합니다.
        - -
        다양한 화면 밀도 지원
        -
        이 강의에서는 다양한 픽셀 밀도를 가진 화면을 지원하는 방법(밀도 독립형 픽셀(density-independent pixel) 사용하기 및 밀도별로 적합한 비트맵 제공하기)을 설명합니다.
        - -
        조정형 UI 플로우 구현
        -
        이 강의에서는 여러 화면 크기/밀도 조합에 조정되도록 UI 플로우를 구현하는 방법(활성 레이아웃의 런타임 감지, 현재 레이아웃에 따른 대응, 화면 구성 변경 처리)을 설명합니다.
        -
        + + +

        강의

        + +
        +
        다양한 화면 크기 지원
        +
        이 강의에서는 여러 다양한 화면 크기에 조정되는 레이아웃을 디자인하는 방법(유연한 보기 크기, {@link android.widget.RelativeLayout}, 화면 크기 및 방향 한정자, 별칭 필터 및 나인-패치 비트맵 사용하기)을 안내합니다.
        + +
        다양한 화면 밀도 지원
        +
        이 강의에서는 다양한 픽셀 밀도를 가진 화면을 지원하는 방법(밀도 독립형 픽셀(density-independent pixel) 사용하기 및 밀도별로 적합한 비트맵 제공하기)을 설명합니다.
        + +
        조정형 UI 플로우 구현
        +
        이 강의에서는 여러 화면 크기/밀도 조합에 조정되도록 UI 플로우를 구현하는 방법(활성 레이아웃의 런타임 감지, 현재 레이아웃에 따른 대응, 화면 구성 변경 처리)을 설명합니다.
        +
        diff --git a/docs/html-intl/intl/ko/training/multiscreen/screendensities.jd b/docs/html-intl/intl/ko/training/multiscreen/screendensities.jd index 5d6e2f3c59b78326ee4a63403543c4e1262394d5..dfaa44f33abc7468676f2b15ac69a3a5594bcb7a 100644 --- a/docs/html-intl/intl/ko/training/multiscreen/screendensities.jd +++ b/docs/html-intl/intl/ko/training/multiscreen/screendensities.jd @@ -12,8 +12,8 @@ next.link=adaptui.html -
        -
        +
        +

        강의 목표

          @@ -29,15 +29,15 @@ next.link=adaptui.html

          다운로드

          - -
          + +
          샘플 앱 다운로드 -

          NewsReader.zip

          -
          - - -
          -
        +

        NewsReader.zip

        +
        + + +
        +

        이 강의에서는 다양한 리소스를 제공하고 해상도 독립형(resolution-independent) 측정 단위를 사용함으로써 다양한 화면 밀도를 지원하는 방법을 설명합니다.

        @@ -48,8 +48,8 @@ next.link=adaptui.html

        예를 들어 두 개의 보기 사이에 여백을 지정할 때 px가 아닌 dp를 사용합니다.

        -<Button android:layout_width="wrap_content" 
        -    android:layout_height="wrap_content" 
        +<Button android:layout_width="wrap_content"
        +    android:layout_height="wrap_content"
             android:text="@string/clickme"
             android:layout_marginTop="20dp" />
         
        @@ -57,8 +57,8 @@ next.link=adaptui.html

        텍스트 크기를 지정할 때에는 항상 sp를 사용합니다.

        -<TextView android:layout_width="match_parent" 
        -    android:layout_height="wrap_content" 
        +<TextView android:layout_width="match_parent"
        +    android:layout_height="wrap_content"
             android:textSize="20sp" />
         
        diff --git a/docs/html-intl/intl/ko/training/multiscreen/screensizes.jd b/docs/html-intl/intl/ko/training/multiscreen/screensizes.jd index f2e77a6e2b04b74bb72ad0d747c4d1d8feb03be4..984923d5ee9355466b1ba54fbeecf83100882eb8 100644 --- a/docs/html-intl/intl/ko/training/multiscreen/screensizes.jd +++ b/docs/html-intl/intl/ko/training/multiscreen/screensizes.jd @@ -10,8 +10,8 @@ next.link=screendensities.html -
        -
        +
        +

        강의 목표

          @@ -30,26 +30,26 @@ next.link=screendensities.html
        1. 다양한 화면 지원
        2. -

          다운로드

          - -
          +

          다운로드

          + +
          샘플 앱 다운로드 -

          NewsReader.zip

          -
          - -
          -
        +

        NewsReader.zip

        +
        + +
        +

        이 강의에서는 다양한 화면 크기를 지원하는 방법을 설명합니다.

        -
          -
        • 화면에 맞게 레이아웃 크기 조정
        • -
        • 화면 구성에 따라 적합한 UI 레이아웃 제공
        • +
            +
          • 화면에 맞게 레이아웃 크기 조정
          • +
          • 화면 구성에 따라 적합한 UI 레이아웃 제공
          • 올바른 화면에 올바른 레이아웃 적용
          • -
          • 정확하게 확대되는 비트맵 제공
          • -
          +
        • 정확하게 확대되는 비트맵 제공
        • +
        -

        'wrap_content' 및 'match_parent' 사용

        +

        'wrap_content' 및 'match_parent' 사용

        레이아웃이 다양한 화면 크기에 따라 유연하게 조정되도록 하려면 일부 뷰 구성요소의 너비와 높이에 "wrap_content""match_parent"를 사용해야 합니다. "wrap_content"를 사용하면 뷰의 너비와 높이가 해당 뷰 내에 콘텐츠가 들어가는데 필요한 최소 크기로 설정되는 반면, "match_parent"(API 수준 8 이전에는 "fill_parent"라고도 함)를 사용하면 구성요소가 확장되어 부모뷰의 크기와 일치하게 됩니다.

        @@ -65,7 +65,7 @@ next.link=screendensities.html

        그림 1. 세로 모드(왼쪽) 및 가로 모드(오른쪽)에서의 뉴스 리더 샘플 앱

        -

        RelativeLayout 사용

        +

        RelativeLayout 사용

        비교적 복잡한 레이아웃을 만들려면 {@link android.widget.LinearLayout}의 중첩 인스턴스와 "wrap_content""match_parent" 크기의 조합을 사용합니다. 하지만 {@link android.widget.LinearLayout} 을 사용하면 자식뷰의 여백 관계를 정확하게 제어할 수 없으며 {@link android.widget.LinearLayout} 단순히 나란하게 표시됩니다. 자식뷰를 일직선이 아닌 다양한 방향으로 표시해야 하는 경우 구성요소 사이의 여백 관계를 중심으로 레이아웃을 지정할 수 있는 {@link android.widget.RelativeLayout}을 사용하는 것이 더 좋은 방법일 수 있습니다. 예를 들어 화면 왼쪽에 하나의 자식뷰를, 오른쪽에 다른 자식뷰를 정렬할 수 있습니다.

        @@ -115,8 +115,8 @@ next.link=screendensities.html

        구성요소의 크기가 변하더라도 여백 관계가 {@link android.widget.RelativeLayout.LayoutParams}.

        - -

        크기 한정자 사용

        + +

        크기 한정자 사용

        이전 섹션에서 다룬 유연한 레이아웃이나 상대적 레이아웃으로는 한계가 있습니다. 이러한 레이아웃이 구성요소 내부 및 주위의 여백을 확장하여 다양한 화면에 맞게 조정되긴 하지만 화면 크기별로 최적의 사용자 환경을 제공하지는 못할 수 있습니다. 따라서 애플리케이션은 유연한 레이아웃을 구현할 뿐 아니라 다양한 화면 구성을 타겟팅할 수 있도록 다양한 대체 레이아웃을 제공해야 합니다. 그 방법은 런타임이 현재 기기의 구성에 따라 적합한 리소스(예: 화면 크기별로 다른 레이아웃 디자인)를 자동으로 선택하도록 해 주는 구성 한정자를 사용하는 것입니다.

        @@ -158,7 +158,7 @@ next.link=screendensities.html

        하지만 Android 3.2 이전 기기는 sw600dp를 크기 한정자로 인식하지 않기 때문에 최소 너비 한정자가 제대로 작동하지 않으며 따라서 large 한정자도 계속 사용해야 합니다. 따라서 res/layout-large/main.xml라는 이름의 파일이 있어야 하며 이 파일은 res/layout-sw600dp/main.xml과 동일한 파일입니다. 다음 섹션에서는 이런 식으로 레이아웃 파일이 중복되지 않게 하는 기술을 살펴보겠습니다.

        -

        레이아웃 별칭 사용

        +

        레이아웃 별칭 사용

        최소 너비 한정자는 Android 3.2 이상 버전에서만 사용할 수 있습니다. 따라서 이전 버전과 호환되도록 하려면 추상화 크기 빈(소형, 보통, 대형 및 초대형)을 계속 사용해야 합니다. 예를 들어 휴대전화에서는 단일 창 UI가 표시되고 7인치 태블릿, TV 및 기타 대형 기기에서는 다중 창 UI가 표시되도록 UI를 디자인하려면 다음 파일을 제공해야 합니다.

        @@ -202,7 +202,7 @@ next.link=screendensities.html {@code large},3.2 이후 버전은 sw600dp와 일치).

        -

        방향 한정자 사용

        +

        방향 한정자 사용

        일부 레이아웃은 가로 및 세로 방향 모두에서 잘 작동하지만 대부분의 레이아웃은 조정을 통해 많은 이점을 누릴 수 있습니다. 다음은 뉴스 리더 샘플 앱에서 화면 크기와 방향별로 레이아웃이 어떻게 작동하는지 보여줍니다.

        diff --git a/docs/html-intl/intl/ko/preview/features/picture-in-picture.jd b/docs/html-intl/intl/ko/training/tv/playback/picture-in-picture.jd similarity index 98% rename from docs/html-intl/intl/ko/preview/features/picture-in-picture.jd rename to docs/html-intl/intl/ko/training/tv/playback/picture-in-picture.jd index bc6ec6282abc3674bfbd8f8a3b4ff529edafff61..96129ce216e1046b5650f1f963971ecc27c2df89 100644 --- a/docs/html-intl/intl/ko/preview/features/picture-in-picture.jd +++ b/docs/html-intl/intl/ko/training/tv/playback/picture-in-picture.jd @@ -4,8 +4,8 @@ page.tags=androidn @jd:body -
        -
        +
        +

        이 문서의 내용

          @@ -59,7 +59,7 @@ PIP 창을 전체 화면으로 전환하거나 PIP를 닫는 PIP 메뉴를 불 메인 화면에서 재생되기 시작하면 PIP 창이 자동으로 닫힙니다. 사용자가 Recents를 통해서 PIP 창을 닫을 수도 있습니다.

          - +

          그림 1. 사용자가 메인 화면에서 콘텐츠를 탐색하는 동안 화면 모서리에 표시되는 PIP 동영상.

          @@ -116,7 +116,7 @@ public void onActionClicked(Action action) {

          미디어 컨트롤 막대에 PIP 버튼을 추가하면 사용자가 동영상 재생을 제어하면서 PIP 모드로 쉽게 전환할 수 있습니다.

          - +

          그림 1. 미디어 컨트롤 막대의 PIP 버튼.

          diff --git a/docs/html-intl/intl/ko/preview/features/tv-recording-api.jd b/docs/html-intl/intl/ko/training/tv/tif/content-recording.jd similarity index 99% rename from docs/html-intl/intl/ko/preview/features/tv-recording-api.jd rename to docs/html-intl/intl/ko/training/tv/tif/content-recording.jd index f353cc6a4e67745f03e958223a88cd5c0db0ad4d..ed8b6e04ec8544c8f06d51fae50108a532980251 100644 --- a/docs/html-intl/intl/ko/preview/features/tv-recording-api.jd +++ b/docs/html-intl/intl/ko/training/tv/tif/content-recording.jd @@ -5,8 +5,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
          -
          +
          +

          이 문서의 내용

          1. 녹화 지원 나타내기
          2. @@ -81,7 +81,7 @@ page.image=images/cards/card-nyc_2x.jpg 전송하는 역할을 담당합니다.

            시스템이 RecordingSession.onTune()을 호출하면 -채널 URI에 전달되고, URI가 지정하는 채널에 맞춰 조정됩니다. +채널 URI에 전달되고, URI가 지정하는 채널에 맞춰 조정됩니다. notifyTuned()를 호출해서 앱이 원하는 채널에 맞춰졌음을 시스템에 알리거나 앱이 적절한 채널에 맞출 수 없으면 notifyError()를 호출합니다.

            diff --git a/docs/html-intl/intl/pt-br/about/versions/android-5.0.jd b/docs/html-intl/intl/pt-br/about/versions/android-5.0.jd index 23904b3325efa348d72e906313ddb3bbaac2b304..5408793c79e95556b5aa5bf351a661b1ce3e2a57 100644 --- a/docs/html-intl/intl/pt-br/about/versions/android-5.0.jd +++ b/docs/html-intl/intl/pt-br/about/versions/android-5.0.jd @@ -426,7 +426,7 @@ sdk.platform.apiLevel=21

            Quando o sistema detectar uma rede adequada, ele se conectará à rede e chamará a chamada de retorno {@link android.net.ConnectivityManager.NetworkCallback#onAvailable(android.net.Network) onAvailable()}. É possível usar o objeto {@link android.net.Network} da chamada de retorno a fim de receber mais informações sobre a rede ou direcionar o tráfego para que a rede selecionada seja usada.

            Bluetooth Low Energy

            -

            O Android 4.3 apresentou o suporte de plataforma para o Bluetooth Low Energy(Bluetooth LE) na função central. No Android 5.0, um dispositivo Android agora pode agir como um dispositivo periférico de Bluetooth LE. Os apps podem usar esse recurso para fazer com que sua presença seja percebida pelos dispositivos vizinhos. É possível, por exemplo, criar apps que permitem que um dispositivo funcione como um pedômetro ou um monitor de integridade de dados e envie seus dados para outro dispositivo Bluetooth LE.

            +

            O Android 4.3 apresentou o suporte de plataforma para o Bluetooth Low Energy(Bluetooth LE) na função central. No Android 5.0, um dispositivo Android agora pode agir como um dispositivo periférico de Bluetooth LE. Os apps podem usar esse recurso para fazer com que sua presença seja percebida pelos dispositivos vizinhos. É possível, por exemplo, criar apps que permitem que um dispositivo funcione como um pedômetro ou um monitor de integridade de dados e envie seus dados para outro dispositivo Bluetooth LE.

            As novas APIs de {@link android.bluetooth.le} permitem que seus apps divulguem anúncios, verifiquem respostas e formem conexões com dispositivos Bluetooth LE vizinhos. Para usar os novos recursos de publicidade e varredura, adicione a permissão {@link android.Manifest.permission#BLUETOOTH_ADMIN BLUETOOTH_ADMIN} no manifesto. Quando os usuários atualizam ou fazem o download do seu app a partir da Play Store, eles são solicitados a conceder a seguinte permissão para seu app: "Informações da conexão Bluetooth: permite que o app controle o Bluetooth, incluindo a divulgação para dispositivos Bluetooth vizinhos ou a busca de informações sobre esses dispositivos."

            Para começar a publicidade de Bluetooth LE para que outros dispositivos possam descobrir seu app, chame {@link android.bluetooth.le.BluetoothLeAdvertiser#startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback) startAdvertising()} e passe uma implementação da classe {@link android.bluetooth.le.AdvertiseCallback}. O objeto de chamada de retorno recebe um relatório do sucesso ou da falha da operação de publicidade.

            diff --git a/docs/html-intl/intl/pt-br/preview/guide.jd b/docs/html-intl/intl/pt-br/about/versions/marshmallow/android-6.0-testing.jd similarity index 99% rename from docs/html-intl/intl/pt-br/preview/guide.jd rename to docs/html-intl/intl/pt-br/about/versions/marshmallow/android-6.0-testing.jd index b33369e774949bcfb5a48c79eb93b8d7a106f43c..c00fd21bf187da0177af77d345775ce422b7a117 100644 --- a/docs/html-intl/intl/pt-br/preview/guide.jd +++ b/docs/html-intl/intl/pt-br/about/versions/marshmallow/android-6.0-testing.jd @@ -5,8 +5,8 @@ page.tags="preview", "developer preview" @jd:body -
            -
            +
            +

            Neste documento

            1. Teste de permissões
            2. diff --git a/docs/html-intl/intl/pt-br/preview/behavior-changes.jd b/docs/html-intl/intl/pt-br/about/versions/nougat/android-7.0-changes.jd similarity index 95% rename from docs/html-intl/intl/pt-br/preview/behavior-changes.jd rename to docs/html-intl/intl/pt-br/about/versions/nougat/android-7.0-changes.jd index 1e56a9951986bcb3f6948e0eb2893b67f4c4face..18a08f4e5a45b71f22c1b058f37f52fce96e5bd4 100644 --- a/docs/html-intl/intl/pt-br/preview/behavior-changes.jd +++ b/docs/html-intl/intl/pt-br/about/versions/nougat/android-7.0-changes.jd @@ -6,8 +6,8 @@ page.image=images/cards/card-n-changes_2x.png @jd:body -
              -
              +
              +

              Neste documento

              @@ -44,7 +44,7 @@ Visão geral da API do Android N

              - Junto com novos recursos e funcionalidades, o Android N + Junto com novos recursos e funcionalidades, o Android N inclui uma variedade de mudanças de comportamento do sistema e da API. Este documento destaca algumas das principais mudanças que você deve entender e considerar nos aplicativos. @@ -77,7 +77,7 @@ recursos do sistema, bem como a forma como ele interage com outros aplicativos p

              - +

              Figura 1. Ilustração de como o modo soneca aplica um primeiro nível de restrições de atividades de sistema para aumentar a vida útil da bateria. @@ -88,7 +88,7 @@ recursos do sistema, bem como a forma como ele interage com outros aplicativos p período, o dispositivo entrará no modo de soneca e aplicará o primeiro subconjunto de restrições: o acesso do aplicativo à rede será desativado e os trabalhos e sincronizações serão adiados. Se o dispositivo permanecer estacionário por um determinado período após entrar no modo soneca, o sistema aplicará -as demais restrições de soneca a {@link android.os.PowerManager.WakeLock}, aos alarmes +as demais restrições de soneca a {@link android.os.PowerManager.WakeLock}, aos alarmes {@link android.app.AlarmManager} e às verificações de GPS e Wi-Fi. Independentemente de as restrições de soneca serem aplicadas parcial ou totalmente, o sistema despertará o dispositivo para breves janelas de manutenção, quando os aplicativos @@ -96,7 +96,7 @@ as demais restrições de soneca a {@link android.os.PowerManager.WakeLock}, aos

              - +

              Figura 2. Ilustração de como o modo soneca aplica um segundo nível de restrições de atividades de sistema após o dispositivo permanecer estacionário por um determinado período. @@ -151,7 +151,7 @@ do dispositivo e a experiência do usuário.

              -

              O novo widget CardView permite exibir informações importantes dentro de +

              O novo widget CardView permite exibir informações importantes dentro de cartões que têm aparência consistente.


              -

              Para obter mais informações, consulte Como criar +

              Para obter mais informações, consulte Como criar listas e cartões.

              Sombras de vistas

              -

              Além das propriedades X e Y, vistas no Android agora têm uma propriedade +

              Além das propriedades X e Y, vistas no Android agora têm uma propriedade Z. Essa nova propriedade representa a elevação de uma vista, que determina:

                @@ -130,7 +130,7 @@ Z. Essa nova propriedade representa a elevação de uma vista, que determina:

              -

              Para obter mais informações, consulte Como +

              Para obter mais informações, consulte Como definir sombras e recortar visualizações.

              @@ -165,7 +165,7 @@ Exibir animações em desenháveis da lista de estado entre mud

              Animações de feedback de toque são integradas em várias vistas padrão, como botões. As novas APIs permitem personalizar essas animações e adicioná-las às vistas personalizadas.

              -

              Para obter mais informações, consulte Como definir +

              Para obter mais informações, consulte Como definir animações personalizadas.

              @@ -182,5 +182,5 @@ uma cor em tempo de execução. imagem de mapa de bits. -

              Para obter mais informações, consulte Como trabalhar +

              Para obter mais informações, consulte Como trabalhar com desenháveis.

              diff --git a/docs/html-intl/intl/pt-br/design/patterns/compatibility.jd b/docs/html-intl/intl/pt-br/design/patterns/compatibility.jd index 775af0c312a0e8acbd7105d36846881146af5b61..bd4ec30ab1ed76bf07039e97b2be41a2a33275e3 100644 --- a/docs/html-intl/intl/pt-br/design/patterns/compatibility.jd +++ b/docs/html-intl/intl/pt-br/design/patterns/compatibility.jd @@ -57,7 +57,7 @@ de ações resultante tem o mesmo estilo que no exemplo anterior, mas é exibida

              Aplicativos legados em telefones com controles de navegação virtuais

              -

              Ao executar um aplicativo que foi desenvolvido para Android 2.3 ou anterior em um telefone com controles de +

              Ao executar um aplicativo que foi desenvolvido para Android 2.3 ou anterior em um telefone com controles de navegação virtuais, um controle de ações adicionais é exibido no lado direito da barra de navegação virtual. É possível tocar no controle para exibir as ações do aplicativo no estilo tradicional de menu do Android.

              diff --git a/docs/html-intl/intl/pt-br/design/patterns/navigation.jd b/docs/html-intl/intl/pt-br/design/patterns/navigation.jd index 8ed12f71b60b791042f0bed2905d37491c0cea2b..89eab9a4a19eecd6f354dd614182e0663422f52a 100644 --- a/docs/html-intl/intl/pt-br/design/patterns/navigation.jd +++ b/docs/html-intl/intl/pt-br/design/patterns/navigation.jd @@ -66,7 +66,7 @@ estará no mesmo lugar dentro da hierarquia do aplicativo e nenhum histórico de
            3. Mudar características de exibição (como mudar o zoom)
            4. Navegação entre telas de mesmo nível

              -

              Quando o aplicativo suporta navegação de uma lista de itens para uma vista de detalhes de um desses itens, +

              Quando o aplicativo suporta navegação de uma lista de itens para uma vista de detalhes de um desses itens, frequentemente é desejável dar suporte à navegação de direção daquele item para outro anterior ou posterior a ele na lista. Por exemplo, no Gmail, é fácil deslizar para a esquerda ou para a direita em uma conversa para visualizar uma mais nova ou mais antiga na mesma Caixa de entrada. Assim como ao mudar a vista dentro de uma tela, tal @@ -82,9 +82,9 @@ ignorar essas telas relacionadas e navegar para a tela do contêiner visualizada -

              Você tem a capacidade de deixar o comportamento de Para Cima ainda mais inteligente com base em seu conhecimento da +

              Você tem a capacidade de deixar o comportamento de Para Cima ainda mais inteligente com base em seu conhecimento da vista de detalhe. Estendendo o exemplo da Play Store acima, imagine que o usuário navegou do último -Livro visualizado para os detalhes da adaptação do Filme. Nesse caso, Para Cima pode retornar a um contêiner +Livro visualizado para os detalhes da adaptação do Filme. Nesse caso, Para Cima pode retornar a um contêiner (filmes) pelo qual o usuário não navegou anteriormente.

              @@ -116,7 +116,7 @@ botão Voltar continua até a Tela inicial.

              Notificações indiretas

              -

              Quando o aplicativo precisa apresentar simultaneamente informações sobre vários eventos, ele pode usar +

              Quando o aplicativo precisa apresentar simultaneamente informações sobre vários eventos, ele pode usar uma única notificação que direcione o usuário a uma tela intersticial. Essa tela resume esses eventos e fornece caminhos para que o usuário mergulhe profundamente no aplicativo. Notificações desse estilo são chamadas de notificações indiretas.

              @@ -128,7 +128,7 @@ tela intersticial, Para Cima e Voltar se comportam como em notificações padrã navegando dentro do aplicativo em vez de voltar à tela intersticial.

              Por exemplo, suponha que um usuário no Gmail receba uma notificação indireta do Agenda. Tocar nessa -notificação abrirá a tela intersticial, que exibirá lembretes para vários +notificação abrirá a tela intersticial, que exibirá lembretes para vários eventos. Tocar em Voltar na tela intersticial retornará o usuário ao Gmail. Tocar em um determinado evento levará o usuário da tela intersticial ao aplicativo completo do Agenda para exibir detalhes do evento. Dos detalhes do evento, Para Cima e Voltar navegam para a vista de nível superior do Agenda.

              @@ -169,7 +169,7 @@ informações e todas as ações associadas que o usuário pode executar. Seu ap atividades, consistindo em atividades que você cria e naquelas que reutiliza de outros aplicativos.

              Uma tarefa é a sequência de atividades que um usuário segue para atingir um objetivo. Uma -única tarefa pode usar atividades apenas de um aplicativo ou pode retirar atividades de uma série +única tarefa pode usar atividades apenas de um aplicativo ou pode retirar atividades de uma série de outros aplicativos.

              Uma intenção é um mecanismo para que um aplicativo sinalize que gostaria a assistência de outro @@ -188,7 +188,7 @@ que foram registradas para tratar a intenção Compartilhar.

              -

              Quando o usuário seleciona o compartilhamento via Gmail, a atividade de composição do Gmail é adicionada como uma continuação da +

              Quando o usuário seleciona o compartilhamento via Gmail, a atividade de composição do Gmail é adicionada como uma continuação da Tarefa A — nenhuma tarefa nova é criada. Se o Gmail tivesse a própria tarefa em execução em segundo plano, ela não seria afetada.

              @@ -209,5 +209,5 @@ Recentes). Se o Gmail já tivesse a própria tarefa em execução em segundo pla pela Tarefa B — o contexto anterior é abandonado em favor do novo objetivo do usuário.

              Quando o aplicativo é registrado para tratar intenções com uma atividade em um ponto profundo da hierarquia do aplicativo, -consulte Navegação para o seu aplicativo pelos widgets de tela +consulte Navegação para o seu aplicativo pelos widgets de tela inicial e notificações para ver orientações sobre como especificar a navegação Para Cima.

              diff --git a/docs/html-intl/intl/pt-br/design/patterns/notifications.jd b/docs/html-intl/intl/pt-br/design/patterns/notifications.jd deleted file mode 100644 index efea6104638c4e795a6d9d4bb489449a0b4b3b82..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/pt-br/design/patterns/notifications.jd +++ /dev/null @@ -1,872 +0,0 @@ -page.title=Notificações -page.tags="notifications","design","L" -@jd:body - - -
              -

              Documentos do desenvolvedor

              -

              Notificação ao usuário

              -
              -
              - - -
              -

              Notificações no Android 4.4 e em anteriores

              -
              -
              - - - -
              -

              Vídeo

              -

              DevBytes: Notificações na pré-visualização do desenvolvedor do Android L

              -
              -
              - - - -

              O sistema de notificações permite que os usuários se mantenham informados sobre eventos relevantes e -imediatos -no aplicativo, como novas mensagens de bate-papo de um amigo ou um evento de calendário. -Pense nas notificações como um canal de notícias que alerta o usuário sobre eventos -importantes à -medida que acontecem ou sobre um registro que grava eventos enquanto o usuário não está prestando -atenção — e que é sincronizado conforme apropriado em todos os dispositivos Android dele.

              - -

              Novo no Android 5.0

              - -

              No Android 5.0, as notificações recebem atualizações importantes: em termos estruturais, visuais e -funcionais:

              - -
                -
              • As notificações passaram por mudanças visuais consistentes com o novo -tema do Material Design.
              • -
              • As notificações agora estão disponíveis na tela de bloqueio do dispositivo, enquanto que -o conteúdo sensível ainda pode -ficar oculto atrás dela.
              • -
              • Notificações de alta prioridade recebidas enquanto o dispositivo está em uso agora usam um novo formato, chamado de -notificações heads-up.
              • -
              • Notificações sincronizadas na nuvem: descartar uma notificação em um dos -dispositivos Android a descarta -também nos outros.
              • -
              - -

              Observação: o projeto de notificação nesta versão do -Android é uma mudança -significativa em relação às versões anteriores. Para obter informações sobre o projeto de notificação em versões -anteriores, consulte Notificações no Android 4.4 ou em anteriores.

              - -

              Anatomia de uma notificação

              - -

              Esta seção aborda as partes básicas de uma notificação e como elas -podem aparecer em diferentes tipos de dispositivos.

              - -

              Layout básico

              - -

              No mínimo, todas as notificações consistem em um layout básico, incluindo:

              - -
                -
              • O ícone da notificação. O ícone simboliza o -aplicativo de origem. Ele também - pode indicar o tipo de notificação, caso o aplicativo gere mais de um -tipo.
              • -
              • Um título da notificação e -texto adicional.
              • -
              • Uma marcação de data e hora.
              • -
              - -

              Notificações criadas com {@link android.app.Notification.Builder Notification.Builder} -para versões anteriores da plataforma têm a mesma aparência e o mesmo funcionamento no Android -5.0, com apenas mudanças menores de estilo que o sistema -entrega a você. Para obter mais informações sobre notificações em versões -anteriores do Android, consulte -Notificações no Android 4.4 ou em anteriores.

              - - - - - -
              -

              - Layout básico de uma notificação em dispositivo portátil (à esquerda) e a mesma notificação em Wear (à direita), -com uma foto do usuário e um ícone de notificação -

              -
              - -

              Layouts expandidos

              - - -

              Você pode escolher o nível de detalhe que as notificações de seu aplicativo -devem fornecer. Elas podem mostrar as primeiras -linhas de uma mensagem ou exibir uma visualização de imagem maior. As informações -adicionais fornecem ao usuário mais -contexto e — em alguns casos — podem permitir que o usuário leia uma mensagem -em sua totalidade. O usuário pode -pinçar para aproximar ou afastar a vista ou realizar deslizamento de um dedo para alternar entre os layouts -compacto e expandido. - Para notificações de um evento, o Android fornece três modelos de layout -expandido (texto, caixa de entrada e - imagem) para usar em seu aplicativo. As imagens a seguir mostram como -se parecem notificações de um evento em - dispositivos portáteis (à esquerda) e usados junto ao corpo (à direita).

              - - - - - -

              Ações

              - -

              O Android tem suporte para ações opcionais que são exibidas na parte inferior -da notificação. -Com ações, os usuários podem tratar as tarefas mais comuns para -determinada notificação de dentro da sombra da notificação sem precisar abrir o -aplicativo de origem. -Isso acelera a interação e, em conjunto com deslizar-para-descartar, ajuda os usuários a -se concentrarem em notificações que sejam importantes.

              - - - - - - -

              Tenha cuidado com o número de ações que inclui em uma -notificação. Quanto mais -ações incluir, maior será a complexidade cognitiva criada. Limite-se -ao menor número possível -de ações, incluindo apenas as ações efetivamente mais importantes e -significativas.

              - -

              Boas candidatas a ações em notificações são ações que:

              - -
                -
              • Sejam essenciais, frequentes e típicas para o tipo de conteúdo -exibido -
              • Permitam que o usuário realize tarefas rapidamente -
              - -

              Evite ações que sejam:

              - -
                -
              • Ambíguas -
              • Idênticas à ação padrão da notificação (como "Ler" ou -"Abrir") -
              - - - -

              Você pode especificar no máximo três ações, cada uma consistindo em um ícone -e um nome de ação. - Adicionar ações a um layout básico simples torna a notificação expansível, -mesmo se a -notificação não tiver um layout expandido. Como as ações são exibidas apenas para notificações -expandidas - e que ficam de outra forma ocultas, certifique-se de que qualquer ação que um -usuário possa invocar de dentro de uma - notificação esteja disponível também dentro do aplicativo -associado.

              - -

              Notificação heads-up

              -
              - -

              - Exemplo de uma notificação heads-up (chamada telefônica recebida, alta prioridade) -que aparece sobre um -aplicativo imersivo -

              -
              - -

              Quando uma notificação de alta prioridade chega (veja à direita), ela é apresentada -aos usuários por -um período curto com um layout expandido mostrando possíveis ações.

              -

              Depois desse período, a notificação recua para a sombra -de notificação. Se a prioridade de uma notificação for -marcada como Alta, Máxima ou tela cheia, ela receberá uma notificação heads-up.

              - -

              Bons exemplos de notificações heads-up

              - -
                -
              • Chamada telefônica recebida durante o uso do dispositivo
              • -
              • Alarme durante o uso do dispositivo
              • -
              • Nova mensagem SMS
              • -
              • Bateria fraca
              • -
              - -

              Diretrizes

              - - -

              Torne-a pessoal

              - -

              Para notificações de itens enviados por outra pessoa (como uma mensagem ou -atualização de status), inclua a imagem da pessoa usando -{@link android.app.Notification.Builder#setLargeIcon setLargeIcon()}. Anexe também informações sobre -a pessoa nos metadados da notificação (consulte {@link android.app.Notification#EXTRA_PEOPLE}).

              - -

              O ícone principal de sua notificação ainda é mostrado, portanto, o usuário pode associá-lo -ao ícone -visível na barra de status.

              - - - -

              - Notificação que mostra a pessoa que a ativou e o conteúdo enviado. -

              - - - - -

              Quando o usuário toca no corpo de uma notificação (fora dos botões -de ação), abra o aplicativo -no lugar em que o usuário possa visualizar e agir sobre os dados referenciados na -notificação. Na maioria dos casos, será a exibição detalhada de um único item de dado, como uma mensagem, -mas também poderá ser uma -vista resumida se a notificação estiver empilhada. Se o aplicativo -levar o usuário a qualquer lugar abaixo do nível superior do aplicativo, insira a navegação na pilha de retorno do aplicativo para que -o usuário possa pressionar o botão Voltar do sistema para voltar ao nível superior. Para obter mais informações, consulte -Navegação para o seu aplicativo pelos widgets de página inicial e notificações no padrão de projeto de Navegação. -

              - -

              Definição e gerenciamento -corretos da prioridade das -notificações

              - -

              O Android tem suporte para um sinalizador de prioridade para notificações. Esse sinalizador permite -influenciar o local em que a notificação é exibida em relação a outras notificações e -ajuda a garantir -que os usuários sempre vejam primeiro as notificações mais importantes. Você pode escolher entre -os seguintes -níveis de prioridade ao publicar uma notificação:

              -
      - - - - - - - - - - - - - - - - - - - - - - - - -
      -

      Prioridade

      -
      -

      Uso

      -
      -

      MAX

      -
      -

      Use para notificações críticas e urgentes que alertam o usuário sobre uma condição -que depende -do tempo ou que precisa ser resolvida antes que o usuário possa continuar -com uma determinada tarefa.

      -
      -

      HIGH

      -
      -

      Use principalmente para comunicações importantes, como uma mensagem ou -eventos de bate-papo com conteúdo particularmente interessante para o usuário. -Notificações de alta prioridade acionam a exibição de uma notificação heads-up.

      -
      -

      DEFAULT

      -
      -

      Use para todas as notificações que não recaiam em nenhuma das outras prioridades descritas aqui.

      -
      -

      LOW

      -
      -

      Use para notificações sobre as quais deseja que o usuário seja informado, mas -que sejam menos urgentes. Notificações de baixa prioridade tendem a ser exibidas na parte inferior da lista, -o que as torna uma boa -opção para coisas como atualizações públicas ou sociais não direcionadas: o usuário pediu para -ser notificado sobre -elas, mas essas notificações nunca devem ter precedência sobre comunicações -urgentes ou diretas.

      -
      -

      MIN

      -
      -

      Use para informações contextuais ou de histórico, como informações sobre clima ou -informações contextuais de localização. -Notificações de prioridade mínima não aparecem na barra de status. O usuário -as descobre expandindo a sombra da notificação.

      -
      - - -

      Como escolher uma prioridade -adequada -

      - -

      DEFAULT, HIGH e MAX são níveis de prioridade de interrupção e arriscam -interromper a atividade -do usuário. Para evitar irritar os usuários de seu aplicativo, reserve níveis de prioridade de interrupção para -notificações que:

      - -
        -
      • Envolvam outra pessoa
      • -
      • Dependam do tempo
      • -
      • Possam mudar imediatamente o comportamento do usuário no mundo real
      • -
      - -

      Notificações definidas como LOW e MIN ainda podem -ser valiosas para o usuário: muitas, se não a maioria, das notificações não precisam demandar a atenção -imediata do usuário, ou vibrar o pulso do usuário, mas ainda contêm informações que o usuário -achará valiosas ao decidir procurar -notificações. Os critérios para notificações de prioridade LOW e MIN -incluem:

      - -
        -
      • Não envolver outras pessoas
      • -
      • Não depender de tempo
      • -
      • Ter conteúdo no qual o usuário pode estar interessado, mas que pode decidir -verificar no momento em que desejar
      • -
      - - - - - -

      Definição de uma categoria -de notificação

      - -

      Se a sua notificação recair em uma das categorias predefinidas (veja -abaixo), atribua-a -adequadamente. Aspectos da IU do sistema, como a sombra da notificação (ou qualquer -outra escuta -de notificação), podem usar essas informações para tomar decisões de classificação e filtragem.

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -

      CATEGORY_CALL

      -
      -

      Chamada recebida (voz ou vídeo) ou solicitação similar de -comunicação síncrona

      -
      -

      CATEGORY_MESSAGE

      -
      -

      Mensagem direta recebida (SMS, mensagem instantânea etc.)

      -
      -

      CATEGORY_EMAIL

      -
      -

      Mensagens assíncronas em lote (e-mail)

      -
      -

      CATEGORY_EVENT

      -
      -

      Evento de calendário

      -
      -

      CATEGORY_PROMO

      -
      -

      Promoção ou publicidade

      -
      -

      CATEGORY_ALARM

      -
      -

      Alarme ou cronômetro

      -
      -

      CATEGORY_PROGRESS

      -
      -

      Andamento de uma operação de execução longa em segundo plano

      -
      -

      CATEGORY_SOCIAL

      -
      -

      Atualização de rede social ou de compartilhamento

      -
      -

      CATEGORY_ERROR

      -
      -

      Erro em operação de segundo plano ou no status de autenticação

      -
      -

      CATEGORY_TRANSPORT

      -
      -

      Controle de transporte de mídia para reprodução

      -
      -

      CATEGORY_SYSTEM

      -
      -

      Atualização do sistema ou do status do dispositivo. Reservado para uso do sistema.

      -
      -

      CATEGORY_SERVICE

      -
      -

      Indicação de serviço de segundo plano em execução

      -
      -

      CATEGORY_RECOMMENDATION

      -
      -

      Uma recomendação específica e oportuna para uma única coisa. Por exemplo, um aplicativo -de notícias pode querer -recomendar uma notícia que acredita que o usuário desejará ler em seguida.

      -
      -

      CATEGORY_STATUS

      -
      -

      Informações contínuas sobre o dispositivo ou o status contextual

      -
      - -

      Resuma as notificações

      - -

      Se uma notificação de um certo tipo já estiver pendente quando o aplicativo tentar enviar uma nova -notificação do mesmo tipo, combine-as em uma única notificação de resumo para o aplicativo. Não -crie um novo objeto.

      - -

      Uma notificação de resumo cria uma descrição resumida e permite que o -usuário entenda quantas notificações -de um determinado tipo estão pendentes.

      - -
      - -

      O que não fazer

      - -
      - -
      -

      O que fazer

      - - -
      - -

      Você pode fornecer -mais detalhes sobre as notificações individuais que compõem um -resumo usando o layout resumido expandido. Essa abordagem permite que os usuários -entendam melhor quais -notificações estão pendentes e decidam se estão interessados o suficiente para lê-las -em detalhes dentro -do aplicativo associado.

      -
      - -

      - Notificação expandida e contraída que é um resumo (usando InboxStyle) -

      -
      - -

      Torne as notificações -opcionais

      - -

      Os usuários devem sempre controlar as notificações. Permita que o usuário -desative as notificações -de seu aplicativo ou altere as propriedades de alerta, como som de alerta e -se a vibração será usada, -adicionando um item de configuração da notificação nas configurações do aplicativo.

      - -

      Use ícones distintos

      -

      Ao olhar para a área de notificação, o usuário deverá ser capaz de discernir -que tipos de -notificações estão atualmente pendentes.

      - -
      - -
      - -

      O que fazer

      -

      Verifique os ícones de notificação que os aplicativos do Android já fornecem e crie -ícones de notificação para o seu -aplicativo que tenham aparência suficientemente distinta.

      - -

      O que fazer

      -

      Use o estilo de ícone de notificação apropriado - para ícones pequenos e o - estilo de ícone de barra -de ação da luminosidade do Material para os ícones - de ação.

      -

      O que fazer

      -

      Mantenha os ícones visualmente simples, evitando detalhes excessivos que sejam -difíceis de discernir.

      - -

      O que não fazer

      -

      Coloque um alfa adicional (esmaecimento ou redução de intensidade) nos ícones pequenos -e nos ícones de - ação; eles podem ter bordas suavizadas, mas, como o Android usa esses -ícones como máscaras (ou seja, somente - o canal alfa é usado), a imagem normalmente deve ser desenhada com -opacidade total.

      - -
      -

      O que não fazer

      - -

      Use cores para distinguir o seu aplicativo dos outros. Ícones de notificação devem -somente ser uma imagem com fundo branco sobre transparente.

      - - -

      Pisque o LED de notificação -adequadamente

      - -

      Muitos dispositivos Android contêm um LED de notificação, que é usado para manter o -usuário informado sobre -eventos enquanto a tela está desligada. Notificações com um nível de prioridade de MAX, -HIGH ou DEFAULT devem -fazer com que o LED brilhe, enquanto que os de prioridade mais baixa (LOW e -MIN) não devem.

      - -

      O controle do usuário sobre as notificações deve se estender ao LED. Ao usar -DEFAULT_LIGHTS, o -LED brilhará na cor branca. Suas notificações não devem usar uma cor -diferente, a não ser que o -usuário as tenha explicitamente personalizado.

      - -

      Criação de notificações -que agradam aos usuários

      - -

      Para criar um aplicativo que os usuários amem, é importante projetar as -notificações cuidadosamente. -As notificações personificam a voz do seu aplicativo e contribuem para -a personalidade dele. Notificações indesejadas ou -irrelevantes podem irritar o usuário ou fazer com que ele reprove a -quantidade de atenção que o -aplicativo exige. Portanto, use notificações de forma cuidadosa.

      - -

      Quando exibir uma notificação

      - -

      Para criar um aplicativo que as pessoas gostem de usar, é importante -reconhecer que a atenção e o foco -do usuário são recursos que devem ser protegidos. Apesar de o sistema de -notificação do Android ter -sido projetado para minimizar o impacto das notificações na atenção do usuário, -ainda é -importante ter ciência do fato de que as notificações interrompem o -fluxo de tarefas do usuário. -Ao planejar as notificações, pergunte-se se elas são importantes o suficiente para -justificar uma interrupção. Se não tiver certeza, permita que o usuário decida se quer -uma notificação usando as configurações de notificação do seu aplicativo ou ajuste -o sinalizador de prioridade das notificações para LOW ou MIN para -evitar distrair o usuário enquanto ele faz -alguma outra coisa.

      - - -

      - Exemplos de notificação que depende de tempo -

      - -

      Apesar de aplicativos bem comportados geralmente se manifestarem apenas quando ocorre interação com eles, alguns -casos justificam que o aplicativo interrompa o usuário com uma notificação não solicitada.

      - -

      Use notificações principalmente para eventos que dependam de tempo, especialmente - se esses eventos síncronos envolverem outras pessoas. Por -exemplo, um bate-papo recebido -é uma forma síncrona em tempo real de comunicação: outro usuário -espera ativamente a resposta. Eventos de calendário são outro exemplo bom de quando usar uma -notificação e atrair a -atenção do usuário, pois o evento é iminente e eventos de calendário frequentemente -envolvem outras pessoas.

      - -

      Quando não exibir -uma notificação

      - -
      - -
      - -

      Em muitos outros casos, notificações não são adequadas:

      - -
        -
      • Evite notificar o usuário sobre informações que não são especificamente -direcionadas a ele ou -que não dependam realmente de tempo. Por exemplo, as atualizações -assíncronas e não direcionadas -que fluem por uma rede social geralmente não justificam uma interrupção -em tempo real. Para os usuários que se importam -com elas, deixe que decidam recebê-las.
      • -
      • Não crie uma notificação se as informações novas relevantes estiverem -atualmente na tela. Em vez disso, -use a IU do próprio aplicativo para notificar o usuário das novas informações -diretamente no contexto. - Por exemplo, um aplicativo de bate-papo não deve criar notificações de sistema enquanto o -usuário estiver conversando ativamente com outro usuário.
      • -
      • Não interrompa o usuário para realizar operações técnicas de baixo nível, como salvar -ou sincronizar informações, nem atualize um aplicativo se o aplicativo ou o sistema puder resolver -o problema sem envolver o usuário.
      • -
      • Não interrompa o usuário para informar um erro se o aplicativo -puder se recuperar dele por conta própria, sem que o usuário -tome qualquer ação.
      • -
      • Não crie notificações que não tenham conteúdo real de notificação e -que meramente anunciem o seu -aplicativo. Uma notificação deve fornecer informações úteis, oportunas e novas e -não deve ser usada -meramente para executar um aplicativo.
      • -
      • Não crie notificações supérfluas apenas para colocar sua marca na frente -dos usuários. - Tais notificações frustram e provavelmente alienam seu público-alvo. A -melhor forma de fornecer - pequenas quantidades de informações atualizadas e manter o usuário envolvido -com o seu - aplicativo é desenvolver um widget que ele possa colocar na -tela inicial.
      • -
      - -

      Interação com -notificações

      - -

      Notificações são indicadas por ícones na barra de status e podem ser acessadas -abrindo a -gaveta de notificações.

      - -

      Tocar em uma notificação abre o aplicativo associado com o conteúdo -detalhado que corresponde à notificação. -Deslizar à esquerda ou à direita em uma notificação a remove da gaveta.

      - -

      Notificações contínuas

      -
      - -

      - Notificação contínua devido à reprodução de música -

      -
      -

      Notificações contínuas mantêm os usuários informados sobre um processo em andamento em -segundo plano. -Por exemplo, reprodutores de música anunciam a faixa em reprodução no -sistema de notificação e -continuam a fazer isso até que o usuário interrompa a reprodução. Notificações contínuas também podem -mostrar ao usuário -feedback sobre tarefas mais longas, como o download de um arquivo ou a codificação de um vídeo. Um usuário não pode remover -manualmente uma notificação contínua da gaveta de notificações.

      - -

      Reprodução de mídia

      -

      No Android 5.0, a tela de bloqueio não mostra controles de transporte por causa da classe -{@link android.media.RemoteControlClient} obsoleta. Mas ela mostra notificações, portanto, a notificação de reprodução -de cada aplicativo agora é a forma -principal para que os usuários controlem a reprodução em um estado bloqueado. Esse comportamento dá aos aplicativos mais -controle sobre quais -botões exibir e de que forma, ao mesmo tempo em que fornece uma experiência consistente -para o usuário, com a tela bloqueada ou não.

      - -

      Diálogos -e avisos

      - -

      O seu aplicativo não deve criar uma caixa de diálogo ou um aviso se não estiver -atualmente na tela. Uma caixa de diálogo ou um aviso - deve ser exibido somente como uma resposta imediata ao usuário tomando uma ação -dentro do seu aplicativo. -Para obter orientação adicional sobre o uso de caixas de diálogo e avisos, consulte -Confirmação e reconhecimento.

      - -

      Avaliação e classificação

      - -

      Notificações são notícias e, portanto, são essencialmente exibidas -em ordem cronológica inversa, com -consideração especial para a -prioridade da notificação declarada no aplicativo.

      - -

      Notificações são uma parte importante da tela de bloqueio e são exibidas proeminentemente -sempre -que a tela do dispositivo é exibida. O espaço na tela de bloqueio é restrito, portanto, -é mais importante -do que nunca identificar as notificações mais urgentes ou relevantes. Por esse -motivo, o Android tem um -algoritmo de classificação mais sofisticado para notificações, levando em conta:

      - -
        -
      • A marcação de data e hora e a prioridade declarada no aplicativo.
      • -
      • Se a notificação incomodou recentemente o usuário com som ou -vibração (ou seja, - se o celular acabou de fazer um ruído e o usuário deseja saber "O que acabou de -acontecer?", a tela de bloqueio - deve responder com um olhar rápido).
      • -
      • Qualquer pessoa anexada à notificação usando {@link android.app.Notification#EXTRA_PEOPLE} - e, em particular, se é contato especial (com estrelas).
      • -
      - -

      Para aproveitar ao máximo essa classificação, concentre-se na experiência -do usuário que deseja -criar, e não em um determinado local na lista.

      - - - -

      Notificações do Gmail têm -prioridade padrão e normalmente - são classificadas abaixo de mensagens de um aplicativo de mensagem instantânea, como o Hangouts, mas -recebem - uma promoção temporária quando novas mensagens chegam. -

      - - -

      Na tela de bloqueio

      - -

      Como as notificações são visíveis na tela de bloqueio, a privacidade do usuário é uma consideração -especialmente - importante. Notificações frequentemente contêm informações sensíveis e -não devem necessariamente estar visíveis -para qualquer pessoa que ligar a tela do dispositivo.

      - -
        -
      • Para dispositivos que têm uma tela de bloqueio segura (PIN, padrão ou senha), a interface tem -partes públicas e privadas. A interface pública pode ser exibida em uma tela de bloqueio segura e, -portanto, vista por qualquer pessoa. A interface privada é o mundo atrás da tela de bloqueio e -só é revelada depois que o usuário faz login no dispositivo.
      • -
      - -

      Controle do usuário sobre as informações exibidas na tela de bloqueio segura

      -
      - -

      - Notificações na tela de bloqueio com conteúdo revelado depois que o usuário desbloqueia o dispositivo. -

      -
      - -

      Ao definir uma tela de bloqueio segura, o usuário poderá escolher ocultar -detalhes sensíveis da tela de bloqueio segura. Nesse caso, a IU do sistema -considerará o nível de visibilidade da notificação para descobrir o que pode -ser exibido com segurança.

      -

      Para controlar o nível de visibilidade, chame -Notification.Builder.setVisibility() -e especifique um destes valores:

      - -
        -
      • VISIBILITY_PUBLIC. -Exibe o conteúdo inteiro da notificação. - Esse é o padrão do sistema se a visibilidade não for especificada.
      • -
      • VISIBILITY_PRIVATE. -Na tela de bloqueio, exibe informações básicas sobre essa notificação, incluindo o -ícone e o nome do aplicativo que a publicou. O restante dos detalhes da notificação não é exibido. -Alguns pontos a ter em mente são: -
          -
        • Se você quer fornecer uma versão pública diferente da sua notificação -para que o sistema a exiba em uma tela de bloqueio segura, forneça um objeto -Notificação substituto no campo Notification.publicVersion. - -
        • Essa configuração dá ao aplicativo uma oportunidade de criar uma versão alternativa do -conteúdo que ainda é útil, mas não revela informações pessoais. Considere o exemplo de um -aplicativo de SMS cujas notificações incluem o texto da mensagem SMS, o nome do remetente e o ícone do contato. -Essa notificação deve ser VISIBILITY_PRIVATE, mas publicVersion ainda pode -conter informações úteis, como "3 novas mensagens", sem outros detalhes -de identificação. -
        -
      • -
      • Notification.VISIBILITY_SECRET. Mostra apenas as informações mínimas, excluindo até mesmo -o ícone da notificação.
      • -
      -

      Notificações no -Android Wear

      - -

      Notificações e suas ações são enviadas a dispositivos Wear por padrão. -Os desenvolvedores podem controlar que notificações são enviadas do -celular ao relógio -e vice-versa. Os desenvolvedores também podem controlar quais ações são transmitidas. Se o -seu aplicativo inclui -ações que não podem ser executadas com um toque, oculte essas ações -na sua notificação do Wear -ou considere colocá-las em um aplicativo do Wear, permitindo que o usuário -termine a ação -no relógio.

      - -

      Transmissão de notificações e ações

      - -

      Um dispositivo conectado, como um celular, pode transmitir notificações para um dispositivo Wear para que as -notificações sejam exibidas nele. De forma similar, ele pode transmitir ações para que o usuário possa agir -sobre as notificações diretamente do dispositivo Wear.

      - -

      Transmitir

      - -
        -
      • Novas mensagens instantâneas
      • -
      • Ações de um toque, como +1, Curtir, Coração
      • -
      - - - -

      Não transmitir

      - -
        -
      • Notificações de podcasts recém-chegados
      • -
      • Ações que mapeiem para recursos que não são possíveis no relógio
      • -
      - - - -

      Ações exclusivas a definir para Wear

      - -

      Há algumas ações que só podem ser realizadas em Wear. Elas incluem:

      - -
        -
      • Listas rápidas de respostas prontas, como "Volto logo"
      • -
      • Abrir no celular
      • -
      • Uma ação "Comentar" ou "Responder" que abre a tela de entrada de voz
      • -
      • Ações que executam aplicativos específicos de Wear
      • -
      - - diff --git a/docs/html-intl/intl/pt-br/guide/components/bound-services.jd b/docs/html-intl/intl/pt-br/guide/components/bound-services.jd index aa024943160f9609acda72f5ae8aeec4fb68fa9c..032950eb962bbe69953125574b000a5ac1d4d228 100644 --- a/docs/html-intl/intl/pt-br/guide/components/bound-services.jd +++ b/docs/html-intl/intl/pt-br/guide/components/bound-services.jd @@ -334,7 +334,7 @@ que o serviço realize vários encadeamentos, deve-se usar a estendendo a classe Binder para que tudo que ele tenha que fazer seja lançar o {@link android.os.IBinder} retornado para a classe {@code LocalService} e solicitar a instância de {@code LocalService}:

      @@ -637,7 +637,7 @@ android.content.Context#stopService stopService()}, independente de vínculo com qualquer cliente.

      Além disso, se o serviço for iniciado e aceitar vínculos, quando o sistema chamar -o método {@link android.app.Service#onUnbind onUnbind()}, será possível retornar +o método {@link android.app.Service#onUnbind onUnbind()}, será possível retornar {@code true} opcionalmente se você quiser receber uma chamada de {@link android.app.Service#onRebind onRebind()} na próxima vez em que um cliente vincular-se ao serviço (em vez de receber uma chamada de {@link android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind diff --git a/docs/html-intl/intl/pt-br/guide/components/fragments.jd b/docs/html-intl/intl/pt-br/guide/components/fragments.jd index 7b1acf9e3439ce87687f833fe15c64a2e661f4cb..74f3dfe2d15b337a94158e91ddcb32ac723ac4eb 100644 --- a/docs/html-intl/intl/pt-br/guide/components/fragments.jd +++ b/docs/html-intl/intl/pt-br/guide/components/fragments.jd @@ -36,7 +36,7 @@ parent.link=activities.html

    • {@link android.app.FragmentManager}
    • {@link android.app.FragmentTransaction}
    • - +

      Veja também

      1. Construção de uma IU dinâmica com Fragmentos
      2. @@ -361,8 +361,8 @@ você precisará usar {@link android.app.FragmentManager#findFragmentByTag findFragmentByTag()}.

        Para ver uma atividade de exemplo que usa um fragmento como um trabalhador de segundo plano, sem uma IU, consulte o exemplo de {@code -FragmentRetainInstance.java}, incluso nos exemplos do SDK (disponibilizados pelo -Android SDK Manager) e localizado no sistema como +FragmentRetainInstance.java}, incluso nos exemplos do SDK (disponibilizados pelo +Android SDK Manager) e localizado no sistema como <sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java.

        @@ -378,7 +378,7 @@ chame {@link android.app.Activity#getFragmentManager()} a partir da atividade.Adquirir fragmentos existentes na atividade, com {@link android.app.FragmentManager#findFragmentById findFragmentById()} (para fragmentos que forneçam uma IU no layout da atividade) ou {@link android.app.FragmentManager#findFragmentByTag -findFragmentByTag()} (para fragmentos que forneçam ou não uma IU). +findFragmentByTag()} (para fragmentos que forneçam ou não uma IU).
      3. Retire os fragmentos da pilha de retorno com {@link android.app.FragmentManager#popBackStack()} (simulando um comando de Voltar do usuário).
      4. Registre uma escuta para as alterações na pilha de retorno com {@link @@ -600,7 +600,7 @@ como usar o provedor de conteúdo estão disponíveis na documentação Adição de itens à barra de ação -

        Os fragmentos podem contribuir com itens de menu para o menu de opções da atividade (e, consequentemente, para a barra de ação) implementando +

        Os fragmentos podem contribuir com itens de menu para o menu de opções da atividade (e, consequentemente, para a barra de ação) implementando {@link android.app.Fragment#onCreateOptionsMenu(Menu,MenuInflater) onCreateOptionsMenu()}. Para que este método receba chamadas, no entanto, você deve chamar {@link android.app.Fragment#setHasOptionsMenu(boolean) setHasOptionsMenu()} durante {@link @@ -785,7 +785,7 @@ android.widget.FrameLayout}), ou iniciar uma nova atividade (onde o fragmento po

        O segundo fragmento, {@code DetailsFragment}, exibe o resumo da peça para o item selecionado na lista de {@code TitlesFragment}:

        - + {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}

        Uma nova chamada da classe {@code TitlesFragment}, ou seja, se o usuário clicar em um item de lista @@ -798,7 +798,7 @@ o resumo da peça selecionada quando a tela está na orientação de retrato:

        Observe que esta atividade finaliza-se se a configuração for de paisagem, pois a atividade principal pode tomar o controle e exibir {@code DetailsFragment} juntamente com {@code TitlesFragment}. Isto pode acontecer se o usuário iniciar {@code DetailsActivity} enquanto estiver na orientação de retrato, diff --git a/docs/html-intl/intl/pt-br/guide/components/fundamentals.jd b/docs/html-intl/intl/pt-br/guide/components/fundamentals.jd index 47b98458e6429755bb32db773853014f557382c2..2fb85531de8a6465fc0aad90f76bc926cfef972d 100644 --- a/docs/html-intl/intl/pt-br/guide/components/fundamentals.jd +++ b/docs/html-intl/intl/pt-br/guide/components/fundamentals.jd @@ -379,7 +379,7 @@ mas serviços externos, como o Google Play, as leem para oferecer uma filtragem aos usuários quando buscam esses aplicativos para seu dispositivo.

        Por exemplo: se o aplicativo exige uma câmera e usa APIs introduzidas no Android 2.1 (API de nível 7), -deve-se declarar esses requisitos no arquivo de manifesto da seguinte forma:

        +deve-se declarar esses requisitos no arquivo de manifesto da seguinte forma:

         <manifest ... >
        @@ -393,7 +393,7 @@ deve-se declarar esses requisitos no arquivo de manifesto da seguinte forma:

        Assim, dispositivos que não tenham câmera e tenham versão Android anterior a 2.1 não poderão instalar o aplicativo a partir do Google Play.

        -

        No entanto, também é possível declarar que o aplicativo usa a câmera como recurso +

        No entanto, também é possível declarar que o aplicativo usa a câmera como recurso não obrigatório. Nesse caso, o aplicativo precisa definir o atributo {@code required} como {@code "false"} e verificar em tempo de execução se o dispositivo tem câmera e desativar os recursos da câmera conforme o necessário.

        diff --git a/docs/html-intl/intl/pt-br/guide/components/index.jd b/docs/html-intl/intl/pt-br/guide/components/index.jd index 02fcaa63c63a78d5b3982a429e71ee11f6037561..5131ead2239c3bb8ae037d1be7827042d39c2ff4 100644 --- a/docs/html-intl/intl/pt-br/guide/components/index.jd +++ b/docs/html-intl/intl/pt-br/guide/components/index.jd @@ -1,7 +1,7 @@ page.title=Componentes do aplicativo page.landing=true -page.landing.intro=A estrutura de aplicativo do Android permite criar aplicativos ricos e inovadores usando um conjunto de componentes reutilizáveis. Esta seção explica como criar os componentes que definem os blocos de construção do aplicativo e como conectá-los usando intenções. -page.metaDescription=A estrutura de aplicativo do Android permite criar aplicativos ricos e inovadores usando um conjunto de componentes reutilizáveis. Esta seção mostra como criar os componentes que definem os blocos de construção do aplicativo e como conectá-los usando intenções. +page.landing.intro=A estrutura de aplicativo do Android permite criar aplicativos ricos e inovadores usando um conjunto de componentes reutilizáveis. Esta seção explica como criar os componentes que definem os blocos de construção do aplicativo e como conectá-los usando intenções. +page.metaDescription=A estrutura de aplicativo do Android permite criar aplicativos ricos e inovadores usando um conjunto de componentes reutilizáveis. Esta seção mostra como criar os componentes que definem os blocos de construção do aplicativo e como conectá-los usando intenções. page.landing.image=images/develop/app_components.png page.image=images/develop/app_components.png @@ -11,7 +11,7 @@ page.image=images/develop/app_components.png

        Artigos de blogue

        - +

        Uso de DialogFragments

        Nesta publicação, mostrarei como usar DialogFragments com a biblioteca de suporte v4 (para compatibilidade retroativa em dispositivos anteriores a Honeycomb) para mostrar uma caixa de diálogo de edição simples e retornar um resultado para a Atividade chamadora usando uma interface.

        @@ -21,7 +21,7 @@ page.image=images/develop/app_components.png

        Fragmentos para todos

        Hoje, lançamos uma biblioteca estática que expõe a mesma API Fragments (bem como o novo LoaderManager e algumas outras classes) para que aplicativos compatíveis com Android 1.6 e posteriores possam usar fragmentos para criar interfaces de usuário compatíveis com tablets.

        - +

        Multiencadeamento para desempenho

        Uma boa prática para criar aplicativos responsivos é garantir que o encadeamento principal da IU @@ -32,11 +32,11 @@ em um encadeamento diferente.

        Treinamento

        - +

        Gerenciamento do ciclo de vida da atividade

        Essa lição explica a importância dos métodos de retorno de chamada do ciclo de vida que cada instância de -Atividade recebe e como utilizá-los para que a atividade faça o que o usuário espera e não consuma recursos +Atividade recebe e como utilizá-los para que a atividade faça o que o usuário espera e não consuma recursos do sistema quando não estiver em uso.

        diff --git a/docs/html-intl/intl/pt-br/guide/components/loaders.jd b/docs/html-intl/intl/pt-br/guide/components/loaders.jd index f3c42094729db5224090075ffa53744402e7229b..c69cbbfd25d2c04048d3126b6d8de46e28c00cab 100644 --- a/docs/html-intl/intl/pt-br/guide/components/loaders.jd +++ b/docs/html-intl/intl/pt-br/guide/components/loaders.jd @@ -21,14 +21,14 @@ parent.link=activities.html
      - +

      Classes principais

      1. {@link android.app.LoaderManager}
      2. {@link android.content.Loader}
      3. -
      - + +

      Exemplos relacionados

      1. @@ -51,7 +51,7 @@ quando o conteúdo é alterado.
      2. quando são recriados após uma alteração de configuração. Portanto, eles não precisam reconsultar os dados.
    - +

    Resumo da API de carregador

    Há várias classes e interfaces que podem ser envolvidas no uso @@ -68,7 +68,7 @@ de carregadores em um aplicativo. Elas são resumidas nesta tabela:

    {@link android.app.Fragment} para gerenciar uma ou mais instâncias de {@link android.content.Loader}. Isto ajuda um aplicativo a gerenciar operações executadas por longos períodos juntamente com o ciclo de vida de {@link android.app.Activity} -ou {@link android.app.Fragment}; o uso mais comum disto é com +ou {@link android.app.Fragment}; o uso mais comum disto é com {@link android.content.CursorLoader}. No entanto, os aplicativos têm a liberdade de criar os próprios carregadores para outros tipos de dados.
    @@ -129,7 +129,7 @@ de {@link android.content.Loader} ou {@link android.content.AsyncTaskLoader} para carregar dados de outra origem.
  • Uma implementação de {@link android.app.LoaderManager.LoaderCallbacks}. É aqui que é possível criar novos carregadores e gerenciar as referências -a carregadores existentes.
  • +a carregadores existentes.
  • Uma maneira de exibir os dados do carregador, como um {@link android.widget.SimpleCursorAdapter}.
  • Uma origem de dados, como um {@link android.content.ContentProvider}, ao usar @@ -140,7 +140,7 @@ android.widget.SimpleCursorAdapter}.
  • O {@link android.app.LoaderManager} gerencia uma ou mais instâncias de {@link android.content.Loader} dentro de uma {@link android.app.Activity} ou um {@link android.app.Fragment}. Há apenas um {@link -android.app.LoaderManager} por atividade ou fragmento.

    +android.app.LoaderManager} por atividade ou fragmento.

    Geralmente, inicializa-se um {@link android.content.Loader} dentro do método {@link @@ -157,13 +157,13 @@ recebe os seguintes parâmetros:

    • Um ID único que identifica o carregador. Neste exemplo, o ID é 0.
    • Argumentos opcionais para fornecer ao carregador -em construção (null neste exemplo).
    • +em construção (null neste exemplo).
    • Uma implementação de {@link android.app.LoaderManager.LoaderCallbacks}, que {@link android.app.LoaderManager} chama para relatar eventos do carregador. Nesse exemplo,  a classe local implementa a interface de {@link android.app.LoaderManager.LoaderCallbacks}, para que ela passe uma referência -para si, {@code this}.
    • +para si, {@code this}.

    A chamada de {@link android.app.LoaderManager#initLoader initLoader()} garante que o carregador foi inicializado e que está ativo. Ela possui dois possíveis resultados:

    @@ -193,7 +193,7 @@ a vida do carregador automaticamente. O {@link android.app.LoaderManager} inicia e interrompe o carregamento quando necessário, além de manter o estado do carregador e do conteúdo associado. À medida que isso ocorre, você raramente interage com os carregadores diretamente (para ver um exemplo de métodos para aprimorar o comportamento -de um carregador, consulte o exemplo de
    LoaderThrottle). +de um carregador, consulte o exemplo de LoaderThrottle). Geralmente, usam-se os métodos {@link android.app.LoaderManager.LoaderCallbacks} para intervir no processo de carregamento quando determinados eventos ocorrem. Para obter mais informações sobre este assunto, consulte Uso dos retornos de chamada de LoaderManager.

    @@ -245,7 +245,7 @@ instancia e retorna um novo {@link android.content.Loader} para o ID fornecido. — chamado quando um carregador anteriormente criado termina o seu carregamento.
      -
    • {@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} +
    • {@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} — chamado quando um carregador anteriormente criado é reiniciado, tornando os dados indisponíveis.
    • @@ -343,7 +343,7 @@ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

      Este método é chamado quando um carregador anteriormente criado é reiniciado, tornando os dados indisponíveis. Este retorno de chamada permite que você descubra quando os dados estão prestes a serem liberados para que seja possível remover a referência a eles.  

      -

      Esta implementação chama +

      Esta implementação chama {@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()} com um valor de null:

      @@ -366,7 +366,7 @@ public void onLoaderReset(Loader<Cursor> loader) { android.app.Fragment} que exibe uma {@link android.widget.ListView} contendo os resultados de uma consulta aos provedores de conteúdo de contatos. Ela usa um {@link android.content.CursorLoader} para gerenciar a consulta no provedor.

      - +

      Para um aplicativo acessar os contatos de um usuário, como neste exemplo, o manifesto deverá incluir a permissão {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.

      diff --git a/docs/html-intl/intl/pt-br/guide/components/processes-and-threads.jd b/docs/html-intl/intl/pt-br/guide/components/processes-and-threads.jd index c8e636dacce834f848b8435bc8d49b05adb8db3d..9bd335d98e8fdd91a7f2f88746b45c3443c6ed38 100644 --- a/docs/html-intl/intl/pt-br/guide/components/processes-and-threads.jd +++ b/docs/html-intl/intl/pt-br/guide/components/processes-and-threads.jd @@ -120,7 +120,7 @@ o dispositivo atingiu o estado de paginação de memória. Portanto, eliminar al
      • Se ele hospedar um {@link android.app.Activity} que não esteja em primeiro plano, -mas ainda seja visível para o usuário (o seu método {@link android.app.Activity#onPause onPause()} tiver sido chamado). +mas ainda seja visível para o usuário (o seu método {@link android.app.Activity#onPause onPause()} tiver sido chamado). Isto poderá ocorrer, por exemplo, se a atividade em primeiro plano iniciar um diálogo, o que permitirá que a atividade anterior seja vista por trás dela.
      • @@ -319,7 +319,7 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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) { diff --git a/docs/html-intl/intl/pt-br/guide/components/recents.jd b/docs/html-intl/intl/pt-br/guide/components/recents.jd index 467f62067a546d5286ffa8ae5ce5180bfd918d7a..9f7588593bba4e4cf9704043b1a116367d865da6 100644 --- a/docs/html-intl/intl/pt-br/guide/components/recents.jd +++ b/docs/html-intl/intl/pt-br/guide/components/recents.jd @@ -41,7 +41,7 @@ page.tags="recents","overview" atividades e tarefas acessadas recentemente. O usuário pode navegar pela lista e selecionar uma tarefa a retomar ou remover uma tarefa da lista deslizando-a para fora. Com a versão 5.0 do Android (API de nível 21), várias instâncias da -mesma atividade contendo diferentes documentos podem aparecer como tarefas na tela de visão geral. Por exemplo, o +mesma atividade contendo diferentes documentos podem aparecer como tarefas na tela de visão geral. Por exemplo, o Google Drive pode ter uma tarefa para cada um dos vários documentos do Google. Cada documento aparece como uma tarefa na tela de visão geral.

        @@ -158,8 +158,8 @@ efeitos quando o usuário abre um documento com o aplicativo:

        "{@code intoExisting}"
        A atividade reutiliza uma tarefa existente para o documento. Isso é o mesmo que configurar o - sinalizador {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} sem configurar - o sinalizador {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, como descrito em + sinalizador {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} sem configurar + o sinalizador {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}, como descrito em Uso do sinalizador Intent para adicionar uma tarefa acima.
        "{@code always}"
        @@ -169,7 +169,7 @@ efeitos quando o usuário abre um documento com o aplicativo:

        "{@code none”}"
        A atividade não cria uma nova tarefa para o documento. A tela de visão geral trata a - atividade como aconteceria por padrão: ela exibe uma tarefa para o aplicativo, que + atividade como aconteceria por padrão: ela exibe uma tarefa para o aplicativo, que retoma a atividade invocada por último pelo usuário.
        "{@code never}"
        @@ -205,7 +205,7 @@ recentemente é removida da tela de visão geral. O valor máximo de {@code andr

        Uso da classe AppTask para remover tarefas

        -

        Na atividade que cria uma nova tarefa na tela de visão geral, é possível +

        Na atividade que cria uma nova tarefa na tela de visão geral, é possível especificar quando remover a tarefa e terminar todas as atividades associadas a ela chamando o método {@link android.app.ActivityManager.AppTask#finishAndRemoveTask() finishAndRemoveTask()}.

        diff --git a/docs/html-intl/intl/pt-br/guide/components/services.jd b/docs/html-intl/intl/pt-br/guide/components/services.jd index 123d90ac9cb32554292672cfa0bb870b43475b42..564ac80d3506cfff22e6c82ffaf63cbafb347b39 100644 --- a/docs/html-intl/intl/pt-br/guide/components/services.jd +++ b/docs/html-intl/intl/pt-br/guide/components/services.jd @@ -185,7 +185,7 @@ usá-los a partir de outros componentes do aplicativo.

        Como atividades (e outros componentes), você deve declarar todos os serviços no arquivo de manifesto do aplicativo.

        -

        Para declarar o serviço, adicione um elemento {@code <service>} +

        Para declarar o serviço, adicione um elemento {@code <service>} como filho do elemento {@code <application>} . Por exemplo:

        @@ -494,7 +494,7 @@ a cada constante.

        Início de um serviço

        -

        É possível iniciar um dispositivo de uma atividade ou outro componente do aplicativo passando uma +

        É possível iniciar um dispositivo de uma atividade ou outro componente do aplicativo passando uma {@link android.content.Intent} a {@link android.content.Context#startService startService()}. O sistema Android chama o método {@link android.app.Service#onStartCommand onStartCommand()} do serviço e passa a ele a {@link diff --git a/docs/html-intl/intl/pt-br/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/pt-br/guide/components/tasks-and-back-stack.jd index d309c6704f3765f19332f60021d1e5c20f08ffbe..8e485b0fc939dda3676234dee3b8949128004756 100644 --- a/docs/html-intl/intl/pt-br/guide/components/tasks-and-back-stack.jd +++ b/docs/html-intl/intl/pt-br/guide/components/tasks-and-back-stack.jd @@ -77,7 +77,7 @@ android.app.Fragment} class documentation.

        --> -

        A tela inicial do dispositivo é o ponto de partida para a maioria das tarefas. Quando o usuário toca em um ícone no inicializador do +

        A tela inicial do dispositivo é o ponto de partida para a maioria das tarefas. Quando o usuário toca em um ícone no inicializador do aplicativo (ou em um atalho na tela inicial), essa tarefa do aplicativo acontece em primeiro plano. Se não existir nenhuma tarefa para o aplicativo (se o aplicativo não tiver sido usado recentemente), uma nova tarefa @@ -85,7 +85,7 @@ será criada e a atividade "principal" daquele aplicativo abrirá como a ativida

        Quando a atividade atual inicia outra, a nova atividade é colocada no topo da pilha e recebe foco. A atividade anterior permanece na pilha, mas é interrompida. Quando uma atividade -para, o sistema retém o estado atual da interface do usuário. Quando o usuário pressiona o botão +para, o sistema retém o estado atual da interface do usuário. Quando o usuário pressiona o botão Voltar , a atividade atual é retirada do topo da pilha (a atividade é destruída) e a atividade anterior reinicia (o estado anterior da IU é restaurado). Atividades na pilha nunca @@ -103,7 +103,7 @@ a atividade atual é destruída e a atividade anterior reinicia.

        -

        Se o usuário continua pressionando Voltar, cada atividade na pilha é retirada para +

        Se o usuário continua pressionando Voltar, cada atividade na pilha é retirada para revelar a anterior até que o usuário retorne à tela inicial (ou a qualquer atividade que estivesse em execução no começo da tarefa). Quando todas as atividades forem removidas da pilha, a tarefa não existirá mais.

        @@ -295,7 +295,7 @@ launchMode} do elemento

        O atributo {@code launchMode} especifica uma instrução sobre como a atividade deve ser inicializada -em uma tarefa. Há quatro modos diferentes de inicialização que podem ser designados ao atributo +em uma tarefa. Há quatro modos diferentes de inicialização que podem ser designados ao atributo launchMode:

        @@ -334,7 +334,7 @@ Entretanto, se uma instância da atividade já existir em uma tarefa separada, o a intenção àquela instância por meio de uma chamada do método {@link android.app.Activity#onNewIntent onNewIntent()} em vez de criar uma nova instância. Somente uma instância da atividade pode existir por vez. -

        Observação: embora a atividade inicie em uma nova tarefa, o botão +

        Observação: embora a atividade inicie em uma nova tarefa, o botão Voltar ainda direciona o usuário à atividade anterior.

    {@code "singleInstance"}.
    Igual à {@code "singleTask"}, exceto que o sistema não inicializa nenhuma outra atividade @@ -505,7 +505,7 @@ A tarefa reterá todas as atividades em sua pilha mesmo após um longo período. href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch
    Se esse atributo for definido como {@code "true"} na atividade raiz de uma tarefa, a pilha será apagada da atividade raiz sempre que o usuário sair da tarefa -e retornar a ela. Em outras palavras, é o oposto de +e retornar a ela. Em outras palavras, é o oposto de {@code alwaysRetainTaskState}. O usuário sempre retorna à tarefa no estado inicial, mesmo ao retirar-se da tarefa somente por um momento.
    @@ -557,13 +557,13 @@ nova tarefa, e o usuário perderia algum tempo trabalhando nessa tarefa. O usuá Página inicial. A tarefa é enviada para segundo plano e não fica mais visível. O usuário não tem como voltar à tarefa porque ela não é representada no inicializador do aplicativo.

    -

    Para esses casos em que se deseja que o usuário não seja capaz de retornar a uma atividade, defina +

    Para esses casos em que se deseja que o usuário não seja capaz de retornar a uma atividade, defina {@code finishOnTaskLaunch} - do elemento + do elemento <activity> como {@code "true"} (consulte Apagar a pilha).

    -

    Veja mais informações sobre a representação e o gerenciamento de atividades +

    Veja mais informações sobre a representação e o gerenciamento de atividades na tela de visão geral em Tela de visão geral.

    diff --git a/docs/html-intl/intl/pt-br/guide/index.jd b/docs/html-intl/intl/pt-br/guide/index.jd index ab396477e2506007b41254f3dd50403a56439c30..74151ccd26ba69f85d00887dcedc1785875d228c 100644 --- a/docs/html-intl/intl/pt-br/guide/index.jd +++ b/docs/html-intl/intl/pt-br/guide/index.jd @@ -29,7 +29,7 @@ tela para a interface de usuário e um serviço realiza trabalho em segundo plano de forma independente.

    De um componente, é possível executar outro componente usando uma intenção. É possível até mesmo -iniciar um componente em um aplicativo diferente, como uma atividade em um aplicativo de mapas para mostrar um endereço. Esse modelo +iniciar um componente em um aplicativo diferente, como uma atividade em um aplicativo de mapas para mostrar um endereço. Esse modelo fornece vários pontos de entrada para um único aplicativo e permite que qualquer aplicativo se comporte como o "padrão" de um usuário para uma ação que outros aplicativos podem invocar.

    @@ -53,7 +53,7 @@ diferentes configurações de dispositivos. Por exemplo, é possível criar dife de layout para diversos tamanhos de tela e o sistema determina qual layout deverá aplicar com base no tamanho da tela do dispositivo atual.

    -

    Você pode consultar a disponibilidade dos recursos do dispositivo em tempo de execução se qualquer recurso do +

    Você pode consultar a disponibilidade dos recursos do dispositivo em tempo de execução se qualquer recurso do aplicativo exigir hardware específico, como uma câmera. Se necessário, também é possível declarar recursos que o aplicativo exige, para que mercados como a Google Play Store não permitam a instalação em dispositivos que não sejam compatíveis com aquele recurso.

    diff --git a/docs/html-intl/intl/pt-br/preview/j8-jack.jd b/docs/html-intl/intl/pt-br/guide/platform/j8-jack.jd similarity index 99% rename from docs/html-intl/intl/pt-br/preview/j8-jack.jd rename to docs/html-intl/intl/pt-br/guide/platform/j8-jack.jd index 504739689a09268895e9e3e47a31d151317758b1..22f4b679febf8a4b73da6455586b300d093a2e65 100644 --- a/docs/html-intl/intl/pt-br/preview/j8-jack.jd +++ b/docs/html-intl/intl/pt-br/guide/platform/j8-jack.jd @@ -23,7 +23,7 @@ page.keywords="android N", "Java 8", "Jack"

    Para começar a usar esses recursos, primeiro faça o download e instale o Android -Studio 2.1 e o Android N Preview SDK, que inclui a +Studio 2.1 e o Android N Preview SDK, que inclui a cadeia de ferramentas Jack obrigatória e o Android Plugin for Gradle atualizado. Se você ainda não instalou o Android N Preview SDK, consulte Preparação para desenvolver para o Android N.

    diff --git a/docs/html-intl/intl/pt-br/guide/topics/manifest/manifest-intro.jd b/docs/html-intl/intl/pt-br/guide/topics/manifest/manifest-intro.jd index e33779684a5c0a5e577f325234540821ae73bee6..639b6dbf4bf133f9eab83b19792c0451e8c92cef 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/manifest/manifest-intro.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/manifest/manifest-intro.jd @@ -34,14 +34,14 @@ O nome do pacote serve como identificador exclusivo para o aplicativo.
  • Descrever os componentes do aplicativo — as atividades, os serviços, os receptores de transmissão e os provedores de conteúdo que compõem o aplicativo. Nomear as classes que implementam os componentes -e publicam seus recursos (por exemplo, que mensagens {@link android.content.Intent +e publicam seus recursos (por exemplo, que mensagens {@link android.content.Intent Intent} eles podem tratar). Essas declarações permitem ao sistema Android saber quais são os componentes e em que condições eles podem ser iniciados.
  • -
  • Determinar que processos hospedarão componentes de aplicativo.
  • +
  • Determinar que processos hospedarão componentes de aplicativo.
  • Declarar as permissões que o aplicativo deve ter para acessar -partes protegidas da API e interagir com outros aplicativos.
  • +partes protegidas da API e interagir com outros aplicativos.
  • Declarar também as permissões que outros devem ter para interagir com os componentes do aplicativo.
  • @@ -66,7 +66,7 @@ elemento que ele pode conter. Cada elemento e seus atributos são documentados na totalidade em um arquivo separado. Para exibir informações detalhadas sobre cada elemento, clique no nome do elemento no diagrama, na lista de elementos em ordem alfabética que acompanha o diagrama -ou em qualquer outra menção ao nome do elemento. +ou em qualquer outra menção ao nome do elemento.

    @@ -128,7 +128,7 @@ ou em qualquer outra menção ao nome do elemento.
     

    Todos os elementos que podem aparecer no arquivo de manifesto estão relacionados abaixo em ordem alfabética. Estes são os únicos elementos legais. Não é possível -adicionar elementos ou atributos próprios. +adicionar elementos ou atributos próprios.

    @@ -158,7 +158,7 @@ adicionar elementos ou atributos próprios.

    - +

    Convenções de arquivos

    @@ -172,25 +172,25 @@ no manifesto:
    Somente os elementos <manifest> e <application> -são necessários — eles devem estar presentes e ocorrer somente uma vez. +são necessários — eles devem estar presentes e ocorrer somente uma vez. A maioria dos outros pode ocorrer diversas vezes ou nunca — embora pelo menos alguns deles devam estar presentes para que o manifesto realize algo significativo.

    -Se um elemento contiver qualquer coisa, ele conterá outros elementos. +Se um elemento contiver qualquer coisa, ele conterá outros elementos. Todos os valores são definidos por meio de atributos, e não como dados de caracteres dentro de um elemento.

    Elementos de mesmo nível geralmente não são ordenados. Por exemplo: os elementos -<activity>, +<activity>, <provider> -e <service> -podem ser combinados entre si em qualquer sequência. (O elemento +e <service> +podem ser combinados entre si em qualquer sequência. (O elemento <activity-alias> -é uma exceção a essa regra: ele deve seguir o -<activity> +é uma exceção a essa regra: ele deve seguir o +<activity> para o qual é alias.)

    @@ -200,32 +200,32 @@ devem ser especificados para um elemento para cumprir a sua finalidade. Use a documentação como guia. Para atributos verdadeiramente opcionais, ele menciona um valor padrão ou declara o que acontece na ausência de uma especificação. -

    Exceto por alguns atributos do elemento +

    Exceto por alguns atributos do elemento <manifest> -raiz, todos os nomes de atributo têm um prefixo {@code android:} — +raiz, todos os nomes de atributo têm um prefixo {@code android:} — por exemplo, {@code android:alwaysRetainTaskState}. Como o prefixo é universal, a documentação geralmente o omite ao referir-se a atributos pelo nome.

    Declaração de nomes de classe
    Muitos elementos correspondem a objetos Java, inclusive elementos do próprio -aplicativo (o elemento -<application> -) e seus componentes principais — atividades -(<activity>), -serviços -(<service>), -receptores de transmissão -(<receiver>) -e provedores de conteúdo -(<provider>). +aplicativo (o elemento +<application> +) e seus componentes principais — atividades +(<activity>), +serviços +(<service>), +receptores de transmissão +(<receiver>) +e provedores de conteúdo +(<provider>).

    -Se uma subclasse for definida, como quase sempre acontece para classes de componentes -({@link android.app.Activity}, {@link android.app.Service}, -{@link android.content.BroadcastReceiver} e {@link android.content.ContentProvider}), +Se uma subclasse for definida, como quase sempre acontece para classes de componentes +({@link android.app.Activity}, {@link android.app.Service}, +{@link android.content.BroadcastReceiver} e {@link android.content.ContentProvider}), a subclasse será declarada por meio de um atributo {@code name}. O nome deve conter -toda a designação do pacote. +toda a designação do pacote. Por exemplo: uma subclasse {@link android.app.Service} pode ser declarada assim:

    @@ -240,11 +240,11 @@ Por exemplo: uma subclasse {@link android.app.Service} pode ser declarada assim:

    No entanto, para encurtar, se o primeiro caractere da string for um ponto, -a string será acrescentada ao nome do pacote do aplicativo (conforme especificado pelo atributo -package - do elemento -<manifest> -). A seguinte atribuição é igual à atribuição acima: +a string será acrescentada ao nome do pacote do aplicativo (conforme especificado pelo atributo +package + do elemento +<manifest> +). A seguinte atribuição é igual à atribuição acima:

    <manifest package="com.example.project" . . . >
    @@ -257,13 +257,13 @@ a string será acrescentada ao nome do pacote do aplicativo (conforme especifica
     </manifest>

    -Ao iniciar um componente, o Android cria uma instância da subclasse nomeada. +Ao iniciar um componente, o Android cria uma instância da subclasse nomeada. Se nenhuma subclasse for especificada, ele criará uma instância da classe base.

    Vários valores
    Se for especificado mais de um valor, o elemento sempre será repetido -em vez de listar os vários valores dentro de um único elemento. +em vez de listar os vários valores dentro de um único elemento. Por exemplo, um filtro de intenção pode listar algumas ações:
    <intent-filter . . . >
    @@ -276,22 +276,22 @@ Por exemplo, um filtro de intenção pode listar algumas ações:
     
    Valores de recurso
    Alguns atributos têm valores que podem ser exibidos aos usuários — por exemplo, uma etiqueta e um ícone de uma atividade. Os valores desses atributos -devem ser localizados e, por tanto, definidos a partir de um recurso ou tema. Os valores +devem ser localizados e, por tanto, definidos a partir de um recurso ou tema. Os valores de recurso são expressos no formato a seguir:

    {@code @[pacote:]tipo:nome}

    em que o nome do pacote pode ser omitido se o recurso estiver no mesmo pacote -que o aplicativo tipo é um tipo de recurso — como uma "string" ou -"drawable" (desenhável) — e nome é o nome que identifica o recurso específico. +que o aplicativo tipo é um tipo de recurso — como uma "string" ou +"drawable" (desenhável) — e nome é o nome que identifica o recurso específico. Por exemplo:

    <activity android:icon="@drawable/smallPic" . . . >

    -Os valores de um tema são expressos de forma semelhante, mas, com um '{@code ?}' +Os valores de um tema são expressos de forma semelhante, mas, com um '{@code ?}' em vez de '{@code @}':

    @@ -299,8 +299,8 @@ em vez de '{@code @}':

    Valores de string
    -
    Quando o valor de um atributo é uma string, devem-se usar duas barras invertidas ('{@code \\}') -para caracteres de escape — por exemplo, '{@code \\n}' para +
    Quando o valor de um atributo é uma string, devem-se usar duas barras invertidas ('{@code \\}') +para caracteres de escape — por exemplo, '{@code \\n}' para uma nova linha ou '{@code \\uxxxx}' para um caractere Unicode.
    @@ -320,7 +320,7 @@ Os componentes fundamentais de um aplicativo (suas atividades, serviços e recep de transmissão) são ativados por intenções. Intenções são pacotes de informações (objetos {@link android.content.Intent}) que descrevem uma ação desejada — inclusive os dados usados em ações, a categoria -do componente que deve executar a ação e outras instruções pertinentes. +do componente que deve executar a ação e outras instruções pertinentes. O Android localiza um componente adequado para responder à intenção, inicia uma nova instância do componente se necessário e passa-o ao objeto da intenção. @@ -330,7 +330,7 @@ ao objeto da intenção. Os componentes anunciam seus recursos — os tipos de intenção aos quais eles podem responder — por meio de filtros de intenções. Como o sistema Android precisa saber que intenções um componente pode tratar antes de iniciá-lo, os filtros -de intenções são especificados no manifesto como elementos +de intenções são especificados no manifesto como elementos <intent-filter> . Os componentes podem ter qualquer quantidade de filtros, em que cada um descreve um recurso diferente. @@ -345,8 +345,8 @@ do componente.

    Para ver como os objetos de intenção são testados em relação aos filtros de intenções, -consulte o documento -Intenções +consulte o documento +Intenções e filtros de intenções em separado.

    @@ -355,41 +355,41 @@ e filtros de intenções em separado.

    Alguns elementos têm atributos {@code icon} e {@code label} de um pequeno ícone -e uma etiqueta de texto que pode ficar visível para os usuários. Alguns deles também têm um atributo -{@code description} para um texto explicativo mais longo que também pode ser -exibido na tela. Por exemplo: o elemento +e uma etiqueta de texto que pode ficar visível para os usuários. Alguns deles também têm um atributo +{@code description} para um texto explicativo mais longo que também pode ser +exibido na tela. Por exemplo: o elemento <permission> -tem todos os três atributos; assim, quando o usuário é consultado para dar -permissão a um aplicativo que a solicitou, serão apresentados ao usuário um ícone -que representa a permissão, o nome da permissão e uma descrição +tem todos os três atributos; assim, quando o usuário é consultado para dar +permissão a um aplicativo que a solicitou, serão apresentados ao usuário um ícone +que representa a permissão, o nome da permissão e uma descrição de tudo o que está envolvido.

    -Em todo caso, o ícone e a etiqueta definidos em um elemento recipiente se tornam as configurações -{@code icon} e {@code label} padrão de todos os subelementos do contêiner. -Assim, o ícone e a etiqueta definidos no elemento -<application> -são o ícone e a etiqueta padrão para cada um dos componentes do aplicativo. -Da mesma forma, o ícone e a etiqueta definidos para um componente — por exemplo, um elemento -<activity> - — são as configurações padrão para cada um dos elementos -<intent-filter> +Em todo caso, o ícone e a etiqueta definidos em um elemento recipiente se tornam as configurações +{@code icon} e {@code label} padrão de todos os subelementos do contêiner. +Assim, o ícone e a etiqueta definidos no elemento +<application> +são o ícone e a etiqueta padrão para cada um dos componentes do aplicativo. +Da mesma forma, o ícone e a etiqueta definidos para um componente — por exemplo, um elemento +<activity> + — são as configurações padrão para cada um dos elementos +<intent-filter> do componente. Se um elemento -<application> -define uma etiqueta, mas uma atividade e seu filtro de intenção não definem, -a etiqueta do aplicativo é tratada como a etiqueta de atividade +<application> +define uma etiqueta, mas uma atividade e seu filtro de intenção não definem, +a etiqueta do aplicativo é tratada como a etiqueta de atividade e do filtro de intenção.

    -O ícone e a etiqueta definidos para um filtro de intenção são usados para representar um componente +O ícone e a etiqueta definidos para um filtro de intenção são usados para representar um componente apresentado para o usuário para preencher a função -anunciada pelo filtro. Por exemplo: um filtro com as configurações -"{@code android.intent.action.MAIN}" e -"{@code android.intent.category.LAUNCHER}" anuncia uma atividade +anunciada pelo filtro. Por exemplo: um filtro com as configurações +"{@code android.intent.action.MAIN}" e +"{@code android.intent.category.LAUNCHER}" anuncia uma atividade como uma que inicia um aplicativo — ou seja, -que deve ser exibida no inicializador do aplicativo. O ícone e a etiqueta +que deve ser exibida no inicializador do aplicativo. O ícone e a etiqueta definidos no filtro são, portanto, as exibidas no inicializador.

    @@ -397,14 +397,14 @@ definidos no filtro são, portanto, as exibidas no inicializador.

    Permissões

    -As permissões são restrições que limitam o acesso a parte do código -ou aos dados de um dispositivo. A limitação é imposta para proteger dados -essenciais que podem sofrer mau uso e distorções ou prejudicar a experiência do usuário. +As permissões são restrições que limitam o acesso a parte do código +ou aos dados de um dispositivo. A limitação é imposta para proteger dados +essenciais que podem sofrer mau uso e distorções ou prejudicar a experiência do usuário.

    -Cada permissão é identificada por uma etiqueta exclusiva. Geralmente a etiqueta indica -a ação que foi restringida. A seguir há alguns exemplos de permissões definidas +Cada permissão é identificada por uma etiqueta exclusiva. Geralmente a etiqueta indica +a ação que foi restringida. A seguir há alguns exemplos de permissões definidas pelo Android:

    @@ -418,25 +418,25 @@ Um recurso pode ser protegido por, no máximo, uma permissão.

    -Se um aplicativo precisar de acesso a um recurso protegido por uma permissão, -ele deve declarar que precisa da permissão com um elemento -<uses-permission> -no manifesto. Assim, quando o aplicativo é instalado -no dispositivo, o instalador determina se concederá ou não a permissão -solicitada, marcando as autoridades que assinaram os certificados -do aplicativo e, em alguns casos, perguntando ao usuário. -Se a permissão for concedida, o aplicativo será capaz de usar os recursos -protegidos. Caso contrário, sua tentativa de acessar esses recursos simplesmente falhará -sem nenhuma notificação ao usuário. +Se um aplicativo precisar de acesso a um recurso protegido por uma permissão, +ele deve declarar que precisa da permissão com um elemento +<uses-permission> +no manifesto. Assim, quando o aplicativo é instalado +no dispositivo, o instalador determina se concederá ou não a permissão +solicitada, marcando as autoridades que assinaram os certificados +do aplicativo e, em alguns casos, perguntando ao usuário. +Se a permissão for concedida, o aplicativo será capaz de usar os recursos +protegidos. Caso contrário, sua tentativa de acessar esses recursos simplesmente falhará +sem nenhuma notificação ao usuário.

    -Um aplicativo também pode proteger seus componentes (atividades, serviços, -receptores de transmissão e provedores de conteúdo) com permissões. Ele pode empregar -qualquer uma das permissões definidas pelo Android (listadas em -{@link android.Manifest.permission android.Manifest.permission}) ou declaradas -por outros aplicativos. Ou então, ele pode definir as suas próprias. As novas permissões são declaradas -com o elemento +Um aplicativo também pode proteger seus componentes (atividades, serviços, +receptores de transmissão e provedores de conteúdo) com permissões. Ele pode empregar +qualquer uma das permissões definidas pelo Android (listadas em +{@link android.Manifest.permission android.Manifest.permission}) ou declaradas +por outros aplicativos. Ou então, ele pode definir as suas próprias. As novas permissões são declaradas +com o elemento <permission>. Por exemplo: uma atividade pode ser protegida da seguinte forma:

    @@ -458,41 +458,41 @@ com o elemento

    Observe que, nesse exemplo, a permissão {@code DEBIT_ACCT}, além de declarada -com o elemento +com o elemento <permission> -, tem seu uso solicitado com o elemento +, tem seu uso solicitado com o elemento <uses-permission>. Ela deve ser solicitada para que outros componentes do aplicativo -iniciem a atividade protegida, mesmo que a proteção -seja imposta pelo próprio aplicativo. +iniciem a atividade protegida, mesmo que a proteção +seja imposta pelo próprio aplicativo.

    Se, no mesmo exemplo, o atributo {@code permission} fosse definido -como uma permissão declarada em outro lugar +como uma permissão declarada em outro lugar (como {@code android.permission.CALL_EMERGENCY_NUMBERS}), não seria -necessário declará-la novamente com um elemento +necessário declará-la novamente com um elemento <permission>. - No entanto, ainda seria necessário solicitar seu uso com -<uses-permission>. + No entanto, ainda seria necessário solicitar seu uso com +<uses-permission>.

    -O elemento -<permission-tree> -declara um espaço de nome de um grupo de permissões que será definido -no código. E +O elemento +<permission-tree> +declara um espaço de nome de um grupo de permissões que será definido +no código. E <permission-group> -define um etiqueta de um conjunto de permissões (os dois declarados no manifesto com elementos -<permission> -e as declaradas em outro lugar). Ele afeta somente a forma com que as permissões estão -agrupadas quando apresentadas ao usuário. O elemento +define um etiqueta de um conjunto de permissões (os dois declarados no manifesto com elementos +<permission> +e as declaradas em outro lugar). Ele afeta somente a forma com que as permissões estão +agrupadas quando apresentadas ao usuário. O elemento <permission-group> -não especifica que permissões pertencem ao grupo; +não especifica que permissões pertencem ao grupo; ele só dá um nome ao grupo. Para incluir uma permissão no grupo, -designa-se o nome do grupo ao atributo -permissionGroup - do elemento +designa-se o nome do grupo ao atributo +permissionGroup + do elemento <permission>.

    @@ -501,17 +501,17 @@ designa-se o nome do grupo ao atributo

    Bibliotecas

    -Todo aplicativo está vinculado à biblioteca Android padrão, que -contém os pacotes básicos para programar aplicativos (com classes comuns +Todo aplicativo está vinculado à biblioteca Android padrão, que +contém os pacotes básicos para programar aplicativos (com classes comuns tais como Activity, Service, Intent, View, Button, Application, ContentProvider etc.).

    -No entanto, alguns pacotes residem em suas próprias bibliotecas. Se o aplicativo -usar código de algum desses pacotes, ele deve receber solicitação explícita para ser -vinculado a eles. O manifesto deve conter um elemento +No entanto, alguns pacotes residem em suas próprias bibliotecas. Se o aplicativo +usar código de algum desses pacotes, ele deve receber solicitação explícita para ser +vinculado a eles. O manifesto deve conter um elemento <uses-library> - separado para nomear cada uma das bibliotecas (o nome da biblioteca se encontra + separado para nomear cada uma das bibliotecas (o nome da biblioteca se encontra na documentação do pacote).

    diff --git a/docs/html-intl/intl/pt-br/guide/topics/providers/calendar-provider.jd b/docs/html-intl/intl/pt-br/guide/topics/providers/calendar-provider.jd index ce72b7db5cff09ac92303b605426f7efd2e7f692..42a517b73783f37ff328d6d4232872b792157630 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/providers/calendar-provider.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/providers/calendar-provider.jd @@ -42,7 +42,7 @@ page.title=Provedor de agenda
  • Uso de intenções para exibir dados de agenda
  • - +
  • Adaptadores de sincronização
  • @@ -113,26 +113,26 @@ as tabelas e os campos principais que as vinculam entre si.

    {@link android.provider.CalendarContract.Calendars}

    - + Essa tabela contém as informações específicas da agenda. Cada linha nessa tabela contém os detalhes de uma única agenda, como nome, cor, informações de sincronização etc. {@link android.provider.CalendarContract.Events} - + Essa tabela contém as informações específicas do evento. Cada linha nessa tabela tem as informações de um único evento — por exemplo: título do evento, local, horário de início, horário de término etc. O evento pode ocorrer uma vez ou diversas vezes. Os participantes, -lembretes e propriedades estendidas são armazenados em tabelas separadas. +lembretes e propriedades estendidas são armazenados em tabelas separadas. Cada um deles tem um {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} que referencia o {@link android.provider.BaseColumns#_ID} na tabela de eventos. {@link android.provider.CalendarContract.Instances} - + Essa tabela contém os horários de início e término para cada ocorrência em um evento. Cada linha nessa tabela representa uma única ocorrência do evento. Para eventos de ocorrência única, há um mapeamento 1:1 @@ -141,7 +141,7 @@ a diversas ocorrências daquele evento são geradas automaticamente. {@link android.provider.CalendarContract.Attendees} - + Essa tabela contém as informações dos participantes (convidados) do evento. Cada linha representa um único convidado de um evento. Ela especifica o tipo de convidado e a resposta quanto à participação do convidado @@ -149,7 +149,7 @@ no evento. {@link android.provider.CalendarContract.Reminders} - + Essa tabela contém os dados de alerta/notificação. Cada linha representa um único alerta de um evento. Um evento pode ter vários lembretes. O número máximo de lembretes por evento @@ -159,7 +159,7 @@ que é definido pelo adaptador de sincronização que possui a agenda fornecida. Os lembretes são especificados em minutos antes do evento e têm um método que determina a forma de alertar o usuário. - +

    A API do Provedor de Agenda é projetada para ser flexível e poderosa. Ao mesmo tempo, @@ -211,7 +211,7 @@ para excluir, inserir ou atualizar dados da agenda:

    A tabela {@link android.provider.CalendarContract.Calendars} contém detalhes de agendas individuais. As colunas -Agendas a seguir são graváveis tanto por aplicativos quanto por adaptadores de sincronização. +Agendas a seguir são graváveis tanto por aplicativos quanto por adaptadores de sincronização. Para obter uma lista completa de campos compatíveis, consulte a referência {@link android.provider.CalendarContract.Calendars}

    @@ -229,7 +229,7 @@ a referência {@link android.provider.CalendarContract.Calendars}

    - + - +

    A seguir há um exemplo que mostra como obter as agendas de propriedade de determinado usuário. Para simplificar o exemplo, a operação de consulta é exibida no encadeamento da interface do usuário ("encadeamento principal"). Na prática, isso deve ser feito em um encadeamento -assíncrono em vez de no encadeamento principal. Para ver mais discussões, consulte +assíncrono em vez de no encadeamento principal. Para ver mais discussões, consulte Carregadores. Se você não estiver somente lendo dados, mas modificando-os, consulte {@link android.content.AsyncQueryHandler}.

    @@ -268,13 +268,13 @@ public static final String[] EVENT_PROJECTION = new String[] { Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3; - + +sincronizadas.

    Na próxima parte do exemplo, você construirá a consulta. A seleção @@ -308,38 +308,38 @@ consulte Prove

    // Run query
     Cursor cur = null;
     ContentResolver cr = getContentResolver();
    -Uri uri = Calendars.CONTENT_URI;   
    -String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    +Uri uri = Calendars.CONTENT_URI;
    +String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                             + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                             + Calendars.OWNER_ACCOUNT + " = ?))";
     String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
    -        "sampleuser@gmail.com"}; 
    -// Submit the query and get a Cursor object back. 
    +        "sampleuser@gmail.com"};
    +// Submit the query and get a Cursor object back.
     cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

    Essa próxima seção usa o cursor para avançar pelo conjunto de resultados. Ele usa as constantes definidas no início do exemplo para retornar os valores de cada campo.

    - +
    // Use the cursor to step through the returned records
     while (cur.moveToNext()) {
         long calID = 0;
         String displayName = null;
         String accountName = null;
         String ownerName = null;
    -      
    +
         // Get the field values
         calID = cur.getLong(PROJECTION_ID_INDEX);
         displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
         accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
         ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
    -              
    +
         // Do something with the values...
     
        ...
     }
     
    - +

    Modificação de uma agenda

    Para realizar uma atualização de uma agenda, é possível fornecer o {@link @@ -350,7 +350,7 @@ URI ou como o primeiro item de seleção. A seleção deve iniciar com "_id=?" e o primeiro selectionArg deve ser o {@link -android.provider.BaseColumns#_ID} da agenda. +android.provider.BaseColumns#_ID} da agenda. Também é possível realizar atualizações com codificações do ID na URI. Este exemplo altera o nome de exibição de uma agenda usando a abordagem @@ -377,14 +377,14 @@ android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} de {@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}. {@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} é um tipo de conta especial para agendas -não associado a nenhuma conta do dispositivo. Agendas desse tipo não são sincronizadas com um servidor. Para +não associado a nenhuma conta do dispositivo. Agendas desse tipo não são sincronizadas com um servidor. Para ver discussões sobre adaptadores de sincronização, consulte Adaptadores de sincronização.

    Tabela de eventos

    A tabela {@link android.provider.CalendarContract.Events} contém detalhes de eventos individuais. Para adicionar, atualizar ou excluir eventos, um aplicativo deve -conter a permissão {@link android.Manifest.permission#WRITE_CALENDAR} +conter a permissão {@link android.Manifest.permission#WRITE_CALENDAR} no arquivo de manifesto.

    As colunas de Eventos a seguir são graváveis tanto por um aplicativo quanto por um adaptador @@ -434,7 +434,7 @@ android.provider.CalendarContract.Events}.

    - + - + - + - - + + - + - + - + - - + - + - + @@ -514,11 +514,11 @@ java.util.TimeZone#getAvailableIDs()}. Observe que essa regra não se aplica a inserções de evento pela intenção {@link android.content.Intent#ACTION_INSERT INSERT} descrita em Uso de uma intenção para inserir um evento — nesta situação, é fornecido um fuso horário padrão. - +
  • Para eventos não recorrentes, é preciso incluir {@link android.provider.CalendarContract.EventsColumns#DTEND}.
  • - - + +
  • Para eventos recorrentes, é necessário incluir uma {@link android.provider.CalendarContract.EventsColumns#DURATION} além de uma {@link android.provider.CalendarContract.EventsColumns#RRULE} ou {@link @@ -528,7 +528,7 @@ android.content.Intent#ACTION_INSERT INSERT} descrita em Tabela de participantes @@ -634,10 +634,10 @@ Log.i(DEBUG_TAG, "Rows deleted: " + rows); representa um único participante ou convidado de um evento. Chamar {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} retorna uma lista de participantes para -o evento com o {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} dado. +o evento com o {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} dado. Esse {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} deve corresponder ao {@link -android.provider.BaseColumns#_ID} de determinado evento.

    +android.provider.BaseColumns#_ID} de determinado evento.

    A tabela a seguir lista os campos graváveis. Ao inserir um novo participante, é necessário incluir todos eles @@ -773,7 +773,7 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values);

    Tabela de instâncias

    -

    A tabela +

    A tabela {@link android.provider.CalendarContract.Instances} contém os horários de início e término das ocorrência de um evento. Cada linha nessa tabela representa uma única ocorrência do evento. A tabela de instâncias não é gravável e fornece @@ -782,7 +782,7 @@ somente um modo de consultar ocorrências de eventos.

    A tabela a seguir relaciona alguns dos campos passíveis de consulta de uma instância. Observe que o fuso horário é definido por {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} -e +e {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}.

    @@ -801,18 +801,18 @@ e
  • - + - + - + @@ -820,16 +820,16 @@ no fuso horário do Agenda. - - + - +
    {@link android.provider.CalendarContract.Calendars#VISIBLE}Um booleano indicando se a agenda foi selecionada para ser exibida. Um valor de 0 indica que eventos associados a essa agenda não devem ser exibidos. Um valor de 1 indica que eventos associados a essa agenda devem @@ -240,7 +240,7 @@ android.provider.CalendarContract.Instances}.
    {@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}Um booleano que indica se a agenda deve ser sincronizada e ter os eventos armazenados no dispositivo. Um valor de 0 indica a não sincronização dessa agenda e o não armazenamento dos eventos no dispositivo. Um valor de 1 indica a sincronização dos eventos dessa agenda @@ -253,7 +253,7 @@ e o armazenamento dos eventos no dispositivo.
    {@link android.provider.CalendarContract.EventsColumns#DURATION}A duração do evento em formato RCF5545. Por exemplo, um valor de "PT1H" indica que o evento deve durar uma hora, e um valor de "P2W" indica @@ -444,39 +444,39 @@ uma duração de 2 semanas.
    {@link android.provider.CalendarContract.EventsColumns#ALL_DAY}Um valor de 1 indica que esse evento ocupa o dia inteiro, como definido pelo fuso horário local. Um valor de 0 indica que é um evento comum que pode iniciar e terminar a qualquer momento durante um dia.
    {@link android.provider.CalendarContract.EventsColumns#RRULE}A regra de recorrência do formato do evento. Por exemplo, "FREQ=WEEKLY;COUNT=10;WKST=SU". Veja mais exemplos aqui.
    {@link android.provider.CalendarContract.EventsColumns#RDATE}As datas de recorrência do evento. - Normalmente, usa-se {@link android.provider.CalendarContract.EventsColumns#RDATE} - em conjunto com {@link android.provider.CalendarContract.EventsColumns#RRULE} + As datas de recorrência do evento. + Normalmente, usa-se {@link android.provider.CalendarContract.EventsColumns#RDATE} + em conjunto com {@link android.provider.CalendarContract.EventsColumns#RRULE} para definir um conjunto agregado de ocorrências repetidas. Para ver mais discussões, consulte Especificação RFC5545.
    {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}Se esse evento considera tempo ocupado ou se há tempo livre que pode ser reagendado.
    {@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}
    {@link android.provider.CalendarContract.Instances#END_DAY}O dia final juliano da instância relativo ao fuso horário -do Agenda. - +do Agenda. +
    {@link android.provider.CalendarContract.Instances#END_MINUTE}O minuto final da instância calculado a partir de meia-noite no fuso horário do Agenda.
    {@link android.provider.CalendarContract.Instances#EVENT_ID}
    {@link android.provider.CalendarContract.Instances#START_DAY}O dia inicial juliano da instância relativo ao fuso horário do Agenda. + O dia inicial juliano da instância relativo ao fuso horário do Agenda.
    {@link android.provider.CalendarContract.Instances#START_MINUTE}O minuto inicial da instância calculado a partir de meia-noite, relativo -ao fuso horário do Agenda. +ao fuso horário do Agenda.
    @@ -840,7 +840,7 @@ ao fuso horário do Agenda. na URI. Neste exemplo, {@link android.provider.CalendarContract.Instances} obtém acesso ao campo {@link android.provider.CalendarContract.EventsColumns#TITLE} por meio -da sua implementação da interface {@link android.provider.CalendarContract.EventsColumns}. +da sua implementação da interface {@link android.provider.CalendarContract.EventsColumns}. Em outras palavras, {@link android.provider.CalendarContract.EventsColumns#TITLE} é retornado por uma vista do banco de dados, não pela consulta da tabela {@link @@ -853,7 +853,7 @@ public static final String[] INSTANCE_PROJECTION = new String[] { Instances.BEGIN, // 1 Instances.TITLE // 2 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; @@ -868,7 +868,7 @@ long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); - + Cursor cur = null; ContentResolver cr = getContentResolver(); @@ -883,28 +883,28 @@ ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query -cur = cr.query(builder.build(), - INSTANCE_PROJECTION, - selection, - selectionArgs, +cur = cr.query(builder.build(), + INSTANCE_PROJECTION, + selection, + selectionArgs, null); - + while (cur.moveToNext()) { String title = null; long eventID = 0; - long beginVal = 0; - + long beginVal = 0; + // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); - - // Do something with the values. - Log.i(DEBUG_TAG, "Event: " + title); + + // Do something with the values. + Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(beginVal); + calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); + Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } }
    @@ -923,8 +923,8 @@ while (cur.moveToNext()) { {@link android.content.Intent#ACTION_VIEW VIEW}

    content://com.android.calendar/time/<ms_since_epoch>

    Também pode-se consultar a URI com -{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. -Para ver um exemplo do uso dessa intenção, consulte
    Uso de intenções para exibir dados de calendários. +{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. +Para ver um exemplo do uso dessa intenção, consulte Uso de intenções para exibir dados de calendários. Abre a agenda no horário especificado por <ms_since_epoch>. @@ -935,11 +935,11 @@ Para ver um exemplo do uso dessa intenção, consulte Uso de intenções para exibir dados de calendários. - + Exibe o evento especificado por <event_id>. @@ -952,12 +952,12 @@ Para ver um exemplo do uso dessa intenção, consulte Uso de uma intenção para editar um evento. - - + + Edita o evento especificado por <event_id>. @@ -972,11 +972,11 @@ Para ver um exemplo do uso dessa intenção, consulte Uso de uma intenção para inserir um evento. - + Cria um evento. @@ -996,7 +996,7 @@ Para ver um exemplo do uso dessa intenção, consulte arquivo de manifesto.

    - +

    Quando usuários executam um aplicativo que usa essa abordagem, ele os direciona ao Agenda para finalizar a adição do evento. A intenção {@link android.content.Intent#ACTION_INSERT INSERT} usa campos extras para pré-preencher um formulário com os detalhes do evento na Agenda. Os usuários podem, então, cancelar o evento, editar o formulário conforme o necessário ou salvar o evento nas suas agendas.

    - +

    A seguir há um fragmento de código que agenda um evento em 19 de janeiro de 2012, que acontece @@ -1075,7 +1075,7 @@ das 7h30 às 8h30. Observe o exposto a seguir sobre esse fragmento de código:

  • Ele especifica {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} como a URI.
  • - +
  • Ele usa os campos extras {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} e {@link @@ -1083,10 +1083,10 @@ android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} para pré-preencher o formulário com o horário do evento. Os valores desses horários devem estar em milissegundos UTC da época.
  • - +
  • Ele usa o campo extra {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL} para fornecer uma lista de termos separados por vírgula de convidados, especificados por endereço de e-mail.
  • - +
     Calendar beginTime = Calendar.getInstance();
    @@ -1158,12 +1158,12 @@ via aplicativo e via adaptador de sincronização:

    • Um adaptador de sincronização precisa especificar que é um adaptador de sincronização que define {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} como true.
    • - - + +
    • Os adaptadores de sincronização precisam fornecer um {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} e um {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} como parâmetros da consulta na URI.
    • - +
    • Os adaptadores de sincronização têm acesso de gravação a mais colunas do que um aplicativo ou widget. Por exemplo: um aplicativo só pode modificar algumas características de uma agenda, como nome, nome de exibição, configurações de visibilidade e se a agenda está @@ -1180,5 +1180,5 @@ e ao ACCOUNT_TYPE que especificou.
    .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }
    -

    Para obter uma implementação de exemplo de um adaptador de sincronização (não especificamente relacionada ao Agenda), consulte +

    Para obter uma implementação de exemplo de um adaptador de sincronização (não especificamente relacionada ao Agenda), consulte SampleSyncAdapter. diff --git a/docs/html-intl/intl/pt-br/guide/topics/providers/contacts-provider.jd b/docs/html-intl/intl/pt-br/guide/topics/providers/contacts-provider.jd index 0d42d2daed530d74530c8bce80ac736a297ee3a9..f3b7c58523af7527b90e1325bb07a9c15245273a 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/providers/contacts-provider.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/providers/contacts-provider.jd @@ -113,14 +113,14 @@ o Provedor de Contatos. Este guia considera que o leitor conhece os preceitos dos provedores de conteúdo do Android. Para saber mais sobre provedores de conteúdo do Android, leia o guia - Preceitos do provedor de conteúdo. + Preceitos do provedor de conteúdo. O aplicativo Exemplo de adaptador de sincronização é um exemplo de uso de um adaptador de sincronização que transfere dados entre o Provedor de contatos e um aplicativo de amostra hospedado pelo Google Web Services.

    Organização do Provedor de Contatos

    - O Provedor de Contatos é um componente do provedor de conteúdo do Android. Ele mantém três tipos de + O Provedor de Contatos é um componente do provedor de conteúdo do Android. Ele mantém três tipos de dados sobre uma pessoa, sendo cada um deles correspondente a uma tabela fornecida pelo provedor, como ilustrado na figura 1:

    @@ -199,7 +199,7 @@ de dados de uma pessoa, ele permite diversos contatos brutos para a mesma pessoa {@link android.provider.ContactsContract.SyncColumns#ACCOUNT_TYPE}. - O formato desse nome é específico deste tipo de conta. + O formato desse nome é específico deste tipo de conta. Não se trata necessariamente de um endereço de e-mail. @@ -239,7 +239,7 @@ de dados de uma pessoa, ele permite diversos contatos brutos para a mesma pessoa
    • O nome de um contato bruto não é armazenado em sua linha em - {@link android.provider.ContactsContract.RawContacts}. Em vez disso, é armazenado na + {@link android.provider.ContactsContract.RawContacts}. Em vez disso, é armazenado na tabela {@link android.provider.ContactsContract.Data}, em uma linha {@link android.provider.ContactsContract.CommonDataKinds.StructuredName}. Os contatos brutos têm apenas uma linha desse tipo na tabela {@link android.provider.ContactsContract.Data}. @@ -275,7 +275,7 @@ de dados de uma pessoa, ele permite diversos contatos brutos para a mesma pessoa Configurações da conta.

      - Suponhamos que Emily Dickinson abra uma janela do navegador, acesse o Gmail como + Suponhamos que Emily Dickinson abra uma janela do navegador, acesse o Gmail como emily.dickinson@gmail.com, abra Contatos e adicione "Thomas Higginson". Mais tarde, ela acessa o Gmail como emilyd@gmail.com e envia um e-mail para "Thomas Higginson", o que automaticamente @@ -309,7 +309,7 @@ de dados de uma pessoa, ele permite diversos contatos brutos para a mesma pessoa tipo de dados, como endereços de e-mail ou números de telefone. Por exemplo: se "Thomas Higginson" para {@code emilyd@gmail.com} (a linha do contato bruto de Thomas Higginson associada à conta Google emilyd@gmail.com) tem um endereço de e-mail pessoal - thigg@gmail.com e um de trabalho + thigg@gmail.com e um de trabalho thomas.higginson@gmail.com, o Provedor de Contatos armazena as duas linhas de endereço de e-mail e vincula ambas ao contato bruto.

      @@ -490,7 +490,7 @@ de dados de uma pessoa, ele permite diversos contatos brutos para a mesma pessoa {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} do contato continuará apontado para a linha do contato para permitir o uso de {@code android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY} - e manter ligações com contatos "favoritos" e assim por diante. Essa coluna tem o próprio formato, que + e manter ligações com contatos "favoritos" e assim por diante. Essa coluna tem o próprio formato, que não tem nenhuma relação com o formato da coluna {@code android.provider.BaseColumns#_ID}.

      @@ -981,7 +981,7 @@ public Loader<Cursor> onCreateLoader(int id, Bundle args) { {@code android.provider.BaseColumns#_ID} do contato bruto como o valor {@link android.provider.ContactsContract.DataColumns#RAW_CONTACT_ID}. Contudo, esse valor não está disponível ao criar a {@link android.content.ContentProviderOperation} - para a linha de dados porque + para a linha de dados porque {@link android.content.ContentProviderOperation} ainda não foi aplicada à linha de contato bruto. Para trabalhar com isso, a classe {@link android.content.ContentProviderOperation.Builder} tem o método {@link android.content.ContentProviderOperation.Builder#withValueBackReference(String, int) withValueBackReference()}. @@ -1403,7 +1403,7 @@ StructuredPostal.CONTENT_URI}, RawContacts.CONTENT_TYPE}, tipo MIME para um grupo de contatos brutos. - Exibe a tela Adicionar contato do aplicativo de contatos do dispositivo. + Exibe a tela Adicionar contato do aplicativo de contatos do dispositivo. São exibidos os valores extras adicionados à intenção. Se enviada com {@link android.app.Activity#startActivityForResult(Intent, int) startActivityForResult()}, a URI de conteúdo do contato bruto recentemente adicionado é passada de volta @@ -1636,7 +1636,7 @@ startActivity(insertIntent); a disponibilidade dos dados dos contatos mesmo quando o dispositivo não está conectado à rede.

      - Embora seja possível implementar a sincronização de diversos modos, o sistema Android fornece + Embora seja possível implementar a sincronização de diversos modos, o sistema Android fornece uma estrutura de sincronização de extensão que automatiza as seguintes tarefas:

        @@ -1652,7 +1652,7 @@ startActivity(insertIntent);

      Para usar essa estrutura, deve-se fornecer uma extensão do adaptador de sincronização. Cada adaptador de sincronização é exclusivo - de um serviço e um provedor de conteúdo, mas pode tratar diversos nomes de conta do mesmo serviço. + de um serviço e um provedor de conteúdo, mas pode tratar diversos nomes de conta do mesmo serviço. A estrutura também permite diversos adaptadores de sincronização para o mesmo serviço e provedor.

      Classes e arquivos do adaptador de sincronização

      @@ -1830,7 +1830,7 @@ elemento <Textos de fluxos sociais

      - Itens de fluxo sempre são associados a um contato bruto. + Itens de fluxo sempre são associados a um contato bruto. O {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID} conecta-se ao valor _ID do contato bruto. O tipo e o nome da conta do contato bruto também são armazenados na linha do item de fluxo. @@ -1861,17 +1861,17 @@ elemento <

      {@code android:icon}
      - + Recurso desenhável do Android que o aplicativo de contatos exibe próximo aos dados. Use isso para indicar ao usuário que os dados são advindos do seu serviço.
      {@code android:summaryColumn}
      - O nome de coluna do primeiro de dois valores recuperados da linha de dados. + O nome de coluna do primeiro de dois valores recuperados da linha de dados. O valor é exibido como a primeira linha da entrada para essa linha de dados. A primeira linha destina-se ao uso como um resumo dos dados, mas isso é opcional. Veja também android:detailColumn. diff --git a/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-basics.jd b/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-basics.jd index 5005f9208bfe7026bac63524ecbfd9dd6dd2d2f4..7bbca94bd937e4c13fea5454660433c28b341cc1 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-basics.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-basics.jd @@ -216,7 +216,7 @@ page.title=Preceitos do provedor de conteúdo Os aplicativos acessam dados a partir de um provedor de conteúdo com um objeto cliente {@link android.content.ContentResolver}. Esse objeto tem métodos que chamam métodos de nome idêntico no objeto do provedor, uma instância de uma das subclasses - concretas de {@link android.content.ContentProvider}. + concretas de {@link android.content.ContentProvider}. Os métodos {@link android.content.ContentResolver} fornecem as funções básicas do "CRUD" (criar, recuperar, atualizar e excluir) de armazenamento persistente.

      @@ -251,7 +251,7 @@ mCursor = getContentResolver().query(

    A tabela 2 mostra como os argumentos para - {@link android.content.ContentResolver#query + {@link android.content.ContentResolver#query query(Uri,projection,selection,selectionArgs,sortOrder)} correspondem a uma declaração SQL SELECT:

    @@ -310,7 +310,7 @@ mCursor = getContentResolver().query( {@link android.provider.UserDictionary.Words#CONTENT_URI} contém a URI de conteúdo da tabela de "palavras" do dicionário do usuário. O objeto {@link android.content.ContentResolver} analisa a autoridade da URI e usa-na para "determinar" o provedor - comparando a autoridade a uma tabela de provedores conhecidos do sistema. + comparando a autoridade a uma tabela de provedores conhecidos do sistema. O {@link android.content.ContentResolver} pode, então, enviar os argumentos da consulta ao provedor correto.

    @@ -344,7 +344,7 @@ Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

    Observação: as classes {@link android.net.Uri} e {@link android.net.Uri.Builder} - contêm métodos convenientes para a construção de objetos de URI bem formados a partir de strings. + contêm métodos convenientes para a construção de objetos de URI bem formados a partir de strings. As {@link android.content.ContentUris} contêm métodos conveniente para anexar valores de ID a uma URI. O fragmento anterior usa {@link android.content.ContentUris#withAppendedId withAppendedId()} para anexar um ID à URI de conteúdo UserDictionary. @@ -359,7 +359,7 @@ Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

    Por uma questão de clareza, os fragmentos de código nesta seção chamam - {@link android.content.ContentResolver#query ContentResolver.query()} no "encadeamento da IU". + {@link android.content.ContentResolver#query ContentResolver.query()} no "encadeamento da IU". No código atual, contudo, deve-se realizar consultas assincronamente em um encadeamento separado. Um modo de fazê-lo é usar a classe {@link android.content.CursorLoader}, descrita com mais detalhes no guia @@ -567,7 +567,7 @@ selectionArgs[0] = mUserInput;

    O método cliente {@link android.content.ContentResolver#query ContentResolver.query()} sempre retorna um {@link android.database.Cursor} contendo as colunas especificadas pela projeção - da consulta para as linhas que atendem aos critérios de seleção da consulta. + da consulta para as linhas que atendem aos critérios de seleção da consulta. Um objeto {@link android.database.Cursor} fornece acesso para leitura aleatório para as linhas e colunas que contém. Usando métodos {@link android.database.Cursor}, é possível repetir as linhas nos resultados, determinar o tipo dos dados de cada coluna, extrair os dados de uma coluna e examinar @@ -946,7 +946,7 @@ mRowsDeleted = getContentResolver().delete( Para acessar um provedor em "modo de lote", cria-se uma matriz de objetos {@link android.content.ContentProviderOperation} e, em seguida, envia-os a um provedor de conteúdo com - {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Confere-se a + {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Confere-se a autoridade do provedor de conteúdo para esse método em vez de para uma URI de conteúdo específica. Isso permite que cada objeto {@link android.content.ContentProviderOperation} na matriz trabalhe com uma tabela diferente. Chamar {@link android.content.ContentResolver#applyBatch @@ -954,7 +954,7 @@ mRowsDeleted = getContentResolver().delete(

    A descrição da classe de contrato {@link android.provider.ContactsContract.RawContacts} - contém um fragmento de código que demonstra a inserção em lote. + contém um fragmento de código que demonstra a inserção em lote. O aplicativo de exemplo do Gerente de contato contém um exemplo de acesso em lote em seu arquivo de origem ContactAdder.java. @@ -1089,7 +1089,7 @@ O aplicativo de exemplo do item/vnd.example.line2

    - A maioria dos provedores define constantes de classe de contrato para os tipos MIME que usam. + A maioria dos provedores define constantes de classe de contrato para os tipos MIME que usam. A classe de contrato {@link android.provider.ContactsContract.RawContacts} do Provedor de Contatos, por exemplo, define a constante {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} para o tipo MIME diff --git a/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-creating.jd index 11ad4c3b1cca845e6d513919fd3a41039eafa615..6ae7b2d6ee3d183ec2f7fdff2597faff0b1f8c37 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-creating.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/providers/content-provider-creating.jd @@ -203,7 +203,7 @@ Projeto de armazenamento de dados.

    • O sistema Android contém uma API de banco de dados SQLite que os provedores do Android usam - para armazenar dados orientados a tabela. + para armazenar dados orientados a tabela. A classe {@link android.database.sqlite.SQLiteOpenHelper} ajuda a criar bancos de dados e a classe {@link android.database.sqlite.SQLiteDatabase} é a classe de base para acessar banco de dados. @@ -539,7 +539,7 @@ public class ExampleProvider extends ContentProvider {

      - Observe que esses métodos têm a mesma assinatura dos métodos + Observe que esses métodos têm a mesma assinatura dos métodos {@link android.content.ContentResolver} de mesmo nome.

      @@ -569,7 +569,7 @@ public class ExampleProvider extends ContentProvider {

    Implementação do método query()

    - + O método {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) ContentProvider.query()} precisa retornar um objeto {@link android.database.Cursor} ou, se falhar, gerar uma {@link java.lang.Exception}. Se você estiver usando um banco de dados SQLite @@ -778,7 +778,7 @@ protected static final class MainDatabaseHelper extends SQLiteOpenHelper { Para tipos de dados comuns como texto, HTML ou JPEG, {@link android.content.ContentProvider#getType(Uri) getType()} deve retornar o tipo MIME padrão daqueles dados. Há uma lista completa desse tipos de padrão - no site de + no site de Tipos de mídia MIME IANA.

    @@ -981,7 +981,7 @@ vnd.android.cursor.item/vnd.com.example.provider.table1 Permissão de leitura, gravação ou leitura/gravação para uma URI de conteúdo no provedor. Especifica-se cada URI que se deseja controlar com um elemento filho - <path-permission> + <path-permission> do elemento <provider>. Para cada URI de conteúdo, pode-se especificar uma permissão de leitura/gravação, uma permissão de leitura, uma permissão de gravação ou as três. As permissões diff --git a/docs/html-intl/intl/pt-br/guide/topics/providers/content-providers.jd b/docs/html-intl/intl/pt-br/guide/topics/providers/content-providers.jd index c9574f6b90c6e7613e3eda060bcdec0b0e2275b6..48f4cd49843d6d5a0210562b4670ca01293ca501 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/providers/content-providers.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/providers/content-providers.jd @@ -52,12 +52,12 @@ dados e fornecem mecanismos para definir a segurança dos dados. Provedores de c padrão que conecta dados em um processo com código em execução em outro processo.

    - Quando desejar acessar dados em um provedor de conteúdo, você usa o - objeto {@link android.content.ContentResolver} no + Quando desejar acessar dados em um provedor de conteúdo, você usa o + objeto {@link android.content.ContentResolver} no {@link android.content.Context} do aplicativo para se comunicar com o provedor como cliente. O objeto {@link android.content.ContentResolver} se comunica com o objeto provedor, uma instância de uma classe que implementa {@link android.content.ContentProvider}. O objeto - provedor recebe solicitações de dados de clientes, realiza a ação solicitada e + provedor recebe solicitações de dados de clientes, realiza a ação solicitada e devolve os resultados.

    @@ -68,10 +68,10 @@ dados e fornecem mecanismos para definir a segurança dos dados. Provedores de c

    O Android propriamente dito inclui provedores de conteúdo que gerenciam dados como áudio, vídeo, imagens e - informações de contato pessoais. Alguns deles estão listados na documentação de - referência do + informações de contato pessoais. Alguns deles estão listados na documentação de + referência do pacote android.provider - . Com algumas restrições, esses provedores podem ser acessados por qualquer aplicativo + . Com algumas restrições, esses provedores podem ser acessados por qualquer aplicativo Android.

    Os tópicos a seguir descrevem provedores de conteúdo em mais detalhes: diff --git a/docs/html-intl/intl/pt-br/guide/topics/providers/document-provider.jd b/docs/html-intl/intl/pt-br/guide/topics/providers/document-provider.jd index 25aab7aa7a9d247261553094926e8639f25c51a6..b2e040ecefa551ee1d8fa5a29103dec03e04a8ab 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/providers/document-provider.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/providers/document-provider.jd @@ -139,7 +139,7 @@ dispositivos de armazenamento USB transitórios ou login/logout do usuário.N documentos.

  • Cada back-end de armazenamento apresenta -arquivos e diretórios individuais referenciando-os com um +arquivos e diretórios individuais referenciando-os com um {@link android.provider.DocumentsContract.Document#COLUMN_DOCUMENT_ID} exclusivo. IDs de documentos devem ser exclusivos e não podem mudar depois de emitidos, pois são usados para concessões persistentes da URI em reinicializações do dispositivo.
  • @@ -236,7 +236,7 @@ imagens armazenadas em um provedor de documentos. -

    Esta seção descreve como programar aplicativos clientes com base nas intenções +

    Esta seção descreve como programar aplicativos clientes com base nas intenções {@link android.content.Intent#ACTION_OPEN_DOCUMENT} e {@link android.content.Intent#ACTION_CREATE_DOCUMENT}.

    @@ -521,7 +521,7 @@ os arquivos, o que, obviamente, não é o ideal.

    Para evitar que isso aconteça, você pode manter as permissões que o sistema forneceu ao aplicativo. Efetivamente, o aplicativo "toma" a concessão de permissão da URI persistente -que o sistema está oferecendo. Isso concede ao usuário um acesso contínuo aos arquivos +que o sistema está oferecendo. Isso concede ao usuário um acesso contínuo aos arquivos por meio do aplicativo mesmo se o dispositivo for reiniciado:

    @@ -624,7 +624,7 @@ em dispositivos que executam o Android 4.4 ou posteriores. Se você deseja que o aplicativo seja compatível com {@link android.content.Intent#ACTION_GET_CONTENT} para adaptar-se a dispositivos que executam o Android 4.3 ou versões anteriores, é necessário desativar o filtro de intenção {@link android.content.Intent#ACTION_GET_CONTENT} -no manifesto para dispositivos que executam Android 4.4 ou versões posteriores. +no manifesto para dispositivos que executam Android 4.4 ou versões posteriores. Um provedor de documentos e {@link android.content.Intent#ACTION_GET_CONTENT} devem ser avaliados de forma mutuamente exclusiva. Se houver compatibilidade com ambos simultaneamente, o aplicativo aparecerá duas vezes na IU do seletor do sistema, oferecendo dois meios de acesso diff --git a/docs/html-intl/intl/pt-br/guide/topics/resources/accessing-resources.jd b/docs/html-intl/intl/pt-br/guide/topics/resources/accessing-resources.jd index f196dfeae779f9f81baac742054fbd065a6ffad5..de8b5df5e486874e0225cdc53b08027420b76f5d 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/resources/accessing-resources.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/resources/accessing-resources.jd @@ -11,7 +11,7 @@ parent.link=index.html {@code R.drawable.myimage}
  • Recursos podem ser referenciados de recursos usando uma sintaxe XML especial, como {@code @drawable/myimage}
  • -
  • Também é possível acessar os recursos do aplicativo com métodos em +
  • Também é possível acessar os recursos do aplicativo com métodos em {@link android.content.res.Resources}
  • @@ -43,10 +43,10 @@ parent.link=index.html

    Depois de fornecer um recurso no aplicativo (discutido em Fornecimento de recursos), é possível aplicá-lo -referenciando seu ID de recurso. Todos os IDs de recursos são definidos na classe {@code R} do projeto, que +referenciando seu ID de recurso. Todos os IDs de recursos são definidos na classe {@code R} do projeto, que a ferramenta {@code aapt} gera automaticamente.

    -

    Quando o aplicativo é compilado, {@code aapt} gera a classe {@code R}, que contém +

    Quando o aplicativo é compilado, {@code aapt} gera a classe {@code R}, que contém IDs de recursos para todos os recursos no diretório {@code res/}. Para cada tipo de recurso, há uma subclasse {@code R} (por exemplo, {@code R.drawable} para todos os recursos desenháveis) e, para cada recurso daquele tipo, há um número inteiro @@ -60,7 +60,7 @@ verificá-la para descobrir um ID de recurso. Ele é sempre composto de:

    string}, {@code drawable} e {@code layout}. Para saber mais sobre os diferentes tipos, consulte Tipos de recursos.
  • O nome do recurso, que é: o nome do arquivo, -excluindo a extensão; ou o valor no atributo {@code android:name} do XML, se o +excluindo a extensão; ou o valor no atributo {@code android:name} do XML, se o recurso for um valor simples (como uma string).
  • @@ -101,7 +101,7 @@ com {@link android.content.Context#getResources()}.

    • Declarar elementos da IU em XML. O Android fornece um vocabulário XML direto que corresponde às classes e subclasses de View, como as de widgets e layouts.
    • -
    • Instanciar elementos do layout em tempo de execução. +
    • Instanciar elementos do layout em tempo de execução. O aplicativo pode criar objetos de View e ViewGroup (e manipular suas propriedades) programaticamente.
    @@ -123,7 +123,7 @@ public void onCreate(Bundle savedInstanceState) {

    O método de retorno de chamada onCreate() na Atividade é chamado pela estrutura do Android quando -ela é inicializada (veja a discussão sobre ciclos de vida no documento +ela é inicializada (veja a discussão sobre ciclos de vida no documento Atividades ).

    @@ -201,7 +201,7 @@ de layout associados a cada uma delas.

    valores. Cada elemento filho deve definir LayoutParams apropriados para seu pai, embora possa também definir diferentes LayoutParams para os próprios filhos.

    -

    Todos os grupos de vistas contêm largura e altura (layout_width e +

    Todos os grupos de vistas contêm largura e altura (layout_width e layout_height) e cada vista é obrigatória para defini-las. Muitos LayoutParams também contêm margens e bordas opcionais.

    @@ -229,7 +229,7 @@ Recursos disponíveis.

    Posição do layout

    A geometria de uma vista de um retângulo. As vistas têm uma localização, - expressa como um par de coordenadas esquerda e topo + expressa como um par de coordenadas esquerda e topo e duas dimensões, expressas como largura e altura. A unidade de localização e de dimensões é o pixel.

    @@ -262,7 +262,7 @@ desnecessárias, chamados {@link android.view.View#getRight()} e {@link android.

    O primeiro par é conhecido como largura medida e altura medida. Essas dimensões definem o tamanho que a vista terá - dentro da vista pai. + dentro da vista pai. Para obter as dimensões medidas, chamam-se {@link android.view.View#getMeasuredWidth()} e {@link android.view.View#getMeasuredHeight()}.

    @@ -368,7 +368,7 @@ partially or totally obscuring them (unless the newer object is transparent).

    Criação de layouts com um adaptador

    Quando o conteúdo do layout é dinâmico ou não predeterminado, é possível usar um layout que -torne {@link android.widget.AdapterView} uma subclasse para preencher o layout com vistas em tempo de execução. +torne {@link android.widget.AdapterView} uma subclasse para preencher o layout com vistas em tempo de execução. Uma subclasse da classe {@link android.widget.AdapterView} usa um {@link android.widget.Adapter} para agrupar dados ao seu layout. O {@link android.widget.Adapter} se comporta como um intermediário entre a fonte dos dados e o layout do {@link android.widget.AdapterView} — o {@link android.widget.Adapter} @@ -399,7 +399,7 @@ a um {@link android.widget.Adapter}, o que recupera dados de uma fonte externa e android.view.View} que representa cada entrada de dados.

    O Android oferece diversas subclasses de {@link android.widget.Adapter} que são úteis para -recuperar diferentes tipos de dados e criar vistas de um {@link android.widget.AdapterView}. +recuperar diferentes tipos de dados e criar vistas de um {@link android.widget.AdapterView}. Os dois adaptadores mais comuns são:

    @@ -438,7 +438,7 @@ getView()} para retornar o tipo de vista que deseja para cada item.

    {@link android.widget.SimpleCursorAdapter}
    -
    Use este adaptador quando os dados vierem de um {@link android.database.Cursor}. +
    Use este adaptador quando os dados vierem de um {@link android.database.Cursor}. Ao usar {@link android.widget.SimpleCursorAdapter}, é necessário especificar um layout a usar para cada linha no {@link android.database.Cursor} e que colunas no {@link android.database.Cursor} devem ser inseridas em determinadas vistas do layout. Por exemplo: se você deseja criar uma lista @@ -466,7 +466,7 @@ fromColumns} na vista {@code toViews} correspondente.

    .
    -

    Se durante o curso de vida do aplicativo, você mudar os dados subjacentes lidos +

    Se durante o curso de vida do aplicativo, você mudar os dados subjacentes lidos pelo adaptador, chame {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. Isso notificará à vista anexada que os dados foram alterados e que ela deve se atualizar.

    diff --git a/docs/html-intl/intl/pt-br/guide/topics/ui/dialogs.jd b/docs/html-intl/intl/pt-br/guide/topics/ui/dialogs.jd index 2cbedbebdebf3c37e1f5c61d801c3e4b6c89d5b5..71e617677507bc28f00e5712ad921b307c686381 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/ui/dialogs.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/ui/dialogs.jd @@ -32,7 +32,7 @@ page.tags=diálogodealerta,fragmentodediálogo
  • {@link android.app.DialogFragment}
  • {@link android.app.AlertDialog}
  • - +

    Veja também

    1. Guia de projeto de caixas de diálogo
    2. @@ -235,8 +235,8 @@ AlertDialog dialog = builder.create();

      Os métodos set...Button() exigem um título para o botão (fornecido -por um recurso de string) e um -{@link android.content.DialogInterface.OnClickListener} que defina a ação a realizar +por um recurso de string) e um +{@link android.content.DialogInterface.OnClickListener} que defina a ação a realizar quando o usuário pressionar o botão.

      Há três botões de ação diferente que podem ser adicionados:

      @@ -248,7 +248,7 @@ quando o usuário pressionar o botão.

      Neutro
      É o que se deve usar quando houver a opção de o usuário não querer continuar a ação, mas não necessariamente cancelá-la. Ele aparece entre os botões positivo - e negativo. Por exemplo: a ação pode ser "Notifique-me mais tarde".
      + e negativo. Por exemplo: a ação pode ser "Notifique-me mais tarde".

      É possível adicionar somente um de cada tipo de botão a uma {@link @@ -271,7 +271,7 @@ Caixa de diálogo com um título e uma lista.

    3. Lista de escolhas múltiplas persistentes (caixas de seleção)
    4. -

      Para criar uma lista de escolha única como a da figura 3, +

      Para criar uma lista de escolha única como a da figura 3, use o método {@link android.app.AlertDialog.Builder#setItems setItems()}:

      @@ -291,7 +291,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
       
       

      Como a lista aparece na área do conteúdo da caixa de diálogo, a caixa não pode exibir uma mensagem e uma lista, e será preciso definir um título -para ela com {@link android.app.AlertDialog.Builder#setTitle setTitle()}. +para ela com {@link android.app.AlertDialog.Builder#setTitle setTitle()}. Para especificar os itens da lista, chame {@link android.app.AlertDialog.Builder#setItems setItems()} passando uma matriz. Alternativamente, é possível especificar uma lista com {@link @@ -320,8 +320,8 @@ Lista de itens de múltipla escolha.

      Para adicionar uma lista de itens de múltipla escolha (caixas de seleção) ou itens de escolha única (botões de rádio), use os métodos {@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, -DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} ou -{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} ou +{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} respectivamente.

      Por exemplo, a seguir apresenta-se como criar uma lista de múltipla escolha como @@ -346,7 +346,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // 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 + // Else, if the item is already in the array, remove it mSelectedItems.remove(Integer.valueOf(which)); } } @@ -373,7 +373,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

      Embora a lista tradicional e uma lista com botões de opção forneçam uma ação de "escolha única", deve-se usar {@link -android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} se você desejar manter a escolha do usuário. Ou seja, se a caixa de diálogo abrir novamente mais tarde, deve indicar qual é a escolha atual do usuário, portanto deve-se criar uma lista com botões de opção.

      @@ -442,7 +442,7 @@ deve-se alterar a família da fonte para {@code "sans-serif"} para que os campos um estilo de fonte compatível.

      Para inflar o layout no {@link android.support.v4.app.DialogFragment}, -obtenha um {@link android.view.LayoutInflater} com +obtenha um {@link android.view.LayoutInflater} com {@link android.app.Activity#getLayoutInflater()} e chame {@link android.view.LayoutInflater#inflate inflate()}, em que o primeiro parâmetro é o ID de recurso do layout e o segundo é uma vista pai do layout. @@ -470,7 +470,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { public void onClick(DialogInterface dialog, int id) { LoginDialogFragment.this.getDialog().cancel(); } - }); + }); return builder.create(); }

      @@ -505,7 +505,7 @@ uma interface por meio da qual entrega os eventos de volta à atividade do host:
       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. */
      @@ -513,10 +513,10 @@ public class NoticeDialogFragment extends DialogFragment {
               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
           @Override
           public void onAttach(Activity activity) {
      @@ -543,7 +543,7 @@ dela por meio de uma implementação da interface {@code NoticeDialogListener}:<
       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();
      @@ -656,7 +656,7 @@ public class CustomDialogFragment extends DialogFragment {
               // 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. */
           @Override
           public Dialog onCreateDialog(Bundle savedInstanceState) {
      @@ -678,7 +678,7 @@ ou como uma IU de tela cheia com base no tamanho da tela:

      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"); @@ -695,7 +695,7 @@ public void showDialog() { }
      -

      Para obter mais informações sobre a realização de operações de fragmentos, consulte o guia +

      Para obter mais informações sobre a realização de operações de fragmentos, consulte o guia Fragmentos.

      Nesse exemplo, o booleano mIsLargeLayout especifica se o dispositivo atual @@ -721,7 +721,7 @@ versões de recurso bool para diferentes tamanhos de tela:

      </resources> -

      Assim, é possível inicializar o valor {@code mIsLargeLayout} durante o método +

      Assim, é possível inicializar o valor {@code mIsLargeLayout} durante o método {@link android.app.Activity#onCreate onCreate()} da atividade:

      @@ -776,7 +776,7 @@ android.support.v4.app.DialogFragment#onDismiss onDismiss()} no {@link
       android.support.v4.app.DialogFragment}.

      Também é possível cancelar uma caixa de diálogo. Trata-se de um evento especial que indica que o usuário -se retirou explicitamente da caixa de diálogo sem concluir a tarefa. Isso ocorre se o usuário pressionar o botão +se retirou explicitamente da caixa de diálogo sem concluir a tarefa. Isso ocorre se o usuário pressionar o botão Voltar, tocar na tela fora da área da caixa de diálogo ou se você chamar {@link android.app.Dialog#cancel()} explicitamente no {@link android.app.Dialog} (como em resposta a um botão "Cancelar" na caixa de diálogo).

      diff --git a/docs/html-intl/intl/pt-br/guide/topics/ui/menus.jd b/docs/html-intl/intl/pt-br/guide/topics/ui/menus.jd index 833f8966b4391bfe7a3105d0e2acdc80dd1593e5..6bdb370740d303afc04b31eed61ae76474729f20 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/ui/menus.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/ui/menus.jd @@ -83,9 +83,9 @@ não têm), então você deve migrar usando a barra de ação para fornecer aces e outras opções.

      Consulte a seção Criação de um menu de opções.

      - +
      Modo de ação contextual e menu de contexto
      - +
      Um menu de contexto é um menu flutuante que aparece quando o usuário realiza um clique longo em um elemento. Ele fornece ações que afetam o conteúdo selecionado ou a estrutura do contexto. @@ -94,7 +94,7 @@ que afetam o conteúdo selecionado em uma barra no topo da tela e permite que o selecione vários itens.

      Consulte a seção Criação de menus contextuais.

      - +
      Menu pop-up
      Um menu pop-up exibe itens em uma lista vertical ancorada à vista que apresentou o menu. É bom para fornecer um estouro de ações relacionado a conteúdo específico @@ -135,7 +135,7 @@ do projeto e crie o menu com os seguintes elementos:

      <item>
      Cria um {@link android.view.MenuItem}, que representa um único item em um menu. Este elemento pode conter um elemento <menu> aninhado para criar um submenu.
      - +
      <group>
      Um recipiente invisível e opcional para os elementos {@code <item>}. Ele permite que você categorize itens de menu para que eles compartilhem propriedades como estado ativo e visibilidade. Para obter mais informações, @@ -218,7 +218,7 @@ para o contexto de atividade atual, como "Buscar", "Escrever e-mail" e "Configur foi desenvolvido:

        -
      • Caso tenha desenvolvido o aplicativo para Android 2.3.x (API de nível 10) ou +
      • Caso tenha desenvolvido o aplicativo para Android 2.3.x (API de nível 10) ou inferior, os conteúdos do menu de opções aparecerão na parte inferior da tela, quando o usuário pressionar o botão Menu, como exibido na figura 1. Quando aberto, a primeira parte visível é o menu @@ -363,7 +363,7 @@ são apresentados na barra de ação. Quando um evento ocorre e você quer reali você deve chamar {@link android.app.Activity#invalidateOptionsMenu invalidateOptionsMenu()} para pedir que o sistema chame {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}.

        -

        Observação: +

        Observação: você nunca deve alterar os itens no menu de opções com base no {@link android.view.View} atualmente em foco. Quando estiver no modo de toque (quando o usuário não está usando cursor de bola ou um teclado), as vistas não podem ter foco, então você nunca deve usar o foco como base para modificar @@ -742,8 +742,8 @@ que exibe um menu pop-up:

         <ImageButton
        -    android:layout_width="wrap_content" 
        -    android:layout_height="wrap_content" 
        +    android:layout_width="wrap_content"
        +    android:layout_height="wrap_content"
             android:src="@drawable/ic_overflow_holo_dark"
             android:contentDescription="@string/descr_overflow_button"
             android:onClick="showPopup" />
        @@ -901,7 +901,7 @@ android.view.MenuItem#setChecked(boolean) setChecked()}.

        (como {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}). É aqui que você deve definir o estado da caixa de seleção, pois a caixa de seleção ou o botão de rádio não altera o seu estado automaticamente. É possível consultar o estado do item (como ele era antes -do usuário selecioná-lo) com {@link android.view.MenuItem#isChecked()} e, em seguida, definir o estado marcado com +do usuário selecioná-lo) com {@link android.view.MenuItem#isChecked()} e, em seguida, definir o estado marcado com {@link android.view.MenuItem#setChecked(boolean) setChecked()}. Por exemplo:

        @@ -1023,9 +1023,9 @@ do filtro de intenção. Por exemplo:

        </intent-filter>
        -

        Leia mais sobre a criação de filtros de intenção no documento +

        Leia mais sobre a criação de filtros de intenção no documento Intenções e filtros de intenções.

        -

        Para obter um exemplo de aplicativo que usa esta técnica, consulte o código de exemplo do +

        Para obter um exemplo de aplicativo que usa esta técnica, consulte o código de exemplo do Bloco de notas.

        diff --git a/docs/html-intl/intl/pt-br/preview/features/multi-window.jd b/docs/html-intl/intl/pt-br/guide/topics/ui/multi-window.jd similarity index 98% rename from docs/html-intl/intl/pt-br/preview/features/multi-window.jd rename to docs/html-intl/intl/pt-br/guide/topics/ui/multi-window.jd index 77421820dde36794d6a10c9fb4a8edb297c45fc5..26259f654e8e1900e4ccae340db24cc4cf0be825 100644 --- a/docs/html-intl/intl/pt-br/preview/features/multi-window.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/ui/multi-window.jd @@ -4,8 +4,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form" @jd:body -
        -
        +
        +

        Neste documento

        1. Visão geral
        2. @@ -34,9 +34,9 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

          Se você compilar o aplicativo com o N Preview SDK, poderá configurar como o aplicativo - processa a exibição de várias janelas. Por exemplo, você pode especificar as dimensões + processa a exibição de várias janelas. Por exemplo, você pode especificar as dimensões mínimas permitidas para a atividade. Você também pode desativar a exibição de várias janelas para - o aplicativo, garantindo que o sistema mostre o aplicativo apenas + o aplicativo, garantindo que o sistema mostre o aplicativo apenas em modo de tela inteira.

          @@ -69,8 +69,8 @@ em modo de tela inteira.
      - +

      Figura 1. Dois aplicativos executando lado a lado em modo de tela dividida.

      diff --git a/docs/html-intl/intl/pt-br/guide/topics/ui/notifiers/notifications.jd b/docs/html-intl/intl/pt-br/guide/topics/ui/notifiers/notifications.jd index 42563ace224828b749aaf52f649ca7121708925a..d3fb4cfab296222cd3aacca2a5619682e4ac01e8 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/ui/notifiers/notifications.jd @@ -92,7 +92,7 @@ A classe {@link android.app.Notification.Builder Notification.Builder} foi adici

      As notificações, como parte importante da interface do usuário do Android, possuem as próprias diretrizes de projeto. As alterações do Material Design introduzidas no Android 5.0 (API de nível 21) são de importância específica e, por isso, recomenda-se revisar o treinamento do Material Design - para obter mais informações. Para saber como projetar notificações e suas interações, leia o guia de projeto + para obter mais informações. Para saber como projetar notificações e suas interações, leia o guia de projeto Notificações.

      Criação de uma notificação

      @@ -451,14 +451,14 @@ todas as notificações emitidas anteriormente. Adicione compatibilidade com Android 4.0.3 e mais antigos. Para fazer isto, especifique o pai da {@link android.app.Activity} que está iniciando adicionando um elemento <meta-data> - como o filho de + como o filho de <activity>.

      - Para este elemento, defina + Para este elemento, defina android:name="android.support.PARENT_ACTIVITY". Defina android:value="<parent_activity_name>", - onde <parent_activity_name> é o valor de + onde <parent_activity_name> é o valor de android:name para o elemento <activity> diff --git a/docs/html-intl/intl/pt-br/guide/topics/ui/overview.jd b/docs/html-intl/intl/pt-br/guide/topics/ui/overview.jd index d12bfe5fac8b593e37f764a5cf9cca45457a8a3f..d82ecf7aa8fa7dea3905515e7e4a3d81506d2b1c 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/ui/overview.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/ui/overview.jd @@ -4,12 +4,12 @@ page.title=Visão geral da IU

      Todos os elementos da interface do usuário em um aplicativo para Android são criados usando objetos {@link android.view.View} e {@link android.view.ViewGroup}. Uma {@link android.view.View} é um objeto que desenha -algo na tela com o qual o usuário pode interagir. Um {@link android.view.ViewGroup} é um +algo na tela com o qual o usuário pode interagir. Um {@link android.view.ViewGroup} é um objeto que contém outros objetos {@link android.view.View} (e {@link android.view.ViewGroup}) para definir o layout da interface.

      O Android fornece uma coleção de subclasses {@link android.view.View} e {@link -android.view.ViewGroup} que oferecem controles de entrada comuns (como botões e campos de +android.view.ViewGroup} que oferecem controles de entrada comuns (como botões e campos de texto) e vários modelos de layout (como um layout linear ou relativo).

      @@ -30,7 +30,7 @@ de uma IU.

      criar uma árvore. Mas a forma mais fácil e efetiva de definir o layout é com um arquivo XML. O XML oferece uma estrutura legível por humanos para o layout, similar a HTML.

      -

      O nome de um elemento XML para uma vista é respectivo à classe do Android que ele representa. Portanto, um elemento +

      O nome de um elemento XML para uma vista é respectivo à classe do Android que ele representa. Portanto, um elemento <TextView> cria um widget {@link android.widget.TextView} na IU e um elemento <LinearLayout> cria um grupo de vistas de {@link android.widget.LinearLayout} .

      @@ -39,7 +39,7 @@ e um elemento <LinearLayout> cria um grupo de vistas de {@lin
       <?xml version="1.0" encoding="utf-8"?>
       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -              android:layout_width="fill_parent" 
      +              android:layout_width="fill_parent"
                     android:layout_height="fill_parent"
                     android:orientation="vertical" >
           <TextView android:id="@+id/text"
      @@ -60,7 +60,7 @@ layout.

      Para obter um guia completo para criar um layout de IU, consulte Layouts XML. - +

      Componentes da interface do usuário

      Você não precisa criar toda a IU usando objetos {@link android.view.View} e {@link diff --git a/docs/html-intl/intl/pt-br/guide/topics/ui/settings.jd b/docs/html-intl/intl/pt-br/guide/topics/ui/settings.jd index f95966c37578da9aa6583b460b86c937494a6a0c..c00b461499d4f4734632b382ddc7bb89f2e9a484 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/ui/settings.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/ui/settings.jd @@ -82,7 +82,7 @@ como programar as configurações do aplicativo por meio de APIs {@link android.

      Figura 1. Capturas de tela das configurações do aplicativo Mensagens -do Android. A seleção de um item definido por uma {@link android.preference.Preference} +do Android. A seleção de um item definido por uma {@link android.preference.Preference} abre uma interface para alterar a configuração.

      @@ -120,8 +120,8 @@ um dos seguintes tipos de dados:

      Como a IU de configurações do aplicativo é criada com objetos {@link android.preference.Preference} - em vez de objetos -{@link android.view.View}, é preciso usar uma subclasse {@link android.app.Activity} ou + em vez de objetos +{@link android.view.View}, é preciso usar uma subclasse {@link android.app.Activity} ou {@link android.app.Fragment} especializada para exibir as configurações de lista:

        @@ -226,8 +226,8 @@ android.preference.ListPreference}. Os dois itens contêm estes três atributos:
        {@code android:key}
        Esse atributo é necessário para preferências que persistem a um valor de dados. Ele especifica a chave exclusiva (uma string) que o sistema usa ao salvar o valor dessa configuração em {@link -android.content.SharedPreferences}. -

        As únicas instâncias em que esse atributo é dispensável ocorrem quando a preferência é um +android.content.SharedPreferences}. +

        As únicas instâncias em que esse atributo é dispensável ocorrem quando a preferência é um {@link android.preference.PreferenceCategory} ou {@link android.preference.PreferenceScreen}, ou quando a preferência especifica um {@link android.content.Intent} para invocar (com um elemento {@code <intent>}) ou um {@link android.app.Fragment} para exibir (com um atributo {@code android:fragment}).

        @@ -285,7 +285,7 @@ android.preference.PreferenceCategory}.

         <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        -    <PreferenceCategory 
        +    <PreferenceCategory
                 android:title="@string/pref_sms_storage_title"
                 android:key="pref_key_storage_settings">
                 <CheckBoxPreference
        @@ -293,12 +293,12 @@ android.preference.PreferenceCategory}.

        android:summary="@string/pref_summary_auto_delete" android:title="@string/pref_title_auto_delete" android:defaultValue="false"... /> - <Preference + <Preference android:key="pref_key_sms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_sms_delete"... /> - <Preference + <Preference android:key="pref_key_mms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" @@ -311,7 +311,7 @@ android.preference.PreferenceCategory}.

        Uso de subtelas

        -

        Para usar grupos de configurações em uma subtela (como ilustrado na figura 3), coloque o grupo +

        Para usar grupos de configurações em uma subtela (como ilustrado na figura 3), coloque o grupo de objetos {@link android.preference.Preference} dentro de {@link android.preference.PreferenceScreen}.

        @@ -588,11 +588,11 @@ dentro de um elemento raiz {@code <preference-headers>}. Por exemplo:

         <?xml version="1.0" encoding="utf-8"?>
         <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
                 android:title="@string/prefs_category_one"
                 android:summary="@string/prefs_summ_category_one" />
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
                 android:title="@string/prefs_category_two"
                 android:summary="@string/prefs_summ_category_two" >
        @@ -636,7 +636,7 @@ public static class SettingsFragment extends PreferenceFragment {
         

        Exibição de cabeçalhos

        Para exibir os cabeçalhos de preferência, é preciso implementar o método de retorno de chamada {@link -android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} e chamar +android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} e chamar {@link android.preference.PreferenceActivity#loadHeadersFromResource loadHeadersFromResource()}. Por exemplo:

        @@ -672,15 +672,15 @@ ao {@link android.preference.PreferenceActivity} que especifica que arquivo XML carregar.

        Por exemplo, abaixo há um arquivo XML de cabeçalhos de preferência usado no Android 3.0 -e posterior ({@code res/xml/preference_headers.xml}):

        +e posterior ({@code res/xml/preference_headers.xml}):

         <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsFragmentOne"
                 android:title="@string/prefs_category_one"
                 android:summary="@string/prefs_summ_category_one" />
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsFragmentTwo"
                 android:title="@string/prefs_category_two"
                 android:summary="@string/prefs_summ_category_two" />
        @@ -692,18 +692,18 @@ mais antigas que a 3.0 ({@code res/xml/preference_headers_legacy.xml}):

         <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        -    <Preference 
        +    <Preference
                 android:title="@string/prefs_category_one"
                 android:summary="@string/prefs_summ_category_one"  >
        -        <intent 
        +        <intent
                     android:targetPackage="com.example.prefs"
                     android:targetClass="com.example.prefs.SettingsActivity"
                     android:action="com.example.prefs.PREFS_ONE" />
             </Preference>
        -    <Preference 
        +    <Preference
                 android:title="@string/prefs_category_two"
                 android:summary="@string/prefs_summ_category_two" >
        -        <intent 
        +        <intent
                     android:targetPackage="com.example.prefs"
                     android:targetClass="com.example.prefs.SettingsActivity"
                     android:action="com.example.prefs.PREFS_TWO" />
        @@ -975,11 +975,11 @@ da caixa de diálogo positiva e negativa:

        public class NumberPickerPreference extends DialogPreference { public NumberPickerPreference(Context context, AttributeSet attrs) { super(context, attrs); - + setDialogLayoutResource(R.layout.numberpicker_dialog); setPositiveButtonText(android.R.string.ok); setNegativeButtonText(android.R.string.cancel); - + setDialogIcon(null); } ... @@ -1194,7 +1194,7 @@ protected void onRestoreInstanceState(Parcelable state) { // Cast state to custom BaseSavedState and pass to superclass SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); - + // Set this Preference's widget to reflect the restored state mNumberPicker.setValue(myState.value); } diff --git a/docs/html-intl/intl/pt-br/guide/topics/ui/ui-events.jd b/docs/html-intl/intl/pt-br/guide/topics/ui/ui-events.jd index e0ace1d4b3cac5a90467e8b3d2c9a936291c4431..2f88248b3eb201f5a9abd5d127fd57182ebe3ad1 100644 --- a/docs/html-intl/intl/pt-br/guide/topics/ui/ui-events.jd +++ b/docs/html-intl/intl/pt-br/guide/topics/ui/ui-events.jd @@ -30,7 +30,7 @@ uma coleção de interfaces aninhadas com retornos de chamada que podem ser defi chamadas de escutas de evento, são a sua passagem para capturar a interação do usuário com a IU.

        Geralmente, as escutas de evento são usadas para escutar a interação do usuário. -No entanto, há casos em que você pode querer estender uma classe View para criar um componente personalizado. +No entanto, há casos em que você pode querer estender uma classe View para criar um componente personalizado. Talvez você queira estender a classe {@link android.widget.Button} para deixar algo mais extravagante. Neste caso, você poderá definir os comportamentos de evento padrão para a classe usando manipuladores de evento.

        @@ -46,27 +46,27 @@ estiver registrada for ativada pela interação do usuário com o item na IU.

        onClick()
        -
        De {@link android.view.View.OnClickListener}. +
        De {@link android.view.View.OnClickListener}. Isto é chamado quando o usuário toca no item (no modo de toque), ou atribui foco ao item com as teclas de navegação ou cursor de bola e pressiona a tecla "enter" adequada ou pressiona o cursor de bola.
        onLongClick()
        -
        De {@link android.view.View.OnLongClickListener}. +
        De {@link android.view.View.OnLongClickListener}. Isto é chamado quando o usuário toca e mantém o item pressionado (no modo de toque), ou atribui foco ao item com as teclas de navegação ou cursor de bola e mantém pressionada a tecla "enter" adequada ou o cursor de bola (por um segundo).
        onFocusChange()
        -
        De {@link android.view.View.OnFocusChangeListener}. +
        De {@link android.view.View.OnFocusChangeListener}. Isto é chamado quando o usuário navega no ou do item, usando as teclas de navegação ou cursor de bola.
        onKey()
        -
        De {@link android.view.View.OnKeyListener}. +
        De {@link android.view.View.OnKeyListener}. Isto é chamado quando o usuário está com foco no item ou solta uma tecla de hardware no dispositivo.
        onTouch()
        -
        De {@link android.view.View.OnTouchListener}. +
        De {@link android.view.View.OnTouchListener}. Isto é chamado quando o usuário realiza uma ação qualificada como um toque de evento, incluindo o pressionamento, a liberação, ou qualquer outro gesto de movimento na tela (dentro dos limites do item).
        onCreateContextMenu()
        -
        De {@link android.view.View.OnCreateContextMenuListener}. +
        De {@link android.view.View.OnCreateContextMenuListener}. Isto é chamado quando um menu de contexto está sendo construído (como resultado de um "clique longo"). Consulte a discussão sobre menus de contexto no guia do desenvolvedor Menus .
        @@ -75,8 +75,8 @@ estiver registrada for ativada pela interação do usuário com o item na IU.

        Esses métodos são os únicos habitantes de suas respectivas interfaces. Para definir um desses métodos e lidar com seus eventos, implemente a interface aninhada na atividade ou defina-a como uma classe anônima. Em seguida, passe uma instância da implementação -para o respectivo método View.set...Listener(). (Ex.:, chame -{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()} +para o respectivo método View.set...Listener(). (Ex.:, chame +{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()} e passe-o à implementação de {@link android.view.View.OnClickListener OnClickListener}.)

        O exemplo abaixo mostra como registrar uma escuta de clique para um botão.

        @@ -121,17 +121,17 @@ public class ExampleActivity extends Activity implements OnClickListener { não tem valor de retorno, mas outros métodos de escuta de evento podem retornar um booleano. O motivo depende do evento. Para os poucos que retornam, apresenta-se a razão:

          -
        • {@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()} - - Isto retorna um booleano para indicar se você consumiu o evento e se ele deve ser levado adiante. - Ou seja, ele retorna verdadeiro para indicar que você lidou com o evento e não deve seguir adiante; +
        • {@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()} - + Isto retorna um booleano para indicar se você consumiu o evento e se ele deve ser levado adiante. + Ou seja, ele retorna verdadeiro para indicar que você lidou com o evento e não deve seguir adiante; ou retorna falso caso você não tenha lidado com ele e/ou o evento deva continuar para qualquer outra escuta de clique.
        • -
        • {@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()} - +
        • {@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()} - Isto retorna um booleano para indicar se você consumiu o evento e se ele deve ser levado adiante. - Ou seja, ele retorna verdadeiro para indicar que você lidou com o evento e não deve seguir adiante; + Ou seja, ele retorna verdadeiro para indicar que você lidou com o evento e não deve seguir adiante; ou retorna falso caso você não tenha lidado com ele e/ou o evento deva continuar para qualquer outra escuta de tecla.
        • -
        • {@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()} - +
        • {@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()} - Isto retorna um booleano para indicar se a escuta consome este evento. O importante é que este evento pode possuir várias ações que se seguem mutuamente. Portanto, se retornar falso quando o evento de ação inferior for recebido, você indicará que não consumiu o evento e que não está @@ -181,14 +181,14 @@ mas podem ter impacto direto na maneira de lidar com os eventos. Portanto, ao ge dentro de um layout, considere esses outros métodos:

          • {@link android.app.Activity#dispatchTouchEvent(MotionEvent) - Activity.dispatchTouchEvent(MotionEvent)} - Isto permite que {@link + Activity.dispatchTouchEvent(MotionEvent)} - Isto permite que {@link android.app.Activity} intercepte todos os evento de toque antes de serem enviados à janela.
          • {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent) ViewGroup.onInterceptTouchEvent(MotionEvent)} - Isto permite que {@link android.view.ViewGroup} assista aos eventos à medida que são enviados para as vistas filho.
          • {@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) ViewParent.requestDisallowInterceptTouchEvent(boolean)} - Chame isto - sobre uma Vista pai para indicar que ela não deve interceptar eventos de toque com {@link + sobre uma Vista pai para indicar que ela não deve interceptar eventos de toque com {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}.
          @@ -199,7 +199,7 @@ Quando um usuário está navegando em uma interface do usuário com teclas direc ver o que aceitará entrada. Se o dispositivo tiver capacidades de toque, no entanto, e o usuário começar a interagir com a interface por meio de toque, então não é mais necessário destacar itens ou fornecer foco para uma vista específica. Contudo, há um modo -de interação chamado "modo de toque". +de interação chamado "modo de toque".

          Para dispositivos com capacidades de toque, quando o usuário toca na tela, o dispositivo @@ -214,7 +214,7 @@ sairá do modo de toque e encontrará uma vista para atribuir foco. Agora, o usu com a interface do usuário sem tocar na tela.

          -O estado de modo de toque é mantido em todo o sistema (todas as janelas e atividades). +O estado de modo de toque é mantido em todo o sistema (todas as janelas e atividades). Para consultar o estado atual, é possível chamar {@link android.view.View#isInTouchMode} para ver se o dispositivo está no modo de toque no momento.

          @@ -282,7 +282,7 @@ como discutido na seção Escutas de evento acima. the framework will take care of measuring, laying out, and drawing the tree as appropriate.
    - +

    Note: 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 diff --git a/docs/html-intl/intl/pt-br/index.jd b/docs/html-intl/intl/pt-br/index.jd index f5e1569dc8466ec1a80cbd71c8ea886e57db32c5..b15ecc89a579df6cb8f7998aa2eb0febc813684e 100644 --- a/docs/html-intl/intl/pt-br/index.jd +++ b/docs/html-intl/intl/pt-br/index.jd @@ -5,49 +5,36 @@ page.customHeadTag= - -

    -
    -
    - -

    Android N Developer Preview

    -

    - Get ready for the next version of Android! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. +

    +
    -
    +

    Если вы хотите изменить частоту фоновых обновлений, чтобы продлить время работы устройства от батареи, сначала рекомендуется проверить текущий уровень заряда и состояние зарядки.

    Именно от этих двух факторов зависит, как обновления повлияют на время работы устройства от батареи. Когда устройство подключено к сети переменного тока, приложение можно обновлять максимально часто, поскольку процесс обновления не будет сказываться на уровне заряда батареи. Если устройство не подключено к сети, следует воздержаться от обновлений, чтобы продлить время его работы от батареи.

    @@ -34,8 +34,8 @@ next.link=docking-monitoring.html

    Если заряд батареи практически исчерпан, можно снизить частоту обновлений (вплоть до их полного прекращения).

    -

    Определение текущего состояния зарядки

    - +

    Определение текущего состояния зарядки

    +

    Начните с определения текущего состояния зарядки. {@link android.os.BatteryManager} передает все сведения о батарее и зарядке в закрепленном намерении {@link android.content.Intent}, которое содержит также информацию о состоянии зарядки.

    Поскольку это намерение является закрепленным, регистрировать {@link android.content.BroadcastReceiver} не нужно. Чтобы получить текущее состояние батареи в виде намерения, нужно вызвать {@code registerReceiver}, передав {@code null} в качестве приемника, как показано в коде ниже. Можно также передать фактический объект {@link android.content.BroadcastReceiver}, но это необязательно, поскольку обработка обновлений будет выполняться позднее.

    @@ -58,7 +58,7 @@ boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;

    Как правило, если устройство подключено к сети переменного тока, фоновые обновления можно выполнять с максимальной частотой. Если устройство заряжается через USB, частоту можно несколько сократить, а если устройство не подключено к сети – сократить еще больше.

    -

    Отслеживание изменений состояния зарядки

    +

    Отслеживание изменений состояния зарядки

    Состояние зарядки изменяется всякий раз, когда пользователь подключает устройство к источнику питания. Поскольку это случается довольно часто, важно отслеживать изменения этого состояния и соответствующим образом корректировать частоту обновления приложения.

    @@ -75,11 +75,11 @@ boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    public class PowerConnectionReceiver extends BroadcastReceiver {
         @Override
    -    public void onReceive(Context context, Intent intent) { 
    +    public void onReceive(Context context, Intent intent) {
             int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
             boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                                 status == BatteryManager.BATTERY_STATUS_FULL;
    -    
    +
             int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
             boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
             boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    @@ -87,7 +87,7 @@ boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    } -

    Определение текущего уровня заряда батареи

    +

    Определение текущего уровня заряда батареи

    В некоторых случаях целесообразно определять текущий уровень заряда батареи. Если он ниже определенного значения, частоту фоновых обновлений следует уменьшить.

    @@ -99,7 +99,7 @@ int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1); float batteryPct = level / (float)scale; -

    Отслеживание существенных изменений уровня заряда батареи

    +

    Отслеживание существенных изменений уровня заряда батареи

    Отслеживать состояние батареи непрерывно не следует,

    diff --git a/docs/html-intl/intl/ru/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html-intl/intl/ru/training/monitoring-device-state/connectivity-monitoring.jd index ca1a9423692f8faa90d067dd9afa485dbdd0b997..d37243193e9ec787311a88da394331d5ccbc2cb1 100644 --- a/docs/html-intl/intl/ru/training/monitoring-device-state/connectivity-monitoring.jd +++ b/docs/html-intl/intl/ru/training/monitoring-device-state/connectivity-monitoring.jd @@ -11,7 +11,7 @@ next.link=manifest-receivers.html @jd:body -
    +

    Содержание урока

    @@ -27,7 +27,7 @@ next.link=manifest-receivers.html
  • Намерения и фильтры намерений -
  • +

    Чаще всего повторяющиеся оповещения и фоновые службы используются для планового обновления приложения из Интернета, кэширования или загрузки больших объемов данных. Однако если подключение к Интернету не установлено или скорость соединения слишком низкая, выполнять загрузку не имеет смысла.

    @@ -35,18 +35,18 @@ next.link=manifest-receivers.html

    Проверить наличие подключения к Интернету и его тип можно с помощью {@link android.net.ConnectivityManager}.

    -

    Определение наличия подключения к Интернету

    - +

    Определение наличия подключения к Интернету

    +

    Если подключение отсутствует, нет смысла планировать обновление из Интернета. В приведенном ниже коде показано, как использовать {@link android.net.ConnectivityManager} для отправки запросов об активной сети и определять возможности подключения.

    ConnectivityManager cm =
             (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    - 
    +
     NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
     boolean isConnected = activeNetwork.isConnectedOrConnecting();
    -

    Определение типа подключения к Интернету

    +

    Определение типа подключения к Интернету

    Также можно определить тип доступного в настоящий момент подключения к Интернету.

    @@ -59,7 +59,7 @@ boolean isConnected = activeNetwork.isConnectedOrConnecting();

    Когда обновления отключены, необходимо отслеживать изменения доступных соединений, чтобы возобновить их сразу после подключения устройства к Интернету.

    -

    Отслеживание изменения возможностей подключения

    +

    Отслеживание изменения возможностей подключения

    {@link android.net.ConnectivityManager} передает действие {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} ({@code "android.net.conn.CONNECTIVITY_CHANGE"}) при каждом изменении сведений о подключении. Зарегистрируйте в манифесте приемник широковещательных намерений, чтобы отслеживать эти изменения и запускать (или приостанавливать) фоновые обновления соответствующим образом.

    diff --git a/docs/html-intl/intl/ru/training/monitoring-device-state/docking-monitoring.jd b/docs/html-intl/intl/ru/training/monitoring-device-state/docking-monitoring.jd index d94f3570458cc770735272ed505b3fa63b69415f..002f35155a22b85cfd2715001f975c15cfcd4da4 100644 --- a/docs/html-intl/intl/ru/training/monitoring-device-state/docking-monitoring.jd +++ b/docs/html-intl/intl/ru/training/monitoring-device-state/docking-monitoring.jd @@ -10,7 +10,7 @@ next.link=connectivity-monitoring.html @jd:body -
    +

    Содержание урока

    @@ -26,7 +26,7 @@ next.link=connectivity-monitoring.html
  • Намерения и фильтры намерений -
  • +

    Устройства под управлением ОС Android можно подключать к нескольким типам док-станций: настольным, которые делятся на цифровые и аналоговые, и автомобильным. В большинстве случаев устройства заряжаются при подключении к док-станции, поэтому состояние подключения к док-станции часто связано с состоянием зарядки.

    @@ -36,8 +36,8 @@ next.link=connectivity-monitoring.html

    Состояние подключения к док-станции также передается в виде закрепленного намерения {@link android.content.Intent}, что позволяет запрашивать сведения о наличии подключения к док-станции и ее типе.

    -

    Определение текущего состояния подключения к док-станции

    - +

    Определение текущего состояния подключения к док-станции

    +

    Сведения о состоянии подключения к док-станции передаются в качестве дополнительных данных в закрепленном оповещении действия {@link android.content.Intent#ACTION_DOCK_EVENT}. Поскольку это закрепленное намерение, регистрировать {@link android.content.BroadcastReceiver} не требуется. Достаточно вызвать {@link android.content.Context#registerReceiver registerReceiver()}, передав {@code null} в качестве приемника широковещательных намерений, как показано в коде ниже.

    IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
    @@ -49,9 +49,9 @@ Intent dockStatus = context.registerReceiver(null, ifilter);
    boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED; -

    Определение типа док-станции

    +

    Определение типа док-станции

    -

    Док-станция, к которой подключено устройство, может быть одного из четырех типов: +

    Док-станция, к которой подключено устройство, может быть одного из четырех типов:

    • автомобильная;
    • настольная;
    • настольная с минимальным набором функций (аналоговая);
    • @@ -60,12 +60,12 @@ boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;

      Обратите внимание, что последние два типа поддерживаются только на уровне API 11, поэтому, даже если вас не интересует, является ли док-станция цифровой или аналоговой, а интересует только ее тип, рекомендуется выполнять проверку по всем трем типам:

      boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
      -boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK || 
      +boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK ||
                        dockState == EXTRA_DOCK_STATE_LE_DESK ||
                        dockState == EXTRA_DOCK_STATE_HE_DESK;
      -

      Отслеживание изменений состояния подключения к док-станции и ее типа

      +

      Отслеживание изменений состояния подключения к док-станции и ее типа

      При каждом подключении устройства к док-станции или отключении от нее передается действие {@link android.content.Intent#ACTION_DOCK_EVENT}. Чтобы отслеживать состояние подключения к док-станции, достаточно зарегистрировать в манифесте приложения приемник широковещательных намерений, как показано ниже.

      diff --git a/docs/html-intl/intl/ru/training/monitoring-device-state/index.jd b/docs/html-intl/intl/ru/training/monitoring-device-state/index.jd index c87d9af5da4da28685faae4d7d166f4460d276cc..e26af09a9c2b6600546ecffe514a4916547c73f1 100644 --- a/docs/html-intl/intl/ru/training/monitoring-device-state/index.jd +++ b/docs/html-intl/intl/ru/training/monitoring-device-state/index.jd @@ -7,10 +7,10 @@ next.link=battery-monitoring.html @jd:body -
      +
      -

      Требования

      +

      Требования

      -
      +

      Качественное приложение должно оказывать минимальное влияние на время работы устройства от батареи. В этом уроке вы научитесь создавать приложения, способные изменять функционал и режим работы в зависимости от состояния устройства.

      Отключение обновления данных фоновых служб при потере подключения и снижение частоты обновления при низком заряде батареи позволяет снизить расход энергии и продлить работу устройства без подзарядки.

      -

      Уроки

      - +

      Уроки

      + - +will want to jump to a lesson or not.--> +
      Отслеживание уровня заряда батареи и состояния зарядки
      Вы узнаете, как изменять частоту обновления приложения, определяя и отслеживая текущий уровень заряда батареи и изменение состояния зарядки.
      @@ -46,4 +46,4 @@ will want to jump to a lesson or not.-->
      Операции с приемниками широковещательных намерений по запросу
      Приемники широковещательных намерений, объявленные в манифесте, можно включать и отключать во время работы приложения. Это позволяет отключать ненужные приемники в зависимости от состояния устройства. Вы узнаете, как повысить эффективность путем включения, отключения или каскадирования приемников изменения состояния и как отложить действие до момента перехода устройства в заданное состояние.
      -
      \ No newline at end of file + \ No newline at end of file diff --git a/docs/html-intl/intl/ru/training/monitoring-device-state/manifest-receivers.jd b/docs/html-intl/intl/ru/training/monitoring-device-state/manifest-receivers.jd index 724ee93e282231d5960116ee5cd2d491a7b5ba70..2bd0fb93658e73b4ecc8f771c7da0b2a7b005823 100644 --- a/docs/html-intl/intl/ru/training/monitoring-device-state/manifest-receivers.jd +++ b/docs/html-intl/intl/ru/training/monitoring-device-state/manifest-receivers.jd @@ -9,7 +9,7 @@ previous.link=connectivity-monitoring.html @jd:body -
      +

      Содержание урока

      @@ -23,7 +23,7 @@ previous.link=connectivity-monitoring.html
    • Намерения и фильтры намерений
    -
    +

    Самый простой способ отслеживать изменения состояния устройства – создать приемники {@link android.content.BroadcastReceiver} для каждого отслеживаемого состояния и зарегистрировать их в манифесте приложения. Затем в каждом из этих приемников можно переопределять график повторяющихся оповещений в зависимости от текущего состояния устройства.

    @@ -31,10 +31,10 @@ previous.link=connectivity-monitoring.html

    Этот способ имеет недостатки: приложение активирует устройство при каждом запуске любого из этих приемников, что далеко не всегда оправданно.

    Оптимальный вариант – включать и выключать приемники широковещательных намерений во время работы приложения. Это позволяет использовать приемники, объявленные в манифесте, как пассивные оповещения, которые инициируются системными событиями только в случае необходимости.

    - -

    Включение, отключение и каскадирование приемников изменения состояния для повышения эффективности

    - + +

    Включение, отключение и каскадирование приемников изменения состояния для повышения эффективности

    +

    {@link android.content.pm.PackageManager} позволяет включать и выключать любые компоненты, определенные в манифесте, в том числе все приемники широковещательных намерений:

    ComponentName receiver = new ComponentName(context, myReceiver.class);
    diff --git a/docs/html-intl/intl/ru/training/multiscreen/adaptui.jd b/docs/html-intl/intl/ru/training/multiscreen/adaptui.jd
    index 490a64ad2de6abf81692ac542336b4b72379903f..ee1dd9dcd16722b3b446f9140d49fb53fa2c000c 100644
    --- a/docs/html-intl/intl/ru/training/multiscreen/adaptui.jd
    +++ b/docs/html-intl/intl/ru/training/multiscreen/adaptui.jd
    @@ -10,9 +10,9 @@ previous.link=screendensities.html
     
     
     
    -
    -
    - +
    +
    +

    Содержание урока

      @@ -27,17 +27,17 @@ previous.link=screendensities.html - +

      Упражнение

      - + - - -
    -
    +

    NewsReader.zip

    +
    + + +
    +

    Алгоритм пользовательского интерфейса зависит от макета, который в данный момент отображается. Например, если приложение работает в двухпанельном режиме, то при нажатии на элемент в левой панели содержание отобразится в правой. В однопанельном режиме содержание откроется отдельно (в другой активности).

    @@ -56,7 +56,7 @@ public class NewsReaderActivity extends FragmentActivity { setContentView(R.layout.main_layout); View articleView = findViewById(R.id.article); - mIsDualPane = articleView != null && + mIsDualPane = articleView != null && articleView.getVisibility() == View.VISIBLE; } } @@ -116,7 +116,7 @@ public void onCreate(Bundle savedInstanceState) { else { /* use list navigation (spinner) */ actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST); - SpinnerAdapter adap = new ArrayAdapter(this, + SpinnerAdapter adap = new ArrayAdapter(this, R.layout.headline_item, CATEGORIES); actionBar.setListNavigationCallbacks(adap, handler); } @@ -168,7 +168,7 @@ public class HeadlinesFragment extends ListFragment { public class HeadlinesFragment extends ListFragment { ... @Override - public void onItemClick(AdapterView<?> parent, + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (null != mHeadlineSelectedListener) { mHeadlineSelectedListener.onHeadlineSelected(position); diff --git a/docs/html-intl/intl/ru/training/multiscreen/index.jd b/docs/html-intl/intl/ru/training/multiscreen/index.jd index 84b9b8b5bdf06b5b24f8f4ff0cce0ed0de3b340e..66cf968edf9b98b0b07cbcac9a6a3d3a70f36ba4 100644 --- a/docs/html-intl/intl/ru/training/multiscreen/index.jd +++ b/docs/html-intl/intl/ru/training/multiscreen/index.jd @@ -7,10 +7,10 @@ next.link=screensizes.html @jd:body -
    -
    - -

    Требования

    +
    +
    + +

    Требования

    - +

    NewsReader.zip

    +
    + +
    +
    +

    На платформе Android работают устройства с самыми разными размерами экрана: от телефонов до телевизоров. Чтобы с вашим приложением могли работать как можно больше пользователей, оно должно корректно отображаться на всех этих устройствах.

    Однако совместимость с разными типами устройств – это еще не все. От размера экрана зависит, какие возможности будет иметь пользователь при работе с приложением. Чтобы пользователи действительно остались довольны вашим приложением, оно должно не просто поддерживать разные экраны, но и быть оптимизировано для каждого из них.

    @@ -48,17 +48,17 @@ href="{@docRoot}tools/support-library/index.html">вспомогательной

    Примечание. В этом модуле и в учебном приложении используется вспомогательная библиотека, позволяющая работать с API {@link android.app.Fragment} в версиях до Android 3.0. Чтобы иметь возможность использовать все необходимые API, загрузите библиотеку и добавьте ее в свое приложение.

    - - -

    Уроки

    - -
    -
    Поддержка разных размеров экрана
    -
    В этом уроке рассказывается, как создать макет, который адаптируется к разным размерам экрана, используя масштабируемые представления, объекты {@link android.widget.RelativeLayout}, квалификаторы размера и ориентации, фильтры псевдонимов и растровые изображений формата nine-patch.
    - -
    Поддержка разных разрешений экрана
    -
    В этом уроке рассказывается, как работать с экранами разного разрешения с помощью не зависящих от разрешения пикселей и как подготовить растровые изображения для каждого из них.
    - -
    Реализация адаптируемых алгоритмов работы пользовательского интерфейса
    -
    В этом уроке рассказывается, как реализовать алгоритм работы интерфейса, адаптирующийся к размеру и разрешению экрана, то есть способный определять активный макет во время выполнения приложения, выбирать дальнейшие действия на основе текущего макета и обрабатывать изменения конфигурации экрана.
    -
    + + +

    Уроки

    + +
    +
    Поддержка разных размеров экрана
    +
    В этом уроке рассказывается, как создать макет, который адаптируется к разным размерам экрана, используя масштабируемые представления, объекты {@link android.widget.RelativeLayout}, квалификаторы размера и ориентации, фильтры псевдонимов и растровые изображений формата nine-patch.
    + +
    Поддержка разных разрешений экрана
    +
    В этом уроке рассказывается, как работать с экранами разного разрешения с помощью не зависящих от разрешения пикселей и как подготовить растровые изображения для каждого из них.
    + +
    Реализация адаптируемых алгоритмов работы пользовательского интерфейса
    +
    В этом уроке рассказывается, как реализовать алгоритм работы интерфейса, адаптирующийся к размеру и разрешению экрана, то есть способный определять активный макет во время выполнения приложения, выбирать дальнейшие действия на основе текущего макета и обрабатывать изменения конфигурации экрана.
    +
    diff --git a/docs/html-intl/intl/ru/training/multiscreen/screendensities.jd b/docs/html-intl/intl/ru/training/multiscreen/screendensities.jd index cfd47246282404ab886065d8999ec3f5c39c9475..ffcdbbca23274e4bc7520311354a78b8d5bced3d 100644 --- a/docs/html-intl/intl/ru/training/multiscreen/screendensities.jd +++ b/docs/html-intl/intl/ru/training/multiscreen/screendensities.jd @@ -12,8 +12,8 @@ next.link=adaptui.html -
    -
    +
    +

    Содержание урока

      @@ -29,15 +29,15 @@ next.link=adaptui.html

      Упражнение

      - - -
    +

    NewsReader.zip

    +
    + + +
    +

    В этом уроке рассказывается, как создать интерфейс, поддерживающий разные разрешения экрана, за счет использования разных ресурсов и не зависящих от разрешения единиц измерения.

    @@ -48,8 +48,8 @@ next.link=adaptui.html

    Например, если вы задаете расстояние между двумя представлениями, рекомендуется использовать dp, а не px:

    -<Button android:layout_width="wrap_content" 
    -    android:layout_height="wrap_content" 
    +<Button android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
         android:text="@string/clickme"
         android:layout_marginTop="20dp" />
     
    @@ -57,8 +57,8 @@ next.link=adaptui.html

    Для определения размера шрифта всегда используйте sp:

    -<TextView android:layout_width="match_parent" 
    -    android:layout_height="wrap_content" 
    +<TextView android:layout_width="match_parent"
    +    android:layout_height="wrap_content"
         android:textSize="20sp" />
     
    diff --git a/docs/html-intl/intl/ru/training/multiscreen/screensizes.jd b/docs/html-intl/intl/ru/training/multiscreen/screensizes.jd index 9684d77486dde06138f211ba56773608ee5597df..57496d9b18bf1807c5e38d09775ede897c5de02e 100644 --- a/docs/html-intl/intl/ru/training/multiscreen/screensizes.jd +++ b/docs/html-intl/intl/ru/training/multiscreen/screensizes.jd @@ -10,8 +10,8 @@ next.link=screendensities.html -
    -
    +
    +

    Содержание урока

      @@ -30,26 +30,26 @@ next.link=screendensities.html
    1. Поддержка нескольких экранов
    2. -

      Упражнение

      - -
      +

      Упражнение

      + + - -
      -
    +

    NewsReader.zip

    +
    + +
    +

    В этом уроке описаны следующие аспекты обеспечения совместимости интерфейса с разными экранами:

    -
      -
    • обеспечение способности макета адаптироваться к размеру экрана;
    • -
    • выбор макета интерфейса, отвечающего конфигурации экрана;
    • +
        +
      • обеспечение способности макета адаптироваться к размеру экрана;
      • +
      • выбор макета интерфейса, отвечающего конфигурации экрана;
      • контроль правильности применяемого макета;
      • -
      • использование масштабируемых растровых изображений.
      • -
      +
    • использование масштабируемых растровых изображений.
    • +
    -

    Использование параметров wrap_content и match_parent

    +

    Использование параметров wrap_content и match_parent

    Чтобы создать масштабируемый макет, способный адаптироваться к разным экранам, используйте в качестве значений ширины и высоты отдельных компонентов представления параметры "wrap_content" и "match_parent". Если используется "wrap_content", для ширины или высоты представления устанавливается минимальное значение, позволяющее уместить содержание на экран, а параметр "match_parent" (известный как "fill_parent" в API до 8 уровня) служит для растягивания компонента по размеру родительского представления.

    @@ -65,7 +65,7 @@ next.link=screendensities.html

    Рисунок 1. Приложение News Reader при вертикальной (слева) и горизонтальной (справа) ориентации.

    -

    Использование объекта RelativeLayout

    +

    Использование объекта RelativeLayout

    С помощью вложенных экземпляров объекта {@link android.widget.LinearLayout} и параметров "wrap_content" и "match_parent" можно создавать достаточно сложные макеты. Однако {@link android.widget.LinearLayout} не дает возможности точно управлять взаимным расположением дочерних представлений: в {@link android.widget.LinearLayout} они просто помещаются в ряд друг за другом. Если необходимо расположить дочерние представления иным образом, используйте объект {@link android.widget.RelativeLayout}, позволяющий задать относительные позиции компонентов. Например, одно дочернее представление можно выровнять по левому краю экрана, а другое – по правому.

    @@ -115,8 +115,8 @@ next.link=screendensities.html

    Обратите внимание: несмотря на изменение размера компонентов их взаимное расположение остается прежним, так как оно задано объектом {@link android.widget.RelativeLayout.LayoutParams}.

    - -

    Использование квалификаторов размера

    + +

    Использование квалификаторов размера

    Масштабируемые или относительные макеты, один из которых продемонстрирован выше, имеют свои ограничения. Хотя они позволяют создать интерфейс, способный адаптироваться к разным экранам за счет растягивания пространства внутри и вокруг компонентов, пользователю может оказаться не слишком удобно работать с таким интерфейсом. Поэтому в приложении должен использоваться не один масштабируемый макет, а несколько альтернативных вариантов для разных конфигураций экрана. Их можно создать с помощью квалификаторов конфигураций, которые позволяют оперативно выбирать ресурсы, отвечающие текущим параметрам экрана (например, разные варианты макетов для экранов разных размеров).

    @@ -158,7 +158,7 @@ next.link=screendensities.html

    Следует учесть, что на Android-устройствах до версии 3.2 квалификатор sw600dp не будет работать, поэтому для них по-прежнему нужно использовать large. Таким образом, вам потребуется еще один файл с названием res/layout-large/main.xml, идентичный файлу res/layout-sw600dp/main.xml. В следующем разделе вы познакомитесь с методом, который позволяет избежать дублирования таких файлов макета.

    -

    Использование псевдонимов макетов

    +

    Использование псевдонимов макетов

    Квалификатор Smallest-width работает только на устройствах Android 3.2 или более поздних версий. Для совместимости с более ранними устройствами по-прежнему следует использовать абстрактные размеры (small, normal, large и xlarge). Например, чтобы интерфейс открывался в однопанельном режиме на телефонах и в многопанельном на планшетных ПК с 7-дюймовым экраном, телевизорах и других крупных устройствах, подготовьте следующие файлы:

    @@ -202,7 +202,7 @@ next.link=screendensities.html {@code large}, а для более новых – sw600dp).

    -

    Использование квалификаторов ориентации

    +

    Использование квалификаторов ориентации

    Хотя некоторые макеты одинаково хорошо смотрятся в вертикальной и горизонтальной ориентациях, в большинстве случаев интерфейс все же приходится адаптировать. Ниже показано, как изменяется макет в приложении News Reader в зависимости от размера и ориентации экрана.

    diff --git a/docs/html-intl/intl/ru/preview/features/picture-in-picture.jd b/docs/html-intl/intl/ru/training/tv/playback/picture-in-picture.jd similarity index 98% rename from docs/html-intl/intl/ru/preview/features/picture-in-picture.jd rename to docs/html-intl/intl/ru/training/tv/playback/picture-in-picture.jd index 5be0bffc505d9f475d76f5405db13981e30504b7..fc26368bb1260f8b814fec4cc01186aaa21c172d 100644 --- a/docs/html-intl/intl/ru/preview/features/picture-in-picture.jd +++ b/docs/html-intl/intl/ru/training/tv/playback/picture-in-picture.jd @@ -4,8 +4,8 @@ page.tags=androidn @jd:body -
    -
    +
    +

    Содержание документа

      @@ -57,7 +57,7 @@ PIP долгим нажатием кнопки Home на пульте д видео, окно PIP автоматически закроется. Пользователи также могут закрыть окно PIP, используя экран последних задач.

      - +

      Рисунок 1. Видео в режиме "картинка в картинке" отображается в углу экрана, пока пользователь просматривает контент на главном экране.

      @@ -114,7 +114,7 @@ public void onActionClicked(Action action) {

      Добавление кнопки PIP на панель управления мультимедиа позволяет пользователям легко переключаться в режим PIP с сохранением возможностей управления воспроизведением видео.

      - +

      Рисунок 1. Кнопка режима "картинка в картинке" на панели управления мультимедиа.

      diff --git a/docs/html-intl/intl/ru/preview/features/tv-recording-api.jd b/docs/html-intl/intl/ru/training/tv/tif/content-recording.jd similarity index 99% rename from docs/html-intl/intl/ru/preview/features/tv-recording-api.jd rename to docs/html-intl/intl/ru/training/tv/tif/content-recording.jd index 5e6ce45b99ecc2c7a3fb126bf1f4b9bafecedaf6..19d6db37eb022de6367de3485c75bcfa1660e078 100644 --- a/docs/html-intl/intl/ru/preview/features/tv-recording-api.jd +++ b/docs/html-intl/intl/ru/training/tv/tif/content-recording.jd @@ -5,8 +5,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
      -
      +
      +

      Содержание документа

      1. Указание на поддержку записи
      2. diff --git a/docs/html-intl/intl/vi/preview/behavior-changes.jd b/docs/html-intl/intl/vi/about/versions/nougat/android-7.0-changes.jd similarity index 98% rename from docs/html-intl/intl/vi/preview/behavior-changes.jd rename to docs/html-intl/intl/vi/about/versions/nougat/android-7.0-changes.jd index 2c287504190cb5e32b447e6ea20cffd248184189..58834a5d254490f62436dd8b178ac5fa012c2b7f 100644 --- a/docs/html-intl/intl/vi/preview/behavior-changes.jd +++ b/docs/html-intl/intl/vi/about/versions/nougat/android-7.0-changes.jd @@ -6,8 +6,8 @@ page.image=images/cards/card-n-changes_2x.png @jd:body -
        -
        +
        +

        Trong tài liệu này

        @@ -67,14 +67,14 @@ page.image=images/cards/card-n-changes_2x.png

        Được đưa vào Android 6.0 (Mức API 23), Chế độ Ngủ sâu cải thiện thời lượng pin bằng cách trì hoãn các hoạt động của CPU và mạng khi người dùng không cắm sạc, - không di chuyển và tắt màn hình thiết bị. Android N + không di chuyển và tắt màn hình thiết bị. Android N thêm các cải tiến cho Chế độ Ngủ sâu bằng cách sử dụng một tập con các hạn chế của CPU và mạng khi thiết bị không được cắm sạc với màn hình bị tắt, nhưng không nhất thiết phải để một chỗ, ví dụ như một thiết bị cầm tay di chuyển trong túi của người dùng.

        - +

        Hình 1. Minh họa cách thức Chế độ Ngủ sâu áp dụng ở cấp đầu tiên của các hạn chế hoạt động hệ thống nhằm cải thiện thời lượng pin. @@ -93,7 +93,7 @@ page.image=images/cards/card-n-changes_2x.png

        - +

        Hình 2. Minh họa cách Chế độ Ngủ sâu áp dụng cấp thứ hai của các hạn chế hoạt động hệ thống sau khi thiết bị được đặt một chỗ trong một khoảng thời gian nhất định. @@ -229,10 +229,10 @@ page.image=images/cards/card-n-changes_2x.png

        - +
        - +
        @@ -250,7 +250,7 @@ page.image=images/cards/card-n-changes_2x.png
        • Nếu một ứng dụng nhắm mục tiêu mức API 23 hoặc thấp hơn thì hệ thống sẽ tự động tắt tất cả các tiến trình chạy ngầm của ứng dụng đó. Điều này có nghĩa là nếu một người dùng rời khỏi - ứng dụng đó để mở màn hình Settings và thay đổi + ứng dụng đó để mở màn hình Settings và thay đổi Display size thì hệ thống sẽ tắt ứng dụng giống như trong trường hợp thiết bị thiếu bộ nhớ. Nếu ứng dụng đó có bất kỳ tiến trình nào chạy ở tiền cảnh thì hệ thống sẽ thông báo cho các tiến trình đó về thay đổi cấu hình như @@ -418,7 +418,7 @@ JavaVM::AttachCurrentThread from <jni.h>.
        • Giờ đây các hạn chế đặt lại mật khẩu cho người quản lý thiết bị sẽ áp dụng với người sở hữu cấu hình. Người quản lý thiết bị không thể sử dụng - DevicePolicyManager.resetPassword() được nữa để xóa mật khẩu hoặc thay đổi + DevicePolicyManager.resetPassword() được nữa để xóa mật khẩu hoặc thay đổi các mật khẩu đã đặt. Người quản lý thiết bị vẫn có thể đặt một mật khẩu nhưng chỉ khi thiết bị không có mật khẩu, mã PIN hoặc mẫu hình.
        • diff --git a/docs/html-intl/intl/vi/preview/samples.jd b/docs/html-intl/intl/vi/about/versions/nougat/android-7.0-samples.jd similarity index 78% rename from docs/html-intl/intl/vi/preview/samples.jd rename to docs/html-intl/intl/vi/about/versions/nougat/android-7.0-samples.jd index aa1a8c65d229477446a8fd5154038c8535d723bf..448c39d96868fff72454049aee1b20240bbcc8f2 100644 --- a/docs/html-intl/intl/vi/preview/samples.jd +++ b/docs/html-intl/intl/vi/about/versions/nougat/android-7.0-samples.jd @@ -16,7 +16,7 @@ page.image=images/cards/card-n-samples_2x.png

          Dùng thử đa cửa sổ

          - +

          Ví dụ này minh họa cách tận dụng giao diện người dùng đa cửa sổ với ứng dụng của bạn. @@ -28,7 +28,7 @@ page.image=images/cards/card-n-samples_2x.png

          Thông báo đang Hoạt động

          - +

          Đây là ví dụ đã có sẵn, minh họa một dịch vụ đơn giản để gửi thông báo bằng cách sử dụng NotificationCompat. Mỗi cuộc hội thoại chưa đọc từ một người dùng @@ -45,7 +45,7 @@ page.image=images/cards/card-n-samples_2x.png

          Dịch vụ Nhắn tin

          - +

          Đây là một ví dụ đã có sẵn, minh họa cách sử dụng NotificationManager để cho biết có bao nhiêu thông báo một ứng dụng hiện @@ -62,7 +62,7 @@ page.image=images/cards/card-n-samples_2x.png

          Khởi động Trực tiếp

          - +

          Ví dụ này minh họa cách lưu trữ và truy cập dữ liệu trên bộ lưu trữ mã hóa thiết bị, luôn khả dụng khi thiết bị được khởi động. @@ -74,7 +74,7 @@ page.image=images/cards/card-n-samples_2x.png

          Truy cập Thư mục theo Phạm vi

          - +

          Ví dụ này minh họa cách đọc và ghi dữ liệu từ các thư mục cụ thể trong khi cần ít quyền hơn. @@ -82,4 +82,4 @@ page.image=images/cards/card-n-samples_2x.png

          Tải mã trên GitHub -

          \ No newline at end of file +

          diff --git a/docs/html-intl/intl/vi/preview/api-overview.jd b/docs/html-intl/intl/vi/about/versions/nougat/android-7.0.jd similarity index 98% rename from docs/html-intl/intl/vi/preview/api-overview.jd rename to docs/html-intl/intl/vi/about/versions/nougat/android-7.0.jd index 0e2c35e0e2286578883d37fed2f848c60fd14706..b218a4e5bf9dde7fd028a59a7516af91c67e3eeb 100644 --- a/docs/html-intl/intl/vi/preview/api-overview.jd +++ b/docs/html-intl/intl/vi/about/versions/nougat/android-7.0.jd @@ -7,8 +7,8 @@ page.image=images/cards/card-n-apis_2x.png -
          -
          +
          +

          Các tính năng chính cho nhà phát triển

              @@ -70,7 +70,7 @@ tương tác với ứng dụng khác. Hãy xem bên dưới để biết thêm
            - +

            Hình 1. Các ứng dụng chạy trong chế độ chia màn hình.

            @@ -126,15 +126,15 @@ hơn. Một số các thay đổi bao gồm:

        - +
        - +
        - +
        @@ -261,7 +261,7 @@ các tiến trình chạy ngầm của nhiều ứng dụng cùng lúc và sử

        Tiết kiệm dữ liệu

        - +

        Hình 4. Tính năng Tiết kiệm dữ liệu trong mục Settings. @@ -296,7 +296,7 @@ Dữ liệu hay chưa và cố gắng giới hạn sử dụng dữ liệu chạ

        - +

        Hình 5. Các ô Cài đặt nhanh trong vùng hiển thị thông báo. @@ -336,7 +336,7 @@ của chúng — người dùng chỉ cần kéo và thả để thêm hoặ

        Chặn số

        Android N đã hỗ trợ chặn số điện thoại trong nền tảng này và cung cấp một - API khuôn khổ cho phép các nhà cung cấp dịch vụ duy trì một danh sách số bị chặn. + API khuôn khổ cho phép các nhà cung cấp dịch vụ duy trì một danh sách số bị chặn. Ứng dụng SMS mặc định, ứng dụng gọi điện mặc định và các ứng dụng của nhà cung cấp có thể đọc và ghi vào danh sách số bị chặn. Các ứng dụng khác không thể truy cập vào danh sách này.

        diff --git a/docs/html-intl/intl/vi/about/versions/nougat/index.jd b/docs/html-intl/intl/vi/about/versions/nougat/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..2d57fa6a6f70021bfb9d3cd19c175fa81faf091f --- /dev/null +++ b/docs/html-intl/intl/vi/about/versions/nougat/index.jd @@ -0,0 +1,110 @@ +page.title=Android 7.0 Nougat +page.tags="androidn","versions" +meta.tags="android n", "nougat", "android 7.0" +fullpage=true +forcelocalnav=true +header.hide=1 +footer.hide=1 +@jd:body + +
        + +
        + + + + +
        +

        Latest

        +
        +
        + +
        +

        Videos

        +
        + New Android capabilities and the right way to use them in your apps. +
        + +
        +
        +
        + +
        +

        Tài nguyên

        +
        + Các thông tin cần thiết để trợ giúp bạn chuẩn bị cho ứng dụng sẵn sàng chạy trên Android Nougat. +
        + +
        +
        +
        \ No newline at end of file diff --git a/docs/html-intl/intl/vi/design/patterns/navigation.jd b/docs/html-intl/intl/vi/design/patterns/navigation.jd index 98490db0e5b635d4344795a487e3545c41814df4..a3d6003dd4169835a6aa7b793413b9c287c1f8f0 100644 --- a/docs/html-intl/intl/vi/design/patterns/navigation.jd +++ b/docs/html-intl/intl/vi/design/patterns/navigation.jd @@ -168,7 +168,7 @@ cần chụp ảnh có thể kích hoạt ứng dụng Camera, ứng dụng này thông tin và tất cả hành động liên kết mà người dùng có thể thực hiện. Ứng dụng của bạn là tập hợp của nhiều hoạt động, bao gồm cả hoạt động do bạn tạo và hoạt động mà bạn sử dụng lại từ các ứng dụng khác.

        -

        Tác vụ là trình tự các hoạt động mà một người dùng tuân theo để hoàn thành một mục tiêu. +

        Tác vụ là trình tự các hoạt động mà một người dùng tuân theo để hoàn thành một mục tiêu. Tác vụ đơn có thể sử dụng các hoạt động từ chỉ một ứng dụng, hoặc có thể dựa trên hoạt động từ nhiều ứng dụng khác nhau.

        diff --git a/docs/html-intl/intl/vi/guide/components/activities.jd b/docs/html-intl/intl/vi/guide/components/activities.jd index 83e7669a7f7676028c73e69744a67ca905a7e419..304b73c879952e0e9a0bb7db153af8ea0483bfc7 100644 --- a/docs/html-intl/intl/vi/guide/components/activities.jd +++ b/docs/html-intl/intl/vi/guide/components/activities.jd @@ -57,7 +57,7 @@ hoạt động có thể bắt đầu một hoạt động khác để thực hi mới bắt đầu, hoạt động trước đó sẽ bị dừng lại, nhưng hệ thống vẫn giữ nguyên hoạt động trong một ngăn xếp ("back stack"). Khi một hoạt động mới bắt đầu, nó được đẩy lên ngăn xếp và chiếm lấy tiêu điểm của người dùng. Ngăn xếp sẽ tuân theo cơ chế xếp chồng cơ bản "vào cuối, ra đầu", -vì thế, khi người dùng kết thúc hoạt động hiện tại và nhấn nút Quay lại, nó +vì thế, khi người dùng kết thúc hoạt động hiện tại và nhấn nút Quay lại, nó sẽ được đẩy ra khỏi ngăn xếp (và bị hủy) và hoạt động trước đó sẽ tiếp tục. (Ngăn xếp được đề cập kỹ hơn trong tài liệu Tác vụ và Ngăn Xếp.)

        @@ -139,7 +139,7 @@ setContentView()}.

        Khai báo hoạt động trong bản kê khai

        Bạn phải khai báo hoạt động của mình trong tệp bản kê khai để hoạt động -có thể truy cập được vào hệ thống. Để khai báo hoạt động của mình, hãy mở tệp bản kê khai của bạn và thêm một phần tử {@code <activity>} +có thể truy cập được vào hệ thống. Để khai báo hoạt động của mình, hãy mở tệp bản kê khai của bạn và thêm một phần tử {@code <activity>} làm con của phần tử {@code <application>} . Ví dụ:

        @@ -161,7 +161,7 @@ bạn phát hành ứng dụng của mình, bạn không nên thay đổi tên n một số tính năng, chẳng hạn như các lối tắt của ứng dụng (hãy đọc bài đăng trên blog, Những Điều Không Thay Đổi Được).

        -

        Xem tài liệu tham khảo phần tử {@code <activity>} +

        Xem tài liệu tham khảo phần tử {@code <activity>} để biết thêm thông tin về việc khai báo hoạt động của bạn trong bản kê khai.

        @@ -200,7 +200,7 @@ tự mình bắt đầu chúng bằng cách sử dụng các ý định rõ ràn

        Tuy nhiên, nếu bạn muốn hoạt động của mình phản hồi lại những ý định ngầm mà được chuyển giao từ các ứng dụng khác (và chính bạn), thì bạn phải định nghĩa các bộ lọc ý định bổ sung cho hoạt động của mình. Với mỗi loại ý định mà bạn muốn phản hồi, bạn phải nêu một {@code -<intent-filter>} bao gồm một phần tử +<intent-filter>} bao gồm một phần tử {@code <action>} và, không bắt buộc, một phần tử {@code <category>} và/hoặc một phần tử {@code @@ -324,7 +324,7 @@ finish()} của nó. Bạn cũng có thể tắt một hoạt động riêng mà bằng cách sử dụng những phương pháp này. Như đề cập trong phần sau về vòng đời của hoạt động, hệ thống Android quản lý tuổi thọ của một hoạt động cho bạn, vì vậy bạn không cần kết thúc các hoạt động của chính mình. Việc gọi những phương pháp này có thể ảnh hưởng tiêu cực tới trải nghiệm người dùng -kỳ vọng và chỉ nên được sử dụng khi bạn tuyệt đối không muốn người dùng quay lại thực thể này của +kỳ vọng và chỉ nên được sử dụng khi bạn tuyệt đối không muốn người dùng quay lại thực thể này của hoạt động.

        @@ -350,7 +350,7 @@ che toàn bộ màn hình. Trạng thái tạm dừng hoàn toàn đang hoạt trình quản lý cửa sổ), nhưng có thể bị hệ thống tắt bỏ trong trường hợp bộ nhớ cực kỳ thấp.
        Dừng
        -
        Hoạt động bị che khuất hoàn toàn bởi một hoạt động khác (hoạt động hiện đang +
        Hoạt động bị che khuất hoàn toàn bởi một hoạt động khác (hoạt động hiện đang “dưới nền"). Hoạt động dừng cũng vẫn đang hoạt động ({@link android.app.Activity} đối tượng được giữ lại trong bộ nhớ, nó duy trì tất cả thông tin về trạng thái và thành viên, nhưng không gắn với trình quản lý cửa sổ). Tuy nhiên, hoạt động không còn hiển thị với người dùng nữa và hệ thống @@ -608,7 +608,7 @@ android.app.Activity#onSaveInstanceState onSaveInstanceState()}.

        Hệ thống gọi {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()} trước khi khiến hoạt động dễ bị hủy. Hệ thống chuyển cho phương pháp này -một {@link android.os.Bundle} trong đó bạn có thể lưu +một {@link android.os.Bundle} trong đó bạn có thể lưu thông tin trạng thái về hoạt động như cặp tên giá trị, bằng cách sử dụng các phương pháp như {@link android.os.Bundle#putString putString()} và {@link android.os.Bundle#putInt putInt()}. Sau đó, nếu hệ thống tắt bỏ tiến trình ứng dụng của bạn diff --git a/docs/html-intl/intl/vi/guide/components/bound-services.jd b/docs/html-intl/intl/vi/guide/components/bound-services.jd index 7a2ddbaf6321e02d0d9db6d39674685f581f80ac..9d19e05513eea2232bc4beec89632e11931ece32 100644 --- a/docs/html-intl/intl/vi/guide/components/bound-services.jd +++ b/docs/html-intl/intl/vi/guide/components/bound-services.jd @@ -357,7 +357,7 @@ handleMessage()}.

        Theo cách này, không có "phương pháp" nào để máy khách gọi đối với dịch vụ. Thay vào đó, máy khách -gửi “thông báo” (đối tượng {@link android.os.Message}) mà dịch vụ nhận được trong +gửi “thông báo” (đối tượng {@link android.os.Message}) mà dịch vụ nhận được trong {@link android.os.Handler} của mình.

        Sau đây là một dịch vụ ví dụ đơn giản sử dụng một giao diện {@link android.os.Messenger}:

        @@ -539,7 +539,7 @@ kỹ hơn ở bên dưới.)

      Ví dụ, đoạn mã HTML sau sẽ kết nối máy khách với dịch vụ được tạo bên trên bằng cách -mở rộng lớp Trình gắn kết, vì vậy tất cả những việc mà nó phải làm là đổi kiểu +mở rộng lớp Trình gắn kết, vì vậy tất cả những việc mà nó phải làm là đổi kiểu {@link android.os.IBinder} được trả về thành lớp {@code LocalService} và yêu cầu thực thể {@code LocalService}:

      diff --git a/docs/html-intl/intl/vi/guide/components/fragments.jd b/docs/html-intl/intl/vi/guide/components/fragments.jd index 95d9c76337fc86b75f7dfda9a5e8d3ba749d37d5..7b6346c4d6fdaf2f4704c7d5e4121d2a2037b02f 100644 --- a/docs/html-intl/intl/vi/guide/components/fragments.jd +++ b/docs/html-intl/intl/vi/guide/components/fragments.jd @@ -36,7 +36,7 @@ parent.link=activities.html
    1. {@link android.app.FragmentManager}
    2. {@link android.app.FragmentTransaction}
    - +

    Xem thêm

    1. Xây dựng một UI Động bằng các Phân đoạn
    2. @@ -148,7 +148,7 @@ của bạn.

      khởi tạo các thành phần thiết yếu của phân đoạn mà bạn muốn giữ lại khi phân đoạn bị tạm dừng hoặc dừng hẳn, sau đó tiếp tục.
      {@link android.app.Fragment#onCreateView onCreateView()}
      -
      Hệ thống sẽ gọi phương pháp này khi đến lúc phân đoạn vẽ giao diện người dùng của nó +
      Hệ thống sẽ gọi phương pháp này khi đến lúc phân đoạn vẽ giao diện người dùng của nó lần đầu tiên. Để vẽ một UI cho phân đoạn của mình, bạn phải trả về một {@link android.view.View} từ phương pháp này, đây là gốc của bố trí phân đoạn của bạn. Bạn có thể trả về giá trị rỗng nếu phân đoạn không cung cấp UI.
      @@ -303,7 +303,7 @@ phân đoạn:

      • Cung cấp thuộc tính {@code android:id} với một ID duy nhất.
      • Cung cấp thuộc tính {@code android:tag} với một xâu duy nhất.
      • -
      • Nếu bạn không cung cấp được thuộc tính nào, hệ thống sẽ sử dụng ID của dạng xem +
      • Nếu bạn không cung cấp được thuộc tính nào, hệ thống sẽ sử dụng ID của dạng xem của bộ chứa.
    @@ -362,7 +362,7 @@ findFragmentByTag()}.

    Để biết ví dụ về hoạt động sử dụng phân đoạn như một trình thực hiện nền, không có UI, hãy xem mẫu {@code FragmentRetainInstance.java}, mẫu này có trong các mẫu SDK (có sẵn thông qua -Trình quản lý SDK Android) và nằm trên hệ thống của bạn như là +Trình quản lý SDK Android) và nằm trên hệ thống của bạn như là <sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java.

    @@ -378,7 +378,7 @@ có nó, hãy gọi {@link android.app.Activity#getFragmentManager()} từ hoạ
  • Nhận các phân đoạn tồn tại trong hoạt động, bằng {@link android.app.FragmentManager#findFragmentById findFragmentById()} (đối với các phân đoạn cung cấp UI trong bố trí hoạt động) hoặc {@link android.app.FragmentManager#findFragmentByTag -findFragmentByTag()} (đối với các phân đoạn có hoặc không cung cấp UI).
  • +findFragmentByTag()} (đối với các phân đoạn có hoặc không cung cấp UI).
  • Lấy phân đoạn ra khỏi ngăn xếp, bằng {@link android.app.FragmentManager#popBackStack()} (mô phỏng một câu lệnh Quay lại của người dùng).
  • Đăng ký một đối tượng theo dõi cho những thay đổi đối với ngăn xếp, bằng {@link @@ -562,9 +562,9 @@ public static class FragmentA extends ListFragment { }
  • -

    Nếu hoạt động chưa triển khai giao diện, khi đó phân đoạn sẽ đưa ra lỗi +

    Nếu hoạt động chưa triển khai giao diện, khi đó phân đoạn sẽ đưa ra lỗi {@link java.lang.ClassCastException}. -Nếu thành công, thành viên {@code mListener} giữ một tham chiếu tới triển khai +Nếu thành công, thành viên {@code mListener} giữ một tham chiếu tới triển khai {@code OnArticleSelectedListener}của hoạt động, sao cho phân đoạn A có thể chia sẻ sự kiện với hoạt động bằng cách gọi các phương pháp được định nghĩa bởi giao diện {@code OnArticleSelectedListener}. Ví dụ, nếu phân đoạn A là một phần mở rộng của {@link android.app.ListFragment}, mỗi lần @@ -785,7 +785,7 @@ android.widget.FrameLayout}), hoặc bắt đầu một hoạt động mới (t

    Phân đoạn thứ hai, {@code DetailsFragment} sẽ hiển thị tóm tắt vở kịch cho mục được chọn từ danh sách trong {@code TitlesFragment}:

    - + {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}

    Nhớ lại ở lớp {@code TitlesFragment} rằng, nếu người dùng nhấp vào một mục danh sách và bố trí @@ -798,7 +798,7 @@ tóm tắt vở kịch được chọn khi màn hình ở hướng đứng:

    {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details_activity} - +

    Lưu ý rằng hoạt động này tự kết thúc nếu cấu hình là khổ ngang, sao cho hoạt động chính có thể chiếm lấy và hiển thị {@code DetailsFragment} bên cạnh {@code TitlesFragment}. Điều này có thể xảy ra nếu người dùng bắt đầu {@code DetailsActivity} ở dạng hướng đứng, nhưng diff --git a/docs/html-intl/intl/vi/guide/components/fundamentals.jd b/docs/html-intl/intl/vi/guide/components/fundamentals.jd index 4b70140723d95e8d2352647c66b03680078d4c4d..725c68dacb686390360e5805efcb26c77e14b44d 100644 --- a/docs/html-intl/intl/vi/guide/components/fundamentals.jd +++ b/docs/html-intl/intl/vi/guide/components/fundamentals.jd @@ -295,16 +295,16 @@ android.app.Activity} và các thuộc tính {@code android:label} quy định m

    Bạn phải khai báo tất cả thành phần của ứng dụng như sau:

    • Các phần tử <activity> +href="{@docRoot}guide/topics/manifest/activity-element.html"><activity> cho hoạt động
    • Các phần tử <service> cho dịch vụ
    • Các phần tử <receiver> +href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver> cho hàm nhận quảng bá
    • Các phần tử <provider> +href="{@docRoot}guide/topics/manifest/provider-element.html"><provider> cho trình cung cấp nội dung
    @@ -379,7 +379,7 @@ chúng, nhưng các dịch vụ bên ngoài như Google Play thì có đọc đ cho người dùng khi họ tìm kiếm ứng dụng từ thiết bị của mình.

    Ví dụ, nếu ứng dụng của bạn yêu cầu máy ảnh và sử dụng các API được giới thiệu trong Android 2.1 (API Mức 7), -bạn cần khai báo những điều này như yêu cầu trong tệp bản kê khai của mình như sau:

    +bạn cần khai báo những điều này như yêu cầu trong tệp bản kê khai của mình như sau:

     <manifest ... >
    diff --git a/docs/html-intl/intl/vi/guide/components/index.jd b/docs/html-intl/intl/vi/guide/components/index.jd
    index 966597d999c20cb89afb91b2f9fc86486d6d7a60..87b51c2849b026939b5a19fc7bb16ac335097f1a 100644
    --- a/docs/html-intl/intl/vi/guide/components/index.jd
    +++ b/docs/html-intl/intl/vi/guide/components/index.jd
    @@ -1,7 +1,7 @@
     page.title=Thành phần Ứng dụng
     page.landing=true
    -page.landing.intro=Khuôn khổ ứng dụng của Android cho phép bạn tạo lập nhiều ứng dụng đa dạng và sáng tạo bằng cách sử dụng một tập hợp các thành phần có thể tái sử dụng. Phần này giải thích cách bạn có thể xây dựng các thành phần định nghĩa các khối dựng cho ứng dụng của mình và cách kết nối chúng với nhau bằng cách sử dụng ý định. 
    -page.metaDescription=Khuôn khổ ứng dụng của Android cho phép bạn tạo lập nhiều ứng dụng đa dạng và sáng tạo bằng cách sử dụng một tập hợp các thành phần có thể tái sử dụng. Phần này giải thích cách bạn có thể xây dựng các thành phần định nghĩa các khối dựng cho ứng dụng của mình và cách kết nối chúng với nhau bằng cách sử dụng ý định. 
    +page.landing.intro=Khuôn khổ ứng dụng của Android cho phép bạn tạo lập nhiều ứng dụng đa dạng và sáng tạo bằng cách sử dụng một tập hợp các thành phần có thể tái sử dụng. Phần này giải thích cách bạn có thể xây dựng các thành phần định nghĩa các khối dựng cho ứng dụng của mình và cách kết nối chúng với nhau bằng cách sử dụng ý định.
    +page.metaDescription=Khuôn khổ ứng dụng của Android cho phép bạn tạo lập nhiều ứng dụng đa dạng và sáng tạo bằng cách sử dụng một tập hợp các thành phần có thể tái sử dụng. Phần này giải thích cách bạn có thể xây dựng các thành phần định nghĩa các khối dựng cho ứng dụng của mình và cách kết nối chúng với nhau bằng cách sử dụng ý định.
     page.landing.image=images/develop/app_components.png
     page.image=images/develop/app_components.png
     
    @@ -11,7 +11,7 @@ page.image=images/develop/app_components.png
     
       

    Bài viết Blog

    - +

    Sử dụng DialogFragments

    Trong bài viết này, tôi sẽ trình bày cách sử dụng DialogFragments bằng thư viện hỗ trợ v4 (cho khả năng tương thích ngược trên các thiết bị chạy phiên bản trước Honeycomb) để hiển thị một hộp thoại chỉnh sửa đơn giản và trả về một kết quả cho lệnh gọi Hoạt động bằng cách sử dụng một giao diện.

    @@ -21,7 +21,7 @@ page.image=images/develop/app_components.png

    Phân đoạn cho Tất cả

    Hôm nay, chúng tôi đã phát hành một thư viện tĩnh giới thiệu API Phân đoạn (cũng như LoaderManager mới và một vài lớp khác) tương tự sao cho các ứng dụng tương thích với phiên bản Android 1.6 hoặc mới hơn có thể sử dụng phân đoạn để tạo các giao diện người dùng tương thích với máy tính bảng.

    - +

    Tạo đa luồng cho Hiệu năng

    Một cách làm hay trong khi tạo các ứng dụng hồi đáp đó là đảm bảo luồng UI chính của bạn @@ -32,7 +32,7 @@ xử lý trong một luồng khác.

    Đào tạo

    - +

    Quản lý Vòng đời của Hoạt động

    Lớp này giải thích các phương pháp gọi lại vòng đời quan trọng mà mỗi thực thể diff --git a/docs/html-intl/intl/vi/guide/components/loaders.jd b/docs/html-intl/intl/vi/guide/components/loaders.jd index b6d277f3d527702311e547f5702106bcca55bfbd..0585076cedbc9d2b3f4d7e20d81646b7675c7da9 100644 --- a/docs/html-intl/intl/vi/guide/components/loaders.jd +++ b/docs/html-intl/intl/vi/guide/components/loaders.jd @@ -21,14 +21,14 @@ parent.link=activities.html - +

    Lớp khóa

    1. {@link android.app.LoaderManager}
    2. {@link android.content.Loader}
    3. -
    - + +

    Các mẫu liên quan

    1. @@ -51,7 +51,7 @@ thay đổi.
    2. tạo lại sau khi cấu hình thay đổi. Vì thế, chúng không cần truy vấn lại dữ liệu của mình. - +

      Tổng quan về API Trình tải

      Có nhiều lớp và giao diện có thể có liên quan trong khi sử dụng @@ -129,10 +129,10 @@ của {@link android.content.Loader} hoặc {@link android.content.AsyncTaskLoad dữ liệu từ một số nguồn khác.

    3. Một triển khai cho {@link android.app.LoaderManager.LoaderCallbacks}. Đây là nơi bạn tạo trình tải mới và quản lý các tham chiếu của mình tới các -trình tải hiện có.
    4. +trình tải hiện có.
    5. Một cách để hiển thị dữ liệu của trình tải, chẳng hạn như {@link android.widget.SimpleCursorAdapter}.
    6. -
    7. Một nguồn dữ liệu, chẳng hạn như một {@link android.content.ContentProvider}, khi sử dụng một +
    8. Một nguồn dữ liệu, chẳng hạn như một {@link android.content.ContentProvider}, khi sử dụng một {@link android.content.CursorLoader}.
    9. Khởi động một Trình tải

      @@ -140,7 +140,7 @@ android.widget.SimpleCursorAdapter}.

      {@link android.app.LoaderManager} quản lý một hoặc nhiều thực thể {@link android.content.Loader} trong một {@link android.app.Activity} hoặc {@link android.app.Fragment}. Chỉ có một {@link -android.app.LoaderManager} trên mỗi hoạt động hoặc phân đoạn.

      +android.app.LoaderManager} trên mỗi hoạt động hoặc phân đoạn.

      Thông thường, bạn sẽ khởi tạo một {@link android.content.Loader} bên trong phương pháp {@link @@ -157,13 +157,13 @@ tham số sau:

      • Một ID duy nhất xác định trình tải. Trong ví dụ này, ID là 0.
      • Các tham đối tùy chọn để cung cấp cho trình tải khi -xây dựng (null trong ví dụ này).
      • +xây dựng (null trong ví dụ này). -
      • Triển khai {@link android.app.LoaderManager.LoaderCallbacks}, phương pháp mà +
      • Triển khai {@link android.app.LoaderManager.LoaderCallbacks}, phương pháp mà {@link android.app.LoaderManager} gọi để báo cáo các sự kiện trình tải. Trong ví dụ này , lớp cục bộ triển khai giao diện {@link android.app.LoaderManager.LoaderCallbacks}, vì thế nó chuyển một tham chiếu -tới chính nó, {@code this}.
      • +tới chính nó, {@code this}.

      Lệnh gọi {@link android.app.LoaderManager#initLoader initLoader()} đảm bảo rằng một trình tải được khởi tạo và hiện hoạt. Nó có hai kết quả có thể xảy ra:

      @@ -193,7 +193,7 @@ vòng đời của trình tải. {@link android.app.LoaderManager} khởi động và dừng tải khi cần và duy trì trạng thái của trình tải và nội dung đi kèm của nó. Như hàm ý, bạn hiếm khi tương tác trực tiếp với các trình tải (thông qua một ví dụ về việc sử dụng các phương pháp trình tải để tinh chỉnh hành vi -của một trình tải, hãy xem ví dụ
      LoaderThrottle). +của một trình tải, hãy xem ví dụ LoaderThrottle). Bạn thường sử dụng nhất là các phương pháp {@link android.app.LoaderManager.LoaderCallbacks} để can thiệp vào tiến trình tải khi diễn ra một sự kiện đặc biệt. Để thảo luận thêm về chủ đề này, hãy xem phần Sử dụng Phương pháp Gọi lại LoaderManager.

      @@ -245,7 +245,7 @@ Khởi tạo và trả về một {@link android.content.Loader} mới cho ID đ — Được gọi khi một trình tải được tạo trước đó đã hoàn tất việc tải.
        -
      • {@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} +
      • {@link android.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} — Được gọi khi một trình tải được tạo trước đó đang được đặt lại, vì thế mà khiến dữ liệu của nó không sẵn có.
      • @@ -315,7 +315,7 @@ public Loader<Cursor> onCreateLoader(int id, Bundle args) {

        Phương pháp này được gọi khi một trình tải được tạo trước đó đã hoàn thành việc tải của mình. Phương pháp này được bảo đảm sẽ được gọi trước khi giải phóng dữ liệu cuối cùng được cung cấp cho trình tải này. Tại điểm này, bạn nên loại bỏ mọi trường hợp sử dụng -dữ liệu cũ (do nó sẽ được giải phóng sớm), nhưng không nên +dữ liệu cũ (do nó sẽ được giải phóng sớm), nhưng không nên tự mình giải phóng dữ liệu do trình tải sở hữu dữ liệu và sẽ đảm nhận việc này.

        @@ -340,11 +340,11 @@ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

        onLoaderReset

        -

        Phương pháp này được gọi khi một trình tải được tạo trước đó đang được đặt lại, vì thế mà khiến +

        Phương pháp này được gọi khi một trình tải được tạo trước đó đang được đặt lại, vì thế mà khiến dữ liệu của nó không sẵn có. Lệnh gọi lại này cho phép bạn tìm hiểu xem khi nào thì dữ liệu sẽ được giải phóng để bạn có thể loại bỏ tham chiếu của mình tới nó.  

        -

        Sự triển khai này gọi ra -{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()} +

        Sự triển khai này gọi ra +{@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()} với một giá trị null:

        @@ -366,7 +366,7 @@ public void onLoaderReset(Loader<Cursor> loader) {
         android.app.Fragment} có chức năng hiển thị một {@link android.widget.ListView} chứa
         kết quả của một truy vấn đối với trình cung cấp nội dung danh bạ. Nó sử dụng một {@link
         android.content.CursorLoader} để quản lý truy vấn trên trình cung cấp.

        - +

        Để một ứng dụng truy cập danh bạ của một người dùng, như minh họa trong ví dụ này, bản kê khai của nó phải bao gồm quyền {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}.

        diff --git a/docs/html-intl/intl/vi/guide/components/processes-and-threads.jd b/docs/html-intl/intl/vi/guide/components/processes-and-threads.jd index 390ca156a1f05f4025232d1fc7cf58f12697363a..b9933edc07fe99406b4ead05ae732dde4bc022b6 100644 --- a/docs/html-intl/intl/vi/guide/components/processes-and-threads.jd +++ b/docs/html-intl/intl/vi/guide/components/processes-and-threads.jd @@ -120,7 +120,7 @@ bắt buộc để đảm bảo giao diện người dùng có phản hồi.

        • Nó lưu trữ một {@link android.app.Activity} mà không nằm trong tiền cảnh, nhưng vẫn -hiển thị với người dùng (phương pháp {@link android.app.Activity#onPause onPause()} của nó đã được gọi). +hiển thị với người dùng (phương pháp {@link android.app.Activity#onPause onPause()} của nó đã được gọi). Điều này có thể xảy ra, ví dụ, nếu hoạt động tiền cảnh đã bắt đầu một hộp thoại, nó cho phép hoạt động trước được nhìn thấy phía sau nó.
        • @@ -202,7 +202,7 @@ gọi lại của hệ thống (chẳng hạn như {@link android.view.View#onKe hoặc một phương pháp gọi lại vòng đời) sẽ luôn chạy trong luồng UI của tiến trình.

          Ví dụ, khi người dùng chạm vào một nút trên màn hình, luồng UI của ứng dụng của bạn sẽ phân phối -sự kiện chạm tới widget, đến lượt mình, widget sẽ đặt trạng thái được nhấn và đăng một yêu cầu vô hiệu hóa tới +sự kiện chạm tới widget, đến lượt mình, widget sẽ đặt trạng thái được nhấn và đăng một yêu cầu vô hiệu hóa tới hàng đợi sự kiện. Luồng UI loại yêu cầu khỏi hàng đợi và thông báo với widget rằng nó nên tự vẽ lại .

          @@ -319,7 +319,7 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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) { diff --git a/docs/html-intl/intl/vi/guide/components/recents.jd b/docs/html-intl/intl/vi/guide/components/recents.jd index 0a176145f9caa72d9b2b19552d2da69ac5340016..271c05d9142e934bc7b8c976564cc0038a17e3e1 100644 --- a/docs/html-intl/intl/vi/guide/components/recents.jd +++ b/docs/html-intl/intl/vi/guide/components/recents.jd @@ -180,7 +180,7 @@ sau khi người dùng mở một tài liệu bằng ứng dụng:

          bất kỳ hoạt động nào mà người dùng đã gọi ra cuối cùng. -

          Lưu ý: Đối với những giá trị ngoài {@code none} và {@code never} +

          Lưu ý: Đối với những giá trị ngoài {@code none} và {@code never} hoạt động phải được định nghĩa bằng {@code launchMode="standard"}. Nếu thuộc tính này không được quy định thì {@code documentLaunchMode="none"} sẽ được sử dụng.

          @@ -191,7 +191,7 @@ hoàn thành. Bạn có thể khống chế hành vi này bằng lớp {@link an bằng một cờ {@link android.content.Intent}, hoặc bằng một thuộc tính <activity>.

          -

          Bạn có thể luôn loại trừ hoàn toàn một tác vụ khỏi màn hình tổng quan bằng cách thiết đặt thuộc tính +

          Bạn có thể luôn loại trừ hoàn toàn một tác vụ khỏi màn hình tổng quan bằng cách thiết đặt thuộc tính <activity> , {@code android:excludeFromRecents} thành {@code true}.

          diff --git a/docs/html-intl/intl/vi/guide/components/services.jd b/docs/html-intl/intl/vi/guide/components/services.jd index 9e3e6c75eccf589d42e2f92fb79be58ff0060f9d..fc2a7eaeb77f7dd5c0ac9cd2b063b287ae1ce627 100644 --- a/docs/html-intl/intl/vi/guide/components/services.jd +++ b/docs/html-intl/intl/vi/guide/components/services.jd @@ -199,7 +199,7 @@ con của phần tử {@code <service>} +

          Xem tham chiếu phần tử {@code <service>} để biết thêm thông tin về việc khai báo dịch vụ của bạn trong bản kê khai.

          Có các thuộc tính khác mà bạn có thể bao gồm trong phần tử {@code <service>} để @@ -605,7 +605,7 @@ tài liệu riêng về Sau khi chạy, một dịch vụ có thể thông báo cho người dùng về sự kiện bằng cách sử dụng Thông báo Cửa sổ hoặc Thông báo Thanh Trạng thái.

          -

          Thông báo cửa sổ là một thông báo xuất hiện một lúc trên bề mặt của cửa sổ hiện tại +

          Thông báo cửa sổ là một thông báo xuất hiện một lúc trên bề mặt của cửa sổ hiện tại rồi biến mất, trong khi thông báo thanh trạng thái cung cấp một biểu tượng trong thanh trạng thái cùng một thông báo, người dùng có thể chọn nó để thực hiện một hành động (chẳng hạn như bắt đầu một hoạt động).

          diff --git a/docs/html-intl/intl/vi/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/vi/guide/components/tasks-and-back-stack.jd index 85afffff5ba54d001383442aaf4a1affbad663cc..76df1dd2e075f9c774e206182a05eb1b40182d9e 100644 --- a/docs/html-intl/intl/vi/guide/components/tasks-and-back-stack.jd +++ b/docs/html-intl/intl/vi/guide/components/tasks-and-back-stack.jd @@ -190,7 +190,7 @@ trạng thái của các hoạt động của mình bằng cách sử dụng cá

          Khi hệ thống dừng một trong các hoạt động của bạn (chẳng hạn như khi một hoạt động mới bắt đầu hoặc tác vụ di chuyển về nền), hệ thống có thể hoàn toàn hủy hoạt động đó nếu nó cần khôi phục -bộ nhớ hệ thống. Khi điều này xảy ra, thông tin về trạng thái của hoạt động sẽ bị mất. Nếu điều này xảy ra, +bộ nhớ hệ thống. Khi điều này xảy ra, thông tin về trạng thái của hoạt động sẽ bị mất. Nếu điều này xảy ra, hệ thống vẫn biết rằng hoạt động có một vị trí trong ngăn xếp, nhưng khi hoạt động được đưa tới vị trí trên cùng của chồng, hệ thống phải tạo lại nó (thay vì tiếp tục). Để tránh @@ -314,7 +314,7 @@ hoạt động nằm trên cùng của ngăn xếp không phải là m

          Ví dụ, giả sử ngăn xếp của một tác vụ bao gồm hoạt động gốc A với các hoạt động B, C, và D ở trên cùng (chồng là A-B-C-D; D ở trên cùng). Một ý định đến cho loại hoạt động D. Nếu D có chế độ khởi chạy {@code "standard"} mặc định, một thực thể mới của lớp sẽ được khởi chạy và -chồng trở thành A-B-C-D-D. Tuy nhiên, nếu chế độ khởi chạy của D là {@code "singleTop"}, thực thể hiện tại +chồng trở thành A-B-C-D-D. Tuy nhiên, nếu chế độ khởi chạy của D là {@code "singleTop"}, thực thể hiện tại của D sẽ nhận ý định thông qua {@link android.app.Activity#onNewIntent onNewIntent()}, bởi nó nằm ở vị trí trên cùng của chồng—chồng vẫn là A-B-C-D. Tuy nhiên, nếu một ý định đến cho hoạt động loại B, khi đó một thực thể @@ -557,9 +557,9 @@ tác vụ mới và người dùng dành một khoảng thời gian làm việc . Lúc này, tác vụ được gửi tới nền và không hiển thị. Bây giờ, người dùng không có cách nào để quay lại tác vụ bởi nó không được biểu diễn trong trình khởi chạy ứng dụng.

          -

          Đối với những trường hợp mà bạn không muốn người dùng có thể quay lại một hoạt động, hãy đặt giá trị của phần tử +

          Đối với những trường hợp mà bạn không muốn người dùng có thể quay lại một hoạt động, hãy đặt giá trị của phần tử <activity> -, +, {@code finishOnTaskLaunch} thành {@code "true"} (xem Xóa chồng).

          diff --git a/docs/html-intl/intl/vi/preview/j8-jack.jd b/docs/html-intl/intl/vi/guide/platform/j8-jack.jd similarity index 100% rename from docs/html-intl/intl/vi/preview/j8-jack.jd rename to docs/html-intl/intl/vi/guide/platform/j8-jack.jd diff --git a/docs/html-intl/intl/vi/guide/topics/manifest/manifest-intro.jd b/docs/html-intl/intl/vi/guide/topics/manifest/manifest-intro.jd index ca2ed26270f2b52d566fefde53d5b66cb6cade30..06668b4c685c3eb2b67238f966686d646aac45ed 100644 --- a/docs/html-intl/intl/vi/guide/topics/manifest/manifest-intro.jd +++ b/docs/html-intl/intl/vi/guide/topics/manifest/manifest-intro.jd @@ -31,27 +31,27 @@ page.title=Bản kê khai Ứng dụng
        • Nó đặt tên gói Java cho ứng dụng. Tên gói đóng vai trò như một mã nhận diện duy nhất cho ứng dụng.
        • -
        • Nó mô tả các thành phần của ứng dụng — hoạt động, -dịch vụ, hàm nhận quảng bá, và trình cung cấp nội dung mà ứng dụng -được soạn bởi. Nó đặt tên các lớp triển khai từng thành phần và -công bố các khả năng của chúng (ví dụ, những tin nhắn {@link android.content.Intent -Intent} mà chúng có thể xử lý). Những khai báo này cho phép hệ thống Android +
        • Nó mô tả các thành phần của ứng dụng — hoạt động, +dịch vụ, hàm nhận quảng bá, và trình cung cấp nội dung mà ứng dụng +được soạn bởi. Nó đặt tên các lớp triển khai từng thành phần và +công bố các khả năng của chúng (ví dụ, những tin nhắn {@link android.content.Intent +Intent} mà chúng có thể xử lý). Những khai báo này cho phép hệ thống Android biết các thành phần là gì và chúng có thể được khởi chạy trong những điều kiện nào.
        • -
        • Nó xác định những tiến trình nào sẽ lưu trữ các thành phần ứng dụng.
        • +
        • Nó xác định những tiến trình nào sẽ lưu trữ các thành phần ứng dụng.
        • -
        • Nó khai báo các quyền mà ứng dụng phải có để -truy cập các phần được bảo vệ của API và tương tác với các ứng dụng khác.
        • +
        • Nó khai báo các quyền mà ứng dụng phải có để +truy cập các phần được bảo vệ của API và tương tác với các ứng dụng khác.
        • -
        • Nó cũng khai báo các quyền mà ứng dụng khác phải có để +
        • Nó cũng khai báo các quyền mà ứng dụng khác phải có để tương tác với các thành phần của ứng dụng.
        • -
        • Nó liệt kê các lớp {@link android.app.Instrumentation} cung cấp -tính năng tạo hồ sơ và các thông tin khác khi ứng dụng đang chạy. Những khai báo này -chỉ xuất hiện trong bản kê khai khi ứng dụng đang được phát triển và +
        • Nó liệt kê các lớp {@link android.app.Instrumentation} cung cấp +tính năng tạo hồ sơ và các thông tin khác khi ứng dụng đang chạy. Những khai báo này +chỉ xuất hiện trong bản kê khai khi ứng dụng đang được phát triển và thử nghiệm; chúng bị loại bỏ trước khi ứng dụng được công bố.
        • -
        • Nó khai báo mức tối thiểu của API Android mà ứng dụng +
        • Nó khai báo mức tối thiểu của API Android mà ứng dụng yêu cầu.
        • Nó liệt kê các thư viện mà ứng dụng phải được liên kết với.
        • @@ -61,12 +61,12 @@ yêu cầu.

          Cấu trúc của Tệp Bản kê khai

          -Sơ đồ bên dưới minh họa cấu trúc chung của tệp bản kê khai và mọi -phần tử mà nó có thể chứa. Từng phần tử, cùng với tất cả thuộc tính -của mình, sẽ được lập tài liệu theo dõi đầy đủ vào một tệp riêng. Để xem thông tin -chi tiết về mọi phần tử, hãy nhấp vào tên phần tử trong sơ đồ, +Sơ đồ bên dưới minh họa cấu trúc chung của tệp bản kê khai và mọi +phần tử mà nó có thể chứa. Từng phần tử, cùng với tất cả thuộc tính +của mình, sẽ được lập tài liệu theo dõi đầy đủ vào một tệp riêng. Để xem thông tin +chi tiết về mọi phần tử, hãy nhấp vào tên phần tử trong sơ đồ, trong danh sách các phần tử theo thứ tự chữ cái mà tuân theo sơ đồ, hoặc trên bất kỳ -nội dung nào khác đề cập tới tên phần tử. +nội dung nào khác đề cập tới tên phần tử.

          @@ -126,9 +126,9 @@ nội dung nào khác đề cập tới tên phần tử.
           

          -Tất cả phần tử có thể xuất hiện trong tệp bản kê khai được liệt kê ở bên dưới -theo thứ tự chữ cái. Đây là những phần tử hợp pháp duy nhất; bạn không thể -thêm các phần tử hay thuộc tính của chính mình. +Tất cả phần tử có thể xuất hiện trong tệp bản kê khai được liệt kê ở bên dưới +theo thứ tự chữ cái. Đây là những phần tử hợp pháp duy nhất; bạn không thể +thêm các phần tử hay thuộc tính của chính mình.

          @@ -158,74 +158,74 @@ thêm các phần tử hay thuộc tính của chính mình.

          - +

          Các Quy ước Tệp

          -Một số quy ước và quy tắc áp dụng chung cho tất cả các phần tử và thuộc tính +Một số quy ước và quy tắc áp dụng chung cho tất cả các phần tử và thuộc tính trong bản kê khai:

          Phần tử
          -
          Chỉ các phần tử +
          Chỉ các phần tử <manifest> và -<application> -là bắt buộc phải có, chúng đều phải có mặt và chỉ có thể xảy ra một lần. -Hầu hết các phần tử khác có thể xảy ra nhiều lần hoặc không xảy ra — mặc dù ít -nhất một vài trong số chúng phải có mặt để bản kê khai thực sự có +<application> +là bắt buộc phải có, chúng đều phải có mặt và chỉ có thể xảy ra một lần. +Hầu hết các phần tử khác có thể xảy ra nhiều lần hoặc không xảy ra — mặc dù ít +nhất một vài trong số chúng phải có mặt để bản kê khai thực sự có ý nghĩa nào đó.

          -Nếu một phần tử chứa bất kỳ nội dung nào, nó có thể chứa các phần tử khác. +Nếu một phần tử chứa bất kỳ nội dung nào, nó có thể chứa các phần tử khác. Tất cả giá trị sẽ được đặt thông qua thuộc tính, chứ không phải là dữ liệu ký tự trong một phần tử.

          Các phần tử cùng cấp thường không theo thứ tự. Ví dụ, các phần tử -<activity>, -<provider>, và -<service> -có thể được trộn lẫn với nhau theo bất kỳ trình tự nào. (Phần tử +<activity>, +<provider>, và +<service> +có thể được trộn lẫn với nhau theo bất kỳ trình tự nào. (Phần tử <activity-alias> -là trường hợp ngoại lệ đối với quy tắc này: Nó phải tuân theo -<activity> +là trường hợp ngoại lệ đối với quy tắc này: Nó phải tuân theo +<activity> , đối tượng mà nó là bí danh cho.)

          Thuộc tính
          -
          Theo cách hiểu thông thường, tất cả thuộc tính đều mang tính tùy chọn. Tuy nhiên, có một số thuộc tính -phải được quy định cho một phần tử để hoàn thành mục đích của nó. Sử dụng +
          Theo cách hiểu thông thường, tất cả thuộc tính đều mang tính tùy chọn. Tuy nhiên, có một số thuộc tính +phải được quy định cho một phần tử để hoàn thành mục đích của nó. Sử dụng tài liệu làm hướng dẫn. Đối với những thuộc tính thực sự tùy chọn, nó đề cập tới một giá trị mặc định hoặc thông báo điều gì sẽ xảy ra nếu không có một đặc tả. -

          Ngoài một số thuộc tính của phần tử -<manifest> -gốc, tất cả tên thuộc tính đều bắt đầu bằng một tiền tố {@code android:}— -ví dụ, {@code android:alwaysRetainTaskState}. Do tiền tố này -phổ dụng, tài liệu thường bỏ sót nó khi tham chiếu tới các thuộc tính +

          Ngoài một số thuộc tính của phần tử +<manifest> +gốc, tất cả tên thuộc tính đều bắt đầu bằng một tiền tố {@code android:}— +ví dụ, {@code android:alwaysRetainTaskState}. Do tiền tố này +phổ dụng, tài liệu thường bỏ sót nó khi tham chiếu tới các thuộc tính theo tên.

          Khai báo tên lớp
          -
          Nhiều thuộc tính tương ứng với các đối tượng Java, bao gồm các phần tử cho -chính ứng dụng (phần tử -<application> -) và các thành phần chính của nó — hoạt động -(<activity>), -dịch vụ -(<service>), -hàm nhận quảng bá -(<receiver>), -và trình cung cấp nội dung -(<provider>). +
          Nhiều thuộc tính tương ứng với các đối tượng Java, bao gồm các phần tử cho +chính ứng dụng (phần tử +<application> +) và các thành phần chính của nó — hoạt động +(<activity>), +dịch vụ +(<service>), +hàm nhận quảng bá +(<receiver>), +và trình cung cấp nội dung +(<provider>).

          -Nếu bạn định nghĩa một lớp con như vẫn luôn làm đối với lớp thành phần -({@link android.app.Activity}, {@link android.app.Service}, -{@link android.content.BroadcastReceiver}, và {@link android.content.ContentProvider}), -lớp con sẽ được khai báo thông qua một thuộc tính {@code name}. Tên phải bao gồm -chỉ định gói đầy đủ. +Nếu bạn định nghĩa một lớp con như vẫn luôn làm đối với lớp thành phần +({@link android.app.Activity}, {@link android.app.Service}, +{@link android.content.BroadcastReceiver}, và {@link android.content.ContentProvider}), +lớp con sẽ được khai báo thông qua một thuộc tính {@code name}. Tên phải bao gồm +chỉ định gói đầy đủ. Ví dụ, một lớp con {@link android.app.Service} có thể được khai báo như sau:

          @@ -239,12 +239,12 @@ Ví dụ, một lớp con {@link android.app.Service} có thể được khai b </manifest>

        -Tuy nhiên, do cách viết tốc ký, nếu ký tự đầu tiên của xâu là một dấu chấm, -xâu sẽ được nối với tên gói của ứng dụng (như được quy định bởi -thuộc tính của phần tử <manifest> +Tuy nhiên, do cách viết tốc ký, nếu ký tự đầu tiên của xâu là một dấu chấm, +xâu sẽ được nối với tên gói của ứng dụng (như được quy định bởi +thuộc tính của phần tử <manifest> -, package -). Cách gán sau cũng giống như trên: +, package +). Cách gán sau cũng giống như trên:

        <manifest package="com.example.project" . . . >
        @@ -257,13 +257,13 @@ thuộc tính của phần tử {@code @[gói:]kiểu:tên}

        -trong đó gói có thể được bỏ qua nếu tài nguyên nằm trong cùng gói -với ứng dụng, kiểu là kiểu của tài nguyên — chẳng hạn như "xâu" hoặc -— "vẽ được" và tên là tên nhận biết tài nguyên cụ thể. +trong đó gói có thể được bỏ qua nếu tài nguyên nằm trong cùng gói +với ứng dụng, kiểu là kiểu của tài nguyên — chẳng hạn như "xâu" hoặc +— "vẽ được" và tên là tên nhận biết tài nguyên cụ thể. Ví dụ:

        <activity android:icon="@drawable/smallPic" . . . >

        -Các giá trị từ một chủ đề được biểu diễn theo cách tương tự, nhưng với một '{@code ?}' +Các giá trị từ một chủ đề được biểu diễn theo cách tương tự, nhưng với một '{@code ?}' thay vì '{@code @}' ở đầu:

        @@ -299,8 +299,8 @@ thay vì '{@code @}' ở đầu:

        Giá trị xâu
        -
        Trường hợp giá trị của một thuộc tính là một xâu, phải sử dụng hai dấu xuyệc ngược ('{@code \\}') -để thoát các ký tự — ví dụ, '{@code \\n}' đối với +
        Trường hợp giá trị của một thuộc tính là một xâu, phải sử dụng hai dấu xuyệc ngược ('{@code \\}') +để thoát các ký tự — ví dụ, '{@code \\n}' đối với một dòng tin tức hoặc '{@code \\uxxxx}' đối với một ký tự Unicode.
        @@ -308,7 +308,7 @@ một dòng tin tức hoặc '{@code \\uxxxx}' đối với một ký tự Unico

        Các Tính năng Tệp

        -Phần sau đây mô tả cách phản ánh một số tính năng của Android +Phần sau đây mô tả cách phản ánh một số tính năng của Android trong tệp bản kê khai.

        @@ -316,23 +316,23 @@ trong tệp bản kê khai.

        Bộ lọc Ý định

        -Các thành phần cốt lõi của một ứng dụng (hoạt động, dịch vụ và hàm nhận -quảng bá) được kích hoạt bởi ý định. Ý định là một -gói thông tin (một đối tượng {@link android.content.Intent}) mô tả một -hành động mong muốn — bao gồm dữ liệu sẽ được dựa trên, thể loại của -thành phần mà sẽ thực hiện hành động, và các chỉ dẫn thích hợp khác. -Android định vị một thành phần phù hợp để hồi đáp ý định, khởi chạy -một thực thể mới của thành phần nếu cần, và chuyển cho nó đối tượng đó +Các thành phần cốt lõi của một ứng dụng (hoạt động, dịch vụ và hàm nhận +quảng bá) được kích hoạt bởi ý định. Ý định là một +gói thông tin (một đối tượng {@link android.content.Intent}) mô tả một +hành động mong muốn — bao gồm dữ liệu sẽ được dựa trên, thể loại của +thành phần mà sẽ thực hiện hành động, và các chỉ dẫn thích hợp khác. +Android định vị một thành phần phù hợp để hồi đáp ý định, khởi chạy +một thực thể mới của thành phần nếu cần, và chuyển cho nó đối tượng đó Ý định.

        -Các thành phần sẽ quảng cáo khả năng của mình — các kiểu ý định mà chúng có thể -hồi đáp — thông qua các bộ lọc ý định. Do hệ thống Android phải -tìm hiểu một thành phần có thể xử lý những ý định nào trước khi khởi chạy thành phần đó, -bộ lọc ý định được quy định trong bản kê khai như là các phần tử +Các thành phần sẽ quảng cáo khả năng của mình — các kiểu ý định mà chúng có thể +hồi đáp — thông qua các bộ lọc ý định. Do hệ thống Android phải +tìm hiểu một thành phần có thể xử lý những ý định nào trước khi khởi chạy thành phần đó, +bộ lọc ý định được quy định trong bản kê khai như là các phần tử <intent-filter> -. Một thành phần có thể có nhiều bộ lọc, mỗi bộ lọc lại mô tả +. Một thành phần có thể có nhiều bộ lọc, mỗi bộ lọc lại mô tả một khả năng khác nhau.

        @@ -344,9 +344,9 @@ thành phần.

        -Để biết thông tin về cách các đối tượng Ý định được kiểm tra thông qua bộ lọc ý định, -hãy xem tài liệu riêng có tiêu đề -Ý định +Để biết thông tin về cách các đối tượng Ý định được kiểm tra thông qua bộ lọc ý định, +hãy xem tài liệu riêng có tiêu đề +Ý định và Bộ lọc Ý định.

        @@ -354,42 +354,42 @@ và Bộ lọc Ý định.

        Biểu tượng và Nhãn

        -Nhiều phần tử có thuộc tính {@code icon} và {@code label} cho một -biểu tượng nhỏ và nhãn văn bản mà có thể được hiển thị với người dùng. Một số cũng có thuộc tính -{@code description} cho văn bản giải trình dài hơn mà cũng có thể -được hiển thị trên màn hình. Ví dụ, phần tử +Nhiều phần tử có thuộc tính {@code icon} và {@code label} cho một +biểu tượng nhỏ và nhãn văn bản mà có thể được hiển thị với người dùng. Một số cũng có thuộc tính +{@code description} cho văn bản giải trình dài hơn mà cũng có thể +được hiển thị trên màn hình. Ví dụ, phần tử <permission> -có cả ba thuộc tính này, vì thế khi người dùng được hỏi xem có -cấp quyền cho một ứng dụng yêu cầu hay không, biểu tượng thể hiện +có cả ba thuộc tính này, vì thế khi người dùng được hỏi xem có +cấp quyền cho một ứng dụng yêu cầu hay không, biểu tượng thể hiện quyền, tên của quyền, và mô tả nội dung của quyền đó đều có thể được trình bày cho người dùng xem.

        -Trong mọi trường hợp, biểu tượng và nhãn được đặt trong một phần tử chứa sẽ trở thành các thiết đặt -{@code icon} và {@code label} mặc định cho tất cả phần tử con của bộ chứa đó. -Vì thế, biểu tượng và nhãn được đặt trong phần tử -<application> -là biểu tượng và nhãn mặc định cho từng thành phần của ứng dụng. -Tương tự, biểu tượng và nhãn được đặt cho một thành phần — ví dụ, một phần tử -<activity> -— sẽ là các cài đặt mặc định cho từng phần tử -<intent-filter> +Trong mọi trường hợp, biểu tượng và nhãn được đặt trong một phần tử chứa sẽ trở thành các thiết đặt +{@code icon} và {@code label} mặc định cho tất cả phần tử con của bộ chứa đó. +Vì thế, biểu tượng và nhãn được đặt trong phần tử +<application> +là biểu tượng và nhãn mặc định cho từng thành phần của ứng dụng. +Tương tự, biểu tượng và nhãn được đặt cho một thành phần — ví dụ, một phần tử +<activity> +— sẽ là các cài đặt mặc định cho từng phần tử +<intent-filter> của thành phần đó. Nếu một phần tử -<application> -thiết đặt một nhãn, nhưng hoạt động và bộ lọc ý định của nó thì không, -nhãn ứng dụng sẽ được coi là nhãn của cả hoạt động và +<application> +thiết đặt một nhãn, nhưng hoạt động và bộ lọc ý định của nó thì không, +nhãn ứng dụng sẽ được coi là nhãn của cả hoạt động và bộ lọc ý định.

        -Biểu tượng và nhãn được đặt cho một bộ lọc ý định sẽ được sử dụng để biểu diễn một thành phần +Biểu tượng và nhãn được đặt cho một bộ lọc ý định sẽ được sử dụng để biểu diễn một thành phần bất cứ khi nào thành phần đó được trình bày với người dùng để thực hiện chức năng -mà bộ lọc đã quảng cáo. Ví dụ, một bộ lọc với các thiết đặt -"{@code android.intent.action.MAIN}" và -"{@code android.intent.category.LAUNCHER}" quảng cáo một hoạt động +mà bộ lọc đã quảng cáo. Ví dụ, một bộ lọc với các thiết đặt +"{@code android.intent.action.MAIN}" và +"{@code android.intent.category.LAUNCHER}" quảng cáo một hoạt động là hoạt động khởi đầu một ứng dụng — cụ thể, là -hoạt động sẽ được hiển thị trong trình khởi chạy ứng dụng. Vì thế, biểu tượng và nhãn +hoạt động sẽ được hiển thị trong trình khởi chạy ứng dụng. Vì thế, biểu tượng và nhãn được đặt trong bộ lọc là những nội dung được hiển thị trong trình khởi chạy.

        @@ -397,14 +397,14 @@ hoạt động sẽ được hiển thị trong trình khởi chạy ứng dụn

        Quyền

        -Một quyền là sự hạn chế giới hạn truy cập vào một phần của mã -hoặc vào dữ liệu trên thiết bị. Giới hạn này được áp đặt nhằm bảo vệ dữ liệu -và mã trọng yếu, có thể bị lạm dụng để bóp méo hoặc làm hỏng trải nghiệm người dùng. +Một quyền là sự hạn chế giới hạn truy cập vào một phần của mã +hoặc vào dữ liệu trên thiết bị. Giới hạn này được áp đặt nhằm bảo vệ dữ liệu +và mã trọng yếu, có thể bị lạm dụng để bóp méo hoặc làm hỏng trải nghiệm người dùng.

        -Mỗi quyền được nhận biết bằng một nhãn duy nhất. Thông thường, nhãn cho biết -hành động bị hạn chế. Ví dụ, sau đây là một số quyền được định nghĩa +Mỗi quyền được nhận biết bằng một nhãn duy nhất. Thông thường, nhãn cho biết +hành động bị hạn chế. Ví dụ, sau đây là một số quyền được định nghĩa bởi Android:

        @@ -418,25 +418,25 @@ Một tính năng có thể được bảo vệ bởi nhiều nhất một quy

        -Nếu một ứng dụng cần truy cập vào một tính năng được bảo vệ bởi một quyền, -nó phải khai báo rằng nó yêu cầu quyền đó cùng với một phần tử -<uses-permission> -trong bản kê khai. Lúc đó, khi ứng dụng được cài đặt trên -thiết bị, trình cài đặt sẽ xác định xem có cấp quyền -được yêu cầu hay không bằng cách kiểm tra các thẩm quyền đã ký chứng chỉ -của ứng dụng và trong một số trường hợp, bằng cách hỏi người dùng. -Nếu quyền được cấp, ứng dụng có thể sử dụng các tính năng +Nếu một ứng dụng cần truy cập vào một tính năng được bảo vệ bởi một quyền, +nó phải khai báo rằng nó yêu cầu quyền đó cùng với một phần tử +<uses-permission> +trong bản kê khai. Lúc đó, khi ứng dụng được cài đặt trên +thiết bị, trình cài đặt sẽ xác định xem có cấp quyền +được yêu cầu hay không bằng cách kiểm tra các thẩm quyền đã ký chứng chỉ +của ứng dụng và trong một số trường hợp, bằng cách hỏi người dùng. +Nếu quyền được cấp, ứng dụng có thể sử dụng các tính năng được bảo vệ. Nếu không, việc thử truy cập những tính năng đó sẽ thất bại -mà không có bất kỳ thông báo nào cho người dùng. +mà không có bất kỳ thông báo nào cho người dùng.

        -Một ứng dụng cũng có thể bảo vệ các thành phần của chính nó (hoạt động, dịch vụ, -hàm nhận quảng bá và trình cung cấp nội dung) bằng các quyền. Nó có thể sử dụng -bất kỳ quyền nào được định nghĩa bởi Android (được liệt kê trong -{@link android.Manifest.permission android.Manifest.permission}) hoặc được khai báo -bởi các ứng dụng khác. Hoặc nó có thể tự định nghĩa quyền của mình. Một quyền mới được khai báo -bằng phần tử +Một ứng dụng cũng có thể bảo vệ các thành phần của chính nó (hoạt động, dịch vụ, +hàm nhận quảng bá và trình cung cấp nội dung) bằng các quyền. Nó có thể sử dụng +bất kỳ quyền nào được định nghĩa bởi Android (được liệt kê trong +{@link android.Manifest.permission android.Manifest.permission}) hoặc được khai báo +bởi các ứng dụng khác. Hoặc nó có thể tự định nghĩa quyền của mình. Một quyền mới được khai báo +bằng phần tử <permission> . Ví dụ, một hoạt động có thể được bảo vệ như sau:

        @@ -457,43 +457,43 @@ bằng phần tử

        -Lưu ý rằng trong ví dụ này, quyền {@code DEBIT_ACCT} không chỉ -được khai báo bằng phần tử +Lưu ý rằng trong ví dụ này, quyền {@code DEBIT_ACCT} không chỉ +được khai báo bằng phần tử <permission> -, việc sử dụng quyền cũng được yêu cầu bằng phần tử -<uses-permission> -. Phải yêu cầu sử dụng quyền để các thành phần khác của -ứng dụng nhằm khởi chạy hoạt động được bảo vệ, mặc dù việc bảo vệ -do chính ứng dụng áp đặt. +, việc sử dụng quyền cũng được yêu cầu bằng phần tử +<uses-permission> +. Phải yêu cầu sử dụng quyền để các thành phần khác của +ứng dụng nhằm khởi chạy hoạt động được bảo vệ, mặc dù việc bảo vệ +do chính ứng dụng áp đặt.

        -Trong cùng ví dụ này, nếu thuộc tính {@code permission} được đặt thành một quyền -được khai báo ở nơi khác -(chẳng hạn như {@code android.permission.CALL_EMERGENCY_NUMBERS}, sẽ không -cần phải khai báo lại nó bằng một phần tử +Trong cùng ví dụ này, nếu thuộc tính {@code permission} được đặt thành một quyền +được khai báo ở nơi khác +(chẳng hạn như {@code android.permission.CALL_EMERGENCY_NUMBERS}, sẽ không +cần phải khai báo lại nó bằng một phần tử <permission> -. Tuy nhiên, sẽ vẫn cần phải yêu cầu sử dụng nó bằng -<uses-permission>. +. Tuy nhiên, sẽ vẫn cần phải yêu cầu sử dụng nó bằng +<uses-permission>.

        -Phần tử -<permission-tree> -sẽ khai báo một vùng tên cho nhóm quyền mà sẽ được định nghĩa trong -mã. Và +Phần tử +<permission-tree> +sẽ khai báo một vùng tên cho nhóm quyền mà sẽ được định nghĩa trong +mã. Và <permission-group> -sẽ định nghĩa một nhãn cho một tập hợp quyền (cả được khai báo trong bản kê khai bằng phần tử -<permission> -và được khai báo ở chỗ khác). Nó chỉ ảnh hưởng tới cách các quyền được -nhóm lại khi được trình bày với người dùng. Phần tử +sẽ định nghĩa một nhãn cho một tập hợp quyền (cả được khai báo trong bản kê khai bằng phần tử +<permission> +và được khai báo ở chỗ khác). Nó chỉ ảnh hưởng tới cách các quyền được +nhóm lại khi được trình bày với người dùng. Phần tử <permission-group> -không quy định những quyền nào thuộc về nhóm; +không quy định những quyền nào thuộc về nhóm; nó chỉ đặt cho nhóm một cái tên. Một quyền được đặt vào nhóm bằng cách gán tên nhóm với thuộc tính của phần tử -<permission> -, -permissionGroup +<permission> +, +permissionGroup .

        @@ -501,17 +501,17 @@ bằng cách gán tên nhóm với thuộc tính của phần tử

        Thư viện

        -Mọi ứng dụng đều được liên kết với thư viện Android mặc định, nó -bao gồm các gói cơ bản để xây dựng ứng dụng (bằng các lớp thông dụng -chẳng hạn như Hoạt động, Dịch vụ, Ý định, Dạng xem, Nút, Ứng dụng, Trình cung cấp Nội dung, +Mọi ứng dụng đều được liên kết với thư viện Android mặc định, nó +bao gồm các gói cơ bản để xây dựng ứng dụng (bằng các lớp thông dụng +chẳng hạn như Hoạt động, Dịch vụ, Ý định, Dạng xem, Nút, Ứng dụng, Trình cung cấp Nội dung, v.v.).

        -Tuy nhiên, một số gói nằm trong thư viện của chính mình. Nếu ứng dụng của bạn -sử dụng mã từ bất kỳ gói nào trong những gói này, nó phải công khai yêu cầu được liên kết -với chúng. Bản kê khai phải chứa một phần tử -<uses-library> -riêng để đặt tên cho từng thư viện. (Tên thư viện có thể được tìm thấy trong tài liệu +Tuy nhiên, một số gói nằm trong thư viện của chính mình. Nếu ứng dụng của bạn +sử dụng mã từ bất kỳ gói nào trong những gói này, nó phải công khai yêu cầu được liên kết +với chúng. Bản kê khai phải chứa một phần tử +<uses-library> +riêng để đặt tên cho từng thư viện. (Tên thư viện có thể được tìm thấy trong tài liệu của gói.)

        diff --git a/docs/html-intl/intl/vi/guide/topics/providers/calendar-provider.jd b/docs/html-intl/intl/vi/guide/topics/providers/calendar-provider.jd index e2ecdb32b2e8116b906e2f0538b3d54d5059137c..c9d779b114834661b323080c637e20d62e2474b2 100644 --- a/docs/html-intl/intl/vi/guide/topics/providers/calendar-provider.jd +++ b/docs/html-intl/intl/vi/guide/topics/providers/calendar-provider.jd @@ -42,7 +42,7 @@ page.title=Trình cung cấp Lịch
      • Sử dụng ý định để xem dữ liệu lịch
    - +
  • Trình điều hợp Đồng bộ
  • @@ -63,8 +63,8 @@ các thao tác trên lịch, sự kiện, người dự, nhắc nhở, v.v.

    API Trình cung cấp Lịch có thể được sử dụng bởi các ứng dụng và trình điều hợp đồng bộ. Các quy tắc thay đổi tùy vào loại chương trình đang thực hiện lệnh gọi. Tài liệu này -tập trung chủ yếu vào việc sử dụng API Trình cung cấp Lịch như một ứng dụng. Để bàn -về việc các trình điều hợp đồng bộ khác nhau như thế nào, hãy xem phần +tập trung chủ yếu vào việc sử dụng API Trình cung cấp Lịch như một ứng dụng. Để bàn +về việc các trình điều hợp đồng bộ khác nhau như thế nào, hãy xem phần Trình điều hợp Đồng bộ.

    @@ -79,17 +79,17 @@ và cũng không cần cung cấp một giao diện người dùng để xem ho

    Nội dung Cơ bản

    -

    Các trình cung cấp nội dung sẽ lưu trữ dữ liệu và cho phép truy cập +

    Các trình cung cấp nội dung sẽ lưu trữ dữ liệu và cho phép truy cập ứng dụng. Trình cung cấp nội dung được nền tảng Android giới thiệu (bao gồm Trình cung cấp Lịch) thường trình bày dữ liệu như một tập hợp gồm nhiều bảng dựa trên một mô hình cơ sở dữ liệu quan hệ, trong đó mỗi hàng là một bản ghi và mỗi cột là dữ liệu thuộc một loại và có ý nghĩa cụ thể. Thông qua API Trình cung cấp Lịch, các ứng dụng và trình điều hợp đồng bộ có thể nhận được quyền truy cập đọc/ghi vào các bảng trong cơ sở dữ liệu là nơi chứa dữ liệu lịch của người dùng.

    -

    Mọi trình cung cấp nội dung đều đưa ra một URI công khai (được bẻ dòng như một đối tượng +

    Mọi trình cung cấp nội dung đều đưa ra một URI công khai (được bẻ dòng như một đối tượng {@link android.net.Uri} ) để xác định tập dữ liệu của nó một cách duy nhất. Trình cung cấp nội dung mà kiểm soát nhiều - tập dữ liệu (nhiều bảng) sẽ đưa ra một URI riêng cho từng bảng. Tất cả + tập dữ liệu (nhiều bảng) sẽ đưa ra một URI riêng cho từng bảng. Tất cả URI cho trình cung cấp đều bắt đầu bằng xâu "content://". Điều này sẽ xác định dữ liệu là đang được kiểm soát bởi một trình cung cấp nội dung. Trình cung cấp Lịch định nghĩa các hằng số cho URI đối với từng lớp (bảng) của nó. Những URI @@ -113,26 +113,26 @@ các bảng chính và các trường liên kết chúng với nhau.

    {@link android.provider.CalendarContract.Calendars}

    - - Bảng này chứa + + Bảng này chứa thông tin riêng của lịch. Mỗi hàng trong bảng này chứa chi tiết của một lịch duy nhất, chẳng hạn như tên, màu, thông tin đồng bộ, v.v. {@link android.provider.CalendarContract.Events} - + Bảng này chứa thông tin riêng theo sự kiện. Mỗi hàng trong bảng có thông tin cho một sự kiện duy nhất—ví dụ: tiêu đề sự kiện, địa điểm, thời gian bắt đầu , thời gian kết thúc, v.v. Sự kiện có thể xảy ra một lần hoặc lặp lại nhiều lần. Người dự, -nhắc nhở, và các tính chất mở rộng được lưu trữ trong các bảng riêng. -Mỗi mục đều có một {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} +nhắc nhở, và các tính chất mở rộng được lưu trữ trong các bảng riêng. +Mỗi mục đều có một {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} tham chiếu tới {@link android.provider.BaseColumns#_ID} trong bảng Sự kiện. {@link android.provider.CalendarContract.Instances} - + Bảng này chứa thời gian bắt đầu và thời gian kết thúc của mỗi lần xảy ra một sự kiện. Mỗi hàng trong bảng này đại diện cho một lần xảy ra sự kiện. Với các sự kiện xảy ra một lần thì có một ánh xạ 1:1 @@ -141,7 +141,7 @@ của thực thể tới sự kiện. Đối với các sự kiện định kỳ {@link android.provider.CalendarContract.Attendees} - + Bảng này chứa thông tin về người dự (khách) của sự kiện. Mỗi hàng đại diện một khách duy nhất của một sự kiện. Nó quy định loại khách và phản hồi tham dự của khách @@ -149,17 +149,17 @@ cho một sự kiện. {@link android.provider.CalendarContract.Reminders} - + Bảng này chứa dữ liệu về cảnh báo/thông báo. Mỗi hàng đại diện một cảnh báo duy nhất cho một sự kiện. Một sự kiện có thể có nhiều nhắc nhở. Số nhắc nhở tối đa của một sự kiện -được quy định trong -{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}, +được quy định trong +{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}, được đặt bởi trình điều hợp đồng bộ đang sở hữu lịch đã cho. Nhắc nhở được quy định bằng số phút trước khi diễn ra sự kiện và có một phương pháp để xác định cách người dùng sẽ được cảnh báo. - +

    API Trình cung cấp Lịch được thiết kế để linh hoạt và mạnh mẽ. Đồng @@ -178,9 +178,9 @@ Lịch.

  • Trình điều hợp đồng bộ. Trình điều hợp đồng bộ có chức năng đồng bộ dữ liệu lịch -lên thiết bị của một người dùng bằng một máy chủ hoặc nguồn dữ liệu khác. Trong bảng +lên thiết bị của một người dùng bằng một máy chủ hoặc nguồn dữ liệu khác. Trong bảng {@link android.provider.CalendarContract.Calendars} và -{@link android.provider.CalendarContract.Events}, +{@link android.provider.CalendarContract.Events}, có các cột để cho trình điều hợp đồng bộ sử dụng. Trình cung cấp và ứng dụng không nên sửa đổi chúng. Trên thực tế, chúng không hiển thị trừ khi được truy cập như một trình điều hợp đồng bộ. Để biết thêm thông tin về @@ -209,9 +209,9 @@ phải bao gồm quyền {@link android.Manifest.permission#WRITE_CALENDAR}

    Bảng Lịch

    -

    Bảng {@link android.provider.CalendarContract.Calendars} chứa thông tin chi tiết +

    Bảng {@link android.provider.CalendarContract.Calendars} chứa thông tin chi tiết cho từng lịch. Các cột -Lịch sau có thể ghi được bởi cả ứng dụng và trình điều hợp đồng bộ. +Lịch sau có thể ghi được bởi cả ứng dụng và trình điều hợp đồng bộ. Để xem danh sách đầy đủ về các trường được hỗ trợ, hãy xem tài liệu tham khảo {@link android.provider.CalendarContract.Calendars}.

    @@ -229,7 +229,7 @@ Lịch sau có thể ghi được bởi cả ứng dụng và Trình tải. Nếu bạn đang không chỉ +không đồng bộ thay vì trên luồng chính. Để bàn thêm, hãy xem phần +Trình tải. Nếu bạn đang không chỉ đọc dữ liệu mà còn sửa đổi nó, hãy xem {@link android.content.AsyncQueryHandler}.

    @@ -268,18 +268,18 @@ public static final String[] EVENT_PROJECTION = new String[] { Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3; - + +đồng bộ.

    Trong phần tiếp theo của ví dụ, bạn sẽ xây dựng truy vấn của mình. Lựa chọn @@ -301,58 +301,58 @@ các lịch có ACCOUNT_NAME đã xem, không chỉ các lịch mà người dùng sở hữu, hãy bỏ qua OWNER_ACCOUNT. Truy vấn sẽ trả về đối tượng {@link android.database.Cursor} mà bạn có thể sử dụng để xem xét tập kết quả được trả về bởi truy vấn -cơ sở dữ liệu. Để bàn thêm về việc sử dụng các truy vấn trong trình cung cấp nội dung, +cơ sở dữ liệu. Để bàn thêm về việc sử dụng các truy vấn trong trình cung cấp nội dung, hãy xem phần Trình cung cấp Nội dung.

    // Run query
     Cursor cur = null;
     ContentResolver cr = getContentResolver();
    -Uri uri = Calendars.CONTENT_URI;   
    -String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    +Uri uri = Calendars.CONTENT_URI;
    +String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                             + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                             + Calendars.OWNER_ACCOUNT + " = ?))";
     String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
    -        "sampleuser@gmail.com"}; 
    -// Submit the query and get a Cursor object back. 
    +        "sampleuser@gmail.com"};
    +// Submit the query and get a Cursor object back.
     cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

    Phần tiếp theo sử dụng con chạy để duyệt qua tập kết quả. Nó sử dụng các hằng số được thiết lập ngay từ đầu ví dụ để trả về các giá trị cho mỗi trường.

    - +
    // Use the cursor to step through the returned records
     while (cur.moveToNext()) {
         long calID = 0;
         String displayName = null;
         String accountName = null;
         String ownerName = null;
    -      
    +
         // Get the field values
         calID = cur.getLong(PROJECTION_ID_INDEX);
         displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
         accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
         ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
    -              
    +
         // Do something with the values...
     
        ...
     }
     
    - +

    Sửa đổi một lịch

    Để thực hiện cập nhật một lịch, bạn có thể cung cấp {@link android.provider.BaseColumns#_ID} của lịch hoặc dưới dạng ID được nối vào cho -Uri +Uri -({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) +({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) hoặc dưới dạng mục chọn đầu tiên. Lựa chọn nên bắt đầu bằng "_id=?", và selectionArg đầu tiên sẽ là {@link -android.provider.BaseColumns#_ID} của lịch. +android.provider.BaseColumns#_ID} của lịch. Bạn cũng có thể thực hiện cập nhật bằng cách mã hóa ID trong URI. Ví dụ này thay đổi tên hiển thị -của một lịch bằng cách sử dụng phương pháp +của một lịch bằng cách sử dụng phương pháp ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) :

    @@ -375,7 +375,7 @@ một ứng dụng cần tạo một lịch cục bộ, nó có thể làm đi chèn lịch dưới dạng một trình điều hợp đồng bộ, sử dụng {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} của {@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}. -{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} +{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} là một loại tài khoản đặc biệt dành cho các lịch không liên kết với một tài khoản thiết bị. Các lịch loại này không được đồng bộ với một máy chủ. Để bàn về trình điều hợp đồng bộ, hãy xem phần Trình điều hợp Đồng bộ.

    @@ -434,7 +434,7 @@ android.provider.CalendarContract.Events}.

    - + - + - + - - + + - + - + - + - - + - - - + @@ -514,11 +514,11 @@ java.util.TimeZone#getAvailableIDs()}. Lưu ý rằng quy tắc này không áp bạn đang chèn một sự kiện thông qua Ý định {@link android.content.Intent#ACTION_INSERT INSERT} như được mô tả trong Sử dụng ý định để chèn một sự kiện—trong kịch bản đó, một múi giờ mặc định sẽ được cung cấp. - +
  • Đối với các sự kiện không định kỳ, bạn phải đưa vào {@link android.provider.CalendarContract.EventsColumns#DTEND}.
  • - - + +
  • Đối với các sự kiện định kỳ, bạn phải đưa vào một {@link android.provider.CalendarContract.EventsColumns#DURATION} bên cạnh {@link android.provider.CalendarContract.EventsColumns#RRULE} hay {@link @@ -526,9 +526,9 @@ android.provider.CalendarContract.EventsColumns#RDATE}. Lưu ý rằng quy tắc bạn đang chèn một sự kiện thông qua Ý định {@link android.content.Intent#ACTION_INSERT INSERT} như được mô tả trong Sử dụng ý định để chèn một sự kiện—trong kịch bản đó, bạn có thể sử dụng một {@link -android.provider.CalendarContract.EventsColumns#RRULE} cùng với {@link android.provider.CalendarContract.EventsColumns#DTSTART} và {@link android.provider.CalendarContract.EventsColumns#DTEND}, và ứng dụng Lịch +android.provider.CalendarContract.EventsColumns#RRULE} cùng với {@link android.provider.CalendarContract.EventsColumns#DTSTART} và {@link android.provider.CalendarContract.EventsColumns#DTEND}, và ứng dụng Lịch sẽ tự động chuyển nó thành một thời lượng.
  • - +

    Sau đây là một ví dụ về cách chèn một sự kiện. Ví dụ này đang được thực hiện trong luồng @@ -539,8 +539,8 @@ thông tin, hãy xem phần {@link android.content.AsyncQueryHandler}.

     long calID = 3;
    -long startMillis = 0; 
    -long endMillis = 0;     
    +long startMillis = 0;
    +long endMillis = 0;
     Calendar beginTime = Calendar.getInstance();
     beginTime.set(2012, 9, 14, 7, 30);
     startMillis = beginTime.getTimeInMillis();
    @@ -561,7 +561,7 @@ Uri uri = cr.insert(Events.CONTENT_URI, values);
     
     // get the event ID that is the last element in the Uri
     long eventID = Long.parseLong(uri.getLastPathSegment());
    -// 
    +//
     // ... do something with event ID
     //
     //
    @@ -578,14 +578,14 @@ người dự hoặc nhắc nhở vào một sự kiện.

    bạn nên sử dụng một Ý định {@link android.content.Intent#ACTION_EDIT EDIT} như được mô tả trong Sử dụng ý định để chỉnh sửa một sự kiện. Tuy nhiên, nếu cần, bạn có thể chỉnh sửa sự kiện trực tiếp. Để thực hiện cập nhật -một Sự kiện, bạn có thể cung cấp _ID của sự kiện +một Sự kiện, bạn có thể cung cấp _ID của sự kiện hoặc dưới dạng ID được nối vào cho Uri ({@link -android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) -hoặc dưới dạng mục chọn đầu tiên. +android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) +hoặc dưới dạng mục chọn đầu tiên. Lựa chọn nên bắt đầu bằng "_id=?", và selectionArg đầu tiên nên là _ID của sự kiện. Bạn cũng có thể thực hiện cập nhật bằng cách sử dụng một lựa chọn không có ID. Sau đây là một ví dụ về cách cập nhật một -sự kiện. Nó thay đổi tiêu đề của sự kiện bằng cách sử dụng phương pháp +sự kiện. Nó thay đổi tiêu đề của sự kiện bằng cách sử dụng phương pháp {@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()} :

    @@ -598,7 +598,7 @@ ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event -values.put(Events.TITLE, "Kickboxing"); +values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows); @@ -625,22 +625,22 @@ ContentValues values = new ContentValues(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().delete(deleteUri, null, null); -Log.i(DEBUG_TAG, "Rows deleted: " + rows); +Log.i(DEBUG_TAG, "Rows deleted: " + rows);

    Bảng Người dự

    Mỗi hàng của bảng {@link android.provider.CalendarContract.Attendees} đại diện -cho một người dự hoặc khách duy nhất của một sự kiện. Gọi -{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} +cho một người dự hoặc khách duy nhất của một sự kiện. Gọi +{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} sẽ trả về một danh sách người dự cho sự kiện -với {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} đã cho. +với {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} đã cho. {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} này phải khớp với {@link -android.provider.BaseColumns#_ID} của một sự kiện cụ thể.

    +android.provider.BaseColumns#_ID} của một sự kiện cụ thể.

    Bảng sau liệt kê các trường -có thể ghi được. Khi chèn một người dự mới, bạn phải điền tất cả +có thể ghi được. Khi chèn một người dự mới, bạn phải điền tất cả ngoại trừ ATTENDEE_NAME.

    @@ -698,7 +698,7 @@ ngoại trừ ATTENDEE_NAME.

    Thêm Người dự

    Sau đây là một ví dụ về cách thêm một người dự vào một sự kiện. Lưu ý rằng -{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} +{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} là bắt buộc:

    @@ -718,17 +718,17 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values);
     

    Bảng Nhắc nhở

    Mỗi hàng của bảng {@link android.provider.CalendarContract.Reminders} đại diện -cho một nhắc nhở của một sự kiện. Gọi +cho một nhắc nhở của một sự kiện. Gọi {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} sẽ trả về một danh sách nhắc nhở cho -sự kiện với +sự kiện với {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} đã cho.

    Bảng sau liệt kê các trường ghi được đối với nhắc nhở. Tất cả đều phải được đưa vào khi chèn một nhắc nhở mới. Lưu ý rằng các trình điều hợp đồng bộ quy định các loại nhắc nhở chúng hỗ trợ trong bảng {@link -android.provider.CalendarContract.Calendars}. Xem -{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} +android.provider.CalendarContract.Calendars}. Xem +{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} để biết chi tiết.

    @@ -773,16 +773,16 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values);

    Bảng Thực thể

    -

    Bảng +

    Bảng {@link android.provider.CalendarContract.Instances} chứa thời gian bắt đầu và thời gian kết thúc của các lần xảy ra một sự kiện. Mỗi hàng trong bảng này đại diện cho một lần xảy ra sự kiện. Bảng thực thể không ghi được và chỉ đưa ra một cách để truy vấn các lần xảy ra sự kiện.

    -

    Bảng sau liệt kê một số trường mà bạn có thể truy vấn đối với một thực thể. Lưu ý -rằng múi giờ được định nghĩa bởi -{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} -và +

    Bảng sau liệt kê một số trường mà bạn có thể truy vấn đối với một thực thể. Lưu ý +rằng múi giờ được định nghĩa bởi +{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} +và {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}.

    @@ -801,18 +801,18 @@ và - + - + - + @@ -820,16 +820,16 @@ của Lịch. - - + - +
    {@link android.provider.CalendarContract.EventsColumns#DURATION}Thời lượng của sự kiện theo định dạng RFC5545. Ví dụ, giá trị bằng "PT1H" cho biết sự kiện sẽ kéo dài một giờ và giá trị bằng "P2W" cho biết @@ -444,39 +444,39 @@ thời lượng là 2 tuần.
    {@link android.provider.CalendarContract.EventsColumns#ALL_DAY}Giá trị bằng 1 cho biết sự kiện này chiếm cả ngày, được xác định bởi múi giờ tại địa phương. Giá trị bằng 0 cho biết đó là một sự kiện thường xuyên mà có thể bắt đầu và kết thúc vào bất cứ lúc nào trong một ngày.
    {@link android.provider.CalendarContract.EventsColumns#RRULE}Quy tắc lặp lại đối với định dạng sự kiện. Ví dụ, "FREQ=WEEKLY;COUNT=10;WKST=SU". Bạn có thể tìm thêm nhiều ví dụ hơn ở đây.
    {@link android.provider.CalendarContract.EventsColumns#RDATE}Ngày lặp lại đối với sự kiện. - Bạn thường sử dụng {@link android.provider.CalendarContract.EventsColumns#RDATE} - cùng với {@link android.provider.CalendarContract.EventsColumns#RRULE} + Ngày lặp lại đối với sự kiện. + Bạn thường sử dụng {@link android.provider.CalendarContract.EventsColumns#RDATE} + cùng với {@link android.provider.CalendarContract.EventsColumns#RRULE} để định nghĩa một tập tổng hợp các trường hợp xảy ra lặp lại. Để bàn thêm, hãy xem phần RFC5545 spec.
    {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}Xem sự kiện này được tính là thời gian bận hay là thời gian rảnh có thể được + + Xem sự kiện này được tính là thời gian bận hay là thời gian rảnh có thể được xếp lại lịch.
    {@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}
    {@link android.provider.CalendarContract.Instances#END_DAY}Ngày kết thúc theo lịch Julian của thực thể theo múi giờ -của Lịch. - +của Lịch. +
    {@link android.provider.CalendarContract.Instances#END_MINUTE}Phút kết thúc của thực thể được xác định từ nửa đêm theo múi giờ của Lịch.
    {@link android.provider.CalendarContract.Instances#EVENT_ID}
    {@link android.provider.CalendarContract.Instances#START_DAY}Ngày bắt đầu theo lịch Julian của thực thể theo múi giờ của Lịch. + Ngày bắt đầu theo lịch Julian của thực thể theo múi giờ của Lịch.
    {@link android.provider.CalendarContract.Instances#START_MINUTE}Phút bắt đầu của thực thể được xác định từ nửa đêm theo múi giờ -của Lịch. +của Lịch.
    @@ -840,7 +840,7 @@ của Lịch. trong URI. Trong ví dụ này, {@link android.provider.CalendarContract.Instances} có quyền truy cập trường {@link android.provider.CalendarContract.EventsColumns#TITLE} thông qua việc -triển khai giao diện {@link android.provider.CalendarContract.EventsColumns} của nó. +triển khai giao diện {@link android.provider.CalendarContract.EventsColumns} của nó. Nói cách khác, {@link android.provider.CalendarContract.EventsColumns#TITLE} được trả về qua một chế độ xem cơ sở dữ liệu, chứ không qua việc truy vấn bảng {@link @@ -853,7 +853,7 @@ public static final String[] INSTANCE_PROJECTION = new String[] { Instances.BEGIN, // 1 Instances.TITLE // 2 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; @@ -868,7 +868,7 @@ long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); - + Cursor cur = null; ContentResolver cr = getContentResolver(); @@ -883,28 +883,28 @@ ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query -cur = cr.query(builder.build(), - INSTANCE_PROJECTION, - selection, - selectionArgs, +cur = cr.query(builder.build(), + INSTANCE_PROJECTION, + selection, + selectionArgs, null); - + while (cur.moveToNext()) { String title = null; long eventID = 0; - long beginVal = 0; - + long beginVal = 0; + // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); - - // Do something with the values. - Log.i(DEBUG_TAG, "Event: " + title); + + // Do something with the values. + Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(beginVal); + calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); + Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } }
  • @@ -922,9 +922,9 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_VIEW VIEW}

    content://com.android.calendar/time/<ms_since_epoch>

    - Bạn cũng có thể tham khảo tới URI bằng -{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. -Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để xem dữ liệu lịch. + Bạn cũng có thể tham khảo tới URI bằng +{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. +Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để xem dữ liệu lịch. Mở lịch đến thời gian được chỉ định bởi <ms_since_epoch>. @@ -935,11 +935,11 @@ while (cur.moveToNext()) {

    content://com.android.calendar/events/<event_id>

    - - Bạn cũng có thể tham khảo tới URI bằng -{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. + + Bạn cũng có thể tham khảo tới URI bằng +{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để xem dữ liệu lịch. - + Xem sự kiện được chỉ định bởi <event_id>. @@ -952,12 +952,12 @@ while (cur.moveToNext()) { {@link android.content.Intent#ACTION_EDIT EDIT}

    content://com.android.calendar/events/<event_id>

    - - Bạn cũng có thể tham khảo tới URI bằng -{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. + + Bạn cũng có thể tham khảo tới URI bằng +{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để chỉnh sửa một sự kiện. - - + + Chỉnh sửa sự kiện được chỉ định bởi <event_id>. @@ -972,11 +972,11 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_INSERT INSERT}

    content://com.android.calendar/events

    - - Bạn cũng có thể tham khảo tới URI bằng -{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. + + Bạn cũng có thể tham khảo tới URI bằng +{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. Để xem một ví dụ về cách sử dụng ý định này, hãy xem Sử dụng ý định để chèn một sự kiện. - + Tạo một sự kiện. @@ -996,7 +996,7 @@ while (cur.moveToNext()) { Tên cho sự kiện. - + {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} Thời gian bắt đầu sự kiện tính bằng mili giây trôi qua kể từ giờ epoch. @@ -1004,25 +1004,25 @@ CalendarContract.EXTRA_EVENT_BEGIN_TIME} {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} - + Thời gian kết thúc sự kiện tính bằng mili giây trôi qua kể từ giờ epoch. {@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY CalendarContract.EXTRA_EVENT_ALL_DAY} - + Một boolean cho biết đó là một sự kiện cả ngày. Giá trị có thể bằng true hoặc false. {@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION Events.EVENT_LOCATION} - + Địa điểm của sự kiện. {@link android.provider.CalendarContract.EventsColumns#DESCRIPTION Events.DESCRIPTION} - + Mô tả sự kiện. @@ -1039,16 +1039,16 @@ Events.DESCRIPTION} {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL Events.ACCESS_LEVEL} - + Sự kiện là riêng tư hay công khai. {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY Events.AVAILABILITY} - + Xem sự kiện này tính là thời gian bận hay là thời gian rảnh có thể được xếp lại lịch. - - + +

    Các phần sau mô tả cách sử dụng những ý định này.

    @@ -1059,23 +1059,23 @@ Events.AVAILABILITY} Bằng cách này, ứng dụng của bạn thậm chí không cần phải có quyền {@link android.Manifest.permission#WRITE_CALENDAR} được bao gồm trong tệp bản kê khai của mình.

    - +

    Khi người dùng chạy một ứng dụng mà sử dụng cách này, ứng dụng sẽ gửi chúng tới Lịch để hoàn thành việc thêm một sự kiện. Ý định {@link android.content.Intent#ACTION_INSERT INSERT} sử dụng các trường phụ thêm để điền trước vào một mẫu bằng các chi tiết của sự kiện trong Lịch. Khi đó, người dùng có thể hủy bỏ sự kiện, chỉnh sửa mẫu nếu cần, hoặc lưu sự kiện vào lịch của mình.

    - +

    Sau đây là một đoạn mã HTML lập biểu một sự kiện vào ngày 19/1/2012, diễn ra từ 7:30 sáng đến 8:30 sáng. Lưu ý điều sau đây về đoạn mã HTML này:

      -
    • Nó quy định {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} +
    • Nó quy định {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} là Uri.
    • - +
    • Nó sử dụng các trường phụ {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} và {@link @@ -1083,10 +1083,10 @@ android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} để điền trước thời gian của sự kiện vào mẫu. Các giá trị đối với những thời gian này phải tính bằng mili giây UTC trôi qua kể từ giờ epoch.
    • - +
    • Nó sử dụng trường phụ {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL} để cung cấp một danh sách người được mời phân cách bằng dấu phẩy, được chỉ định theo địa chỉ e-mail.
    • - +
     Calendar beginTime = Calendar.getInstance();
    @@ -1158,18 +1158,18 @@ truy cập Trình cung cấp Lịch:

    • Trình điều hợp đồng bộ cần chỉ định rằng nó là một trình điều hợp đồng bộ bằng cách đặt {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} thành true.
    • - - + +
    • Trình điều hợp đồng bộ cần cung cấp một {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} và một {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} làm tham số truy vấn trong URI.
    • - +
    • Trình điều hợp đồng bộ có quyền truy nhập ghi vào nhiều cột hơn ứng dụng hay widget. - Ví dụ, một ứng dụng chỉ có thể sửa đổi một vài đặc điểm của một lịch, + Ví dụ, một ứng dụng chỉ có thể sửa đổi một vài đặc điểm của một lịch, chẳng hạn như tên lịch, tên hiển thị, thiết đặt hiển thị, và lịch có được đồng bộ hay không. Nếu so sánh, một trình điều hợp đồng bộ có thể truy cập không chỉ những cột đó, mà còn nhiều cột khác, chẳng hạn như màu lịch, múi giờ, mức truy nhập, địa điểm, v.v. -Tuy nhiên, trình điều hợp đồng bộ bị hạn chế đối với ACCOUNT_NAME và +Tuy nhiên, trình điều hợp đồng bộ bị hạn chế đối với ACCOUNT_NAMEACCOUNT_TYPE mà nó quy định.

    Sau đây là một phương pháp hữu ích hơn mà bạn có thể sử dụng để trả về một URI để dùng với một trình điều hợp đồng bộ:

    @@ -1180,5 +1180,5 @@ Tuy nhiên, trình điều hợp đồng bộ bị hạn chế đối với -

    Để biết việc triển khai mẫu trình điều hợp đồng bộ (không liên quan cụ thể tới Lịch), hãy xem phần +

    Để biết việc triển khai mẫu trình điều hợp đồng bộ (không liên quan cụ thể tới Lịch), hãy xem phần SampleSyncAdapter. diff --git a/docs/html-intl/intl/vi/guide/topics/providers/contacts-provider.jd b/docs/html-intl/intl/vi/guide/topics/providers/contacts-provider.jd index 2fa2ed3c9bdf9ecc1e500828d93d15b032d7b45b..2d94e10c7ab8afd33de9e87530485de0c8c2ca2b 100644 --- a/docs/html-intl/intl/vi/guide/topics/providers/contacts-provider.jd +++ b/docs/html-intl/intl/vi/guide/topics/providers/contacts-provider.jd @@ -253,7 +253,7 @@ page.title=Trình cung cấp Danh bạ Ví dụ, nếu bạn muốn ứng dụng của mình duy trì dữ liệu danh bạ cho dịch vụ dựa trên nền web của mình với miền {@code com.example.dataservice}, và tài khoản của người dùng cho dịch vụ của bạn là {@code becky.sharp@dataservice.example.com}, trước tiên, người dùng phải thêm - "loại" tài khoản ({@code com.example.dataservice}) và "tên" tài khoản + "loại" tài khoản ({@code com.example.dataservice}) và "tên" tài khoản ({@code becky.smart@dataservice.example.com}) trước khi ứng dụng của bạn có thể thêm hàng liên lạc thô. Bạn có thể giải thích yêu cầu này với người dùng bằng tài liệu, hoặc bạn có thể nhắc người dùng thêm loại và tên này, hoặc cả hai. Loại tài khoản và tên tài khoản @@ -1697,7 +1697,7 @@ startActivity(insertIntent);

    Nếu dịch vụ chấp nhận thông tin xác thực, trình xác thực có thể lưu giữ thông tin xác thực đó để sử dụng sau. Vì khuôn khổ trình xác thực bổ trợ, - {@link android.accounts.AccountManager} có thể cung cấp quyền truy cập bất kỳ token xác thực nào mà một trình xác thực + {@link android.accounts.AccountManager} có thể cung cấp quyền truy cập bất kỳ token xác thực nào mà một trình xác thực hỗ trợ và chọn hiện ra, chẳng hạn như token xác thực OAuth2.

    @@ -1821,7 +1821,7 @@ mà cung cấp dữ liệu cụ thể cho

    Dữ liệu từ Luồng Xã hội

    - Các bảng {@code android.provider.ContactsContract.StreamItems} và + Các bảng {@code android.provider.ContactsContract.StreamItems} và {@code android.provider.ContactsContract.StreamItemPhotos} quản lý dữ liệu đến từ các mạng xã hội. Bạn có thể ghi một trình điều hợp đồng bộ mà thêm dữ liệu luồng từ mạng của chính mình vào những bảng này, hoặc bạn có thể đọc dữ liệu luồng từ những bảng này và @@ -1830,7 +1830,7 @@ mà cung cấp dữ liệu cụ thể cho

    Văn bản từ luồng xã hội

    - Các mục dòng dữ liệu luôn được liên kết với một liên lạc thô. + Các mục dòng dữ liệu luôn được liên kết với một liên lạc thô. {@code android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID} liên kết với giá trị _ID của liên lạc thô mới. Loại tài khoản và tên tài khoản của liên lạc thô cũng được lưu giữ trong hàng mục dòng. @@ -1934,7 +1934,7 @@ mà cung cấp dữ liệu cụ thể cho Cột này có sẵn để tương thích ngược với các phiên bản trước của Trình cung cấp Danh bạ mà đã sử dụng nó để lưu giữ ảnh. Tuy nhiên, trong phiên bản hiện tại bạn không nên sử dụng cột này để lưu giữ ảnh. Thay vào đó, hãy sử dụng - hoặc {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} hoặc + hoặc {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID} hoặc {@code android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI} (cả hai đều được mô tả trong các điểm sau) để lưu giữ ảnh trong một tệp. Lúc này, cột này chứa một hình thu nhỏ của ảnh sẵn sàng để đọc. @@ -2344,7 +2344,7 @@ mà cung cấp dữ liệu cụ thể cho việc truy xuất thông tin ảnh. Không có lớp thuận tiện cho việc truy xuất hình thu nhỏ chính đối với một liên lạc thô, nhưng bạn có thể gửi một truy vấn tới bảng {@link android.provider.ContactsContract.Data}, chọn - {@code android.provider.BaseColumns#_ID} của liên lạc thô, + {@code android.provider.BaseColumns#_ID} của liên lạc thô, {@link android.provider.ContactsContract.CommonDataKinds.Photo#CONTENT_ITEM_TYPE Photo.CONTENT_ITEM_TYPE}, và cột {@link android.provider.ContactsContract.Data#IS_PRIMARY} để tìm hàng ảnh chính của liên lạc thô. diff --git a/docs/html-intl/intl/vi/guide/topics/providers/content-provider-basics.jd b/docs/html-intl/intl/vi/guide/topics/providers/content-provider-basics.jd index 5f868cacf5aea33b0b795e2e405cfa7de0c01a12..808c0f712a34a44919e7da576ad1104f73408b07 100644 --- a/docs/html-intl/intl/vi/guide/topics/providers/content-provider-basics.jd +++ b/docs/html-intl/intl/vi/guide/topics/providers/content-provider-basics.jd @@ -236,7 +236,7 @@ page.title=Nội dung Cơ bản về Trình cung cấp Nội dung Ví dụ, để có một danh sách các từ và nội dung bản địa của chúng từ Trình cung cấp Từ điển Người dùng, bạn hãy gọi {@link android.content.ContentResolver#query ContentResolver.query()}. Phương pháp {@link android.content.ContentResolver#query query()} sẽ gọi phương pháp - {@link android.content.ContentProvider#query ContentProvider.query()} được định nghĩa bởi + {@link android.content.ContentProvider#query ContentProvider.query()} được định nghĩa bởi Trình cung cấp Từ điển Người dùng. Các dòng mã sau thể hiện một lệnh gọi {@link android.content.ContentResolver#query ContentResolver.query()}:

    @@ -251,7 +251,7 @@ mCursor = getContentResolver().query(

    Bảng 2 cho biết các tham đối tới - {@link android.content.ContentResolver#query + {@link android.content.ContentResolver#query query(Uri,projection,selection,selectionArgs,sortOrder)} khớp với một câu lệnh SQL SELECT như thế nào:

    @@ -292,7 +292,7 @@ mCursor = getContentResolver().query( sortOrder ORDER BY col,col,... - sortOrder quy định thứ tự các hàng xuất hiện trong + sortOrder quy định thứ tự các hàng xuất hiện trong {@link android.database.Cursor} được trả về. @@ -344,7 +344,7 @@ Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

    Lưu ý: Các lớp {@link android.net.Uri} và {@link android.net.Uri.Builder} - chứa các phương pháp thuận tiện để xây dựng đối tượng URI định dạng tốt từ các xâu. + chứa các phương pháp thuận tiện để xây dựng đối tượng URI định dạng tốt từ các xâu. {@link android.content.ContentUris} chứa các phương pháp thuận tiện để nối các giá trị id với một URI. Đoạn mã HTML trước sử dụng {@link android.content.ContentUris#withAppendedId withAppendedId()} để nối một id với URI nội dung Từ điển Người dùng. @@ -359,8 +359,8 @@ withAppendedId()} để nối một id với URI nội dung Từ điển Ngườ

    Để giải thích rõ, đoạn mã HTML trong phần này gọi - {@link android.content.ContentResolver#query ContentResolver.query()} trên "luồng UI"". Tuy nhiên, trong - mã thực sự, bạn nên thực hiện các truy vấn không đồng bộ trên một luồng riêng. Một cách để làm + {@link android.content.ContentResolver#query ContentResolver.query()} trên "luồng UI"". Tuy nhiên, trong + mã thực sự, bạn nên thực hiện các truy vấn không đồng bộ trên một luồng riêng. Một cách để làm điều này đó là sử dụng lớp {@link android.content.CursorLoader}, nó được mô tả chi tiết hơn trong hướng dẫn Trình tải. Bênh cạnh đó, các dòng mã chỉ là đoạn mã HTML; chúng không thể hiện một ứng dụng @@ -428,7 +428,7 @@ String[] mSelectionArgs = {""};

    Đoạn mã HTML tiếp theo cho biết cách sử dụng {@link android.content.ContentResolver#query ContentResolver.query()}, bằng cách sử dụng Trình cung cấp Từ điển - Người dùng như một ví dụ. Truy vấn máy khách trình cung cấp tương tự như một truy vấn SQL, và nó chứa một + Người dùng như một ví dụ. Truy vấn máy khách trình cung cấp tương tự như một truy vấn SQL, và nó chứa một tập hợp các cột để trả về, một tập hợp các tiêu chí lựa chọn, và một thứ tự sắp xếp.

    @@ -438,8 +438,8 @@ String[] mSelectionArgs = {""};

    Biểu thức để chỉ định các hàng cần truy xuất sẽ được chia thành một mệnh đề lựa chọn và tham đối lựa chọn. Mệnh đề lựa chọn là sự kết hợp giữa các biểu thức lô-gic và biểu thức Boolean, - tên cột, và giá trị (biến mSelectionClause). Nếu bạn chỉ định - tham số thay thế được ? thay vì một giá trị, phương pháp truy vấn sẽ truy xuất giá trị + tên cột, và giá trị (biến mSelectionClause). Nếu bạn chỉ định + tham số thay thế được ? thay vì một giá trị, phương pháp truy vấn sẽ truy xuất giá trị từ mảng tham đối lựa chọn (biến mSelectionArgs).

    @@ -565,14 +565,14 @@ selectionArgs[0] = mUserInput;

    Hiển thị các kết quả truy vấn

    - Phương pháp máy khách {@link android.content.ContentResolver#query ContentResolver.query()} luôn trả về - một {@link android.database.Cursor} chứa các cột được chỉ định bởi dự thảo của - truy vấn cho các hàng khớp với các tiêu chí lựa chọn của truy vấn. Một đối tượng - {@link android.database.Cursor} cung cấp truy cập đọc ngẫu nhiên vào các hàng và cột mà nó - chứa. Bằng cách sử dụng phương pháp {@link android.database.Cursor}, bạn có thể lặp lại các hàng trong + Phương pháp máy khách {@link android.content.ContentResolver#query ContentResolver.query()} luôn trả về + một {@link android.database.Cursor} chứa các cột được chỉ định bởi dự thảo của + truy vấn cho các hàng khớp với các tiêu chí lựa chọn của truy vấn. Một đối tượng + {@link android.database.Cursor} cung cấp truy cập đọc ngẫu nhiên vào các hàng và cột mà nó + chứa. Bằng cách sử dụng phương pháp {@link android.database.Cursor}, bạn có thể lặp lại các hàng trong kết quả, xác định kiểu dữ liệu của từng cột, lấy dữ liệu ra khỏi cột, và kiểm tra các tính chất khác - của kết quả. Một số triển khai {@link android.database.Cursor} sẽ tự động - cập nhật đối tượng khi dữ liệu của trình cung cấp thay đổi, hoặc kích khởi các phương pháp trong một đối tượng quan sát + của kết quả. Một số triển khai {@link android.database.Cursor} sẽ tự động + cập nhật đối tượng khi dữ liệu của trình cung cấp thay đổi, hoặc kích khởi các phương pháp trong một đối tượng quan sát khi {@link android.database.Cursor} thay đổi, hoặc cả hai.

    @@ -703,14 +703,14 @@ if (mCursor != null) {

    Để nhận các quyền cần để truy cập một trình cung cấp, ứng dụng yêu cầu chúng bằng một phần tử <uses-permission> - trong tệp bản kê khai của nó. Khi Trình quản lý Gói Android cài đặt các ứng dụng, người dùng + trong tệp bản kê khai của nó. Khi Trình quản lý Gói Android cài đặt các ứng dụng, người dùng phải phê chuẩn tất cả quyền mà ứng dụng yêu cầu. Nếu người dùng phê chuẩn tất cả quyền, khi đó Trình quản lý Gói sẽ tiếp tục cài đặt; nếu người dùng không phê chuẩn chúng, Trình quản lý Gói sẽ hủy bỏ việc cài đặt.

    Phần tử -<uses-permission> +<uses-permission> sau yêu cầu quyền truy cập đọc vào Trình cung cấp Từ điển Người dùng:

    @@ -793,8 +793,8 @@ content://user_dictionary/words/<id_value>
         Để cập nhật một hàng, bạn sử dụng một đối tượng {@link android.content.ContentValues} với các giá trị
         được cập nhật giống như cách bạn làm với việc chèn, và các tiêu chí lựa chọn giống như cách bạn làm với truy vấn.
         Phương pháp máy khách mà bạn sử dụng là
    -    {@link android.content.ContentResolver#update ContentResolver.update()}. Bạn chỉ cần thêm 
    -    các giá trị vào đối tượng {@link android.content.ContentValues} cho các cột mà bạn đang cập nhật. Nếu bạn 
    +    {@link android.content.ContentResolver#update ContentResolver.update()}. Bạn chỉ cần thêm
    +    các giá trị vào đối tượng {@link android.content.ContentValues} cho các cột mà bạn đang cập nhật. Nếu bạn
         muốn xóa các nội dung của một cột, hãy đặt giá trị thành null.
     

    @@ -828,7 +828,7 @@ mRowsUpdated = getContentResolver().update(

    Bạn cũng nên thanh lọc thông tin đầu vào của người dùng khi gọi - {@link android.content.ContentResolver#update ContentResolver.update()}. Để tìm hiểu thêm về + {@link android.content.ContentResolver#update ContentResolver.update()}. Để tìm hiểu thêm về điều này, hãy đọc phần Bảo vệ trước mục nhập độc hại.

    Xóa dữ liệu

    @@ -858,7 +858,7 @@ mRowsDeleted = getContentResolver().delete(

    Bạn cũng nên thanh lọc thông tin đầu vào của người dùng khi gọi - {@link android.content.ContentResolver#delete ContentResolver.delete()}. Để tìm hiểu thêm về + {@link android.content.ContentResolver#delete ContentResolver.delete()}. Để tìm hiểu thêm về điều này, hãy đọc phần Bảo vệ trước mục nhập độc hại.

    @@ -929,7 +929,7 @@ mRowsDeleted = getContentResolver().delete(
  • Truy cập dữ liệu thông qua ý định: Mặc dù không thể gửi một ý định - trực tiếp tới một trình cung cấp, bạn có thể gửi một ý định tới ứng dụng của trình cung cấp đó, + trực tiếp tới một trình cung cấp, bạn có thể gửi một ý định tới ứng dụng của trình cung cấp đó, đây thường là cách tốt nhất để sửa đổi dữ liệu của trình cung cấp.
  • @@ -947,14 +947,14 @@ mRowsDeleted = getContentResolver().delete( bạn tạo một mảng đối tượng {@link android.content.ContentProviderOperation} rồi phân phối chúng tới một trình cung cấp nội dung bằng {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. Bạn chuyển - quyền của trình cung cấp nội dung cho phương pháp này thay vì một URI nội dung cụ thể. + quyền của trình cung cấp nội dung cho phương pháp này thay vì một URI nội dung cụ thể. Điều này cho phép đối tượng {@link android.content.ContentProviderOperation} trong mảng có tác dụng đối với một bảng khác. Một lệnh gọi tới {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()} trả về một mảng kết quả.

    Mô tả lớp hợp đồng {@link android.provider.ContactsContract.RawContacts} - bao gồm một đoạn mã HTML thể hiện việc chèn hàng loạt. Ứng dụng mẫu + bao gồm một đoạn mã HTML thể hiện việc chèn hàng loạt. Ứng dụng mẫu Trình quản lý Danh bạ có một ví dụ về truy cập hàng loạt trong tệp nguồn ContactAdder.java của nó. @@ -1053,7 +1053,7 @@ mRowsDeleted = getContentResolver().delete( trả kiểm soát về ứng dụng của bạn.

  • - Hoạt động của bạn trả về tiền cảnh, và hệ thống sẽ gọi phương pháp + Hoạt động của bạn trả về tiền cảnh, và hệ thống sẽ gọi phương pháp {@link android.app.Activity#onActivityResult onActivityResult()} của hoạt động của bạn. Phương pháp này nhận được ý định kết quả do hoạt động lựa chọn tạo trong ứng dụng Danh bạ. diff --git a/docs/html-intl/intl/vi/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/vi/guide/topics/providers/content-provider-creating.jd index 2e8579a1e92eff57d75cc3cc8e37f3457f6de54f..fcc9b0eb60ef01a6e7aec80eda21a9e4092f79bf 100644 --- a/docs/html-intl/intl/vi/guide/topics/providers/content-provider-creating.jd +++ b/docs/html-intl/intl/vi/guide/topics/providers/content-provider-creating.jd @@ -221,7 +221,7 @@ page.title=Tạo một Trình cung cấp Nội dung có một trình cung cấp cho phép kết hợp dữ liệu bảng và các tệp.
  • - Để làm việc với dữ liệu trên nền mạng, hãy sử dụng các lớp trong {@link java.net} và + Để làm việc với dữ liệu trên nền mạng, hãy sử dụng các lớp trong {@link java.net} và {@link android.net}. Bạn cũng có thể đồng bộ hoá dữ liệu trên nền mạng với một kho lưu trữ dữ liệu cục bộ chẳng hạn như một cơ sở dữ liệu, rồi cung cấp dữ liệu dưới dạng bảng hoặc tệp. Ứng dụng mẫu @@ -381,7 +381,7 @@ page.title=Tạo một Trình cung cấp Nội dung
    Khớp với một URI nội dung cho các bảng dataset1 - và dataset2, nhưng không khớp với URI nội dung cho table1 hoặc + và dataset2, nhưng không khớp với URI nội dung cho table1 hoặc table3.
    @@ -614,7 +614,7 @@ public class ExampleProvider extends ContentProvider {

    Triển khai phương pháp delete()

    - Phương pháp {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} + Phương pháp {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} không cần phải xóa hàng thực chất khỏi kho lưu trữ dữ liệu của bạn. Nếu bạn đang sử dụng một trình điều hợp đồng bộ với trình cung cấp của mình, bạn nên cân nhắc đánh dấu một hàng đã xóa bằng cờ "xóa" thay vì gỡ bỏ hàng một cách hoàn toàn. Trình điều hợp đồng bộ có thể @@ -626,7 +626,7 @@ public class ExampleProvider extends ContentProvider { update()} lấy cùng tham đối {@link android.content.ContentValues} được sử dụng bởi {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()}, và cùng tham đối selectionselectionArgs được sử dụng bởi - {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} và + {@link android.content.ContentProvider#delete(Uri, String, String[]) delete()} và {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) ContentProvider.query()}. Điều này có thể cho phép bạn sử dụng lại mã giữa những phương pháp này.

    diff --git a/docs/html-intl/intl/vi/guide/topics/providers/document-provider.jd b/docs/html-intl/intl/vi/guide/topics/providers/document-provider.jd index 30844d7c277e2639b6107ff5b2f3af0ebbd2e2f5..7948fc259409d4e683a7dfa5600f291cb1f2dca1 100644 --- a/docs/html-intl/intl/vi/guide/topics/providers/document-provider.jd +++ b/docs/html-intl/intl/vi/guide/topics/providers/document-provider.jd @@ -146,7 +146,7 @@ không thay đổi giữa các lần khởi động lại thiết bị.
  • Tài liệu có thể là một tệp mở được (có một kiểu MIME cụ thể), hoặc một -thư mục chứa các tài liệu bổ sung (có kiểu MIME +thư mục chứa các tài liệu bổ sung (có kiểu MIME {@link android.provider.DocumentsContract.Document#MIME_TYPE_DIR}).
  • Mỗi tài liệu có thể có các khả năng khác nhau như được mô tả bởi @@ -177,7 +177,7 @@ có thể sử dụng kho lưu trữ đám mây dựa trên tag cho dữ liệu trực tiếp với nhau. Một máy khách yêu cầu quyền để tương tác với tệp (cụ thể là quyền đọc, chỉnh sửa, tạo hoặc xóa tệp).
  • -
  • Tương tác bắt đầu khi một ứng dụng (trong ví dụ này này một ứng dụng ảnh) thể hiện ý định +
  • Tương tác bắt đầu khi một ứng dụng (trong ví dụ này này một ứng dụng ảnh) thể hiện ý định {@link android.content.Intent#ACTION_OPEN_DOCUMENT} hoặc {@link android.content.Intent#ACTION_CREATE_DOCUMENT}. Ý định có thể bao gồm các bộ lọc để cụ thể hơn các tiêu chí—ví dụ, "cấp cho tôi tất cả tệp mở được có kiểu MIME là 'image'."
  • diff --git a/docs/html-intl/intl/vi/guide/topics/resources/accessing-resources.jd b/docs/html-intl/intl/vi/guide/topics/resources/accessing-resources.jd index b5491dcdee2c8d6fca3e1c96f0c7d3dc5d6bd81f..0054562cde1a49d4c94140a9ef97e43a3369b2db 100644 --- a/docs/html-intl/intl/vi/guide/topics/resources/accessing-resources.jd +++ b/docs/html-intl/intl/vi/guide/topics/resources/accessing-resources.jd @@ -259,8 +259,8 @@ tham chiếu một tài nguyên hệ thống, bạn sẽ cần đưa vào tên g android:text="@string/hello" /> -

    Lưu ý: Bạn nên sử dụng các tài nguyên xâu -vào mọi lúc, để ứng dụng của bạn có thể được bản địa hóa cho các ngôn ngữ khác. +

    Lưu ý: Bạn nên sử dụng các tài nguyên xâu +vào mọi lúc, để ứng dụng của bạn có thể được bản địa hóa cho các ngôn ngữ khác. Để biết thông tin về việc tạo các tài nguyên thay thế (chẳng hạn như xâu được bản địa hóa), hãy xem phần Cung cấp Tài nguyên Thay thế. Để được hướng dẫn đầy đủ về việc bản địa hóa ứng dụng của bạn cho các ngôn ngữ khác, diff --git a/docs/html-intl/intl/vi/guide/topics/resources/providing-resources.jd b/docs/html-intl/intl/vi/guide/topics/resources/providing-resources.jd index b733643e75cd21fedb069846678809b8eb85e26f..ef1c6b6d4c7732b0451f3e0e8db5f1b3ce1af060 100644 --- a/docs/html-intl/intl/vi/guide/topics/resources/providing-resources.jd +++ b/docs/html-intl/intl/vi/guide/topics/resources/providing-resources.jd @@ -190,7 +190,7 @@ phải được lưu ở đây, chẳng hạn như một Chú ý: Không được lưu tệp tài nguyên trực tiếp vào trong thư mục +

    Chú ý: Không được lưu tệp tài nguyên trực tiếp vào trong thư mục {@code res/}—nó sẽ gây ra lỗi với trình biên dịch.

    Để biết thêm thông tin về các loại tài nguyên, hãy xem tài liệu Các Loại Tài nguyên.

    @@ -312,7 +312,7 @@ mã mạng di động hiện tại.

    v.v.

    Ngôn ngữ được định nghĩa bằng một mã ngôn ngữ ISO - 639-1 gồm hai chữ cái, có thể theo sau là một mã khu vực + 639-1 gồm hai chữ cái, có thể theo sau là một mã khu vực ISO 3166-1-alpha-2 dài hai chữ cái (đằng trước là "{@code r}" chữ thường).

    @@ -498,7 +498,7 @@ Nhiều Màn hình.

  • {@code xlarge}: Các màn hình lớn hơn đáng kể so với màn hình HVGA mật độ trung bình truyền thống. Kích cỡ bố trí tối thiểu đối với một màn hình siêu lớn bằng xấp xỉ 720x960 đơn vị dp. Trong hầu hết trường hợp, những thiết bị có màn hình - siêu lớn sẽ quá lớn để mang trong túi và gần như là + siêu lớn sẽ quá lớn để mang trong túi và gần như là thiết bị kiểu máy tính bảng. Được thêm trong API mức 9.
  • Lưu ý: Việc sử dụng một hạn định kích cỡ không hàm ý rằng các @@ -510,7 +510,7 @@ bất kỳ tài nguyên nào phù hợp nhất.

    ứng dụng của bạn sẽ bị lỗi vào thời gian chạy (ví dụ, nếu tất cả tài nguyên bố trí được gắn thẻ hạn định {@code xlarge} nhưng thiết bị lại có màn hình kích cỡ bình thường).

    Được thêm trong API mức 4.

    - +

    Xem Hỗ trợ Nhiều Màn hình để biết thêm thông tin.

    Xem thêm trường cấu hình {@link android.content.res.Configuration#screenLayout}, @@ -530,7 +530,7 @@ hay lớn.

  • {@code notlong}: Màn hình không dài, chẳng hạn như QVGA, HVGA và VGA
  • Được thêm trong API mức 4.

    -

    Giá trị này thuần túy được dựa trên tỷ lệ khung ảnh của màn hình (màn hình "dài" sẽ rộng hơn). Nó +

    Giá trị này thuần túy được dựa trên tỷ lệ khung ảnh của màn hình (màn hình "dài" sẽ rộng hơn). Nó không liên quan tới hướng của màn hình.

    Xem thêm trường cấu hình {@link android.content.res.Configuration#screenLayout}, ở đó cho biết màn hình có dài không.

    @@ -628,7 +628,7 @@ Mức 8
  • {@code xxhdpi}: Màn hình mật độ siêu siêu cao; xấp xỉ 480dpi. Được thêm trong API Mức 16
  • {@code xxxhdpi}: Mật độ siêu siêu siêu cao sử dụng (chỉ biểu tượng trình khởi chạy, xem - ghi chú + ghi chú trong Hỗ trợ Nhiều Màn hình); xấp xỉ 640dpi. Được thêm trong API Mức 18
  • {@code nodpi}: Loại này có thể được sử dụng cho tài nguyên bitmap mà bạn không muốn được định cỡ @@ -950,7 +950,7 @@ layout-land/} cho khổ ngang và {@code layout-port/} cho khổ dọc, hãy đ cấu hình mà bạn chưa nghĩ đến, mà còn bởi các phiên bản Android mới đôi khi thêm hạn định cấu hình mà những phiên bản cũ hơn không hỗ trợ. Nếu bạn sử dụng một hạn định tài nguyên mới, nhưng vẫn duy trì tính tương thích về mã với các phiên bản cũ hơn của Android thì khi một phiên bản cũ hơn của -Android chạy trên ứng dụng của bạn, nó sẽ bị lỗi nếu bạn không cung cấp tài nguyên mặc định, do nó +Android chạy trên ứng dụng của bạn, nó sẽ bị lỗi nếu bạn không cung cấp tài nguyên mặc định, do nó không thể sử dụng tài nguyên được đặt tên bằng hạn định mới. Ví dụ, nếu {@code minSdkVersion} của bạn được đặt bằng 4, và bạn xác định tất cả tài nguyên vẽ được của mình bằng cách sử dụng chế độ ban đêm ({@code night} hoặc {@code notnight}, đã được thêm trong API Mức 8), khi đó một thiết bị API mức 4 sẽ không thể truy cập tài nguyên vẽ được của bạn và sẽ bị lỗi. Trong trường hợp diff --git a/docs/html-intl/intl/vi/guide/topics/resources/runtime-changes.jd b/docs/html-intl/intl/vi/guide/topics/resources/runtime-changes.jd index 4a9c38ccfe6052614af5136e423ff3fced543153..328b8ec3ad8e91980d8523a1e45a5ee0b67ba130 100644 --- a/docs/html-intl/intl/vi/guide/topics/resources/runtime-changes.jd +++ b/docs/html-intl/intl/vi/guide/topics/resources/runtime-changes.jd @@ -82,12 +82,12 @@ hoạt động của mình để giữ lại các đối tượng có trạng th

    Để giữ lại các đối tượng có trạng thái trong một phân đoạn trong khi thay đổi cấu hình thời gian chạy:

      -
    1. Mở rộng lớp {@link android.app.Fragment} và khai báo các tham chiếu tới đối tượng +
    2. Mở rộng lớp {@link android.app.Fragment} và khai báo các tham chiếu tới đối tượng có trạng thái của bạn.
    3. Gọi {@link android.app.Fragment#setRetainInstance(boolean)} khi phân đoạn được tạo.
    4. Thêm phân đoạn vào hoạt động của bạn.
    5. -
    6. Sử dụng {@link android.app.FragmentManager} để truy xuất phân đoạn khi hoạt động +
    7. Sử dụng {@link android.app.FragmentManager} để truy xuất phân đoạn khi hoạt động được khởi động lại.
    @@ -125,8 +125,8 @@ rò rỉ tất cả dạng xem và tài nguyên của thực thể hoạt độn có nghĩa là ứng dụng của bạn duy trì việc lưu giữ tài nguyên và chúng không thể được thu dọn bộ nhớ rác, vì thế rất nhiều bộ nhớ có thể bị mất.)

    -

    Khi đó, hãy sử dụng {@link android.app.FragmentManager} để thêm phân đoạn vào hoạt động. -Bạn có thể thu được đối tượng dữ liệu từ phân đoạn khi hoạt động bắt đầu lại trong khi +

    Khi đó, hãy sử dụng {@link android.app.FragmentManager} để thêm phân đoạn vào hoạt động. +Bạn có thể thu được đối tượng dữ liệu từ phân đoạn khi hoạt động bắt đầu lại trong khi thay đổi cấu hình thời gian chạy. Ví dụ, định nghĩa hoạt động của bạn như sau:

    @@ -168,7 +168,7 @@ public class MyActivity extends Activity {
     

    Trong ví dụ này, {@link android.app.Activity#onCreate(Bundle) onCreate()} thêm một phân đoạn hoặc khôi phục một tham chiếu đến nó. {@link android.app.Activity#onCreate(Bundle) onCreate()} cũng lưu trữ đối tượng có trạng thái bên trong thực thể phân đoạn đó. -{@link android.app.Activity#onDestroy() onDestroy()} cập nhật đối tượng có trạng thái bên trong +{@link android.app.Activity#onDestroy() onDestroy()} cập nhật đối tượng có trạng thái bên trong thực thể phân đoạn được giữ lại.

    diff --git a/docs/html-intl/intl/vi/guide/topics/ui/controls.jd b/docs/html-intl/intl/vi/guide/topics/ui/controls.jd index 37fe81c8c73a89e06789a0fcae950f4b085f1283..eda00506d0aff39ae3fefdb436cf0245680649dc 100644 --- a/docs/html-intl/intl/vi/guide/topics/ui/controls.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/controls.jd @@ -69,7 +69,7 @@ kiểu điều khiển nhập liệu cụ thể, bạn có thể xây dựng Nút chọn một Tương tự như hộp kiểm, chỉ khác ở chỗ chỉ có thể chọn một tùy chọn trong nhóm. - {@link android.widget.RadioGroup RadioGroup} + {@link android.widget.RadioGroup RadioGroup}
    {@link android.widget.RadioButton RadioButton} diff --git a/docs/html-intl/intl/vi/guide/topics/ui/declaring-layout.jd b/docs/html-intl/intl/vi/guide/topics/ui/declaring-layout.jd index 6add812d89f7d5192356da81754c559c877d1e30..54852000a50f82a95d3a0cd6ec75479668c6af78 100644 --- a/docs/html-intl/intl/vi/guide/topics/ui/declaring-layout.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/declaring-layout.jd @@ -107,7 +107,7 @@ trong thư mục dự án res/layout/ Android của bạn để bi

    Nạp Tài nguyên XML

    -

    Khi bạn biên dịch ứng dụng của mình, từng tệp bố trí XML được biên dịch thành một tài nguyên +

    Khi bạn biên dịch ứng dụng của mình, từng tệp bố trí XML được biên dịch thành một tài nguyên {@link android.view.View}. Bạn nên nạp tài nguyên bố trí từ mã ứng dụng của mình, trong triển khai gọi lại {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} của bạn. Làm vậy bằng cách gọi {@link android.app.Activity#setContentView(int) setContentView()}, @@ -260,7 +260,7 @@ Tài nguyên Có sẵn.

    - Cặp thứ nhất được gọi là chiều rộng đo được và + Cặp thứ nhất được gọi là chiều rộng đo đượcchiều cao đo được. Những kích thước này xác định một dạng xem muốn phóng lớn bao nhiêu trong dạng xem mẹ của nó. Các kích thước đo được có thể thu được bằng cách gọi {@link android.view.View#getMeasuredWidth()} diff --git a/docs/html-intl/intl/vi/guide/topics/ui/dialogs.jd b/docs/html-intl/intl/vi/guide/topics/ui/dialogs.jd index 1fa45508ef0c384df4fec3e132a7029ec840992e..00d523014a647968b5979b5fd4a160fadb0493f8 100644 --- a/docs/html-intl/intl/vi/guide/topics/ui/dialogs.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/dialogs.jd @@ -32,7 +32,7 @@ page.tags=alertdialog,dialogfragment

  • {@link android.app.DialogFragment}
  • {@link android.app.AlertDialog}
  • - +

    Xem thêm

    1. Hướng dẫn thiết kế hộp thoại
    2. @@ -235,8 +235,8 @@ AlertDialog dialog = builder.create();

    Các phương pháp set...Button() yêu cầu một tiêu đề cho nút (được cung cấp -bởi một tài nguyên xâu) và một -{@link android.content.DialogInterface.OnClickListener} có chức năng định nghĩa hành động sẽ tiến hành +bởi một tài nguyên xâu) và một +{@link android.content.DialogInterface.OnClickListener} có chức năng định nghĩa hành động sẽ tiến hành khi người dùng nhấn nút.

    Có ba nút hành động khác nhau mà bạn có thể thêm:

    @@ -248,7 +248,7 @@ khi người dùng nhấn nút.

    Trung lập
    Bạn nên sử dụng nút này khi người dùng có thể không muốn tiếp tục với hành động, nhưng không hẳn muốn hủy bỏ. Nó nằm ở giữa nút - tích cực và tiêu cực. Ví dụ, hành động có thể là "Nhắc tôi sau."
    + tích cực và tiêu cực. Ví dụ, hành động có thể là "Nhắc tôi sau."

    Bạn chỉ có thể thêm một nút mỗi loại vào một {@link @@ -271,7 +271,7 @@ Hộp thoại có tiêu đề và danh sách.

  • Danh sách nhiều lựa chọn cố định (hộp kiểm)
  • -

    Để tạo danh sách một lựa chọn như danh sách trong hình 3, +

    Để tạo danh sách một lựa chọn như danh sách trong hình 3, hãy sử dụng phương pháp {@link android.app.AlertDialog.Builder#setItems setItems()}:

    @@ -291,7 +291,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
     
     

    Vì danh sách xuất hiện trong vùng nội dung của hộp thoại, hộp thoại không thể hiển thị cả thông báo và danh sách và bạn nên đặt một tiêu đề cho hộp thoại -bằng {@link android.app.AlertDialog.Builder#setTitle setTitle()}. +bằng {@link android.app.AlertDialog.Builder#setTitle setTitle()}. Để chỉ định các mục cho danh sách, hãy gọi {@link android.app.AlertDialog.Builder#setItems setItems()}, chuyển một mảng. Hoặc, bạn có thể chỉ định một danh sách bằng cách sử dụng {@link @@ -317,11 +317,11 @@ Danh sách nhiều mục lựa chọn.

    Thêm một danh sách nhiều lựa chọn hoặc một lựa chọn cố định

    -

    Để thêm một danh sách nhiều lựa chọn (hộp kiểm) hoặc +

    Để thêm một danh sách nhiều lựa chọn (hộp kiểm) hoặc một lựa chọn (nút chọn một), hãy sử dụng các phương pháp {@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, -DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} hoặc -{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} hoặc +{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} tương ứng.

    Ví dụ, sau đây là cách bạn có thể tạo một danh sách nhiều lựa chọn như @@ -346,7 +346,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // 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 + // Else, if the item is already in the array, remove it mSelectedItems.remove(Integer.valueOf(which)); } } @@ -373,7 +373,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

    Mặc dù cả danh sách truyền thống và danh sách có nút chọn một đều cung cấp hành động "một lựa chọn", bạn nên sử dụng {@link -android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} nếu bạn muốn cố định lựa chọn của người dùng. Cụ thể, nếu việc mở hộp thoại lại sau này báo hiệu lựa chọn hiện tại của người dùng, khi đó bạn hãy tạo một danh sách với các nút chọn một.

    @@ -442,7 +442,7 @@ bạn nên đổi họ phông thành {@code "sans-serif"} sao cho cả hai trư một kiểu phông thống nhất.

    Để bung bố trí ra trong {@link android.support.v4.app.DialogFragment} của bạn, -hãy lấy một {@link android.view.LayoutInflater} với +hãy lấy một {@link android.view.LayoutInflater} với {@link android.app.Activity#getLayoutInflater()} và gọi {@link android.view.LayoutInflater#inflate inflate()}, trong đó tham số đầu tiên là ID tài nguyên bố trí và tham số thứ hai là một dạng xem mẹ cho bố trí. @@ -470,7 +470,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { public void onClick(DialogInterface dialog, int id) { LoginDialogFragment.this.getDialog().cancel(); } - }); + }); return builder.create(); }

    @@ -505,7 +505,7 @@ giao diện mà thông qua đó, nó sẽ chuyển các sự kiện lại cho ho
     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. */
    @@ -513,10 +513,10 @@ public class NoticeDialogFragment extends DialogFragment {
             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
         @Override
         public void onAttach(Activity activity) {
    @@ -543,7 +543,7 @@ của hộp thoại thông qua triển khai giao diện {@code NoticeDialogListe
     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();
    @@ -656,7 +656,7 @@ public class CustomDialogFragment extends DialogFragment {
             // 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. */
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
    @@ -678,7 +678,7 @@ hay UI toàn màn hình, dựa vào kích cỡ màn hình:

    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"); @@ -776,7 +776,7 @@ android.support.v4.app.DialogFragment#onDismiss onDismiss()} trong {@link android.support.v4.app.DialogFragment} của mình.

    Bạn cũng có thể hủy bỏ một hộp thoại. Đây là một sự kiện đặc biệt chỉ báo người dùng -chủ ý rời khỏi hộp thoại mà không hoàn thành tác vụ. Điều này xảy ra nếu người dùng nhấn nút +chủ ý rời khỏi hộp thoại mà không hoàn thành tác vụ. Điều này xảy ra nếu người dùng nhấn nút Quay lại, chạm vào màn hình ngoài vùng hộp thoại, hoặc nếu bạn công khai gọi {@link android.app.Dialog#cancel()} trên {@link android.app.Dialog} (chẳng hạn như khi hồi đáp lại một nút "Hủy bỏ" trong hộp thoại).

    diff --git a/docs/html-intl/intl/vi/guide/topics/ui/menus.jd b/docs/html-intl/intl/vi/guide/topics/ui/menus.jd index 8e9e1c412c5a9061bd348abf807d06d0e3702216..7950907d88bb8133b2adc37b88c5999dcdc11857 100644 --- a/docs/html-intl/intl/vi/guide/topics/ui/menus.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/menus.jd @@ -83,9 +83,9 @@ không có), vì thế bạn nên chuyển sang sử dụng thanh hành động các tùy chọn khác.

    Xem phần về Tạo một Menu Tùy chọn.

    - +
    Menu ngữ cảnh và chế độ hành động theo ngữ cảnh
    - +
    Menu ngữ cảnh là một menu nổi xuất hiện khi người dùng thực hiện nhấp giữ trên một phần tử. Nó cung cấp các hành động ảnh hưởng tới nội dung hoặc khung ngữ cảnh được chọn. @@ -94,7 +94,7 @@ các mục hành động ảnh hưởng tới nội dung được chọn trong m chọn nhiều mục.

    Xem phần nói về Tạo Menu Ngữ cảnh.

    - +
    Menu bật lên
    Menu bật lên sẽ hiển thị danh sách các mục trong một danh sách thẳng đứng được neo vào dạng xem đã gọi ra menu. Nên cung cấp một phần tràn gồm các hành động liên quan tới nội dung cụ thể hoặc @@ -128,14 +128,14 @@ kích cỡ màn hình khác nhau và các cấu hình khác bằng cách tận d dự án của bạn và xây dựng menu với các phần tử sau:

    <menu>
    -
    Định nghĩa một {@link android.view.Menu}, đó là một bộ chứa các mục menu. Phần tử +
    Định nghĩa một {@link android.view.Menu}, đó là một bộ chứa các mục menu. Phần tử <menu> phải là một nút gốc cho tệp và có thể giữ một hoặc nhiều phần tử <item><group>.
    <item>
    Tạo một {@link android.view.MenuItem}, nó biểu diễn một mục đơn trong một menu. Phần tử này có thể chứa một phần tử <menu> được lồng nhau để tạo một menu con.
    - +
    <group>
    Một bộ chứa tùy chọn, vô hình cho các phần tử {@code <item>}. Nó cho phép bạn phân loại các mục menu sao cho chúng chia sẻ các tính chất như trạng thái hiện hoạt và khả năng hiển thị. Để biết thêm @@ -273,7 +273,7 @@ tính chất của chúng bằng các API {@link android.view.MenuItem}.

    Nếu bạn phát triển ứng dụng của mình cho phiên bản Android 2.3.x và thấp hơn, hệ thống gọi {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} để tạo menu tùy chọn -khi người dùng mở menu lần đầu tiên. Nếu bạn phát triển cho phiên bản Android 3.0 vào cao hơn, +khi người dùng mở menu lần đầu tiên. Nếu bạn phát triển cho phiên bản Android 3.0 vào cao hơn, hệ thống sẽ gọi {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} khi bắt đầu hoạt động để hiển thị các mục cho thanh hành động.

    @@ -346,7 +346,7 @@ trừ khi menu bị vô hiệu hóa vì lý do nào đó. Tuy nhiên, bạn ch android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} để tạo trạng thái menu ban đầu chứ không phải để thực hiện thay đổi trong vòng đời của hoạt động.

    -

    Nếu bạn muốn sửa đổi menu tùy chọn dựa trên +

    Nếu bạn muốn sửa đổi menu tùy chọn dựa trên các sự kiện xảy ra trong vòng đời của hoạt động, bạn có thể làm vậy trong phương pháp {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}. Phương pháp này chuyển cho bạn đối tượng {@link android.view.Menu} như hiện đang có để bạn có thể sửa đổi nó, @@ -363,7 +363,7 @@ trình bày trong thanh hành động. Khi một sự kiện xảy ra và bạn gọi {@link android.app.Activity#invalidateOptionsMenu invalidateOptionsMenu()} để yêu cầu hệ thống gọi {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}.

    -

    Lưu ý: +

    Lưu ý: Bạn không nên thay đổi các mục trong menu tùy chọn dựa trên {@link android.view.View} đang trong tiêu điểm. Khi ở chế độ cảm ứng (khi người dùng không sử dụng bi xoay hay d-pad), các dạng xem không thể lấy tiêu điểm, vì thế bạn không nên sử dụng tiêu điểm làm cơ sở để sửa đổi @@ -609,7 +609,7 @@ someView.setOnLongClickListener(new View.OnLongClickListener() {

    Khi bạn gọi {@link android.app.Activity#startActionMode startActionMode()}, hệ thống sẽ trả về {@link android.view.ActionMode} được tạo. Bằng cách lưu điều này trong một biến thành viên, bạn có thể -thực hiện thay đổi thanh hành động theo ngữ cảnh để hồi đáp những sự kiện khác. Trong mẫu trên, +thực hiện thay đổi thanh hành động theo ngữ cảnh để hồi đáp những sự kiện khác. Trong mẫu trên, {@link android.view.ActionMode} được sử dụng để đảm bảo rằng thực thể {@link android.view.ActionMode} không được tạo lại nếu nó đã hiện hoạt, bằng cách kiểm tra xem thành viên có rỗng không trước khi khởi động chế độ hành động.

    @@ -742,8 +742,8 @@ hiển thị một menu bật lên:

     <ImageButton
    -    android:layout_width="wrap_content" 
    -    android:layout_height="wrap_content" 
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
         android:src="@drawable/ic_overflow_holo_dark"
         android:contentDescription="@string/descr_overflow_button"
         android:onClick="showPopup" />
    @@ -1026,6 +1026,6 @@ bộ lọc ý định. Ví dụ:

    Tìm hiểu thêm về việc ghi các bộ lọc ý định trong tài liệu Ý định và Bộ lọc Ý định.

    -

    Để tham khảo một ứng dụng mẫu sử dụng kỹ thuật này, hãy xem mã mẫu +

    Để tham khảo một ứng dụng mẫu sử dụng kỹ thuật này, hãy xem mã mẫu Note Pad.

    diff --git a/docs/html-intl/intl/vi/preview/features/multi-window.jd b/docs/html-intl/intl/vi/guide/topics/ui/multi-window.jd similarity index 98% rename from docs/html-intl/intl/vi/preview/features/multi-window.jd rename to docs/html-intl/intl/vi/guide/topics/ui/multi-window.jd index 485bc284786f1e8dea2dc945f1a1142676810566..3317d1c4db46d0f64377a4ab60eacea95c9cc651 100644 --- a/docs/html-intl/intl/vi/preview/features/multi-window.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/multi-window.jd @@ -4,8 +4,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form" @jd:body -
    -
    +
    +

    Trong tài liệu này

    1. Tổng quan
    2. @@ -33,7 +33,7 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      Nếu bạn dựng ứng dụng của bạn bằng N Preview SDK, bạn có thể cấu hình cách ứng dụng của bạn - xử lý hiển thị đa cửa sổ. Ví dụ, bạn có thể quy định + xử lý hiển thị đa cửa sổ. Ví dụ, bạn có thể quy định các kích thước tối thiểu cho phép của hoạt động của bạn. Bạn cũng có thể vô hiệu hóa hiển thị đa cửa sổ cho ứng dụng của bạn, đảm bảo rằng hệ thống chỉ hiển thị ứng dụng của bạn trong chế độ toàn màn hình. @@ -68,8 +68,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form" - +

      Hình 1. Hai ứng dụng chạy trong chế độ chia màn hình.

      @@ -117,7 +117,7 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      Lưu ý: Trong chế độ đa cửa sổ, một ứng dụng có thể trong trạng thái - tạm dừng và vẫn hiển thị với người dùng. Ứng dụng có thể cần tiếp tục + tạm dừng và vẫn hiển thị với người dùng. Ứng dụng có thể cần tiếp tục các hoạt động của nó thậm chí trong khi đamg bị tạm dừng. Ví dụ, một ứng dụng phát video đang ở trong chế độ tạm dừng nhưng vẫn hiển thị thì sẽ tiếp tục hiển thị video của nó. Vì lý do này, chúng tôi đề nghị các hoạt động phát video không tạm dừng @@ -129,13 +129,13 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      Khi người dùng đặt một ứng dụng vào trong chế độ đa cửa sổ, hệ thống sẽ thông báo về - hoạt động thay đổi cấu hình đó, như được quy định trong Xử lý Thay đổi + hoạt động thay đổi cấu hình đó, như được quy định trong Xử lý Thay đổi Thời gian chạy. Về cơ bản, thay đổi này có ngụ ý về vòng đời hoạt động tương tự vì khi hệ thống thông báo cho ứng dụng rằng thiết bị đã chuyển từ chế độ hướng dọc sang chế độ ngang, ngoại trừ trường hợp các kích thước của thiết bị đã được thay đổi thay vì chỉ bị hoán đổi. Như đã thảo luận trong phần Xử lý Thay đổi Thời gian chạy, hoạt động của bạn có thể tự xử lý thay đổi cấu hình này, hoặc nó - có thể cho phép hệ thống hủy hoạt động này và tạo lại nó với + có thể cho phép hệ thống hủy hoạt động này và tạo lại nó với các kích thước mới.

      @@ -207,7 +207,7 @@ android:supportsPictureInPicture=["true" | "false"]

      Thuộc tính bố trí

      - Với Android N, phần tử bản kê khai <layout> + Với Android N, phần tử bản kê khai <layout> có hỗ trợ một số thuộc tính sẽ ảnh hưởng đến cách hoạt động có hành vi như thế nào trong chế độ đa cửa sổ:

      @@ -244,7 +244,7 @@ android:supportsPictureInPicture=["true" | "false"]
      Chiều cao và chiều rộng tối thiểu cho hoạt động trong cả chế độ chia màn hình - và chế độ hình dạng tự do. Nếu người dùng di chuyển thanh phân chia trong chế độ chia màn hình + và chế độ hình dạng tự do. Nếu người dùng di chuyển thanh phân chia trong chế độ chia màn hình để làm cho hoạt động nhỏ hơn mức tối thiểu quy định, hệ thống sẽ cắt xén hoạt động đó thành kích cỡ mà người dùng yêu cầu.
      @@ -295,7 +295,7 @@ android:supportsPictureInPicture=["true" | "false"]

      Các phương thức mới sau đây đã được thêm vào lớp {@link android.app.Activity} - để hỗ trợ hiển thị đa cửa sổ. Để biết chi tiết về mỗi phương thức, xem + để hỗ trợ hiển thị đa cửa sổ. Để biết chi tiết về mỗi phương thức, xem Tham chiếu N Preview SDK.

      @@ -560,7 +560,7 @@ android:supportsPictureInPicture=["true" | "false"]
    3. Thực hiện một vài thao tác thay đổi kích cỡ nối tiếp nhau thật nhanh. Xác minh rằng ứng dụng - của bạn không bị lỗi hoặc bị rò rỉ bộ nhớ. Để biết thông tin về kiểm tra việc sử dụng bộ nhớ của + của bạn không bị lỗi hoặc bị rò rỉ bộ nhớ. Để biết thông tin về kiểm tra việc sử dụng bộ nhớ của ứng dụng, xem Kiểm tra Sử dụng RAM của bạn.
    4. diff --git a/docs/html-intl/intl/vi/guide/topics/ui/notifiers/notifications.jd b/docs/html-intl/intl/vi/guide/topics/ui/notifiers/notifications.jd index 5890cb331b965ddb22e97cb2337a58d98bc6897d..8b6e1c8458c91dafa7749a61c070a35de484a053 100644 --- a/docs/html-intl/intl/vi/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/notifiers/notifications.jd @@ -150,7 +150,7 @@ thông báo, bạn chuyển đối tượng {@link android.app.Notification} t {@link android.app.PendingIntent} chứa một {@link android.content.Intent} có chức năng bắt đầu một {@link android.app.Activity} trong ứng dụng của bạn. Để liên kết - {@link android.app.PendingIntent} với một cử chỉ, hãy gọi phương pháp + {@link android.app.PendingIntent} với một cử chỉ, hãy gọi phương pháp {@link android.support.v4.app.NotificationCompat.Builder} phù hợp. Ví dụ, nếu bạn muốn bắt đầu {@link android.app.Activity} khi người dùng nhấp vào văn bản thông báo trong ngăn kéo thông báo, bạn hãy thêm {@link android.app.PendingIntent} bằng cách gọi @@ -449,7 +449,7 @@ numMessages = 0;
      1. Thêm hỗ trợ cho phiên bản Android 4.0.3 và trước đó. Để làm điều này, hãy quy định mẹ của - {@link android.app.Activity} mà bạn đang bắt đầu bằng cách thêm phần tử + {@link android.app.Activity} mà bạn đang bắt đầu bằng cách thêm phần tử <meta-data> làm con của <activity>. @@ -466,9 +466,9 @@ numMessages = 0;

      2. - Cũng thêm hỗ trợ cho phiên bản Android 4.1 và sau đó. Để làm điều này, hãy thêm thuộc tính + Cũng thêm hỗ trợ cho phiên bản Android 4.1 và sau đó. Để làm điều này, hãy thêm thuộc tính android:parentActivityName - vào phần tử + vào phần tử <activity> của {@link android.app.Activity} mà bạn đang bắt đầu.
      3. diff --git a/docs/html-intl/intl/vi/guide/topics/ui/overview.jd b/docs/html-intl/intl/vi/guide/topics/ui/overview.jd index 7bd45527c7b4b494d23294f69bf73ca7f7c08b6f..260b40d9e19c85f5c04ce321e28b7a4814e9c943 100644 --- a/docs/html-intl/intl/vi/guide/topics/ui/overview.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/overview.jd @@ -39,7 +39,7 @@ và một phần tử <LinearLayout> tạo ra một nhóm d
         <?xml version="1.0" encoding="utf-8"?>
         <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -              android:layout_width="fill_parent" 
        +              android:layout_width="fill_parent"
                       android:layout_height="fill_parent"
                       android:orientation="vertical" >
             <TextView android:id="@+id/text"
        @@ -60,7 +60,7 @@ bố trí.

        Để xem hướng dẫn đầy đủ về tạo bố trí UI, hãy xem phần Bố trí XML. - +

        Thành phần Giao diện Người dùng

        Bạn không phải xây dựng tất cả UI của mình bằng cách sử dụng các đối tượng {@link android.view.View} và {@link diff --git a/docs/html-intl/intl/vi/guide/topics/ui/settings.jd b/docs/html-intl/intl/vi/guide/topics/ui/settings.jd index 8e19b979d0ac180451c42f100701391fc870cdc5..47a5c27d1f087c3cca67af52c766583ac14a2f42 100644 --- a/docs/html-intl/intl/vi/guide/topics/ui/settings.jd +++ b/docs/html-intl/intl/vi/guide/topics/ui/settings.jd @@ -82,7 +82,7 @@ cách xây dựng thiết đặt ứng dụng của bạn bằng cách sử dụ

        Hình 1. Ảnh chụp màn hình từ thiết đặt của ứng dụng -Messaging trên Android. Chọn một mục được định nghĩa bởi một {@link android.preference.Preference} +Messaging trên Android. Chọn một mục được định nghĩa bởi một {@link android.preference.Preference} sẽ mở ra một giao diện để thay đổi thiết đặt.

        @@ -121,7 +121,7 @@ sau:

        Vì thiết đặt của ứng dụng của bạn được xây dựng bằng cách sử dụng các đối tượng {@link android.preference.Preference} thay vì đối tượng -{@link android.view.View}, bạn nên sử dụng một lớp con {@link android.app.Activity} hoặc +{@link android.view.View}, bạn nên sử dụng một lớp con {@link android.app.Activity} hoặc {@link android.app.Fragment} chuyên dụng để hiển thị thiết đặt danh sách:

      - +

      Note: 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 diff --git a/docs/html-intl/intl/vi/preview/download.jd b/docs/html-intl/intl/vi/preview/download.jd deleted file mode 100644 index f6aa7ccc67e9703a8190b8e4ab8770ad26984dd1..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/download.jd +++ /dev/null @@ -1,541 +0,0 @@ -page.title=Kiểm thử trên Thiết bị -meta.tags="preview", "nexus","system image" -page.tags="preview", "androidn" -page.image=images/cards/card-n-downloads_2x.png - -@jd:body - -

      - - - - -
      - - - -

      - Để chạy và kiểm thử ứng dụng của bạn trên nền tảng mới, bạn cần phải thiết lập môi trường thời gian chạy Android N -. Bạn có thể thực hiện điều đó bằng một trong các cách sau: -

      - -
        -
      • Cài đặt Android N trên một thiết bị phần cứng được hỗ trợ, hoặc
      • -
      • Thiết lập một bộ giả lập Android chạy Android N
      • -
      - -

      - Nếu bạn muốn có một môi trường để kiểm thử khả năng tương thích cơ bản của ứng dụng của bạn trên - nền tảng mới này, tất cả những gì bạn cần là APK hiện tại của bạn và một thiết bị phần cứng hoặc - bộ giả lập. Bạn không nhất thiết phải cập nhật môi trường phát triển đầy đủ - để thực hiện kiểm thử cơ bản. -

      - -

      - Nếu bạn muốn sửa đổi ứng dụng của mình để nhắm mục tiêu đến Android N hoặc sử dụng các API Android N mới, - bạn cần thiết lập một môi trường phát triển được cập nhật để hỗ trợ - Android N. Thiết lập để Phát triển dành cho - Android N có các chi tiết. -

      - - -

      Thiết lập thiết bị phần cứng

      - -

      - Bản N Developer Preview cung cấp các cập nhật hệ thống cho một loạt các thiết bị phần cứng - mà bạn có thể sử dụng để kiểm thử ứng dụng của bạn, từ điện thoại tới máy tính bảng và TV. -

      - -

      - Nếu bạn có quyền truy cập vào một thiết bị được hỗ trợ, bạn có thể cập nhật nó thành bản dựng theo mốc của Preview dành cho - Nhà phát triển bằng một trong những cách sau: -

      - -
        -
      • Đăng ký cập nhật hệ thống tự động qua vô tuyến cho thiết bị thông qua - Chương trình Android Beta. Sau khi đăng ký, thiết bị của bạn sẽ nhận được - qua sóng vô tuyến các cập nhật định kỳ về tất cả bản dựng theo mốc trong bản N Developer Preview. Cách tiếp cận này - được khuyến khích bởi nó cho phép bạn chuyển tiếp liền mạch từ môi trường hiện tại của bạn - qua nhiều bản phát hành khác nhau của N Developer Preview.
      • -
      • Tải xuống ảnh hệ thống của Developer Preview và flash thiết bị. - Các cập nhật qua vô tuyến không được cung cấp tự động cho các thiết bị mà bạn flash thủ công, nhưng - bạn có thể đăng ký Chương trình Android Beta cho các thiết bị đó để nhận cập nhật qua vô tuyến.
      • -
      - -

      Đăng ký cập nhật tự động qua vô tuyến cho thiết bị

      - -

      - Nếu bạn có quyền truy cập vào một thiết bị được hỗ trợ (xem danh sách trong bảng - Tải xuống), bạn có thể nhận được cập nhật qua sóng vô tuyến để xem trước các phiên bản của Android - bằng cách đăng ký Chương trình Android Beta cho thiết bị. Các cập nhật này được - tự động tải xuống và sẽ cập nhật thiết bị của bạn giống như các bản cập nhật - hệ thống chính thức. -

      - -

      - Bạn có thể hủy đăng ký thiết bị bất cứ lúc nào. Thiết bị sẽ nhận được bản cập nhật qua vô tuyến - của phiên bản Android sản xuất mới nhất khả dụng cho thiết bị đó - (ví dụ, Android 6.0 Marshmallow). Việc cập nhật yêu cầu phải thiết lập lại thiết bị - hoàn toàn, vì vậy dữ liệu người dùng trên thiết bị sẽ được gỡ bỏ. Hãy đảm bảo sao lưu - dữ liệu quan trọng trước khi hủy đăng ký thiết bị. -

      - -

      - Để biết thêm thông tin và đăng ký thiết bị của bạn, xem - trang web Chương trình Android Beta. -

      - -

      Lưu ý: - Việc hủy đăng ký yêu cầu phải cài đặt lại toàn bộ thiết bị. Trước hết hãy sao lưu - các dữ liệu quan trọng. -

      - -

      Flash thiết bị thủ công

      - -

      - Bất cứ lúc nào bạn cũng có thể tải xuống ảnh hệ thống mới nhất của Developer Preview và - flash thủ công nó vào thiết bị của bạn. Xem bảng dưới đây để tải xuống ảnh hệ thống - cho thiết bị kiểm thử của bạn. Việc flash thủ công thiết bị sẽ hữu ích nếu bạn cần - kiểm soát chính xác môi trường kiểm thử hoặc cần phải cài đặt lại thường xuyên, - chẳng hạn như cho kiểm thử tự động. -

      - -

      - Việc cài đặt ảnh hệ thống trên thiết bị sẽ gỡ bỏ tất cả dữ liệu khỏi - thiết bị, vì vậy trước hết bạn nên sao lưu dữ liệu của mình. -

      - -

      - Sau khi sao lưu dữ liệu thiết bị và tải xuống ảnh hệ thống bên dưới - khớp với thiết bị của bạn, hãy làm theo hướng dẫn tại developers.google.com/android - để flash ảnh này vào thiết bị của bạn. -

      - -

      - Các ảnh hệ thống được flash thủ công không - tự động nhận cập nhật qua vô tuyến cho các bản dựng theo mốc sau này của - Developer Preview. Hãy đảm bảo giữ cho môi trường của bạn được cập nhật và flash một - ảnh hệ thống mới tại mỗi mốc của Developer Preview. -

      - -

      - Nếu bạn quyết định muốn nhận cập nhật qua vô tuyến sau khi đã flash thủ công thiết bị, - tất cả những gì bạn cần làm là đăng ký Chương trình Android - Beta cho thiết bị. Bạn có thể đăng ký thiết bị bất cứ lúc nào để nhận được - bản cập nhật qua vô tuyến tiếp theo của Preview. -

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Thiết bịTải xuống / Tổng kiểm
      Nexus 5X
      "bullhead"
      bullhead-npc56p-preview-6c877a3d.tgz
      - MD5: b5cf874021023b398f5b983b24913f5d
      - SHA-1: 6c877a3d9fae7ec8a1678448e325b77b7a7b143a -
      Nexus 6
      "shamu"
      shamu-npc56p-preview-54b13c67.tgz
      - MD5: af183638cf34e0eb944a1957d7696f60
      - SHA-1: 54b13c6703d369cc79a8fd8728fe4103c6343973 -
      Nexus 6P
      "angler"
      angler-npc56p-preview-85ffc1b1.tgz
      - MD5: bc4934ea7bd325753eee1606d3725a24
      - SHA-1: 85ffc1b1be402b1b96f9ba10929e86bba6c6c588 -
      Nexus 9
      "volantis"
      volantis-npc56p-preview-0e8ec8ef.tgz
      - MD5: c901334c6158351e945f188167ae56f4
      - SHA-1: 0e8ec8ef98c7a8d4f58d15f90afc5176303efca4 -
      Nexus 9G
      "volantisg"
      volantisg-npc56p-preview-1bafdbfb.tgz
      - MD5: 7bb95bebc478d7257cccb4652899d1b4
      - SHA-1: 1bafdbfb502e979a9fe4c257a379c4c7af8a3ae6 -
      Nexus Player
      "fugu"
      fugu-npc56r-preview-7027d5b6.tgz
      - MD5: f5d3d8f75836ccfe4c70e8162e498be4
      - SHA-1: 7027d5b662bceda4c80a91a0a14ef0e5a7ba795b -
      Pixel C
      "ryu"
      ryu-npc56p-preview-335a86a4.tgz
      - MD5: 4e21fb183bbbf467bee91598d587fd2e
      - SHA-1: 335a86a435ee51f18464de343ad2e071c38f0e92 -
      General Mobile 4G (Android One)
      "seed"
      seed_l8150-npc56p-preview-82472ebc.tgz
      - MD5: 983e083bc7cd0c4a2d39d6ebaa20202a
      - SHA-1: 82472ebc9a6054a103f53cb400a1351913c95127 -
      - -

      Gỡ cài đặt Preview khỏi thiết bị

      - -

      - Nếu bạn muốn gỡ cài đặt preview khỏi thiết bị, bạn có thể thực hiện điều đó bằng một trong - những cách sau:

      -
        -
      • Lấy thông số kỹ thuật của ảnh hệ thống nguyên gốc và sau đó flash thủ công - nó cho thiết bị. -
          -
        • Đối với các thiết bị Nexus và Pixel C, xem - trang Ảnh Cài đặt Gốc - cho Thiết bị Nexus để tìm bản tải xuống.
        • -
        • Đối với các thiết bị khác, vui lòng liên hệ trực tiếp với nhà sản xuất -thiết bị. Hoặc, nếu thiết bị được hỗ trợ - trong Chương trình Android Beta, bạn có thể đăng ký - chương trình cho thiết bị và sau đó hủy đăng ký thiết bị (xem bên dưới).
        • -
        -
      • -
      • Hủy đăng ký thiết bị khỏi Chương trình Android Beta. Nếu - thiết bị được đăng ký Chương trình Android Beta - , không quan trọng là thiết bị nào, bạn có thể dễ dàng hủy đăng ký thiết bị khỏi chương trình này. -

        - Thiết bị sẽ nhận được bản cập nhật qua vô tuyến của phiên bản Android sản xuất - mới nhất có sẵn cho thiết bị đó (ví dụ, Android 6.0 Marshmallow). - Bản cập nhật yêu cầu thiết lập lại toàn bộ thiết bị, vì vậy dữ liệu người dùng trên thiết bị sẽ được - gỡ bỏ. Hãy đảm bảo rằng bạn đã sao lưu dữ liệu quan trọng trước khi - hủy đăng ký thiết bị. -

        -
      • -
      - -

      Lưu ý: - Việc gỡ cài đặt ảnh hệ thống của Developer Preview trước khi - kết thúc chương trình yêu cầu phải thiết lập lại toàn bộ thiết bị và gỡ bỏ tất cả dữ liệu người dùng - trên thiết bị. -

      - - -

      Thiết lập bộ giả lập

      - -

      Để sử dụng Bộ Giả Lập Android chạy Android N Preview, bạn cần -tải xuống Android N Preview SDK và tạo một thiết bị ảo cho -bộ giả lập.

      - -

      Đầu tiên, tải xuống Android N Preview SDK như sau (nếu bạn -đã có nó trong khi thiết lập -để phát triển dành cho Android N, bạn có thể bỏ qua phần này): - -

        -
      1. Trong Android Studio, Mở hộp thoại Settings - (File > Settings trên Windows/Linux, hoặc - Android Studio > Preferences trên Mac). Trong bảng điều khiển - bên trái, chọn Appearance & Behavior > - System Settings > Android SDK. - -
      2. Nhấp vào tab SDK Platforms, rồi chọn hộp kiểm - Android N Preview.
      3. - -
      4. Nhấp vào tab SDK Tools, rồi chọn - Android SDK Build Tools, Android SDK - Platform-Tools, và các hộp kiểm Android SDK Tools -. -
      5. - -
      6. Nhấp vào OK và chấp nhận thỏa thuận - giấy phép cho bất kỳ gói nào sẽ được cài đặt. -
      7. -
      - -

      Giờ đây bạn sẽ có Android SDK Built-Tools 24.0 0 rc1, -Platform-Tools 24.0.0 rc1, và SDK Tools -25.0.9. Nếu bạn không cập nhật Các Công cụ SDK lên 25.0.9, bạn sẽ không -thể chạy ảnh hệ thống x86_64 cho Android N.

      - - -

      Bây giờ, hãy tạo một thiết bị ảo với ảnh hệ thống Android N:

      - -
        -
      1. Mở Trình quản lý AVD bằng cách chọn Tools > Android > - AVD Manager.
      2. -
      3. Nhấp vào Create Virtual Device.
      4. -
      5. Chọn một thiết bị chẳng hạn như Nexus 5X, Nexus 6P, Nexus 9, hoặc Android TV, - rồi nhấp vào Next.
      6. -
      7. Chọn ảnh hệ thống N (với - x86 ABI), rồi nhấp vào Next. - (Hiện chỉ có ảnh hệ thống x86 được hỗ trợ với Bộ giả lập Android -dành cho Preview Android N.) -
      8. Hoàn thành các bước cấu hình AVD còn lại và nhấp vào - Finish.
      9. -
      - -

      Giờ đây bạn có thể khởi chạy Bộ giả lập Android với AVD Preview Android N.

      - -

      -Để có trải nghiệm tốt nhất trong Bộ giả lập Android, hãy cài đặt -Android Studio 2.1 Preview, có hỗ trợ Bộ giả lập Android 2.0 Beta -với hiệu suất nhanh hơn nhiều so với Bộ giả lập trong -Android Studio 1.5.

      - -

      Lưu ý: - Nếu bạn hiện đang sử dụng Android Studio 2.0 Beta, một vấn đề đã được biết đến - sẽ ngăn cản bạn tạo AVD bằng ảnh hệ thống của N Preview, vì vậy - hiện bạn cần sử dụng preview của Android Studio 2.1 để tạo các AVD. -

      - -

      Để biết thêm thông tin về tạo thiết bị ảo, hãy xem Quản lý Thiết bị ảo. -

      - - - - - - - - - - - - - - -
      - -
      - - - - diff --git a/docs/html-intl/intl/vi/preview/features/background-optimization.jd b/docs/html-intl/intl/vi/preview/features/background-optimization.jd deleted file mode 100644 index 9554725f25a3bee9b2628ab1d9d4e8ee7a953503..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/features/background-optimization.jd +++ /dev/null @@ -1,390 +0,0 @@ -page.title=Tối ưu hóa Chạy ngầm -page.metaDescription=Các hạn chế mới đối với truyền phát không biểu thị. -page.keywords="android N", "implicit broadcasts", "job scheduler" -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

      - Các tiến trình chạy ngầm có thể tiêu tốn bộ nhớ và pin. Ví dụ, một - truyền phát không biểu thị có thể bắt đầu nhiều tiến trình chạy ngầm đã đăng ký - để theo dõi chúng, ngay cả khi các tiến trình đó có thể không làm việc nhiều. Điều này có thể có - ảnh hưởng lớn đến cả hiệu suất của thiết bị lẫn trải nghiệm của người dùng. -

      - -

      - Để loại bỏ vấn đề này, N Developer Preview áp dụng các hạn chế - sau: -

      - -
        -
      • Các ứng dụng nhắm đến Preview không nhận được truyền phát {@link - android.net.ConnectivityManager#CONNECTIVITY_ACTION} nếu chúng - đăng ký nhận truyền phát trong bản kê khai của chúng. Các ứng dụng đang chạy ở tiền cảnh - vẫn có thể theo dõi {@code CONNECTIVITY_CHANGE} trên luồng chính của chúng bằng cách - đăng ký{@link android.content.BroadcastReceiver} với {@link - android.content.Context#registerReceiver Context.registerReceiver()}. -
      • - -
      • Ứng dụng không thể gửi hoặc nhận các truyền phát {@link - android.hardware.Camera#ACTION_NEW_PICTURE} hoặc {@link - android.hardware.Camera#ACTION_NEW_VIDEO}. Việc tối ưu này - tác động đến mọi ứng dụng, không chỉ các ứng dụng nhắm đến Preview. -
      • -
      - -

      - Khuôn khổ Android cung cấp một số giải pháp để giảm thiểu sự cần thiết đối với - các truyền phát không biểu thị. Ví dụ, {@link android.app.job.JobScheduler} - và - {@code GcmNetworkManager} cung cấp một cơ chế lên lịch hiệu quả - cho các hoạt động mạng khi đáp ứng các điều kiện được chỉ định, ví dụ như kết nối tới mạng - không đo lưu lượng. Bây giờ bạn cũng có thể sử dụng {@link android.app.job.JobScheduler} - để phản ứng lại với các thay đổi đối với các trình cung cấp nội dung. Các đối tượng {@link android.app.job.JobInfo} - gói gọn các tham số {@link android.app.job.JobScheduler} - dùng để lên lịch tác vụ của bạn. Khi đáp ứng được các điều kiện của tác vụ, hệ thống - sẽ thực thi tác vụ này trên {@link android.app.job.JobService} của ứng dụng của bạn. -

      - -

      - Trong tài liệu này, chúng ta sẽ tìm hiểu cách sử dụng các phương thức thay thế, chẳng hạn như - {@link android.app.job.JobScheduler}, để thích ứng ứng dụng của bạn với các hạn chế - mới này. -

      - -

      - Các hạn chế về CONNECTIVITY_ACTION -

      - -

      - Các ứng dụng nhắm đến N Developer Preview không nhận được truyền phát {@link - android.net.ConnectivityManager#CONNECTIVITY_ACTION} nếu chúng - đăng ký nhận truyền phát trong bản kê khai của chúng, và các tiến trình phụ thuộc vào truyền phát này - sẽ không khởi động. Điều này cũng đặt ra một vấn đề cho ứng dụng - về việc theo dõi thay đổi mạng hoặc thực hiện các hoạt động mạng hàng loạt khi - thiết bị kết nối với một mạng không đo lưu lượng. Một số giải pháp để tránh khỏi hạn chế này - đã tồn tại trong khuôn khổ Android, nhưng chọn được một giải pháp phù hợp - phụ thuộc vào những gì bạn muốn ứng dụng của bạn hoàn thành. -

      - -

      - Lưu ý: Một{@link android.content.BroadcastReceiver} có đăng ký - {@link android.content.Context#registerReceiver Context.registerReceiver()} - tiếp tục nhận các truyền phát này trong khi ứng dụng đang ở tiền cảnh. -

      - -

      - Lên lịch Tác vụ Mạng trên Kết nối Không đo lưu lượng -

      - -

      - Khi sử dụng lớp{@link android.app.job.JobInfo.Builder JobInfo.Builder} - để xây dựng đối tượng {@link android.app.job.JobInfo} của bạn, hãy áp dụng phương thức {@link - android.app.job.JobInfo.Builder#setRequiredNetworkType - setRequiredNetworkType()} và chuyển {@link android.app.job.JobInfo - JobInfo.NETWORK_TYPE_UNMETERED} dưới dạng một tham số tác vụ. Đoạn mã mẫu sau - lên lịch một dịch vụ để chạy khi thiết bị kết nối với một mạng - không đo lưu lượng và đang sạc: -

      - -
      -public static final int MY_BACKGROUND_JOB = 0;
      -...
      -public static void scheduleJob(Context context) {
      -  JobScheduler js =
      -      (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
      -  JobInfo job = new JobInfo.Builder(
      -    MY_BACKGROUND_JOB,
      -    new ComponentName(context, MyJobService.class))
      -      .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
      -      .setRequiresCharging(true)
      -      .build();
      -  js.schedule(job);
      -}
      -
      - -

      - Khi các điều kiện cho tác vụ của bạn đã được đáp ứng, ứng dụng của bạn sẽ nhận được lệnh gọi lại để chạy - phương thức{@link android.app.job.JobService#onStartJob onStartJob()}trong - {@code JobService.class} được chỉ định. Để xem thêm các ví dụ về triển khai {@link - android.app.job.JobScheduler} , hãy xem ứng dụng mẫu JobScheduler. -

      - -

      - Các ứng dụng sử dụng dịch vụ GMSCore, và nhắm đến Android 5.0 (API mức 21) - hoặc thấp hơn, có thể sử dụng - {@code GcmNetworkManager} và quy định {@code Task.NETWORK_STATE_UNMETERED}. -

      - -

      - Theo dõi Kết nối Mạng Trong khi Ứng dụng đang Chạy -

      - -

      - Các ứng dụng đang chạy ở tiền cảnh vẫn có thể theo dõi {@code - CONNECTIVITY_CHANGE} bằng một{@link - android.content.BroadcastReceiver} đã đăng ký. Tuy nhiên, API {@link - android.net.ConnectivityManager} cung cấp phương thức yêu cầu lệnh gọi lại hiệu quả hơn - chỉ khi đáp ứng được các điều kiện được chỉ định. -

      - -

      - Các đối tượng {@link android.net.NetworkRequest} định nghĩa các tham số của - lệnh gọi lại mạng xét về {@link android.net.NetworkCapabilities}. Bạn - tạo các đối tượng {@link android.net.NetworkRequest} bằng lớp {@link - android.net.NetworkRequest.Builder NetworkRequest.Builder}. {@link - android.net.ConnectivityManager#registerNetworkCallback(android.net.NetworkRequest, - android.net.ConnectivityManager.NetworkCallback) registerNetworkCallback()} - rồi chuyển đối tượng{@link android.net.NetworkRequest} sang hệ thống. Khi - đáp ứng được các điều kiện mạng, ứng dụng nhận lệnh gọi lại để thực thi phương thức - {@link android.net.ConnectivityManager.NetworkCallback#onAvailable - onAvailable()} như được định nghĩa trong lớp {@link - android.net.ConnectivityManager.NetworkCallback} của nó. -

      - -

      - Ứng dụng tiếp tục nhận lệnh gọi lại cho đến khi ứng dụng tồn tại hoặc nó gọi - {@link android.net.ConnectivityManager#unregisterNetworkCallback - unregisterNetworkCallback()}. -

      - -

      - Các hạn chế về NEW_PICTURE và NEW_VIDEO -

      - -

      - Trong N Developer Preview, ứng dụng không thể gửi hoặc nhận các truyền phát {@link - android.hardware.Camera#ACTION_NEW_PICTURE} hoặc {@link - android.hardware.Camera#ACTION_NEW_VIDEO}. Hạn chế này giúp - loại bỏ các tác động về hiệu suất và trải nghiệm của người dùng khi một số ứng dụng phải - thức dậy để xử lý một ảnh hoặc video mới. N Developer Preview - mở rộng {@link android.app.job.JobInfo} và {@link - android.app.job.JobParameters} để cung cấp một giải pháp thay thế. -

      - -

      - Các phương thức JobInfo Mới -

      - -

      - Để kích hoạt tác vụ khi thay đổi URI nội dung, N Developer Preview sẽ mở rộng - API{@link android.app.job.JobInfo} bằng các phương thức sau: -

      - -
      -
      - {@code JobInfo.TriggerContentUri()} -
      - -
      - Gói gọn các tham số yêu cầu để kích hoạt tác vụ khi thay đổi URI nội dung. -
      - -
      - {@code JobInfo.Builder.addTriggerContentUri()} -
      - -
      - Chuyển một đối tượng {@code TriggerContentUri} đến {@link - android.app.job.JobInfo}. Một {@link android.database.ContentObserver} - sẽ theo dõi URI nội dung được gói gọn. Nếu có nhiều đối tượng {@code - TriggerContentUri} được liên kết với một tác vụ, hệ thống sẽ cung cấp - lệnh gọi lại ngay cả khi hệ thống báo cáo có sự thay đổi chỉ ở trong một trong những URI nội dung. -
      - -
      - Thêm cờ {@code TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS} để - kích hoạt tác vụ nếu bất kỳ kế nhiệm nào của URI đã cho thay đổi. Cờ này - tương ứng với tham số {@code notifyForDescendants} đã chuyển đến {@link - android.content.ContentResolver#registerContentObserver - registerContentObserver()}. -
      -
      - -

      - Lưu ý: {@code TriggerContentUri()} không thể được sử dụng - kết hợp với {@link android.app.job.JobInfo.Builder#setPeriodic - setPeriodic()} hoặc {@link android.app.job.JobInfo.Builder#setPersisted - setPersisted()}. Để tiếp tục theo dõi các thay đổi nội dung, hãy lên lịch một - {@link android.app.job.JobInfo} mới trước khi {@link - android.app.job.JobService} của ứng dụng hoàn thành xử lý lệnh gọi lại gần đây nhất. -

      - -

      - Đoạn mã mẫu sau lên lịch kích hoạt một tác vụ khi hệ thống báo cáo - có sự thay đổi về URI nội dung, {@code MEDIA_URI}: -

      - -
      -public static final int MY_BACKGROUND_JOB = 0;
      -...
      -public static void scheduleJob(Context context) {
      -  JobScheduler js =
      -          (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
      -  JobInfo.Builder builder = new JobInfo.Builder(
      -          MY_BACKGROUND_JOB,
      -          new ComponentName(context, MediaContentJob.class));
      -  builder.addTriggerContentUri(
      -          new JobInfo.TriggerContentUri(MEDIA_URI,
      -          JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
      -  js.schedule(builder.build());
      -}
      -
      -

      - Khi hệ thống báo cáo có sự thay đổi trong (các) URI nội dung được chỉ định, ứng dụng của bạn - sẽ nhận được lệnh gọi lại và một đối tượng {@link android.app.job.JobParameters} được chuyển sang - phương thức {@link android.app.job.JobService#onStartJob onStartJob()} - trong {@code MediaContentJob.class}. -

      - -

      - Các phương thức JobParameter Mới -

      - -

      - N Developer Preview cũng mở rộng {@link android.app.job.JobParameters} để - cho phép ứng dụng của bạn nhận thông tin hữu ích về những gì thẩm quyền nội dung - và các URI đã kích hoạt tác vụ: -

      - -
      -
      - {@code Uri[] getTriggeredContentUris()} -
      - -
      - Trả về mảng URI đã kích hoạt tác vụ đó. Kết quả trả về có thể bằng {@code - null} nếu không có URI nào kích hoạt tác vụ (ví dụ như, tác vụ đã được - kích hoạt do thời hạn hoặc lý do khác), hoặc số các URI - bị thay đổi nhiều hơn 50. -
      - -
      - {@code String[] getTriggeredContentAuthorities()} -
      - -
      - Trả về mảng xâu thẩm quyền nội dung đã kích hoạt tác vụ đó. - Nếu mảng được trả về không phải {@code null}, hãy dùng {@code getTriggeredContentUris()} - để truy xuất chi tiết về URI nào đã thay đổi. -
      -
      - -

      - Mã mẫu sau sẽ ghi đè lên phương thức {@link - android.app.job.JobService#onStartJob JobService.onStartJob()} và - và ghi lại các thẩm quyền nội dung và URI đã kích hoạt tác vụ. -

      - -
      -@Override
      -public boolean onStartJob(JobParameters params) {
      -  StringBuilder sb = new StringBuilder();
      -  sb.append("Media content has changed:\n");
      -  if (params.getTriggeredContentAuthorities() != null) {
      -      sb.append("Authorities: ");
      -      boolean first = true;
      -      for (String auth :
      -          params.getTriggeredContentAuthorities()) {
      -          if (first) {
      -              first = false;
      -          } else {
      -             sb.append(", ");
      -          }
      -           sb.append(auth);
      -      }
      -      if (params.getTriggeredContentUris() != null) {
      -          for (Uri uri : params.getTriggeredContentUris()) {
      -              sb.append("\n");
      -              sb.append(uri);
      -          }
      -      }
      -  } else {
      -      sb.append("(No content)");
      -  }
      -  Log.i(TAG, sb.toString());
      -  return true;
      -}
      -
      - -

      - Tối ưu hóa thêm Ứng dụng của bạn -

      - -

      - Tối ưu hóa ứng dụng của bạn để chạy trên các thiết bị có bộ nhớ ít, hoặc đang trong điều kiện - bộ nhớ ít có thể cải thiện hiệu suất và trải nghiệm của người dùng. Loại bỏ - các thành phần phụ thuộc trên các dịch vụ chạy ngầm và bộ thu truyền phát không biểu thị đã đăng ký tĩnh - có thể giúp ứng dụng của bạn chạy tốt hơn trên các thiết bị như vậy. Mặc dù - N Developer Preview thực hiện các bước để giảm bớt một vài trong số các vấn đề này, nhưng chúng tôi - khuyến nghị bạn nên tối ưu ứng dụng của bạn để chạy hoàn toàn không cần sử dụng - các tiến trình chạy ngầm này. -

      - -

      - N Developer Preview giới thiệu một số lệnh Android Debug Bridge (ADB) bổ sung mà - bạn có thể sử dụng để kiểm thử hành vi của ứng dụng bằng các tiến trình chạy ngầm đã bị vô hiệu hóa đó: -

      - -
        -
      • Để mô phỏng các điều kiện trong đó các truyền phát không biểu thị và dịch vụ chạy ngầm - không có sẵn, hãy nhập lệnh sau: -
      • - -
      • -
        -{@code $ adb shell cmd appops set RUN_IN_BACKGROUND ignore}
        -
        -
      • - -
      • Để kích hoạt lại các truyền phát không biểu thị và dịch vụ chạy ngầm, hãy nhập - lệnh sau: -
      • - -
      • -
        -{@code $ adb shell cmd appops set RUN_IN_BACKGROUND allow}
        -
        -
      • -
      \ No newline at end of file diff --git a/docs/html-intl/intl/vi/preview/features/icu4j-framework.jd b/docs/html-intl/intl/vi/preview/features/icu4j-framework.jd deleted file mode 100644 index 63f6825df8bae3ac87d6ddf2a28a0e483bee93bf..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/features/icu4j-framework.jd +++ /dev/null @@ -1,160 +0,0 @@ -page.title=API Khuôn khổ Android ICU4J -page.tags=androidn -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

      - ICU4J là bộ thư viện Java mã nguồn mở được sử dụng rộng rãi để cung cấp hỗ trợ Unicode - và toàn cầu hóa cho các ứng dụng phần mềm. Android N - cung cấp một tập nhỏ các API ICU4J trong khuôn khổ Android cho các nhà phát triển ứng dụng - sử dụng trong gói {@code android.icu}. Các API này sử dụng - dữ liệu bản địa hóa có trong thiết bị. Do đó, bạn có thể giảm kích thước tệp APK - bằng cách không biên dịch các thư viện ICU4J vào tệp APK; thay vào đó bạn có thể - gọi chúng trong khuôn khổ một cách đơn giản. (Trong trường hợp này, bạn có thể muốn cung cấp - nhiều phiên bản - tệp APK để những người dùng chạy phiên bản Android thấp hơn Android N - có thể tải phiên bản ứng dụng có chứa các thư viện ICU4J.) -

      - -

      - Tài liệu này sẽ bắt đầu bằng việc cung cấp thông tin cơ bản về các mức Android API - tối thiểu cần để hỗ trợ các thư viện này. Sau đó tài liệu sẽ giải thích những gì - bạn cần để hiểu được công việc triển khai ICU4J liên quan cụ thể đến Android. Cuối cùng, - tài liệu sẽ cho bạn biết cách sử dụng các API ICU4J trong khuôn khổ Android. -

      - -

      Liên quan đến ICU4J

      - -

      - Android N cung cấp một tập nhỏ các API ICU4J thông qua - gói android.icu thay vì gói com.ibm.icu. -Khuôn khổ Android có thể chọn không - cung cấp các API ICU4J vì nhiều lý do; ví dụ, Android N không cung cấp - một số API bị loại bỏ hoặc những API chưa được đội ngũ ICU công bố là - bản ổn định. Vì nhóm ICU sẽ loại bỏ các API này trong tương lai do đó Android cũng sẽ đánh dấu - chúng là bị loại bỏ nhưng vẫn tiếp tục thêm vào. -

      - -

      Bảng 1. Các phiên bản ICU và CLDR được sử dụng - trong Android N.

      - - - - - - - - - - - -
      Mức Android APIPhiên bản ICUPhiên bản CLDR
      Android N5628
      - -

      Sau đây là một vài lưu ý quan trọng:

      - -
        -
      • Các API khuôn khổ Android ICU4J không có tất cả các API của ICU4J.
      • -
      • Các nhà phát triển NDK cần biết rằng ICU4C Android không được hỗ trợ.
      • -
      • Các API trong khuôn khổ Android không thay thế hỗ trợ của Android cho -việc bản địa hóa bằng -các tài nguyên.
      • -
      - -

      Chuyển nhập sang gói android.icu từ com.ibm.icu

      - -

      - Nếu bạn đã sử dụng các API ICU4J trong ứng dụng và - các API android.icu đáp ứng yêu cầu của bạn thì việc chuyển nhập sang - các API của khuôn khổ đòi hỏi bạn phải thay đổi thành phần nhập vào của Java - từ com.ibm.icu sang android.icu. Khi đó bạn có thể - xóa các tệp ICU4J của bạn khỏi tệp APK. -

      - -

      - Lưu ý: Các API khuôn khổ ICU4J sử dụng không gian tên {@code android.icu} - thay vì {@code com.ibm.icu}. Điều này là để tránh xung đột - không gian tên trong các tệp APK có chứa các thư viện {@code com.ibm.icu} của riêng chúng. -

      - -

      - Chuyển nhập sang các API android.icu từ các API Android SDK khác -

      - -

      - Một số lớp trong gói javaandroid có - các lớp tương ứng với các lớp trong ICU4J. Tuy nhiên, ICU4J thường cung cấp hỗ trợ - rộng hơn cho các tiêu chuẩn và ngôn ngữ. -

      -

      Sau đây là một số ví dụ để giúp bạn bắt đầu:

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      LớpThay thế
      java.lang.Character android.icu.lang.UCharacter
      java.text.BreakIterator android.icu.text.BreakIterator
      java.text.DecimalFormat android.icu.text.DecimalFormat
      java.util.Calendar -android.icu.util.Calendar
      android.text.BidiFormatter - android.icu.text.Bidi -
      android.text.format.DateFormat - android.icu.text.DateFormat -
      android.text.format.DateUtils android.icu.text.DateFormat -android.icu.text.RelativeDateTimeFormatter -
      - -

      Cấp phép

      - -

      - ICU4J được phát hành theo giấy phép ICU. Hãy xem Hướng dẫn sử dụng - ICU để biết thêm chi tiết. -

      diff --git a/docs/html-intl/intl/vi/preview/features/multilingual-support.jd b/docs/html-intl/intl/vi/preview/features/multilingual-support.jd deleted file mode 100644 index 94a71277ce7d53234bb91d62e24e21e96905fcb7..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/features/multilingual-support.jd +++ /dev/null @@ -1,217 +0,0 @@ -page.title=Ngôn ngữ và Bản địa -page.tags=androidn -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

      Android N cung cấp hỗ trợ cải tiến cho người dùng sử dụng nhiều ngôn ngữ, -cho phép họ chọn nhiều bản địa trong phần cài đặt. Android N -cung cấp khả năng này bằng cách mở rộng số lượng lớn các bản địa được hỗ trợ -và thay đổi cách hệ thống phân giải tài nguyên. Phương thức phân giải tài nguyên -mới hoạt động mạnh mẽ hơn và được thiết kế để tương thích với các tệp APK có sẵn. Tuy nhiên -bạn cần kiểm tra thêm để phát hiện mọi hành vi không mong muốn. Ví dụ, bạn -cần kiểm thử để đảm bảo rằng ứng dụng của mình sẽ thiết lập mặc định cho ngôn ngữ mong muốn. Ngoài ra, -nếu ứng dụng của bạn hỗ trợ đa ngôn ngữ thì bạn cần đảm bảo rằng việc hỗ trợ này hoạt động như -dự kiến. Cuối cùng, bạn cần cố gắng đảm bảo rằng ứng dụng sẽ xử lý tinh tế -những ngôn ngữ mà bạn không có ý định thiết kế ứng dụng để hỗ trợ.

      - -

      Tài liệu này sẽ bắt đầu bằng việc giải thích về chiến lược phân giải tài nguyên trong phiên bản trước -Android N. Tiếp theo, tài liệu sẽ mô tả chiến lược phân giải tài nguyên -được cải tiến của Android N. Cuối cùng, tài liệu sẽ giải thích cách sử dụng -số lượng các bản địa được mở rộng để hỗ trợ thêm nhiều người dùng đa ngữ.

      - -

      Thử thách phân giải tài nguyên ngôn ngữ

      - -

      Trước Android N, không phải lúc nào Android cũng có thể so khớp -thành công ứng dụng với các bản địa của hệ thống. Ví dụ, giả sử ngôn ngữ mặc định của ứng dụng của bạn - là Tiếng Anh (Mỹ) nhưng ứng dụng cũng có các xâu văn bản Tiếng Tây Ban Nha được bản địa hóa trong các tệp tài nguyên {@code es_ES} -.

      -

      Khi mã nguồn Java tham chiếu đến các xâu đó thì nó sẽ phân giải các ngôn ngữ của xâu như -sau:

      -
        -
      • Nếu một thiết bị được đặt thành {@code es_MX} (Tiếng Tây Ban Nha-Mêxicô) thì Android sẽ tải -xâu từ các tệp tài nguyên {@code es_ES}.
      • -
      • Nếu thiết bị được đặt thành {@code en_AU} thì Android sẽ trả về {@code -en_US}. Hệ thống cũng sẽ đặt mặc định thành {@code en_US} nếu người dùng chọn một -ngôn ngữ mà ứng dụng không hỗ trợ chút nào, ví dụ như Tiếng Pháp.
      • -
      - - -

      Các vấn đề phân giải này phát sinh bởi vì hệ thống sẽ gỡ mã quốc gia - khỏi bản địa nếu nó không tìm thấy sự trùng khớp tuyệt đối. Ví dụ:

      -

      -Bảng 1. Phân giải tài nguyên không có trùng khớp bản địa tuyệt đối. -

      - - - - - - - - - - - - - -
      Cài đặt Người dùngTài nguyên Ứng dụngPhân giải tài nguyên
      fr_CH -mặc định (en)
      -de_DE
      -es_ES
      -fr_FR
      -it_IT
      -
      -Thử fr_CH => Không được
      -Thử fr => Không được
      -Sử dụng mặc định (en) -
      - - -

      Trong ví dụ này, hệ thống hiển thị các xâu Tiếng Anh mà không -xác định được liệu người dùng có biết Tiếng Anh hay không. Đây là hành vi khá phổ biến -ngày nay. Android N cần phải giảm bớt đáng kể tần suất -của những kết quả như vậy.

      - -

      Các cải tiến đối với Chiến lược phân giải tài nguyên

      -

      Android N mang đến cách thức phân giải tài nguyên mạnh mẽ hơn, và -tìm các giải pháp thay thế hiệu quả hơn một cách tự động. Tuy nhiên, để tăng tốc việc phân giải và nâng cao -khả năng bảo trì, bạn cần lưu trữ các tài nguyên trong những nhánh ngôn ngữ mẹ phổ biến nhất. - Ví dụ, nếu trước đây lưu tài nguyên Tiếng Tây Ban Nha trong thư mục {@code es-US} - thì hãy chuyển chúng vào trong thư mục {@code es-419}, nơi chứa Tiếng Tây Ban Nha Mỹ La-tinh. - Tương tự, nếu bạn có các xâu tài nguyên trong một thư mục có tên {@code en-GB} thì hãy đổi tên - thư mục đó thành {@code en-001} (Tiếng Anh quốc tế) bởi vì nhánh mẹ -phổ biến nhất cho chuỗi en-GB là {@code en-001}. - Các ví dụ sau sẽ giải thích tại sao các thực hành này sẽ nâng cao hiệu năng và -độ ổn định của việc phân giải tài nguyên.

      - -

      Các ví dụ về phân giải tài nguyên

      - -

      Với Android N, trường hợp được mô tả trong Bảng 1 được phân giải -theo cách khác:

      - -

      -Bảng 2. Một chiến lược phân giải cải tiến khi không có -trùng khớp bản địa tuyệt đối.

      - - - - - - - - - - - - -
      Cài đặt Người dùngTài nguyên Ứng dụngPhân giải tài nguyên
        -
      1. fr_CH
      2. -
      -
      -mặc định (en)
      -de_DE
      -es_ES
      -fr_FR
      -it_IT
      -
      -Thử fr_CH => Không được
      -Thử fr => Không được
      -Thử nhánh con của fr => fr_FR
      -Sử dụng fr_FR -
      - - -

      Bây giờ thì người dùng sẽ nhận được tài nguyên Tiếng Pháp thay vì Tiếng Anh. Ví dụ này cũng cho thấy - lý do bạn nên lưu trữ các xâu Tiếng Pháp trong {@code fr} thay vì {@code fr_FR} - cho Android N. Phương pháp ở đây là ghép nhánh ngôn ngữ mẹ gần nhất, - giúp cho việc phân giải nhanh hơn và dễ dự đoán hơn.

      - -

      Ngoài lôgic phân giải được cải tiến này, Android giờ đây cung cấp thêm nhiều -ngôn ngữ cho người dùng lựa chọn. Chúng ta hãy thử lại ví dụ trên với Tiếng Ý - được xác định là một ngôn ngữ người dùng bổ sung nhưng không được ứng dụng hỗ trợ cho Tiếng Pháp.

      - -

      -Bảng 3. Phân giải tài nguyên khi ứng dụng chỉ khớp -với cài đặt bản địa được ưu tiên thứ hai của người dùng.

      - - - - - - - - - - - - - - -
      Cài đặt Người dùngTài nguyên Ứng dụngPhân giải tài nguyên
        -
      1. fr_CH
      2. -
      3. it_CH
      4. -
      -
      -mặc định (en)
      -de_DE
      -es_ES
      -it_IT
      -
      -Thử fr_CH => Không được
      -Thử fr => Không được
      -Thử nhánh con của fr => Không được
      -Thử it_CH => Không được
      -Thử it => Không được
      -Thử nhánh con của it => it_IT
      -Sử dụng it_IT -
      -

      Người dùng vẫn nhận được ngôn ngữ họ biết mặc dù ứng dụng không -hỗ trợ Tiếng Pháp.

      - - -

      Thiết kế ứng dụng để hỗ trợ các bản địa bổ sung

      -

      API LocaleList

      - -

      Android N bổ sung thêm một API {@code LocaleList.GetDefault()} - mới cho phép các ứng dụng truy vấn trực tiếp danh sách các ngôn ngữ mà người dùng đã chỉ định. API này -cho phép bạn tạo hành vi ứng dụng -phức tạp hơn và hiển thị nội dung được tối ưu hóa tốt hơn. Ví dụ, Tìm kiếm - có thể hiển thị các kết quả bằng nhiều ngôn ngữ dựa trên cài đặt của người dùng. Các ứng dụng trình duyệt - có thể tránh đề nghị dịch trang web sang một ngôn ngữ mà người dùng đó đã biết, - và các ứng dụng bàn phím có thể tự động bật tất cả các bố trí phù hợp.

      - -

      Bộ định dạng

      - -

      Tính tới Android 6.0 (API mức 23), Android 6.0 chỉ hỗ trợ một hoặc hai bản địa -cho nhiều ngôn ngữ phổ biến -(en, es, ar, fr, ru). Bởi vì chỉ có một vài biến thể của từng ngôn ngữ, -các ứng dụng không gặp vấn đề gì với việc lưu trữ một số chữ số và ngày tháng dưới dạng xâu được chèn trực tiếp khi viết mã -trong các tệp tài nguyên. Tuy nhiên, với tập hợp mở rộng các bản địa được hỗ trợ bởi Android, -có thể có -nhiều khác biệt lớn về các định dạng ngày tháng, thời gian, tiền tệ và thông tin -tương tự ngay cả trong một bản địa. Chèn trực tiếp các định dạng có thể khiến -người dùng cuối bối rối. Do đó, khi phát triển cho Android N -hãy đảm bảo sử dụng các bộ định dạng thay vì các xâu chữ số và ngày tháng được chèn trực tiếp khi viết mã.

      - -

      Một ví dụ điển hình là Tiếng Ả-rập với được Android N hỗ trợ mở rộng từ -một {@code ar_EG} tới 27 bản địa Tiếng Ả-rập. Các bản địa này có thể chia sẻ hầu hết các tài nguyên, -nhưng một số bản địa ưu tiên chữ số ASCII trong khi những bản địa khác lại ưu tiên con số truyền thống. Ví dụ, -khi bạn muốn soạn một câu có biến bằng số, như -"Choose a 4 digit pin" thì bạn hãy sử dụng bộ định dạng như sau:

      - -
       format(locale, "Choose a %d-digit PIN", 4)
      diff --git a/docs/html-intl/intl/vi/preview/features/notification-updates.jd b/docs/html-intl/intl/vi/preview/features/notification-updates.jd deleted file mode 100644 index d80cf6c08f5eb69757f365508cf75507ab396d6b..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/features/notification-updates.jd +++ /dev/null @@ -1,328 +0,0 @@ -page.title=Thông báo -page.tags=notifications -helpoutsWidget=true -page.image=/preview/images/notifications-card.png - -trainingnavtop=true - -@jd:body - -
      -
      - - -

      Tài liệu này gồm có

      -
        -
      1. Trả lời Trực tiếp
      2. -
      3. Thông báo Gộp
      4. -
      5. Dạng xem Tùy chỉnh
      6. -
      - -
      -
      - -

      Android N giới thiệu một số API mới cho phép ứng dụng đăng -các thông báo có khả năng hiển thị và tương tác cao.

      - -

      Android N mở rộng API thông báo {@link android.support.v4.app.RemoteInput} -hiện có để hỗ trợ trả lời giữa dòng trên thiết bị cầm tay. Tính năng này cho phép người dùng - phản hồi nhanh chóng từ khu vực hiển thị thông báo mà không cần truy cập ứng dụng của bạn.

      - -

      - Android N cũng cho phép bạn gộp các thông báo tương tự nhau để - xuất hiện dưới dạng một thông báo đơn lẻ. Để điều này có thể xảy ra, Android N sử dụng phương thức {@link - android.support.v4.app.NotificationCompat.Builder#setGroup - NotificationCompat.Builder.setGroup()} hiện có. Người dùng có thể mở rộng mỗi - thông báo, và thực hiện các hành động như trả lời và bỏ qua trên mỗi - thông báo, từng thông báo một từ khu vực hiển thị thông báo. -

      - -

      Cuối cùng, Android N cũng thêm các API mới cho phép bạn tận dụng các trang trí -của hệ thống trong các dạng xem thông báo tùy chỉnh của ứng dụng của bạn. Các API này giúp -đảm bảo rằng dạng xem thông báo có chung một cách trình bày nhất quán -với các mẫu tiêu chuẩn.

      - -

      Tài liệu này nêu bật một số các thay đổi chính mà bạn cần cân nhắc - khi sử dụng các tính năng thông báo mới trong ứng dụng của mình.

      - -

      Trả lời Trực tiếp

      - -

      Với tính năng Trả lời Trực tiếp trong Android N, người dùng có thể -phản hồi lại tin nhắn văn bản hoặc cập nhật danh sách tác vụ trực tiếp trong giao diện -của thông báo. Trên thiết bị cầm tay, hành động trả lời giữa dòng xuất hiện dưới dạng một nút bổ sung - được gắn kèm với thông báo đó. Khi người dùng trả lời qua bàn phím, hệ thống sẽ đính kèm - phản hồi bằng văn bản với ý định - bạn đã quy định cho hành động thông báo và gửi ý định đến ứng dụng cầm tay - của bạn. - - - -

      - Hình 1. Android N thêm nút hành động Reply -. -

      - -

      Thêm các hành động trả lời giữa dòng

      - -

      Để tạo một hành động thông báo hỗ trợ trả lời trực tiếp: -

      - -
        -
      1. Tạo thực thể{@link android.support.v4.app.RemoteInput.Builder} - mà bạn có thể thêm vào hành động -thông báo của bạn. Hàm dựng của lớp này sẽ chấp nhận xâu mà hệ thống sử dụng làm khóa - cho nhập liệu văn bản. Sau đó, ứng dụng cầm tay của bạn sử dụng khóa đó để truy xuất văn bản - nhập liệu. - -
        -// Key for the string that's delivered in the action's intent
        -private static final String KEY_TEXT_REPLY = "key_text_reply";
        -String replyLabel = getResources().getString(R.string.reply_label);
        -RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
        -        .setLabel(replyLabel)
        -        .build();
        -
        -
      2. -
      3. Đính kèm đối tượng {@link android.support.v4.app.RemoteInput} - với một hành động bằng cách sử dụng addRemoteInput(). - -
        -// Create the reply action and add the remote input
        -Notification.Action action =
        -        new Notification.Action.Builder(R.drawable.ic_reply_icon,
        -                getString(R.string.label), replyPendingIntent)
        -                .addRemoteInput(remoteInput)
        -                .build();
        -
        -
      4. - -
      5. Áp dụng hành động cho thông báo và phát hành thông báo. - -
        -// Build the notification and add the action
        -Notification notification =
        -        new Notification.Builder(mContext)
        -                .setSmallIcon(R.drawable.ic_message)
        -                .setContentTitle(getString(R.string.title))
        -                .setContentText(getString(R.string.content))
        -                .addAction(action))
        -                .build();
        -
        -// Issue the notification
        -NotificationManager notificationManager =
        -        NotificationManager.from(mContext);
        -notificationManager.notify(notificationId, notification);
        -
        -
        -
      6. - -
      - - -

      Hệ thống sẽ nhắc người dùng nhập liệu một phản hồi khi chúng kích hoạt -hành động thông báo.

      - - -

      - Hình 2. Người dùng nhập liệu văn bản từ khu vực hiển thị thông báo. -

      - -

      Truy xuất mục nhập của người dùng từ trả lời giữa dòng

      - -

      Để nhận mục nhập của người dùng từ giao diện thông báo đến hoạt động bạn -đã khai báo trong ý định của hành động trả lời:

      -
        -
      1. Gọi {@link android.support.v4.app.RemoteInput#getResultsFromIntent - getResultsFromIntent()} bằng cách chuyển ý định của hành động thông báo dưới dạng - tham số đầu vào. Phương thức này trả về {@link android.os.Bundle} - có chứa phản hồi văn bản. -
      2. - -
        -Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
        -
        - -
      3. Truy vấn gói bằng cách sử dụng khóa kết quả (đã cung cấp cho hàm dựng {@link - android.support.v4.app.RemoteInput.Builder}). -
      4. -
      - -

      Đoạn mã sau minh họa cách thức một phương thức truy xuất văn bản đầu vào -từ một gói:

      - -
      -// Obtain the intent that started this activity by calling
      -// Activity.getIntent() and pass it into this method to
      -// get the associated string.
      -
      -private CharSequence getMessageText(Intent intent) {
      -    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
      -    if (remoteInput != null) {
      -            return remoteInput.getCharSequence(KEY_TEXT_REPLY);
      -            }
      -    return null;
      - }
      -
      - -

      Ứng dụng có thể áp dụng lô-gic để quyết định hành động nào nên lấy trên văn bản -được truy xuất. -Đối với các ứng dụng tương tác (chẳng hạn như trò chuyện), hãy cung cấp thêm ngữ cảnh trong chính thông báo - (ví dụ như nhiều dòng lịch sử trò chuyện, gồm có các tin nhắn của riêng người dùng) - để người dùng có thể phản hồi phù hợp. -Khi người dùng phản hồi qua {@link android.support.v4.app.RemoteInput}, - hãy bao gồm văn bản trong lịch sử trả lời bằng phương thức {@code setRemoteInputHistory()} -.

      - -

      Thông báo Gộp

      - -

      Android N cung cấp cho các nhà phát triển một cách mới để hiển thị - hàng đợi thông báo: thông báo gộp. Cách hiển thị này tương tự với tính năng - Ngăn xếp - Thông báo có trong Android Wear. Ví dụ, nếu ứng dụng của bạn tạo thông báo - cho tin nhắn nhận được, khi có nhiều hơn một tin nhắn nhận được, hãy gói - các thông báo lại với nhau thành một nhóm đơn lẻ. Bạn có thể - sử dụng phương thức {@link android.support.v4.app.NotificationCompat.Builder#setGroup -Builder.setGroup()} hiện có để gói các thông báo tương tự.

      - -

      - Nhóm thông báo sẽ quy định phân cấp trên các thông báo bao gồm nó. - Ở trên cùng của phân cấp là thông báo mẹ hiển thị tóm tắt - thông tin cho nhóm đó. Người dùng có thể mở rộng - nhóm thông báo tăng dần lên, và hệ thống sẽ hiển thị thêm thông tin khi - người dùng truy sâu hơn. Khi người dùng mở rộng gói này, hệ thống sẽ lộ ra thêm - thông tin cho tất cả các thông báo con của gói, khi người dùng - mở rộng một trong những thông báo đó, hệ thống sẽ lộ ra toàn bộ nội dung của nó. -

      - - -

      - Hình 3. Người dùng có thể mở rộng nhóm - thông báo tăng dần lên. -

      - -

      Để tìm hiểu cách thêm thông báo vào một nhóm, xem -Thêm -Mỗi Thông báo vào một Nhóm.

      - - -

      Thực hành tốt nhất cho thông báo gộp

      -

      Mục này sẽ cung cấp hướng dẫn về việc khi nào sử dụng nhóm thông báo thay vì - các thông báo{@link android.app.Notification.InboxStyle InboxStyle} -có sẵn trong các phiên bản cũ hơn của -nền tảng Android.

      - -

      Khi nào nên sử dụng thông báo gộp

      - -

      Bạn nên sử dụng các nhóm thông báo chỉ khi tất cả các điều kiện sau là -đúng đối với trường hợp sử dụng của bạn:

      - -
        -
      • Thông báo con là loại thông báo đầy đủ và có thể được hiển thị - riêng rẽ mà không cần tóm tắt nhóm.
      • -
      • Sẽ có lợi khi làm nổi lên các thông báo con một cách riêng rẽ. Ví -dụ: -
      • -
          -
        • Các thông báo này có thể hành động được, bằng các hành động cụ thể cho mỗi thông báo con.
        • -
        • Có nhiều thông tin hơn đối với thông báo con mà người dùng sẽ muốn đọc.
        • -
        -
      - -

      Các ví dụ về các trường hợp sử dụng tốt nhóm thông báo bao gồm: ứng dụng nhắn tin -hiển thị danh sách các tin nhắn đến, hoặc ứng dụng email hiển thị danh sách -các email đã nhận được.

      - -

      -Ví dụ về các trường hợp trong đó một thông báo đơn lẻ được ưu tiên - bao gồm tin nhắn riêng từ một người đơn lẻ, hoặc biểu diễn danh sách - các mục văn bản một hàng. Bạn có thể sử dụng -({@link android.app.Notification.InboxStyle InboxStyle} hoặc -{@link android.app.Notification.BigTextStyle BigTextStyle}) để hoàn thành -việc này. -

      - -

      Hiển thị Thông báo gộp

      - -

      - Ứng dụng sẽ luôn đăng tóm tắt nhóm, ngay cả khi nhóm chỉ chứa - một thông báo con duy nhất. Hệ thống này sẽ ngăn chặn tóm tắt và hiển thị trực tiếp - thông báo con nếu nó chỉ chứa một thông báo duy nhất. Điều này đảm bảo - rằng hệ thống có thể cung cấp một trải nghiệm nhất quán khi người dùng trượt nhanh khỏi - thông báo con của nhóm. -

      - -

      - Lưu ý: Phiên bản Android N này không - ngăn chặn tóm tắt cho nhóm thông báo có chứa một thông báo con duy nhất. Chức năng - này sẽ được thêm vào trong phiên bản sau của Android N. -

      - -

      Thông báo lướt nhanh

      - -

      Trong khi hệ thống thường hiển thị các thông báo con dưới dạng một nhóm, bạn có thể đặt - chúng tạm thời hiển thị dưới dạng - - thông báo cảnh báo. Tính năng này đặc biệt hữu ích bởi vì nó cho phép - truy cập ngay lập tức thông báo con gần đây nhất và các hành động liên kết với thông báo con đó. -

      - - -

      Tính tương thích ngược

      - -

      - Cả nhóm thông báo và đầu vào từ xa đều là một phần của API {@link - android.app.Notification} vì Android 5.0 (API mức 21) hỗ trợ - các thiết bị Android Wear. Nếu bạn đã dựng các thông báo bằng các API này, - hành động duy nhất bạn cần phải thực hiện là xác minh rằng ứng dụng có hành vi tương ứng - với các hướng dẫn đã mô tả ở trên, và cân nhắc việc triển khai {@code - setRemoteInputHistory()}. -

      - -

      - Để hỗ trợ tính tương thích ngược, các API giống vậy sẽ được cung cấp cho - lớp {@link android.support.v4.app.NotificationCompat} - của thư viện hỗ trợ, cho phép bạn dựng các thông báo hoạt động trên các phiên bản - Android cũ hơn. Trên máy tính bảng và thiết bị cầm tay, người dùng chỉ nhìn thấy thông báo tóm tắt, - vì vậy ứng dụng vẫn có kiểu hòm thư hoặc thông báo tương tự - biểu diễn cho toàn bộ nội dung thông tin của nhóm. Vì các thiết bị Android - Wear cho phép người dùng xem các thông báo con thậm chí trên - các mức nền tảng thấp hơn, bạn nên dựng các thông báo con dù cho mức API - là mức nào. -

      - -

      Dạng xem Tùy chỉnh

      -

      Bắt đầu từ Android N, bạn có thể tùy chỉnh dạng xem và -vẫn có các trang trí hệ thống như tiêu đề thông báo, hành động, và -các bố trí mở rộng được.

      - -

      Để kích hoạt khả năng này, Android N thêm các API sau để tạo kiểu cho dạng xem tùy chỉnh - của bạn:

      - -
      -
      -{@code DecoratedCustomViewStyle()}
      -
      Thông báo kiểu khác với thông báo -media.
      -
      -{@code DecoratedMediaCustomViewStyle()}
      -
      Thông báo media tạo kiểu.
      -
      - -

      Để sử dụng API mới này, hãy gọi phương thức {@code setStyle()}, chuyển nó sang -kiểu dạng xem tùy chỉnh mong muốn.

      - -

      Đoạn mã này cho biết cách dựng đối tượng thông báo tùy chỉnh bằng phương thức -{@code DecoratedCustomViewStyle()}.

      - -
      -Notification noti = new Notification.Builder()
      -           .setSmallIcon(R.drawable.ic_stat_player)
      -           .setLargeIcon(albumArtBitmap))
      -           .setCustomContentView(contentView);
      -           .setStyle(new Notification.DecoratedCustomViewStyle())
      -           .build();
      -
      -
      diff --git a/docs/html-intl/intl/vi/preview/index.jd b/docs/html-intl/intl/vi/preview/index.jd deleted file mode 100644 index bd64b250fb375d8f4fb0e6d44caca4d3008af063..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/index.jd +++ /dev/null @@ -1,120 +0,0 @@ -page.title=Android N Developer Preview -page.tags="preview","developer" -meta.tags="preview", "android" -fullpage=true -forcelocalnav=true -header.hide=1 -footer.hide=1 -@jd:body - - - -
      -
      -
      - -
      -

      Android N Developer Preview

      -

      - Hãy chuẩn bị sẵn sàng cho Android N! - Kiểm thử ứng dụng của bạn trên Nexus và các thiết bị khác. Hỗ trợ các hành vi - hệ thống mới nhằm tiết kiệm năng lượng và bộ nhớ. - Mở rộng ứng dụng của bạn bằng UI đa cửa sổ, - thông báo trả lời trực tiếp và nhiều tính năng khác. -

      - - - - Bắt đầu - -
      -
      - -
      -
      -
      -
      -
      -
      -
      - - - - - -
      -

      Tài nguyên

      -
      - Các thông tin cần thiết để trợ giúp bạn chuẩn bị cho ứng dụng sẵn sàng chạy trên Android N. -
      - -
      - -
      -
      - diff --git a/docs/html-intl/intl/vi/preview/overview.jd b/docs/html-intl/intl/vi/preview/overview.jd deleted file mode 100644 index a71bf61b34ab64115caf03b4065a2c7de9a9d383..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/overview.jd +++ /dev/null @@ -1,440 +0,0 @@ -page.title=Tổng quan về Chương trình -page.metaDescription=Hãy chuẩn bị ứng dụng sẵn sàng cho phiên bản Android tiếp theo. -page.image=images/cards/card-n-overview_2x.png -meta.tags="preview", "developer", "android" -page.tags="preview", "developer", "android" - -@jd:body - - -

      - Chào mừng bạn đến với Android N Developer Preview, một chương trình - cung cấp cho bạn mọi thứ cần thiết để kiểm thử và tối ưu hóa các ứng dụng cho phiên bản - Android tiếp theo. Đây là chương trình miễn phí và bạn có thể bắt đầu ngay bằng cách - tải xuống các công cụ của N Developer Preview. -

      - - - - - - - -
      -
      -
      -
      -
      - Thiết bị phần cứng và ảnh của bộ giả lập -
      - -

      - Chạy và kiểm thử ứng dụng của bạn trên một loạt các thiết bị hoặc trên bộ giả lập. - -

      -
      - -
      -
      - Mã nền tảng mới nhất -
      - -

      - Chúng tôi sẽ cung cấp các bản cập nhật hàng tháng trong thời gian của Preview vì vậy bạn sẽ được kiểm tra các thay đổi nền tảng mới nhất. -

      -
      - -
      -
      - Ưu tiên các vấn đề của nhà phát triển -
      - -

      - Trong một vài tuần đầu, chúng tôi sẽ dành ưu tiên cho các vấn đề - được nhà phát triển báo cáo, vì vậy hãy kiểm thử và gửi phản hồi sớm nhất có thể. -

      -
      - -
      - -
      - - -
      -
      - Các hành vi và khả năng mới -
      - -

      - Tiến hành công việc sớm để hỗ trợ các hành vi mới của nền tảng và phát triển với các tính năng mới. -

      -
      - -
      -
      - Cập nhật qua OTA -
      - -

      - Các bản cập nhật liền mạch qua sóng vô tuyến cho bất kỳ thiết bị nào được hỗ trợ thông qua - Chương trình Android Beta. Không cần phải flash. -

      -
      - -
      -
      - Phản hồi và hỗ trợ -
      - -

      - Báo cáo các vấn đề và gửi phản hồi về cho chúng tôi thông qua - bộ theo dõi vấn đề của chúng tôi. Kết nối với các nhà phát triển - khác trong - Cộng đồng Nhà phát triển N. -

      -
      -
      -
      -
      - - - -

      Tiến trình thời gian và các bản cập nhật

      - - -

      - N Developer Preview sẽ kéo dài từ 9 tháng 3 năm 2016 đến khi phát hành công chúng - bản Android N cuối cùng cho AOSP và OEM, dự kiến trong Q3 2016. -

      - -

      - Tại các mốc phát triển chính chúng tôi sẽ cung cấp các bản cập nhật cho môi trường phát triển và - kiểm thử của bạn. Nói chung, bạn có thể nhận một bản cập nhật hàng tháng (khoảng cách - 4 đến 6 tuần). Các mốc được liệt kê dưới đây. -

      - -
        -
      • Preview 1 (phát hành lần đầu, alpha)
      • -
      • Preview 2 (bản cập nhật tăng dần, alpha)
      • -
      • Preview 3 (bản cập nhật tăng dần, beta)
      • -
      • Preview 4 (các API cuối cùng và SDK chính thức, phát hành Play)
      • -
      • Preview 5 (các ảnh hệ thống gần hoàn thiện để kiểm thử cuối cùng)
      • -
      • Phát hành bản cuối cho AOSP và hệ sinh thái
      • -
      - -

      - Mỗi bản cập nhật sẽ có các công cụ SDK, ảnh hệ thống xem trước, bộ giả lập, tài liệu - tham khảo và những khác biệt về API. -

      - -

      - Ba phiên bản Preview đầu tiên sẽ cung cấp một môi trường - kiểm thử và phát triển sớm để giúp bạn xác định - các vấn đề tương thích trong ứng dụng hiện tại và lập kế hoạch di chuyển hoặc trang bị hoạt động - cần thiết để nhắm tới nền tảng mới. Đây là giai đoạn ưu tiên để bạn - gửi phản hồi cho chúng tôi về các tính năng, khả năng tương thích của API và tệp - — đối với mọi vấn đề đó, vui lòng sử dụng bộ theo dõi - vấn đề. Sẽ có một số thay đổi với API giữa các bản cập nhật này. -

      - -

      - Tại Preview 4 và 5 bạn sẽ được sử dụng các -API và SDK N cuối cùng để phát triển, và cả các ảnh hệ thống gần hoàn thiện - để kiểm thử các hành vi, tính năng của hệ thống. Android N sẽ cung cấp một mức - API chuẩn vào thời điểm này. Bạn có thể tiến hành kiểm thử khả năng tương thích cuối cùng đối với các ứng dụng - cũ và tinh chỉnh mã nguồn mới có sử dụng các API hoặc tính năng mới của N. -

      - -

      - Ngoài ra, bắt đầu từ Preview 4 bạn có thể phát hành ứng dụng lên - các thiết bị chạy Android N ở cấp API chính thức, chẳng hạn như - thiết bị người dùng được chọn cho chương trình Android Beta. Bạn có thể - phát hành ứng dụng lên kênh alpha và beta của Google Play trước do đó bạn có thể kiểm thử - ứng dụng của mình với người dùng Android Beta trước khi phân phối rộng rãi trên - cửa hàng. -

      - -

      - Khi bạn kiểm thử và phát triển trên Android N, chúng tôi khuyến cáo bạn duy trì - môi trường phát triển được cập nhật khi các cập nhật Preview được - phát hành. Để giúp cho quá trình này thuận tiện hơn, bạn có thể đăng ký các thiết bị kiểm thử của mình vào - chương trình Android Beta và lấy các bản cập nhật qua sóng vô tuyến (OTA) tại - mỗi mốc. Ngoài ra, các ảnh xem trước cũng có sẵn để bạn - tải xuống và flash thủ công. -

      - -

      - Chúng tôi sẽ thông báo cho bạn khi các cập nhật Preview xuất hiện thông qua Blog Nhà phát triển Android, cũng - như thông qua trang này và Cộng đồng - Nhà phát triển Android N. -

      - - -

      Có gì trong N Developer Preview?

      - -

      - N Developer Preview có tất cả mọi thứ bạn cần để kiểm thử ứng dụng - sẵn có của bạn trên nhiều loại kích cỡ màn hình, công nghệ mạng, chipset CPU/GPU - và kiến trúc phần cứng. -

      - -

      Bộ công cụ SDK

      - -

      Bạn có thể tải xuống các thành phần này thông qua Trình quản lý SDK trong Android Studio:

      - -
        -
      • N Developer Preview SDK và công cụ -
      • Ảnh hệ thống cho bộ giả lập (32-bit và 64-bit) của N Developer Preview -
      • Ảnh hệ thống cho bộ giả lập cho Android TV (32-bit) của N Developer Preview -
      • Các thư viện hỗ trợ của N Developer Preview (dành cho các mẫu ứng dụng mới) -
      - -

      - Chúng tôi sẽ cung cấp các bản cập nhật cho các công cụ phát triển này theo từng mốc khi cần thiết. -

      - -

      Ảnh hệ thống cho phần cứng

      - -

      - N Developer Preview bao gồm các ảnh hệ thống cho Nexus và phần cứng khác mà bạn có thể sử dụng khi - kiểm thử và phát triển trên các thiết bị vật lý. Hãy xem trang Ảnh cho Thiết bị để có danh sách đầy đủ - các ảnh cho phần cứng. -

      - -

      - Chúng tôi sẽ cung cấp các ảnh hệ thống cập nhật cho những thiết bị này tại mỗi mốc. Bạn - có thể tải xuống và flash các ảnh hệ thống cập nhật vào các thiết bị kiểm thử - một cách thủ công nhiều lần theo nhu cầu. Điều này đặc biệt hữu ích đối với các môi trường - kiểm thử tự động, trong đó bạn có thể cần flash lại thiết bị nhiều - lần. -

      - -

      Lưu ý: - Các thiết bị được flash thủ công sẽ không nhận các bản cập nhật qua OTA giống như trong - preview của năm ngoái. Năm nay bạn có thể nhận qua OTA bằng cách đăng ký các thiết bị trong - Chương trình Android Beta — hãy xem chi tiết trong phần tiếp theo. -

      - -

      Các bản cập nhật OTA thông qua Chương trình Android Beta

      - -

      - Tính năng mới cho Android N là một chương trình cập nhật qua sóng vô tuyến (OTA) sẽ tự động - phát hành các cập nhật Preview mới nhất của Android N trực tiếp tới thiết bị đã đăng ký - trong chương trình. Đây là chương trình miễn phí và mở đối với bất cứ ai có một - thiết bị được hỗ trợ đã đăng ký với tài khoản Google của họ. -

      - -

      - Để đăng ký vào chương trình, hãy truy cập trang Chương trình - Android Beta. Bạn sẽ thấy - tất cả các thiết bị đã đăng ký với tài khoản của bạn có đủ điều kiện để đăng ký - Android Beta. -

      - -
        -
      1. Hãy chọn các thiết bị bạn muốn nhận bản cập nhật Android N -
      2. Nhấp vào Đăng ký, đọc và đồng ý với các điều khoản dịch vụ và sau đó nhấp OK -
      - -

      - Một khi đã đăng ký, thiết bị của bạn sẽ sớm nhận được một bản cập nhật. Trong hầu hết trường hợp, - bạn sẽ không cần thực hiện thiết lập lại toàn bộ dữ liệu để chuyển sang Android N. Tuy nhiên, - chúng tôi khuyến cáo bạn sao lưu bất kỳ dữ liệu nào bạn không muốn bị mất trước khi - đăng ký thiết bị. -

      - -

      - Khi các bản cập nhật được phát hành tới thiết bị của bạn, chúng tôi khuyến cáo bạn tải xuống và - cài đặt sớm nhất có thể. Bạn sẽ muốn cập nhật các - thay đổi mới nhất về UI, hành vi, API và các tính năng của hệ thống. -

      - -

      - Khi kết thúc Developer Preview, các thiết bị đăng ký của bạn sẽ - nhận một bản cập nhật của bản phát hành Android N chính thức. -

      - -

      - Bạn có thể hủy đăng ký các thiết bị của mình trong chương trình Android Beta bất kỳ lúc nào thông qua - trang Android Beta. Trước khi hủy đăng ký, hãy chắc chắn sao lưu dự phòng dữ liệu của bạn trên - thiết bị đó. -

      - -

      Lưu ý: - Khi bạn hủy đăng ký, thiết bị của bạn sẽ được khôi phục cài đặt gốc - về phiên bản mới nhất - của Android 6.0 Marshmallow (không nhất thiết là phiên bản bạn từng - được cài đặt trước khi đăng ký thiết bị). Để đảm bảo cài đặt mới hoàn toàn, - dữ liệu của bạn sẽ bị xóa khỏi thiết bị, bao gồm danh bạ, tin nhắn, - ảnh, v.v... -

      - -

      Tài liệu và mã mẫu

      - -

      - Các nguồn tài liệu này có trên trang Developer Preview để - trợ giúp bạn tìm hiểu về Android N: -

      - -
        -
      • Thiết lập để Phát triển dành cho -Android N có - các hướng dẫn từng bước để bắt đầu.
      • -
      • Các thay đổi - Hành vi chỉ ra cho bạn các phần chính yếu để kiểm thử.
      • -
      • Tổng quan về các API mới, bao gồm một phần Tổng quan về API, bản tải xuống được - Tham khảo - API và các hướng dẫn chi tiết cho nhà phát triển đối với các tính năng quan trọng như - hỗ trợ đa cửa sổ, thông báo gộp, hỗ trợ đa bản địa và các tính năng khác. -
      • Mã mẫu trong đó - minh họa cách hỗ trợ các quyền và tính năng mới. -
      • Ghi chú phát hành - cho phiên bản hiện hành của N Developer Preview, bao gồm các ghi chú về thay đổi và - các báo cáo về sự khác biệt. -
      - -

      Tham khảo API có thể tải xuống

      - -

      - Trong các cập nhật preview có sớm bạn có thể tải xuống - Tham khảo API - mới nhất cho nền tảng Android N dưới dạng tệp lưu trữ zip riêng biệt. Bản tải xuống - tham khảo này cũng có một báo cáo về các khác biệt để giúp bạn nhận biết các thay đổi API từ - API 23 và bản cập nhật trước đó. -

      - -

      - Khi các API Android N hoàn thiện và được chỉ định một mức API chính thức, - chúng tôi sẽ cung cấp tham khảo API cho bạn trực tuyến tại https://developer.android.com. -

      - -

      - Tài nguyên Hỗ trợ -

      - -

      - Khi bạn kiểm thử và phát triển trên N Developer Preview, xin vui lòng sử dụng các kênh sau - để thông báo các vấn đề và gửi phản hồi. -

      - -
        -
      • Bộ theo dõi Vấn đề N Developer Preview - kênh phản hồi chính của bạn. Bạn có thể thông báo lỗi, các vấn đề về - hiệu năng và phản hồi chung thông qua bộ theo dõi vấn đề. Bạn cũng có thể kiểm tra -các vấn đề đã biết và - tìm các bước khắc phục. Chúng tôi sẽ cập nhật thông tin cho bạn về vấn đề của bạn khi nó đã được phân loại và gửi tới - nhóm kỹ thuật Android xem xét.
      • -
      • Cộng đồng Nhà phát triển Android N là - một cộng đồng Google+ nơi bạn có thể kết nối với các nhà phát triển khác đang thử nghiệm - Android N. Bạn có thể chia sẻ các phát hiện hoặc ý tưởng hoặc tìm câu trả lời cho các - thắc mắc về Android N. Chúng tôi sẽ điều hành cộng đồng này và cung cấp các câu trả lời và - hướng dẫn khi cần thiết.
      • -
      - -

      Nhắm mục tiêu, API xem trước và phát hành

      - -

      - N Developer Preview sẽ cung cấp một hệ thống và thư viện - Android chỉ dành cho phát triển mà không có mức API tiêu chuẩn. Nếu bạn muốn - bỏ các hành vi về khả năng tương thích để kiểm thử ứng dụng của mình (đặc biệt - khuyến cáo), bạn có thể nhắm mục tiêu phiên bản xem trước của Android N bằng cách thiết lập - targetSdkVersion - của ứng dụng thành “N”. -

      - -

      - Android N Developer Preview cung cấp các API xem trước - — các API này không phải bản chính thức cho đến khi SDK cuối cùng được phát hành, - hiện được dự kiến phát hành vào quý ba năm 2016. Điều này có nghĩa là có thể - có các thay đổi API nhỏ sau này, đặc biệt trong - các tuần đầu của chương trình. Chúng tôi sẽ cung cấp bản tóm tắt các thay đổi cho bạn theo - mỗi bản cập nhật của Android N Developer Preview. -

      - -

      - Lưu ý: Mặc dù các API xem trước có thể thay đổi nhưng - các hành vi hệ thống cơ bản vẫn ổn định và sẵn sàng để kiểm thử - ngay. -

      - -

      - Google Play không cho phép phát hành các ứng dụng nhắm mục tiêu tới N Developer - Preview. Khi có bản SDK cuối cùng của Android N bạn sẽ có thể - nhắm mục tiêu mức API Android N chính thức và phát hành ứng dụng của mình lên Google - Play thông qua các kênh phát hành alpha và beta. Trong thời gian này, nếu bạn muốn - phân phối một ứng dụng nhắm mục tiêu Android N cho người kiểm thử thì bạn có thể thực hiện phân phối qua email hoặc - bằng cách tải trực tiếp trên trang web của bạn. -

      - -

      - Khi Android N được phát hành hoàn chỉnh cho AOSP và OEM, dự kiến vào Q3 2016, - bạn có thể phát hành ứng dụng của mình nhắm mục tiêu Android N lên kênh - phát hành công chúng trong Google Play. -

      - - -

      Cách thức bắt đầu

      - -

      - Để bắt đầu kiểm thử ứng dụng của bạn với Android N: -

      - -
        -
      1. Xem lại Tổng quan về API - và Các thay đổi Hành vi để - biết được có những gì mới và nó sẽ tác động đến ứng dụng của bạn như thế nào. Đặc biệt, - hãy tìm hiểu về các tính năng thông báo mới và - hỗ trợ đa cửa sổ.
      2. -
      3. Thiết lập môi trường của bạn bằng cách làm theo các hướng dẫn để Preview SDK - và cấu hình các thiết bị kiểm thử.
      4. -
      5. Làm theo các hướng dẫn - flash để flash ảnh hệ thống Android N mới nhất cho thiết bị của bạn.
      6. -
      7. Xem lại Tham khảo API - và các ví dụ về Android N để hiểu - sâu hơn về các tính năng API mới cũng như cách sử dụng chúng trong ứng dụng của bạn. -
      8. Tham gia Cộng đồng - Nhà phát triển Android N để nhận được thông tin mới nhất và kết nối với các - nhà phát triển khác đang thử nghiệm với nền tảng mới.
      9. -
      - -

      - Cảm ơn bạn đã tham gia chương trình Android N Developer Preview! -

      diff --git a/docs/html-intl/intl/vi/preview/setup-sdk.jd b/docs/html-intl/intl/vi/preview/setup-sdk.jd deleted file mode 100644 index bdba71349087b60c7cc037b44885825540d821a2..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/vi/preview/setup-sdk.jd +++ /dev/null @@ -1,223 +0,0 @@ -page.title=Thiết lập Preview -meta.keywords="preview", "android" -page.tags="preview", "developer preview" -page.image=images/cards/card-n-sdk_2x.png - -@jd:body - - - - -

      Để phát triển các ứng dụng cho Android N Preview bạn cần thực hiện một số cập nhật -đối với môi trường phát triển của mình như mô tả trên trang này.

      - -

      Để đơn thuần thử khả năng tương thích của ứng dụng trên -ảnh hệ thống Android N, hãy làm theo hướng dẫn Kiểm thử trên một Thiết bị Android N.

      - - - - -

      Tải Android Studio 2.1 (bản xem trước)

      - -

      Nền tảng Android N bổ sung hỗ trợ cho các tính năng của ngôn ngữ Java 8, -yêu cầu phải có một trình biên dịch mới có tên là Jack. Phiên bản Jack mới nhất -hiện chỉ được hỗ trợ trong Android Studio 2.1. Do đó, nếu bạn muốn -sử dụng các tính năng của ngôn ngữ Java 8 thì bạn cần sử dụng Android Studio 2.1 để -dựng ứng dụng. Nếu không, bạn không cần sử dụng trình biên dịch Jack nhưng bạn -vẫn cần cập nhật lên JDK 8 để biên dịch cho nền tảng Android N, -như mô tả dưới đây. -

      - -

      Android Studio 2.1 hiện đang có dưới dạng bản xem trước trong kênh -phát hành Canary. Nếu bạn đã -có Android Studio và không muốn cập nhật lên kênh canary thì bạn có thể -tải xuống Android Studio 2.1 dưới dạng bản cài đặt riêng và sử dụng -để phát triển với Android N để không làm ảnh hưởng đến môi trường Android Studio -chính của bạn.

      - -

      Để tải xuống Android Studio 2.1 dưới dạng bản cài đặt riêng, hãy thực hiện -các bước sau (hoặc nếu bạn muốn nhận Android Studio 2.1 dưới dạng bản cập nhật cho -bản cài đặt có sẵn thì hãy chuyển đến bước 4):

      - -
        -
      1. Chỉnh sửa tên của - bản cài đặt Android Studio có sẵn và thêm số phiên bản. Làm như vậy - để khi bạn cài đặt, phiên bản mới sẽ không ghi đè lên phiên bản có sẵn.
      2. -
      3. Tải xuống tệp ZIP phù hợp cho hệ điều hành của bạn từ - trang tải xuống của kênh canary. -
      4. -
      5. Giải nén gói đó và chuyển các thành phần của Android Studio 2.1 tới - vị trí phù hợp cho các ứng dụng của bạn trên hệ thống rồi khởi chạy nó.
      6. -
      7. Mở hộp thoại Settings - (File > Settings trên Windows/Linux, hoặc - Android Studio > Preferences trên Mac). Trong khung - bên trái, chọnAppearance & Behavior > System Settings > - Updates. -
      8. -
      9. Trên khung Updates, chọn hộp kiểm Automatically - check updates for và chọn - Canary Channel từ danh sách thả xuống. -
      10. -
      - -

      Hãy để cửa sổ cài đặt này mở cho bước tiếp theo.

      - - -

      Tải N Preview SDK

      - -

      Để bắt đầu phát triển với các API Android N, bạn cần cài đặt - Android N Preview SDK trong Android Studio như sau:

      - -
        -
      1. Vẫn tại khung Updates (bước 4 bên trên), - hãy chọn hộp kiểm Automatically - check updates for Android SDK và chọn - Preview Channel từ danh sách thả xuống. -
      2. -
      3. Nhấp vào Check Now.
      4. - -
      5. Trong khung bên trái, chọn Appearance & Behavior > - System Settings > Android SDK. - -
      6. Nhấp vào tab SDK Platforms, rồi chọn hộp kiểm - Android N Preview.
      7. - -
      8. Nhấp vào tab SDK Tools, rồi chọn - Android SDK Build Tools, Android SDK - Platform-Tools, và các hộp kiểm Android SDK Tools -. -
      9. - -
      10. Nhấp vào OK, sau đó đồng ý với các thỏa thuận - cấp phép cho các gói cần được cài đặt. -
      11. -
      - -

      Tải tài liệu tham khảo cho N Preview

      - -

      - Thông tin chi tiết về các API Android N có trong tài liệu tham khảo của - Bản xem trước N mà bạn có thể tải xuống từ bảng sau. - Gói này có một bản ngoại tuyến được rút gọn của trang web - cho nhà phát triển Android và có một bản tham khảo API được cập nhật cho API Android N, một - báo cáo về sự khác biệt API. -

      - - - - - - - - - - -
      Tài liệuTổng kiểm
      - n-preview-1-docs.zip - MD5: 4ab33ccbe698f46f125cc5b807cf9c2f
      - SHA-1: 6a3880b3ccd19614daae5a4d0698ea6ae11c20a5 -
      - - - -

      Tải JDK và JRE của Java 8

      - -

      Để biên dịch ứng dụng của bạn cho nền tảng Android N, bạn cần sử dụng -Bộ công cụ phát triển Java 8 (JDK 8) và để sử dụng một số công cụ với Android -Studio 2.1 thì bạn cần cài đặt Java 8 Runtime Environment (JRE). Vì vậy, nếu -bạn không có phiên bản mới nhất của mỗi bộ thì hãy tải xuống JDK 8 và JRE 8 -ngay.

      - -

      Sau đó đặt phiên bản JDK trong Android Studio như sau:

      - -
        -
      1. Mở một dự án Android trong Android Studio, sau đó mở - hộp thoại Project Structure bằng cách chọn File > - Project Structure. (Bằng cách khác, bạn có thể đặt mặc định - cho mọi dự án bằng cách chọn File > Other Settings > - Default Project Structure.) -
      2. -
      3. Trong khung bên trái của hộp thoại, hãy nhấp SDK Location. -
      4. -
      5. Trong ô JDK Location, hãy nhập vị trí của - Java 8 JDK (nhấp vào nút bên phải - để duyệt tìm tệp của bạn), sau đó nhấp OK. -
      6. -
      - - - - -

      Cập nhật hoặc Tạo một dự án

      - -

      - Dự án của bạn phải được cấu hình phù hợp để sử dụng các API Android N. -

      - -

      Nếu bạn dự định sử dụng các tính năng của ngôn ngữ Java 8 thì bạn cũng nên đọc mục -Các tính năng của Ngôn ngữ Java 8 -để biết thêm thông tin về các tính năng của Java 8 được hỗ trợ và -cách cấu hình dự án với trình biên dịch Jack.

      - - -

      Cập nhật một dự án có sẵn

      - -

      Mở tệp - build.gradle cho mô-đun của bạn và cập nhật các giá trị như - sau: -

      - -
      -android {
      -  compileSdkVersion 'android-N'
      -  buildToolsVersion '24.0.0-rc1'
      -  ...
      -
      -  defaultConfig {
      -     minSdkVersion 'N'
      -     targetSdkVersion 'N'
      -     ...
      -  }
      -  ...
      -}
      - - -

      Tạo một dự án mới

      - - -

      Để tạo một dự án mới để phát triển với Android N Preview SDK:

      - -
        -
      1. Nhấp vào File > New Project. và thực hiện theo các bước đến khi - bạn đến trang Target Android Devices. -
      2. -
      3. Trong trang này, hãy chọn tùy chọn Phone and Tablet.
      4. -
      5. Dưới tùy chọn Phone and Tablet, trong danh sách tùy chọn Minimum - SDK hãy chọn - N: Android API 23, N Preview (Preview).
      6. -
      - - -

      Các bước tiếp theo

      - - diff --git a/docs/html-intl/intl/vi/preview/features/direct-boot.jd b/docs/html-intl/intl/vi/training/articles/direct-boot.jd similarity index 98% rename from docs/html-intl/intl/vi/preview/features/direct-boot.jd rename to docs/html-intl/intl/vi/training/articles/direct-boot.jd index d95d83103b151096d90ba0638229c8f932b13aad..c93e2552e2080c505314e9d675e0a806fe4f5e4d 100644 --- a/docs/html-intl/intl/vi/preview/features/direct-boot.jd +++ b/docs/html-intl/intl/vi/training/articles/direct-boot.jd @@ -5,8 +5,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
      -
      +
      +

      Trong tài liệu này

      1. Yêu cầu Truy cập để Chạy trong quá trình Khởi động Trực tiếp
      2. @@ -81,7 +81,7 @@ bộ lọc ý định cho LOCKED_BOOT_COMPLETED trong bản kê kha </receiver>
    -

    Khi người dùng đã mở khóa thiết bị thì mọi thành phần có thể truy cập +

    Khi người dùng đã mở khóa thiết bị thì mọi thành phần có thể truy cập cả bộ nhớ lưu trữ mã hóa thiết bị lẫn bộ nhớ lưu trữ mã hóa thông tin xác thực.

    Truy cập Bộ nhớ Lưu trữ Mã hóa của Thiết bị

    @@ -89,7 +89,7 @@ cả bộ nhớ lưu trữ mã hóa thiết bị lẫn bộ nhớ lưu trữ mã

    Để truy cập bộ nhớ lưu trữ mã hóa thiết bị, hãy tạo một thực thể {@link android.content.Context} thứ hai bằng cách gọi Context.createDeviceEncryptedStorageContext(). Tất cả các lệnh gọi -API bộ nhớ lưu trữ đều sử dụng bối cảnh này để truy cập bộ nhớ lưu trữ mã hóa thiết bị. +API bộ nhớ lưu trữ đều sử dụng bối cảnh này để truy cập bộ nhớ lưu trữ mã hóa thiết bị. Ví dụ sau sẽ truy cập bộ nhớ lưu trữ mã hóa của thiết bị và mở một tệp dữ liệu ứng dụng có sẵn:

    diff --git a/docs/html-intl/intl/vi/preview/features/scoped-folder-access.jd b/docs/html-intl/intl/vi/training/articles/scoped-directory-access.jd similarity index 96% rename from docs/html-intl/intl/vi/preview/features/scoped-folder-access.jd rename to docs/html-intl/intl/vi/training/articles/scoped-directory-access.jd index d6db0ece657af50e50cb4723f2fcd9aa80c4e270..a4d97796aaa36f14b5742843f3b8901a6d670b0e 100644 --- a/docs/html-intl/intl/vi/preview/features/scoped-folder-access.jd +++ b/docs/html-intl/intl/vi/training/articles/scoped-directory-access.jd @@ -4,8 +4,8 @@ page.tags=androidn @jd:body -
    -
    +
    +

    Trong tài liệu này

    1. Truy cập một Thư mục lưu trữ bên ngoài
    2. @@ -57,8 +57,8 @@ startActivityForResult(intent, request_code);

      Hệ thống sẽ cố gắng cấp quyền truy cập tới thư mục bên ngoài và nếu cần sẽ xác nhận quyền truy cập với người dùng bằng một UI được đơn giản hóa:

      - +

      Hình 1. Một ứng dụng yêu cầu truy cập tới thư mục Pictures.

      diff --git a/docs/html-intl/intl/vi/preview/features/security-config.jd b/docs/html-intl/intl/vi/training/articles/security-config.jd similarity index 99% rename from docs/html-intl/intl/vi/preview/features/security-config.jd rename to docs/html-intl/intl/vi/training/articles/security-config.jd index 797e198a15ab103ee1416a6b1951b6f6bf42a97b..1d8670df08514584e9eba8dcda44988ead7a105b 100644 --- a/docs/html-intl/intl/vi/preview/features/security-config.jd +++ b/docs/html-intl/intl/vi/training/articles/security-config.jd @@ -4,8 +4,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
      -
      +
      +

      Trong tài liệu này

        diff --git a/docs/html-intl/intl/vi/training/material/animations.jd b/docs/html-intl/intl/vi/training/material/animations.jd index e93c99d64508f1ff9efb54a993c978f494d19674..9299d3c931a89579f14f49e7ecf025137c312bb0 100644 --- a/docs/html-intl/intl/vi/training/material/animations.jd +++ b/docs/html-intl/intl/vi/training/material/animations.jd @@ -21,7 +21,7 @@ page.title=Định nghĩa Hoạt hình Tùy chỉnh
      -

      Hoạt hình theo phong cách material design phản hồi hành động của người dùng và cung cấp +

      Hoạt hình theo phong cách material design phản hồi hành động của người dùng và cung cấp tính liên tục trực quan khi người dùng tương tác với ứng dụng của bạn. Giao diện material cung cấp một số hoạt hình mặc định cho các nút và chuyển tiếp hoạt động, và Android 5.0 (API mức 21) và cao hơn cho phép bạn tùy chỉnh những hoạt hình này và tạo các hoạt hình mới:

      @@ -160,7 +160,7 @@ trung tâm.
    3. Chuyển tiếp phần tử chung xác định các dạng xem chung giữa hai hoạt động sẽ chuyển tiếp như thế nào giữa những hoạt động này. Ví dụ, nếu hai hoạt động có cùng -hình ảnh ở các vị trí và kích cỡ khác nhau, chuyển tiếp phần tử chung changeImageTransform +hình ảnh ở các vị trí và kích cỡ khác nhau, chuyển tiếp phần tử chung changeImageTransform sẽ thể hiện và co giãn hình ảnh một cách mượt mà giữa những hoạt động này.
    4. @@ -329,7 +329,7 @@ thay vì {@link android.app.Activity#finish Activity.finish()}.

      Để tạo một hoạt hình chuyển tiếp cảnh giữa hai hoạt động có nhiều hơn một phần tử chung, hãy định nghĩa các phần tử chung trong cả hai bố trí bằng thuộc tính android:transitionName - (hoặc sử dụng phương thức {@link android.view.View#setTransitionName View.setTransitionName()} + (hoặc sử dụng phương thức {@link android.view.View#setTransitionName View.setTransitionName()} trong cả hai hoạt động), và tạo một đối tượng {@link android.app.ActivityOptions} như sau:

      diff --git a/docs/html-intl/intl/vi/training/material/compatibility.jd b/docs/html-intl/intl/vi/training/material/compatibility.jd
      index e19a745dd9b9819742c86cbdb81c7048be399f32..2f5c0160f67577e78f5725492473d5b884432fd9 100644
      --- a/docs/html-intl/intl/vi/training/material/compatibility.jd
      +++ b/docs/html-intl/intl/vi/training/material/compatibility.jd
      @@ -94,7 +94,7 @@ r21 và cao hơn gồm những tính năng material design sau:

      Bảng màu

      -

      Để có được các kiểu phong cách material design và tùy chỉnh bảng màu bằng Thư viện Hỗ trợ v7 +

      Để có được các kiểu phong cách material design và tùy chỉnh bảng màu bằng Thư viện Hỗ trợ v7 của Android, hãy áp dụng một trong các chủ đề Theme.AppCompat:

      diff --git a/docs/html-intl/intl/vi/training/material/drawables.jd b/docs/html-intl/intl/vi/training/material/drawables.jd
      index 175e77d629e8ab5a5e125eebd4ab3a374f181929..db69412c544e0e3cd2d9fc05987a0b2b73f4e20e 100644
      --- a/docs/html-intl/intl/vi/training/material/drawables.jd
      +++ b/docs/html-intl/intl/vi/training/material/drawables.jd
      @@ -57,7 +57,7 @@ Lớp này trích xuất những màu nổi bật sau:

    5. Sáng lặng
    6. -

      Để trích xuất những màu này, hãy chuyển một đối tượng {@link android.graphics.Bitmap} cho phương thức tĩnh +

      Để trích xuất những màu này, hãy chuyển một đối tượng {@link android.graphics.Bitmap} cho phương thức tĩnh {@link android.support.v7.graphics.Palette#generate Palette.generate()} trong luồng chạy ngầm nơi bạn tải hình ảnh của mình. Nếu bạn không thể sử dụng luồng đó, hãy gọi phương thức {@link android.support.v7.graphics.Palette#generateAsync Palette.generateAsync()} và diff --git a/docs/html-intl/intl/vi/training/material/get-started.jd b/docs/html-intl/intl/vi/training/material/get-started.jd index 9e612ad10c07c25326a611551615ec98517ac695..45d7c09e3e0b1004319ff3c55fa5bcdf0ce9537b 100644 --- a/docs/html-intl/intl/vi/training/material/get-started.jd +++ b/docs/html-intl/intl/vi/training/material/get-started.jd @@ -94,7 +94,7 @@ bố trí của bạn, hãy đặc biệt chú ý tới điều sau đây:

      Quy định Độ cao trong Dạng xem của Bạn

      -

      Dạng xem có thể đổ bóng và giá trị độ cao của một dạng xem +

      Dạng xem có thể đổ bóng và giá trị độ cao của một dạng xem xác định kích cỡ bóng và thứ tự vẽ của nó. Để đặt độ cao của một dạng xem, hãy sử dụng thuộc tính android:elevation trong bố trí của bạn:

      @@ -122,7 +122,7 @@ chạm.

      {@link android.support.v7.widget.RecyclerView} là một phiên bản dễ ghép nối hơn của {@link android.widget.ListView} có hỗ trợ các kiểu bố trí khác nhau và cung cấp những cải tiến về hiệu năng. {@link android.support.v7.widget.CardView} cho phép bạn hiện các mẩu thông tin bên trong thẻ với -một diện mạo nhất quán giữa các ứng dụng. Ví dụ về mã sau đây minh họa cách thêm +một diện mạo nhất quán giữa các ứng dụng. Ví dụ về mã sau đây minh họa cách thêm {@link android.support.v7.widget.CardView} vào bố trí của bạn:

      diff --git a/docs/html-intl/intl/vi/training/material/index.jd b/docs/html-intl/intl/vi/training/material/index.jd
      index 44b74e1826fdffd35b137ea48a6527080f5ba260..eb489457e7c2115c5a092a1c8d486543f22891d9 100644
      --- a/docs/html-intl/intl/vi/training/material/index.jd
      +++ b/docs/html-intl/intl/vi/training/material/index.jd
      @@ -17,7 +17,7 @@ page.metaDescription=Tìm hiểu cách áp dụng material design cho ứng dụ
       
       

      Material design là một hướng dẫn toàn diện về thiết kế trực quan, chuyển động và tương tác giữa nhiều nền tảng và thiết bị. Để sử dụng material design trong ứng dụng Androi của mình, hãy làm theo hướng dẫn -mô tả trong +mô tả trong đặc tả material design và sử dụng những thành phần và tính năng mới sẵn có trong Android 5.0 (API mức 21).

      diff --git a/docs/html-intl/intl/vi/training/material/lists-cards.jd b/docs/html-intl/intl/vi/training/material/lists-cards.jd index 7127649bda830b8be081cb1366a266e5e946d974..47a7d6f8f3b4897a9631e41b4a99507080660612 100644 --- a/docs/html-intl/intl/vi/training/material/lists-cards.jd +++ b/docs/html-intl/intl/vi/training/material/lists-cards.jd @@ -210,7 +210,7 @@ android.support.v7.widget.CardView} có thể có đổ bóng và góc bo tròn. Để biết thêm thông tin, hãy xem phần Duy trì Tính tương thích.

      -

      Sử dụng những thuộc tính sau để tùy chỉnh diện mạo của widget +

      Sử dụng những thuộc tính sau để tùy chỉnh diện mạo của widget {@link android.support.v7.widget.CardView}:

        diff --git a/docs/html-intl/intl/vi/training/material/shadows-clipping.jd b/docs/html-intl/intl/vi/training/material/shadows-clipping.jd index e9091f289fcb1a4390a891444fc409462b4108a9..f4ce4025963f4e0e20adc796e482a7cd686264a4 100644 --- a/docs/html-intl/intl/vi/training/material/shadows-clipping.jd +++ b/docs/html-intl/intl/vi/training/material/shadows-clipping.jd @@ -22,7 +22,7 @@ page.title=Định nghĩa Đổ bóng và Dạng xem Cắt hình tầm quan trọng tương đối của từng phần tử và tập chung sự chú ý của họ vào tác vụ hiện có.

        Độ cao của một dạng xem, được biểu diễn bằng thuộc tính Z, sẽ xác định diện mạo trực quan của -bóng đổ: dạng xem có giá trị Z cao hơn sẽ đổ bóng lớn hơn, mềm hơn. Dạng xem có giá trị Z cao hơn sẽ che khuất dạng xem +bóng đổ: dạng xem có giá trị Z cao hơn sẽ đổ bóng lớn hơn, mềm hơn. Dạng xem có giá trị Z cao hơn sẽ che khuất dạng xem có giá trị Z thấp hơn; tuy nhiên, giá trị Z của một dạng xem không ảnh hưởng tới kích cỡ của dạng xem.

        Đổ bóng được vẽ bởi dạng xem mẹ của dạng xem cao hơn, do vậy nó phụ thuộc vào tiêu chuẩn cắt dạng xem, @@ -51,7 +51,7 @@ trong không gian 3D.

        Hình 1 - Đổ bóng cho các độ cao dạng xem khác nhau.

        Để đặt độ cao của dạng xem trong một định nghĩa bố trí, hãy sử dụng thuộc tính android:elevation -. Để đặt độ cao của dạng xem trong mã của một hoạt động, hãy sử dụng phương thức +. Để đặt độ cao của dạng xem trong mã của một hoạt động, hãy sử dụng phương thức {@link android.view.View#setElevation View.setElevation()}.

        Để đặt độ dịch của dạng xem, hãy sử dụng phương thức {@link android.view.View#setTranslationZ @@ -59,7 +59,7 @@ View.setTranslationZ()}.

        Các phương thức {@link android.view.ViewPropertyAnimator#z ViewPropertyAnimator.z()} và {@link android.view.ViewPropertyAnimator#translationZ ViewPropertyAnimator.translationZ()} mới cho phép -bạn dễ dàng tạo hiệu ứng hoạt hình cho độ cao của dạng xem. Để biết thêm thông tin, hãy xem tài liệu tham khảo API cho +bạn dễ dàng tạo hiệu ứng hoạt hình cho độ cao của dạng xem. Để biết thêm thông tin, hãy xem tài liệu tham khảo API cho {@link android.view.ViewPropertyAnimator} và hướng dẫn cho nhà phát triển về Hoạt hình Thuộc tính .

        diff --git a/docs/html-intl/intl/vi/preview/features/picture-in-picture.jd b/docs/html-intl/intl/vi/training/tv/playback/picture-in-picture.jd similarity index 98% rename from docs/html-intl/intl/vi/preview/features/picture-in-picture.jd rename to docs/html-intl/intl/vi/training/tv/playback/picture-in-picture.jd index 4b3cb400f72ea5d7b4808f20b36705eb70604ccb..9156152eb0d08459d1fbc11767576cb1deba4d9c 100644 --- a/docs/html-intl/intl/vi/preview/features/picture-in-picture.jd +++ b/docs/html-intl/intl/vi/training/tv/playback/picture-in-picture.jd @@ -4,8 +4,8 @@ page.tags=androidn @jd:body -
        -
        +
        +

        Trong tài liệu này

          @@ -57,7 +57,7 @@ PIP bằng cách bấm giữ nút Home trên điều khiển từ xa. N khác bắt đầu phát trên màn hình chính, cửa sổ PIP sẽ tự động được đóng. Người dùng cũng có thể đóng cửa sổ PIP thông qua nút Recents.

          - +

          Hình 1. Một video Ảnh trong ảnh được hiển thị ở góc màn hình khi người dùng duyệt nội dung trên màn hình chính.

          @@ -114,7 +114,7 @@ public void onActionClicked(Action action) {

          Thêm một nút PIP vào thanh điều khiển media của bạn sẽ cho phép người dùng dễ dàng chuyển sang chế độ PIP khi điều khiển phát lại video.

          - +

          Hình 1. Một nút Ảnh trong ảnh trên thanh điều khiển media.

          @@ -128,7 +128,7 @@ các hành động ở chế độ PIP trên thanh điều khiển và sử dụ video. Hãy xóa các phần tử UI trước khi hoạt động của bạn vào chế độ PIP, và khôi phục các phần tử này khi hoạt động quay lại chế độ toàn màn hình. Ghi đè phương thức Activity.onPictureInPictureChanged() hoặc -Fragment.onPictureInPictureChanged() và bật hoặc +Fragment.onPictureInPictureChanged() và bật hoặc tắt các phần tử UI khi cần thiết, ví dụ:

          @@ -150,7 +150,7 @@ public void onPictureInPictureChanged(boolean inPictureInPicture) {
           

          Khi hoạt động của bạn chuyển sang chế độ PIP thì hệ thống sẽ coi hoạt động đó đang ở trong trạng thái tạm dừng và sẽ gọi phương thức onPause() của hoạt động. Việc phát lại video không nên được tạm dừng và cần được tiếp tục phát nếu hoạt động -bị tạm dừng do chế độ PIP. Hãy kiểm tra chế độ PIP trong phương thức +bị tạm dừng do chế độ PIP. Hãy kiểm tra chế độ PIP trong phương thức onPause() của hoạt động và xử lý việc phát lại cho phù hợp, ví dụ:

          diff --git a/docs/html-intl/intl/vi/preview/features/tv-recording-api.jd b/docs/html-intl/intl/vi/training/tv/tif/content-recording.jd similarity index 99% rename from docs/html-intl/intl/vi/preview/features/tv-recording-api.jd rename to docs/html-intl/intl/vi/training/tv/tif/content-recording.jd index 6dfb53ea3c9a54531e9856bbcc309d6b31262040..bfd718b289861cd458a1e71c2584d18c3c203362 100644 --- a/docs/html-intl/intl/vi/preview/features/tv-recording-api.jd +++ b/docs/html-intl/intl/vi/training/tv/tif/content-recording.jd @@ -5,8 +5,8 @@ page.image=images/cards/card-nyc_2x.jpg @jd:body -
          -
          +
          +

          Trong tài liệu này

          1. Chỉ báo Hỗ trợ ghi lại
          2. diff --git a/docs/html-intl/intl/zh-cn/about/versions/android-5.0.jd b/docs/html-intl/intl/zh-cn/about/versions/android-5.0.jd index 8e20975eb5124154cff71e0f04efa4a6cb9bcd13..81591450ec8fc06851626bb1b5764d7e1b64cc48 100644 --- a/docs/html-intl/intl/zh-cn/about/versions/android-5.0.jd +++ b/docs/html-intl/intl/zh-cn/about/versions/android-5.0.jd @@ -430,7 +430,7 @@ sdk.platform.apiLevel=21

            当系统检测到合适的网络时,它将连接到该网络并调用 {@link android.net.ConnectivityManager.NetworkCallback#onAvailable(android.net.Network) onAvailable()} 回调。您可以在回调中使用 {@link android.net.Network} 对象来获取关于该网络的更多信息,或者指示通信使用选定的网络。

            低功耗蓝牙

            -

            Android 4.3 中作为重头戏引入了对低功耗蓝牙(“低功耗蓝牙”)的平台支持。在 Android 5.0 中,Android 设备现在可以用作低功耗蓝牙外围设备。应用可以使用此功能使附近的设备知道它的存在。例如,您可以构建相应的应用来允许设备用作计步器或健康检测器并与另一低功耗蓝牙设备交换其数据。

            +

            Android 4.3 中作为重头戏引入了对低功耗蓝牙(“低功耗蓝牙”)的平台支持。在 Android 5.0 中,Android 设备现在可以用作低功耗蓝牙外围设备。应用可以使用此功能使附近的设备知道它的存在。例如,您可以构建相应的应用来允许设备用作计步器或健康检测器并与另一低功耗蓝牙设备交换其数据。

            新的 {@link android.bluetooth.le} API 允许您的应用对公告进行广播,扫描响应,以及与附近的低功能蓝牙设备建立连接。要使用新的公告和扫描功能,请在您的清单中添加 {@link android.Manifest.permission#BLUETOOTH_ADMIN BLUETOOTH_ADMIN} 权限。当用户从 Play 商店更新或下载您的应用时,会要求他们向您的应用授予以下权限:“蓝牙连接信息:允许应用控制蓝牙,包括向附近的蓝牙设备进行广播以及获取关于这些设备的信息。”

            要开始低功耗蓝牙公告以便其他设备可以发现您的应用,请调用 {@link android.bluetooth.le.BluetoothLeAdvertiser#startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback) startAdvertising()} 并传入 {@link android.bluetooth.le.AdvertiseCallback} 类的一个实施。回调对象将收到关于公告操作成功或失败的报告。

            diff --git a/docs/html-intl/intl/zh-cn/preview/guide.jd b/docs/html-intl/intl/zh-cn/about/versions/marshmallow/android-6.0-testing.jd similarity index 99% rename from docs/html-intl/intl/zh-cn/preview/guide.jd rename to docs/html-intl/intl/zh-cn/about/versions/marshmallow/android-6.0-testing.jd index 9f7737f7e62828192f174ff6185d153a5f2e531f..d1e118741cff0abb2a0fa0580d2e40c05468047d 100644 --- a/docs/html-intl/intl/zh-cn/preview/guide.jd +++ b/docs/html-intl/intl/zh-cn/about/versions/marshmallow/android-6.0-testing.jd @@ -5,8 +5,8 @@ page.tags="preview", "developer preview" @jd:body -
            -
            +
            +

            本文内容

            1. 测试权限
            2. diff --git a/docs/html-intl/intl/zh-cn/preview/behavior-changes.jd b/docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0-changes.jd similarity index 98% rename from docs/html-intl/intl/zh-cn/preview/behavior-changes.jd rename to docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0-changes.jd index 4e3a6b5854e06cc7a1b97fae8ba623f3d0cb03b3..71aff37720d2d6b8370cae388169aa54ab1a5a66 100644 --- a/docs/html-intl/intl/zh-cn/preview/behavior-changes.jd +++ b/docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0-changes.jd @@ -6,8 +6,8 @@ page.image=images/cards/card-n-changes_2x.png @jd:body -
              -
              +
              +

              本文内容

              @@ -77,7 +77,7 @@ Android N 包括旨在延长设备电池寿命和减少 RAM 使用的系统行

              - +

              图 1. 低电耗模式如何应用第一级系统活动限制以延长电池寿命的图示。 @@ -96,7 +96,7 @@ Android N 包括旨在延长设备电池寿命和减少 RAM 使用的系统行

              - +

              图 2. 低电耗模式如何在设备处于静止状态达到一定时间后应用第二级系统活动限制的图示。 @@ -282,10 +282,10 @@ android.hardware.Camera#ACTION_NEW_VIDEO} 广播。此项优化会影响所有

              - +
              - +
              diff --git a/docs/html-intl/intl/zh-cn/preview/samples.jd b/docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0-samples.jd similarity index 74% rename from docs/html-intl/intl/zh-cn/preview/samples.jd rename to docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0-samples.jd index dd68566df7c1619ec0d9050cf7164cbfb248b448..600e33a6b05919a167fcb11d19200cf1ac9cd47b 100644 --- a/docs/html-intl/intl/zh-cn/preview/samples.jd +++ b/docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0-samples.jd @@ -16,7 +16,7 @@ page.image=images/cards/card-n-samples_2x.png

              多窗口 Playground

              - +

              此示例演示如何在您的应用中充分利用多窗口用户界面。 @@ -28,7 +28,7 @@ page.image=images/cards/card-n-samples_2x.png

              活动通知

              - +

              这是一个已存在的示例,其显示一个使用 NotificationCompat 发送通知的简单服务。该服务将来自用户的每个未读会话以不同的通知形式发送。 @@ -45,7 +45,7 @@ page.image=images/cards/card-n-samples_2x.png

              消息传递服务

              - +

              这是一个已存在的示例,其演示如何使用 NotificationManager 指示应用当前显示的通知数量。 @@ -62,7 +62,7 @@ page.image=images/cards/card-n-samples_2x.png

              直接启动

              - +

              此示例显示如何在设备加密的存储(启动设备后始终可用)中存储和访问数据。 @@ -74,7 +74,7 @@ page.image=images/cards/card-n-samples_2x.png

              作用域目录访问

              - +

              此示例演示如何从特定目录读取和写入数据,同时需要较少的权限。 @@ -82,4 +82,4 @@ page.image=images/cards/card-n-samples_2x.png

              在 GitHub 中获取 -

              \ No newline at end of file +

              diff --git a/docs/html-intl/intl/zh-cn/preview/api-overview.jd b/docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0.jd similarity index 98% rename from docs/html-intl/intl/zh-cn/preview/api-overview.jd rename to docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0.jd index 495692ac2d85f2f71a72053690552bd38786af20..8810d39a12e6440384a61e139998ffc5b19661af 100644 --- a/docs/html-intl/intl/zh-cn/preview/api-overview.jd +++ b/docs/html-intl/intl/zh-cn/about/versions/nougat/android-7.0.jd @@ -7,8 +7,8 @@ page.image=images/cards/card-n-apis_2x.png -
              -
              +
              +

              重要的开发者功能

                  @@ -78,7 +78,7 @@ page.image=images/cards/card-n-apis_2x.png
                - +

                图 1. 在分屏模式下运行的应用。

                @@ -142,15 +142,15 @@ page.image=images/cards/card-n-apis_2x.png
      - +
      - +
      - +
      @@ -277,7 +277,7 @@ JobScheduler 可实现控制和简洁性,我们想要所有应用都使用它

      Data Saver

      - +

      图 4. 设置中的 Data Saver @@ -357,7 +357,7 @@ Vulkan 还允许多个线程同时执行工作,如命令缓冲区构建,以

      - +

      图 5. 通知栏中的快速设置图块。 @@ -762,7 +762,7 @@ Android 扩展包 (AEP) 的所有扩展(EXT_texture_sRGB_decode<

      虽然我们建议您对您的应用采用 APK Signature Scheme v2,但这项新方案并非强制性的。 如果您的应用在使用 APK Signature Scheme v2 时不能正确构建,您可以停用这项新方案。 -禁用过程会导致 Android Studio 2.2 和 Android Gradle 2.2 插件仅使用传统签名方案来签署您的应用。 +禁用过程会导致 Android Studio 2.2 和 Android Gradle 2.2 插件仅使用传统签名方案来签署您的应用。 若要仅用传统方案签署,打开多层 build.gradle 文件,然后将行 v2SigningEnabled false 添加到您的版本签名配置中: @@ -970,7 +970,7 @@ API 提供了一个包含计时数据的 {@code FrameMetrics} 对象,其渲染 虚拟文件功能可以让您的 {@link android.provider.DocumentsProvider} 返回可与 {@link android.content.Intent#ACTION_VIEW}Intent 使用的文件 URI,即使它们没有直接字节码表示。 -Android N 还允许您为用户文件(虚拟或其他类)提供备用格式。 +Android N 还允许您为用户文件(虚拟或其他类)提供备用格式。

      diff --git a/docs/html-intl/intl/zh-cn/about/versions/nougat/index.jd b/docs/html-intl/intl/zh-cn/about/versions/nougat/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..5619de8f036886b9f94eacf8ea1d716ffa4e548d --- /dev/null +++ b/docs/html-intl/intl/zh-cn/about/versions/nougat/index.jd @@ -0,0 +1,110 @@ +page.title=Android 7.0 Nougat +page.tags="androidn","versions" +meta.tags="android n", "nougat", "android 7.0" +fullpage=true +forcelocalnav=true +header.hide=1 +footer.hide=1 +@jd:body + +
      + +
      + + + + +
      +

      最新

      +
      +
      + +
      +

      Videos

      +
      + New Android capabilities and the right way to use them in your apps. +
      + +
      +
      +
      + +
      +

      资源

      +
      + 这些必备信息可帮助您的应用为Android Nougat做好准备。 +
      + +
      +
      +
      \ No newline at end of file diff --git a/docs/html-intl/intl/zh-cn/design/patterns/notifications.jd b/docs/html-intl/intl/zh-cn/design/patterns/notifications.jd deleted file mode 100644 index 57e02e44942c36e29ba97d3ce107b4c971309f63..0000000000000000000000000000000000000000 --- a/docs/html-intl/intl/zh-cn/design/patterns/notifications.jd +++ /dev/null @@ -1,872 +0,0 @@ -page.title=通知 -page.tags="notifications","design","L" -@jd:body - - -
      -

      开发者文档

      -

      通知用户

      -
      -
      - - -
      -

      Android 4.4 及更低版本中的通知

      -
      -
      - - - -
      -

      视频

      -

      DevBytes:Android L 开发者预览当中的通知

      -
      -
      - - - -

      通知系统可让用户随时了解应用中的相关和即时事件,例如来自好友的新聊天信息或日历事件。可将通知视作新闻频道,在重要的事件发生时提醒用户注意,或者当作日志,在用户未注意时记录事件—可在用户的所有 Android 设备上按需同步。 - - - - - -

      - -

      Android 5.0 新增内容

      - -

      在 Android 5.0 中,通知在结构、外观和功能方面获得了重要的更新: -

      - -
        -
      • 通知在外观上发生了更改,与新的材料设计主题保持一致。 -
      • -
      • 通知现在可以在设备锁定屏幕上使用,而敏感信息仍然可以隐藏于背后。 - -
      • -
      • 设备在使用时收到的高优先级通知现在采用名为浮动通知的新格式。 -
      • -
      • 云同步通知:在一台 Android 设备上清除通知,则在其他设备上也会将其清除。 - -
      • -
      - -

      注:该版本 Android 的通知设计与之前的版本大不相同。 - -有关之前版本通知设计的信息,请参阅 Android 4.4 及更低版本中的通知。 -

      - -

      通知详解

      - -

      本部分介绍通知的基本组成部分,及其在不同类型设备上显示的方式。 -

      - -

      基本布局

      - -

      所有通知至少要包括一个基本布局,包括:

      - -
        -
      • 通知的图标。图标以符号形式表示来源应用。如果应用生成多个类型的通知,它也可用于指明通知类型。 - - -
      • -
      • 通知标题以及其他 -文本
      • -
      • 时间戳
      • -
      - -

      利用 {@link android.app.Notification.Builder Notification.Builder}为之前版本平台创建的通知,其外观和行为方式与在 Android -5.0 中完全相同,唯一的变动在于系统为您处理通知的方式存在细微的样式变动。 - -如需了解之前 Android 版本通知设计的详细信息,请参阅 Android 4.4 及更低版本中的通知。 - -

      - - - - - -
      -

      - 手持设备通知(左)和穿戴设备(右)上同一通知的基本布局,带有用户照片和通知图标 - -

      -
      - -

      展开布局

      - - -

      您可以选择让应用的通知提供多少信息详情。 -它们可显示消息的前几行,也可以显示更大的预览图像。 -额外的信息可以为用户提供更多上下文,并且,在某些情况下,可能允许用户完整阅读消息。 - - -用户可进行两指缩放或执行单指滑移,在紧凑和展开布局之间切换。 - - - 对于单一事件通知,Android 提供了三种展开布局模板(文本、收件箱和图像),供您在应用中使用。 - -下图展示单一事件通知在手持设备(左)和穿戴式设备(右)上的外观。 - -

      - - - - - -

      操作

      - -

      Android 支持在通知底部显示可选的操作。通过操作,用户可在通知栏中处理最常见的任务,而无需打开来源应用。这样可加快交互的速度,而通过结合使用滑动清除通知的功能,有助于用户专注于对自身重要的通知。 - - - - - -

      - - - - - - -

      请慎重考虑要在通知中包含多少操作。 -您加入的操作越多,用户就越无所适从。 -请通过只包含最重要且有意义的操作,尽量减少通知中的操作数量。 - - -

      - -

      适合在通知中使用的操作具有如下特点:

      - -
        -
      • 对正在显示的内容类型必要、常用且常见 - -
      • 让用户可以迅速完成任务 -
      - -

      避免以下类型的操作:

      - -
        -
      • 含义模糊 -
      • 跟通知的默认操作一样(例如“阅读”或“打开”) - -
      - - - -

      您最多可以指定三个操作,每个操作由操作图标和名称组成。 - - 通过为简单的基本布局添加操作,可以展开该通知,即使该通知没有展开布局,此方法仍然有效。 - -由于操作仅对展开的通知显示(否则会隐藏),因此要确保用户从通知调用的任何操作都可在相关联的应用中使用。 - - - - -

      - -

      浮动通知

      -
      - -

      - 出现在沉浸式应用顶部的浮动通知(手机来电,高优先级)示例 - - -

      -
      - -

      收到高优先级通知时(见右侧),它会向用户短时间显示一个包含可选操作的展开布局。 - -

      -

      之后,通知会缩回通知栏。 -如果通知的优先级标志为高、最大或全屏,则会得到浮动通知。 -

      - -

      浮动通知的范例

      - -
        -
      • 使用设备时来电
      • -
      • 使用设备时闹铃
      • -
      • 新的短信
      • -
      • 电池电量过低
      • -
      - -

      指导原则

      - - -

      个人化

      - -

      对于他人发送的项目通知(例如消息或状态更新),请使用 -{@link android.app.Notification.Builder#setLargeIcon setLargeIcon()} 包含此人的头像。 -另外将有关此人的信息附加到通知的元数据(参阅 {@link android.app.Notification#EXTRA_PEOPLE})。 -

      - -

      您通知的主图标仍然会显示,因此,该用户可将其与状态栏中显示的图标相关联。 - -

      - - - -

      - 显示触发通知的用户以及该用户所发送信息的通知。 -

      - - - - -

      在用户触摸通知的正文时(在操作按钮的外面),打开应用并定位至正确的位置,以便用户可查看通知中引用的数据并据此操作。 - - -在大多数情况下,该位置是某个数据项目(例如消息)的详情视图,但如果是存档通知,那么也可能是摘要视图。 - -如果您的应用将用户带到应用顶层以下的任何位置,可将导航插入应用的返回栈,这样用户就可以通过按下系统返回按钮返回至顶层。 - -如需了解详细信息,请参阅导航设计模式中的“通过主屏幕小工具和通知进入您的应用”。 - -

      - -

      正确设置和管理通知优先级。 - -

      - -

      Android 支持通知的优先级标志。该标志可以影响您的通知相对于其他通知出现的位置,并且可以帮助确保用户始终能在第一时间看到对他们最重要的通知。 - - -在发布通知时,您可以选择下列优先级之一: - -

      - - - - - - - - - - - - - - - - - - - - - - - - - -
      -

      优先级

      -
      -

      用法

      -
      -

      MAX

      -
      -

      用于重要和紧急的通知,告知用户属于时间关键型状况,或者必须予以解决方可继续执行某个特定任务。 - - -

      -
      -

      HIGH

      -
      -

      主要用于重要通信,例如包含用户特别感兴趣的内容的消息或聊天事件。高优先级通知会触发浮动通知显示。 - -

      -
      -

      DEFAULT

      -
      -

      用于不属于此处所述其他任何优先级的所有通知。

      -
      -

      LOW

      -
      -

      用于您希望告知用户但不是很紧急的通知。 -低优先级通知最好显示在列表的底部,这里正适合放置公共事项或无收件人姓名的社交更新之类的通知: - -用户要求接收相关通知,但是这些通知的优先级永远不会高于紧急或直接通信。 - - -

      -
      -

      MIN

      -
      -

      用于上下文或背景信息,例如天气信息或上下文位置信息。最低优先级通知不会出现在状态栏中。 - -用户可在展开的通知栏上找到它们。 -

      -
      - - -

      如何选择合适的优先级 - -

      - -

      DEFAULTHIGHMAX 是中断优先级别,在活动过程中有中断用户的风险。 - -为了避免打扰应用的用户,中断优先级仅保留用于以下通知 -:

      - -
        -
      • 涉及另一个用户
      • -
      • 时间敏感
      • -
      • 可能会立即改变用户在现实世界中的行为
      • -
      - -

      设置为 LOWMIN 的通知可能仍然对用户很重要: -很多通知(如果不是绝大多数)不需要用户立即注意,也不需要振动,但仍然包含用户选择查看通知时将会觉得重要的信息。 - - -LOWMIN优先级通知的条件包括: -

      - -
        -
      • 不涉及其他用户
      • -
      • 不属于时间敏感型
      • -
      • 包含用户可能感兴趣但可选择在空闲时浏览的内容 -
      • -
      - - - - - -

      设置通知类别 -

      - -

      如果通知属于以下预定义类别(参阅下文)之一,则为其分配相应的类别。 - -诸如通知栏(或其他任何通知侦听器)这样的系统 UI 项目,可使用该信息来进行评级和筛选决策。 - -

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -

      CATEGORY_CALL

      -
      -

      来电(语音或视频)或相似的同步通信请求 -

      -
      -

      CATEGORY_MESSAGE

      -
      -

      传入的直接消息(短信、即时消息等)

      -
      -

      CATEGORY_EMAIL

      -
      -

      异步群发消息(电子邮件)

      -
      -

      CATEGORY_EVENT

      -
      -

      日历事件

      -
      -

      CATEGORY_PROMO

      -
      -

      促销或广告

      -
      -

      CATEGORY_ALARM

      -
      -

      闹铃或定时器

      -
      -

      CATEGORY_PROGRESS

      -
      -

      长时间运行的后台操作的进度

      -
      -

      CATEGORY_SOCIAL

      -
      -

      社交网络或共享更新

      -
      -

      CATEGORY_ERROR

      -
      -

      后台操作或身份验证状态中的错误

      -
      -

      CATEGORY_TRANSPORT

      -
      -

      媒体传输播放控制

      -
      -

      CATEGORY_SYSTEM

      -
      -

      系统或设备状态更新。保留给系统使用。

      -
      -

      CATEGORY_SERVICE

      -
      -

      正在运行的后台服务的指示

      -
      -

      CATEGORY_RECOMMENDATION

      -
      -

      对于某个事件的特定、及时建议。例如,新闻应用可能会建议用户接下来可能想要阅读的新话题。 - -

      -
      -

      CATEGORY_STATUS

      -
      -

      有关设备或上下文状态的持续信息

      -
      - -

      通知摘要

      - -

      如果特定类型的通知已经在您的应用尝试发送同类型的新通知时挂起,可将它们合并到单个应用摘要通知中,而不要新建对象。 - -

      - -

      摘要通知会生成摘要说明,让用户了解特定类型的通知有多少处于挂起状态。 - -

      - -
      - -

      禁忌用法

      - -
      - -
      -

      建议用法

      - - -
      - -

      您可通过使用展开的摘要布局提供有关组成摘要的各个通知的更多详情。 - -此方法可让用户更好地了解哪些通知处于挂起状态,如果他们有足够的兴趣,还可在相关联的应用中阅读详情。 - - - -

      -
      - -

      - 展开和收起的摘要通知(使用 InboxStyle) -

      -
      - -

      将通知设置为可选 -

      - -

      用户应始终能控制通知。允许用户通过将某个通知设置项目添加至您的应用设置,禁用应用的通知或更改其提醒属性,例如警报声和是否使用振动。 - - - -

      - -

      使用不同的图标

      -

      通过扫一眼通知区域,用户可以了解哪些类型的通知当前处于挂起状态。 - -

      - -
      - -
      - -

      建议用法

      -

      查看 Android 应用已经提供的通知图标并为您的应用创建外观明显不同的通知图标。 - -

      - -

      建议用法

      -

      对小图标使用正确的通知图标样式,对操作图标使用相应的材料灯操作栏图标。 - - - -

      -

      建议用法

      -

      图标外观要简洁清晰,避免使用过于精细、难以辨认的图标。 -

      - -

      禁忌用法

      -

      对小图标和操作图标设置任何附加的阿尔法通道属性(变暗或变淡);这些图标会有抗锯齿边缘,但是由于 Android 使用这些图标作为蒙板(即仅使用阿尔法通道),因此通常应以完全不透明的方式绘制图像。 - - - - -

      - -
      -

      禁忌用法

      - -

      利用色彩将您的应用与其他应用区分开来。通知图标应该是纯白透明背景图像。 -

      - - -

      对通知 LED 施加相应的脉冲 -

      - -

      许多 Android 设备都配有通知 LED,用于让用户在屏幕关闭时了解事件。 - -优先级为 MAX、 -HIGHDEFAULT 的通知应让 LED 发光,而优先级较低的通知(LOWMIN)则不应让 LED 发光。 - -

      - -

      用户对通知的控制应延伸至 LED。当您使用 DEFAULT_LIGHTS 时,LED 将发出白光。 - -您的通知不应使用不同的颜色,除非用户明确对其进行了自定义。 - -

      - -

      构建用户关注的通知 -

      - -

      要创建用户喜爱的应用,精心设计通知很重要。通知是应用的代言人,还可增强应用的个性化特征。 - - -无用或者不重要的通知会给用户带来烦恼,或者由于过分分散用户的注意力而使其感到愤怒,因此请谨慎使用通知。 - - -

      - -

      何时显示通知

      - -

      要创建人们乐于使用的应用,就需要认识到用户的注意力和关注点是一种必须予以保护的资源,这一点很重要。 - -尽管 Android 的通知系统在设计上希望最小化通知对用户注意力的影响,但是仍然要重视通知会中断用户任务流程这一事实。在您计划通知时,要问问自己,它们是否足够重要,是否适合让用户中断手上的任务。 - - - - - - -如果您不确定,可允许用户使用应用的通知设置来选择是否接收通知,或者将通知优先级标志调整为 LOWMIN,从而避免在用户做其他事情时分散他们的注意力。 - - - -

      - - -

      - 时间敏感通知的示例 -

      - -

      尽管行为良好的应用通常只在用户对其操作后才会发出通知,但在极少数情况下,应用通过无提示的通知形式打断用户也是值得的。 -

      - -

      将通知主要用于时间敏感的事件,尤其是这些同步事件涉及其他用户时。 -例如,传入的聊天属于实时同步通信形式: - -另一个用户在主动等待您的回应。 -日历事件是使用通知并引起用户注意的另一个好例子,因为事件已经迫近,并且日历事件通常涉及其他人员。 - - -

      - -

      何时不显示通知 -

      - -
      - -
      - -

      在其他很多情况下都不适合显示通知:

      - -
        -
      • 不要将并非特定于用户的信息或并非确实时间敏感的信息告知用户。 - -例如,流经社交网络的异步和未经订阅的更新,通常不适合引发实时中断。 - - -对于确实关注它们的用户,可让他们选择接收通知。 -
      • -
      • 如果相关的新信息当前显示在屏幕上,则不要创建通知。 -不过可以使用应用本身的 UI 在上下文中将新信息直接告知用户。 - - - 例如,聊天应用不应在用户主动和另一名用户聊天时创建系统通知。 -
      • -
      • 对于技术要求不高的操作(例如保存或同步信息或更新应用),如果应用或系统无需用户参与就可解决问题,请不要中断用户。 - -
      • -
      • 如果可以让应用自行恢复错误,而不必让用户采取任何操作,则不要中断用户来告知他们发生此错误。 - -
      • -
      • 请不要创建没有实际通知内容和仅仅是为您的应用做宣传的通知。通知应当提供有用、及时、最新的信息,而不应仅用于推广应用。 - - - -
      • -
      • 请不要为了向用户宣传您的品牌而创建过多的通知。 - - 此类通知会让用户不满,从而很可能离您而去。提供少量更新信息并让用户保持与您的应用交互的最佳方式是开发一个小工具,让用户可以选择是否将其放在主屏幕上。 - - - - -
      • -
      - -

      与通知交互 -

      - -

      通知由状态栏中的图标指示,并且可以通过打开抽屉式通知栏进行访问。 - -

      - -

      触摸通知会打开相关联的应用并进入与通知匹配的详细内容。在通知上向左或向右滑动会将其从抽屉式通知栏中删除。 - -

      - -

      持续性通知

      -
      - -

      - 因播放音乐而持续显示的通知 -

      -
      -

      持续性通知可让用户持续了解后台运行的进度。例如,音乐播放器在通知系统中通告当前播放的曲目,并继续进行播放,直至用户停止播放。 - - - -持续性通知也可为持续时间较长的任务(例如下载文件或视频编码之类的任务)向用户显示反馈。 - -用户无法手动从抽屉式通知栏中删除持续性通知。 -

      - -

      媒体播放

      -

      在 Android 5.0 中,锁定屏幕不会为弃用的 -{@link android.media.RemoteControlClient} 类显示传输控件。但是它确实会显示通知,因此每个应用的播放通知现在是用户在锁屏状态控制播放的主要方式。 - -此行为可让应用更好地控制显示哪些按钮,这样,无论是否锁屏,都可以为用户提供一致的体验。 - - -

      - -

      对话框和 Toast -

      - -

      如果您的应用当前未显示在屏幕上,则不应创建对话框或 Toast。 -对话框或 Toast 应仅限用于即时响应用户在应用内部采取的操作。有关使用对话框和 Toast 的进一步指导,请参阅确认和确知。 - - - -

      - -

      排名和排序

      - -

      通知属于新闻,因此基本以时间倒序显示,并且会特别考虑应用规定的通知优先级。 - - -

      - -

      通知是锁定屏幕的关键部分,并且在设备显示屏每次亮起时突出显示。 - -锁定屏幕上的空间有限,因此确定哪些通知最为紧急或最密切相关非常重要。 - -由于这个原因,Android 在处理通知时使用了更为精密的排序算法,考虑到以下因素: - -

      - -
        -
      • 时间戳以及应用规定的优先级。
      • -
      • 通知是否最近以声音或振动形式告知过用户。 -(也就是说,如果手机刚发出了铃声,并且用户希望知道“刚才发生了什么?”,那么锁定屏幕应让用户一眼看到相应的通知。) - - -
      • -
      • 与使用 {@link android.app.Notification#EXTRA_PEOPLE} 的通知相关的任何人,尤其是加星标的联系人。 -
      • -
      - -

      为了充分利用此排序功能,请专注于您希望建立的用户体验,而不是拘泥于列表上的某个特定项。 - -

      - - - -

      Gmail 通知使用的是默认优先级,因此它们的顺序通常低于来自即时通讯应用(例如环聊)的消息,但是在有新邮件送达时会临时占位。 - - - - -

      - - -

      在锁定屏幕上

      - -

      由于通知在锁定屏幕上可见,所以用户隐私是特别重要的考虑事项。 - -通知通常包含敏感信息,并且不一定需要让所有拿起设备并打开显示屏的人看到。 - -

      - -
        -
      • 对于配置了安全锁定屏幕(PIN 码、图案或密码)的设备,界面分为公用和私人部分。 -公用界面可显示在安全锁定屏幕上,因此任何人都可看见。 -私人界面是锁定屏幕背后的内容,只有在用户登录设备后才会显示。 -
      • -
      - -

      用户对显示在安全锁定屏幕上的信息的控制

      -
      - -

      - 位于锁定屏幕上的通知,具有用户解锁设备后可显示的内容。 -

      -
      - -

      在设置安全锁定屏幕时,用户可以选择从安全锁定屏幕隐藏敏感的详细信息。 -在这种情况下,系统 UI 会考虑通知的可见性级别,从而确定哪些内容可以安全地显示出来。 - -

      -

      要控制可见性级别,可调用 Notification.Builder.setVisibility(),然后指定以下值之一: - -

      - -
        -
      • VISIBILITY_PUBLIC。显示通知的完整内容。 - - 在未指定可见性的情况下,此设置是系统的默认设置。
      • -
      • VISIBILITY_PRIVATE。在锁定屏幕上,会显示通知的基本信息,包括其图标以及发布此通知的应用名称。 - -剩下的通知详细信息不会显示。需要注意的一些有用建议如下: - -
          -
        • 如果您希望为通知提供不同的公用版本,供系统显示在安全锁定屏幕上,可在 Notification.publicVersion 字段中提供替换通知对象。 - - - -
        • 该设置可让您的应用有机会创建有用内容的删减版本,但是不会显示个人信息。 -可参考短信应用的示例,这种应用的通知包括短信的文本以及发信者的姓名和联系人图标。该通知应为 VISIBILITY_PRIVATE,但是 publicVersion 仍然可以包含“有 3 条新消息”这样的有用信息,而不会提供其他识别性详细信息。 - - - - -
        -
      • -
      • Notification.VISIBILITY_SECRET。仅显示最为精简的信息,甚至不包括通知图标。 -
      • -
      -

      Android Wear 上的通知 -

      - -

      通知及其操作默认会和穿戴设备桥接。开发者可以控制哪些通知会从手机桥接至手表,反之亦然。 - - -开发者也可以控制哪些操作会进行桥接。如果您的应用包含无法通过单次点击完成的操作,则可以将这些操作隐藏在您的 Android Wear 设备通知中,或者考虑将它们连接至 Android Wear 设备应用,从而可让用户在其手表上完成操作。 - - - - - -

      - -

      桥接通知和操作

      - -

      连接的设备,例如手机,可将通知桥接至 Android Wear 设备,从而将通知显示在此处。 -与此相似,您也可以桥接操作,从而让用户可在 Android Wear 设备上直接操作通知。 -

      - -

      桥接

      - -
        -
      • 新的即时通讯
      • -
      • 单次点击操作,例如 +1、赞、收藏
      • -
      - - - -

      不要桥接

      - -
        -
      • 新收到的播客通知
      • -
      • 映射至手表上无法使用的功能的操作
      • -
      - - - -

      为 Android Wear 设备定义的独特操作

      - -

      有些操作只能在 Android Wear 上执行。包括以下情况:

      - -
        -
      • 例如“马上回来”这样的预设回复快速列表
      • -
      • 在手机上打开
      • -
      • 调出语音输入屏幕的“评论”或“回复”操作
      • -
      • 启动 Android Wear 专用应用的操作
      • -
      - - diff --git a/docs/html-intl/intl/zh-cn/design/style/writing.jd b/docs/html-intl/intl/zh-cn/design/style/writing.jd index 7944c24c1ed203cc5ee9de6505eac4046728c4ef..c0c3e5408897c771ae6303c4fbcd2c758d07ef1e 100644 --- a/docs/html-intl/intl/zh-cn/design/style/writing.jd +++ b/docs/html-intl/intl/zh-cn/design/style/writing.jd @@ -174,7 +174,7 @@ page.type=设计
    7. 使用缩写词。
    8. 使用“您”或“你”直接与读者对话。
    9. 语气应轻松自然,但要避免使用俚语。
    10. - +

      避免使用令人困惑或令人厌烦的表达

      diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/about.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/about.jd index bfdb210ee0d94f1942cc34bd1fc0b2d8a010c111..382c4c729515c869f2e62efe86184d45e2d6c229 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/about.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/about.jd @@ -6,7 +6,7 @@ page.image=/distribute/images/about-play.jpg @jd:body -
      +

      关于 Google Play

        diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/developer-console.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/developer-console.jd index 7d0bd55ca3071ead37d9a02b712b8a6944b76f41..d9255662f762a73aebd1ae47fc87003089711c68 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/developer-console.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/developer-console.jd @@ -4,8 +4,8 @@ page.image=/distribute/images/developer-console.jpg Xnonavpage=true @jd:body - -
        + +

        发布功能

          diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/families/faq.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/families/faq.jd index ea8bb613cda3d770fd16ca7e2889117cea08d4d9..7b0cf1db1e2f710045a38dc2011c377b962dd185 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/families/faq.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/families/faq.jd @@ -10,7 +10,7 @@ page.metaDescription=“为家庭设计”计划的问答 font-weight:bold; } - +

            本文内容

            @@ -141,7 +141,7 @@ page.metaDescription=“为家庭设计”计划的问答 假设您的应用符合该计划的所有要求,我们预计发布时间不会超过正常时间;但是,如果在“为家庭设计”审查时被拒绝,则应用的发布可能会延迟。 - +
    diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/families/start.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/families/start.jd index aab4b5aaa95b150c4f3949df239ce0da4945591f..e81bac5843fedd3074a4fefe3facc76e2b54665e 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/families/start.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/families/start.jd @@ -78,7 +78,7 @@ ESRB 10+ 分级的应用只能选择一个目标年龄:9-12 岁或一般受众

    注意:在“为家庭设计”计划中发布的应用也可供 - Google Play 上的所有用户使用。 + Google Play 上的所有用户使用。

    diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/guide.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/guide.jd index b70bcb5c79eea3deff3be2d0db5af1df7d1eac10..7b280cf1baea5faed2b47c0b9c4e9f86532c3592 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/guide.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/guide.jd @@ -18,7 +18,7 @@ page.image=distribute/images/play_dev_guide.png

    • 在 Google Play 上发布 —使用 Google Play - 的开发者控制台,将您的应用分发给全球超过 10 亿 + 的开发者控制台,将您的应用分发给全球超过 10 亿 Android 用户。
    • diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/auto.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/auto.jd index a590446f4dfb5aa503bec7d49405da9c1833b7fb..9f61a35a011382fa900d36ef629416d0c8f89257 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/auto.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/auto.jd @@ -162,7 +162,7 @@ page.image=/distribute/images/gp-auto-quality.png - 布局 + 布局 diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/core.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/core.jd index 0dae9e170e583aa1bc93bcc79a9b8860f4edbf51..793d110e6f87cc16af046947c844ca0ded39724a 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/core.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/core.jd @@ -12,7 +12,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
    • Google Play
    • - +

      测试

      1. 设置测试环境
      2. @@ -24,7 +24,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
      3. 平板电脑应用的质量
      4. 优化您的应用
      - + @@ -84,7 +84,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg ID - + 说明 @@ -746,7 +746,7 @@ data-cardsizes="6x3" data-maxresults="6">
    • 应用商品详情包括高品质的置顶大图。
    • -
    • 置顶大图不能包含设备图片、屏幕截图,也不能包含缩小后以及在应用适配的最小尺寸屏幕上显示时难以辨认的小文字。 +
    • 置顶大图不能包含设备图片、屏幕截图,也不能包含缩小后以及在应用适配的最小尺寸屏幕上显示时难以辨认的小文字。
    • @@ -1049,7 +1049,7 @@ data-cardsizes="6x3,6x3,6x3,6x3,6x3,6x3" data-maxresults="6">

      要强制启动硬件加速(在设备支持的情况下),请将 - hardware-accelerated="true"添加到应用清单文件中的<application>并重新编译。 + hardware-accelerated="true"添加到应用清单文件中的<application>并重新编译。

      diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tablets.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tablets.jd index 1d9d620fca3560afb3314f6b3b8938b411a28c48..3df311aa761259114a198f461d2f4a1088241f25 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tablets.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tablets.jd @@ -48,7 +48,7 @@ Xnonavpage=true

      - 本文档中提供了相关资源的链接,这些资源可帮助您了解文中给出的各条建议。 + 本文档中提供了相关资源的链接,这些资源可帮助您了解文中给出的各条建议。

      @@ -56,7 +56,7 @@ Xnonavpage=true

      为了打造上佳的平板电脑应用体验,首先要根据应用适配的所有设备和机型,确保您的应用满足相应的应用核心质量标准。 -有关完整信息,请参阅应用核心质量准则。 +有关完整信息,请参阅应用核心质量准则

      @@ -116,7 +116,7 @@ style="font-weight:500;">舍弃拉伸变形的界面:在平板电脑上,单

        -
      • 根据需要,针对 large 和 +
      • 根据需要,针对 largexlarge 屏幕提供自定义布局。您还可以提供可根据屏幕的最短尺寸最小可用宽度和高度加载的布局。 @@ -207,8 +207,8 @@ style="font-weight:500;">复合视图将手机界面的多个单一视图( android.app.Fragment} 子类实现各个内容面板。这样一来,您可以在共用内容的不同机型和不同屏幕间最大程度地重复使用代码。
      • -
      • 确定要在哪些屏幕尺寸上使用多窗格界面,然后在相应的屏幕尺寸单元(例如 -large/xlarge)中提供不同的布局,或最小屏幕宽度(例如 +
      • 确定要在哪些屏幕尺寸上使用多窗格界面,然后在相应的屏幕尺寸单元(例如 +large/xlarge)中提供不同的布局,或最小屏幕宽度(例如 sw600dp/sw720)。
      @@ -309,7 +309,7 @@ android.app.Fragment} 子类实现各个内容面板。这样一来,您可以 data-cardSizes="9x3" data-maxResults="6"> -

      5. +

      5. 调整字体大小和触控目标

      要确保您的应用在平板电脑上易于使用,请花些时间针对您要适配的各种屏幕配置调整平板电脑界面中的字体大小和触控目标。 @@ -345,7 +345,7 @@ android.app.Fragment} 子类实现各个内容面板。这样一来,您可以

      6. 调整主屏幕小部件的尺寸

      -

      如果您的应用中包含主屏幕小部件,需要注意以下几点,以确保用户在平板电脑屏幕上获得良好体验: +

      如果您的应用中包含主屏幕小部件,需要注意以下几点,以确保用户在平板电脑屏幕上获得良好体验:

        @@ -411,7 +411,7 @@ android.app.Fragment} 子类实现各个内容面板。这样一来,您可以 为确保分发到尽可能多的平板电脑,务必让应用适配各种支持平板电脑的 Android 版本。 对平板电脑的支持是从 Android 3.0(API 级别 11)开始的。 - 对平板电脑、手机及其他设备的统一界面框架支持是从 Android + 对平板电脑、手机及其他设备的统一界面框架支持是从 Android 4.0 开始的

        @@ -494,8 +494,8 @@ android.app.Fragment} 子类实现各个内容面板。这样一来,您可以
      • 与此类似,还请检查清单文件,找出 表明硬件功能要求不适用于平板电脑的 <permission> 元素。 -如果您找到这样的权限,请务必为功能明确声明对应的 -<uses-feature> 元素并加入 +如果您找到这样的权限,请务必为功能明确声明对应的 +<uses-feature> 元素并加入 android:required=”false” 属性。
      @@ -529,21 +529,21 @@ android.app.Fragment} 子类实现各个内容面板。这样一来,您可以

        -
      • 如果声明 +
      • 如果声明 <supports-screens> 元素,就不要指定 android:largeScreens="false"android:xlargeScreens="false"
      • -
      • 如果应用适配的 minSdkVersion 值小于 13,必须使用 +
      • 如果应用适配的 minSdkVersion 值小于 13,必须使用 android:largeScreens="true"android:xlargeScreens="true" 声明 <supports-screens> 元素。
      -

      如果应用在清单文件中声明了 +

      如果应用在清单文件中声明了 <compatible-screens> 元素,该元素应包含相关属性, 以列举应用支持的平板电脑屏幕的所有尺寸和密度组合。 -请注意,如果可能,您应避免在应用中使用 +请注意,如果可能,您应避免在应用中使用 <compatible-screens> 元素。

      @@ -586,7 +586,7 @@ android.app.Fragment} 子类实现各个内容面板。这样一来,您可以
    • 添加在 7 英寸和 10 英寸平板电脑上截取的屏幕截图。
    • -
    • 如果可能,添加横屏和竖屏截取的屏幕截图。 +
    • 如果可能,添加横屏和竖屏截取的屏幕截图。
    • diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tv.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tv.jd index 6a609457bc582459524e2cf912cafff592e36608..99a12d585b7e8d0feafc857e93a1b815bbcb20fd 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tv.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/tv.jd @@ -133,7 +133,7 @@ page.image=/distribute/images/gp-tv-quality.png - 布局 + 布局 diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/wear.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/wear.jd index 99483eccc760862d84a49eb1605d5102dfa2763f..eb9166de7b04e2662eaa4bcf62f62ea3bcf38e59 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/wear.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/quality/wear.jd @@ -91,7 +91,7 @@ page.image=/distribute/images/gp-wear-quality.png

      手持类应用包括具有可穿戴设备特有功能的通知或直接在穿戴设备上运行的可穿戴类应用。 - + (了解方法

      @@ -441,7 +441,7 @@ data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">

      - 如果我的应用不符合穿戴设备的要求,是否仍会在 Google Play + 如果我的应用不符合穿戴设备的要求,是否仍会在 Google Play 上向手机和平板电脑显示我的新应用或更新版本并且仍可在可穿戴设备上安装?

      diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/tv.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/tv.jd index e557024186a95a7d992591c7c2aa281bca795256..a1b2f4c22a16a07679e1b1cf8d9540d77f828527 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/tv.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/tv.jd @@ -88,7 +88,7 @@ Android TV 的 Google Play 体验仅展示可在电视上使用的应用

      在考虑您的电视应用时,请查看开发者文档和可用性准则,并且尽可能支持这些准则。 -确保为用户设计一种出色 Leanback 观看体验,并使用 SDK 中随附的 +确保为用户设计一种出色 Leanback 观看体验,并使用 SDK 中随附的 Leanback 库来打造这种体验。您想针对电视用例优化应用的其他部分,最好在开发过程的早期确定这些部分。 @@ -261,7 +261,7 @@ Google Play 将展示优质应用,以便用户能够在 Google Play 中轻松 当您进行必要的调整后,就可以将应用的新版本上传到开发者控制台。 - +

      @@ -282,7 +282,7 @@ Google Play 将展示优质应用,以便用户能够在 Google Play 中轻松

    • 已批准 — 您的应用已被审查并获得批准。该应用将直接提供给 Android TV 用户。 - +
    • diff --git a/docs/html-intl/intl/zh-cn/distribute/googleplay/wear.jd b/docs/html-intl/intl/zh-cn/distribute/googleplay/wear.jd index 182abdf81d1f3ac17a9c020d01cdd41c2fecd871..480ce5db33a9f55b53c41aba999ad84c6f12aec7 100644 --- a/docs/html-intl/intl/zh-cn/distribute/googleplay/wear.jd +++ b/docs/html-intl/intl/zh-cn/distribute/googleplay/wear.jd @@ -60,7 +60,7 @@ page.metaDescription=将您的应用、游戏和内容分发到 Android Wear。

      为了做好准备,以便在 Android Wear 上成功推出应用,首先要查阅在穿戴设备上提供出色应用体验的准则。 -请参考 Android +请参考 Android Wear 设计准则,了解有关针对穿戴设备扩展应用的建议,以及有关设计和可用性的详情。

      @@ -120,7 +120,7 @@ Wear 设计准则,了解有关针对穿戴设备扩展应用的建议,

      您的穿戴设备应用应表现出色,在 Android Wear 上看起来引人入胜,并且提供尽可能最佳的用户体验。 Google Play 将展示精选的优质穿戴设备应用,以便用户轻松发现。 -以下说明了您如何加入平台,提交用户喜爱的 +以下说明了您如何加入平台,提交用户喜爱的 Android Wear 应用:

      diff --git a/docs/html-intl/intl/zh-cn/distribute/resources.jd b/docs/html-intl/intl/zh-cn/distribute/resources.jd index 71bd4665a23eed596d2dee72a77c7034a10d2fcb..4c5644c9dda2c9f7aa7f27f1e617df1ca2f22035 100644 --- a/docs/html-intl/intl/zh-cn/distribute/resources.jd +++ b/docs/html-intl/intl/zh-cn/distribute/resources.jd @@ -8,7 +8,7 @@ page.metaDescription=我们翻译了以下一些网站资源,希望能帮助 @jd:body
      -

      - 发布应用之前,请务必确保您的应用可在目标 Android 平台版本和设备屏幕尺寸上正常运行。 + 发布应用之前,请务必确保您的应用可在目标 Android 平台版本和设备屏幕尺寸上正常运行。

      @@ -400,7 +400,7 @@ Google Play 会根据该设置来筛选应用,因此您选择的内容分级
    • 将应用发布为免费应用后,您无法再将其改成付费应用。 -不过,您仍能通过 Google Play +不过,您仍能通过 Google Play 的应用内结算服务销售应用内商品订阅

      @@ -449,9 +449,9 @@ Google Play 会根据该设置来筛选应用,因此您选择的内容分级

      如果您希望找到更多方法通过应用获利并建立与用户的互动,则应考虑使用“应用内结算”或“即时购买”。 这些服务深受用户和开发者的欢迎。 -要使用“应用内结算”或“即时购买”,您需要对应用的二进制文件进行更改,因此,您需要先完成更改并测试实现方法,然后才能创建发布版 APK。 +要使用“应用内结算”或“即时购买”,您需要对应用的二进制文件进行更改,因此,您需要先完成更改并测试实现方法,然后才能创建发布版 APK。 + -

      相关资源

      @@ -955,7 +955,7 @@ Google Play 团队会为用户提供下载、安装和付款方面的支持,
      • - 经常查看您应用的商品详情页上的评分和评论。 + 经常查看您应用的商品详情页上的评分和评论。 注意反复出现的主题,这可能表示存在错误或其他问题。

      • @@ -991,7 +991,7 @@ Google Play 团队会为用户提供下载、安装和付款方面的支持,
      • - 确认并修正您应用中出现的问题。保持公开透明并主动在商品详情页上列出已知问题是有益之举。 + 确认并修正您应用中出现的问题。保持公开透明并主动在商品详情页上列出已知问题是有益之举。

      • diff --git a/docs/html-intl/intl/zh-cn/distribute/tools/localization-checklist.jd b/docs/html-intl/intl/zh-cn/distribute/tools/localization-checklist.jd index 522b7f5e4d4d0fd12fc7d9325de8fecda8272a4f..e37f04337fbfc3685e11b07704f4d8186091ebd2 100644 --- a/docs/html-intl/intl/zh-cn/distribute/tools/localization-checklist.jd +++ b/docs/html-intl/intl/zh-cn/distribute/tools/localization-checklist.jd @@ -62,7 +62,7 @@ page.image=/distribute/images/localization-checklist.jpg 用户可以控制其 Android 设备上使用的语言和语言区域,反过来这些因素也会影响应用的显示方式。 - +

        @@ -820,7 +820,7 @@ data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">

    • - 如果您正在准备国际化营销,请务必加入本地化的 Google Play + 如果您正在准备国际化营销,请务必加入本地化的 Google Play 徽章,让用户知道您是在 Google Play 上发布应用的。您可以使用徽章生成器快速构建本地化的徽章,然后用到您的网站或营销材料中。 您还可以获得高分辨率的资源。 diff --git a/docs/html-intl/intl/zh-cn/distribute/tools/promote/badges.jd b/docs/html-intl/intl/zh-cn/distribute/tools/promote/badges.jd index 1c8216136cdaf2f1c673162bddcd66fbf17daf2a..cc1234d376527137b4c4ef53ec67953ddb9721a4 100644 --- a/docs/html-intl/intl/zh-cn/distribute/tools/promote/badges.jd +++ b/docs/html-intl/intl/zh-cn/distribute/tools/promote/badges.jd @@ -35,7 +35,7 @@ div.button-row input { vertical-align: middle; margin: 0 5px 0 0; } -#jd-content div.button-row img { +#body-content div.button-row img { margin: 0; vertical-align: middle; } diff --git a/docs/html-intl/intl/zh-cn/distribute/tools/promote/linking.jd b/docs/html-intl/intl/zh-cn/distribute/tools/promote/linking.jd index c7cf7cf700b170b9dd5e98a968c26d0ca1c4a6ee..e9b13c02f00282673da1e1bf90051373aaadfffc 100644 --- a/docs/html-intl/intl/zh-cn/distribute/tools/promote/linking.jd +++ b/docs/html-intl/intl/zh-cn/distribute/tools/promote/linking.jd @@ -13,7 +13,7 @@ page.metaDescription=了解如何构建链接,把用户从浏览或搜索带

      -

      Google Play 提供多种链接格式,可让你按自己需要的方式将用户从 Android 应用、网页、广告、评论、文章、社交媒体帖子等链接到你的商品。

      +

      Google Play 提供多种链接格式,可让你按自己需要的方式将用户从 Android 应用、网页、广告、评论、文章、社交媒体帖子等链接到你的商品。

      这些链接格式可让你:

        diff --git a/docs/html-intl/intl/zh-cn/google/play/billing/api.jd b/docs/html-intl/intl/zh-cn/google/play/billing/api.jd index fbdbac6c28433b243989713381cf5c8696539c6a..ba1d63760e11b3c43be4cdec25982d85d1bef777 100644 --- a/docs/html-intl/intl/zh-cn/google/play/billing/api.jd +++ b/docs/html-intl/intl/zh-cn/google/play/billing/api.jd @@ -32,7 +32,7 @@ parent.link=index.html

        另请参见

        1. 销售应用内商品
        2. -
        + @@ -68,7 +68,7 @@ parent.link=index.html
        1. Google Play 返回的 Bundle 中包含 PendingIntent,您的应用可用它来启动购买结帐界面。
        2. 您的应用通过调用 startIntentSenderForResult 方法来启动 PendingIntent。
        3. -
        4. 当结帐流程结束后(即用户成功购买商品或取消购买),Google Play 会向您的 onActivityResult 方法发送响应 IntentonActivityResult 的结果代码中有一个代码将用于表明用户是完成了购买还是取消了购买。响应 Intent 中会包含所购商品的相关信息,其中包括 Google Play 为了唯一标识此次购买交易而生成的 purchaseToken 字符串。Intent 中还包含使用您的私人开发者密钥签署的购买签名。
        5. +
        6. 当结帐流程结束后(即用户成功购买商品或取消购买),Google Play 会向您的 onActivityResult 方法发送响应 IntentonActivityResult 的结果代码中有一个代码将用于表明用户是完成了购买还是取消了购买。响应 Intent 中会包含所购商品的相关信息,其中包括 Google Play 为了唯一标识此次购买交易而生成的 purchaseToken 字符串。Intent 中还包含使用您的私人开发者密钥签署的购买签名。
        diff --git a/docs/html-intl/intl/zh-cn/google/play/billing/billing_admin.jd b/docs/html-intl/intl/zh-cn/google/play/billing/billing_admin.jd index 989c0e7d59a2f492cfbff749938a3365d618c429..50e2fe3f226d5891011caf0fd7f68c18651b5b6d 100644 --- a/docs/html-intl/intl/zh-cn/google/play/billing/billing_admin.jd +++ b/docs/html-intl/intl/zh-cn/google/play/billing/billing_admin.jd @@ -15,7 +15,7 @@ parent.link=index.html
      • 获取相关支持
      • - +

        另请参见

        1. 应用内结算概述
        2. diff --git a/docs/html-intl/intl/zh-cn/google/play/filters.jd b/docs/html-intl/intl/zh-cn/google/play/filters.jd index 9d68faf41bdfa2214351eb7e792b414f344a5855..87df676bfe2b4d33e8d3e90eaaf62ad61f39e816 100644 --- a/docs/html-intl/intl/zh-cn/google/play/filters.jd +++ b/docs/html-intl/intl/zh-cn/google/play/filters.jd @@ -166,7 +166,7 @@ targetSdkVersion
          设置为 4 或更大时,所有属性的默认值

          示例 2
          清单文件声明 <uses-sdk android:minSdkVersion="3" - android:targetSdkVersion="4"> 并且不包括 + android:targetSdkVersion="4">
          并且不包括 <supports-screens> 元素。 结果:Google Play 将向所有设备的用户显示该应用,除非还有其他筛选器。

          @@ -400,10 +400,10 @@ Google Play 然后根据 这样,您可以只包括每种设备配置所需的纹理,从而减小 APK 文件的大小。 -根据每个设备是否支持您的纹理压缩格式,Google Play +根据每个设备是否支持您的纹理压缩格式,Google Play 将向其提供您已声明支持该设备的 APK。

          -

          目前,只有在每个 APK 根据以下配置提供不同筛选时,Google Play +

          目前,只有在每个 APK 根据以下配置提供不同筛选时,Google Play 才允许您为同一应用发布多个 APK:

          • OpenGL 纹理压缩格式 diff --git a/docs/html-intl/intl/zh-cn/guide/components/activities.jd b/docs/html-intl/intl/zh-cn/guide/components/activities.jd index efc1fb1ba71129161d5ff9465a48cd7c06c860d5..0e7c4fda89a9db118f4b7ae191003453401e3411 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/activities.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/activities.jd @@ -1,5 +1,5 @@ page.title=Activity -page.tags=Activity, Intent +page.tags=Activity, Intent @jd:body
            @@ -215,7 +215,7 @@ That Cannot Change

            启动 Activity

            您可以通过调用 {@link android.app.Activity#startActivity - startActivity()},并将其传递给描述您想启动的 Activity 的 {@link android.content.Intent} + startActivity()},并将其传递给描述您想启动的 Activity 的 {@link android.content.Intent} 来启动另一个 Activity。Intent 对象会指定您想启动的具体 Activity 或描述您想执行的操作类型(系统会为您选择合适的 Activity,甚至是来自其他应用的 Activity)。 @@ -608,7 +608,7 @@ android.app.Activity#onSaveInstanceState onSaveInstanceState()}。

            系统会先调用 {@link android.app.Activity#onSaveInstanceState onSaveInstanceState()},然后再使 Activity 变得易于销毁。系统会向该方法传递一个 -{@link android.os.Bundle},您可以在其中使用 +{@link android.os.Bundle},您可以在其中使用 {@link android.os.Bundle#putString putString()} 和 {@link android.os.Bundle#putInt putInt()} 等方法以名称-值对形式保存有关 Activity 状态的信息。然后,如果系统终止您的应用进程,并且用户返回您的 Activity,则系统会重建该 Activity,并将 diff --git a/docs/html-intl/intl/zh-cn/guide/components/bound-services.jd b/docs/html-intl/intl/zh-cn/guide/components/bound-services.jd index ed6aaf6ecbf85ec3689785f2e1c87588122ed6a4..fda6ba704506a03876c9ef079d9ab362172e7168 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/bound-services.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/bound-services.jd @@ -636,7 +636,7 @@ onStartCommand()} android.content.Context#stopService stopService()} 为止,无论其是否绑定到任何客户端。

            -

            此外,如果您的服务已启动并接受绑定,则当系统调用您的 {@link android.app.Service#onUnbind onUnbind()} 方法时,如果您想在客户端下一次绑定到服务时接收 +

            此外,如果您的服务已启动并接受绑定,则当系统调用您的 {@link android.app.Service#onUnbind onUnbind()} 方法时,如果您想在客户端下一次绑定到服务时接收 {@link android.app.Service#onRebind onRebind()} 调用(而不是接收 {@link android.app.Service#onBind onBind()} 调用),则可选择返回 diff --git a/docs/html-intl/intl/zh-cn/guide/components/fragments.jd b/docs/html-intl/intl/zh-cn/guide/components/fragments.jd index a4c2cbb824991f8bf5c566ec8914e0fc0509fbea..12a26e25863a26d2159376ad0fe5824b2f142647 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/fragments.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/fragments.jd @@ -36,7 +36,7 @@ parent.link=activities.html

          • {@link android.app.FragmentManager}
          • {@link android.app.FragmentTransaction}
        - +

        另请参阅

        1. 利用片段构建动态 UI
        2. @@ -362,7 +362,7 @@ findFragmentByTag()}。

          如需查看将没有 UI 的片段用作后台工作线程的示例 Activity,请参阅 {@code FragmentRetainInstance.java} 示例,该示例包括在 SDK 示例(通过 -Android SDK 管理器提供)中,以 +Android SDK 管理器提供)中,以 <sdk_root>/APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java 形式位于您的系统中。

          @@ -378,7 +378,7 @@ Android SDK 管理器提供)中,以
        3. 通过 {@link android.app.FragmentManager#findFragmentById findFragmentById()}(对于在 Activity 布局中提供 UI 的片段)或 {@link android.app.FragmentManager#findFragmentByTag -findFragmentByTag()}(对于提供或不提供 UI 的片段)获取 Activity 中存在的片段
        4. +findFragmentByTag()}(对于提供或不提供 UI 的片段)获取 Activity 中存在的片段
        5. 通过 {@link android.app.FragmentManager#popBackStack()}(模拟用户发出的 Back 命令)将片段从返回栈中弹出
        6. 通过 {@link @@ -785,7 +785,7 @@ android.widget.FrameLayout}),也可能会启动一个新活动(在该活

          第二个片段 {@code DetailsFragment} 显示从 {@code TitlesFragment} 的列表中选择的项目的戏剧摘要:

          - + {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}

          从 {@code TitlesFragment} 类中重新调用,如果用户点击某个列表项,且当前布局“根本不”包括 {@code R.id.details} @@ -798,7 +798,7 @@ Activity 以显示该项目的内容。

          {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details_activity} - +

          请注意,如果配置为横向,则此 Activity 会自行完成,以便主 Activity 可以接管并沿 {@code TitlesFragment} 显示 {@code DetailsFragment}。如果用户在纵向显示时启动 diff --git a/docs/html-intl/intl/zh-cn/guide/components/fundamentals.jd b/docs/html-intl/intl/zh-cn/guide/components/fundamentals.jd index 4ff22b64acbefd38f59de9c702ed8235f5d18620..faaa0a3ffb6f31265d5c5998950c21dedf1e9103 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/fundamentals.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/fundamentals.jd @@ -379,7 +379,7 @@ Google Play 等外部服务会读取它们,以便当用户在其设备中搜索应用时为用户提供过滤功能。

          例如,如果您的应用需要相机,并使用 Android 2.1(API 7 级)中引入的 -API,您应该像下面这样在清单文件中以要求形式声明这些信息:

          +API,您应该像下面这样在清单文件中以要求形式声明这些信息:

           <manifest ... >
          @@ -390,7 +390,7 @@ API,您应该像下面这样在清单文件中以要求形式声明这些信
           </manifest>
           
          -

          现在,没有相机且 +

          现在,没有相机且 Android 版本低于 2.1 的设备将无法从 Google Play 安装您的应用。

          不过,您也可以声明您的应用使用相机,但并不要求必须使用。 diff --git a/docs/html-intl/intl/zh-cn/guide/components/index.jd b/docs/html-intl/intl/zh-cn/guide/components/index.jd index 53e81849c550e2006670cd92336b1203bb9b4e6a..73c1bdf2d7b218a47560ab3084f4b975f036ae6c 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/index.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/index.jd @@ -11,7 +11,7 @@ page.image=images/develop/app_components.png

        - +

        关键类

        1. {@link android.app.LoaderManager}
        2. {@link android.content.Loader}
        3. -
        - + +

        相关示例

        1. @@ -51,7 +51,7 @@ android.app.Fragment}。
        2. 因此,它们无需重新查询其数据。
      - +

      Loader API 摘要

      在应用中使用加载器时,可能会涉及到多个类和接口。 @@ -129,7 +129,7 @@ android.content.ContentProvider} 支持的数据。您也可以实现自己的 或 {@link android.content.AsyncTaskLoader} 子类,从其他源中加载数据。

    • 一个 {@link android.app.LoaderManager.LoaderCallbacks} -实现。您可以使用它来创建新加载器,并管理对现有加载器的引用。
    • +实现。您可以使用它来创建新加载器,并管理对现有加载器的引用。
    • 一种显示加载器数据的方法,如 {@link android.widget.SimpleCursorAdapter}。
    • 使用 @@ -140,11 +140,11 @@ android.widget.SimpleCursorAdapter}。
    • {@link android.app.LoaderManager} 可在 {@link android.app.Activity} 或 {@link android.app.Fragment} 内管理一个或多个 {@link android.content.Loader} 实例。每个 Activity 或片段只有一个 {@link -android.app.LoaderManager}。

      +android.app.LoaderManager}。

      通常,您会使用 Activity 的 {@link android.app.Activity#onCreate onCreate()} 方法或片段的 -{@link android.app.Fragment#onActivityCreated onActivityCreated()} +{@link android.app.Fragment#onActivityCreated onActivityCreated()} 方法初始化 {@link android.content.Loader}。您执行操作如下:

      @@ -157,13 +157,13 @@ getLoaderManager().initLoader(0, null, this);
    • 用于标识加载器的唯一 ID。在此示例中,ID 为 0。
    • 在构建时提供给加载器的可选参数(在此示例中为 null -)。
    • +)。
    • {@link android.app.LoaderManager.LoaderCallbacks} 实现, {@link android.app.LoaderManager} 将调用此实现来报告加载器事件。在此示例中,本地类实现 {@link android.app.LoaderManager.LoaderCallbacks} -接口,因此它会将引用 {@code this} 传递给自己。
    • +接口,因此它会将引用 {@code this} 传递给自己。

    {@link android.app.LoaderManager#initLoader initLoader()} 调用确保加载器已初始化且处于Activity状态。这可能会出现两种结果:

    @@ -362,11 +362,11 @@ public void onLoaderReset(Loader<Cursor> loader) {

    示例

    -

    以下是一个 +

    以下是一个 {@link android.app.Fragment} 完整实现示例。它展示了一个 {@link android.widget.ListView},其中包含针对联系人内容提供程序的查询结果。它使用 {@link android.content.CursorLoader} 管理提供程序的查询。

    - +

    应用如需访问用户联系人(正如此示例中所示),其清单文件必须包括权限 {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}。

    diff --git a/docs/html-intl/intl/zh-cn/guide/components/processes-and-threads.jd b/docs/html-intl/intl/zh-cn/guide/components/processes-and-threads.jd index c88ecf4b81e813d5bd63aa5c552172feb9af16a2..3f7c3cfa6d90ad0b56a936b62a52d500524ae4f1 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/processes-and-threads.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/processes-and-threads.jd @@ -47,7 +47,7 @@ Linux 进程。默认情况下,同一应用的所有组件在相同的进程 <activity>}
    {@code <service>}{@code <receiver>}{@code -<provider>}—均支持 +<provider>}—均支持 {@code android:process} 属性,此属性可以指定该组件应在哪个进程运行。您可以设置此属性,使每个组件均在各自的进程中运行,或者使一些组件共享一个进程,而其他组件则不共享。 此外,您还可以设置 {@code android:process},使不同应用的组件在相同的进程中运行,但前提是这些应用共享相同的 Linux 用户 ID 并使用相同的证书进行签署。 @@ -319,7 +319,7 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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) { diff --git a/docs/html-intl/intl/zh-cn/guide/components/recents.jd b/docs/html-intl/intl/zh-cn/guide/components/recents.jd index 2bf1a5bd4ff35752c127d8399e086f615ab0ffce..bc218f44d07266f7e4c31e8c2078b8a6a0ec55f0 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/recents.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/recents.jd @@ -118,7 +118,7 @@ public void createNewDocument(View view) { 如果未找到任务或者 Intent 包含 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 标志,则会以该 Activity 作为其根创建新任务。如果找到的话,则会将该任务转到前台并将新 - Intent + Intent 传递给 {@link android.app.Activity#onNewIntent onNewIntent()}。新 Activity 将获得 Intent 并在概览屏幕中创建新文档,如下例所示:

    @@ -176,7 +176,7 @@ protected void onNewIntent(Intent intent) {
    该 Activity 不会为文档创建新任务。设置此值会替代 {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT} 和 {@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK} 标志的行为(如果在 - Intent + Intent 中设置了其中一个标志),并且概览屏幕将为应用显示单个任务,该任务将从用户上次调用的任意 Activity 开始继续执行。
    diff --git a/docs/html-intl/intl/zh-cn/guide/components/services.jd b/docs/html-intl/intl/zh-cn/guide/components/services.jd index 9a00e704fa38076e3d15e0c18582fb1c5e702f41..c7c848b75e39a90223b7ed6e0508afe72f8be83e 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/services.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/services.jd @@ -244,7 +244,7 @@ android.content.Context#startService startService()} 方法并传递 {@link andr {@link android.app.Service#onStartCommand onStartCommand()} 方法接收此 {@link android.content.Intent}。

    -

    例如,假设某 Activity 需要将一些数据保存到在线数据库中。该 Activity 可以启动一个协同服务,并通过向 +

    例如,假设某 Activity 需要将一些数据保存到在线数据库中。该 Activity 可以启动一个协同服务,并通过向 {@link android.content.Context#startService startService()} 传递一个 Intent,为该服务提供要保存的数据。服务通过 {@link diff --git a/docs/html-intl/intl/zh-cn/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/zh-cn/guide/components/tasks-and-back-stack.jd index 07fdf6e80a027c98705f0060ad4a519fabc168ce..88aa78ebb516104df3192569b291bf9fc444d2c0 100644 --- a/docs/html-intl/intl/zh-cn/guide/components/tasks-and-back-stack.jd +++ b/docs/html-intl/intl/zh-cn/guide/components/tasks-and-back-stack.jd @@ -45,7 +45,7 @@ Android 多任务运行机制

    一个 Activity 甚至可以启动设备上其他应用中存在的 Activity。例如,如果应用想要发送电子邮件,则可将 Intent 定义为执行“发送”操作并加入一些数据,如电子邮件地址和电子邮件。 然后,系统将打开其他应用中声明自己处理此类 - Intent 的 Activity。在这种情况下, Intent + Intent 的 Activity。在这种情况下, Intent 是要发送电子邮件,因此将启动电子邮件应用的“撰写”Activity(如果多个 Activity 支持相同 Intent,则系统会让用户选择要使用的 Activity)。发送电子邮件时,Activity 将恢复,看起来好像电子邮件 Activity 是您的应用的一部分。 即使这两个 Activity 可能来自不同的应用,但是 @@ -246,7 +246,7 @@ B)。与该应用交互之后,用户再次返回主屏幕并选择最初启

  • {@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}
  • -

    在下文中,您将了解如何使用这些清单文件属性和 Intent +

    在下文中,您将了解如何使用这些清单文件属性和 Intent 标志定义 Activity 与任务的关联方式,以及 Activity 在返回栈中的行为方式。

    此外,我们还单独介绍了有关如何在概览屏幕中显示和管理任务与 Activity 的注意事项。 @@ -282,7 +282,7 @@ A 启动 Activity B,则 Activity B 可以在其清单文件中定义它应该 B 的请求(如其清单文件中所定义)。

    注:某些适用于清单文件的启动 -模式不可用作 Intent 标志,同样,某些可用作 Intent +模式不可用作 Intent 标志,同样,某些可用作 Intent 标志的启动模式无法在清单文件中定义。

    @@ -370,7 +370,7 @@ Android 浏览器的 属性和可接受的值。

    注:使用 {@code launchMode} -属性为 Activity 指定的行为可由 Intent +属性为 Activity 指定的行为可由 Intent 附带的 Activity 启动标志替代,下文将对此进行讨论。

    @@ -378,7 +378,7 @@ Android 浏览器的

    使用 Intent 标志

    启动 Activity 时,您可以通过在传递给 {@link -android.app.Activity#startActivity startActivity()} 的 Intent +android.app.Activity#startActivity startActivity()} 的 Intent 中加入相应的标志,修改 Activity 与其任务的默认关联方式。可用于修改默认行为的标志包括:

    @@ -404,7 +404,7 @@ android.app.Activity#startActivity startActivity()} 的 Intent 属性没有值。

    {@code FLAG_ACTIVITY_CLEAR_TOP} 通常与 {@code FLAG_ACTIVITY_NEW_TASK} -结合使用。一起使用时,通过这些标志,可以找到其他任务中的现有 Activity,并将其放入可从中响应 Intent +结合使用。一起使用时,通过这些标志,可以找到其他任务中的现有 Activity,并将其放入可从中响应 Intent 的位置。

    注:如果指定 Activity 的启动模式为 {@code "standard"},则该 Activity 也会从堆栈中删除,并在其位置启动一个新实例,以便处理传入的 Intent。 diff --git a/docs/html-intl/intl/zh-cn/preview/j8-jack.jd b/docs/html-intl/intl/zh-cn/guide/platform/j8-jack.jd similarity index 100% rename from docs/html-intl/intl/zh-cn/preview/j8-jack.jd rename to docs/html-intl/intl/zh-cn/guide/platform/j8-jack.jd diff --git a/docs/html-intl/intl/zh-cn/guide/topics/manifest/manifest-intro.jd b/docs/html-intl/intl/zh-cn/guide/topics/manifest/manifest-intro.jd index c7ade4f392dbfd7679384f08471097a25e0b73f7..65b3b232df42f928eafd062a3079129e54813e63 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/manifest/manifest-intro.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/manifest/manifest-intro.jd @@ -34,14 +34,14 @@ Android 系统提供有关您的应用的基本信息,系统必须获得这些

  • 描述应用的各个组件,即:构成应用的 Activity、服务、广播接收器和内容提供程序。 为实现每个组件的类命名并发布其功能(例如,它们可以处理的 -{@link android.content.Intent +{@link android.content.Intent Intent} 消息)。根据这些声明,Android 系统可以了解这组件具体是什么,以及在什么条件下可以启动它们
  • -
  • 确定将托管应用组件的进程
  • +
  • 确定将托管应用组件的进程
  • 声明应用必须具备哪些权限才能访问 -API 中受保护的部分并与其他应用交互
  • +API 中受保护的部分并与其他应用交互
  • 还声明其他应用与该应用组件交互所需具备的权限
  • @@ -66,7 +66,7 @@ API 中受保护的部分并与其他应用交互 要查看有关任何元素的详细信息,请点击该图中或其后按字母顺序排列的元素列表中相应的元素名称,或者点击任何其他地方提到的相应元素名称。 - +

    @@ -128,7 +128,7 @@ API 中受保护的部分并与其他应用交互
     

    可出现在清单文件中的所有元素按字母顺序罗列如下。 这些是仅有的合法元素;您无法添加自己的元素或属性。 - +

    @@ -158,7 +158,7 @@ API 中受保护的部分并与其他应用交互

    - +

    文件约定

    @@ -218,7 +218,7 @@ Activity (<service>)、广播接收器 (<receiver>) 以及内容提供程序 -(<provider>)。 +(<provider>)。

    如果按照您针对组件类({@link android.app.Activity}、{@link android.app.Service}、{@link android.content.BroadcastReceiver} @@ -244,7 +244,7 @@ Activity 元素的 package 属性中所指定)。 -以下赋值与上述方法相同: +以下赋值与上述方法相同:

    <manifest package="com.example.project" . . . >
    @@ -339,7 +339,7 @@ Android 系统在启动某组件之前必须了解该组件可以处理哪些 In
     

    显式命名目标组件的 Intent 将激活该组件;过滤器不起作用。但是,不按名称指定目标的 - Intent + Intent 只有在能够通过组件的一个过滤器时才可激活该组件。

    @@ -399,7 +399,7 @@ Android 系统在启动某组件之前必须了解该组件可以处理哪些 In

    权限 是一种限制,用于限制对部分代码或设备上数据的访问。 施加限制是为了保护可能被误用以致破坏或损害用户体验的关键数据和代码。 - +

    @@ -427,7 +427,7 @@ Android 定义的一些权限: 如果授予权限,则应用能够使用受保护的功能。 否则,其访问这些功能的尝试将会失败,并且不会向用户发送任何通知。 - +

    @@ -464,7 +464,7 @@ Android <uses-permission> 元素来请求。要让应用的其他组件也能够启动受保护的 Activity,就必须请求其使用权限,即便保护是由应用本身施加的亦如此。 - +

    @@ -474,7 +474,7 @@ Android <permission> 元素再次声明。 但是,仍有必要通过 -<uses-permission> 请求使用它。 +<uses-permission> 请求使用它。

    diff --git a/docs/html-intl/intl/zh-cn/guide/topics/providers/calendar-provider.jd b/docs/html-intl/intl/zh-cn/guide/topics/providers/calendar-provider.jd index 59682843897da6c49f4ffb8cc3c6d5c1ff5904cf..b34cd8bf28911aa6ecad87c0d0087a89fd890fa2 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/providers/calendar-provider.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/providers/calendar-provider.jd @@ -42,7 +42,7 @@ page.title=日历提供程序

  • 使用 Intent 对象查看日历数据
  • - +
  • 同步适配器
  • @@ -113,14 +113,14 @@ URI 的格式为 <class>.CONTENT_URI。例如,{@li

    {@link android.provider.CalendarContract.Calendars}

    - + 此表储存日历特定信息。 此表中的每一行都包含一个日历的详细信息,例如名称、颜色、同步信息等。 {@link android.provider.CalendarContract.Events} - + 此表储存事件特定信息。 此表中的每一行都包含一个事件的信息—例如事件名称、地点、开始时间、结束时间等。 @@ -132,7 +132,7 @@ URI 的格式为 <class>.CONTENT_URI。例如,{@li {@link android.provider.CalendarContract.Instances} - + 此表储存每个事件实例的开始时间和结束时间。 此表中的每一行都表示一个事件实例。 对于一次性事件,实例与事件为 1:1 @@ -141,7 +141,7 @@ URI 的格式为 <class>.CONTENT_URI。例如,{@li {@link android.provider.CalendarContract.Attendees} - + 此表储存事件参加者(来宾)信息。 每一行都表示事件的一位来宾。 它指定来宾的类型以及事件的来宾出席响应。 @@ -149,7 +149,7 @@ URI 的格式为 <class>.CONTENT_URI。例如,{@li {@link android.provider.CalendarContract.Reminders} - + 此表储存提醒/通知数据。 每一行都表示事件的一个提醒。一个事件可以有多个提醒。 每个事件的最大提醒数量在 @@ -159,7 +159,7 @@ URI 的格式为 <class>.CONTENT_URI。例如,{@li 中指定,后者由拥有给定日历的同步适配器设置。提醒以事件发生前的分钟数形式指定,其具有一个可决定用户提醒方式的方法。 - +

    Calendar Provider API 以灵活、强大为设计宗旨。提供良好的最终用户体验以及保护日历及其数据的完整性也同样重要。 @@ -229,7 +229,7 @@ android.Manifest.permission#READ_CALENDAR} 权限。文件中必须包括用于 {@link android.provider.CalendarContract.Calendars#VISIBLE} - + 表示是否选择显示该日历的布尔值。值为 0 表示不应显示与该日历关联的事件。 值为 1 @@ -240,7 +240,7 @@ android.provider.CalendarContract.Instances} 表中行的生成。 {@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS} - + 一个布尔值,表示是否应同步日历并将其事件存储在设备上。 值为 0 表示不同步该日历,也不将其事件存储在设备上。值为 1 @@ -268,13 +268,13 @@ public static final String[] EVENT_PROJECTION = new String[] { Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;

    - + +帐户不会进行同步。

    在示例的下一部分,您需要构建查询。选定范围指定查询的条件。 @@ -308,38 +308,38 @@ android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}

    // Run query
     Cursor cur = null;
     ContentResolver cr = getContentResolver();
    -Uri uri = Calendars.CONTENT_URI;   
    -String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    +Uri uri = Calendars.CONTENT_URI;
    +String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                             + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                             + Calendars.OWNER_ACCOUNT + " = ?))";
     String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
    -        "sampleuser@gmail.com"}; 
    -// Submit the query and get a Cursor object back. 
    +        "sampleuser@gmail.com"};
    +// Submit the query and get a Cursor object back.
     cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

    以下后续部分使用游标单步调试结果集。它使用在示例开头设置的常量来返回每个字段的值。

    - +
    // Use the cursor to step through the returned records
     while (cur.moveToNext()) {
         long calID = 0;
         String displayName = null;
         String accountName = null;
         String ownerName = null;
    -      
    +
         // Get the field values
         calID = cur.getLong(PROJECTION_ID_INDEX);
         displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
         accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
         ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
    -              
    +
         // Do something with the values...
     
        ...
     }
     
    - +

    修改日历

    如需执行日历更新,您可以通过 @@ -434,7 +434,7 @@ android.provider.CalendarContract.Events} 参考资料。

    {@link android.provider.CalendarContract.EventsColumns#DURATION} - + RFC5545 格式的事件持续时间。例如,值为 "PT1H" 表示事件应持续一小时,值为 @@ -444,39 +444,39 @@ android.provider.CalendarContract.Events} 参考资料。

    {@link android.provider.CalendarContract.EventsColumns#ALL_DAY} - + 值为 1 表示此事件占用一整天(按照本地时区的定义)。值为 0 表示它是常规事件,可在一天内的任何时间开始和结束。 - + - - + + {@link android.provider.CalendarContract.EventsColumns#RRULE} - + 事件的重复发生规则格式。例如,"FREQ=WEEKLY;COUNT=10;WKST=SU"。 您可以在此处找到更多示例。 - + - + {@link android.provider.CalendarContract.EventsColumns#RDATE} 事件的重复发生日期。 -{@link android.provider.CalendarContract.EventsColumns#RDATE} -与 {@link android.provider.CalendarContract.EventsColumns#RRULE} +{@link android.provider.CalendarContract.EventsColumns#RDATE} +与 {@link android.provider.CalendarContract.EventsColumns#RRULE} 通常联合用于定义一组聚合重复实例。 如需查看更详细的介绍,请参阅 RFC5545 规范。 - + {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY} - + 将此事件视为忙碌时间还是可调度的空闲时间。 - + {@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY} @@ -514,11 +514,11 @@ java.util.TimeZone#getAvailableIDs()}。请注意,如果您按参加者表

    {@link android.provider.CalendarContract.Attendees} -表的每一行都表示事件的一位参加者或来宾。调用 -{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} +表的每一行都表示事件的一位参加者或来宾。调用 +{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 会返回一个参加者列表,其中包含具有给定 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 的事件的参加者。 -此 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} +此 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 必须匹配特定事件的 {@link -android.provider.BaseColumns#_ID}。

    +android.provider.BaseColumns#_ID}。

    下表列出了可写入的字段。 插入新参加者时,您必须加入除 ATTENDEE_NAME 之外的所有字段。 @@ -718,7 +718,7 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values);

    提醒表

    {@link android.provider.CalendarContract.Reminders} -表的每一行都表示事件的一个提醒。调用 +表的每一行都表示事件的一个提醒。调用 {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 会返回一个提醒列表,其中包含具有给定 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 的事件的提醒。

    @@ -727,7 +727,7 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values);

    下表列出了提醒的可写入字段。插入新提醒时,必须加入所有字段。 请注意,同步适配器指定它们在 {@link -android.provider.CalendarContract.Calendars} 表中支持的提醒类型。详情请参阅 +android.provider.CalendarContract.Calendars} 表中支持的提醒类型。详情请参阅 {@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} 。

    @@ -780,9 +780,9 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values);

    下表列出了一些您可以执行实例查询的字段。请注意, -时区由 -{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} -和 +时区由 +{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} +和 {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES} 定义。

    @@ -801,18 +801,18 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values); {@link android.provider.CalendarContract.Instances#END_DAY} - + 与日历时区相应的实例儒略历结束日。 - - + + {@link android.provider.CalendarContract.Instances#END_MINUTE} - + 从日历时区午夜开始计算的实例结束时间(分钟)。 - + {@link android.provider.CalendarContract.Instances#EVENT_ID} @@ -820,16 +820,16 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values); {@link android.provider.CalendarContract.Instances#START_DAY} - 与日历时区相应的实例儒略历开始日。 + 与日历时区相应的实例儒略历开始日。 {@link android.provider.CalendarContract.Instances#START_MINUTE} - + 从日历时区午夜开始计算的实例开始时间(分钟)。 - + - + @@ -853,7 +853,7 @@ public static final String[] INSTANCE_PROJECTION = new String[] { Instances.BEGIN, // 1 Instances.TITLE // 2 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; @@ -868,7 +868,7 @@ long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); - + Cursor cur = null; ContentResolver cr = getContentResolver(); @@ -883,28 +883,28 @@ ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query -cur = cr.query(builder.build(), - INSTANCE_PROJECTION, - selection, - selectionArgs, +cur = cr.query(builder.build(), + INSTANCE_PROJECTION, + selection, + selectionArgs, null); - + while (cur.moveToNext()) { String title = null; long eventID = 0; - long beginVal = 0; - + long beginVal = 0; + // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); - - // Do something with the values. - Log.i(DEBUG_TAG, "Event: " + title); + + // Do something with the values. + Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(beginVal); + calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); + Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } } @@ -922,9 +922,9 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_VIEW VIEW}

    content://com.android.calendar/time/<ms_since_epoch>

    - 您还可以通过 + 您还可以通过 {@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI} 引用 URI。 -如需查看使用该 Intent 对象的示例,请参阅
    使用 Intent 对象查看日历数据。 +如需查看使用该 Intent 对象的示例,请参阅使用 Intent 对象查看日历数据。 打开日历后定位到 <ms_since_epoch> 指定的时间。 @@ -935,11 +935,11 @@ while (cur.moveToNext()) {

    content://com.android.calendar/events/<event_id>

    - - 您还可以通过 + + 您还可以通过 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 引用 URI。 如需查看使用该 Intent 对象的示例,请参阅使用 Intent 对象查看日历数据。 - + 查看 <event_id> 指定的事件。 @@ -952,12 +952,12 @@ while (cur.moveToNext()) { {@link android.content.Intent#ACTION_EDIT EDIT}

    content://com.android.calendar/events/<event_id>

    - - 您还可以通过 + + 您还可以通过 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 引用 URI。 如需查看使用该 Intent 对象的示例,请参阅使用 Intent 对象编辑事件。 - - + + 编辑 <event_id> 指定的事件。 @@ -972,11 +972,11 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_INSERT INSERT}

    content://com.android.calendar/events

    - - 您还可以通过 + + 您还可以通过 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 引用 URI。 如需查看使用该 Intent 对象的示例,请参阅使用 Intent 对象插入事件。 - + 创建事件。 @@ -996,7 +996,7 @@ while (cur.moveToNext()) { 事件的名称。 - + {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} 事件开始时间,以从公元纪年开始计算的毫秒数表示。 @@ -1004,25 +1004,25 @@ CalendarContract.EXTRA_EVENT_BEGIN_TIME} {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} - + 事件结束时间,以从公元纪年开始计算的毫秒数表示。 {@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY CalendarContract.EXTRA_EVENT_ALL_DAY} - + 一个布尔值,表示事件属于全天事件。值可以是 truefalse。 {@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION Events.EVENT_LOCATION} - + 事件的地点。 {@link android.provider.CalendarContract.EventsColumns#DESCRIPTION Events.DESCRIPTION} - + 事件描述。 @@ -1039,16 +1039,16 @@ Events.DESCRIPTION} {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL Events.ACCESS_LEVEL} - + 事件是私人性质还是公共性质。 {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY Events.AVAILABILITY} - + 将此事件视为忙碌时间还是可调度的空闲时间。 - - + +

    下文描述如何使用这些 Intent 对象。

    @@ -1059,23 +1059,23 @@ Events.AVAILABILITY} {@link android.Manifest.permission#WRITE_CALENDAR} 权限。

    - +

    当用户运行使用此方法的应用时,应用会将其转到日历来完成事件添加操作。 {@link android.content.Intent#ACTION_INSERT INSERT} Intent 利用 extra 字段为表单预填充日历中事件的详细信息。用户随后可取消事件、根据需要编辑表单或将事件保存到日历中。

    - +

    以下是一个代码段,用于安排一个在 2012 年 1 月 19 日上午 7:30 开始、8:30 结束的事件。请注意该代码段中的以下内容:

      -
    • 它将 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} +
    • 它将 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 指定为 URI。
    • - +
    • 它使用 {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} 和 {@link @@ -1083,10 +1083,10 @@ android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} extra 字段为表单预填充事件的时间。这些时间的值必须以从公元纪年开始计算的协调世界时毫秒数表示。
    • - +
    • 它使用 {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL} extra 字段提供以逗号分隔的受邀者电子邮件地址列表。
    • - +
     Calendar beginTime = Calendar.getInstance();
    @@ -1158,18 +1158,18 @@ startActivity(intent);
     
     
    • 同步适配器需要通过将 {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} 设置为 true 来表明它是同步适配器。
    • - - + +
    • 同步适配器需要提供 {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} 和 {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} 作为 URI 中的查询参数。
    • - +
    • 与应用或小工具相比,同步适配器拥有写入权限的列更多。 例如,应用只能修改日历的少数几种特性, 例如其名称、显示名称、能见度设置以及是否同步日历。 相比之下,同步适配器不仅可以访问这些列,还能访问许多其他列, 例如日历颜色、时区、访问级别、地点等等。不过,同步适配器受限于它指定的 -ACCOUNT_NAME 和 +ACCOUNT_NAMEACCOUNT_TYPE

    您可以利用以下 helper 方法返回供与同步适配器一起使用的 URI:

    @@ -1180,5 +1180,5 @@ android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} 作为 URI 中的查 .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }
    -

    如需查看同步适配器的实现示例(并非仅限与日历有关的实现),请参阅 +

    如需查看同步适配器的实现示例(并非仅限与日历有关的实现),请参阅 SampleSyncAdapter。 diff --git a/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-basics.jd b/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-basics.jd index 4c91d3a19c96cda97a775d370d873df1a641461d..b1a1c5ab49c89f106282e7fcf8f6a5e7d9e67f9b 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-basics.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-basics.jd @@ -251,7 +251,7 @@ mCursor = getContentResolver().query(

    表 2 显示了 - {@link android.content.ContentResolver#query + {@link android.content.ContentResolver#query query(Uri,projection,selection,selectionArgs,sortOrder)} 的参数如何匹配 SQL SELECT 语句:

    @@ -717,7 +717,7 @@ if (mCursor != null) { <uses-permission android:name="android.permission.READ_USER_DICTIONARY">

    - + 安全与权限指南中详细介绍了权限对提供程序访问的影响。

    @@ -944,7 +944,7 @@ mRowsDeleted = getContentResolver().delete(

    要在“批量模式”下访问提供程序, -您可以创建 {@link android.content.ContentProviderOperation} 对象数组,然后使用 {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()} +您可以创建 {@link android.content.ContentProviderOperation} 对象数组,然后使用 {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()} 将其分派给内容提供程序。 您需将内容提供程序的授权传递给此方法,而不是特定内容 URI。这样可使数组中的每个 {@link android.content.ContentProviderOperation} 对象都能适用于其他表。 @@ -1191,6 +1191,6 @@ vnd.android.cursor.item/vnd.example.line2

    - + 内容 URI 部分介绍了单个行的内容 URI。

    diff --git a/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-creating.jd index 6da57435f43dca7bddc743b3f9c514137182be9c..329754e1c5d80cb547272c0fd5263e317b65509d 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-creating.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/providers/content-provider-creating.jd @@ -277,7 +277,7 @@ page.title=创建内容提供程序

    - + 内容提供程序基础知识主题中描述了内容 URI 的基础知识。

    @@ -569,7 +569,7 @@ public class ExampleProvider extends ContentProvider {

    实现 query() 方法

    - + {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) ContentProvider.query()} 方法必须返回 {@link android.database.Cursor} 对象。如果失败,则会引发 {@link java.lang.Exception}。 如果您使用 SQLite 数据库作为数据存储,则只需返回由 {@link android.database.sqlite.SQLiteDatabase} 类的其中一个 @@ -831,7 +831,7 @@ vnd.android.cursor.item/vnd.com.example.provider.table1

    文件的 MIME 类型

    - 如果您的提供程序提供文件,请实现 + 如果您的提供程序提供文件,请实现 {@link android.content.ContentProvider#getStreamTypes(Uri, String) getStreamTypes()}。 该方法会为您的提供程序可以为给定内容 URI 返回的文件返回一个 MIME 类型 {@link java.lang.String} 数组。您应该通过 MIME 类型过滤器参数过滤您提供的 MIME 类型,以便只返回客户端想处理的那些 MIME 类型。 diff --git a/docs/html-intl/intl/zh-cn/guide/topics/providers/document-provider.jd b/docs/html-intl/intl/zh-cn/guide/topics/providers/document-provider.jd index fd36e2963606376d0f0c94202cfadfc4b2f1c12a..db5b1a4f09d02c421a908ebffc8ef998f6ad83f9 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/providers/document-provider.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/providers/document-provider.jd @@ -177,7 +177,7 @@ URI 授权; 中,提供程序和客户端并不直接交互。客户端请求与文件交互(即读取、编辑、创建或删除文件)的权限; -

  • 交互在应用(在本示例中为照片应用)触发 Intent +
  • 交互在应用(在本示例中为照片应用)触发 Intent {@link android.content.Intent#ACTION_OPEN_DOCUMENT} 或 {@link android.content.Intent#ACTION_CREATE_DOCUMENT} 后开始。Intent 可能包括进一步细化条件的过滤器—例如,“为我提供所有 MIME 类型为‘图像’的可打开文件”;
  • @@ -460,7 +460,7 @@ DocumentsContract.deleteDocument(getContentResolver(), uri);

    您可以使用 SAF 就地编辑文本文档。以下代码段会触发 -{@link android.content.Intent#ACTION_OPEN_DOCUMENT} Intent +{@link android.content.Intent#ACTION_OPEN_DOCUMENT} Intent 并使用类别 {@link android.content.Intent#CATEGORY_OPENABLE} 以仅显示可以打开的文档。它会进一步过滤以仅显示文本文件:

    @@ -589,7 +589,7 @@ SAF
  • 一个包括 -{@code android.content.action.DOCUMENTS_PROVIDER} 操作的 Intent +{@code android.content.action.DOCUMENTS_PROVIDER} 操作的 Intent 过滤器,以便在系统搜索提供程序时让您的提供程序出现在选取器中。
  • @@ -623,7 +623,7 @@ SAF Android 4.4 及更高版本的设备。如果您想让应用支持 {@link android.content.Intent#ACTION_GET_CONTENT} 以适应运行 Android 4.3 及更低版本的设备,则应在您的清单文件中为运行 Android 4.4 -或更高版本的设备禁用 {@link android.content.Intent#ACTION_GET_CONTENT} Intent +或更高版本的设备禁用 {@link android.content.Intent#ACTION_GET_CONTENT} Intent 过滤器。应将文档提供程序和 {@link android.content.Intent#ACTION_GET_CONTENT} 视为具有互斥性。如果您同时支持这两者,您的应用将在系统选取器 @@ -631,7 +631,7 @@ UI 中出现两次,提供两种不同的方式来访问您存储的数据。这会给用户造成困惑。

    建议按照以下步骤为运行 Android 4.4 版或更高版本的设备禁用 -{@link android.content.Intent#ACTION_GET_CONTENT} Intent +{@link android.content.Intent#ACTION_GET_CONTENT} Intent 过滤器:

      @@ -643,7 +643,7 @@ UI
    1. 添加一个Activity别名,为 4.4 版(API 19 -级)或更高版本禁用 {@link android.content.Intent#ACTION_GET_CONTENT} Intent +级)或更高版本禁用 {@link android.content.Intent#ACTION_GET_CONTENT} Intent 过滤器。例如:
      diff --git a/docs/html-intl/intl/zh-cn/guide/topics/resources/providing-resources.jd b/docs/html-intl/intl/zh-cn/guide/topics/resources/providing-resources.jd
      index ea46d86152a4a854ff1319302ab4105a8d7363bc..1516814ccf4767015ef96cd17291901a281cfaa6 100644
      --- a/docs/html-intl/intl/zh-cn/guide/topics/resources/providing-resources.jd
      +++ b/docs/html-intl/intl/zh-cn/guide/topics/resources/providing-resources.jd
      @@ -398,7 +398,7 @@ UI。因此,使用的值应该是布局所需要的实际最小尺寸
                 
    2. 600,适用于 600x1024 mdpi 之类的屏幕(7 英寸平板电脑)。
    3. 720,适用于 720x1280 mdpi 之类的屏幕(10 英寸平板电脑)。
    4. -

      应用为多个资源目录提供不同的 +

      应用为多个资源目录提供不同的 smallestWidth 限定符值时,系统会使用最接近(但未超出)设备 smallestWidth 的值。

      此项为 API 级别 13 中新增配置。

      @@ -428,7 +428,7 @@ smallestWidth 值。

      应用为多个资源目录提供不同的此配置值时,系统会使用最接近(但未超出)设备当前屏幕宽度的值。 此处的值考虑到了屏幕装饰元素,因此如果设备显示屏的左边缘或右边缘上有一些永久性 UI -元素,考虑到这些 UI +元素,考虑到这些 UI 元素,它会使用小于实际屏幕尺寸的宽度值,这样会减少应用的可用空间。

      @@ -456,7 +456,7 @@ smallestWidth 值。

      应用为多个资源目录提供不同的此配置值时,系统会使用最接近(但未超出)设备当前屏幕高度的值。 此处的值考虑到了屏幕装饰元素,因此如果设备显示屏的上边缘或下边缘有一些永久性 UI -元素,考虑到这些 UI +元素,考虑到这些 UI 元素,同时为减少应用的可用空间,它会使用小于实际屏幕尺寸的高度值。 非固定的屏幕装饰元素(例如,全屏时可隐藏的手机状态栏)并不在考虑范围内,标题栏或操作栏等窗口装饰也不在考虑范围内,因此应用必须准备好处理稍小于其所指定值的空间。 @@ -510,7 +510,7 @@ xlarge} 限定符标记,但设备是标准尺寸的屏幕)。

      此项为 API 级别 4 中新增配置。

      - +

      如需了解详细信息,请参阅支持多个屏幕

      另请参阅 {@link android.content.res.Configuration#screenLayout} 配置字段,该字段表示屏幕是小尺寸、标准尺寸还是大尺寸。 diff --git a/docs/html-intl/intl/zh-cn/guide/topics/ui/controls.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/controls.jd index 0f1a543d1f66d06775cbb14f364abb69c1680892..3d78bdc57259e12fc0c5b785a0c52eb099916b07 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/ui/controls.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/controls.jd @@ -69,7 +69,7 @@ parent.link=index.html 单选按钮 与复选框类似,不同的是只能选择组中的一个选项。 - {@link android.widget.RadioGroup RadioGroup} + {@link android.widget.RadioGroup RadioGroup}
      {@link android.widget.RadioButton RadioButton} diff --git a/docs/html-intl/intl/zh-cn/guide/topics/ui/dialogs.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/dialogs.jd index 84922b40e4454db00e07d512e3457f274e70dc53..595407d87d25ff0419839879a4a7a1ae7a5cdc06 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/ui/dialogs.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/dialogs.jd @@ -32,7 +32,7 @@ page.tags=提醒对话框,对话框片段

    5. {@link android.app.DialogFragment}
    6. {@link android.app.AlertDialog}
    - +

    另请参阅

    1. 对话框设计指南
    2. @@ -248,7 +248,7 @@ AlertDialog dialog = builder.create();
      中性
      您应该在用户可能不想继续执行操作,但也不一定想要取消操作时使用此按钮。 它出现在肯定按钮和否定按钮之间。 -例如,实际操作可能是“稍后提醒我”。
      +例如,实际操作可能是“稍后提醒我”。

      对于每种按钮类型,您只能为 {@link @@ -317,10 +317,10 @@ android.app.AlertDialog.Builder#setAdapter setAdapter()} 指定一个列表。

      添加永久性多选列表或单选列表

      -

      要想添加多选项(复选框)或单选项(单选按钮)列表,请分别使用 +

      要想添加多选项(复选框)或单选项(单选按钮)列表,请分别使用 {@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, -DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} 或 -{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} 或 +{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} 方法。

      @@ -346,7 +346,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // 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 + // Else, if the item is already in the array, remove it mSelectedItems.remove(Integer.valueOf(which)); } } @@ -373,7 +373,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

      尽管传统列表和具有单选按钮的列表都能提供“单选”操作,但如果您想持久保存用户的选择,则应使用 {@link -android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()}。也就是说,如果稍后再次打开对话框时系统应指示用户的当前选择,那么您就需要创建一个具有单选按钮的列表。

      @@ -442,7 +442,7 @@ android.app.AlertDialog.Builder#setView setView()} 将其添加到 {@link androi {@code "sans-serif"},以便两个文本字段都使用匹配的字体样式。

      要扩展 {@link android.support.v4.app.DialogFragment} -中的布局,请通过 {@link android.app.Activity#getLayoutInflater()} +中的布局,请通过 {@link android.app.Activity#getLayoutInflater()} 获取一个 {@link android.view.LayoutInflater} 并调用 {@link android.view.LayoutInflater#inflate inflate()},其中第一个参数是布局资源 ID,第二个参数是布局的父视图。然后,您可以调用 @@ -470,7 +470,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { public void onClick(DialogInterface dialog, int id) { LoginDialogFragment.this.getDialog().cancel(); } - }); + }); return builder.create(); } @@ -505,7 +505,7 @@ API。

       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. */
      @@ -513,10 +513,10 @@ public class NoticeDialogFragment extends DialogFragment {
               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
           @Override
           public void onAttach(Activity activity) {
      @@ -543,7 +543,7 @@ public class NoticeDialogFragment extends DialogFragment {
       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();
      @@ -656,7 +656,7 @@ public class CustomDialogFragment extends DialogFragment {
               // 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. */
           @Override
           public Dialog onCreateDialog(Bundle savedInstanceState) {
      @@ -678,7 +678,7 @@ UI:

      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"); diff --git a/docs/html-intl/intl/zh-cn/guide/topics/ui/menus.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/menus.jd index b77f3bf497daa663f7332d0f0e6662050520e8c6..bafbc65e7167aa0b3e89635aec57bbd8b8e1ce04 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/ui/menus.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/menus.jd @@ -83,9 +83,9 @@ Android 3.0 及更高版本的系统中,创建选项菜单部分。

      - +
      上下文菜单和上下文操作模式
      - +
      上下文菜单是用户长按某一元素时出现的浮动菜单。 它提供的操作将影响所选内容或上下文框架。 @@ -94,7 +94,7 @@ Android 3.0 及更高版本的系统中,创建上下文菜单部分。

      - +
      弹出菜单
      弹出菜单将以垂直列表形式显示一系列项目,这些项目将锚定到调用该菜单的视图中。 它特别适用于提供与特定内容相关的大量操作,或者为命令的另一部分提供选项。 @@ -135,7 +135,7 @@ XML 菜单资源<item>
      创建 {@link android.view.MenuItem},此元素表示菜单中的一项,可能包含嵌套的 <menu> 元素,以便创建子菜单。
      - +
      <group>
      {@code <item>} 元素的不可见容器(可选)。它支持您对菜单项进行分类,使其共享活动状态和可见性等属性。 如需了解详细信息,请参阅创建菜单组部分。 @@ -742,8 +742,8 @@ android.view.Menu} 对象中。在 API 级别 14 及更高版本中,您可以
       <ImageButton
      -    android:layout_width="wrap_content" 
      -    android:layout_height="wrap_content" 
      +    android:layout_width="wrap_content"
      +    android:layout_height="wrap_content"
           android:src="@drawable/ic_overflow_holo_dark"
           android:contentDescription="@string/descr_overflow_button"
           android:onClick="showPopup" />
      diff --git a/docs/html-intl/intl/zh-cn/preview/features/multi-window.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/multi-window.jd
      similarity index 98%
      rename from docs/html-intl/intl/zh-cn/preview/features/multi-window.jd
      rename to docs/html-intl/intl/zh-cn/guide/topics/ui/multi-window.jd
      index cfcdf6d5e5f380787e9242f256645ad15890d3c3..5ec27d73058c5e63b3f3324dee98e191c0e4e065 100644
      --- a/docs/html-intl/intl/zh-cn/preview/features/multi-window.jd
      +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/multi-window.jd
      @@ -4,8 +4,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form"
       
       @jd:body
       
      -
      -
      +
      +

      本文内容

      1. 概览
      2. @@ -69,8 +69,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form" - +

        图 1. 两个应用在分屏模式中左右并排显示。

        diff --git a/docs/html-intl/intl/zh-cn/guide/topics/ui/notifiers/notifications.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/notifiers/notifications.jd index c0bd74cdd3ac3cc3f8533d335b96aa401e7edde8..890831841457e6a46a48f8f3f74aef0d87ab93d9 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/notifiers/notifications.jd @@ -321,7 +321,7 @@ Android 4.1 及更高版本的系统中可用。

        - 注:此 + 注:此 Gmail 功能需要“收件箱”扩展布局,该布局是自 Android 4.1 版本起可用的扩展通知功能的一部分。

        @@ -409,7 +409,7 @@ numMessages = 0; 您要启动的 {@link android.app.Activity} 是应用的正常工作流的一部分。在这种情况下,请设置 {@link android.app.PendingIntent} 以启动全新任务并为 -{@link android.app.PendingIntent}提供返回栈,这将重现应用的正常“返回”行为。 +{@link android.app.PendingIntent}提供返回栈,这将重现应用的正常“返回”行为。

        Gmail 应用中的通知演示了这一点。点击一封电子邮件消息的通知时,您将看到消息具体内容。 触摸返回将使您从 @@ -533,7 +533,7 @@ Gmail 中撰写消息时点击了一封电子邮件的通知,则会立即转 TaskStackBuilder.editIntentAt()} 向堆栈中的 {@link android.content.Intent} 对象添加参数。有时,需要确保目标 {@link android.app.Activity} 在用户使用“返回”导航回它时会显示有意义的数据。 - +

      3. 通过调用 diff --git a/docs/html-intl/intl/zh-cn/guide/topics/ui/overview.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/overview.jd index 5097c76e4027957c8b3cf4ea70681873eed31f91..78f4734fde591aa7274fb7e7e35e0e7389afef98 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/ui/overview.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/overview.jd @@ -39,7 +39,7 @@ UI
         <?xml version="1.0" encoding="utf-8"?>
         <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        -              android:layout_width="fill_parent" 
        +              android:layout_width="fill_parent"
                       android:layout_height="fill_parent"
                       android:orientation="vertical" >
             <TextView android:id="@+id/text"
        @@ -60,7 +60,7 @@ UI
         

        有关创建 UI 布局的完整指南,请参阅 XML 布局。 - +

        用户界面组件

        您无需使用 {@link android.view.View} 和 {@link diff --git a/docs/html-intl/intl/zh-cn/guide/topics/ui/settings.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/settings.jd index f9be97be8c2e1b91e6f1dfe0df627b4e2aa6cb2d..71b185da2ba211e46dceae1feddd38af568ea7e1 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/ui/settings.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/settings.jd @@ -226,7 +226,7 @@ android.preference.ListPreference}。这两项均包括以下三个属性:

        {@code android:key}
        对于要保留数据值的首选项,必须拥有此属性。它指定系统在将此设置的值保存在 {@link -android.content.SharedPreferences} 中时所用的唯一键(字符串)。 +android.content.SharedPreferences} 中时所用的唯一键(字符串)。

        不需要此属性的仅有情形是:首选项是 {@link android.preference.PreferenceCategory} 或{@link android.preference.PreferenceScreen},或者首选项指定要调用的 {@link android.content.Intent}(使用 {@code <intent>} 元素)或要显示的 {@link android.app.Fragment}(使用 {@code @@ -285,7 +285,7 @@ android.preference.PreferenceCategory} 内。

         <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        -    <PreferenceCategory 
        +    <PreferenceCategory
                 android:title="@string/pref_sms_storage_title"
                 android:key="pref_key_storage_settings">
                 <CheckBoxPreference
        @@ -293,12 +293,12 @@ android.preference.PreferenceCategory} 内。

        android:summary="@string/pref_summary_auto_delete" android:title="@string/pref_title_auto_delete" android:defaultValue="false"... /> - <Preference + <Preference android:key="pref_key_sms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_sms_delete"... /> - <Preference + <Preference android:key="pref_key_mms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" @@ -588,11 +588,11 @@ XML 标头文件定义。
        2.每组设置均由
         <?xml version="1.0" encoding="utf-8"?>
         <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
                 android:title="@string/prefs_category_one"
                 android:summary="@string/prefs_summ_category_one" />
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
                 android:title="@string/prefs_category_two"
                 android:summary="@string/prefs_summ_category_two" >
        @@ -672,15 +672,15 @@ android.preference.Preference <Preference>} 元素均会向 {@link android
         

        例如,下面就是一个用于 Android 3.0 -及更高版本系统的首选项标头 XML 文件 ({@code res/xml/preference_headers.xml}):

        +及更高版本系统的首选项标头 XML 文件 ({@code res/xml/preference_headers.xml}):

         <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsFragmentOne"
                 android:title="@string/prefs_category_one"
                 android:summary="@string/prefs_summ_category_one" />
        -    <header 
        +    <header
                 android:fragment="com.example.prefs.SettingsFragmentTwo"
                 android:title="@string/prefs_category_two"
                 android:summary="@string/prefs_summ_category_two" />
        @@ -692,18 +692,18 @@ Android 3.0 版本的系统提供相同标头的首选项文件 ({@code res/xml/
         
         
         <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        -    <Preference 
        +    <Preference
                 android:title="@string/prefs_category_one"
                 android:summary="@string/prefs_summ_category_one"  >
        -        <intent 
        +        <intent
                     android:targetPackage="com.example.prefs"
                     android:targetClass="com.example.prefs.SettingsActivity"
                     android:action="com.example.prefs.PREFS_ONE" />
             </Preference>
        -    <Preference 
        +    <Preference
                 android:title="@string/prefs_category_two"
                 android:summary="@string/prefs_summ_category_two" >
        -        <intent 
        +        <intent
                     android:targetPackage="com.example.prefs"
                     android:targetClass="com.example.prefs.SettingsActivity"
                     android:action="com.example.prefs.PREFS_TWO" />
        @@ -920,7 +920,7 @@ android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} 添加 Intent 过滤器。
         </activity>
         
        -

        此 Intent +

        此 Intent 过滤器指示系统此 Activity 控制应用的数据使用情况。因此,当用户从系统的“设置”应用检查应用所使用的数据量时,可以使用“查看应用设置”按钮启动 {@link android.preference.PreferenceActivity},这样,用户就能够优化应用使用的数据量。 @@ -975,11 +975,11 @@ android.preference.DialogPreference} public class NumberPickerPreference extends DialogPreference { public NumberPickerPreference(Context context, AttributeSet attrs) { super(context, attrs); - + setDialogLayoutResource(R.layout.numberpicker_dialog); setPositiveButtonText(android.R.string.ok); setNegativeButtonText(android.R.string.cancel); - + setDialogIcon(null); } ... @@ -1194,7 +1194,7 @@ protected void onRestoreInstanceState(Parcelable state) { // Cast state to custom BaseSavedState and pass to superclass SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); - + // Set this Preference's widget to reflect the restored state mNumberPicker.setValue(myState.value); } diff --git a/docs/html-intl/intl/zh-cn/guide/topics/ui/ui-events.jd b/docs/html-intl/intl/zh-cn/guide/topics/ui/ui-events.jd index f9e976302d347003707e8d9f59a19aeb19330510..faa294d0e6b45edc277228f8d9fc64a5828797b8 100644 --- a/docs/html-intl/intl/zh-cn/guide/topics/ui/ui-events.jd +++ b/docs/html-intl/intl/zh-cn/guide/topics/ui/ui-events.jd @@ -181,14 +181,14 @@ dispatchKeyEvent()} 方法的分派过程。除了通过视图捕获按

        • {@link android.app.Activity#dispatchTouchEvent(MotionEvent) - Activity.dispatchTouchEvent(MotionEvent)}:此方法允许 {@link + Activity.dispatchTouchEvent(MotionEvent)}:此方法允许 {@link android.app.Activity} 在分派给窗口之前截获所有触摸事件。
        • {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent) ViewGroup.onInterceptTouchEvent(MotionEvent)}:此方法允许 {@link android.view.ViewGroup} 监视分派给子视图的事件。
        • {@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) ViewParent.requestDisallowInterceptTouchEvent(boolean)}: -对父视图调用此方法表明不应使用 {@link +对父视图调用此方法表明不应使用 {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)} 截获触摸事件。
        @@ -199,7 +199,7 @@ dispatchKeyEvent()} 方法的分派过程。除了通过视图捕获按 但是,如果设备具有触摸功能且用户开始通过触摸界面与之交互,则不再需要突出显示项目或聚焦到特定视图对象上。 因此,有一种交互模式称为“触摸模式”。 - +

        对于支持触摸功能的设备,当用户触摸屏幕时,设备会立即进入触摸模式。 @@ -282,7 +282,7 @@ ID。例如:

        the framework will take care of measuring, laying out, and drawing the tree as appropriate.
      - +

      Note: 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 diff --git a/docs/html-intl/intl/zh-cn/index.jd b/docs/html-intl/intl/zh-cn/index.jd index ca3a84b80eb2b74ba0d825aad3ce42ced79f1284..c1a5d6f3e4c4ff847402b0498fd2e81569b46dfa 100644 --- a/docs/html-intl/intl/zh-cn/index.jd +++ b/docs/html-intl/intl/zh-cn/index.jd @@ -5,49 +5,36 @@ page.customHeadTag= - -

      -
      -
      - -

      Android N Developer Preview

      -

      - Get ready for the next version of Android! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. +

      +
      -
    - +

    測試

    1. 設定測試環境
    2. @@ -25,7 +25,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
    3. 平板電腦應用程式品質
    4. 最佳化您的應用程式
    - + @@ -70,7 +70,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg ID - + 描述 @@ -1011,4 +1011,4 @@ data-cardsizes="6x3,6x3,6x3,6x3,6x3,6x3" data-maxresults="6">

    請確保使用{@link android.os.StrictMode.ThreadPolicy.Builder#penaltyFlashScreen() penaltyFlashScreen()}針對 ThreadPolicy 啟用政策違犯的視覺通知。 -

    \ No newline at end of file +

    \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/tablets.jd b/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/tablets.jd index 3c16f9daa50bae6c2681c83d7a148adc2c2a2a30..d584e5375095b735de3d5fb60d5a2ba598defdf0 100644 --- a/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/tablets.jd +++ b/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/tablets.jd @@ -46,7 +46,7 @@ Xnonavpage=true

    1.測試基本平板電腦應用程式品質

    -

    提供平板電腦應用程式絕佳體驗的第一步,是確保其符合應用程式所針對所有裝置及尺寸規格的核心應用程式品質準則。如需完備資訊,請參閱核心應用程式品質指導方針。 +

    提供平板電腦應用程式絕佳體驗的第一步,是確保其符合應用程式所針對所有裝置及尺寸規格的核心應用程式品質準則。如需完備資訊,請參閱核心應用程式品質指導方針

    diff --git a/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/wear.jd b/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/wear.jd index 47a2d916a604888c2d0df1d0ddaf8fffa717f587..6dc85e856b5d9f5c81519664362a3e551e54c4f6 100644 --- a/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/wear.jd +++ b/docs/html-intl/intl/zh-tw/distribute/googleplay/quality/wear.jd @@ -395,4 +395,4 @@ data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">

    是。上述需求僅判斷在 Google Play 上是否將您的應用程式視為 Android Wear 應用程式,以及該應用程式是否可供 Android Wear 使用者更輕鬆地探尋。若未接受您的應用程式為 Wear 應用程式,仍會向其他裝置類型 (例如手機或平板電腦) 提供該應用程式,並且仍會安裝在穿戴式裝置上。 -

    \ No newline at end of file +

    \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/distribute/googleplay/start.jd b/docs/html-intl/intl/zh-tw/distribute/googleplay/start.jd index 3364e49bbdcae25a7d9dbe33efce82149d0d7e49..8bff67d02eb7de074acb7225181b37af21cda34d 100644 --- a/docs/html-intl/intl/zh-tw/distribute/googleplay/start.jd +++ b/docs/html-intl/intl/zh-tw/distribute/googleplay/start.jd @@ -134,4 +134,4 @@ href="https://support.google.com/googleplay/android-developer/bin/answer.py?hl=e data-query="collection:distribute/googleplay/gettingstarted" data-sortOrder="-timestamp" data-cardSizes="9x3" - data-maxResults="6"> \ No newline at end of file + data-maxResults="6"> \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/distribute/googleplay/tv.jd b/docs/html-intl/intl/zh-tw/distribute/googleplay/tv.jd index c4f7a7cd089c930ec987b7c0df195989445afa7b..aa2096ad4cdd3e45d703e96b7848d40b64d14df7 100644 --- a/docs/html-intl/intl/zh-tw/distribute/googleplay/tv.jd +++ b/docs/html-intl/intl/zh-tw/distribute/googleplay/tv.jd @@ -173,7 +173,7 @@ page.metaDescription=將您的應用程式、遊戲與內容散佈至 Android

    5.追蹤您的檢閱與核准

    - 若您的應用程式符合 Android 電視的技術與品質準則 (如上所述),則會向 Android 電視的使用者提供您的應用程式。若您的應用程式不符合該準則,您將收到傳送至您開發人員帳戶地址的通知電子郵件,內含需要修正的領域的摘要。若您已進行所需調整,可以將新版本的應用程式上傳至 Developer Console。 + 若您的應用程式符合 Android 電視的技術與品質準則 (如上所述),則會向 Android 電視的使用者提供您的應用程式。若您的應用程式不符合該準則,您將收到傳送至您開發人員帳戶地址的通知電子郵件,內含需要修正的領域的摘要。若您已進行所需調整,可以將新版本的應用程式上傳至 Developer Console。

    @@ -190,7 +190,7 @@ page.metaDescription=將您的應用程式、遊戲與內容散佈至 Android

  • - 已核准 - 已檢閱並核准您的應用程式。會直接向 Android 電視使用者提供該應用程式。 + 已核准 - 已檢閱並核准您的應用程式。會直接向 Android 電視使用者提供該應用程式。
  • @@ -207,4 +207,4 @@ page.metaDescription=將您的應用程式、遊戲與內容散佈至 Android data-query="collection:tvlanding" data-cardSizes="9x6, 6x3x2" data-maxResults="6"> - \ No newline at end of file + \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/distribute/googleplay/wear.jd b/docs/html-intl/intl/zh-tw/distribute/googleplay/wear.jd index 19a48f56a5b552de1aa04b800d137b0bec5a45d2..f4aca5cca51ab6c1305e96ff83de74dff8bd3527 100644 --- a/docs/html-intl/intl/zh-tw/distribute/googleplay/wear.jd +++ b/docs/html-intl/intl/zh-tw/distribute/googleplay/wear.jd @@ -196,4 +196,4 @@ page.metaDescription=將您的應用程式、遊戲與內容散佈至 Android We data-query="collection:wearlanding" data-cardSizes="6x2" data-maxResults="3"> - \ No newline at end of file + \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/distribute/tools/launch-checklist.jd b/docs/html-intl/intl/zh-tw/distribute/tools/launch-checklist.jd index 6e974174849be6c9263f747f69caa2b7bc1ffb3c..167c4f10d5ace5167fdbb104eba7fb1074e407ab 100644 --- a/docs/html-intl/intl/zh-tw/distribute/tools/launch-checklist.jd +++ b/docs/html-intl/intl/zh-tw/distribute/tools/launch-checklist.jd @@ -789,4 +789,4 @@ data-maxresults="6"> data-query="collection:distribute/toolsreference/launchchecklist/afterlaunch" data-sortOrder="-timestamp" data-cardSizes="9x3,9x3,9x3,9x3,9x3,9x3" - data-maxResults="6"> \ No newline at end of file + data-maxResults="6"> \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/distribute/tools/localization-checklist.jd b/docs/html-intl/intl/zh-tw/distribute/tools/localization-checklist.jd index 1b95d0b3458d1bced98edf217c597c1b1b6a3bc4..c34fcee498bc09766e22e3663d65b3cf543d15f3 100644 --- a/docs/html-intl/intl/zh-tw/distribute/tools/localization-checklist.jd +++ b/docs/html-intl/intl/zh-tw/distribute/tools/localization-checklist.jd @@ -713,4 +713,4 @@ data-maxresults="6"> data-query="collection:distribute/toolsreference/localizationchecklist/supportlaunch" data-sortOrder="-timestamp" data-cardSizes="9x3,9x3,6x3,9x3,9x3,9x3" - data-maxResults="6"> \ No newline at end of file + data-maxResults="6"> \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/google/play/filters.jd b/docs/html-intl/intl/zh-tw/google/play/filters.jd index e96b9ddcacd80997a47059c558ded0c64c9d3318..eec87ac75156176b28bfa4419139afb1f18413e4 100644 --- a/docs/html-intl/intl/zh-tw/google/play/filters.jd +++ b/docs/html-intl/intl/zh-tw/google/play/filters.jd @@ -263,4 +263,4 @@ href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-featur

    注意:針對同一應用程式發行多個 APK 是進階功能,多數應用程式應僅發行為諸多裝置組態提供支援的單一 APK。發行多個 APK 需要您遵循篩選器中的特定規則,並格外注意每個 APK 的版本代碼,以確保每個組態使用正確的更新路徑。

    -

    若您需要有關如何在 Google Play 上發行多個 APK 的詳細資訊,請參閱多 APK 支援

    \ No newline at end of file +

    若您需要有關如何在 Google Play 上發行多個 APK 的詳細資訊,請參閱多 APK 支援

    \ No newline at end of file diff --git a/docs/html-intl/intl/zh-tw/guide/components/bound-services.jd b/docs/html-intl/intl/zh-tw/guide/components/bound-services.jd index da47634b894fa7be7a544427a5eed99d3d54bb60..e26e993fd672fc984c3a5aeac90dd0d03a751163 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/bound-services.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/bound-services.jd @@ -303,7 +303,7 @@ public class BindingActivity extends Activity { } -

    上述範例顯示:用戶端如何使用 +

    上述範例顯示:用戶端如何使用 {@link android.content.ServiceConnection} 的實作和 {@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} 回呼,繫結至服務。下一節提供關於繫結至服務處理程序的詳細資訊。

    @@ -334,7 +334,7 @@ android.os.Messenger} 讓服務一次處理一個呼叫。如果您的服務必 -

    如果服務要和遠端處理程序溝通,則可以使用 +

    如果服務要和遠端處理程序溝通,則可以使用 {@link android.os.Messenger} 為您的服務提供介面。此技術讓您不需要使用 AIDL,就可以執行處理程序間通訊 (IPC)。

    @@ -636,7 +636,7 @@ android.content.Context#stopService stopService()} 加以停止,否則服務

    -

    此外,如果您的服務已啟動並且接受繫結,當系統呼叫您的 {@link android.app.Service#onUnbind onUnbind()} 方法時,可以選擇傳回 +

    此外,如果您的服務已啟動並且接受繫結,當系統呼叫您的 {@link android.app.Service#onUnbind onUnbind()} 方法時,可以選擇傳回 {@code true} (如果您希望用戶端下次繫結至服務時,可以接收 {@link android.app.Service#onRebind onRebind()} 呼叫,而不是接收 {@link android.app.Service#onBind onBind()} 的呼叫)。{@link android.app.Service#onRebind diff --git a/docs/html-intl/intl/zh-tw/guide/components/fragments.jd b/docs/html-intl/intl/zh-tw/guide/components/fragments.jd index e54769b0c88b39e1d6159cf7eac77ce7d32415c7..dfef8f1ffaa9e5d5c597edf7901c2daaa3328b3d 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/fragments.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/fragments.jd @@ -36,7 +36,7 @@ parent.link=activities.html

  • {@link android.app.FragmentManager}
  • {@link android.app.FragmentTransaction}
  • - +

    另請參閱

    1. 使用片段建置動態 UI
    2. @@ -46,7 +46,7 @@ parent.link=activities.html -

      {@link android.app.Fragment} 代表一種行為或 +

      {@link android.app.Fragment} 代表一種行為或 {@link android.app.Activity} 中的一部分使用者介面。您可以合併單一 Activity 中的多個片段,藉此建置 多窗格 UI 以及在多個 Activity 中重複使用片段。您可以將片段想成是 Activity 的模組化區段,片段擁有自己的生命週期、接收自己的輸入事件,而且您可以在 Activity 執行時新增或移除片段 (有點像是您可以在不同 Activity 中重複使用的「子 Activity」)。 @@ -204,11 +204,11 @@ android.app.ListFragment} 的子類別,則實作完畢後系統預設會傳回 {@link android.widget.ListView},因此您不必加以實作。

      如要從 {@link -android.app.Fragment#onCreateView onCreateView()} 傳回版面配置,您可以從 XML 中定義的l版面配置資源擴大它。為協助您完成這項作業,{@link android.app.Fragment#onCreateView onCreateView()} 提供了 +android.app.Fragment#onCreateView onCreateView()} 傳回版面配置,您可以從 XML 中定義的l版面配置資源擴大它。為協助您完成這項作業,{@link android.app.Fragment#onCreateView onCreateView()} 提供了 {@link android.view.LayoutInflater} 物件。

      -

      例如,以下是 {@link android.app.Fragment} 的子類別,可從 +

      例如,以下是 {@link android.app.Fragment} 的子類別,可從 {@code example_fragment.xml} 檔案載入版面配置:

      @@ -378,7 +378,7 @@ FragmentRetainInstance.java} 範例 (可透過 Android SDK Manager 存取)
         
    3. 使用 {@link android.app.FragmentManager#findFragmentById findFragmentById()} (針對在 Activity 版面配置中提供 UI 的片段) 或 {@link android.app.FragmentManager#findFragmentByTag findFragmentByTag()} (針對未提供 UI 的片段) 取得 Activity 中的現有片段。 -
    4. +
    5. 使用 {@link android.app.FragmentManager#popBackStack()} (模擬使用者的「返回」命令) 將片段從返回堆疊中推出。
    6. 使用 {@link @@ -563,7 +563,7 @@ public static class FragmentA extends ListFragment {
    7. 如果 Activity 並未實作介面,那麼片段會擲回 -{@link java.lang.ClassCastException}。成功擲回時,{@code mListener} 成員會保留 Activity 所實作 +{@link java.lang.ClassCastException}。成功擲回時,{@code mListener} 成員會保留 Activity 所實作 {@code OnArticleSelectedListener} 的參照資料,以便片段 A 呼叫 {@code OnArticleSelectedListener} 介面定義的方法與 Activity 分享事件。 例如,假設片段 A 是 @@ -739,7 +739,7 @@ android.app.Activity#onCreate onCreate()} 回呼後,Activity 中的片段就 這個 Activity 範例同時示範了如何根據螢幕設定提供不同的片段設定。

      -

      注意:如需這個 Activity 的完整原始碼,請查閱 +

      注意:如需這個 Activity 的完整原始碼,請查閱 {@code FragmentLayout.java}

      @@ -785,7 +785,7 @@ android.widget.FrameLayout}),或是啟動新的 Activity (藉此顯示片段)

      第二個片段 {@code DetailsFragment} 則會針對 {@code TitlesFragment} 中,使用者所選清單項目的劇本摘要:

      - + {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details}

      針對 {@code TitlesFragment} 類別發出的回呼,如果使用者點擊清單項目,而且目前的版面配置「並未」包含 {@code R.id.details} 檢視 ({@code DetailsFragment} 所屬的檢視),則應用程式會執行 {@code DetailsActivity} Activity 來顯示項目內容。 @@ -798,7 +798,7 @@ android.widget.FrameLayout}),或是啟動新的 Activity (藉此顯示片段) {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java details_activity} - +

      請注意,這個 Activity 會在螢幕採用橫向版面配置的情況下自行結束,因此主要 Activity 會接續顯示 {@code TitlesFragment} 旁的 {@code DetailsFragment}。如果使用者在採用直向版面配置的裝置上執行 {@code DetailsActivity},然後將該裝置旋轉成橫向 (這會重新執行目前的 Activity),就可能會發生這種情況。 diff --git a/docs/html-intl/intl/zh-tw/guide/components/fundamentals.jd b/docs/html-intl/intl/zh-tw/guide/components/fundamentals.jd index d3b3c2899614a70221f20bda44b06e3a52af2d26..9e4079e5e35e93eb439022eab46fac1ec4b4504d 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/fundamentals.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/fundamentals.jd @@ -309,7 +309,7 @@ href="{@docRoot}guide/topics/manifest/provider-element.html"><provider>

      系統看不到您納入來源但未在宣示說明中宣告的 Activity、服務和內容供應程式,因此系統無法執行這些項目。 -不過,您可在宣示說明宣告廣播接收器,或是透過程式碼以動態方式建立廣播接收器 (將廣播接收器建立為 +不過,您可在宣示說明宣告廣播接收器,或是透過程式碼以動態方式建立廣播接收器 (將廣播接收器建立為 {@link android.content.BroadcastReceiver} 物件),然後呼叫 {@link android.content.Context#registerReceiver registerReceiver()} 向系統註冊廣播接收器。 @@ -379,7 +379,7 @@ startActivity()},系統就可能會啟動您的 Activity 讓使用者撰寫及

      例如,假設您的應用程式需要相機且採用 Android 2.1 (API 級別 7) 導入的 API,建議您用下列方式在宣示說明檔案中宣告這些需求: -

      +

       <manifest ... >
      diff --git a/docs/html-intl/intl/zh-tw/guide/components/index.jd b/docs/html-intl/intl/zh-tw/guide/components/index.jd
      index f34c7120e8ad39456e192bb91ca9274d7e605637..a59bcd465cb9be6cdb724ff229019a1ffc1533af 100644
      --- a/docs/html-intl/intl/zh-tw/guide/components/index.jd
      +++ b/docs/html-intl/intl/zh-tw/guide/components/index.jd
      @@ -11,7 +11,7 @@ page.image=images/develop/app_components.png
       
         

      部落格文章

      - +

      使用 DialogFragments

      本文示範如何搭配 v4 支援程式庫 (可針對 Honeycomb 以下版本裝置提供向下相容性支援) 使用 DialogFragments 來顯示簡易的編輯對話方塊,以及透過介面將結果回傳給呼叫「Activity」。

      @@ -21,7 +21,7 @@ page.image=images/develop/app_components.png

      適用於各種裝置的片段

      我們於今日推出的靜態程式庫可列出相同的 Fragments API (以及新的 LoaderManager 和些許其他類別),讓與 Android 1.6 以下版本相容的應用程式能夠使用片段來建立相容於平板電腦的使用者介面。

      - +

      運用多個執行緒來提升效能

      建立回應式應用程式的建議做法是,最小化您的主要 UI 執行緒所執行的工作數。 @@ -32,7 +32,7 @@ page.image=images/develop/app_components.png

      培訓

      - +

      管理 Activity 生命週期

      本課程說明每個「Activity」執行個體都會接收的生命週期重要回呼方法,並且說明如何使用這些方法,讓 Activity 的運作能符合使用者的預期,以及讓 Activity 在不需要系統資源時不耗用這類資源。 diff --git a/docs/html-intl/intl/zh-tw/guide/components/intents-filters.jd b/docs/html-intl/intl/zh-tw/guide/components/intents-filters.jd index d3edac3f817abb1d9b7238254d5006402c53d84c..7e61f5e01ad3fba26d29033beeeb0509fa029030 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/intents-filters.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/intents-filters.jd @@ -76,7 +76,7 @@ android.content.Context#bindService bindService()} 來繫結至另一個元件

    8. 如何傳送廣播:

      廣播是指任何應用程式都可接收的訊息。系統會傳送各種系統事件廣播,例如系統開機或裝置開始充電。 您可以將 {@link android.content.Intent} 傳送至 {@link android.content.Context#sendBroadcast(Intent) sendBroadcast()}、 -{@link android.content.Context#sendOrderedBroadcast(Intent, String) 或{@link +{@link android.content.Context#sendOrderedBroadcast(Intent, String)} 或{@link android.content.Context#sendStickyBroadcast sendStickyBroadcast()},以向其他應用程式傳送廣播。 diff --git a/docs/html-intl/intl/zh-tw/guide/components/loaders.jd b/docs/html-intl/intl/zh-tw/guide/components/loaders.jd index 89bfc80744d9605aae4f8a5e9ff2b21a6fcea079..112993a660854c4b1d82772091f546c734c028ec 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/loaders.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/loaders.jd @@ -21,14 +21,14 @@ parent.link=activities.html

    - +

    重要類別

    1. {@link android.app.LoaderManager}
    2. {@link android.content.Loader}
    3. -
    - + +

    相關範例

    1. LoaderCursor @@ -51,7 +51,7 @@ android.app.Fragment} 。
    2. 因此不需要重新查詢資料。 - +

      載入器 API 摘要

      有多個類別和介面可能與在應用程式中使用載入器有關。 @@ -129,7 +129,7 @@ android.content.ContentProvider} 所備份資料的 {@link android.content.Curso

    3. {@link android.app.LoaderManager.LoaderCallbacks} 的實作。 您可以在這裡建立新的載入器和管理對現有載入器的參照。 -
    4. +
    5. 顯示載入器資料的一種方式,例如 {@link android.widget.SimpleCursorAdapter}。
    6. 使用 {@link android.content.CursorLoader} 時的資料來源,例如 {@link android.content.ContentProvider}。 @@ -140,7 +140,7 @@ android.widget.SimpleCursorAdapter}。
    7. {@link android.app.LoaderManager} 可在 {@link android.app.Activity} 或 {@link android.app.Fragment} 內管理一或多個 {@link android.content.Loader} 執行個體。 每個 Activity 或片段只能有一個 {@link -android.app.LoaderManager}。

      +android.app.LoaderManager}。

      您通常會在 Activity 的 {@link android.app.Activity#onCreate onCreate()} 方法內或在片段的 {@link android.app.Fragment#onActivityCreated onActivityCreated()} 方法內,初始化 {@link android.content.Loader}, @@ -157,13 +157,13 @@ getLoaderManager().initLoader(0, null, this);

      • 可識別載入器的不重複 ID。在本範例中,此 ID 為 0。
      • 可在建構時提供給載入器的選用引數 (在本範例中為null)。 -
      • +
      • {@link android.app.LoaderManager.LoaderCallbacks} 實作, {@link android.app.LoaderManager} 會呼叫此實作來回報載入器事件。在本範例中,本機類別會實作 {@link android.app.LoaderManager.LoaderCallbacks} 執行個體,以將參照傳送給它自己 ({@code this})。 -
      • +

      {@link android.app.LoaderManager#initLoader initLoader()} 呼叫可確保載入器已初始化且處於有效狀態。 可能會有兩種結果:

      @@ -343,7 +343,7 @@ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

      這個方法是在正要重設先前建立的載入器時呼叫,以便使其資料無法使用。 此回呼方法可讓您知道即將要發佈資料,而能先行將其參照移除。  

      -

      此實作會以 null 的值呼叫 +

      此實作會以 null 的值呼叫 {@link android.widget.SimpleCursorAdapter#swapCursor swapCursor()}:

      @@ -366,7 +366,7 @@ public void onLoaderReset(Loader<Cursor> loader) { android.app.Fragment} 的完整實作, 其顯示的 {@link android.widget.ListView} 包含聯絡人內容供應程式的查詢結果。它使用 {@link android.content.CursorLoader} 管理對供應程式的查詢。

      - +

      如本範例所示,針對要存取使用者聯絡人的應用程式,它的宣示說明必須包含 {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS} 權限。

      diff --git a/docs/html-intl/intl/zh-tw/guide/components/processes-and-threads.jd b/docs/html-intl/intl/zh-tw/guide/components/processes-and-threads.jd index 74dbb8ebb3f151dfa70b65a11e0bd869c9058077..56027ceb88a3564afd5d0aec3c48a67ffd456dc1 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/processes-and-threads.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/processes-and-threads.jd @@ -49,7 +49,7 @@ page.tags=生命週期、背景 <receiver>}
      {@code <provider>} — 的宣示說明項目都支援 {@code android:process} 屬性,這項屬性能指定元件應在哪個處理程序執行。 您可以設定此屬性讓每個元件都以自己的處理程序執行,或只讓當中的部分元件共用同一處理程序。 -您也可以設定 +您也可以設定 {@code android:process},讓不同應用程式的元件以相同的處理程序執行,只要這些應用程式分享相同的 Linux 使用者 ID 並以相同的憑證簽署。

      @@ -142,7 +142,7 @@ android.content.Context#startService startService()} 方法啟動的服務的處
    8. 背景處理程序 -

      這種處理程序會保留使用者目前看不見的 Activity (已呼叫 Activity 的 +

      這種處理程序會保留使用者目前看不見的 Activity (已呼叫 Activity 的 {@link android.app.Activity#onStop onStop()} 方法)。這些處理程序會間接影響使用者體驗,且系統能隨時將其終止,藉此回收記憶體以供前景、可見或服務處理程序使用。 @@ -319,7 +319,7 @@ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { 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) { diff --git a/docs/html-intl/intl/zh-tw/guide/components/recents.jd b/docs/html-intl/intl/zh-tw/guide/components/recents.jd index d56c12c0e87bbc8a00d91f4b1a243337a3511e04..5ac0e2625bef2df101f6165ab043579013df791b 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/recents.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/recents.jd @@ -181,7 +181,7 @@ protected void onNewIntent(Intent intent) {

      注意:如果值不是 {@code none} 與 {@code never},則 Activity 必須使用 {@code launchMode="standard"} 定義。 -如果沒有指定此屬性,則會使用 +如果沒有指定此屬性,則會使用 {@code documentLaunchMode="none"}。

      移除工作

      diff --git a/docs/html-intl/intl/zh-tw/guide/components/tasks-and-back-stack.jd b/docs/html-intl/intl/zh-tw/guide/components/tasks-and-back-stack.jd index e23301d641bcf28fa13f02f5bdc077352e599436..e3ce58f7770de6e00cff07095e9c8cbf6880ffd8 100644 --- a/docs/html-intl/intl/zh-tw/guide/components/tasks-and-back-stack.jd +++ b/docs/html-intl/intl/zh-tw/guide/components/tasks-and-back-stack.jd @@ -440,13 +440,13 @@ android.app.Activity#startActivity startActivity()} 的意圖中包含旗標,

      在兩種情況下會用到親和性:

        -
      • 當啟動 Activity 的意圖包含 +
      • 當啟動 Activity 的意圖包含 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} 旗標。

        根據預設,新的 Activity 會啟動至 Activity (名為 {@link android.app.Activity#startActivity startActivity()}) 的工作中。 系統會將它推入至與呼叫端相同的返回堆疊。 -不過,如果傳送至 +不過,如果傳送至 {@link android.app.Activity#startActivity startActivity()} 的意圖包含 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} 旗標,則系統會找尋不同的工作來放置新的 Activity。 這通常是新工作。 @@ -455,7 +455,7 @@ android.app.Activity#startActivity startActivity()} 的意圖中包含旗標,

        如果此旗標導致 Activity 開始新的工作,而使用者按 [首頁] 按鈕離開它,必須要有方法可以讓使用者回來瀏覽這個工作。 -有些實體 (例如,通知管理員) 總是從外部工作開始 Activity,從來不使用自己的工作,因此他們都會將 {@code FLAG_ACTIVITY_NEW_TASK} 放入傳送到 +有些實體 (例如,通知管理員) 總是從外部工作開始 Activity,從來不使用自己的工作,因此他們都會將 {@code FLAG_ACTIVITY_NEW_TASK} 放入傳送到 {@link android.app.Activity#startActivity startActivity()} 的意圖。 如果您的 Activity 可以由外部實體呼叫且可能使用此旗標,記得要提供使用者獨立的方法回到啟動的工作,例如,透過啟動組件圖示 (工作的根 Activity 有一個 {@link android.content.Intent#CATEGORY_LAUNCHER} 意圖篩選器;請參閱下方的開始工作)。 @@ -505,7 +505,7 @@ href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetain href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch

        如果這項屬性在工作的根 Activity 中設為 {@code "true"},則剛描述的預設行為不會發生。 即使過了很長的一段時間,工作仍然會在堆疊保留所有的 Activity。 -換句話說,它與 +換句話說,它與 {@code alwaysRetainTaskState} 相反。即便使用者只離開工作一小段時間,使用者還是會回到工作的起始狀態。
        @@ -526,8 +526,8 @@ href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTask

        開始工作

        -

        您可以給予 Activity 一個意圖篩選器,將 -{@code "android.intent.action.MAIN"} 設定為指定的動作, +

        您可以給予 Activity 一個意圖篩選器,將 +{@code "android.intent.action.MAIN"} 設定為指定的動作, {@code "android.intent.category.LAUNCHER"} 設定為指定的類別,以便將該 Activity 設定為工作的進入點。 例如:

        @@ -547,7 +547,7 @@ href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTask

        第二項功能很重要:使用者必須能夠在離開工作後,使用此 Activity 啟動組件回到此工作。 -由於這個原因,兩個將 Activity 標示為一律啟動工作的啟動模式 {@code "singleTask"} 和 +由於這個原因,兩個將 Activity 標示為一律啟動工作的啟動模式 {@code "singleTask"} 和 {@code "singleInstance"},應只能在 Activity 有 {@link android.content.Intent#ACTION_MAIN} 和 {@link android.content.Intent#CATEGORY_LAUNCHER} 篩選器時才能使用。 diff --git a/docs/html-intl/intl/zh-tw/preview/j8-jack.jd b/docs/html-intl/intl/zh-tw/guide/platform/j8-jack.jd similarity index 100% rename from docs/html-intl/intl/zh-tw/preview/j8-jack.jd rename to docs/html-intl/intl/zh-tw/guide/platform/j8-jack.jd diff --git a/docs/html-intl/intl/zh-tw/guide/topics/manifest/manifest-intro.jd b/docs/html-intl/intl/zh-tw/guide/topics/manifest/manifest-intro.jd index 5e42e37d91fc54598dae72ab85ec940a46f89fc8..77a2b80d49f43f4f5284df3ba2879cdb6dc250ae 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/manifest/manifest-intro.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/manifest/manifest-intro.jd @@ -33,15 +33,15 @@ page.title=應用程式宣示說明

      • 描述應用程式的元件 — 組成應用程式的 Activity、服務、廣播接收器和內容供應程式。 -為實作每個元件的類別命名以及發佈類別的功能 (例如,類別可處理的 {@link android.content.Intent +為實作每個元件的類別命名以及發佈類別的功能 (例如,類別可處理的 {@link android.content.Intent Intent} 訊息)。 這些宣告可讓 Android 系統瞭解元件為何以及可在哪些情況下啟動。
      • -
      • 決定代管應用程式元件的程序。
      • +
      • 決定代管應用程式元件的程序。
      • 宣告應用程式必須擁有哪些權限,才能存取 API 受保護的部分以及與其他應用程式互動。 -
      • +
      • 宣示說明亦可宣告其他項目必須擁有哪些權限,才能與應用程式的元件互動。
      • @@ -66,7 +66,7 @@ Intent} 訊息)。 如要查看任一元素的詳細資訊,只要按一下圖表中的元素名稱、圖表後方按字母順序列出的元素清單,或在他處提及的任何元素名稱。 - +

        @@ -128,7 +128,7 @@ Intent} 訊息)。
         

        下方按字母順序列出可出現在宣示說明檔案中的所有元素。 只有這些才是符合資格的元素,您無法新增自己的元素或屬性。 - +

        @@ -158,7 +158,7 @@ Intent} 訊息)。

        - +

        檔案轉換

        @@ -185,7 +185,7 @@ Intent} 訊息)。

        系統通常不會將位於相同層級的元素排序。例如, <activity>、 -<provider> 和 +<provider><service> 元素能以任何順序排列組合。 ( <activity-alias> 元素是這項規則的例外狀況: @@ -218,7 +218,7 @@ Intent} 訊息)。 - +

        如果您一如往常定義元件類別 ({@link android.app.Activity}、{@link android.app.Service}、 @@ -244,7 +244,7 @@ Intent} 訊息)。 package 屬性指定)。 -下列的指派結果會和上述相同: +下列的指派結果會和上述相同:

        <manifest package="com.example.project" . . . >
        @@ -375,7 +375,7 @@ Android 會找出適當的元件來回應意圖、視需要啟動元件的新執
         <intent-filter> 元素預設值。
         
         
        -如果 
        +如果
         <application> 元素設有一個標籤,但 Activity 與其意圖篩選器並未設定該標籤,系統會將應用程式標籤視為 Activity 和意圖篩選器的標籤。
         
         
        @@ -399,7 +399,7 @@ Android 會找出適當的元件來回應意圖、視需要啟動元件的新執
         

        單一 權限 是指一項限制,可限制某部分程式碼或裝置上資料的存取權。 系統會強制實施這項限制,以保護會遭到誤用而扭曲或損害使用者體驗的重要資料與程式碼。 - +

        @@ -427,12 +427,12 @@ Android 會找出適當的元件來回應意圖、視需要啟動元件的新執 如果授予權限,該應用程式就能夠使用受保護的功能。 如果不授予權限,存取相關功能的嘗試就會失敗,但使用者不會收到任何通知。 - +

        應用程式也能利用權限來保護自己的元件 (Activity、服務、廣播接收器和內容供應程式)。 -它能使用 Android 定義的任何權限 (列於 +它能使用 Android 定義的任何權限 (列於 {@link android.Manifest.permission android.Manifest.permission}) 或其他應用程式宣告的任何權限。 此外,應用程式也能自行定義權限。新的權限是以 @@ -458,13 +458,13 @@ Android 會找出適當的元件來回應意圖、視需要啟動元件的新執

        請注意,在本範例中,不只以 -<permission> 元素宣告 {@code DEBIT_ACCT} 權限,還使用 +<permission> 元素宣告 {@code DEBIT_ACCT} 權限,還使用 <uses-permission> 元素來要求使用此權限。 即使保護是由應用程式本身強制施行,還是必須要求使用該權限,應用程式的其他元件才能啟動受保護的 Activity。 - +

        @@ -474,7 +474,7 @@ Android 會找出適當的元件來回應意圖、視需要啟動元件的新執 不過,還是必須利用 -<uses-permission> 來要求使用。 +<uses-permission> 來要求使用。

        diff --git a/docs/html-intl/intl/zh-tw/guide/topics/providers/calendar-provider.jd b/docs/html-intl/intl/zh-tw/guide/topics/providers/calendar-provider.jd index 42434e4b30e8a393571004d564ca507210e44920..682e82de807116ef9b7538aa339a3f5500b82bd7 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/providers/calendar-provider.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/providers/calendar-provider.jd @@ -42,7 +42,7 @@ page.title=日曆供應程式

      • 使用意圖檢視日曆資料
    - +
  • 同步配接器
  • @@ -86,7 +86,7 @@ page.title=日曆供應程式

    -

    每個內容供應程式都會公開一個公用 URI (包裝為 +

    每個內容供應程式都會公開一個公用 URI (包裝為 {@link android.net.Uri} 物件),可唯一識別其資料集。 控制多個資料集 (多個表格) 的內容供應程式會為每個資料集公開個別的 URI。 供應程式所有 URI 的開頭字串為「content://」。 @@ -113,14 +113,14 @@ page.title=日曆供應程式

    {@link android.provider.CalendarContract.Calendars}

    - + 此表格內含日曆特定的資訊。 此表格中的每一列包含單一日曆的詳細資訊,例如名稱、色彩、同步資訊等等。 {@link android.provider.CalendarContract.Events} - + 此表格內含活動特定的資訊。 此表格中的每一列包含單一活動的資訊 — 例如,活動標題、位置、開始時間、結束時間等等。 @@ -132,7 +132,7 @@ page.title=日曆供應程式 {@link android.provider.CalendarContract.Instances} - + 此表格內含活動每次發生的開始和結束時間。 此表格的每一列代表單一活動發生。 單次活動執行個體和活動的對應為 1:1。 @@ -141,7 +141,7 @@ page.title=日曆供應程式 {@link android.provider.CalendarContract.Attendees} - + 此表格內含活動參與者 (邀請對象) 的資訊。 每一列代表一個活動的單一邀請對象。 其中會指出邀請對象類型,以及邀請對象是否出席該活動的回應。 @@ -149,17 +149,17 @@ page.title=日曆供應程式 {@link android.provider.CalendarContract.Reminders} - + 此表格內含警示/通知資訊。 每一列代表一個活動的單一警示。一個活動可以設定多個提醒。 -每個活動的最大數量提醒指定於 +每個活動的最大數量提醒指定於 {@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS},此項是由擁有指定日曆的同步配接器所設定。 提醒是以分鐘數指定活動發生前的時間,而且有一個方法用於決定通知使用者的方式。 - +

    「日曆供應程式」API 的設計具備彈性且功能強大。提供良好的使用者體驗,以及保護日曆及其資料的完整性,兩者一樣重要。 @@ -178,7 +178,7 @@ page.title=日曆供應程式

  • 同步配接器。同步配接器會將使用者裝置的日曆資料與另一台伺服器或資料來源進行同步。 -在 +在 {@link android.provider.CalendarContract.Calendars} 和 {@link android.provider.CalendarContract.Events} 表格中,會保留某些欄讓同步配接器使用。供應程式和應用程式不應加以修改。 @@ -229,7 +229,7 @@ android.Manifest.permission#READ_CALENDAR} 權限。宣示說明檔案必須包 {@link android.provider.CalendarContract.Calendars#VISIBLE} - + 指出是否選擇要顯示日曆的布林值。值 0 表示與此日曆關聯的活動不應顯示。 值 1 表示與此日曆關聯的活動應顯示。 @@ -240,7 +240,7 @@ android.provider.CalendarContract.Instances} 表格中列的產生。 {@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS} - + 指出日曆是否應同步,並且讓日曆的活動儲存在裝置上的布林值。 值 0 表示不同步此日曆,並且不要在裝置上儲存其活動。 值 1 表示同步此日曆的活動,並且在裝置上儲存其活動。 @@ -268,18 +268,18 @@ public static final String[] EVENT_PROJECTION = new String[] { Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3; - + +

    在範例的下一個部分,您將建構查詢。選項會指定查詢的條件。 @@ -308,49 +308,49 @@ android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} 帳戶不會進行同步

    // Run query
     Cursor cur = null;
     ContentResolver cr = getContentResolver();
    -Uri uri = Calendars.CONTENT_URI;   
    -String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    +Uri uri = Calendars.CONTENT_URI;
    +String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                             + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                             + Calendars.OWNER_ACCOUNT + " = ?))";
     String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
    -        "sampleuser@gmail.com"}; 
    -// Submit the query and get a Cursor object back. 
    +        "sampleuser@gmail.com"};
    +// Submit the query and get a Cursor object back.
     cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

    下一節會使用游標逐步檢視結果集。它會使用範例一開始設定好的常數,傳回每個欄位的值。

    - +
    // Use the cursor to step through the returned records
     while (cur.moveToNext()) {
         long calID = 0;
         String displayName = null;
         String accountName = null;
         String ownerName = null;
    -      
    +
         // Get the field values
         calID = cur.getLong(PROJECTION_ID_INDEX);
         displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
         accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
         ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
    -              
    +
         // Do something with the values...
     
        ...
     }
     
    - +

    修改日曆

    如要執行日曆的更新,您可以提供日曆的 {@link -android.provider.BaseColumns#_ID},可以是 URI 的附加 ID +android.provider.BaseColumns#_ID},可以是 URI 的附加 ID ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 或以第一個選擇項目方式提供。 -選項的開頭應該是 "_id=?",而且第一個 +選項的開頭應該是 "_id=?",而且第一個 selectionArg 應該是日曆的 {@link android.provider.BaseColumns#_ID}。 -您也可以透過將 ID 編碼在 URI 中,以執行更新。此範例會使用 +您也可以透過將 ID 編碼在 URI 中,以執行更新。此範例會使用 ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 方式變更日曆的顯示名稱: @@ -434,7 +434,7 @@ android.provider.CalendarContract.Events} 參照。

    {@link android.provider.CalendarContract.EventsColumns#DURATION} - + 活動的持續期間,以 RFC5545 格式表示。例如,值 "PT1H" 表示活動持續一小時,而值 "P2W" 指出持續 2 週。 @@ -444,24 +444,24 @@ android.provider.CalendarContract.Events} 參照。

    {@link android.provider.CalendarContract.EventsColumns#ALL_DAY} - + 值 1 表示此活動需要整天,如同當地時區所定義。 值 0 表示定期活動,會在一天中的任何時間開始和結束。 - + - - + + {@link android.provider.CalendarContract.EventsColumns#RRULE} - + 活動的週期規則。例如,"FREQ=WEEKLY;COUNT=10;WKST=SU"。 您可以在這裡查看更多範例。 - + - + {@link android.provider.CalendarContract.EventsColumns#RDATE} 活動重複發生的日期。您通常會將 {@link android.provider.CalendarContract.EventsColumns#RDATE} 和 {@link android.provider.CalendarContract.EventsColumns#RRULE} 一起使用,以定義週期性活動的彙總集合。 @@ -470,13 +470,13 @@ android.provider.CalendarContract.Events} 參照。

    如需更多討論,請參閱 RFC5545 規格。 - + {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY} - + 活動要視為忙碌或有空 (可以安排其他活動) 的時間。 - + {@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY} @@ -494,7 +494,7 @@ android.provider.CalendarContract.Events} 參照。

    新增活動

    -

    您的應用程式插入新活動時,我們建議您使用 +

    您的應用程式插入新活動時,我們建議您使用 {@link android.content.Intent#ACTION_INSERT INSERT} 意圖 (如同使用意圖插入活動所述)。不過,如果需要,您也可以直接插入活動。 本節將描述如何執行此動作。

    @@ -514,11 +514,11 @@ java.util.TimeZone#getAvailableIDs()}。 android.content.Intent#ACTION_INSERT INSERT} 意圖 (如同使用意圖插入活動 — 所描述的案例) 插入活動,則不適用此規則,將會提供預設時區。
  • - +
  • 對於非週期性活動,您必須包括 {@link android.provider.CalendarContract.EventsColumns#DTEND}。
  • - - + +
  • 對於週期性活動,您必須包括 {@link android.provider.CalendarContract.EventsColumns#DURATION},以及 {@link android.provider.CalendarContract.EventsColumns#RRULE} 或 {@link @@ -528,7 +528,7 @@ android.provider.CalendarContract.EventsColumns#RRULE} 搭配 {@link android.pro
  • - +

    以下是插入活動的範例。為了簡化,會在 UI 執行緒中執行此示範。 @@ -539,8 +539,8 @@ android.provider.CalendarContract.EventsColumns#RRULE} 搭配 {@link android.pro

     long calID = 3;
    -long startMillis = 0; 
    -long endMillis = 0;     
    +long startMillis = 0;
    +long endMillis = 0;
     Calendar beginTime = Calendar.getInstance();
     beginTime.set(2012, 9, 14, 7, 30);
     startMillis = beginTime.getTimeInMillis();
    @@ -561,7 +561,7 @@ Uri uri = cr.insert(Events.CONTENT_URI, values);
     
     // get the event ID that is the last element in the Uri
     long eventID = Long.parseLong(uri.getLastPathSegment());
    -// 
    +//
     // ... do something with event ID
     //
     //
    @@ -581,11 +581,11 @@ long eventID = Long.parseLong(uri.getLastPathSegment()); android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 或以第一個選擇項目方式提供。 -選項的開頭應該是 "_id=?",而且第一個 +選項的開頭應該是 "_id=?",而且第一個 selectionArg 應該是活動的 _ID。 您也可以使用不含 ID 的選項進行更新。以下是更新活動的範例。 -它使用 +它使用 {@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()} 方式變更活動的標題:

    @@ -598,7 +598,7 @@ ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event -values.put(Events.TITLE, "Kickboxing"); +values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows); @@ -625,19 +625,19 @@ ContentValues values = new ContentValues(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = getContentResolver().delete(deleteUri, null, null); -Log.i(DEBUG_TAG, "Rows deleted: " + rows); +Log.i(DEBUG_TAG, "Rows deleted: " + rows);

    參與者表格

    {@link android.provider.CalendarContract.Attendees} 表格的每一列都代表活動的單一參與者或邀請對象。 -呼叫 +呼叫 {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 會傳回指定 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 活動的參與者清單。 此 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 必須符合特定活動的 {@link android.provider.BaseColumns#_ID}。 -

    +

    下表列出可寫入的欄位。 插入新的參與者時,您必須包括 ATTENDEE_NAME 以外的所有項目。 @@ -718,8 +718,8 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values);

    提醒表格

    {@link android.provider.CalendarContract.Reminders} 表格的每一列都代表活動的單一提醒。 -呼叫 -{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 會傳回指定 +呼叫 +{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 會傳回指定 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 活動的提醒清單。

    @@ -727,7 +727,7 @@ Uri uri = cr.insert(Attendees.CONTENT_URI, values);

    下表列出提醒可寫入的欄位。插入新的提醒時,必須包括所有項目。 請注意,同步配接器會在 {@link android.provider.CalendarContract.Calendars} 表格中指出同步配接器支援的提醒類型。 -如需詳細資料,請參閱 +如需詳細資料,請參閱 {@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS}。

    @@ -779,8 +779,8 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values); 執行個體表格無法寫入,僅供查詢活動的發生。

    -

    下表列出您可以針對執行個體查詢的欄位。請注意,時區是由 -{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} 和 +

    下表列出您可以針對執行個體查詢的欄位。請注意,時區是由 +{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} 和 {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES} 所定義。

    @@ -801,18 +801,18 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values); {@link android.provider.CalendarContract.Instances#END_DAY} - + 執行個體的凱撒曆結束日,與「日曆」的時區相關。 - - + + {@link android.provider.CalendarContract.Instances#END_MINUTE} - + 執行個體的結束分鐘,從「日曆」時區的午夜開始計算。 - + {@link android.provider.CalendarContract.Instances#EVENT_ID} @@ -820,16 +820,16 @@ Uri uri = cr.insert(Reminders.CONTENT_URI, values); {@link android.provider.CalendarContract.Instances#START_DAY} - 執行個體的凱撒曆開始日,與「日曆」的時區相關。 + 執行個體的凱撒曆開始日,與「日曆」的時區相關。 {@link android.provider.CalendarContract.Instances#START_MINUTE} - + 執行個體的開始分鐘,從午夜開始計算,與「日曆」的時區相關。 - + - + @@ -853,7 +853,7 @@ public static final String[] INSTANCE_PROJECTION = new String[] { Instances.BEGIN, // 1 Instances.TITLE // 2 }; - + // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; @@ -868,7 +868,7 @@ long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); - + Cursor cur = null; ContentResolver cr = getContentResolver(); @@ -883,28 +883,28 @@ ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query -cur = cr.query(builder.build(), - INSTANCE_PROJECTION, - selection, - selectionArgs, +cur = cr.query(builder.build(), + INSTANCE_PROJECTION, + selection, + selectionArgs, null); - + while (cur.moveToNext()) { String title = null; long eventID = 0; - long beginVal = 0; - + long beginVal = 0; + // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); - - // Do something with the values. - Log.i(DEBUG_TAG, "Event: " + title); + + // Do something with the values. + Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(beginVal); + calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); - Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); + Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } } @@ -922,9 +922,9 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_VIEW VIEW}

    content://com.android.calendar/time/<ms_since_epoch>

    - 您也可以使用 + 您也可以使用 {@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI} 參照 URI。如需使用此意圖的範例,請參閱使用意圖檢視日曆資料。 - + 開啟日曆到 <ms_since_epoch> 指定的時間。 @@ -935,11 +935,11 @@ while (cur.moveToNext()) {

    content://com.android.calendar/events/<event_id>

    - - 您也可以使用 + + 您也可以使用 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 參照 URI。如需使用此意圖的範例,請參閱使用意圖檢視日曆資料。 - + 檢視 <event_id> 指定的活動。 @@ -952,12 +952,12 @@ while (cur.moveToNext()) { {@link android.content.Intent#ACTION_EDIT EDIT}

    content://com.android.calendar/events/<event_id>

    - - 您也可以使用 + + 您也可以使用 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 參照 URI。如需使用此意圖的範例,請參閱使用意圖編輯活動。 - - + + 編輯 <event_id> 指定的活動。 @@ -972,11 +972,11 @@ while (cur.moveToNext()) {
    {@link android.content.Intent#ACTION_INSERT INSERT}

    content://com.android.calendar/events

    - - 您也可以使用 + + 您也可以使用 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 參照 URI。如需使用此意圖的範例,請參閱使用意圖插入活動。 - + 建立活動。 @@ -996,7 +996,7 @@ while (cur.moveToNext()) { 活動的名稱。 - + {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} 活動開始時間,以紀元元年 1 月 1 日零時起算經過的毫秒數為單位。 @@ -1004,25 +1004,25 @@ CalendarContract.EXTRA_EVENT_BEGIN_TIME} {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} - + 活動結束時間,以紀元元年 1 月 1 日零時起算經過的毫秒數為單位。 {@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY CalendarContract.EXTRA_EVENT_ALL_DAY} - - 指出活動為整天的布林值。值可以是 + + 指出活動為整天的布林值。值可以是 truefalse。 {@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION Events.EVENT_LOCATION} - + 活動的地點。 {@link android.provider.CalendarContract.EventsColumns#DESCRIPTION Events.DESCRIPTION} - + 活動描述。 @@ -1039,16 +1039,16 @@ Events.DESCRIPTION} {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL Events.ACCESS_LEVEL} - + 活動為私人或公開性質。 {@link android.provider.CalendarContract.EventsColumns#AVAILABILITY Events.AVAILABILITY} - + 活動要視為忙碌或有空 (可以安排其他活動) 的時間。 - - + +

    以下各節說明如何使用這些意圖。

    @@ -1059,14 +1059,14 @@ android.Manifest.permission#WRITE_CALENDAR} 權限包括在其SampleSyncAdapter。 diff --git a/docs/html-intl/intl/zh-tw/guide/topics/providers/contacts-provider.jd b/docs/html-intl/intl/zh-tw/guide/topics/providers/contacts-provider.jd index b5f888012eed280ec7edb763c824179e49512d33..2bcc3e62b3d33010b55ad2ed2abc696abde4fe59 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/providers/contacts-provider.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/providers/contacts-provider.jd @@ -614,7 +614,7 @@ Email.CONTENT_ITEM_TYPE} (內含使用者名稱,而不是電子郵件地址)

    如要擷取內含使用者的設定檔的聯絡人列,請呼叫 {@link android.content.ContentResolver#query(Uri,String[], String, String[], String) ContentResolver.query()}。 -將內容 URI 設為 +將內容 URI 設為 {@link android.provider.ContactsContract.Profile#CONTENT_URI},並且不要提供任何選取條件。 您也可以使用此內容 URI 做為擷取原始聯絡人或設定檔資料的基礎 URI。 例如,以下程式碼片段會擷取設定檔資料: @@ -932,7 +932,7 @@ public Loader<Cursor> onCreateLoader(int id, Bundle args) { 您應該儘可能透過建立 {@link android.content.ContentProviderOperation} 物件的{@link java.util.ArrayList},然後呼叫 {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()},以「批次模式」在聯絡人供應程式中進行資料的插入、更新以及刪除。 -因為聯絡人供應程式會在單一交易中執行 +因為聯絡人供應程式會在單一交易中執行 {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 的所有操作,所以您所做的修改不會讓聯絡人存放庫處於不一致的狀態。 @@ -1004,7 +1004,7 @@ public Loader<Cursor> onCreateLoader(int id, Bundle args) { previousResult

    - + {@link android.content.ContentResolver#applyBatch(String, ArrayList) applyBatch()} 中的 {@link android.content.ContentProviderResult} 物件以 0 開始的陣列索引值。套用批次操作時,每次操作結果都會儲存在結果的中繼陣列。 @@ -1758,7 +1758,7 @@ onPerformSync()} 方法完成。
    {@link android.accounts.AccountManager} 會啟動此服以開始驗證程序。 服務的 {@link android.app.Service#onCreate()} 方法會具現化為驗證器物件。 -系統需驗證應用程式同步配接器的使用者帳戶時,會呼叫服務的 +系統需驗證應用程式同步配接器的使用者帳戶時,會呼叫服務的 {@link android.app.Service#onBind(Intent) onBind()} 方法以取得驗證器的 {@link android.os.IBinder}。 這樣可以讓系統以跨處理程序的方式呼叫驗證器的方法。 @@ -2115,7 +2115,7 @@ openAssetFileDescriptor()} 可取得相片檔案的控制代碼。 activityclass 值是 Activity 的完整類別名稱,以此 Activity 接收意圖。 invite_action_label 值是顯示在裝置聯絡人應用程式內 [新增連線] 選單中的文字字串。 - + diff --git a/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-basics.jd b/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-basics.jd index 78314784ba9e13ac8af69ae6e41cb9b986b24839..a00caed1f435095001d4b00ed2fcba168e411e1e 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-basics.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-basics.jd @@ -237,7 +237,7 @@ page.title=內容供應程式基本概念 {@link android.content.ContentResolver#query query()} 方法會呼叫使用者字典供應程式所定義的 {@link android.content.ContentProvider#query ContentProvider.query()} 方法。 -以下是 +以下是 {@link android.content.ContentResolver#query ContentResolver.query()} 呼叫的程式碼:

    @@ -250,7 +250,7 @@ mCursor = getContentResolver().query(
         mSortOrder);                        // The sort order for the returned rows
     

    - 表 2 列出 + 表 2 列出 {@link android.content.ContentResolver#query query(Uri,projection,selection,selectionArgs,sortOrder)} 的引數及相對應的 SQL SELECT 陳述式:

    @@ -284,7 +284,7 @@ query(Uri,projection,selection,selectionArgs,sortOrder)} 的引數及相對應 selectionArgs - (沒有任何相對應的關鍵字/參數。選取引數會取代選取子句中的 + (沒有任何相對應的關鍵字/參數。選取引數會取代選取子句中的 ? 預留位置。) @@ -581,7 +581,7 @@ selectionArgs[0] = mUserInput;

    - 如果沒有任何資料欄符合選取條件,則供應程式會傳回 {@link android.database.Cursor#getCount Cursor.getCount()} 為 0 的 + 如果沒有任何資料欄符合選取條件,則供應程式會傳回 {@link android.database.Cursor#getCount Cursor.getCount()} 為 0 的 {@link android.database.Cursor} 物件 (即沒有任何內容的游標)。

    @@ -595,7 +595,7 @@ selectionArgs[0] = mUserInput;

    - 以下程式碼片段是上一個程式碼片段的延伸。它會建立內含查詢所擷取 {@link android.database.Cursor} 的 + 以下程式碼片段是上一個程式碼片段的延伸。它會建立內含查詢所擷取 {@link android.database.Cursor} 的 {@link android.widget.SimpleCursorAdapter} 物件,並將該物件設定為 {@link android.widget.ListView} 的配接器: @@ -674,7 +674,7 @@ if (mCursor != null) {

    {@link android.database.Cursor} 實作方法包含數個用於從物件擷取不同資料類型的「get」方法。 例如,上方程式碼片段使用了 {@link android.database.Cursor#getString getString()}。 -此外,這種實作方法還包括 +此外,這種實作方法還包括 {@link android.database.Cursor#getType getType()} 方法,可傳回指定資料欄資料類型的值。

    @@ -709,7 +709,7 @@ if (mCursor != null) {

    - 以下的 + 以下的 <uses-permission> 元素會要求使用者字典供應程式的讀取存取權:

    @@ -733,7 +733,7 @@ if (mCursor != null) {

    插入資料

    - 如要在供應程式中插入資料,請呼叫 + 如要在供應程式中插入資料,請呼叫 {@link android.content.ContentResolver#insert ContentResolver.insert()} 方法。 這個方法會在供應程式中插入新的資料列,並傳回該列的內容 URI。 以下程式碼片段示範如何在使用者字典供應程式中插入新的字詞: @@ -785,14 +785,14 @@ content://user_dictionary/words/<id_value>

    - 如要從傳回的 {@link android.net.Uri} 取得 _ID 的值,請呼叫 + 如要從傳回的 {@link android.net.Uri} 取得 _ID 的值,請呼叫 {@link android.content.ContentUris#parseId ContentUris.parseId()}。

    更新資料

    如要更新資料列,請使用內含經過更新的值 (與您在插入資料時所使用的值相同) 以及選取條件 (與您在建立查詢時所使用的選取條件相同) 的 {@link android.content.ContentValues} 物件。 - 您所使用的用戶端方法為 + 您所使用的用戶端方法為 {@link android.content.ContentResolver#update ContentResolver.update()}。您只需針對要更新的資料欄,將相關值加到 {@link android.content.ContentValues} 物件即可。 如果您想清除資料欄的內容,請將值設定為 null。 @@ -901,7 +901,7 @@ Cursor.getType()} 來確認可用的資料類型。 例如,聯絡人供應程式中的 {@link android.provider.ContactsContract.Data} 表格會使用 MIME 類型為每個資料列中儲存的聯絡人資料加上標籤。 -如要取得與內容 URI 相對應的 MIME 類型,請呼叫 +如要取得與內容 URI 相對應的 MIME 類型,請呼叫 {@link android.content.ContentResolver#getType ContentResolver.getType()}。

    @@ -1009,13 +1009,13 @@ ContentResolver.applyBatch()},則系統會傳回一系列結果。

    - 供應程式會使用 + 供應程式會使用 <provider> - 元素的 + 元素的 android:grantUriPermission - 屬性以及 + 屬性以及 <provider> - 元素的 + 元素的 <grant-uri-permission> 子元素在本身的宣示說明中為內容 URI 定義 URI 權限。如要進一步瞭解 URI 權限的運作機制,請參閱安全性和權限指南的「URI 權限」。 @@ -1032,8 +1032,8 @@ ContentResolver.applyBatch()},則系統會傳回一系列結果。

    1. 您的應用程式使用 {@link android.app.Activity#startActivityForResult -startActivityForResult()} 方法,傳送了內含 -{@link android.content.Intent#ACTION_PICK} 動作的意圖以及「聯絡人」MIME 類型 +startActivityForResult()} 方法,傳送了內含 +{@link android.content.Intent#ACTION_PICK} 動作的意圖以及「聯絡人」MIME 類型 {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE}。
    2. @@ -1043,9 +1043,9 @@ startActivityForResult()} 方法,傳送了內含
    3. 在選取 Activity 中,使用者選取了要更新的聯絡人。 -一旦使用者進行這項動作,選取 Activity 便會呼叫 +一旦使用者進行這項動作,選取 Activity 便會呼叫 {@link android.app.Activity#setResult setResult(resultcode, intent)} 來設定要傳回您應用程式的意圖。 -該意圖包含使用者所選聯絡人的內容 URI,以及「額外」的旗標 +該意圖包含使用者所選聯絡人的內容 URI,以及「額外」的旗標 {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}。 這些旗標可將 URI 權限授予您的應用程式,以便其讀取內容 URI 指向的聯絡人資料。選取 Activity 隨後會呼叫 {@link android.app.Activity#finish()} 來傳回您應用程式的控制權。 @@ -1053,7 +1053,7 @@ startActivityForResult()} 方法,傳送了內含
    4. - 您的 Activity 返回前景,而系統呼叫您 Activity 的 + 您的 Activity 返回前景,而系統呼叫您 Activity 的 {@link android.app.Activity#onActivityResult onActivityResult()} 方法。 這個方法可接收聯絡人應用程式中的選取 Activity 所建立的結果意圖。 @@ -1071,7 +1071,7 @@ startActivityForResult()} 方法,傳送了內含

      - 例如,日曆應用程式接受可讓您啟用應用程式插入 UI 的 + 例如,日曆應用程式接受可讓您啟用應用程式插入 UI 的 {@link android.content.Intent#ACTION_INSERT} 意圖。您可以在該意圖中傳入「額外」的資料,供應用程式用於預先填入使用者介面。由於週期性活動的語法較為複雜,因此建議您利用 {@link android.content.Intent#ACTION_INSERT} 啟用日曆應用程式,然後讓使用者透過該應用程式將活動插入日曆供應程式。 @@ -1089,7 +1089,7 @@ Android 平台內建的大多數供應程式都可在 {@link android.provider}

      例如,使用者字典供應程式有一個內含內容 URI 和欄名稱常數的 {@link android.provider.UserDictionary} 合約類別。 -「字詞」表格的內容 URI 是在 +「字詞」表格的內容 URI 是在 {@link android.provider.UserDictionary.Words#CONTENT_URI UserDictionary.Words.CONTENT_URI} 常數中定義。 此外,{@link android.provider.UserDictionary.Words} 類別也包含欄名稱常數,可用於本指南中的程式碼片段範例。 @@ -1106,7 +1106,7 @@ String[] mProjection =

      聯絡人供應程式的另一個合約類別為 {@link android.provider.ContactsContract}。 - 此類別的參考文件附有程式碼片段範例。其中一個 + 此類別的參考文件附有程式碼片段範例。其中一個 {@link android.provider.ContactsContract.Intents.Insert} 子類別為內含意圖常數和意圖資料的合約類別。

      diff --git a/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-creating.jd b/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-creating.jd index 3d46ee4b4c8092c176a3d31893b819034a94c2af..9f1ca3176af163ae515bb0c70951b0fa955f915c 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-creating.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/providers/content-provider-creating.jd @@ -239,7 +239,7 @@ page.title=建立內容供應程式 表格資料一律需包含「主索引鍵」欄,方便供應程式保存每個資料列的數值。 您可以使用這些值將資料列連結至其他表格中的相關資料列 (也就是將這些值當作「外部索引鍵」使用)。 事實上,您也可以使用此資料欄的任何名稱進行連結,但使用 {@link android.provider.BaseColumns#_ID BaseColumns._ID} 是最佳做法,這是因為將供應程式的查詢結果連結至 -{@link android.widget.ListView} 時需要將某個擷取出的資料列命名為 +{@link android.widget.ListView} 時需要將某個擷取出的資料列命名為 _ID。 @@ -288,14 +288,14 @@ MIME 類型欄中的值會決定 BLOB 欄的資料定義, 此外,也請針對 Android 套件名稱採取此建議做法;您可以將供應程式授權定義為內含供應程式的套件名稱的副檔名。 例如,假設您 Android 套件的名稱為 - com.example.<appname>,則請將供應程式的授權定義為 + com.example.<appname>,則請將供應程式的授權定義為 com.example.<appname>.provider

      設計路徑結構

      開發人員通常只要附加指向個別表格的路徑,即可從授權建立內容 URI。 -例如,假設您有「table1」和「table2」這兩個表格,則您可以結合上述範例中的授權來產生內容 URI -com.example.<appname>.provider/table1 和 +例如,假設您有「table1」和「table2」這兩個表格,則您可以結合上述範例中的授權來產生內容 URI +com.example.<appname>.provider/table1com.example.<appname>.provider/table2。 路徑並不侷限於單一區隔,而您也不必為每個路徑層級產生表格。 @@ -350,11 +350,11 @@ MIME 類型欄中的值會決定 BLOB 欄的資料定義, content://com.example.app.provider/table1:名稱為 table1 的表格。

    5. - content://com.example.app.provider/table2/dataset1:名稱為 + content://com.example.app.provider/table2/dataset1:名稱為 dataset1 的表格。
    6. - content://com.example.app.provider/table2/dataset2:名稱為 + content://com.example.app.provider/table2/dataset2:名稱為 dataset2 的表格。
    7. @@ -380,7 +380,7 @@ MIME 類型欄中的值會決定 BLOB 欄的資料定義, content://com.example.app.provider/table2/*
      - 與 dataset1dataset2 表格的內容 URI 相符,但與 table1 或 + 與 dataset1dataset2 表格的內容 URI 相符,但與 table1table3 的內容 URI 不符。
      @@ -393,8 +393,8 @@ MIME 類型欄中的值會決定 BLOB 欄的資料定義,

      以下程式碼片段說明各種方法在 {@link android.content.UriMatcher} 中的運作方式。 - 這個程式碼會以不同方式處理整個表格的 URI 以及單一資料列的 URI;針對表格使用內容 URI 模式 -content://<authority>/<path>,針對單一資料列則使用 + 這個程式碼會以不同方式處理整個表格的 URI 以及單一資料列的 URI;針對表格使用內容 URI 模式 +content://<authority>/<path>,針對單一資料列則使用 content://<authority>/<path>/<id>

      @@ -469,8 +469,8 @@ public class ExampleProvider extends ContentProvider {

      另一個 {@link android.content.ContentUris} 類別可提供使用內容 URI 的 id 部分的簡便方法。 -{@link android.net.Uri} 和 -{@link android.net.Uri.Builder} 類別則可提供剖析現有 +{@link android.net.Uri} 和 +{@link android.net.Uri.Builder} 類別則可提供剖析現有 {@link android.net.Uri} 物件及建置新物件的簡便方法。

      @@ -485,7 +485,7 @@ public class ExampleProvider extends ContentProvider {

      必要方法

      抽象類別 {@link android.content.ContentProvider} 會定義 6 種方法,而您必須將這些方法實作成您所擁有子類別的一部分。 -嘗試存取您內容供應程式的用戶端應用程式會呼叫以下所有方法 +嘗試存取您內容供應程式的用戶端應用程式會呼叫以下所有方法 ({@link android.content.ContentProvider#onCreate() onCreate()} 除外):

      @@ -539,7 +539,7 @@ public class ExampleProvider extends ContentProvider {

    - 請注意,上述方法採用的簽名與同名的 + 請注意,上述方法採用的簽名與同名的 {@link android.content.ContentResolver} 方法相同。

    @@ -641,7 +641,7 @@ Android 可以針對下列例外狀況執行這項動作,藉此協助解決查

    - 例如,如果您採用 SQLite 資料庫,您可以透過 + 例如,如果您採用 SQLite 資料庫,您可以透過 {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} 建立新的 {@link android.database.sqlite.SQLiteOpenHelper} 物件,然後在初次開啟資料庫時建立 SQL 表格。 為了加快這個程序,當您初次呼叫 {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase @@ -651,10 +651,10 @@ SQLiteOpenHelper.onCreate()} 方法。

    - 以下兩個程式碼片段展示了 + 以下兩個程式碼片段展示了 {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()} 與 {@link android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) SQLiteOpenHelper.onCreate()} 之間的互動過程。 -而第一個程式碼片段是用於實作 +而第一個程式碼片段是用於實作 {@link android.content.ContentProvider#onCreate() ContentProvider.onCreate()}:

    @@ -808,7 +808,7 @@ protected static final class MainDatabaseHelper extends SQLiteOpenHelper {
                 <name> 必須是全域唯一值,而 <type> 必須為相對應 URI 模式的專屬值。
     
     建議您使用貴公司的名稱或您應用程式的部分 Android 套件名稱做為 <name>。
    -針對 
    +針對
     <type>,則建議您使用可識別與 URI 相關的表格的字串。
     
             

    @@ -816,8 +816,8 @@ protected static final class MainDatabaseHelper extends SQLiteOpenHelper {

    - 例如,假設供應程式的授權為 -com.example.app.provider,而該授權可提供 + 例如,假設供應程式的授權為 +com.example.app.provider,而該授權可提供 table1 這個表格,則 table1 中多個資料列的 MIME 類型會如下所示:

    @@ -940,7 +940,7 @@ ContentProvider.getStreamTypes()} 會傳回如下所示的陣列:
     為了將權限設為僅適用於您的供應程式,請針對
      
         android:name 屬性使用 Java 式範圍。
    -例如,請將讀取權限命名為 
    +例如,請將讀取權限命名為
     com.example.app.provider.permission.READ_PROVIDER

    @@ -955,7 +955,7 @@ ContentProvider.getStreamTypes()} 會傳回如下所示的陣列:
    這項權限是由 - <provider> 元素的 + <provider> 元素的 android:permission 屬性所指定,可控制整個供應程式的讀取及寫入存取權。 @@ -967,10 +967,10 @@ ContentProvider.getStreamTypes()} 會傳回如下所示的陣列: 整個供應程式的讀取權限及寫入權限。您可以使用 <provider> 元素的 - android:readPermission 和 + android:readPermission 和 android:writePermission 屬性指定這兩項權限。 -這些權限的優先等級比 +這些權限的優先等級比 android:permission 所需的權限來得高。
    @@ -1037,9 +1037,9 @@ Context.revokeUriPermission()}。

    - 如要將臨時存取權委派給某款應用程式,您就必須在意圖中加入 -{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} 或 -{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} 旗標,或是同時加入以上兩者。請使用 + 如要將臨時存取權委派給某款應用程式,您就必須在意圖中加入 +{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} 或 +{@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} 旗標,或是同時加入以上兩者。請使用 {@link android.content.Intent#setFlags(int) setFlags()} 方法設定這些旗標。

    @@ -1187,7 +1187,7 @@ Context.revokeUriPermission()}。

    意圖和資料存取權

    應用程式可透過 {@link android.content.Intent} 以間接方式存取內容供應程式。 - 利用這種存取方式的應用程式不會呼叫 {@link android.content.ContentResolver} 或 + 利用這種存取方式的應用程式不會呼叫 {@link android.content.ContentResolver} 或 {@link android.content.ContentProvider} 的任何方法,而是會傳送可啟動 Activity (此 Activity 通常屬於供應程式本身的應用程式) 的意圖。 目標 Activity 會負責擷取資料並在本身的 UI 中顯示該資料。視意圖中的動作而定,目標 Activity 也可能會提示使用者修改供應程式的資料。 diff --git a/docs/html-intl/intl/zh-tw/guide/topics/providers/document-provider.jd b/docs/html-intl/intl/zh-tw/guide/topics/providers/document-provider.jd index 1dc7c46f43873167e4c2be88a2116d2691d6d685..a6af7586b88476b95256e699d73484e8fbc6d45e 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/providers/document-provider.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/providers/document-provider.jd @@ -213,7 +213,7 @@ Android 4.4 儲存空間存取架構:用戶端

    -

    針對搭載 Android 4.4 以上版本的裝置,您的應用程式還可以呼叫 +

    針對搭載 Android 4.4 以上版本的裝置,您的應用程式還可以呼叫 {@link android.content.Intent#ACTION_OPEN_DOCUMENT} 意圖,以顯示系統所控管的挑選器 UI,方便使用者瀏覽其他應用程式提供的所有檔案。 透過這個單一 UI,使用者可以從任何受支援的應用程式挑選檔案。 @@ -560,7 +560,7 @@ getContentResolver().takePersistableUriPermission(uri, takeFlags);

  • 供應程式的名稱 (也就是供應程式的類別名稱),包括套件名稱。範例:com.example.android.storageprovider.MyCloudProvider
  • -
  • 授權的名稱 (也就是套件的名稱;在此範例中為 +
  • 授權的名稱 (也就是套件的名稱;在此範例中為 com.example.android.storageprovider) 以及內容供應程式的類型 (documents)。範例:{@code com.example.android.storageprovider.documents}。
  • @@ -588,7 +588,7 @@ getContentResolver().takePersistableUriPermission(uri, takeFlags);
    <bool name="atLeastKitKat">true</bool>
    -
  • 內含 +
  • 內含 {@code android.content.action.DOCUMENTS_PROVIDER} 動作的意圖篩選器,讓您的供應程式能夠在系統搜尋供應程式時顯示在挑選器中。
  • @@ -618,7 +618,7 @@ getContentResolver().takePersistableUriPermission(uri, takeFlags);

    支援搭載 Android 4.3 以下版本的裝置

    -

    只有搭載 Android 4.4 以上版本的裝置可使用 +

    只有搭載 Android 4.4 以上版本的裝置可使用 {@link android.content.Intent#ACTION_OPEN_DOCUMENT} 意圖。如果您想讓應用程式支援 {@link android.content.Intent#ACTION_GET_CONTENT} 以便與搭載 Android 4.3 以下版本的裝置相容,請針對搭載 Android 4.4 以上版本的裝置停用宣示說明中的 {@link android.content.Intent#ACTION_GET_CONTENT} 意圖篩選器。 @@ -833,7 +833,7 @@ public Cursor queryDocument(String documentId, String[] projection) throws

    實作 openDocument

    您必須實作 {@link android.provider.DocumentsProvider#openDocument -openDocument()} 來傳回代表特定檔案的 +openDocument()} 來傳回代表特定檔案的 {@link android.os.ParcelFileDescriptor}。其他應用程式可利用傳回的 {@link android.os.ParcelFileDescriptor} 傳輸資料。 使用者選取檔案而且用戶端應用程式呼叫 {@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()} 要求存取該檔案後,系統就會呼叫這個方法。範例: diff --git a/docs/html-intl/intl/zh-tw/guide/topics/resources/accessing-resources.jd b/docs/html-intl/intl/zh-tw/guide/topics/resources/accessing-resources.jd index 3a5a96121d942f5fc6f803327b4ec0bd22de8c0a..d1ac69cde5dbf1e00552c1557f92991070f1f3bd 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/resources/accessing-resources.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/resources/accessing-resources.jd @@ -101,12 +101,12 @@ android.content.res.Resources} (以 {@link android.content.Context#getResources(

    有些裝置設定可以在執行階段期間進行變更 (例如,螢幕方向、鍵盤可用性和語言)。 -進行這類變更時,Android 會重新啟動執行中的 +進行這類變更時,Android 會重新啟動執行中的 {@link android.app.Activity} (呼叫 {@link android.app.Activity#onDestroy()},後面加上 {@link android.app.Activity#onCreate(Bundle) onCreate()})。 重新啟動行為的設計是以符合新裝置設定的替代資源自動重新載入您的應用程式,以協助您的應用程式適應新的設定。 diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/controls.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/controls.jd index 0f27ae4e8803f256d7abf642a8e64d314a5eda9f..1ab66c3f12f3a3c86d8d0ae294cdebd142121967 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/controls.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/controls.jd @@ -69,7 +69,7 @@ parent.link=index.html 圓形按鈕 功用與核取方塊類似,但會限制使用者只能從一組選項中選取一個選項。 - {@link android.widget.RadioGroup RadioGroup} + {@link android.widget.RadioGroup RadioGroup}
    {@link android.widget.RadioButton RadioButton} diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/declaring-layout.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/declaring-layout.jd index 72755715e3a217d13102ab1a1c244bd0fb4fde81..580ee230363a14c16fc0556cf2e7cf9275277a4b 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/declaring-layout.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/declaring-layout.jd @@ -272,7 +272,7 @@ android.view.ViewGroup.LayoutParams} 的巢狀類別。這個子類別包含定 可定義檢視在螢幕中的實際大小 (描繪期間以及版面配置之後)。 這些值可能 (但未必) 會與寬度和高度測量值不同。 -您可以呼叫 +您可以呼叫 {@link android.view.View#getWidth()} 和 {@link android.view.View#getHeight()} 來取得尺寸描繪值。

    @@ -421,7 +421,7 @@ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
  • 含有陣列中所有字串的 {@link android.widget.TextView} 的版面配置
  • 字串陣列
  • -

    接著,針對您的 {@link android.widget.ListView} 呼叫 +

    接著,針對您的 {@link android.widget.ListView} 呼叫 {@link android.widget.ListView#setAdapter setAdapter()}:

     ListView listView = (ListView) findViewById(R.id.listview);
    diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/dialogs.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/dialogs.jd
    index b0ae12ea3a19874410df1a81a5e68faa4b82bd91..6e6db354ee77d323f0304a44010803aaf5e53e07 100644
    --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/dialogs.jd
    +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/dialogs.jd
    @@ -32,7 +32,7 @@ page.tags=alertdialog,dialogfragment
           
  • {@link android.app.DialogFragment}
  • {@link android.app.AlertDialog}
  • - +

    另請參閱

    1. 對話方塊設計指南
    2. @@ -248,7 +248,7 @@ AlertDialog dialog = builder.create();
      中立
      如果使用者不想繼續進行特定動作,但並非要取消動作,請使用這種按鈕。 這種按鈕會顯示在正面和負面按鈕之間。 -範例:[稍後提醒我] 按鈕。
      +範例:[稍後提醒我] 按鈕。

      您可以將以上其中一種按鈕加入 {@link @@ -320,7 +320,7 @@ android.app.AlertDialog.Builder#setAdapter setAdapter()} 指定清單。

      如要加入多重選項 (核取方塊) 或單一選項 (圓形按鈕),請使用 {@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} 或 -{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} 方法。

      @@ -346,7 +346,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // 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 + // Else, if the item is already in the array, remove it mSelectedItems.remove(Integer.valueOf(which)); } } @@ -372,7 +372,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

    雖然傳統清單和包含圓形按鈕的清單都可提供「單選」動作,但如果您想保留使用者的選擇,請使用 {@link -android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()}。也就是說,如果您想讓對話方塊再次開啟時顯示使用者目前所選的選項,請建立包含圓形按鈕的清單。 @@ -470,7 +470,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { public void onClick(DialogInterface dialog, int id) { LoginDialogFragment.this.getDialog().cancel(); } - }); + }); return builder.create(); } @@ -479,7 +479,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

    提示:如果您想自訂對話方塊,請改為將 {@link android.app.Activity} 顯示為對話方塊,而不是使用 {@link android.app.Dialog} API。 方法很簡單,只要建立 Activity 然後在 {@code -<activity>} 宣示說明元素中將其主題設為 +<activity>} 宣示說明元素中將其主題設為 {@link android.R.style#Theme_Holo_Dialog Theme.Holo.Dialog} 即可:

    @@ -505,7 +505,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
     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. */
    @@ -513,10 +513,10 @@ public class NoticeDialogFragment extends DialogFragment {
             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
         @Override
         public void onAttach(Activity activity) {
    @@ -543,7 +543,7 @@ public class NoticeDialogFragment extends DialogFragment {
     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();
    @@ -656,7 +656,7 @@ public class CustomDialogFragment extends DialogFragment {
             // 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. */
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
    @@ -678,7 +678,7 @@ public class CustomDialogFragment extends DialogFragment {
     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");
    diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/menus.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/menus.jd
    index be1fa7f0dfdab6f9e4efb9881d424524a4f5be57..6f7405bc00eff0240635982afef1970810578dce 100644
    --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/menus.jd
    +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/menus.jd
    @@ -83,9 +83,9 @@ parent.link=index.html
     

    請參閱建立選項選單

    - +
    內容選單和內容關聯動作模式
    - +
    內容選單是會在使用者長按某元素時顯示的浮動選單。 它提供的動作會影響所選取內容或內容畫面。 @@ -94,7 +94,7 @@ parent.link=index.html

    請參閱建立內容關聯選單

    - +
    彈出式選單
    彈出式選單顯示的項目清單會以垂直清單的方式,錨定在呼叫該選單的檢視。 它很適合用來提供與特定內容有關的動作溢出,或針對第二部分的命令提供選項。 @@ -135,7 +135,7 @@ parent.link=index.html
    <item>
    建立代表選單中單一項目的 {@link android.view.MenuItem}。此元素可以包含巢狀 <menu> 元素以建立子選單。
    - +
    <group>
    可供 {@code <item>} 元素選用的不可見容器。它可讓您將選單項目分類,以便分享屬性,例如有效狀態與可見度。 如需詳細資訊,請參閱建立選單群組。 @@ -742,8 +742,8 @@ android.widget.PopupMenu#getMenu() PopupMenu.getMenu()} 所傳回的 {@link andr
     <ImageButton
    -    android:layout_width="wrap_content" 
    -    android:layout_height="wrap_content" 
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
         android:src="@drawable/ic_overflow_holo_dark"
         android:contentDescription="@string/descr_overflow_button"
         android:onClick="showPopup" />
    @@ -900,7 +900,7 @@ android.view.MenuItem#setChecked(boolean) setChecked()} 方法在程式碼中變
     

    已選取可勾選項目時,系統會呼叫所選取個別項目的回呼方法 (例如 {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()})。 您必須在這裡設定核取方塊的狀態,原因是核取方塊或選項按鈕並不會自動變更其狀態。 -您可以利用 +您可以利用 {@link android.view.MenuItem#isChecked()} 來查詢項目的目前狀態 (使用者選取它之前的狀態),然後利用 {@link android.view.MenuItem#setChecked(boolean) setChecked()} 來設定勾選狀態。例如:

    @@ -1010,7 +1010,7 @@ addIntentOptions()} 時,它會覆寫第一個引數中所指定選單群組中

    您也能向其他應用程式提供 Activity 的服務,這樣即可在其他應用程式的選單中包含您的應用程式 (與上述的角色顛倒)。

    -

    如要包含在其他應用程式選單中,您必須照常定義意圖篩選器,但務必為意圖篩選器類別納入 +

    如要包含在其他應用程式選單中,您必須照常定義意圖篩選器,但務必為意圖篩選器類別納入 {@link android.content.Intent#CATEGORY_ALTERNATIVE} 和/或 {@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} 值。 例如:

    diff --git a/docs/html-intl/intl/zh-tw/preview/features/multi-window.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/multi-window.jd similarity index 98% rename from docs/html-intl/intl/zh-tw/preview/features/multi-window.jd rename to docs/html-intl/intl/zh-tw/guide/topics/ui/multi-window.jd index 788951c8fb984873a939e5c80da172e913746cd4..86d22fb821071a9f8d50c59886cfd1dd03a8eeec 100644 --- a/docs/html-intl/intl/zh-tw/preview/features/multi-window.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/multi-window.jd @@ -4,8 +4,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form" @jd:body -
    -
    +
    +

    此文件內容

    1. 總覽
    2. @@ -68,8 +68,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form" - +

      圖 1. 在分割畫面模式中並排執行的兩個應用程式。

      @@ -170,7 +170,7 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      android:resizeableActivity

      - 在宣示說明的 <activity> 或 + 在宣示說明的 <activity><application> 節點中,設定此屬性以啟用或停用多視窗顯示:

      diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/notifiers/notifications.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/notifiers/notifications.jd index b8537445cff01b27877887ac5823a84a2c01e9ab..d7bf46997853702b265ba2d0ea2dd1e633177d0c 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/notifiers/notifications.jd @@ -81,7 +81,7 @@ page.title=通知 圖 2.通知匣中的通知。

      -

      注意:除非另外註明,否則本指南參照支援程式庫 4 版中的 +

      注意:除非另外註明,否則本指南參照支援程式庫 4 版中的 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} 類別。類別 {@link android.app.Notification.Builder Notification.Builder} 是在 Android 3.0 (API 級別 11) 新增。 @@ -97,10 +97,10 @@ page.title=通知

      建立通知

      -

      您會為 +

      您會為 {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} 物件中的通知指定 UI 資訊與動作。 -如要建立通知本身,您可以呼叫 -{@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()},其傳回的 +如要建立通知本身,您可以呼叫 +{@link android.support.v4.app.NotificationCompat.Builder#build NotificationCompat.Builder.build()},其傳回的 {@link android.app.Notification} 物件會包含您的規格。如要發出通知,您可以呼叫 {@link android.app.NotificationManager#notify NotificationManager.notify()} 將 {@link android.app.Notification} 物件傳送至系統。

      @@ -149,7 +149,7 @@ page.title=通知 在 {@link android.app.Notification} 內,動作本身是由 {@link android.app.PendingIntent} 完成定義,其中包含的 {@link android.content.Intent} 會啟動您應用程式中的 -{@link android.app.Activity}。如要將 +{@link android.app.Activity}。如要將 {@link android.app.PendingIntent} 與手勢關聯,可呼叫 {@link android.support.v4.app.NotificationCompat.Builder} 的適當方法。例如,如果當使用者按一下通知匣中的通知文字時,您希望啟動 {@link android.app.Activity},可呼叫 @@ -394,7 +394,7 @@ numMessages = 0;

      啟動 Activity 時保留導覽

      當您從通知啟動 {@link android.app.Activity} 時,您必須保留使用者預期的導覽體驗。 -按一下 [返回] 應可將使用者從應用程式的一般工作流程帶回主螢幕,而按一下 +按一下 [返回] 應可將使用者從應用程式的一般工作流程帶回主螢幕,而按一下 [近期記錄] 應會將 {@link android.app.Activity} 顯示為個別的工作。如要保留導覽體驗,請以全新的工作啟動 {@link android.app.Activity}。您該如何設定 @@ -466,7 +466,7 @@ numMessages = 0;

    3. - 此外您還需要新增 Android 4.1 以上版本的支援。為此,請將 + 此外您還需要新增 Android 4.1 以上版本的支援。為此,請將 android:parentActivityName 屬性新增到您要啟動 {@link android.app.Activity} 的 <activity> 元素。 @@ -722,7 +722,7 @@ setProgress(max, progress, false)} 將該列新增至您的通知,然後發出

      當操作完成時,您可以繼續顯示進度列或將其移除。不論是任何一種情況,都務必更新通知文字來指出操作已完成。 - 如要移除進度列,請呼叫 + 如要移除進度列,請呼叫 {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}。例如:

      @@ -933,7 +933,7 @@ Notification notification = new Notification.Builder(context)

      - 如要定義自訂通知版面配置,請從具現化可擴大 XML 配置檔案的 + 如要定義自訂通知版面配置,請從具現化可擴大 XML 配置檔案的 {@link android.widget.RemoteViews} 物件著手。接著,改為呼叫 {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()},而不是呼叫像是 {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()} 的方法。 diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/overview.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/overview.jd index 44d05a82ebc2ea7ba8feaadc97a631f72c5878df..0ac4002cf424aef773a069743b328d9d6aa23817 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/overview.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/overview.jd @@ -39,7 +39,7 @@ XML 提供類似於 HTML 且人類看得懂的版面配置結構。

       <?xml version="1.0" encoding="utf-8"?>
       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      -              android:layout_width="fill_parent" 
      +              android:layout_width="fill_parent"
                     android:layout_height="fill_parent"
                     android:orientation="vertical" >
           <TextView android:id="@+id/text"
      @@ -60,7 +60,7 @@ XML 提供類似於 HTML 且人類看得懂的版面配置結構。

      如需建立 UI 版面配置的完整指南,請參閱 XML 版面配置。 - +

      使用者介面元件

      您不必使用 {@link android.view.View} 與 {@link diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/settings.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/settings.jd index 91ac929e0fa12b8f4ae4bf27b19a9ae70d2209ea..7a7ff9b7973c934866bed821eba3bafa95efbc0b 100644 --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/settings.jd +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/settings.jd @@ -226,7 +226,7 @@ android.preference.ListPreference}。這兩個項目都包含下列三個屬性

      {@code android:key}
      需要這個屬性才能保留資料值的偏好設定。它會指定當系統將此設定值儲存於 {@link android.content.SharedPreferences} 時要使用的唯一索引鍵 (字串)。 - +

      只有在下列情況下不需要此屬性:偏好設定為 {@link android.preference.PreferenceCategory} 或 {@link android.preference.PreferenceScreen},或者偏好設定指定 {@link android.content.Intent} 進行呼叫 (搭配 {@code <intent>} 元素) 或 {@link android.app.Fragment} 進行顯示 (搭配 {@code android:fragment} 屬性)。 @@ -285,7 +285,7 @@ android.preference.PreferenceCategory}。

       <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
      -    <PreferenceCategory 
      +    <PreferenceCategory
               android:title="@string/pref_sms_storage_title"
               android:key="pref_key_storage_settings">
               <CheckBoxPreference
      @@ -293,12 +293,12 @@ android.preference.PreferenceCategory}。
                   android:summary="@string/pref_summary_auto_delete"
                   android:title="@string/pref_title_auto_delete"
                   android:defaultValue="false"... />
      -        <Preference 
      +        <Preference
                   android:key="pref_key_sms_delete_limit"
                   android:dependency="pref_key_auto_delete"
                   android:summary="@string/pref_summary_delete_limit"
                   android:title="@string/pref_title_sms_delete"... />
      -        <Preference 
      +        <Preference
                   android:key="pref_key_mms_delete_limit"
                   android:dependency="pref_key_auto_delete"
                   android:summary="@string/pref_summary_delete_limit"
      @@ -588,11 +588,11 @@ android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} 回呼以
       
       <?xml version="1.0" encoding="utf-8"?>
       <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
               android:title="@string/prefs_category_one"
               android:summary="@string/prefs_summ_category_one" />
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
               android:title="@string/prefs_category_two"
               android:summary="@string/prefs_summ_category_two" >
      @@ -672,15 +672,15 @@ android.preference.Preference <Preference>} 元素會傳送一個 {@link a
       

      例如,下列為使用 Android 3.0及更新版本的偏好設定標頭 XML 檔案 ({@code res/xml/preference_headers.xml}): -

      +

       <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsFragmentOne"
               android:title="@string/prefs_category_one"
               android:summary="@string/prefs_summ_category_one" />
      -    <header 
      +    <header
               android:fragment="com.example.prefs.SettingsFragmentTwo"
               android:title="@string/prefs_category_two"
               android:summary="@string/prefs_summ_category_two" />
      @@ -692,18 +692,18 @@ android.preference.Preference <Preference>} 元素會傳送一個 {@link a
       
       
       <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
      -    <Preference 
      +    <Preference
               android:title="@string/prefs_category_one"
               android:summary="@string/prefs_summ_category_one"  >
      -        <intent 
      +        <intent
                   android:targetPackage="com.example.prefs"
                   android:targetClass="com.example.prefs.SettingsActivity"
                   android:action="com.example.prefs.PREFS_ONE" />
           </Preference>
      -    <Preference 
      +    <Preference
               android:title="@string/prefs_category_two"
               android:summary="@string/prefs_summ_category_two" >
      -        <intent 
      +        <intent
                   android:targetPackage="com.example.prefs"
                   android:targetClass="com.example.prefs.SettingsActivity"
                   android:action="com.example.prefs.PREFS_TWO" />
      @@ -975,11 +975,11 @@ android.preference.DialogPreference} 的建構函式,該偏好設定宣告版
       public class NumberPickerPreference extends DialogPreference {
           public NumberPickerPreference(Context context, AttributeSet attrs) {
               super(context, attrs);
      -        
      +
               setDialogLayoutResource(R.layout.numberpicker_dialog);
               setPositiveButtonText(android.R.string.ok);
               setNegativeButtonText(android.R.string.cancel);
      -        
      +
               setDialogIcon(null);
           }
           ...
      @@ -1194,7 +1194,7 @@ protected void onRestoreInstanceState(Parcelable state) {
           // Cast state to custom BaseSavedState and pass to superclass
           SavedState myState = (SavedState) state;
           super.onRestoreInstanceState(myState.getSuperState());
      -    
      +
           // Set this Preference's widget to reflect the restored state
           mNumberPicker.setValue(myState.value);
       }
      diff --git a/docs/html-intl/intl/zh-tw/guide/topics/ui/ui-events.jd b/docs/html-intl/intl/zh-tw/guide/topics/ui/ui-events.jd
      index 68714e8b2b5918e649d50e443bf7bb48fe4d9900..8e009e0d3bea0a1a24f98fee93515fec4bca0324 100644
      --- a/docs/html-intl/intl/zh-tw/guide/topics/ui/ui-events.jd
      +++ b/docs/html-intl/intl/zh-tw/guide/topics/ui/ui-events.jd
      @@ -187,7 +187,7 @@ android.app.Activity} 能在發送至視窗之前攔截所有輕觸事件。
    4. - 這讓 {@link android.view.ViewGroup} 在發送至子檢視時能監控事件。
    5. {@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) - ViewParent.requestDisallowInterceptTouchEvent(boolean)} - 呼叫這個父檢視以指出不應該使用 {@link + ViewParent.requestDisallowInterceptTouchEvent(boolean)} - 呼叫這個父檢視以指出不應該使用 {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)} 攔截輕觸事件。
    6. @@ -199,11 +199,11 @@ android.view.ViewGroup} 在發送至子檢視時能監控事件。 不過,如果裝置具有輕觸功能,而且使用者透過輕觸方式開始與介面互動,就不需要再將項目反白顯示,或是對特定檢視提供焦點。 因此,這就是名稱為「輕觸模式」的互動模式。 - +

      如果是具備輕觸功能的裝置,使用者輕觸螢幕之後,裝置就會進入輕觸模式。 -從這點以此類推,只有 +從這點以此類推,只有 {@link android.view.View#isFocusableInTouchMode} 為 true 的檢視才可設定焦點,例如文字編輯小工具。 其他可輕觸的檢視,例如按鈕,在輕觸時不會成為焦點;按下時,只會觸發 on-click 接聽器。 @@ -214,7 +214,7 @@ android.view.ViewGroup} 在發送至子檢視時能監控事件。

      -整個系統 (所有視窗和 Activity) 都會保留輕觸模式的狀態。如要查詢目前的狀態,您可以呼叫 +整個系統 (所有視窗和 Activity) 都會保留輕觸模式的狀態。如要查詢目前的狀態,您可以呼叫 {@link android.view.View#isInTouchMode} 以查看裝置目前是否處於輕觸模式。

      @@ -282,7 +282,7 @@ android.view.ViewGroup} 在發送至子檢視時能監控事件。 the framework will take care of measuring, laying out, and drawing the tree as appropriate.
    - +

    Note: 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 diff --git a/docs/html-intl/intl/zh-tw/index.jd b/docs/html-intl/intl/zh-tw/index.jd index a5772ef0fab01d102ab21de4dda4cf36809948ff..022df77b61de18598d4dcecec6a42c5840ca9ef5 100644 --- a/docs/html-intl/intl/zh-tw/index.jd +++ b/docs/html-intl/intl/zh-tw/index.jd @@ -5,49 +5,36 @@ page.customHeadTag= - -

    -
    -
    - -

    Android N Developer Preview

    -

    - Get ready for the next version of Android! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. +

    +
    - -
    diff --git a/docs/html/distribute/users/promote-with-ads.jd b/docs/html/distribute/users/promote-with-ads.jd index 2db4ca30610790946b63d4404f5c9864b147005c..d99f449b31a5469f150f63cd7c4bee144560ebc5 100644 --- a/docs/html/distribute/users/promote-with-ads.jd +++ b/docs/html/distribute/users/promote-with-ads.jd @@ -6,20 +6,27 @@ page.tags="users, ads, adwords"

    Users have a huge amount of choice when it comes to which apps they install and use, so it’s important to actively find new ways to promote your app and drive -ongoing engagement. AdWords is a powerful and effective way to do both.

    +ongoing engagement. AdWords campaigns, which you create in the +
    Google Play Developer Console, +are a powerful and effective way to do both.

    -

    Drive installs

    +

    Drive installs with universal app campaigns

    -

    AdWords promotes your app to interested -users where they spend time on phones and -tablets – with app install ads on Google Search, YouTube, Gmail, and within -apps and across the web on the Google Display Network. AdWords is a powerful -way to scale app promotion across Google networks and find customers that are -most likely to install your app.

    +

    AdWords is a powerful way to scale +app promotion across Google networks and find customers who are most likely to +install your app. AdWords promotes your app to interested users where they spend +time on phones and tablets – with app install ads on Google Play, Google Search, +YouTube, Gmail, and within apps and across the web.

    -

    Get started with AdWords -app install ads.

    +

    By creating a universal app camapign, you can reach all of these +networks. This type of campaign allocates ads, bids, and budgets automatically, +making it easier to improve install volume for your app.

    + +

    To learn more about creating universal ad campaigns, read the article about +creating +an AdWords campaign for your app in the Google Play Developer Console Help +Center.

    @@ -27,18 +34,16 @@ app install ads.

    From Google Play

    - +

    - Promote your app on Google Play when users are searching and browsing - for apps. + Reach users as they search for apps and games on Google Play.

    -

    - From search + From Google Search

    - +

    Connect with users as they search for content and services provided by your app. @@ -49,47 +54,32 @@ app install ads.

    From YouTube

    - +

    Promote your app when users are watching related videos.

    -
    -
    -
    -

    From apps

    - +

    Reach users while they’re engaged with apps and games across the AdMob network.

    -

    From the web

    - +

    Reach users while they’re engaged with websites across the Google Display Network.

    - -
    -

    - From Gmail -

    - -

    - Promote your app while users communicate and get things done in Gmail. -

    -
    @@ -130,77 +120,7 @@ app install ads.

    -

    - Engage with users -

    - -

    - Getting a user to install an app is one thing, but you'll also want them to - open it regularly. AdWords offers app re-engagement tools to help your app - stay in mind with users who’ve already installed it on their phone. AdWords - can remind them of key features and encourage them to try your app again, or - help them complete an activity they didn't know your app could handle. -

    - -
    -
    -
    -

    - From search -

    - -

    - Add deep links to your app, then bring users straight to relevant app - content when they’re searching. -

    -
    - -
    -

    - From apps -

    - -

    - Use remarketing and deep links to bring users to just the right place - in your app to re-engage and convert, from other apps and games they - love. -

    -
    -
    -
    - -

    - Tips -

    - -
      -
    • Track what users do in your app after they’ve clicked an ad, by - installing the AdWords conversion tracking - SDK. -
    • - -
    • Advertise a compelling reason for users to re-engage with your app (such - as a reminder or a special offer). -
    • - -
    • - Add - deep links to your app that’ll take users directly to the parts of your - app that will be most relevant and interesting to them, where they can - easily take action. -
    • - -
    • Re-engage your app users across the display network with remarketing - lists and search with keywords. -
    • - -
    • Use remarketing lists to target high value users so that you can drive - more conversions in your app. -
    • -
    - - +
    9. License from Google -9.1 Subject to terms and conditions of these Terms, Google gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the Service as provided to you by Google. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Service as provided by Google, in the manner permitted by the Terms. +9.1 Subject to terms and conditions of these Terms, Google gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the Service as provided to you by Google. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Service as provided by Google, in the manner permitted by the Terms. 9.2 You may not (and you may not permit anyone else to) copy, modify, create a derivative work of, reverse engineer, decompile or otherwise attempt to extract the source code from the Service or any part thereof, unless this is expressly permitted or required by law, or unless you have been specifically told that you may do so by Google, in writing. @@ -208,7 +208,7 @@ with the Android Backup Service Terms of Service

    -

    Register with Android Backup Service

    @@ -234,7 +234,7 @@ onclick="onRegister(); return false;" >Register with Android Backup Service< ); } } - + function boxFocusChanged(obj, focused) { if (focused) { if(obj.value == DEFAULT_TEXT){ @@ -248,14 +248,14 @@ onclick="onRegister(); return false;" >Register with Android Backup Service< } } } - - + + function onFormInput() { /* verify that the TOS is agreed and a bit version is chosen */ var packagename = $("#pname").val(); if ($("input#agree").is(":checked") && packagename.length - && packagename != DEFAULT_TEXT) { + && packagename != DEFAULT_TEXT) { /* reveal the button */ $("a#registerButton").removeClass('disabled'); } else { diff --git a/docs/html/google/index.jd b/docs/html/google/index.jd index 027ba23a6e5b70d635fd654e072839cc07cece88..9b7ff0b8b48fedd1f242e7ff82ed49c6a3abf5ad 100644 --- a/docs/html/google/index.jd +++ b/docs/html/google/index.jd @@ -53,7 +53,7 @@ footer.hide=1

    Google Play developer tools

    - Scale your publishing, manage your catalog, build revenue using Google Play developer tools. + Scale your publishing, manage your catalog, build revenue using Google Play developer tools.
    diff --git a/docs/html/google/play/billing/billing_admin.jd b/docs/html/google/play/billing/billing_admin.jd index 05f3ad593b9d2cc44ab9e08a684d52c3c24ba0f2..9936489d7d4572f8e2ab8d12a611ffd4e9e797fc 100644 --- a/docs/html/google/play/billing/billing_admin.jd +++ b/docs/html/google/play/billing/billing_admin.jd @@ -51,9 +51,9 @@ apps. You can sell an item using Google Play's in-app billing feature only if th listed on an app's product list. Each app has its own product list; you cannot sell items that appear on another app's product list.

    -

    You can access an app's product list by opening the In-app Products +

    You can access an app's product list by opening the In-app Products page for an app that is listed in your developer account. The link to the -In-app Products page appears only if you have a Google payments merchant +In-app Products page appears only if you have a Google payments merchant account and the app's manifest includes the com.android.vending.BILLING permission. For more information about this permission, see @@ -73,7 +73,7 @@ uploading an unpublished draft version. This functionality is no longer supported; instead, you must publish it to the alpha or beta distribution channel. For more information, see Draft Apps -are No Longer Supported. +are No Longer Supported.

    In addition, an app package can have only one product list. If you create a product list for an app, and you use the -

    You can add items to a product list two ways: you can add items one at a time on the In-app -Products page, or you can add a batch of items by importing the items from a +

    You can add items to a product list two ways: you can add items one at a time on the In-app +Products page, or you can add a batch of items by importing the items from a comma-separated values (CSV) file. Adding items one at a time is useful if your app has only a few in-app items or you are adding only a few items to a product list for testing purposes. The CSV file method is useful if your app has a large @@ -100,14 +100,14 @@ number of in-app items.

    1. Log in to your publisher account.
    2. -
    3. In the All applications panel, click on the - app name, then open the In-app Products page.
    4. +
    5. In the All applications panel, click on the + app name, then open the In-app Products page.
    6. Click Add new product. After you provide the product type and ID for the item you are selling, click Continue.

      Product Type
      -

      The product type can be Managed product or Subscription. You cannot +

      The product type can be "Managed product" or "Subscription." You cannot change an item's product type after you create the item. For more information, see Choosing a Product Type.

      Note: For subscription items, you cannot change the @@ -169,7 +169,7 @@ number of in-app items.

      You can also change prices for other currencies manually, but you can do this only if a currency is used in one of the target countries for your app. You can specify target countries for your app on the - Pricing & Distribution page in the Google Play + Pricing & Distribution page in the Google Play Developer Console.

      @@ -187,235 +187,412 @@ number of in-app items.

      Adding a batch of items to a product list

      -

      To add a batch of items to a product list using a CSV file, you first need to create your CSV -file. The data values that you specify in the CSV file represent the same data values you specify -manually through the In-app Products UI (see Adding items one at a time -to a product list). +

      To add a batch of items to a product list using a CSV file, you first need to +create your CSV file. The data values that you specify in the CSV file represent +the options that you set when adding in-app products to a product list using the +Google Play Developer Console UI. For more information about using this UI, see +Adding items one at a time to a product list. -

      If you are importing and exporting CSV files with in-app products, keep -country-specific pricing in mind. If you use auto-fill, you can provide a -tax-exclusive default price, and tax-inclusive prices will be auto-filled. If you -do not use auto-fill, prices you provide must include tax.

      +

      Note: Batch upload of in-app product lists +containing subscriptions is not supported. Also, when updating existing items in +a batch upload, you cannot include changes to in-app products that are linked to +a pricing template.

      -

      Note: Batch upload of product lists containing -subscriptions is not supported. Also, when updating existing items in a batch -upload, you cannot include changes to in-app products that are linked to a -pricing template.

      - -

      To import the items that are specified in your CSV file, do the following:

      +

      To import the in-app products that are specified in your CSV file, do the +following:

        -
      1. Log in to your publisher account.
      2. -
      3. In the All applications panel, select the app - name, then open the In-app Products page.
      4. -
      5. On the In-app Products List page, click Import/Export - > Import in-app products from CSV file, then select your - CSV file. -

        The CSV file must be on your local computer or on a local disk that is connected to your - computer.

        -
      6. -
      7. Select the Overwrite checkbox if you want to overwrite existing items in - your product list. -

        This option overwrites values of existing items only if the value of the product_id - in the CSV file matches the In-app Product ID for an existing item in the product list. - Overwriting doesn't delete items that are on a product list but not present in the CSV - file.

        +
      8. + Log in to your + publisher account. +
      9. +
      10. In the All applications panel, select the app + name, then open the In-app Products page.
      11. +
      12. +

        On the In-app Products page, click + Import/Export > Import in-app products from CSV + file to open the Import In-app Products dialog.

        +
      13. +
      14. +

        + If you want to overwrite existing in-app products in your product list + during the import process, select the Overwrite existing + products checkbox. +

        +

        + This option overwrites values of existing items only if the value of the + Product ID in the CSV file matches the in-app product ID for + an existing in-app product in the product list. The overwriting process + doesn't delete in-app products that exist in a product list but aren't + included in the CSV file +

        +

        Note: If you choose not to overwrite + existing items, the Product ID given to each item in the CSV + file must be different from any of the Product ID values + assigned to existing in-app products. +

        +
      15. +
      16. + Select Browse files, then choose the CSV file that contains + the items you want to import. The CSV file must be stored locally.
      -

      You can also export an existing product list to a CSV file by clicking Export to CSV - on the In-app Product List page. This is useful if you have manually added items to -a product list and you want to start managing the product list through a CSV file.

      +

      + You can also export an existing product list to a CSV file by clicking + Import/Export > Export in-app products to CSV file + on the In-app Products page. This is useful if you have + used the UI to add in-app products to your app but you want to start managing + the product list through a CSV file instead. +

      Formatting batches of items

      -

      The CSV file uses commas (,) and semicolons (;) to separate data values. -Commas are used to separate primary data values, and semicolons are used to -separate subvalues. For example, the syntax for the CSV file is as follows:

      +

      + The CSV file uses commas (,) and semicolons (;) to + separate data values. Commas are used to separate primary data values, and + semicolons are used to separate subvalues. Each item must appear entirely on a + single line within the CSV file. +

      +

      + When creating a CSV file that represents a list of items, you must specify the + CSV syntax on the first row, followed by the items themselves on subsequent + rows, as shown in the following example: +

      + +
      +Product ID,Published State,Purchase Type,Auto Translate,Locale; Title; Description,Auto Fill Prices,Price,Pricing Template ID
      +basic_sleeping_potion,published,managed_by_android,false,en_US; Basic Sleeping Potion; Puts small creatures to sleep.; es_ES; Poción básica de dormir; Causa las criaturas pequeñas ir a dormir.,false,,4637138456024710495
      +standard_sleeping_potion,published,managed_by_android,false,en_US; Standard Sleeping Potion; Puts all creatures to sleep for 2 minutes.,true, 1990000,
      +invisibility_potion,published,managed_by_android,false,en_US; Invisibility Potion; Invisible to all enemies for 5 minutes.,false, US; 1990000; BR; 6990000; RU; 129000000; IN; 130000000; ID; 27000000000; MX; 37000000;
      +
      -

      "product_id","publish_state","purchase_type","autotranslate -","locale; title; description","autofill","country; -price" +

      + This example contains details for three items, each of which represents an + in-app product:

      +
        +
      • + The first item defines a title and description for the en_US + and es_ES locales. A pricing template defines the item's + price. +
      • +
      • + The second item doesn't use a pricing template. Instead, it specifies a + price for the default country (US). The Google Play Developer Console + uses current exchange rates and locally relevant pricing patterns to + automatically set the prices in all other countries where the app is + distributed. +
      • +
      • + The third item also doesn't use a pricing template. The item's price is + specified manually for each country where the app is distributed. +
      • +
      -

      Descriptions and usage details are provided below.

      +

      + Each row in a CSV file can contain the following values, though at least one + of these values is undefined in each row: +

      -
      product_id
      +
      Product ID
      - This is equivalent to the In-app Product ID setting in the In-app Products UI. If you specify - a product_id that already exists in a product list, and you choose to overwrite - the product list while importing the CSV file, the data for the existing item is overwritten with - the values specified in the CSV file. The overwrite feature does not delete items that are on a - product list but not present in the CSV file. +

      + Setting this value in the CSV file has the same effect as entering a + Product ID when creating a new in-app product. +

      +

      + If you specify a Product ID assigned to an in-app product that already + exists in a product list, and you've checked the Overwrite + existing products checkbox in the Import In-app Products + dialog, the data for the existing in-app product is overwritten with the + values that you specify in the CSV file. +

      -
      publish_state
      +
      Publish State
      - This is equivalent to the Publishing State setting in the In-app Products UI. Can be - published or unpublished. +

      + This value must be set to published + or unpublished. +

      +

      + Setting this value to published has the same effect as + navigating to an item's Managed Product Details page and choosing + Active in the drop-down list next to the in-app product's + title and product ID. Setting the value to unpublished + has the same effect as choosing Inactive in the same + drop-down list. +

      -
      purchase_type
      +
      Purchase Type
      - This is equivalent to the Product Type setting in the In-app Products UI. Can be - managed_by_android, which is equivalent to Managed per user account - in the In-app Products UI, or managed_by_publisher, which is equivalent - to Unmanaged in the In-app Products UI. +

      + This value must be set to managed_by_android because batch + upload of product lists containing subscriptions is not supported. +

      +

      + Setting this value to managed_by_android has the same effect + as selecting Managed product in the Add New + Product dialog when creating an in-app product. +

      -
      autotranslate
      +
      Auto Translate
      - This is equivalent to selecting the Fill fields with auto translation - checkbox in the In-app Products UI. Can be true or false. +

      + This value must be set to false because auto-translation of + in-app product details isn't supported. +

      +

      + If you want to provide translations of an in-app product's title and + description, you need to specify these translations explicitly within the + Locale value. +

      -
      locale
      +
      Locale, Title, and Description
      -

      This is equivalent to the Language setting in the In-app Products UI. You must have an entry - for the default locale. The default locale must be the first entry in the list of - locales, and it must include a title and description. If you want to provide - translated versions of the title and description in addition to the default, - you must use the following syntax rules:

      -
        +

        + If you include only one locale for an item, you must specify your app's + default locale and the item's default title and description: +

        + +
        +app_default_locale; item_default_title; item_default_description;
        +
        + +

        + Setting these values has the same effect as performing the following + sequence of actions: +

        +
        1. -

          If autotranslate is true, you must specify the default locale, - default title, default description, and other locales using the following format:

          -

          "true,"default_locale; default_locale_title; - default_locale_description; locale_2; locale_3, ..."

          + Choosing a default language when you add a new app to your + publisher account.
        2. -

          If autotranslate is false, you must specify the default locale, - default title, and default description as well as the translated titles and descriptions using - the following format:

          -

          "false,"default_locale; default_locale_title; - default_locale_description; locale_2; locale_2_title; - local_2_description; locale_3; locale_3_title; - locale_3_description; ..."

          + Navigating to an in-app product's Managed Product Details page.
        3. -
      -

      See table 1 for a list of the language codes you can use with the locale field.

      -
      -
      title
      -
      - This is equivalent to the Title setting in the In-app Products UI. If the title - contains a semicolon, it must be escaped with a backslash (for example, \;). Also, a backslash - must be escaped with a backslash (for example, \\). -
      -
      description
      -
      - This is equivalent to the Description in the In-app Products UI. If the description - contains a semicolon, it must be escaped with a backslash (for example, \;). Also, a backslash - must be escaped with a backslash (for example, \\). +
    7. + Specifying the in-app product's default title and description. +
    8. +
    +

    + When setting the Locale value, you can use any of the + language codes that appear within the Add Your Own Translations + dialog. You can access this dialog by navigating to an in-app product's + Managed Product Details page and clicking Add + translations or Manage translations. +

    +

    + Note: When specifying the Title and + Description values, use backslashes to escape the semicolon + (\;) and backslash (\\) characters. +

    +

    + If you want to include translated versions of the item's title and + description, you must list the default locale, title, and description, + followed by the locales, titles, and descriptions for each translation. + In the following example, the in-app product uses en_US + (United States English) as the default locale and es_ES + (Spain Spanish) as a translation: +

    +
    +en_US; Invisibility Cloak; Makes you invisible.; es_ES; Capote Invisible; Se vuelven invisible.
    +
    +

    + Note: An app contains a single default language, but each + in-app product maintains its own list of translations. Therefore, although + the first locale in each item's Locale value must be the same + throughout the CSV file, the other locales can differ from one item to + another. +

    +

    + Providing values for multiple translations has the same effect as + performing the following sequence of actions: +

    +
      +
    1. + Navigating to an in-app product's Managed Product Details page. +
    2. +
    3. + Clicking Add translations. +
    4. +
    5. + Selecting the languages for the translations and clicking + Add. +
    6. +
    7. + Choosing one of the languages you added in the previous step. +
    8. +
    9. + Specifying a new title and description, which serve as translations into + the selected language. +
    10. +
    11. + Repeating steps 4 and 5 to add translations into all other non-default + languages. +
    12. +
    -
    autofill
    +
    Auto Fill Prices, Country, and + Price
    -

    This is equivalent to clicking Auto Fill in the In-app Products UI. Can be - true or false. The syntax for specifying the country - and price varies depending on which autofill setting you use:

    +

    + You can set Auto Fill Prices to true or + false. + If an in-app product uses a pricing + template, you should set Auto Fill Prices to + false, and you shouldn't set a value for the + Price. +

    +

    + Note: When you specify an item's price in a CSV file, you + provide a price in micro-units, where 1,000,000 micro-units is + equivalent to 1 unit of real currency. +

    +

    + The following sections describe how the value of + Auto Fill Prices affects the syntax and meaning of the + Country and Price values. +

    +
    Using auto-filled prices
    +

    + If you set Auto Fill Prices to true, you specify + only the item's default price; you don't include a Country + value. Setting Auto Fill Prices to true has the + same effect as performing the following sequence of actions: +

    +
      +
    1. + Navigating to an in-app product's Managed Product Details page. +
    2. +
    3. + Selecting Edit in the Price section. +
    4. +
    5. + Entering a default, tax-exclusive price. Auto-filled prices include tax. +
    6. +
    7. + Clicking the checkbox next to COUNTRY in the Edit Local + Prices dialog that appears. +
    8. +
    9. + Selecting Refresh exchange rates. +
    10. +
    11. + Selecting Apply. +
    12. +
    +

    + For example, under the following conditions: +

      +
    • Your app's default locale is en_US.
    • +
    • An in-app product's default, tax-exclusive price is $1.99.
    • +
    • You want the prices for other countries auto-filled.
    • +
    +

    + ...you'd set the values of Auto Fill Prices and + Price at the end of a row in the CSV file as follows: +

    + +
    +true,1990000,
    +
    + +
    Not using auto-filled prices
    +

    + If you set Auto Fill Prices to false instead, + you specify a series of Country and Price + values for all countries where you distribute your app, including the country corresponding to your app's default locale. + Each Country value is the two-letter uppercase ISO country + code that represents a country where your app is distributed. +

    +

    + Note: You must provide a country code and price for each + country that your app is targeting. To view and edit the list of countries + that your app targets, open your app's Pricing & Distribution + page. +

    +

    + Each Price value represents the cost of the item in + micro-units of the currency used in that country. Setting Auto Fill + Prices to false has the same effect as performing + the following sequence of actions: +

    +
      +
    1. + Navigating to an in-app product's Managed Product Details page. +
    2. +
    3. + Selecting Edit in the Price section. +
    4. -

      If autofill is set to true, you need to specify only the default - price in your home currency, and you must use this syntax:

      -

      "true","default_price_in_home_currency" + Explicitly setting tax-inclusive prices for different countries in the + Edit Local Prices dialog that appears.

    5. -

      If autofill is set to false, you need to specify a country - and a price for each currency, and you must use the following syntax:

      -

      "false", "home_country; default_price_in_home_currency; country_2; - country_2_price; country_3; country_3_price; ..."

      + Selecting Apply.
    6. +
    +

    + For example, if you're offering your app for the following prices (all + taxes included) in other countries: +

    +
      +
    • R$6.99 in Brazil.
    • +
    • 129 ₽ in Russia.
    • +
    • ₹130 in India.
    • +
    • Rp 27,000 in Indonesia.
    • +
    • $37 in Mexico.
    -

    Note: If you use an autofill value of false - and set country prices manually, you must incorporate country-specific - pricing patterns, including tax rates, into the prices you provide.

    -
    -
    country
    -
    - The country for which you are specifying a price. You can only list countries that your - app is targeting. The country codes are two-letter uppercase - ISO country codes (such as "US"), as defined by - ISO 3166-2. +

    + ...you'd set the values of Auto Fill Prices, + Country, and Price at the end of a row in the + CSV file as follows: +

    + +
    +false, BR; 6990000; RU; 129000000; IN; 130000000; ID; 27000000000; MX; 37000000;
    +
    +
    -
    price
    +
    Pricing Template ID
    - This is equivalent to the Price in the In-app Products UI. The price must be specified in - micro-units. To convert a currency value to micro-units, you multiply the real value by - 1,000,000. - For example, if you want to sell an in-app item for $1.99, you specify 1990000 in the - price field. +

    + If an item is linked to a pricing template, you should set Auto Fill + Prices to false, and you shouldn't set a value for the + Price column. If the item isn't linked to a pricing template, + you shouldn't set a value for the Pricing Template ID; instead, + you should set Auto Fill Prices, Country, and + Price based on how you want to set the in-app product's prices. +

    +

    + Setting this value has the same effect as navigating to an in-app product's + Managed Product Details page and linking the product's price to the + pricing template that has the same pricing template ID as the one specified + in the CSV file. This pricing template ID appears underneath a pricing + template's name on the Pricing template page. +

    +

    + If you import a CSV file, and you've checked the Overwrite existing + products checkbox in the Import In-app Products dialog, + you can update the links between in-app products and pricing templates. To + link the product to a specific pricing template, set the Pricing + Template ID value to that pricing template's ID. To unlink an in-app + product from all pricing templates, don't set a value for its Pricing + Template ID. +

    +

    + You can link up to 100 app prices or in-app product prices to a particular + pricing template. Therefore, don't specify the same Pricing Template + ID value in more than 100 rows of a CSV file. +

    -

    Table 1. Language codes you can use -with the locale field.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    LanguageCodeLanguageCode
    Chinesezh_TWItalianit_IT
    Czechcs_CZJapaneseja_JP
    Danishda_DKKoreanko_KR
    Dutchnl_NLNorwegianno_NO
    Englishen_USPolishpl_PL
    Frenchfr_FRPortuguesept_PT
    Finnishfi_FIRussianru_RU
    Germande_DESpanishes_ES
    Hebrewiw_ILSwedishsv_SE
    Hindihi_IN----
    -

    Pricing Templates

    @@ -432,8 +609,12 @@ with the locale field.

    When creating a pricing template, you provide new pricing information that you - can apply to paid apps and in-app products. To add a pricing template, do the - following: + can apply to paid apps and in-app products. You can link the prices of up to + 100 apps and in-app products to a single pricing template. +

    + +

    + To add a pricing template, do the following:

      @@ -442,14 +623,14 @@ with the locale field.

      account. -
    1. In the Settings panel, open the Pricing - template page. +
    2. In the Settings panel, open the Pricing + template page.
    3. - If you are adding your first pricing template, the Add a Pricing - Template banner appears. Select Add template to + If you are adding your first pricing template, the Add a Pricing + Template banner appears. Select Add template to create a new template. The new template's Pricing tab appears.

      @@ -510,8 +691,8 @@ with the locale field.

      account.
    4. -
    5. In the Settings panel, open the Pricing - template page. This page shows the list of pricing templates you have +
    6. In the Settings panel, open the Pricing + template page. This page shows the list of pricing templates you have created for your account.
    7. @@ -571,8 +752,8 @@ with the locale field.

      account. -
    8. In the All applications panel, select the app name, then - open the In-app Products page. +
    9. In the All applications panel, select the app name, then + open the In-app Products page.
    10. Choose the in-app product that you want to link to a pricing template. @@ -591,7 +772,7 @@ with the locale field.

      To link the price of a paid app to a pricing template, you follow a similar - process on the app's Pricing & Distribution page. + process on the app's Pricing & Distribution page.

      @@ -623,7 +804,7 @@ with the locale field.

    11. Select the app that contains the in-app product you want to delete.
    12. -
    13. Open the app's In-app Products page. +
    14. Open the app's In-app Products page.
    15. Choose the in-app product that you want to delete. @@ -697,8 +878,8 @@ with the locale field.

      account.
    16. -
    17. In the Settings panel, open the Pricing - template page, which shows the list of pricing templates you have +
    18. In the Settings panel, open the Pricing + template page, which shows the list of pricing templates you have created for your account.
    19. @@ -712,15 +893,15 @@ with the locale field.

    -

    Choosing a Product Type

    +

    Choosing a Product Type

    An item's product type controls how Google Play manages the purchase of the item. The supported product types include "managed product" and "subscription." Since support for different product types can vary among versions of the In-app Billing API, make sure that you choose a product -type that's valid for the version of the In-app Billing API that your app uses.

    +type that's valid for the version of the In-app Billing API that your app uses.

    For details, refer to the documentation for the In-app Billing API. +href="{@docRoot}google/play/billing/api.html#producttype">In-app Billing API.

    Handling Refunds

    @@ -820,8 +1001,8 @@ app.

    To locate the key for an app, follow these steps:

      -
    1. Open the All applications panel.
    2. -
    3. Click on the app name, then open the Services & APIs +
    4. Open the All applications panel.
    5. +
    6. Click on the app name, then open the Services & APIs page.
    7. Scroll down to the section of the page labeled Your License Key for This Application, as shown in figure 5.
    8. @@ -836,7 +1017,7 @@ for apps that depend on the (former) developer key.

      width="700" alt="">
      Figure 5. You can find the license key for each app on the - Services & APIs page. + Services & APIs page.
      diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd index e666bc67c0afae2c1a60dd59a9a3e5fccfe6f05f..5d6b3a8f2e3ff1b156397676b0d6fe4dc77c4dec 100755 --- a/docs/html/google/play/billing/billing_integrate.jd +++ b/docs/html/google/play/billing/billing_integrate.jd @@ -90,7 +90,7 @@ method calls.

    9. Select Google Play Billing Library.
    10. Click Install packages to complete the download.
    -

    The {@code IInAppBillingService.aidl} file will be installed to {@code <sdk>/extras/google/play_billing/}.

    +

    The {@code IInAppBillingService.aidl} file will be installed to {@code /extras/google/play_billing/}.

    To add the AIDL to your project:

    @@ -116,7 +116,7 @@ method calls.

    OK.
  • Using your operating system file explorer, navigate to - {@code <sdk>/extras/google/play_billing/}, copy the + {@code /extras/google/play_billing/}, copy the {@code IInAppBillingService.aidl} file, and paste it into the {@code com.android.vending.billing} package in your project.
  • diff --git a/docs/html/google/play/billing/billing_overview.jd b/docs/html/google/play/billing/billing_overview.jd index a05cc8d769920288ab77a98b45b44e5769461fa6..7d932b7058adfbbca3b92ffdc84fcd928e577ffe 100644 --- a/docs/html/google/play/billing/billing_overview.jd +++ b/docs/html/google/play/billing/billing_overview.jd @@ -7,19 +7,20 @@ parent.link=index.html

    Quickview

      -
    • Use In-app Billing to sell digital goods, including one-time items and +
    • Use In-app Billing to sell digital products, including one-time products and recurring subscriptions.
    • -
    • Supported for any app published on Google Play. You only need a Google +
    • In-app Billing is supported for any app published on Google Play. You need only a + Google Play Developer Console account and a Google payments merchant account.
    • -
    • Checkout processing is automatically handled by Google Play, with the -same look-and-feel as for app purchases.
    • +
    • Google Play automatically handles checkout processing with the +same look and feel as app purchases.

    In this document

    1. In-app Billing API
    2. In-app Products
        -
      1. Product Types +
      2. Product types
    3. Google Play Developer Console
    4. @@ -27,30 +28,33 @@ same look-and-feel as for app purchases.
    5. Sample App
    6. Migration Considerations
    -

    Related Samples

    +

    Related samples

    1. Sample Application (V3)
    -

    Related Videos

    +

    Related videos

      -
    1. Implementing +
    2. + Implementing Freemium
    -

    This documentation describes the fundamental In-app Billing components and +

    This document describes the fundamental In-app Billing components and features that you need to understand in order to add In-app Billing features into your application.

    -

    Note: Ensure that you comply with applicable laws in the countries where you -distribute apps. For example, in EU countries, laws based on the - -Unfair Commercial Practices Directive prohibit direct exhortations to children to buy advertised -products or to persuade their parents or other adults to buy advertised products for them. -See the - +

    Note: Ensure that you comply with applicable laws in the countries where + you distribute apps. For example, in EU countries, laws based on the + +Unfair Commercial Practices Directive prohibit direct exhortations to children to buy + advertised products or to persuade their parents or other adults to buy advertised products + for them. See the + position of the EU consumer protection authorities for more information on this and other topics.

    @@ -61,75 +65,82 @@ exposed by the Google Play app that is installed on the device. The Google Play app then conveys billing requests and responses between your application and the Google Play server. In practice, your application never directly communicates with the Google Play server. Instead, your application -sends billing requests to the Google Play application over interprocess +sends billing requests to the Google Play app over interprocess communication (IPC) and receives responses from the Google Play app. Your application does not manage any network connections between itself and the Google Play server.

    -

    In-app Billing can be implemented only in applications that you publish +

    You can implement In-app Billing only in applications that you publish through Google Play. To complete in-app purchase requests, the Google Play app must be able to access the Google Play server over the network.

    -

    In-app billing Version 3 is the latest version, and maintains very broad +

    In-app Billing Version 3 is the latest version, and it maintains very broad compatibility across the range of Android devices. In-app Billing Version 3 is -supported on devices running Android 2.2 or higher that have the latest version -of the Google Play store installed (a vast majority of active devices).

    Version 3 features

    +

    In-app Billing Version 3 provides the following features:

      -
    • Requests are sent through a streamlined API that allows you to easily request -product details from Google Play, order in-app products, and quickly restore -items based on users' product ownership
    • -
    • Order information is synchronously propagated to the device on purchase -completion
    • -
    • All purchases are “managed” (that is, Google Play keeps track of the user's -ownership of in-app products). The user cannot own multiple copies of an in-app -item; only one copy can be owned at any point in time
    • -
    • Purchased items can be consumed. When consumed, the item reverts to the -"unowned" state and can be purchased again from Google Play
    • -
    • Provides support for subscriptions
    • +
    • Your app sends requests through a streamlined API that allows users to easily request +product details from Google Play and order in-app products. The API quickly restores +products based on the user's ownership.
    • +
    • The API synchronously propagates order information to the device on purchase +completion.
    • +
    • All purchases are managed (that is, Google Play keeps track of the user's +ownership of in-app products). The user can't own multiple copies of an in-app +product; only one copy can be owned at any point in time.
    • +
    • Purchased products can be consumed. When consumed, the product reverts to the +unowned state and can be purchased again from Google Play.
    • +
    • The API provides support for subscriptions.

    For details about other versions of In-app Billing, see the Version Notes.

    In-app Products

    -

    In-app products are the digital goods that you offer for sale from inside your -application to users. Examples of digital goods includes in-game currency, +

    In-app products are the digital products that you offer for sale to users from inside your +application. Examples of digital products include in-game currency, application feature upgrades that enhance the user experience, and new content for your application.

    You can use In-app Billing to sell only digital content. -You cannot use In-app Billing to sell physical goods, personal services, or -anything that requires physical delivery. Unlike with priced applications, once -the user has purchased an in-app product there is no refund window.

    +You can't use In-app Billing to sell physical products, personal services, or +anything that requires physical delivery. Unlike with priced applications, there is no refund + window after +the user has purchased an in-app product.

    Google Play does not provide any form of content delivery. You are responsible for delivering the digital content that you sell in your -applications. In-app products are always explicitly associated with one and -only one app. That is, one application cannot purchase an in-app product -published for another app, even if they are from the same developer.

    +applications. In-app products are always explicitly associated with + only one app. That is, one application can't purchase an in-app product +that is published for another app, even if they are from the same developer.

    Product types

    In-app Billing supports different product types to give you flexibility in how you monetize your application. In all cases, you define your products using the Google Play Developer Console.

    -

    You can specify these types of products for your In-app Billing application -— managed in-app products and subscriptions. Google Play -handles and tracks ownership for in-app products and subscriptions on your -application on a per user account basis. -Learn more about -the product types supported by In-app Billing Version 3.

    +

    You can specify two product types for your In-app Billing application: + managed in-app products and subscriptions. Google Play +handles and tracks ownership for in-app products and subscriptions for your +application on a per-user basis. +Learn more about +the product types supported by In-app Billing Version 3.

    Google Play Developer Console

    The Developer Console is where you can publish your In-app Billing application and manage the various in-app products that are available for purchase from your application.

    You can create a product list of -digital goods that are associated with your application, including items for -one-time purchase and recurring subscriptions. For each item, you can define -information such as the item’s unique product ID (also called its SKU), product -type, pricing, description, and how Google Play should handle and track -purchases for that product.

    +digital products that are associated with your application, including products for +one-time purchase and recurring subscriptions. You can define +information for each product such as the following:

    +
      +
    • Unique product ID (also called its SKU).
    • +
    • Product type.
    • +
    • Pricing.
    • +
    • Description.
    • +
    • Google Play handling and tracking of purchases for that product.
    • +

    If you sell several of your apps or in-app products at the same price, you can add pricing templates to manage these price points from a centralized location. When using pricing templates, you can include local taxes @@ -146,7 +157,7 @@ products and product list, see In-app Billing.

    Google Play Purchase Flow

    -

    Google Play uses the same checkout backend service as is used for application +

    Google Play uses the same backend checkout service that is used for application purchases, so your users experience a consistent and familiar purchase flow.

    Important: You must have a Google payments merchant account to use the In-app Billing service on Google Play.

    @@ -157,8 +168,8 @@ processing the financial transaction.

    When the checkout process is complete, Google Play sends your application the purchase details, such as the order number, the order date and time, and the price paid. At no point does your -application have to handle any financial transactions; that role is provided by -Google Play.

    +application have to handle any financial transactions; that role belongs to + Google Play.

    Sample Application

    To help you integrate In-app Billing into your application, the Android SDK @@ -166,16 +177,16 @@ provides a sample application that demonstrates how to sell in-app products and from inside an app.

    The -TrivialDrive sample for the Version 3 API sample shows how to use the In-app +TrivialDrive for the Version 3 API sample shows how to use the In-app Billing Version 3 API to implement in-app product and subscription purchases for a driving game. The -application demonstrates how to send In-app Billing requests, and handle +application demonstrates how to send In-app Billing requests and handle synchronous responses from Google Play. The application also shows how to record -item consumption with the API. The Version 3 sample includes convenience classes +product consumption with the API. The Version 3 sample includes convenience classes for processing In-app Billing operations as well as perform automatic signature verification.

    -

    Recommendation: Make sure to obfuscate the +

    Recommendation: Be sure to obfuscate the code in your application before you publish it. For more information, see Security and Design.

    @@ -183,16 +194,17 @@ and Design.

    Migration Considerations

    The In-app Billing Version 2 API was discontinued in January 2015. If you have an existing In-app Billing implementation that uses API Version 2 or -earlier, you must migrate to In-app Billing Version -3.

    +earlier, you must migrate to +In-app Billing Version 3.

    -

    If you have published apps selling in-app products, note that:

    +

    After migration, managed and unmanaged products are handled as follows:

      -
    • Managed items and subscriptions that you have previously defined in the Developer Console will -work with Version 3 as before.
    • -
    • Unmanaged items that you have defined for existing applications will be -treated as managed products if you make a purchase request for these items using -the Version 3 API. You do not need to create a new product entry in Developer -Console for these items, and you can use the same product IDs to purchase these -items. +
    • Managed products and subscriptions that you have previously defined in the + Developer Console + work with Version 3 just as before.
    • +
    • Unmanaged products that you have defined for existing applications are + treated as managed products if you make a purchase request for these products using +the Version 3 API. You don't need to create a new product entry in the Developer +Console for these products, and you can use the same product IDs to manage these +products.
    diff --git a/docs/html/google/play/billing/billing_promotions.jd b/docs/html/google/play/billing/billing_promotions.jd index ccf50fc601c30b65b22ff7c13857360f128d25a9..4fe1abfc4aa3b5d9afb6a074ed2be2ad325f247d 100644 --- a/docs/html/google/play/billing/billing_promotions.jd +++ b/docs/html/google/play/billing/billing_promotions.jd @@ -1,7 +1,7 @@ page.title=In-app Promotions parent.title=In-app Billing parent.link=index.html -page.metaDescription=Support promo codes in your app, which let you give content or features away to a limited number of users free of charge. +page.metaDescription=Support promo codes in your app, which lets you give content or features away to a limited number of users free of charge. page.image=/images/play_dev.jpg page.tags="promotions, billing, promo codes" meta.tags="monetization, inappbilling, promotions" @@ -13,7 +13,7 @@ meta.tags="monetization, inappbilling, promotions"

    In this document

    1. Creating and Redeeming Promo Codes
    2. -
    3. Supporting Promo Codes In Your App
    4. +
    5. Supporting Promo Codes in Your App
    6. Testing In-app Promotions

    See also

    @@ -27,26 +27,26 @@ meta.tags="monetization, inappbilling, promotions"

    Promo codes let you give content or features away to a limited number of - users free of charge. Once you create a promo code, you can distribute it + users free of charge. After you create a promo code, you can distribute it subject to the terms of - service. The user enters the promo code in your app or in the Play Store app, - and gets the item at no cost. You can use promo codes in many ways to - creatively engage with users. For example: + service. The user enters the promo code in your app or in the Google Play Store app + and receives the item at no cost. You can use promo codes in many ways to + creatively engage with users, such as the following:

    • A game could have a special item, such as a character or decoration, that's only available to players who attend an event. The developer could distribute cards with promo codes at the event, and users would enter their - promo code to unlock the item. + promo codes to unlock the item.
    • -
    • An app developer might distribute promo codes at local businesses, to +
    • An app developer might distribute promo codes at local businesses to encourage potential users to try the app.
    • -
    • An app developer might give out "friends and family" codes to its employees to +
    • An app developer might give friends and family codes to its employees to share with their friends.
    @@ -54,11 +54,11 @@ meta.tags="monetization, inappbilling, promotions"

    Every promo code is associated with a particular product ID (also known as a SKU). You can create promo codes for your existing in-app - products. You can also keep a SKU off the Play Store, so the only way to get + products. You can also keep an SKU off the Play Store, so that the only way to get that item is by entering that SKU's promo code. When a user enters the promo - code in the Play Store or in their app, the user gets the item, just as if + code in the Play Store or in an app, the user gets the item, just as if they paid full price for it. If your app already uses In-app Billing version 3 to + "{@docRoot}google/play/billing/api.html">In-app Billing Version 3 to support in-app purchases, it's easy to add support for promo codes.

    @@ -67,12 +67,12 @@ meta.tags="monetization, inappbilling, promotions"

    You create promo codes through the Google Play - Developer Console. Each promo code is associated with a single product item + Developer Console. Each promo code is associated with a single product registered in the developer console.

    - When a user gets a promo code, they redeem it in one of two ways: + A user can redeem a promo code in one of these two ways:

      @@ -85,33 +85,20 @@ meta.tags="monetization, inappbilling, promotions"
    • The user can redeem the code in the Google Play Store app. Once the user enters the code, the Play Store prompts the user to open the app (if they have - the latest version installed) or to download or update it. (We do not - currently support redeeming promo codes from the Google Play web store.) + the latest version installed) or to download or update it. Google doesn't + currently support redeeming promo codes from the Google Play web store.
    -

    - If the promo code is for a consumable product, - the user can apply an additional code for the same product after the first - product is consumed. For example, a game might offer promo codes for a bundle - of extra lives. Betty has two different promo codes for that bundle. She - redeems a single promo code, then launches the game. When the game launches, - the her character receives the lives, consuming the item. She can now redeem - the second promo code for another bundle of lives. (She cannot redeem the - second promo code until after she consumes the item she purchased with the - first promo code.) -

    - -

    Supporting Promo Codes In Your App

    +

    Supporting Promo Codes in Your App

    - To support promotion codes, your app should call the getPurchases() method whenever the app starts or resumes. This method returns a bundle of all current, unconsumed purchases, including purchases the user made by redeeming - a promo code. This simplest approach is to call getPurchases() in your activity's {@link android.app.Activity#onResume onResume()} method, @@ -119,21 +106,21 @@ meta.tags="monetization, inappbilling, promotions" activity is unpaused. Calling getPurchases() - on startup and resume guarantees that your app will find out about all + on startup and resume guarantees that your app finds out about all purchases and redemptions the user may have made while the app wasn't running. Furthermore, if a user makes a purchase while the app is running and - your app misses it for any reason, your app will still find out about the + your app misses it for any reason, your app still finds out about the purchase the next time the activity resumes and calls getPurchases().

    - In addition, your app should allow users to redeem promo codes inside the app + Your app should allow users to redeem promo codes inside the app itself. If your app supports the in-app purchase workflow (described in Making - In-app Billing Requests), your app automatically supports in-app + In-app Billing requests), your app automatically supports in-app redemption of promo codes. When you launch the in-app purchase UI, the user has the option to pay for the purchase with a promo code. Your activity's {@link android.app.Activity#onActivityResult @@ -141,9 +128,9 @@ meta.tags="monetization, inappbilling, promotions" purchase was completed. However, your app should still call getPurchases() - on startup and resume, just in case the purchase and consumption workflow - didn't complete. For example, if the user successfully redeems a promo code, - and then your app crashes before the item is consumed, your app still gets + on startup and resume, in case the purchase and consumption workflow + didn't complete. For example, if the user successfully redeems a promo code + and then your app crashes before the item is consumed, your app still receives information about the purchase when the app calls getPurchases() on its next startup. @@ -160,8 +147,8 @@ meta.tags="monetization, inappbilling, promotions"

    To listen for the PURCHASES_UPDATED intent, dynamically create a {@link android.content.BroadcastReceiver} object and register it to listen - for "com.android.vending.billing.PURCHASES_UPDATED". Register - the receiver by putting code like this in your activity's {@link + for com.android.vending.billing.PURCHASES_UPDATED. Register + the receiver by inserting code similar to the following in your activity's {@link android.app.Activity#onResume onResume()} method:

    @@ -172,36 +159,34 @@ registerReceiver(myPromoReceiver, promoFilter);

    When the user makes a purchase, the system invokes your broadcast receiver's {@link android.content.BroadcastReceiver#onReceive onReceive()} method. That - method should call getPurchases() to see what purchases the user has made.

    -

    - Your activity's {@link android.app.Activity#onPause onPause()} method should - unregister the broadcast receiver, to reduce system overhead when your app - isn't running: +

    To reduce system overhead when your app + isn't running, your activity's {@link android.app.Activity#onPause onPause()} method must + unregister the broadcast receiver:

    unRegisterReceiver(myPromoReceiver);

    - Note: You should not register this broadcast receiver in the + Note: Don't register this broadcast receiver in the app manifest. Declaring the receiver in the manifest can cause the system to launch the app to handle the intent if the user makes a purchase while the app - isn't running. This behavior is not necessary, and may be annoying to the - user. Instead, your app should call getPurchases() - when the user launches it, to find out about any purchases the user made - while the app wasn't running. + isn't running. This behavior is not necessary and may be annoying to the + user. + To find out about any purchases the user made while the app wasn't running, + call getPurchases() when the user launches the app.

    Testing In-app Promotions

    - If your app supports in-app promotions, you should test the following use + If your app supports in-app promotions, test the following use cases.

    @@ -211,18 +196,18 @@ registerReceiver(myPromoReceiver, promoFilter); If the user redeems a promo code within the app's purchase flow, as described in Making - In-app Billing Requests, the system invokes your activity's {@link + In-app Billing requests, the system invokes your activity's {@link android.app.Activity#onActivityResult onActivityResult()} method to handle the purchase. Verify that {@link android.app.Activity#onActivityResult - onActivityResult()} handles the purchase properly, whether the user uses cash + onActivityResult()} handles the purchase properly, whether the user pays with money or a promo code.

    -

    User redeems promo code in the Play Store

    +

    User redeems promo code in the Google Play Store

    If the user redeems a promo code in the Play Store, there are several - possible workflows. You should verify each one of these. + possible workflows. Verify each one of these workflows.

    App is not installed

    @@ -231,16 +216,16 @@ registerReceiver(myPromoReceiver, promoFilter); If the user redeems a promo code for an app that is not installed on the device, the Play Store prompts the user to install the app. (If the app is installed but not up-to-date, the Play Store prompts the user to update the - app.) You should test the following sequence on a device that does not + app.) Test the following sequence on a device that doesn't have your app installed.

      -
    1. User redeems a promo code for the app in the Play Store. The Play Store +
    2. The user redeems a promo code for the app in the Play Store. The Play Store prompts the user to install your app.
    3. -
    4. User installs and launches your app. Verify that on startup, the app +
    5. The user installs and launches your app. Verify that on startup, the app calls getPurchases() @@ -252,16 +237,16 @@ registerReceiver(myPromoReceiver, promoFilter);

      If the user redeems a promo code for an app that is installed on the device, - the Play Store prompts the user to switch to the app. You should test the + the Play Store prompts the user to switch to the app. Test the following sequence on a device that has your app installed but not running:

        -
      1. User redeems a promo code for the app in the Play Store. The Play Store +
      2. The user redeems a promo code for the app in the Play Store. The Play Store prompts the user to switch to your app.
      3. -
      4. User launches your app. Verify that on startup, the app calls The user launches your app. Verify that on startup the app calls getPurchases() and correctly detects the purchase the user made with the promo code. @@ -274,15 +259,15 @@ registerReceiver(myPromoReceiver, promoFilter);

        If the user redeems a promo code for an app that is currently running on the device, the Play Store notifies the app via a PURCHASES_UPDATED - intent. You should test the following sequence: + intent. Test the following sequence:

          -
        1. User launches the app. Verify that the app has properly registered itself to +
        2. The user launches the app. Verify that the app has properly registered itself to receive the PURCHASES_UPDATED intent.
        3. -
        4. User launches the Play Store app and redeems a promo code for the app. The Play +
        5. The user launches the Play Store app and redeems a promo code for the app. The Play Store fires a PURCHASES_UPDATED intent. Verify that your app's {@link android.content.BroadcastReceiver#onReceive BroadcastReceiver.onReceive()} callback fires to handle the intent. @@ -291,11 +276,11 @@ registerReceiver(myPromoReceiver, promoFilter);
        6. Your {@link android.content.BroadcastReceiver#onReceive onReceive()} method should respond to the intent by calling getPurchases(). Verify that it calls this method, and that + >getPurchases(). Verify that your app calls this method and that it correctly detects the purchase the user made with the promo code.
        7. -
        8. User switches back to your app. Verify that the user has the purchased +
        9. The user switches back to your app. Verify that the user has the purchased item.
        diff --git a/docs/html/google/play/billing/billing_testing.jd b/docs/html/google/play/billing/billing_testing.jd index 755f3ffd62208101e9dcc41fc47a8f04d1c66496..44b7ad3081cf1f02400e7fc37eb53fc8dc4a32af 100644 --- a/docs/html/google/play/billing/billing_testing.jd +++ b/docs/html/google/play/billing/billing_testing.jd @@ -81,8 +81,8 @@ accounts.

        Once authorized for testing access, those users can make purchases without - being charged. The orderId field for test purchases remains - blank, ensuring that there are no actual charges to user accounts. + being charged. Test purchases don't have an orderId field, which + ensures that there are no actual charges to user accounts.

        @@ -127,11 +127,11 @@ account. Users can confirm the account that is making a purchase by expanding th purchase dialog.

        - Note: For test purchases, leave the {@code orderId} field - blank. You can use the {@code purchaseToken} field to identify test purchases. + Note: Test purchases don't have an orderId + field. To track test purchases, you use the purchaseToken field + instead.

        -

        Test purchases and developer account

        Authorized license test accounts are associated with your developer account in Google Play, rather than with a specific APK or package name. Identifying an diff --git a/docs/html/google/play/expansion-files.jd b/docs/html/google/play/expansion-files.jd index 3c01684ade50aa403ae943dbefe7f814027dd0d8..cb8f2775eb0828040d35723eb75f031437b5e66c 100755 --- a/docs/html/google/play/expansion-files.jd +++ b/docs/html/google/play/expansion-files.jd @@ -131,7 +131,7 @@ considers them opaque binary blobs and renames the files using the following sch

        {@code main} or {@code patch}
        Specifies whether the file is the main or patch expansion file. There can be only one main file and one patch file for each APK.
        -
        {@code <expansion-version>}
        +
        {@code }
        This is an integer that matches the version code of the APK with which the expansion is first associated (it matches the application's {@code android:versionCode} @@ -139,7 +139,7 @@ value).

        "First" is emphasized because although the Developer Console allows you to re-use an uploaded expansion file with a new APK, the expansion file's name does not change—it retains the version applied to it when you first uploaded the file.

        -
        {@code <package-name>}
        +
        {@code }
        Your application's Java-style package name.
        @@ -162,9 +162,9 @@ itself, you must save the files to the exact same location.

          -
        • {@code <shared-storage>} is the path to the shared storage space, available from +
        • {@code } is the path to the shared storage space, available from {@link android.os.Environment#getExternalStorageDirectory()}.
        • -
        • {@code <package-name>} is your application's Java-style package name, available +
        • {@code } is your application's Java-style package name, available from {@link android.content.Context#getPackageName()}.
        @@ -470,7 +470,7 @@ and "Google Play Downloader Library", choose Minimum SDK level, then se Finish.
      5. Select File > Project Structure.
      6. Select the Properties tab and in Library -Repository, enter the library from the {@code <sdk>/extras/google/} directory +Repository, enter the library from the {@code /extras/google/} directory ({@code play_licensing/} for the License Verification Library or {@code play_apk_expansion/downloader_library/} for the Downloader Library).
      7. Select OK to create the new module.
      8. @@ -716,7 +716,7 @@ application's {@code SampleDownloaderActivity} class for details.)

      9. Start the download by calling the static method {@code DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent -notificationClient, Class<?> serviceClass)}. +notificationClient, Class serviceClass)}.

        The method takes the following parameters:

        • context: Your application's {@link android.content.Context}.
        • @@ -780,7 +780,7 @@ public void onCreate(Bundle savedInstanceState) {
        • When the {@code startDownloadServiceIfRequired()} method returns anything other than {@code NO_DOWNLOAD_REQUIRED}, create an instance of {@code IStub} by -calling {@code DownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class<?> +calling {@code DownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class downloaderService)}. The {@code IStub} provides a binding between your activity to the downloader service such that your activity receives callbacks about the download progress.

          In order to instantiate your {@code IStub} by calling {@code CreateStub()}, you must pass it @@ -956,7 +956,7 @@ which explains how to implement a license policy such as this one.

          depends on the type of file you've used. As discussed in the overview, your expansion files can be any kind of file you want, but are renamed using a particular file name format and are saved to -{@code <shared-storage>/Android/obb/<package-name>/}.

          +{@code /Android/obb//}.

          Regardless of how you read your files, you should always first check that the external storage is available for reading. There's a chance that the user has the storage mounted to a @@ -1059,7 +1059,7 @@ option to specify the file suffixes that should not be compressed:

          The Google Market Apk Expansion package includes a library called the APK Expansion Zip Library (located in {@code -<sdk>/extras/google/google_market_apk_expansion/zip_file/}). This is an optional library that +/extras/google/google_market_apk_expansion/zip_file/}). This is an optional library that helps you read your expansion files when they're saved as ZIP files. Using this library allows you to easily read resources from your ZIP expansion files as a virtual file system.

          diff --git a/docs/html/google/play/filters.jd b/docs/html/google/play/filters.jd index 50cc8079264193986c6bcde5bfcc0c5adbee7d0f..a73b17f17fe285b6b624836192a5a09f18c0057e 100644 --- a/docs/html/google/play/filters.jd +++ b/docs/html/google/play/filters.jd @@ -382,9 +382,12 @@ characteristics that affect filtering on Google Play.

          suspended, users will not be able to reinstall or update it, even if it appears in their Downloads.

          Priced - Status

          Not all users can see paid apps. To show paid apps, a device -must have a SIM card and be running Android 1.1 or later, and it must be in a -country (as determined by SIM carrier) in which paid apps are available.

          + Status

          Not all users can see paid apps. To show + paid apps, a device must be running Android 1.1 or later, and it must be in + a country where paid apps are available. If a device has a SIM card, the SIM + carrier determines whether paid apps are available. If a device doesn't have + a SIM card, the device's IP address is used to determine whether the device + is in a country where paid apps are available.

          Country Targeting

          When you upload your app to Google Play, you can select the countries in which to distribute your app diff --git a/docs/html/google/play/licensing/adding-licensing.jd b/docs/html/google/play/licensing/adding-licensing.jd index 3bf4c1a6133306e719abf9bcf311e96cbd1d3038..bfd4f91d83a1c36c27c3899fe3cc5820c53e5bb3 100644 --- a/docs/html/google/play/licensing/adding-licensing.jd +++ b/docs/html/google/play/licensing/adding-licensing.jd @@ -7,7 +7,7 @@ parent.link=index.html

          - +

          In this document

          1. Adding the Licensing Permission
          2. @@ -42,7 +42,7 @@ to close IPC connections
          3. Publishing a Licensed Application
          4. Where to Get Support
          - +
          @@ -572,7 +572,7 @@ the dontAllow() method on {@code LicenseCheckerCallback}.
        • In case of a recoverable local or server error, such as when the network is not available to send the request, {@code LicenseChecker} passes a {@code RETRY} response to -your {@code Policy} object's processServerResponse() method. +your {@code Policy} object's processServerResponse() method.

          Also, both the {@code allow()} and {@code dontAllow()} callback methods receive a reason argument. The {@code allow()} method's reason is usually {@code Policy.LICENSED} or {@code Policy.RETRY} and the {@code dontAllow()} reason is usually {@code @@ -672,7 +672,7 @@ private class MyLicenseCheckerCallback implements LicenseCheckerCallback { return; } displayResult(getString(R.string.dont_allow)); - + if (reason == Policy.RETRY) { // If the reason received from the policy is RETRY, it was probably // due to a loss of connection with the service, so we should give the @@ -854,9 +854,9 @@ sample application calls checkAccess() from a

          Embed your public key for licensing

          For each application, the Google Play service automatically -generates a 2048-bit RSA public/private key pair that is used for -licensing and in-app billing. The key pair is uniquely associated with the -application. Although associated with the application, the key pair is +generates a 2048-bit RSA public/private key pair that is used for +licensing and in-app billing. The key pair is uniquely associated with the +application. Although associated with the application, the key pair is not the same as the key that you use to sign your applications (or derived from it).

          The Google Play Developer Console exposes the public key for licensing to any @@ -876,11 +876,11 @@ your application's public key for licensing:

          href="http://play.google.com/apps/publish">Developer Console and sign in. Make sure that you sign in to the account from which the application you are licensing is published (or will be published).
        • -
        • In the application details page, locate the Services & APIs +
        • In the application details page, locate the Services & APIs link and click it.
        • -
        • In the Services & APIs page, locate the -Licensing & In-App Billing section. Your public key for -licensing is given in the +
        • In the Services & APIs page, locate the +Licensing & In-App Billing section. Your public key for +licensing is given in the Your License Key For This Application field.
      diff --git a/docs/html/google/play/licensing/licensing-reference.jd b/docs/html/google/play/licensing/licensing-reference.jd index d4ca79a77cb8dd507d9aa3d1ad10edc8f11b82ec..2b16299448c97857a0184d7999da3dbb50f02ddc 100644 --- a/docs/html/google/play/licensing/licensing-reference.jd +++ b/docs/html/google/play/licensing/licensing-reference.jd @@ -7,7 +7,7 @@ parent.link=index.html
      - +

      In this document

      1. LVL Classes and Interfaces
      2. @@ -418,7 +418,7 @@ responses in the allow() method. The count of {@code RETRY} respons maintained in the processServerResponse() method, not shown.

        -
            
        +
         public boolean allowAccess() {
             long ts = System.currentTimeMillis();
             if (mLastResponse == LicenseResponse.LICENSED) {
        diff --git a/docs/html/google/play/licensing/overview.jd b/docs/html/google/play/licensing/overview.jd
        index ecb384dc74ed3804199b5509a713d5ff1e0c6458..8d7977e1cb009d8ab6e73db8030ea72e9bd0329e 100755
        --- a/docs/html/google/play/licensing/overview.jd
        +++ b/docs/html/google/play/licensing/overview.jd
        @@ -6,14 +6,14 @@ parent.link=index.html
         
         
        - +

        Quickview

        • Licensing allows you to verify your app was purchased from Google Play
        • Your app maintains control of how it enforces its licensing status
        • The service is free for all developers who publish on Google Play
        - +

        In this document

        1. License Responses are Secure
        2. @@ -21,7 +21,7 @@ parent.link=index.html
        3. Requirements and Limitations
        4. Replacement for Copy Protection
        - +
        @@ -107,10 +107,10 @@ response data using an RSA key pair that is shared exclusively between the Googl server and you.

        The licensing service generates a single licensing key pair for each -application and exposes the public key in your application's -Services & APIs page in the Developer Console. You must copy -the public key from the Developer Console and embed it in your application -source code. The server retains the private key internally and uses it to sign +application and exposes the public key in your application's +Services & APIs page in the Developer Console. You must copy +the public key from the Developer Console and embed it in your application +source code. The server retains the private key internally and uses it to sign license responses for the applications you publish with that account.

        When your application receives a signed response, it uses the embedded public @@ -209,7 +209,7 @@ practices in the following documents, you can help ensure that your implementati secure.

      3. Adding licensing to an application does not affect the way the application functions when run on a device that does not offer Google Play.
      4. -
      5. You can implement licensing controls for a free app, but only if you're using the service to +
      6. You can implement licensing controls for a free app, but only if you're using the service to provide APK expansion files.
      7. diff --git a/docs/html/google/play/licensing/setting-up.jd b/docs/html/google/play/licensing/setting-up.jd index 352b79b304a4d31184a6de5d9575fe8a88b59c99..11ca4d7d3722d1ede67097897a9f57fed09c6128 100755 --- a/docs/html/google/play/licensing/setting-up.jd +++ b/docs/html/google/play/licensing/setting-up.jd @@ -181,12 +181,12 @@ these steps:

        1. Launch the Android SDK Manager, available under the Android Studio Tools menu (Tools > Android > SDK Manager) or by executing -{@code <sdk>/tools/android sdk}.
        2. +{@code /tools/android sdk}.
        3. Select and download Google APIs for the Android version you'd like to target (must be Android 2.2 or higher).
        4. When the download is complete, open the AVD Manager, available under the Android Studio Tools menu (Tools > Android > AVD Manager) or by executing -{@code <sdk>/tools/android avd}.
        5. +{@code /tools/android avd}.
        6. In the Android Virtual Device Manager window, select + Create Virtual Device to set the configuration details for the new AVD.
        7. In the Virtual Device Configuration window, select device hardware, then @@ -317,7 +317,7 @@ project as a new module.

          File > New > Import Module.
        8. In the New Module window, in Source directory, enter the LVL's library directory (the directory containing the library's AndroidManifest.xml file) -as the project root ({@code <sdk>/extras/google/play_licensing/library/AndroidManifest.xml}), +as the project root ({@code /extras/google/play_licensing/library/AndroidManifest.xml}), then select Next.
        9. Select Finish to import the library module.
        diff --git a/docs/html/google/play/publishing/multiple-apks.jd b/docs/html/google/play/publishing/multiple-apks.jd index fd4481dc076a3e4c7fd9dd74ef681832be7ebeb6..a878fb3ab1ad657259e0c14925723abb0c84a970 100644 --- a/docs/html/google/play/publishing/multiple-apks.jd +++ b/docs/html/google/play/publishing/multiple-apks.jd @@ -250,11 +250,11 @@ If you can't avoid using both, be aware that for any conflicts in agreement betw
      8. Device feature sets -

        This is based on your manifest file's This is based on your manifest file's {@code } element(s).

        For example, you can provide one APK for devices that support multitouch and another -APK for devices that do not support multitouch. See +APK for devices that do not support multitouch. See Features Reference for a list of features supported by the platform.


        diff --git a/docs/html/guide/_book.yaml b/docs/html/guide/_book.yaml index 6d6686b3cf3f7708752c5db2e1d285b7df3ef124..f09fe771bd1a7b027bcc032f5002dc38ae659e5d 100644 --- a/docs/html/guide/_book.yaml +++ b/docs/html/guide/_book.yaml @@ -9,6 +9,33 @@ toc: - title: System Permissions path: /guide/topics/security/permissions.html +- title: Platform Architecture + path: /guide/platform/index.html + section: + - title: Use Java 8 Language Features + path: /guide/platform/j8-jack.html + path_attributes: + - name: es-lang + value: Funciones del lenguaje Java 8 + - name: in-lang + value: Fitur Bahasa Java 8 + - name: ja-lang + value: Java 8 の機能 + - name: ko-lang + value: Java 8 언어 기능 + - name: pt-br-lang + value: Recursos de linguagem do Java 8 + - name: ru-lang + value: Возможности языка Java 8 + - name: vi-lang + value: Tính năng của Ngôn ngữ Java 8 + - name: zh-cn-lang + value: Java 8 语言功能 + - name: zh-tw-lang + value: Java 8 語言功能 + - title: Verifying App Behavior on the Android Runtime (ART) + path: /guide/practices/verifying-apps-art.html + - title: App Components path: /guide/components/index.html section: @@ -69,6 +96,11 @@ toc: path: /guide/topics/resources/runtime-changes.html - title: Localization path: /guide/topics/resources/localization.html + section: + - title: ICU4J Android Framework APIs + path: /guide/topics/resources/icu4j-framework.html + - title: Language and Locale + path: /guide/topics/resources/multilingual-support.html - title: Resource Types path: /guide/topics/resources/available-resources.html section: @@ -203,6 +235,8 @@ toc: path: /guide/topics/search/adding-custom-suggestions.html - title: Searchable Configuration path: /guide/topics/search/searchable-config.html + - title: Multi-Window Support + path: /guide/topics/ui/multi-window.html - title: Drag and Drop path: /guide/topics/ui/drag-drop.html - title: Accessibility @@ -362,14 +396,16 @@ toc: path: /guide/topics/data/data-storage.html - title: Data Backup path: /guide/topics/data/backup.html + section: + - title: Auto Backup + path: /guide/topics/data/autobackup.html + - title: Key/Value Backup + path: /guide/topics/data/keyvaluebackup.html + - title: Testing Backup and Restore + path: /guide/topics/data/testingbackup.html - title: App Install Location path: /guide/topics/data/install-location.html -- title: Libraries - path: /topic/libraries/index.html - section: - - include: /topic/libraries/_book.yaml - - title: Administration path: /guide/topics/admin/index.html section: @@ -417,5 +453,3 @@ toc: path: /guide/practices/screen-compat-mode.html - title: Supporting Tablets and Handsets path: /guide/practices/tablets-and-handsets.html - - title: Verifying App Behavior on ART - path: /guide/practices/verifying-apps-art.html diff --git a/docs/html/guide/_project.yaml b/docs/html/guide/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d1f8e5e04de642471c2bbb85491ddcd49dff2358 --- /dev/null +++ b/docs/html/guide/_project.yaml @@ -0,0 +1,6 @@ +name: "API Guides" +home_url: /guide/ +description: "Android provides a rich application framework that allows you to build innovative apps and games for mobile devices in a Java language environment." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /develop/_project.yaml diff --git a/docs/html/guide/appendix/app-intents.jd b/docs/html/guide/appendix/app-intents.jd index 8898927f240f46abae9d66e1f04fa43811710f2e..5fb004fff85637d6310853c0c3a16dcbcb7a0ad8 100644 --- a/docs/html/guide/appendix/app-intents.jd +++ b/docs/html/guide/appendix/app-intents.jd @@ -89,13 +89,13 @@ excludeFromSuggestions=true pitchPanorama center-of-view in degrees from -90 (look straight up) to 90 (look straight down.) zoomPanorama zoom. 1.0 = normal zoom, 2.0 = zoomed in 2x, 3.0 = zoomed in 4x, and so on.
        - A zoom of 1.0 is 90 degree horizontal FOV for a nominal - landscape mode 4 x 3 aspect ratio display. - Android phones in portrait mode will adjust the zoom so that - the vertical FOV is approximately the same as the landscape vertical - FOV. This means that the horizontal FOV of an Android phone in portrait - mode is much narrower than in landscape mode. This is done to minimize - the fisheye lens effect that would be present if a 90 degree horizontal + A zoom of 1.0 is 90 degree horizontal FOV for a nominal + landscape mode 4 x 3 aspect ratio display. + Android phones in portrait mode will adjust the zoom so that + the vertical FOV is approximately the same as the landscape vertical + FOV. This means that the horizontal FOV of an Android phone in portrait + mode is much narrower than in landscape mode. This is done to minimize + the fisheye lens effect that would be present if a 90 degree horizontal FOV was used in portrait mode. mapZoomThe map zoom of the map location associated with this panorama. This value is passed on to the Maps activity when the Street View "Go to Maps" menu item is chosen. It corresponds to the z parameter in diff --git a/docs/html/guide/appendix/g-app-intents.jd b/docs/html/guide/appendix/g-app-intents.jd index 9ec72db2411fa4266490fd5cab7582df5e02c73a..21c927b913b755d15593cffabae46f14d9b581e1 100644 --- a/docs/html/guide/appendix/g-app-intents.jd +++ b/docs/html/guide/appendix/g-app-intents.jd @@ -83,7 +83,7 @@ href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filter - Google Streetview + Google Streetview google.streetview:cbll=lat,lng&cbp=1,yaw,,pitch,zoom&mz=mapZoom VIEW diff --git a/docs/html/guide/appendix/glossary.jd b/docs/html/guide/appendix/glossary.jd index a200a6c0ff0e5bb9134ece04a0853f2b53336c86..75a533ad9084e5dd836eac7f1427d3095a1a79df 100755 --- a/docs/html/guide/appendix/glossary.jd +++ b/docs/html/guide/appendix/glossary.jd @@ -15,7 +15,7 @@ excludeFromSuggestions=true
        .dex file
        -
        Compiled Android application code file. +
        Compiled Android application code file.

        Android programs are compiled into .dex (Dalvik Executable) files, which are in turn zipped into a single .apk file on the device. .dex files can be created by automatically translating compiled applications written in @@ -26,7 +26,7 @@ excludeFromSuggestions=true a string value assigned to an Intent. Action strings can be defined by Android or by a third-party developer. For example, android.intent.action.VIEW for a Web URL, or com.example.rumbler.SHAKE_PHONE for a custom application - to vibrate the phone. + to vibrate the phone.

        Related: Intent.

        @@ -41,8 +41,8 @@ excludeFromSuggestions=true
        adb
        Android Debug Bridge, a command-line debugging application included with the SDK. It provides tools to browse the device, copy tools on the device, and - forward ports for debugging. If you are developing in Android Studio, - adb is integrated into your development environment. See + forward ports for debugging. If you are developing in Android Studio, + adb is integrated into your development environment. See Android Debug Bridge for more information.
        @@ -90,7 +90,7 @@ excludeFromSuggestions=true
        DDMS
        Dalvik Debug Monitor Service, a GUI debugging application included with the SDK. It provides screen capture, log dump, and process - examination capabilities. If you are developing in Android Studio, + examination capabilities. If you are developing in Android Studio, DDMS is integrated into your development environment. See Using DDMS to learn more about the program.
        @@ -100,7 +100,7 @@ excludeFromSuggestions=true is not intended to persist in the history stack, contain complex layout, or perform complex actions. Android provides a default simple dialog for you with optional buttons, though you can define your own dialog layout. - The base class for dialogs is {@link android.app.Dialog Dialog}. + The base class for dialogs is {@link android.app.Dialog Dialog}.

        Related: Activity.

        Drawable
        @@ -113,7 +113,7 @@ excludeFromSuggestions=true — xml or bitmap files that describe the image. Drawable resources are compiled into subclasses of {@link android.graphics.drawable}. For more information about drawables and other resources, see Resources. + href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources.

        Related: Resources, Canvas

        @@ -133,7 +133,7 @@ excludeFromSuggestions=true based on the criteria supplied in the Intent and the Intent Filters defined by other applications. For more information, see Intents and - Intent Filters. + Intent Filters.

        Related: Intent Filter, Broadcast Receiver.

        @@ -147,7 +147,7 @@ excludeFromSuggestions=true application/activity that best matches the Intent and criteria. For more information, see Intents and - Intent Filters. + Intent Filters.

        Related: Intent, Broadcast Receiver.

        @@ -155,12 +155,12 @@ excludeFromSuggestions=true
        An application class that listens for Intents that are broadcast, rather than being sent to a single target application/activity. The system delivers a broadcast Intent to all interested broadcast receivers, which - handle the Intent sequentially. -

        Related: Intent, Intent + handle the Intent sequentially. +

        Related: Intent, Intent Filter.

        - +
        Layout Resource
        -
        An XML file that describes the layout of an Activity screen. +
        An XML file that describes the layout of an Activity screen.

        Related: Resources

        Manifest File
        @@ -175,15 +175,15 @@ excludeFromSuggestions=true
        A resizeable bitmap resource that can be used for backgrounds or other images on the device. See - Nine-Patch Stretchable Image for more information. + Nine-Patch Stretchable Image for more information.

        Related: Resources.

        OpenGL ES
        Android provides OpenGL ES libraries that you can use for fast, complex 3D images. It is harder to use than a Canvas object, but - better for 3D objects. The {@link android.opengl} and - {@link javax.microedition.khronos.opengles} packages expose - OpenGL ES functionality. + better for 3D objects. The {@link android.opengl} and + {@link javax.microedition.khronos.opengles} packages expose + OpenGL ES functionality.

        Related: Canvas, Surface

        Resources
        @@ -205,15 +205,15 @@ excludeFromSuggestions=true
        Service
        An object of class {@link android.app.Service} that runs in the background (without any UI presence) to perform various persistent - actions, such as playing music or monitoring network activity. + actions, such as playing music or monitoring network activity.

        Related: Activity

        Surface
        An object of type {@link android.view.Surface} representing a block of memory that gets composited to the screen. A Surface holds a Canvas object for drawing, and provides various helper methods to draw layers and resize - the surface. You should not use this class directly; use - {@link android.view.SurfaceView} instead. + the surface. You should not use this class directly; use + {@link android.view.SurfaceView} instead.

        Related: Canvas

        SurfaceView
        @@ -249,7 +249,7 @@ excludeFromSuggestions=true windows, and so on). It receives calls from its parent object (see viewgroup, below)to draw itself, and informs its parent object about where and how big it would like to be (which may or may not be respected by the - parent). For more information, see {@link android.view.View}. + parent). For more information, see {@link android.view.View}.

        Related: Viewgroup, Widget

        @@ -259,18 +259,18 @@ excludeFromSuggestions=true they can be, as well as for calling each to draw itself when appropriate. Some viewgroups are invisible and are for layout only, while others have an intrinsic UI (for instance, a scrolling list box). Viewgroups are all - in the {@link android.widget widget} package, but extend - {@link android.view.ViewGroup ViewGroup}. + in the {@link android.widget widget} package, but extend + {@link android.view.ViewGroup ViewGroup}.

        Related: View

        Widget
        One of a set of fully implemented View subclasses that render form elements and other UI components, such as a text box or popup menu. Because a widget is fully implemented, it handles measuring and drawing - itself and responding to screen events. Widgets are all in the + itself and responding to screen events. Widgets are all in the {@link android.widget} package.
        - + -

        An intent allows you to start an activity in another app by describing a simple -action you'd like to perform (such as "view a map" or "take a picture") -in an {@link android.content.Intent} object. This type of intent is -called an implicit intent because it does not specify the app component -to start, but instead specifies an action and provides some -data with which to perform the action.

        - -

        When you call -{@link android.content.Context#startActivity startActivity()} or -{@link android.app.Activity#startActivityForResult startActivityForResult()} and pass it an -implicit intent, the system resolves the intent to an app that can handle the intent -and starts its corresponding {@link android.app.Activity}. If there's more than one app -that can handle the intent, the system presents the user with a dialog to pick which app -to use.

        - -

        This page describes several implicit intents that you can use to perform common actions, -organized by the type of app that handles the intent. Each section also shows how you can -create an intent filter to -advertise your app's ability to perform the same action.

        - -

        Caution: If there are no apps on the device that can receive -the implicit intent, your app will crash when it calls {@link android.content.Context#startActivity -startActivity()}. To first verify that an app exists to receive the intent, call {@link -android.content.Intent#resolveActivity resolveActivity()} on your {@link android.content.Intent} -object. If the result is non-null, there is at least one app that can handle the intent and -it's safe to call {@link android.content.Context#startActivity startActivity()}. If the result is -null, you should not use the intent and, if possible, you should disable the feature that invokes -the intent.

        - -

        If you're not familiar with how to create intents or intent filters, you should first read -Intents and Intent Filters.

        - -

        To learn how to fire the intents listed on this page from your development host, see -Verify Intents with the Android Debug Bridge.

        +

        + An intent allows you to start an activity in another app by describing a + simple action you'd like to perform (such as "view a map" or "take a + picture") in an {@link android.content.Intent} object. This type of intent + is called an implicit intent because it does not specify the app + component to start, but instead specifies an action and provides + some data with which to perform the action. +

        -

        Google Now

        +

        + When you call {@link android.content.Context#startActivity startActivity()} + or {@link android.app.Activity#startActivityForResult + startActivityForResult()} and pass it an implicit intent, the system + resolves + the intent to an app that can handle the intent and starts its + corresponding {@link android.app.Activity}. If there's more than one app + that can handle the intent, the system presents the user with a dialog to + pick which app to use. +

        -

        Google Now fires some of the intents listed -on this page in response to voice commands. For more information, see -Intents Fired by Google Now.

        +

        + This page describes several implicit intents that you can use to perform + common actions, organized by the type of app that handles the intent. Each + section also shows how you can create an intent + filter to advertise your app's ability to perform the same action. +

        +

        + Caution: If there are no apps on the device that can + receive the implicit intent, your app will crash when it calls {@link + android.content.Context#startActivity startActivity()}. To first verify that + an app exists to receive the intent, call {@link + android.content.Intent#resolveActivity resolveActivity()} on your {@link + android.content.Intent} object. If the result is non-null, there is at least + one app that can handle the intent and it's safe to call {@link + android.content.Context#startActivity startActivity()}. If the result is + null, you should not use the intent and, if possible, you should disable the + feature that invokes the intent. +

        +

        + If you're not familiar with how to create intents or intent filters, you + should first read Intents and Intent + Filters. +

        +

        + To learn how to fire the intents listed on this page from your development + host, see Verify Intents with the Android Debug + Bridge. +

        +

        Google Voice Actions

        +

        + Google Voice + Actions fires some of the intents listed on this page in response to + voice commands. For more information, see + Intents fired by Google Voice Actions. +

        Alarm Clock

        -

        Create an alarm

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "set an alarm for 7 am"
        • +
        • "set an alarm for 7 am" +
        @@ -301,22 +321,30 @@ android.provider.AlarmClock#ACTION_SET_ALARM} intent, your app must have the

        Create a timer

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "set timer for 5 minutes"
        • +
        • "set timer for 5 minutes" +
        -

        To create a countdown timer, use the {@link android.provider.AlarmClock#ACTION_SET_TIMER} -action and specify timer details such as the duration using extras defined below.

        +

        + To create a countdown timer, use the {@link + android.provider.AlarmClock#ACTION_SET_TIMER} action and specify timer + details such as the duration using extras defined below. +

        Note: This intent was added in Android 4.4 (API level 19).

        @@ -594,28 +622,36 @@ how to create an appropriate {@link android.net.Uri} for the output location, re </activity>
      9. -

        When handling this intent, your activity should check for the {@link -android.provider.MediaStore#EXTRA_OUTPUT} extra in the incoming {@link android.content.Intent}, -then save the captured image or video at the location specified by that extra and call {@link -android.app.Activity#setResult(int,Intent) setResult()} with an -{@link android.content.Intent} that includes a compressed thumbnail -in an extra named "data".

        +

        + When handling this intent, your activity should check for the {@link + android.provider.MediaStore#EXTRA_OUTPUT} extra in the incoming {@link + android.content.Intent}, then save the captured image or video at the + location specified by that extra and call {@link + android.app.Activity#setResult(int,Intent) setResult()} with an {@link + android.content.Intent} that includes a compressed thumbnail in an extra + named "data". +

        Start a camera app in still image mode

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "take a picture"
        • +
        • "take a picture" +
        @@ -661,17 +697,22 @@ public void capturePhoto() {

        Start a camera app in video mode

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "record a video"
        • +
        • "record a video" +
        @@ -1348,20 +1389,30 @@ Framework guide.

        Call a car

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "get me a taxi"
        • -
        • "call me a car"
        • +
        • "get me a taxi" +
        • + +
        • "call me a car" +
        -

        (Android Wear only)

        + +

        + (Android Wear only) +

        To call a taxi, use the @@ -1548,17 +1599,22 @@ public void playMedia(Uri file) {

        Play music based on a search query

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "play michael jackson billie jean"
        • +
        • "play michael jackson billie jean" +
        @@ -1861,19 +1917,28 @@ android.content.Intent#ACTION_DIAL} action and specify a phone number using the URI scheme defined below. When the phone app opens, it displays the phone number but the user must press the Call button to begin the phone call.

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "call 555-5555"
        • -
        • "call bob"
        • -
        • "call voicemail"
        • +
        • "call 555-5555" +
        • + +
        • "call bob" +
        • + +
        • "call voicemail" +
        @@ -1947,16 +2012,22 @@ public void dialPhoneNumber(String phoneNumber) {

        Search using a specific app

        - -
        -
        - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "search for cat videos on myvideoapp"
        • +
        • "search for cat videos on myvideoapp" +
        @@ -1976,7 +2047,7 @@ the SEARCH_ACTION action, as shown in the example intent filter bel
        "com.google.android.gms.actions.SEARCH_ACTION"
        -
        Support search queries from Google Now.
        +
        Support search queries from Google Voice Actions.
        @@ -2084,7 +2155,7 @@ that are available.

        Example intent:

         public void openWifiSettings() {
        -    Intent intent = new Intent(Intent.ACTION_WIFI_SETTINGS);
        +    Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
             if (intent.resolveActivity(getPackageManager()) != null) {
                 startActivity(intent);
             }
        @@ -2207,17 +2278,22 @@ at {@link android.provider.Telephony}.

        Load a web URL

        - -
        -
        - - - + +
        +
        + +
        -

        Google Now

        + +

        + Google Voice Actions +

        +
          -
        • "open example.com"
        • +
        • "open example.com" +
        @@ -2307,128 +2383,4 @@ adb shell am start -a android.intent.action.DIAL \

        For more information, see -ADB Shell Commands.

        - - - - - - -

        Intents Fired by Google Now

        - -

        Google Now recognizes many voice commands -and fires intents for them. As such, users may launch your app with a Google Now voice command -if your app declares the corresponding intent filter. For example, if your app can -set an alarm and you add the corresponding intent filter to your -manifest file, Google Now lets users choose your app when they request to set an alarm, as -shown in figure 1.

        - - -

        Figure 1. Google Now lets users choose from installed -apps that support a given action.

        - -

        Google Now recognizes voice commands for the actions listed in table 1. For more information -about declaring each intent filter, click on the action description.

        - -

        Table 1. Voice commands recognized by Google Now -(Google Search app v3.6).

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        CategoryDetails and ExamplesAction Name
        Alarm -

        Set alarm

        -
          -
        • "set an alarm for 7 am"
        • -
        -
        {@link android.provider.AlarmClock#ACTION_SET_ALARM AlarmClock.ACTION_SET_ALARM}
        -

        Set timer

        -
          -
        • "set a timer for 5 minutes"
        • -
        -
        {@link android.provider.AlarmClock#ACTION_SET_TIMER AlarmClock.ACTION_SET_TIMER}
        Communication -

        Call a number

        -
          -
        • "call 555-5555"
        • -
        • "call bob"
        • -
        • "call voicemail"
        • -
        -
        {@link android.content.Intent#ACTION_CALL Intent.ACTION_CALL}
        Local -

        Book a car

        -
          -
        • "call me a car"
        • -
        • "book me a taxi"
        • -
        -
        - ReserveIntents
        .ACTION_RESERVE_TAXI_RESERVATION
        Media -

        Play music from search

        -
          -
        • "play michael jackson billie jean"
        • -
        -
        {@link android.provider.MediaStore#INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH MediaStore
        .INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH}
        -

        Take a picture

        -
          -
        • "take a picture"
        • -
        -
        {@link android.provider.MediaStore#INTENT_ACTION_STILL_IMAGE_CAMERA MediaStore
        .INTENT_ACTION_STILL_IMAGE_CAMERA}
        -

        Record a video

        -
          -
        • "record a video"
        • -
        -
        {@link android.provider.MediaStore#INTENT_ACTION_VIDEO_CAMERA MediaStore
        .INTENT_ACTION_VIDEO_CAMERA}
        Search -

        Search using a specific app

        -
          -
        • "search for cat videos
          on myvideoapp"
        • -
        -
        "com.google.android.gms.actions
        .SEARCH_ACTION"
        Web browser -

        Open URL

        -
          -
        • "open example.com"
        • -
        -
        {@link android.content.Intent#ACTION_VIEW Intent.ACTION_VIEW}
        +ADB Shell Commands.

        \ No newline at end of file diff --git a/docs/html/guide/components/loaders.jd b/docs/html/guide/components/loaders.jd index ddd513b2a2c5c5e1ffc7d9fa3749c94c408c29f9..7c4baa846ae3c4651949159bb52b375b51c702cf 100644 --- a/docs/html/guide/components/loaders.jd +++ b/docs/html/guide/components/loaders.jd @@ -21,14 +21,14 @@ parent.link=activities.html
    - +

    Key classes

    1. {@link android.app.LoaderManager}
    2. {@link android.content.Loader}
    3. -
    - + +

    Related samples

    1. recreated after a configuration change. Thus, they don't need to re-query their data.
    2. - +

      Loader API Summary

      There are multiple classes and interfaces that may be involved in using @@ -131,10 +131,10 @@ of {@link android.content.Loader} or {@link android.content.AsyncTaskLoader} to load data from some other source.

    3. An implementation for {@link android.app.LoaderManager.LoaderCallbacks}. This is where you create new loaders and manage your references to existing -loaders.
    4. +loaders.
    5. A way of displaying the loader's data, such as a {@link android.widget.SimpleCursorAdapter}.
    6. -
    7. A data source, such as a {@link android.content.ContentProvider}, when using a +
    8. A data source, such as a {@link android.content.ContentProvider}, when using a {@link android.content.CursorLoader}.
    9. Starting a Loader

      @@ -142,7 +142,7 @@ android.widget.SimpleCursorAdapter}.

      The {@link android.app.LoaderManager} manages one or more {@link android.content.Loader} instances within an {@link android.app.Activity} or {@link android.app.Fragment}. There is only one {@link -android.app.LoaderManager} per activity or fragment.

      +android.app.LoaderManager} per activity or fragment.

      You typically initialize a {@link android.content.Loader} within the activity's {@link @@ -159,13 +159,13 @@ the following parameters:

      • A unique ID that identifies the loader. In this example, the ID is 0.
      • Optional arguments to supply to the loader at -construction (null in this example).
      • +construction (null in this example).
      • A {@link android.app.LoaderManager.LoaderCallbacks} implementation, which the {@link android.app.LoaderManager} calls to report loader events. In this example, the local class implements the {@link android.app.LoaderManager.LoaderCallbacks} interface, so it passes a reference -to itself, {@code this}.
      • +to itself, {@code this}.

      The {@link android.app.LoaderManager#initLoader initLoader()} call ensures that a loader is initialized and active. It has two possible outcomes:

      @@ -196,7 +196,7 @@ the life of the loader automatically. The {@link android.app.LoaderManager} starts and stops loading when necessary, and maintains the state of the loader and its associated content. As this implies, you rarely interact with loaders directly (though for an example of using loader methods to fine-tune a loader's -behavior, see the
      LoaderThrottle sample). +behavior, see the LoaderThrottle sample). You most commonly use the {@link android.app.LoaderManager.LoaderCallbacks} methods to intervene in the loading process when particular events occur. For more discussion of this topic, see -

      If you find other problems while using Jack, If you find other issues while using Jack, please file a bug.

      \ No newline at end of file diff --git a/docs/html/guide/practices/compatibility.jd b/docs/html/guide/practices/compatibility.jd index 83e841c39b7b68cc2d4ebf9b752537a379704c63..fb3db840f76a74ecf4d2768e45c5a29bcabb67b8 100644 --- a/docs/html/guide/practices/compatibility.jd +++ b/docs/html/guide/practices/compatibility.jd @@ -114,7 +114,7 @@ is {@link android.content.pm.PackageManager#FEATURE_APP_WIDGETS}.

      If necessary, you can prevent users from installing your app when their devices don't provide a given feature by declaring it with a {@code <uses-feature>} +"{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code } element in your app's manifest file.

      @@ -164,7 +164,7 @@ android.content.pm.PackageManager#FEATURE_BLUETOOTH} device feature. You can dis on this feature and make your app available to devices without Bluetooth by setting the {@code required} attribute to {@code "false"} in the {@code <uses-feature>} tag. +"{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code } tag. For more information about implicitly required device features, read Permissions that Imply Feature Requirements.

      @@ -180,7 +180,7 @@ Android 1.0 is API level 1 and Android 4.4 is API level 19.

      The API level allows you to declare the minimum version with which your app is compatible, using the {@code -<uses-sdk>} manifest tag and its +} manifest tag and its {@code minSdkVersion} attribute.

      diff --git a/docs/html/guide/practices/index.jd b/docs/html/guide/practices/index.jd index b61272b91ad7e1c744054b708369987bed2e4713..f34a6ba2eef4e5a6b16864fd3110d95ec9bae60d 100644 --- a/docs/html/guide/practices/index.jd +++ b/docs/html/guide/practices/index.jd @@ -1,7 +1,7 @@ page.title=Best Practices excludeFromSuggestions=true page.landing=true -page.landing.intro=Design and build apps the right way. Learn how to create apps that look great and perform well on as many devices as possible, from phones to tablets and more. +page.landing.intro=Design and build apps the right way. Learn how to create apps that look great and perform well on as many devices as possible, from phones to tablets and more. page.landing.image= @jd:body @@ -10,20 +10,20 @@ page.landing.image= diff --git a/docs/html/guide/practices/optimizing-for-3.0.jd b/docs/html/guide/practices/optimizing-for-3.0.jd index 8d07eb9847d834379910756c67bb2d0d74af9bf4..db45e19ce0da34f86bcab1e04e21f9482807456a 100644 --- a/docs/html/guide/practices/optimizing-for-3.0.jd +++ b/docs/html/guide/practices/optimizing-for-3.0.jd @@ -4,7 +4,7 @@ excludeFromSuggestions=true @@ -181,7 +181,7 @@ larger screens.

    10. Perform your usual tests to be sure everything works and looks as expected.
    - +
  • Apply the new "holographic" theme to your application
    1. Open your manifest file and update the {@code android:targetSdkVersion} to {@code "11"}. For example:
       <manifest ... >
      -    <uses-sdk android:minSdkVersion="4" 
      +    <uses-sdk android:minSdkVersion="4"
                     android:targetSdkVersion="11" />
           <application ... >
               ...
      @@ -446,7 +446,7 @@ Multi-choice List: An example of how to provide multiple-choice selection fo
       GridView.
    2. -Content Loaders: An example using new Loader APIs to asynchronously load data.
    3. +Content Loaders: An example using new Loader APIs to asynchronously load data.
    4. Property Animation: Several samples using the new animation APIs to animate object @@ -624,7 +624,7 @@ landscape orientation and that is how most users will use them. So, you should e application can function in landscape. Even if you want to avoid rotating the screen while your application is running, you should not assume that portrait is the device's default orientation. You should either ensure that your layout is usable in both portrait and landscape orientations or -provide an alternative layout resource for landscape orientation.

      If you believe your application or game provides its best experience when the screen is tall, diff --git a/docs/html/guide/practices/screen-compat-mode.jd b/docs/html/guide/practices/screen-compat-mode.jd index 34580ba824cf280e54765f759662d05a284e3398..18a089e1d1198fce50b9152478897b6ac3232260 100644 --- a/docs/html/guide/practices/screen-compat-mode.jd +++ b/docs/html/guide/practices/screen-compat-mode.jd @@ -75,7 +75,7 @@ android:targetSdkVersion} to {@code "4"} or higher, or set {@code android:resizeable} to {@code "true"}.

      - +
      Version 2 (Android 3.2 and greater)
      The system draws the application's layout the same as it would on a normal size handset (approximately emulating a 320dp x 480dp screen), then scales it @@ -151,9 +151,9 @@ android:xlargeScreens} attribute to {@code "true"}:

      system will always resize your layout to fit the screen. This works regardless of what values you've set in the {@code } -attributes.

      +attributes.

    5. - +
    6. Easy but has other effects:

      In your manifest's {@code } diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd index 2223dbf3096dc6d9ac4b6d4ab89959a4d9a42853..ea9f988daac7d7e83e2ade44ff0f4e05d7f29515 100644 --- a/docs/html/guide/practices/screens_support.jd +++ b/docs/html/guide/practices/screens_support.jd @@ -139,7 +139,7 @@ or position in a density-independent way.

      The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the -screen in use. The conversion of dp units to screen pixels is simple: +screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different @@ -214,7 +214,7 @@ changes in screen density.

      Note: These minimum screen sizes were not as well defined prior to -Android 3.0, so you may encounter some devices that are mis-classified between normal and large. +Android 3.0, so you may encounter some devices that are mis-classified between normal and large. These are also based on the physical resolution of the screen, so may vary across devices—for example a 1024x720 tablet with a system bar actually has a bit less space available to the application due to it being used by the system bar.

      @@ -904,7 +904,7 @@ href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><support manifest element:

      - +
      {@code android:requiresSmallestWidthDp}
      diff --git a/docs/html/guide/practices/tablets-and-handsets.jd b/docs/html/guide/practices/tablets-and-handsets.jd index 85327b6d7036be1aee5e3be68a364b1cf67126b3..a1bafd3d7dec596555da7bd1daee8178ddacf0b3 100644 --- a/docs/html/guide/practices/tablets-and-handsets.jd +++ b/docs/html/guide/practices/tablets-and-handsets.jd @@ -89,7 +89,7 @@ href="{@docRoot}guide/components/fragments.html">Fragments developer guide.<
    7. -
    8. Use the action bar, but follow best practices and ensure your design +
    9. Use the action bar, but follow best practices and ensure your design is flexible enough for the system to adjust the action bar layout based on the screen size.

      The {@link android.app.ActionBar} is a UI component for activities that replaces the traditional diff --git a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd index f6669e4f36b433e24cfb0b4b57ddae6691bd81f7..b66fdd42a1f4cfb2b691514a390e1747036b5e12 100644 --- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd +++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd @@ -8,7 +8,7 @@ parent.link=index.html

      @@ -105,7 +105,7 @@ need to
    10. It illustrates activities and tasks with examples, and describes some of their underlying principles and mechanisms, such as navigation, - multitasking, activity re-use, intents, and the activity stack. + multitasking, activity re-use, intents, and the activity stack. The document also highlights design decisions that are available to you and what control they give you over the UI of your application.

      @@ -146,7 +146,7 @@ document),

      An Android application typically consists of one or more - related, loosely bound activities for the user to interact with, typically bundled up in a single file (with an .apk suffix). Android ships with a rich set @@ -186,10 +186,10 @@ document), seamless, activity after activity, task after task.

      - +

      An activity handles a particular type of content (data) and accepts a - set of related user actions. Each activity has a + set of related user actions. Each activity has a lifecycle that is independent of the other activities in its application or task — each activity is @@ -283,7 +283,7 @@ independent of the other to the activity stack, so that pressing Back displays the previous activity on the stack. However, the user cannot use the Back button to go back further than the last visit to Home. The adding of an activity to - the current stack happens whether or not that activity begins a new + the current stack happens whether or not that activity begins a new task (as long as that task was started without going Home), so going back can let the user go back to activities in previous tasks. The user can get to tasks earlier than @@ -297,7 +297,7 @@ independent of the other designing the navigation, if you have screen A and you want the user to be able go to a subsequent screen B and then use the Back button to go back to screen A, then the screen A needs to be implemented as an - activity. The one exception to this rule is if your application + activity. The one exception to this rule is if your application takes control of the Back button and manages the navigation itself. @@ -340,7 +340,7 @@ itself. Send a text message with an attachment

    11. - View a YouTube video and share it by email with someone else + View a YouTube video and share it by email with someone else
    12. @@ -666,7 +666,7 @@ itself. mailto:info@example.com link, they are actually initiating an Intent object, or just an intent, which then gets resolved to a particular component (we consider only activity components here). - So, the result of a user touching a mailto: link is an Intent object + So, the result of a user touching a mailto: link is an Intent object that the system tries to match to an activity. If that Intent object was written explicitly naming an activity (an explicit intent), then the system immediately launches that activity in response to the user @@ -925,7 +925,7 @@ href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filter For instance, you could disable the user control that initiates the Intent object, or display a message to the user that lets them go to a location, such as Google Play, to download its application. - In this way, your code can start the activity (using either startActivity() + In this way, your code can start the activity (using either startActivity() or startActivityForResult()) only if the intent has tested to resolve to an activity that is actually present.

      @@ -947,7 +947,7 @@ href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filter launcher (typically implemented as a sliding drawer on the Home screen), or from a shortcut icon on the Home screen, or from the task switcher. (The mechanism for this is for the - activity to have an + activity to have an intent filter with action MAIN and category LAUNCHER.) @@ -1103,7 +1103,7 @@ MAIN and activity to be run.

      - +

      Notifications and App Widgets should provide consistent back behavior

      Notifications and app widgets are two common ways that a user can launch diff --git a/docs/html/guide/practices/ui_guidelines/icon_design.jd b/docs/html/guide/practices/ui_guidelines/icon_design.jd index 07266607ed4c2617074efd6e49dccf8d3b60e4c9..6b546c9fd21dfd9132f485ab00f1e0ff16bbd9cf 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design.jd @@ -58,7 +58,7 @@ Screens

      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      @@ -72,13 +72,13 @@ professional to users.

      This document provides information to help you create icons for various parts of your application’s user interface that match the general styles used by the -Android 2.x framework. Following these guidelines will help you to create a +Android 2.x framework. Following these guidelines will help you to create a polished and unified experience for the user.

      The following documents discuss detailed guidelines for the common types of icons used throughout Android applications:

      -
      +
      Launcher Icons
      A Launcher icon is a graphic that represents your application on the device's Home screen and in the Launcher window.
      @@ -103,7 +103,7 @@ icons used throughout Android applications:

      graphically represent list items. An example is the Settings application.
      -

      To get started creating your icons more quickly, you can download +

      To get started creating your icons more quickly, you can download the Android Icon Templates Pack.

      @@ -142,7 +142,7 @@ section in the box at the top-right corner of this page.

      Android is designed to run on a variety of devices that offer a range of screen sizes and resolutions. When you design the icons for your application, it's important keep in mind that your application may be installed on any of -those devices. As described in the Supporting Multiple Screens document, the Android platform makes it straightforward for you to provide icons in such a way that they will be displayed properly on any device, @@ -158,7 +158,7 @@ your application, see Resource directory qualifiers for screen size and density.

      -

      For tips on how to create and manage icon sets for multiple densities, see +

      For tips on how to create and manage icon sets for multiple densities, see Tips for Designers.

      @@ -290,7 +290,7 @@ initially draw launcher icons on an 864x864 artboard, it will be easier and cleaner to tweak the icons when you scale the artboard down to the target sizes for final asset creation.

      - +

      When scaling, redraw bitmap layers as needed

      diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd b/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd index 831de4569edd2a7db1f3d3c507b77c6e178a8c1a..37657f4d1eccb2fec3b34931bd400ffcca7e7351 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_action_bar.jd @@ -31,7 +31,7 @@ Screens
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd b/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd index c958ed9a655ec6137998dbbc3d05889636f8dcfe..a7ee73f41a7873972ddab40eade7cb7cacf82a85 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_dialog.jd @@ -29,7 +29,7 @@ Screens
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd b/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd index f47e186790a937a03b1d120e0da754c2d41e84c8..3bb1a627c85cea9fa5b27845c61436245555b3ae 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd @@ -28,7 +28,7 @@ Screens
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd b/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd index 2df3a2250ef55c89d3b641a367ca4283e9aeb826..483e076ac52f44b5abf3db1b71fe7242d33fbe45 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd @@ -95,7 +95,7 @@ but rather they are meant to emphasize the common approaches that your icons can share with others on the device. Figure 1, at right, provides examples.

      -

      Figure 1. Example launcher icons for Android 2.0 and diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_list.jd b/docs/html/guide/practices/ui_guidelines/icon_design_list.jd index 29e1a9380de71f35747152a9e3bb6921469eaa74..fa350bc2b6a7b9431a84cee9e95d02c98920aee7 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_list.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_list.jd @@ -30,7 +30,7 @@ Screens

      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd b/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd index a5b35977fc0e11a193290f059c9ff44a4c7bae1d..25b23d0f628c34c2971a0d6730773c7354350c3a 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_menu.jd @@ -34,7 +34,7 @@ Screens
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      @@ -267,7 +267,7 @@ menu icon color palette. appropriate. For example, in Figure 3 the logical place for rounded corners is the roof and not the rest of the building. -
    13. All dimensions specified on this page are based on a 48x48 pixel artboard +
    14. All dimensions specified on this page are based on a 48x48 pixel artboard size with a 6 pixel safeframe.
    15. The menu icon effect (the outer glow) described in
    16. Final art must be exported as a transparent PNG file.
    17. -
    18. Templates for creating menu icons in Adobe Photoshop are available in the +
    19. Templates for creating menu icons in Adobe Photoshop are available in the Icon Templates Pack.
    20. diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd b/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd index 4993adb0328b770c5c7cdc719967ea1cebdf5972..27df450e167329609bab1a32e4d6f5e5d1ab453d 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_status_bar.jd @@ -42,7 +42,7 @@ Screens
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd b/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd index cbe6706fb06777b6bea2502871ab2931684eee4c..308e6d092c1ed89a85fb15449b600b173f2ee392 100644 --- a/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd +++ b/docs/html/guide/practices/ui_guidelines/icon_design_tab.jd @@ -34,7 +34,7 @@ Screens
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design, including more guidelines for Iconography.

      @@ -291,10 +291,10 @@ your application.

      the Android platform.

      Warning: -Because these resources can change between platform versions, you +Because these resources can change between platform versions, you should not reference the system's copy of the resources. If you want to use any icons or other internal drawable resources, you should store a -local copy of those icons or drawables in your application resources, +local copy of those icons or drawables in your application resources, then reference the local copy from your application code. In that way, you can maintain control over the appearance of your icons, even if the system's copy changes. Note that the grid below is not intended to be complete.

      diff --git a/docs/html/guide/practices/ui_guidelines/index.jd b/docs/html/guide/practices/ui_guidelines/index.jd index 91a0725b82e3d23b8af48850ec908e6dc56956ae..713109cf2bcf06af8cf0d6c5200c9d48c3aba21e 100644 --- a/docs/html/guide/practices/ui_guidelines/index.jd +++ b/docs/html/guide/practices/ui_guidelines/index.jd @@ -7,7 +7,7 @@ excludeFromSuggestions=true
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      The Android UX team has put together a set of guidelines for the interaction and visual design of Android applications. The new collection provides an overview of Android styles, design patterns, building blocks for exceptional Android designs, and more.

      diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd index bf87bdd124e7fa267eedc98d99d85b1bc200566d..949752588a120a4095fcf7a9512e269686c27039 100644 --- a/docs/html/guide/practices/ui_guidelines/menu_design.jd +++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd @@ -8,7 +8,7 @@ parent.link=index.html @@ -16,7 +16,7 @@ parent.link=index.html

      This document has been deprecated.

      -

      For design guidelines about adding user actions and other options, read the design guidelines +

      For design guidelines about adding user actions and other options, read the design guidelines for Action Bar or the developer guide about Menus.

      @@ -25,7 +25,7 @@ for Action Bar or the dev onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
      - + @@ -37,7 +37,7 @@ onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
      - +

      Quickview

        @@ -85,15 +85,15 @@ onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
    - +

    A menu holds a set of commands (user actions) that are normally hidden, and are accessible by a button, key, or gesture. Menu commands provide a means - for performing operations and for navigating to other parts of your + for performing operations and for navigating to other parts of your application or other applications. Menus are useful for freeing screen space, as an alternative to placing functionality and navigation, in buttons or other - user controls in the content area of your application. + user controls in the content area of your application.

    @@ -102,7 +102,7 @@ onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" /> the functionality and navigation for your application. Briefly:

    • The Options menu contains primary functionality that applies - globally to the current activity or starts a related activity. + globally to the current activity or starts a related activity. It is typically invoked by a user pressing a hard button, often labeled Menu.
    • The Context menu contains secondary functionality for the currently selected item. It is typically invoked by a user's touch & hold @@ -113,11 +113,11 @@ onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />

      All but the simplest applications have menus. The system automatically - lays the menus out and provides standard ways for users to access them. + lays the menus out and provides standard ways for users to access them. In this sense, they are familiar and dependable ways for users to access functionality across all applications. All menus are panels that "float" on top of the activity screen and are smaller than full screen, so that the - application is still visible around its edges. This is a visual reminder + application is still visible around its edges. This is a visual reminder that a menu is an intermediary operation that disappears once it's used.

      @@ -127,8 +127,8 @@ onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />

      Tour of the Menus

      -

      Note: Your menus and screens might not look -like those shown in this document; they may vary from one version of Android +

      Note: Your menus and screens might not look +like those shown in this document; they may vary from one version of Android or device to another.

      @@ -137,13 +137,13 @@ or device to another.

      The Options menu contains commands that apply globally across the current activity, or can start another activity. They do not apply to a selected - item in the content (a Context menu does that). + item in the content (a Context menu does that).

      - On most devices, a user presses the Menu button to access the Options menu, - as shown in the screenshot below. To close the menu, the user presses - Menu again, or presses the Back button. + On most devices, a user presses the Menu button to access the Options menu, + as shown in the screenshot below. To close the menu, the user presses + Menu again, or presses the Back button. In fact, to cancel out of any menu, press the Back button. (Pressing the Menu button or touching outside the menu also works.) Note that how to invoke this menu may be different on different devices. @@ -153,15 +153,15 @@ or device to another. Each activity activity has its own set of operations and therefore its own Options menu. - An application with multiple activities would have a different Options menu - for each activity. + An application with multiple activities would have a different Options menu + for each activity.

      For example, in the message list view of an email program, the Options menu - might let you search the messages, compose a new message, refresh the list, - or change the email settings. The compose view of an email program would - have a different Options menu, such as adding a CC field, attaching a file, + might let you search the messages, compose a new message, refresh the list, + or change the email settings. The compose view of an email program would + have a different Options menu, such as adding a CC field, attaching a file, or discarding the message.

      @@ -179,7 +179,7 @@ or device to another.
    • Options expanded menu - If the activity has more menu items than will fit on the icon menu, then the last icon is labeled "More" — selecting it - displays a list that can contain any number of menu items and will scroll + displays a list that can contain any number of menu items and will scroll as necessary.
    @@ -202,18 +202,18 @@ or device to another.

    A user can touch & hold on content on the screen to - access a Context menu (if one exists), as shown in the screenshot below. + access a Context menu (if one exists), as shown in the screenshot below. A Context menu is a list of menu items (commands) that can operate on the selected content. The command can either be part of the current - activity, or the system can pass the selected content along to - an operation in another activity (by way of an + activity, or the system can pass the selected content along to + an operation in another activity (by way of an intent).

    For example, in an email message list, a user can touch & hold on an email message to open a Context menu containing commands to read, - archive, or delete the message. + archive, or delete the message.

    @@ -231,7 +231,7 @@ or device to another. In the above example, if the user performs touch & hold on the contact "Obi Wan Kenobi", a Context menu opens. The commands provided in this Context menu are the complete set of actions that can be performed - on this contact. + on this contact.

    @@ -246,7 +246,7 @@ or device to another.

    Also note, as shown in the following screenshot, the Context menu and the next screen both hold the same complete set of commands that can be performed - on this contact. The Context menu displays the commands in a list, + on this contact. The Context menu displays the commands in a list, while the "View contact" activity splits them into various items in the Options menu, icon buttons and list items.

    @@ -268,10 +268,10 @@ or device to another.

    Text Commands in Context Menu

    - Text links and text fields in the content both have system-provided operations + Text links and text fields in the content both have system-provided operations that are common across all applications: operations such as "Select all", "Select text", - "Copy all", and "Add to dictionary". If the text field is editable, it also - has other operations, such as "Cut all" and "Input Method", and if text + "Copy all", and "Add to dictionary". If the text field is editable, it also + has other operations, such as "Cut all" and "Input Method", and if text is also on the clipboard, it has "Paste". The system automatically inserts the appropriate menu items into the Context menu of text links and text fields, as shown in the following screenshot. @@ -342,7 +342,7 @@ or device to another. An example of a selection-specific Context menu is when a user performs a touch & hold on a person's name in a list view of a contacts application. The Context menu would typically contain commands "View contact", "Call contact", - and "Edit contact". + and "Edit contact".

    Place the most frequently used operations first

    @@ -365,7 +365,7 @@ or device to another.

    Don't put commands only in a Context menu

    - If a user can fully access your application without using Context menus, + If a user can fully access your application without using Context menus, then it's designed properly! In general, if part of your application is inaccessible without using Context menus, then you need to duplicate those commands elsewhere.

    @@ -373,8 +373,8 @@ or device to another.

    Before opening a Context menu, it has no visual representation that identifies its presence (whereas the Options menu has the Menu button), and so is not - particularly discoverable. - Therefore, in general, a Context menu should duplicate commands + particularly discoverable. + Therefore, in general, a Context menu should duplicate commands found in the corresponding activity screen. For example, while it's useful to let the user call a phone number from a Context menu invoked by touch & hold on a name in a list of contacts, that operation should also @@ -388,7 +388,7 @@ or device to another. As described under shortcut, touching on an item in the content should activate the same command as touching the first item in the Context menu. Both cases should be the most intuitive - operation for that item. + operation for that item.

    Selecting an item in the content should perform the most intuitive operation

    @@ -427,13 +427,13 @@ or device to another.

    A Context menu should identify the selected item

    - When a user does touch & hold on an item, the Context menu should - contain the name of the selected item. Therefore, + When a user does touch & hold on an item, the Context menu should + contain the name of the selected item. Therefore, when creating a Context menu, be sure to include a title and the name of the - selected item so that it's clear to the user what the context is. + selected item so that it's clear to the user what the context is. For example, if a user selects a contact "Joan of Arc", put that name in the title of the Context menu (using - {@link android.view.ContextMenu#setHeaderTitle(java.lang.CharSequence) setHeaderTitle}). + {@link android.view.ContextMenu#setHeaderTitle(java.lang.CharSequence) setHeaderTitle}). Likewise, a command to edit the contact should be called "Edit contact", not just "Edit".

    @@ -442,7 +442,7 @@ or device to another.

    Put only the most important commands fixed on the screen

    - By putting commands in menus, you free up the screen to hold more content. + By putting commands in menus, you free up the screen to hold more content. On the other hand, fixing commands in the content area of an activity makes them more prominent and easy to use.

    @@ -456,7 +456,7 @@ or device to another. To give a command the highest prominence, ensuring the command is obvious and won't be overlooked.
    Example: A "Buy" button in a store application.
  • -
  • +
  • When quick access to the command is important and going to the menu would be tedious or slow.
    Example: Next/Previous buttons or Zoom In/Out buttons in an image viewing application. @@ -494,7 +494,7 @@ or device to another. When a dialog is displayed, pressing the Menu button should do nothing. This also holds true for activities that look like dialogs. A dialog box is recognizable by being - smaller than full-screen, having zero to three buttons, is non-scrollable, and + smaller than full-screen, having zero to three buttons, is non-scrollable, and possibly a list of selectable items that can include checkboxes or radio buttons.

    @@ -520,12 +520,12 @@ true

    Sometimes a menu item's action cannot be performed — for example, - the "Forward" button in a browser cannot work until after the "Back" + the "Forward" button in a browser cannot work until after the "Back" button has been pressed. We recommend:

      -
    • +
    • In Options menu - disable the menu item, which dims the text and icon, turning it gray. This applies to menu items in both the icon menu and the "More" menu. It would be disorienting for the icon menu to change from 6 diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd index cf2cd64d483a2a5dc1bc95b9626b0960e38c9763..95c594dba972e544ac9c6ba5e8fb9e12525368a2 100644 --- a/docs/html/guide/practices/ui_guidelines/widget_design.jd +++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd @@ -46,7 +46,7 @@ parent.link=index.html
      -

      New Guides for App Designers!

      +

      New Guides for App Designers!

      Check out the new documents for designers at Android Design.

      diff --git a/docs/html/guide/practices/verifying-apps-art.jd b/docs/html/guide/practices/verifying-apps-art.jd index 217c65c9fcd2bfa493578ddae16cd0209d00afb3..2da7c0e86124ef3edd97981e43e7ee501974c6be 100644 --- a/docs/html/guide/practices/verifying-apps-art.jd +++ b/docs/html/guide/practices/verifying-apps-art.jd @@ -2,60 +2,82 @@ page.title=Verifying App Behavior on the Android Runtime (ART) @jd:body
      -
      -

      Quickview

      -
        -
      • The new Android runtime (ART) is available on some of the newest Android - devices, though all of them currently have Dalvik as the default - runtime.
      • -
      • App developers should make sure their apps are compatible with ART, - especially if you use JNI to run native code or if you use certain tools - that produce non-standard code (such as some obfuscators).
      • -
      - -

      In this document

      -
        -
      1. Addressing Garbage Collection (GC) Issues
      2. -
      3. Preventing JNI Issues -
          -
        1. Checking JNI code for garbage-collection - issues
        2. -
        3. Error handling
        4. -
        5. Object model changes
        6. -
        -
      4. -
      5. Preventing Stack Size Issues
      6. -
      7. Fixing AOT Compilation Issues
      8. -
      9. Reporting Problems
      10. -
      -

      See also

      -
        -
      1. Introducing ART
      2. -
      3. Debugging -Android JNI with CheckJNI
      4. -
      -
      +
      -

      With Android 4.4, we are beginning to roll out a new Android runtime, -ART. This runtime offers a number of new features that improve -performance and smoothness of the Android platform and apps. (You can find more -information about ART's new features in Introducing -ART.)

      - -

      Currently, ART is available on a number of Android 4.4 devices, such as the -Nexus 4, Nexus 5, Nexus 7, and Google Play edition devices. -At this time, all devices still use Dalvik as the default runtime. We encourage -you to test your apps for ART compatibility and to take advantage of ART's new -features. However, for the time being, you should also take care to maintain -compatibility with Dalvik.

      - -

      This document lets you know about things to watch for when migrating an -existing app to be compatible with ART. Most apps should just work when -running with ART. However, some techniques that work on Dalvik do not work on -ART. This document discusses some of these issues.

      +

      + The Android runtime (ART) is the default runtime for devices running Android + 5.0 (API level 21) and higher. This runtime offers a number of features + that improve performance and smoothness of the Android platform and apps. + You can find more information about ART's new features in Introducing + ART. +

      + +

      + However, some techniques that work on Dalvik do not work on ART. This + document lets you know about things to watch for when migrating an existing + app to be compatible with ART. Most apps should just work when running with + ART. +

      Addressing Garbage Collection (GC) Issues

      @@ -147,7 +169,7 @@ in use, this can lead to memory corruption or other problems. For example:

      Error handling

      -

      ART's JNI throws errors in a number of cases where Dalvik didn’t. (Once +

      ART's JNI throws errors in a number of cases where Dalvik doesn’t. (Once again, you can catch many such cases by testing with CheckJNI.)

      For example, if RegisterNatives is called with a method that diff --git a/docs/html/guide/topics/admin/device-admin.jd b/docs/html/guide/topics/admin/device-admin.jd index e2fef04b75372822062b6850d540d3f13f8f43b1..2a8583a83e7dcd56ef6f9da5fdad63df92f98fb8 100644 --- a/docs/html/guide/topics/admin/device-admin.jd +++ b/docs/html/guide/topics/admin/device-admin.jd @@ -135,60 +135,60 @@ can require PIN or passwords to have at least six characters. combination of letters and numbers. They may include symbolic characters. - + Complex password required Requires that passwords must contain at least a letter, a numerical digit, and a special symbol. Introduced in Android 3.0. - - + + Minimum letters required in password The minimum number of -letters required in the password for all admins or a particular one. Introduced in Android 3.0. +letters required in the password for all admins or a particular one. Introduced in Android 3.0. - - - - Minimum lowercase letters required in password - The minimum number of lowercase -letters required in the password for all admins or a particular one. Introduced in Android 3.0. + + + + Minimum lowercase letters required in password + The minimum number of lowercase +letters required in the password for all admins or a particular one. Introduced in Android 3.0. - - - Minimum non-letter characters required in password + + + Minimum non-letter characters required in password The minimum number of -non-letter characters required in the password for all admins or a particular one. Introduced in Android 3.0. +non-letter characters required in the password for all admins or a particular one. Introduced in Android 3.0. - - - Minimum numerical digits required in password - The minimum number of numerical digits required in the password for all admins or a particular one. Introduced in Android 3.0. + + + Minimum numerical digits required in password + The minimum number of numerical digits required in the password for all admins or a particular one. Introduced in Android 3.0. - - Minimum symbols required in password - The minimum number of symbols required in the password for all admins or a particular one. Introduced in Android 3.0. + + Minimum symbols required in password + The minimum number of symbols required in the password for all admins or a particular one. Introduced in Android 3.0. - - Minimum uppercase letters required in password - The minimum number of uppercase letters required in the password for all admins or a particular one. Introduced in Android 3.0. + + Minimum uppercase letters required in password + The minimum number of uppercase letters required in the password for all admins or a particular one. Introduced in Android 3.0. - - Password expiration timeout - When the password will expire, expressed as a delta in milliseconds from when a device admin sets the expiration timeout. Introduced in Android 3.0. + + Password expiration timeout + When the password will expire, expressed as a delta in milliseconds from when a device admin sets the expiration timeout. Introduced in Android 3.0. - - Password history restriction + + Password history restriction This policy prevents users from reusing the last n unique passwords. This policy is typically used in conjunction with {@link android.app.admin.DevicePolicyManager#setPasswordExpirationTimeout(android.content.ComponentName,long) setPasswordExpirationTimeout()}, which forces users to update their passwords after a specified amount of time has elapsed. -Introduced in Android 3.0. +Introduced in Android 3.0. - + Maximum failed password attempts Specifies how many times a user can enter the wrong password before the @@ -203,18 +203,18 @@ pressed a button before the device locks the screen. When this happens, users need to enter their PIN or passwords again before they can use their devices and access data. The value can be between 1 and 60 minutes. - -Require storage encryption -Specifies that the storage area should be encrypted, if the device supports it. + +Require storage encryption +Specifies that the storage area should be encrypted, if the device supports it. Introduced in Android 3.0. Disable camera - + Specifies that the camera should be disabled. Note that this doesn't have to be a permanent disabling. The camera can be enabled/disabled dynamically based on context, time, and so on. Introduced in Android 4.0. - + @@ -234,7 +234,7 @@ Administration API lets you do the following:

        The examples used in this document are based on the Device Administration API sample, which is included in the SDK samples (available through the -Android SDK Manager) and located on your system as +Android SDK Manager) and located on your system as <sdk_root>/ApiDemos/app/src/main/java/com/example/android/apis/app/DeviceAdminSample.java.

        The sample application offers a demo of device admin features. It presents users @@ -250,8 +250,8 @@ policies, the system returns an error.

      • Set how many failed password attempts can occur before the device is wiped (that is, restored to factory settings).
      • Set how long from now the password will expire.
      • -
      • Set the password history length (length refers to number of old passwords stored in the history). -This prevents users from reusing +
      • Set the password history length (length refers to number of old passwords stored in the history). +This prevents users from reusing one of the last n passwords they previously used.
      • Specify that the storage area should be encrypted, if the device supports it.
      • Set the maximum amount of inactive time that can elapse before the device @@ -259,7 +259,7 @@ locks.
      • Make the device lock immediately.
      • Wipe the device's data (that is, restore factory settings).
      • Disable the camera.
      • - +
      @@ -454,8 +454,8 @@ changes to prompt the user to activate the device admin application, as shown in

      Figure 2. Sample Application: Activating the Application

      -

      Below is the code that gets executed when the user clicks the Enable Admin checkbox. This has the effect of triggering the -{@link android.preference.Preference.OnPreferenceChangeListener#onPreferenceChange(android.preference.Preference, java.lang.Object) onPreferenceChange()} +

      Below is the code that gets executed when the user clicks the Enable Admin checkbox. This has the effect of triggering the +{@link android.preference.Preference.OnPreferenceChangeListener#onPreferenceChange(android.preference.Preference, java.lang.Object) onPreferenceChange()} callback. This callback is invoked when the value of this {@link android.preference.Preference} has been changed by the user and is about to be set and/or persisted. If the user is enabling the application, the display changes to prompt the user to activate the device admin application, as shown in figure 2. Otherwise, the device admin application is disabled.

      @@ -556,7 +556,7 @@ containing at least numeric characters.
      {@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_COMPLEX}
      The user must have entered a password containing at least a letter, a numerical digit and -a special symbol.
      +a special symbol.
      {@link android.app.admin.DevicePolicyManager#PASSWORD_QUALITY_SOMETHING}
      The policy requires some kind @@ -581,7 +581,7 @@ example, you could set a policy that states that passwords must contain at least contents:

        -
      • {@link android.app.admin.DevicePolicyManager#setPasswordMinimumLetters(android.content.ComponentName,int) setPasswordMinimumLetters()}
      • +
      • {@link android.app.admin.DevicePolicyManager#setPasswordMinimumLetters(android.content.ComponentName,int) setPasswordMinimumLetters()}
      • {@link android.app.admin.DevicePolicyManager#setPasswordMinimumLowerCase(android.content.ComponentName,int) setPasswordMinimumLowerCase()}
      • @@ -622,8 +622,8 @@ int maxFailedPw; mDPM.setMaximumFailedPasswordsForWipe(mDeviceAdminSample, maxFailedPw);
        Set password expiration timeout
        -

        Beginning with Android 3.0, you can use the -{@link android.app.admin.DevicePolicyManager#setPasswordExpirationTimeout(android.content.ComponentName,long) setPasswordExpirationTimeout()} +

        Beginning with Android 3.0, you can use the +{@link android.app.admin.DevicePolicyManager#setPasswordExpirationTimeout(android.content.ComponentName,long) setPasswordExpirationTimeout()} method to set when a password will expire, expressed as a delta in milliseconds from when a device admin sets the expiration timeout. For example:

        DevicePolicyManager mDPM;
        @@ -632,18 +632,18 @@ long pwExpiration;
         ...
         mDPM.setPasswordExpirationTimeout(mDeviceAdminSample, pwExpiration);
         
        - +
        Restrict password based on history
        -

        Beginning with Android 3.0, you can use the -{@link android.app.admin.DevicePolicyManager#setPasswordHistoryLength(android.content.ComponentName,int) setPasswordHistoryLength()} +

        Beginning with Android 3.0, you can use the +{@link android.app.admin.DevicePolicyManager#setPasswordHistoryLength(android.content.ComponentName,int) setPasswordHistoryLength()} method to limit users' ability to reuse old passwords. This method takes a length parameter, which specifies how many old passwords are stored. When this policy is active, users cannot enter a new password that matches the last n passwords. This prevents users from using the same password over and over. This policy is typically used -in conjunction with +in conjunction with {@link android.app.admin.DevicePolicyManager#setPasswordExpirationTimeout(android.content.ComponentName,long) setPasswordExpirationTimeout()}, which forces users to update their passwords after a specified amount of time has elapsed.

        @@ -705,7 +705,7 @@ mDPM.setCameraDisabled(mDeviceAdminSample, mDisableCameraCheckbox.isChecked());<

        Storage encryption

        Beginning with Android 3.0, you can use the -{@link android.app.admin.DevicePolicyManager#setStorageEncryption(android.content.ComponentName,boolean) setStorageEncryption()} +{@link android.app.admin.DevicePolicyManager#setStorageEncryption(android.content.ComponentName,boolean) setStorageEncryption()} method to set a policy requiring encryption of the storage area, where supported.

        For example:

        diff --git a/docs/html/guide/topics/appwidgets/host.jd b/docs/html/guide/topics/appwidgets/host.jd index 169e388918e2a31a02ab5ca5ce466911bf45f146..7b00019239be13d741ebae8d87e20c33ebdb6f8e 100644 --- a/docs/html/guide/topics/appwidgets/host.jd +++ b/docs/html/guide/topics/appwidgets/host.jd @@ -4,7 +4,7 @@ page.tags=AppWidgetHost,home screen,launcher
        - +

        In this document

        1. Binding App Widgets @@ -32,58 +32,58 @@ to embed app widgets access to content. If you're building a Home replacement or a similar app, you can also allow the user to embed app widgets by implementing an {@link android.appwidget.AppWidgetHost}. -This is not something that most apps will ever need to do, but if you are -creating your own host, it's important to understand the contractual obligations +This is not something that most apps will ever need to do, but if you are +creating your own host, it's important to understand the contractual obligations a host implicitly agrees to.

          -

          This document focuses on the responsibilities involved in implementing a custom -{@link android.appwidget.AppWidgetHost}. For an example of how to implement an +

          This document focuses on the responsibilities involved in implementing a custom +{@link android.appwidget.AppWidgetHost}. For an example of how to implement an {@link android.appwidget.AppWidgetHost}, see the source code for the -Android Home screen +Android Home screen -Launcher. +Launcher. -

          Here is an overview of key classes and concepts involved in implementing a custom +

          Here is an overview of key classes and concepts involved in implementing a custom {@link android.appwidget.AppWidgetHost}:

            -
          • App Widget Host— - The {@link android.appwidget.AppWidgetHost} provides the interaction -with the AppWidget service for apps, like the home screen, that want to embed -app widgets in their UI. An {@link android.appwidget.AppWidgetHost} must have -an ID that is unique within the host's own package. This ID remains persistent +
          • App Widget Host— + The {@link android.appwidget.AppWidgetHost} provides the interaction +with the AppWidget service for apps, like the home screen, that want to embed +app widgets in their UI. An {@link android.appwidget.AppWidgetHost} must have +an ID that is unique within the host's own package. This ID remains persistent across all uses of the host. The ID is typically a hard-coded value that you assign in your application.
          • - +
          • App Widget ID— - Each app widget instance is assigned a unique ID at the time of binding -(see {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}, -discussed in more detail in Binding app widgets). -The unique ID is obtained by the host using {@link android.appwidget.AppWidgetHost#allocateAppWidgetId() allocateAppWidgetId()}. This ID is persistent across the lifetime of the widget, -that is, until it is deleted from the host. Any host-specific state (such as the -size and location of the widget) should be persisted by the hosting package and + Each app widget instance is assigned a unique ID at the time of binding +(see {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()}, +discussed in more detail in Binding app widgets). +The unique ID is obtained by the host using {@link android.appwidget.AppWidgetHost#allocateAppWidgetId() allocateAppWidgetId()}. This ID is persistent across the lifetime of the widget, +that is, until it is deleted from the host. Any host-specific state (such as the +size and location of the widget) should be persisted by the hosting package and associated with the app widget ID.
          • - -
          • App Widget Host View— - {@link android.appwidget.AppWidgetHostView} can be thought of as a frame -that the widget is wrapped in whenever it needs to be displayed. An app widget -is assigned to an {@link android.appwidget.AppWidgetHostView} every time the + +
          • App Widget Host View— + {@link android.appwidget.AppWidgetHostView} can be thought of as a frame +that the widget is wrapped in whenever it needs to be displayed. An app widget +is assigned to an {@link android.appwidget.AppWidgetHostView} every time the widget is inflated by the host.
          • Options Bundle— -The {@link android.appwidget.AppWidgetHost} uses the options bundle to communicate -information to the {@link android.appwidget.AppWidgetProvider} about how the -widget is being displayed (for example, size range, and whether the widget is on -a lockscreen or the home screen). This information allows the -{@link android.appwidget.AppWidgetProvider} to tailor the widget's contents +The {@link android.appwidget.AppWidgetHost} uses the options bundle to communicate +information to the {@link android.appwidget.AppWidgetProvider} about how the +widget is being displayed (for example, size range, and whether the widget is on +a lockscreen or the home screen). This information allows the +{@link android.appwidget.AppWidgetProvider} to tailor the widget's contents and appearance based on how and where it is displayed. -You use +You use {@link android.appwidget.AppWidgetHostView#updateAppWidgetOptions(android.os.Bundle) updateAppWidgetOptions()} -and +and {@link android.appwidget.AppWidgetHostView#updateAppWidgetSize updateAppWidgetSize()} -to modify an app widget's -bundle. Both of these methods trigger a callback to the +to modify an app widget's +bundle. Both of these methods trigger a callback to the {@link android.appwidget.AppWidgetProvider}.

          @@ -98,15 +98,15 @@ app is running on.

          Binding app widgets on Android 4.0 and lower

          -

          On devices running Android version 4.0 and lower, users add app widgets -via a system activity that allows users to select a widget. This implicitly -does a permission check—that is, by adding the app widget, the user is -implicitly granting permission to your app to add app widgets to the host. -Here is an example that illustrates -this approach, taken from the original -Launcher. In this snippet, an event handler invokes -{@link android.app.Activity#startActivityForResult(android.content.Intent,int) startActivityForResult()} -with the request code {@code REQUEST_PICK_APPWIDGET} in response to a +

          On devices running Android version 4.0 and lower, users add app widgets +via a system activity that allows users to select a widget. This implicitly +does a permission check—that is, by adding the app widget, the user is +implicitly granting permission to your app to add app widgets to the host. +Here is an example that illustrates +this approach, taken from the original +Launcher. In this snippet, an event handler invokes +{@link android.app.Activity#startActivityForResult(android.content.Intent,int) startActivityForResult()} +with the request code {@code REQUEST_PICK_APPWIDGET} in response to a user action:

          @@ -118,9 +118,9 @@ public void onClick(DialogInterface dialog, int which) {
               ...
                   case AddAdapter.ITEM_APPWIDGET: {
                       ...
          -            int appWidgetId = 
          +            int appWidgetId =
                               Launcher.this.mAppWidgetHost.allocateAppWidgetId();
          -            Intent pickIntent = 
          +            Intent pickIntent =
                               new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
                       pickIntent.putExtra
                               (AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
          @@ -135,7 +135,7 @@ public void onClick(DialogInterface dialog, int which) {
           app widget to your activity. In the following example, the activity responds
           by calling {@code addAppWidget()} to add the app widget:

          -
          public final class Launcher extends Activity 
          +
          public final class Launcher extends Activity
                   implements View.OnClickListener, OnLongClickListener {
               ...
               @Override
          @@ -152,7 +152,7 @@ by calling {@code addAppWidget()} to add the app widget:

          completeAddAppWidget(data, mAddItemCellInfo, !mDesktopLocked); break; } - } + } ... } }
          @@ -164,7 +164,7 @@ needs to be configured before it's added:

          int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET); - AppWidgetProviderInfo appWidget = + AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); if (appWidget.configure != null) { @@ -183,7 +183,7 @@ see Creating App Widget Configuration Activity.

          Once the app widget is ready, the next step is to do the -actual work of adding it to the workspace. The +actual work of adding it to the workspace. The original Launcher uses a method called {@code completeAddAppWidget()} to do this.

          @@ -201,12 +201,12 @@ binding. To use this improved process, your app must declare the

          But this is just the first step. At runtime the user must explicitly grant permission to your app to allow it to add app widgets to the host. To test whether your app has permission to add the widget, -you use the -{@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} -method. +you use the +{@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} +method. If {@link android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed bindAppWidgetIdIfAllowed()} returns {@code false}, your app must display a dialog prompting the -user to grant permission +user to grant permission ("allow" or "always allow," to cover all future app widget additions). This snippet gives an example of how to display the dialog:

          @@ -218,9 +218,9 @@ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options); startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
          -

          The host also has to check whether the user added +

          The host also has to check whether the user added an app widget that needs configuration. For more discussion of this topic, -see +see Creating an App Widget Configuration Activity.

          @@ -229,23 +229,23 @@ an App Widget Configuration Activity.

          @@ -273,7 +273,7 @@ from the Configuration Activity. This is a necessary step for many app widge they can be properly displayed.
        2. Every app widget specifies a minimum width and height in dps, as defined in the {@link android.appwidget.AppWidgetProviderInfo} metadata -(using {@link android.appwidget.AppWidgetProviderInfo#minWidth android:minWidth} and +(using {@link android.appwidget.AppWidgetProviderInfo#minWidth android:minWidth} and {@link android.appwidget.AppWidgetProviderInfo#minHeight android:minHeight}). Make sure that the widget is laid out with at least this many dps. For example, many hosts align icons and widgets in a grid. In this scenario, @@ -379,7 +379,7 @@ so it is not explicitly required to set this for a home screen host.

          for your app—for example, if your host is a home screen, ensure that the {@link android.appwidget.AppWidgetProviderInfo#widgetCategory android:widgetCategory} -attribute in the +attribute in the {@link android.appwidget.AppWidgetProviderInfo} metadata includes the flag {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN}. Similarly, for the lockscreen, ensure that field includes the flag {@link android.appwidget.AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}. For more diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd index c9575e025f053c9744535e41b67e3df3e9c39f2a..7d555ed2d8d89ff7af9fee073e399f3993d303d5 100644 --- a/docs/html/guide/topics/appwidgets/index.jd +++ b/docs/html/guide/topics/appwidgets/index.jd @@ -4,7 +4,7 @@ page.tags=home,AppWidgetProvider
          - +

          In this document

          1. The Basics
          2. @@ -21,7 +21,7 @@ Intents Activity
            1. Updating the App Widget -from +from the Configuration Activity
            @@ -33,7 +33,7 @@ from collections
          3. Keeping Collection Data Fresh
          4. -
          +
        @@ -50,10 +50,10 @@ collections

        App Widgets are miniature application views that can be embedded in other applications (such as the Home screen) and receive periodic updates. These views are -referred +referred to as Widgets in the user interface, and you can publish one with an App Widget provider. An application component -that is +that is able to hold other App Widgets is called an App Widget host. The screenshot below shows the Music App Widget.

        @@ -85,14 +85,14 @@ update frequency,
        Defines the basic methods that allow you to programmatically interface with the App Widget, based on broadcast events. Through it, you will receive broadcasts when the -App Widget is updated, +App Widget is updated, enabled, disabled and deleted.
        View layout
        Defines the initial layout for the App Widget, defined in XML.

        Additionally, you can implement an App Widget configuration Activity. This is -an optional +an optional {@link android.app.Activity} that launches when the user adds your App Widget and allows him or her to modify App Widget settings at create-time.

        @@ -117,7 +117,7 @@ application's

        The <receiver> element requires the -android:name +android:name attribute, which specifies the {@link android.appwidget.AppWidgetProvider} used by the App Widget.

        @@ -133,7 +133,7 @@ automatically sends all other App Widget broadcasts to the AppWidgetProvider as necessary.

        The <meta-data> element specifies the -{@link android.appwidget.AppWidgetProviderInfo} resource and requires the +{@link android.appwidget.AppWidgetProviderInfo} resource and requires the following attributes:

        • android:name - Specifies the metadata name. Use @@ -141,21 +141,21 @@ following attributes:

          to identify the data as the {@link android.appwidget.AppWidgetProviderInfo} descriptor.
        • android:resource - Specifies the {@link -android.appwidget.AppWidgetProviderInfo} +android.appwidget.AppWidgetProviderInfo} resource location.

        Adding the AppWidgetProviderInfo Metadata

        -

        The {@link android.appwidget.AppWidgetProviderInfo} defines the essential +

        The {@link android.appwidget.AppWidgetProviderInfo} defines the essential qualities of an App Widget, such as its minimum layout dimensions, its initial layout resource, how often to update the App Widget, and (optionally) a configuration Activity to launch at create-time. Define the AppWidgetProviderInfo object in an XML resource using a single <appwidget-provider> element and save it in the project's -res/xml/ +res/xml/ folder.

        For example:

        @@ -167,7 +167,7 @@ folder.

        android:updatePeriodMillis="86400000" android:previewImage="@drawable/preview" android:initialLayout="@layout/example_appwidget" - android:configure="com.example.android.ExampleAppWidgetConfigure" + android:configure="com.example.android.ExampleAppWidgetConfigure" android:resizeMode="horizontal|vertical" android:widgetCategory="home_screen"> </appwidget-provider> @@ -206,33 +206,33 @@ folder.

      • The updatePeriodMillis attribute defines how often the App Widget framework should request an update from the {@link -android.appwidget.AppWidgetProvider} by calling the -{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()} +android.appwidget.AppWidgetProvider} by calling the +{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()} callback method. The actual update is not guaranteed to occur exactly on time with this value and we suggest updating as infrequently as possible—perhaps no more than once an hour to conserve the battery. You might also allow the user to adjust the frequency in a configuration—some people might want a stock ticker to update every 15 -minutes, or maybe only four times a day. +minutes, or maybe only four times a day.

        Note: If the device is asleep when it -is time for an update +is time for an update (as defined by updatePeriodMillis), then the device will -wake up in order +wake up in order to perform the update. If you don't update more than once per hour, this -probably won't +probably won't cause significant problems for the battery life. If, however, you need -to update more +to update more frequently and/or you do not need to update while the device is asleep, -then you can instead +then you can instead perform updates based on an alarm that will not wake the device. To do -so, set an alarm with +so, set an alarm with an Intent that your AppWidgetProvider receives, using the {@link -android.app.AlarmManager}. +android.app.AlarmManager}. Set the alarm type to either {@link -android.app.AlarmManager#ELAPSED_REALTIME} or +android.app.AlarmManager#ELAPSED_REALTIME} or {@link android.app.AlarmManager#RTC}, which will only deliver the alarm when the device is awake. Then set -updatePeriodMillis to +updatePeriodMillis to zero ("0").

      • The initialLayout attribute points to the layout resource @@ -244,7 +244,7 @@ android.app.Activity} to launch when Widget properties. This is optional (read Creating an App Widget Configuration Activity below).
      • - +
      • The previewImage attribute specifies a preview of what the app widget will look like after it's configured, which the user sees when selecting the app widget. If not supplied, the user instead sees your @@ -255,7 +255,7 @@ using previewImage, see Setting a Preview Image. Introduced in Android 3.0.
      • The autoAdvanceViewId attribute specifies the view ID of the -app widget subview that should be auto-advanced by the widget's host. Introduced in Android 3.0.
      • +app widget subview that should be auto-advanced by the widget's host. Introduced in Android 3.0.
      • The resizeMode attribute specifies the rules by which a widget can be resized. You use this attribute to make homescreen widgets @@ -264,7 +264,7 @@ widget to show its resize handles, then drag the horizontal and/or vertical handles to change the size on the layout grid. Values for the resizeMode attribute include "horizontal", "vertical", and "none". To declare a widget as resizeable horizontally and vertically, supply the value -"horizontal|vertical". Introduced in Android 3.1.
      • +"horizontal|vertical". Introduced in Android 3.1.
      • The minResizeHeight attribute specifies the minimum height (in dps) to which the widget can be resized. This field has no effect if it is greater than {@code minHeight} or if @@ -296,7 +296,7 @@ View objects listed below, but before you begin designing your App Widget, please read and understand the App Widget -Design +Design Guidelines.

        Creating the App Widget layout is simple if you're @@ -306,7 +306,7 @@ However, you must be aware that App Widget layouts are based on {@link android.widget.RemoteViews}, which do not support every kind of layout or view widget.

        -

        A RemoteViews object (and, consequently, an App Widget) can support the +

        A RemoteViews object (and, consequently, an App Widget) can support the following layout classes:

          @@ -334,7 +334,7 @@ following layout classes:

          Descendants of these classes are not supported.

          -

          RemoteViews also supports {@link android.view.ViewStub}, which is an invisible, zero-sized View you can use +

          RemoteViews also supports {@link android.view.ViewStub}, which is an invisible, zero-sized View you can use to lazily inflate layout resources at runtime.

          @@ -386,7 +386,7 @@ to lazily inflate layout resources at runtime.

      - {@link android.appwidget.AppWidgetProvider#onAppWidgetOptionsChanged onAppWidgetOptionsChanged()} + {@link android.appwidget.AppWidgetProvider#onAppWidgetOptionsChanged onAppWidgetOptionsChanged()}
      This is called when the widget is first placed and any time the widget is resized. You can use this callback to show or hide content based on the widget's size ranges. You get the size ranges by calling {@link android.appwidget.AppWidgetManager#getAppWidgetOptions getAppWidgetOptions()}, which returns a {@link android.os.Bundle} that includes the following:

        -
      • {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_WIDTH}—Contains +
      • {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_WIDTH}—Contains the lower bound on the current width, in dp units, of a widget instance.
      • -
      • {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_HEIGHT}—Contains +
      • {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_HEIGHT}—Contains the lower bound on the current height, in dp units, of a widget instance.
      • {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_WIDTH}—Contains the upper bound on the current width, in dp units, of a widget instance.
      • -
      • {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_HEIGHT}—Contains +
      • {@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_HEIGHT}—Contains the upper bound on the current width, in dp units, of a widget instance.
      @@ -444,34 +444,34 @@ This callback was introduced in API Level 16 (Android 4.1). If you implement thi host.
      {@link android.appwidget.AppWidgetProvider#onEnabled(Context)}
      This is called when an instance the App Widget is created for the first -time. For example, if the user +time. For example, if the user adds two instances of your App Widget, this is only called the first time. If you need to open a new database or perform other setup that only needs to -occur once - for all App Widget instances, then this is a good place to do it.
      +occur once + for all App Widget instances, then this is a good place to do it.
      {@link android.appwidget.AppWidgetProvider#onDisabled(Context)}
      This is called when the last instance of your App Widget is deleted from -the App Widget host. - This is where you should clean up any work done in - {@link android.appwidget.AppWidgetProvider#onEnabled(Context)}, - such as delete a temporary database.
      +the App Widget host. + This is where you should clean up any work done in + {@link android.appwidget.AppWidgetProvider#onEnabled(Context)}, + such as delete a temporary database.
      {@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)}
      This is called for every broadcast and before each of the above callback methods. You normally don't need to implement this method because the default -AppWidgetProvider - implementation filters all App Widget broadcasts and calls the above - methods as appropriate.
      +AppWidgetProvider + implementation filters all App Widget broadcasts and calls the above + methods as appropriate. -

      The most important AppWidgetProvider callback is -{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} +

      The most important AppWidgetProvider callback is +{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} because it is called when each App Widget is added to a host (unless you use a configuration Activity). If your App Widget accepts any user interaction events, then you need to register the event handlers in this callback. If your App Widget doesn't create temporary -files or databases, or perform other work that requires clean-up, then -{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} +files or databases, or perform other work that requires clean-up, then +{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} may be the only callback method you need to define. For example, if you want an App Widget with a button that launches an Activity when clicked, you could use the following @@ -503,9 +503,9 @@ public class ExampleAppWidgetProvider extends AppWidgetProvider { } -

      This AppWidgetProvider defines only the +

      This AppWidgetProvider defines only the {@link -android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} +android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} method for the purpose of defining a {@link android.app.PendingIntent} that launches an {@link android.app.Activity} and attaching it to the App Widget's button with {@link @@ -528,8 +528,8 @@ running after the callback methods return (see {@link android.content.BroadcastReceiver} for information about the broadcast lifecycle). If your App Widget setup process can take several seconds (perhaps while performing web requests) and you require that your process continues, -consider starting a {@link android.app.Service} in the -{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} +consider starting a {@link android.app.Service} in the +{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} method. From within the Service, you can perform your own updates to the App Widget without worrying about the AppWidgetProvider closing down due to an Application @@ -537,7 +537,7 @@ Not Responding (ANR) error. See the Wiktionary sample's AppWidgetProvider for an example of an App Widget running a {@link android.app.Service}.

      -

      Also see the Also see the ExampleAppWidgetProvider.java sample class.

      @@ -546,9 +546,9 @@ sample class.

      {@link android.appwidget.AppWidgetProvider} is just a convenience class. If you would like -to receive the App Widget broadcasts directly, you can implement your own -{@link android.content.BroadcastReceiver} or override the -{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)} callback. +to receive the App Widget broadcasts directly, you can implement your own +{@link android.content.BroadcastReceiver} or override the +{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)} callback. The Intents you need to care about are as follows:

      • {@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE}
      • @@ -565,11 +565,11 @@ The Intents you need to care about are as follows:

        If you would like the user to configure settings when he or she adds a new App Widget, you can create an App Widget configuration Activity. This {@link -android.app.Activity} +android.app.Activity} will be automatically launched by the App Widget host and allows the user to configure available settings for the App Widget at create-time, such as the App Widget -color, size, +color, size, update period or other functionality settings.

        The configuration Activity should be declared as a normal Activity in the @@ -588,8 +588,8 @@ so the Activity needs to accept this Intent. For example:

        Also, the Activity must be declared in the AppWidgetProviderInfo XML file, -with the -android:configure attribute (see Adding +with the +android:configure attribute (see Adding the AppWidgetProviderInfo Metadata above). For example, the configuration Activity can be declared like this:

        @@ -597,13 +597,13 @@ can be declared like this:

         <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
             ...
        -    android:configure="com.example.android.ExampleAppWidgetConfigure" 
        +    android:configure="com.example.android.ExampleAppWidgetConfigure"
             ... >
         </appwidget-provider>
         

        Notice that the Activity is declared with a fully-qualified namespace, -because +because it will be referenced from outside your package scope.

        That's all you need to get started with a configuration Activity. Now all you @@ -612,21 +612,21 @@ Activity. There are, however, two important things to remember when you implement the Activity:

        • The App Widget host calls the configuration Activity and the configuration -Activity should always +Activity should always return a result. The result should include the App Widget ID passed by the Intent that launched the Activity (saved in the Intent extras as {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}).
        • -
        • The - {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} +
        • The + {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} method will not be called when the App Widget is created (the system will not send the ACTION_APPWIDGET_UPDATE broadcast when a configuration Activity is launched). It is the responsibility of the configuration Activity to -request an update from the - AppWidgetManager when the App Widget is first created. However, -{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} +request an update from the + AppWidgetManager when the App Widget is first created. However, +{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} will be called for subsequent updates—it is only skipped the first time.
        @@ -641,8 +641,8 @@ configuration Activity

        When an App Widget uses a configuration Activity, it is the responsibility of the Activity -to update the App Widget when configuration is complete. -You can do so by requesting an update directly from the +to update the App Widget when configuration is complete. +You can do so by requesting an update directly from the {@link android.appwidget.AppWidgetManager}.

        Here's a summary of the procedure to properly update the App Widget and close @@ -655,7 +655,7 @@ Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { mAppWidgetId = extras.getInt( - AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); } @@ -696,7 +696,7 @@ reaching the end, the App Widget host is notified that the configuration was cancelled and the App Widget will not be added.

        -

        See the See the ExampleAppWidgetConfigure.java sample class in ApiDemos for an example.

        @@ -708,7 +708,7 @@ sample class in ApiDemos for an example.

        android.appwidget.AppWidgetProviderInfo#previewImage} field, which specifies a preview of what the app widget looks like. This preview is shown to the user from the widget picker. If this field is not supplied, the app widget's icon is used for -the preview.

        +the preview.

        This is how you specify this setting in XML:

        @@ -742,12 +742,12 @@ list. For an example, see the Gmail app widget.
        {@link android.widget.GridView}
        A view that shows items in two-dimensional scrolling grid. For an example, see the Bookmarks app -widget.
        +widget.
        {@link android.widget.StackView}
        A stacked card view (kind of like a rolodex), where the user can flick the front card up/down to see the previous/next card, respectively. Examples include -the YouTube and Books app widgets. 
        +the YouTube and Books app widgets. 
        {@link android.widget.AdapterViewFlipper}
        An adapter-backed simple {@link @@ -764,7 +764,7 @@ must include extra architecture to support their use in app widgets. In the context of an app widget, the {@link android.widget.Adapter} is replaced by a {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, which is simply a thin wrapper around the {@link android.widget.Adapter} -interface. +interface. When requested for a specific item in the collection, the {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} creates @@ -782,7 +782,7 @@ interface for an adapter between a collection view (such as {@link android.widget.ListView}, {@link android.widget.GridView}, and so on) and the underlying data for that view. From the StackView Widget -sample, here is an example of the boilerplate code you use to implement +sample, here is an example of the boilerplate code you use to implement this service and interface:

        @@ -813,13 +813,13 @@ sample:

        This sample consists of a stack of 10 views, which display the values "0!" through "9!" The sample -app widget has these primary behaviors:

        +app widget has these primary behaviors:

        • The user can vertically fling the top view in the app widget to display the next or previous view. This is a built-in StackView -behavior.
        • +behavior.
        • Without any user interaction, the app widget automatically advances through @@ -828,17 +828,17 @@ its views in sequence, like a slide show. This is due to the setting res/xml/stackwidgetinfo.xml file. This setting applies to the view ID, which in this case is the view ID of the stack view.
        • - +
        • If the user touches the top view, the app widget displays the {@link android.widget.Toast} message "Touched view n," where n is the index (position) of the touched view. For more discussion of -how this is implemented, see +how this is implemented, see Adding behavior to individual items.

        Implementing app widgets with collections

        -

        To implement an app widget with collections, you follow the same basic steps +

        To implement an app widget with collections, you follow the same basic steps you would use to implement any app widget. The following sections describe the additional steps you need to perform to implement an app widget with collections.

        @@ -940,7 +940,7 @@ collection:

        int[] appWidgetIds) { // update each of the app widgets with the remote adapter for (int i = 0; i < appWidgetIds.length; ++i) { - + // Set up the intent that starts the StackViewService, which will // provide the views for this collection. Intent intent = new Intent(context, StackWidgetService.class); @@ -949,13 +949,13 @@ int[] appWidgetIds) { intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); // Instantiate the RemoteViews object for the app widget layout. RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout); - // Set up the RemoteViews object to use a RemoteViews adapter. + // Set up the RemoteViews object to use a RemoteViews adapter. // This adapter connects // to a RemoteViewsService through the specified intent. // This is how you populate the data. rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent); - - // The empty view is displayed when the collection has no items. + + // The empty view is displayed when the collection has no items. // It should be in the same layout used to instantiate the RemoteViews // object above. rv.setEmptyView(R.id.stack_view, R.id.empty_view); @@ -963,12 +963,12 @@ int[] appWidgetIds) { // // Do additional processing specific to this app widget... // - - appWidgetManager.updateAppWidget(appWidgetIds[i], rv); + + appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); } - +

        RemoteViewsService class

        As described above, your {@link android.widget.RemoteViewsService} subclass provides the {@link android.widget.RemoteViewsService.RemoteViewsFactory -RemoteViewsFactory} used to populate the remote collection view.

        +RemoteViewsFactory} used to populate the remote collection view.

        Specifically, you need to perform these steps:

        @@ -993,7 +993,7 @@ perform these steps:

      • Subclass {@link android.widget.RemoteViewsService}. {@link android.widget.RemoteViewsService} is the service through which a remote adapter can request {@link android.widget.RemoteViews}.
      • - +
      • In your {@link android.widget.RemoteViewsService} subclass, include a class that implements the {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} @@ -1027,12 +1027,12 @@ functions as an adapter to glue the data to the remote collection view.

        The two most important methods you need to implement for your {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} -subclass are +subclass are {@link android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} and {@link android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()} -.

        +.

        The system calls {@link android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} when @@ -1047,7 +1047,7 @@ array and the text they contain is displayed

        Here is an excerpt from the StackView Widget -sample's +sample's {@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} implementation that shows portions of the {@link android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} @@ -1081,7 +1081,7 @@ RemoteViewsService.RemoteViewsFactory { RemoteViewsFactory} method {@link android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()} returns a {@link android.widget.RemoteViews} object corresponding to the data at -the specified position in the data set. Here is an excerpt from +the specified position in the data set. Here is an excerpt from the StackView Widget sample's {@link @@ -1089,8 +1089,8 @@ android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} implementation:

        public RemoteViews getViewAt(int position) {
        -   
        -    // Construct a remote views item based on the app widget item XML file, 
        +
        +    // Construct a remote views item based on the app widget item XML file,
             // and set the text based on the position.
             RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
             rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
        @@ -1104,7 +1104,7 @@ implementation:

        The above sections show you how to bind your data to your app widget collection. But what if you want to add dynamic behavior to the individual items -in your collection view?

        +in your collection view?

        As described in Using the AppWidgetProvider Class, you normally use {@link @@ -1122,7 +1122,7 @@ android.widget.RemoteViews#setOnClickFillInIntent(int, android.content.Intent) setOnClickFillInIntent()}. This entails setting up up a pending intent template for your collection view, and then setting a fill-in intent on each item in the collection via your {@link android.widget.RemoteViewsService.RemoteViewsFactory -RemoteViewsFactory}.

        +RemoteViewsFactory}.

        This section uses the StackView Widget sample to describe how to add behavior to individual items. In the TOAST_ACTION.

      • When the user touches a view, the intent is fired and it broadcasts TOAST_ACTION.
      • - +
      • This broadcast is intercepted by the StackWidgetProvider's {@link android.appwidget.AppWidgetProvider#onReceive(android.content.Context, android.content.Intent) onReceive()} method, and the app widget displays the @@ -1154,7 +1154,7 @@ href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget sample uses a broadcast, but typically an app widget would simply launch an activity in a scenario like this one.

        -
        Setting up the pending intent template
        +
        Setting up the pending intent template

        The StackWidgetProvider ({@link android.appwidget.AppWidgetProvider} subclass) sets up a pending intent. @@ -1162,7 +1162,7 @@ Individuals items of a collection cannot set up their own pending intents. Instead, the collection as a whole sets up a pending intent template, and the individual items set a fill-in intent to create unique behavior on an item-by-item -basis.

        +basis.

        This class also receives the broadcast that is sent when the user touches a view. It processes this event in its {@link @@ -1179,7 +1179,7 @@ message for the current view.

            ... // Called when the BroadcastReceiver receives an Intent broadcast. - // Checks to see whether the intent's action is TOAST_ACTION. If it is, the app widget + // Checks to see whether the intent's action is TOAST_ACTION. If it is, the app widget // displays a Toast message for the current item. @Override public void onReceive(Context context, Intent intent) { @@ -1192,12 +1192,12 @@ message for the current view.

            }     super.onReceive(context, intent); } - + @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // update each of the app widgets with the remote adapter     for (int i = 0; i < appWidgetIds.length; ++i) { - +     // Sets up the intent that points to the StackViewService that will     // provide the views for this collection.     Intent intent = new Intent(context, StackWidgetService.class); @@ -1207,7 +1207,7 @@ message for the current view.

            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));     RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);     rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent); - +     // The empty view is displayed when the collection has no items. It should be a sibling     // of the collection view.     rv.setEmptyView(R.id.stack_view, R.id.empty_view); @@ -1227,13 +1227,13 @@ message for the current view.

            PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,     PendingIntent.FLAG_UPDATE_CURRENT);     rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent); - +     appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); } } - +
        Setting the fill-in Intent

        Your {@link android.widget.RemoteViewsService.RemoteViewsFactory @@ -1274,17 +1274,17 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {        ...     }     ... - - // Given the position (index) of a WidgetItem in the array, use the item's text value in + + // Given the position (index) of a WidgetItem in the array, use the item's text value in // combination with the app widget item XML file to construct a RemoteViews object.     public RemoteViews getViewAt(int position) {         // position will always range from 0 to getCount() - 1. - +         // Construct a RemoteViews item based on the app widget item XML file, and set the         // text based on the position.         RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);         rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text); - +         // Next, set a fill-intent, which will be used to fill in the pending intent template         // that is set on the collection view in StackWidgetProvider.         Bundle extras = new Bundle(); @@ -1294,9 +1294,9 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { // Make it possible to distinguish the individual on-click // action of a given item     rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent); - +     ... - +     // Return the RemoteViews object.     return rv; } diff --git a/docs/html/guide/topics/connectivity/bluetooth-le.jd b/docs/html/guide/topics/connectivity/bluetooth-le.jd index 3d606863052a25a6cb715573e1397c73628f45ff..ba742eeef8a2a5349fadadffb71f3b4a3f2a5473 100644 --- a/docs/html/guide/topics/connectivity/bluetooth-le.jd +++ b/docs/html/guide/topics/connectivity/bluetooth-le.jd @@ -171,7 +171,7 @@ include the following in your app's manifest:

        However, if you want to make your app available to devices that don't support BLE, -you should still include this element in your app's manifest, but set {@code required="false"}. +you should still include this element in your app's manifest, but set {@code required="false"}. Then at run-time you can determine BLE availability by using {@link android.content.pm.PackageManager#hasSystemFeature PackageManager.hasSystemFeature()}: diff --git a/docs/html/guide/topics/connectivity/bluetooth.jd b/docs/html/guide/topics/connectivity/bluetooth.jd index 96008c5c5701a619cb70b0d0fcb86e71a77dc5b5..42229fd3733121b02fb370c6cb358c87ef069991 100644 --- a/docs/html/guide/topics/connectivity/bluetooth.jd +++ b/docs/html/guide/topics/connectivity/bluetooth.jd @@ -4,55 +4,55 @@ page.tags=wireless,bluetoothadapter,bluetoothdevice

        - +

        In this document

        -
          +
          1. The Basics
          2. Bluetooth Permissions
          3. -
          4. Setting Up Bluetooth
          5. -
          6. Finding Devices -
              -
            1. Querying paired devices
            2. -
            3. Discovering devices
            4. -
          7. -
          8. Connecting Devices -
              -
            1. Connecting as a server
            2. -
            3. Connecting as a client
            4. -
          9. +
          10. Setting Up Bluetooth
          11. +
          12. Finding Devices +
              +
            1. Querying paired devices
            2. +
            3. Discovering devices
            4. +
          13. +
          14. Connecting Devices +
              +
            1. Connecting as a server
            2. +
            3. Connecting as a client
            4. +
          15. Managing a Connection
          16. -
          17. Working with Profiles +
          18. Working with Profiles
            1. Vendor-specific AT commands
            2. Health Device Profile
          19. -
          - -

          Key classes

          -
            -
          1. {@link android.bluetooth.BluetoothAdapter}
          2. -
          3. {@link android.bluetooth.BluetoothDevice}
          4. -
          5. {@link android.bluetooth.BluetoothSocket}
          6. -
          7. {@link android.bluetooth.BluetoothServerSocket}
          8. -
          - -

          Related samples

          -
            -
          1. Bluetooth Chat
          2. +
          + +

          Key classes

          +
            +
          1. {@link android.bluetooth.BluetoothAdapter}
          2. +
          3. {@link android.bluetooth.BluetoothDevice}
          4. +
          5. {@link android.bluetooth.BluetoothSocket}
          6. +
          7. {@link android.bluetooth.BluetoothServerSocket}
          8. +
          + +

          Related samples

          +
            +
          1. Bluetooth Chat
          2. Bluetooth HDP (Health Device Profile)
          3. -
          - -
        -
        - - + + + + + +

        The Android platform includes support for the Bluetooth network stack, which allows a device to wirelessly exchange data with other Bluetooth devices. The application framework provides access to the Bluetooth functionality through the Android Bluetooth APIs. These APIs let applications wirelessly connect to other Bluetooth devices, enabling point-to-point and multipoint -wireless features.

        - +wireless features.

        +

        Using the Bluetooth APIs, an Android application can perform the following:

      • + +
        {@link android.bluetooth.BluetoothDevice}
        Represents a remote Bluetooth device. Use this to request a connection with a remote device through a {@link android.bluetooth.BluetoothSocket} or query information about the -device such as its name, address, class, and bonding state.
        - -
        {@link android.bluetooth.BluetoothSocket}
        +device such as its name, address, class, and bonding state. + +
        {@link android.bluetooth.BluetoothSocket}
        Represents the interface for a Bluetooth socket (similar to a TCP {@link java.net.Socket}). This is the connection point that allows an application to exchange data with another Bluetooth device via InputStream -and OutputStream.
        - -
        {@link android.bluetooth.BluetoothServerSocket}
        +and OutputStream. + +
        {@link android.bluetooth.BluetoothServerSocket}
        Represents an open server socket that listens for incoming requests (similar to a TCP {@link java.net.ServerSocket}). In order to connect two Android devices, one device must open a server socket with this class. When a remote Bluetooth device makes a connection request to the this device, the {@link android.bluetooth.BluetoothServerSocket} will return a connected {@link android.bluetooth.BluetoothSocket} when the -connection is accepted.
        - -
        {@link android.bluetooth.BluetoothClass}
        +connection is accepted. + +
        {@link android.bluetooth.BluetoothClass}
        Describes the general characteristics and capabilities of a Bluetooth device. This is a read-only set of properties that define the device's major and minor device classes and its services. However, this does not reliably describe all Bluetooth profiles and services supported by the device, but is useful as a -hint to the device type.
        - +hint to the device type. +
        {@link android.bluetooth.BluetoothProfile}
        An interface that represents a Bluetooth profile. A Bluetooth profile is a wireless interface specification for Bluetooth-based communication between devices. An example is the Hands-Free profile. For more discussion of profiles, see Working with Profiles
        +href="#Profiles">Working with Profiles
        {@link android.bluetooth.BluetoothHeadset}
        Provides support for Bluetooth headsets to be used with mobile phones. This includes both Bluetooth -Headset and Hands-Free (v1.5) profiles.
        +Headset and Hands-Free (v1.5) profiles.
        {@link android.bluetooth.BluetoothA2dp}
        Defines how high quality audio can be streamed from one device to another over a Bluetooth connection. -"A2DP" stands for Advanced Audio Distribution Profile.
        +"A2DP" stands for Advanced Audio Distribution Profile.
        {@link android.bluetooth.BluetoothHealth}
        Represents a Health Device Profile proxy that controls the Bluetooth service.
        @@ -146,23 +146,23 @@ application’s registration state and Bluetooth channel state.
        {@link android.bluetooth.BluetoothHealthAppConfiguration}
        -
        Represents an application configuration that the Bluetooth Health third-party +
        Represents an application configuration that the Bluetooth Health third-party application registers to communicate with a remote Bluetooth health -device.
        +device.
        {@link android.bluetooth.BluetoothProfile.ServiceListener}
        An interface that notifies {@link android.bluetooth.BluetoothProfile} IPC clients when they have been connected to or disconnected from the service (that is, the internal service that runs a particular profile).
        - - - - - - -

        Bluetooth Permissions

        - + + + + + + +

        Bluetooth Permissions

        +

        In order to use Bluetooth features in your application, you must declare the Bluetooth permission {@link android.Manifest.permission#BLUETOOTH}. You need this permission to perform any Bluetooth communication, @@ -175,40 +175,40 @@ ability to discover local Bluetooth devices. The other abilities granted by this permission should not be used, unless the application is a "power manager" that will modify Bluetooth settings upon user request. Note: If you use {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission, then you must -also have the {@link android.Manifest.permission#BLUETOOTH} permission.

        - +also have the {@link android.Manifest.permission#BLUETOOTH} permission.

        +

        Declare the Bluetooth permission(s) in your application manifest file. For -example:

        - -
         
        +example:

        + +
         <manifest ... >
           <uses-permission android:name="android.permission.BLUETOOTH" />
           ...
         </manifest>
        -
        - +
        +

        See the <uses-permission> -reference for more information about declaring application permissions.

        - - -

        Setting Up Bluetooth

        - -
        - +href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission> +reference for more information about declaring application permissions.

        + + +

        Setting Up Bluetooth

        + +
        + Figure 1: The enabling Bluetooth dialog. -
        - +
        +

        Before your application can communicate over Bluetooth, you need to verify -that Bluetooth is supported on the device, and if so, ensure that it is enabled.

        - +that Bluetooth is supported on the device, and if so, ensure that it is enabled.

        +

        If Bluetooth is not supported, then you should gracefully disable any Bluetooth features. If Bluetooth is supported, but disabled, then you can request that the user enable Bluetooth without leaving your application. This setup is -accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.

        - - -
          +accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.

          + + +
          1. Get the {@link android.bluetooth.BluetoothAdapter}

            The {@link android.bluetooth.BluetoothAdapter} is required for any and all Bluetooth activity. To get the {@link android.bluetooth.BluetoothAdapter}, call the static {@link @@ -217,15 +217,15 @@ android.bluetooth.BluetoothAdapter#getDefaultAdapter()} method. This returns a Bluetooth adapter (the Bluetooth radio). There's one Bluetooth adapter for the entire system, and your application can interact with it using this object. If {@link android.bluetooth.BluetoothAdapter#getDefaultAdapter()} returns null, -then the device does not support Bluetooth and your story ends here. For example:

            -
             
            +then the device does not support Bluetooth and your story ends here. For example:

            +
             BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
             if (mBluetoothAdapter == null) {
                 // Device does not support Bluetooth
             }
            -
            -
          2. - + + +
          3. Enable Bluetooth

            Next, you need to ensure that Bluetooth is enabled. Call {@link android.bluetooth.BluetoothAdapter#isEnabled()} to check whether Bluetooth is @@ -234,17 +234,17 @@ request that Bluetooth be enabled, call {@link android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()} with the {@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_ENABLE} action Intent. This will issue a request to enable Bluetooth through the system settings (without -stopping your application). For example:

            -
             
            +stopping your application). For example:

            +
             if (!mBluetoothAdapter.isEnabled()) {
                 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                 startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
             }
            -
            - +
            +

            A dialog will appear requesting user permission to enable Bluetooth, as shown in Figure 1. If the user responds "Yes," the system will begin to enable Bluetooth -and focus will return to your application once the process completes (or fails).

            +and focus will return to your application once the process completes (or fails).

            The {@code REQUEST_ENABLE_BT} constant passed to {@link android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()} is a locally @@ -259,9 +259,9 @@ android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()} callback. If Bluetooth was not enabled due to an error (or the user responded "No") then the result code is {@link android.app.Activity#RESULT_CANCELED}.

            -
          4. -
          - + +
        +

        Optionally, your application can also listen for the {@link android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED} broadcast Intent, which the system will broadcast whenever the Bluetooth state has changed. This broadcast contains @@ -273,21 +273,21 @@ android.bluetooth.BluetoothAdapter#STATE_ON}, {@link android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}, and {@link android.bluetooth.BluetoothAdapter#STATE_OFF}. Listening for this broadcast can be useful to detect changes made to the Bluetooth state while your -app is running.

        - +app is running.

        +

        Tip: Enabling discoverability will automatically enable Bluetooth. If you plan to consistently enable device discoverability before performing Bluetooth activity, you can skip step 2 above. Read about enabling discoverability, -below.

        - - -

        Finding Devices

        - +below.

        + + +

        Finding Devices

        +

        Using the {@link android.bluetooth.BluetoothAdapter}, you can find remote Bluetooth devices either through device discovery or by querying the list of paired (bonded) -devices.

        - +devices.

        +

        Device discovery is a scanning procedure that searches the local area for Bluetooth enabled devices and then requesting some information about each one (this is sometimes referred to as "discovering," "inquiring" or "scanning"). @@ -296,15 +296,15 @@ request only if it is currently enabled to be discoverable. If a device is discoverable, it will respond to the discovery request by sharing some information, such as the device name, class, and its unique MAC address. Using this information, the device performing discovery can then choose to initiate a -connection to the discovered device.

        - +connection to the discovered device.

        +

        Once a connection is made with a remote device for the first time, a pairing request is automatically presented to the user. When a device is paired, the basic information about that device (such as the device name, class, and MAC address) is saved and can be read using the Bluetooth APIs. Using the known MAC address for a remote device, a connection can be initiated with it at -any time without performing discovery (assuming the device is within range).

        - +any time without performing discovery (assuming the device is within range).

        +

        Remember there is a difference between being paired and being connected. To be paired means that two devices are aware of each other's existence, have a shared link-key that can be used for authentication, and are capable of @@ -312,28 +312,28 @@ establishing an encrypted connection with each other. To be connected means that the devices currently share an RFCOMM channel and are able to transmit data with each other. The current Android Bluetooth API's require devices to be paired before an RFCOMM connection can be established. (Pairing is automatically performed -when you initiate an encrypted connection with the Bluetooth APIs.)

        - +when you initiate an encrypted connection with the Bluetooth APIs.)

        +

        The following sections describe how to find devices that have been paired, or -discover new devices using device discovery.

        - +discover new devices using device discovery.

        +

        Note: Android-powered devices are not discoverable by default. A user can make the device discoverable for a limited time through the system settings, or an application can request that the user enable discoverability without leaving the -application. How to enable discoverability -is discussed below.

        - - -

        Querying paired devices

        - +application. How to enable discoverability +is discussed below.

        + + +

        Querying paired devices

        +

        Before performing device discovery, its worth querying the set of paired devices to see if the desired device is already known. To do so, call {@link android.bluetooth.BluetoothAdapter#getBondedDevices()}. This will return a Set of {@link android.bluetooth.BluetoothDevice}s representing paired devices. For example, you can query all paired devices and then -show the name of each device to the user, using an ArrayAdapter:

        -
         
        +show the name of each device to the user, using an ArrayAdapter:

        +
         Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
         // If there are paired devices
         if (pairedDevices.size() > 0) {
        @@ -343,24 +343,24 @@ if (pairedDevices.size() > 0) {
                 mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
             }
         }
        -
        - +
        +

        All that's needed from the {@link android.bluetooth.BluetoothDevice} object in order to initiate a connection is the MAC address. In this example, it's saved as a part of an ArrayAdapter that's shown to the user. The MAC address can later be extracted in order to initiate the connection. You can learn more about creating -a connection in the section about Connecting Devices.

        - - -

        Discovering devices

        - +a connection in the section about Connecting Devices.

        + + +

        Discovering devices

        +

        To start discovering devices, simply call {@link android.bluetooth.BluetoothAdapter#startDiscovery()}. The process is asynchronous and the method will immediately return with a boolean indicating whether discovery has successfully started. The discovery process usually involves an inquiry scan of about 12 seconds, followed by a page scan of -each found device to retrieve its Bluetooth name.

        - +each found device to retrieve its Bluetooth name.

        +

        Your application must register a BroadcastReceiver for the {@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent in order to receive information about each @@ -371,8 +371,8 @@ Intent carries the extra fields {@link android.bluetooth.BluetoothDevice#EXTRA_CLASS}, containing a {@link android.bluetooth.BluetoothDevice} and a {@link android.bluetooth.BluetoothClass}, respectively. For example, here's how you can -register to handle the broadcast when devices are discovered:

        -
         
        +register to handle the broadcast when devices are discovered:

        +
         // Create a BroadcastReceiver for ACTION_FOUND
         private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
             public void onReceive(Context context, Intent intent) {
        @@ -389,15 +389,15 @@ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         // Register the BroadcastReceiver
         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
         registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
        -
        - +
        +

        All that's needed from the {@link android.bluetooth.BluetoothDevice} object in order to initiate a connection is the MAC address. In this example, it's saved as a part of an ArrayAdapter that's shown to the user. The MAC address can later be extracted in order to initiate the connection. You can learn more about creating a connection -in the section about Connecting Devices.

        - +in the section about Connecting Devices.

        +

        Caution: Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources. Once you have found a device to @@ -406,10 +406,10 @@ connect, be certain that you always stop discovery with attempting a connection. Also, if you already hold a connection with a device, then performing discovery can significantly reduce the bandwidth available for the connection, so you should -not perform discovery while connected.

        - -

        Enabling discoverability

        - +not perform discovery while connected.

        + +

        Enabling discoverability

        +

        If you would like to make the local device discoverable to other devices, call {@link android.app.Activity#startActivityForResult(Intent,int)} with the {@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_DISCOVERABLE} action @@ -420,30 +420,30 @@ discoverable for 120 seconds. You can define a different duration by adding the extra. The maximum duration an app can set is 3600 seconds, and a value of 0 means the device is always discoverable. Any value below 0 or above 3600 is automatically set to 120 secs). For example, this snippet sets the duration to -300:

        +300:

        Intent discoverableIntent = new
         Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
         discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
         startActivity(discoverableIntent);
        -
        - -
        - + + +
        + Figure 2: The enabling discoverability dialog. -
        - +
        +

        A dialog will be displayed, requesting user permission to make the device discoverable, as shown in Figure 2. If the user responds "Yes," then the device will become discoverable for the specified amount of time. Your activity will then receive a call to the {@link android.app.Activity#onActivityResult(int,int,Intent) onActivityResult())} callback, with the result code equal to the duration that the device is discoverable. If the user responded "No" or if an error occurred, the result code will -be {@link android.app.Activity#RESULT_CANCELED}.

        - +be {@link android.app.Activity#RESULT_CANCELED}.

        +

        Note: If Bluetooth has not been enabled on the device, -then enabling device discoverability will automatically enable Bluetooth.

        - +then enabling device discoverability will automatically enable Bluetooth.

        +

        The device will silently remain in discoverable mode for the allotted time. If you would like to be notified when the discoverable mode has changed, you can register a BroadcastReceiver for the {@link @@ -457,18 +457,18 @@ new and old scan mode, respectively. Possible values for each are android.bluetooth.BluetoothAdapter#SCAN_MODE_NONE}, which indicate that the device is either in discoverable mode, not in discoverable mode but still able to receive connections, or not in discoverable -mode and unable to receive connections, respectively.

        - +mode and unable to receive connections, respectively.

        +

        You do not need to enable device discoverability if you will be initiating the connection to a remote device. Enabling discoverability is only necessary when you want your application to host a server socket that will accept incoming connections, because the remote devices must be able to discover the device -before it can initiate the connection.

        - - - -

        Connecting Devices

        - +before it can initiate the connection.

        + + + +

        Connecting Devices

        +

        In order to create a connection between your application on two devices, you must implement both the server-side and client-side mechanisms, because one device must open a server socket and the other one must initiate the connection @@ -478,36 +478,36 @@ client are considered connected to each other when they each have a connected point, each device can obtain input and output streams and data transfer can begin, which is discussed in the section about Managing a Connection. This section describes how -to initiate the connection between two devices.

        - +to initiate the connection between two devices.

        +

        The server device and the client device each obtain the required {@link android.bluetooth.BluetoothSocket} in different ways. The server will receive it when an incoming connection is accepted. The client will receive it when it -opens an RFCOMM channel to the server.

        - -
        - +opens an RFCOMM channel to the server.

        + +
        + Figure 3: The Bluetooth pairing dialog. -
        - +
        +

        One implementation technique is to automatically prepare each device as a server, so that each one has a server socket open and listening for connections. Then either device can initiate a connection with the other and become the client. Alternatively, one device can explicitly "host" the connection and open a server socket on demand and the other device can simply initiate the -connection.

        - +connection.

        +

        Note: If the two devices have not been previously paired, then the Android framework will automatically show a pairing request notification or dialog to the user during the connection procedure, as shown in Figure 3. So when attempting to connect devices, your application does not need to be concerned about whether or not the devices are paired. Your RFCOMM connection attempt will block until the user has successfully paired, -or will fail if the user rejects pairing, or if pairing fails or times out.

        - - -

        Connecting as a server

        - +or will fail if the user rejects pairing, or if pairing fails or times out.

        + + +

        Connecting as a server

        +

        When you want to connect two devices, one must act as a server by holding an open {@link android.bluetooth.BluetoothServerSocket}. The purpose of the server socket is to listen for incoming connection requests and when one is accepted, @@ -515,26 +515,26 @@ provide a connected {@link android.bluetooth.BluetoothSocket}. When the {@link android.bluetooth.BluetoothSocket} is acquired from the {@link android.bluetooth.BluetoothServerSocket}, the {@link android.bluetooth.BluetoothServerSocket} can (and should) be -discarded, unless you want to accept more connections.

        - - +

        Here's the basic procedure to set up a server socket and accept a -connection:

        - -
          +connection:

          + +
          1. Get a {@link android.bluetooth.BluetoothServerSocket} by calling the {@link android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String, @@ -546,9 +546,9 @@ UUID is also included in the SDP entry and will be the basis for the connection agreement with the client device. That is, when the client attempts to connect with this device, it will carry a UUID that uniquely identifies the service with which it wants to connect. These UUIDs must match in order for the connection to -be accepted (in the next step).

            -
          2. - +be accepted (in the next step).

            + +
          3. Start listening for connection requests by calling {@link android.bluetooth.BluetoothServerSocket#accept()}.

            This is a blocking call. It will return when either a connection has been @@ -556,9 +556,9 @@ accepted or an exception has occurred. A connection is accepted only when a remote device has sent a connection request with a UUID matching the one registered with this listening server socket. When successful, {@link android.bluetooth.BluetoothServerSocket#accept()} will -return a connected {@link android.bluetooth.BluetoothSocket}.

            -
          4. - +return a connected {@link android.bluetooth.BluetoothSocket}.

            + +
          5. Unless you want to accept additional connections, call {@link android.bluetooth.BluetoothServerSocket#close()}.

            This releases the server socket and all its resources, but does not close the @@ -567,10 +567,10 @@ android.bluetooth.BluetoothServerSocket#accept()}. Unlike TCP/IP, RFCOMM only al connected client per channel at a time, so in most cases it makes sense to call {@link android.bluetooth.BluetoothServerSocket#close()} on the {@link android.bluetooth.BluetoothServerSocket} immediately after accepting a connected -socket.

            -
          6. -
          - +socket.

          + +
        +

        The {@link android.bluetooth.BluetoothServerSocket#accept()} call should not be executed in the main activity UI thread because it is a blocking call and will prevent any other interaction with the application. It usually makes @@ -583,16 +583,16 @@ android.bluetooth.BluetoothServerSocket} (or {@link android.bluetooth.BluetoothSocket}) from another thread and the blocked call will immediately return. Note that all methods on a {@link android.bluetooth.BluetoothServerSocket} or {@link android.bluetooth.BluetoothSocket} -are thread-safe.

        - -

        Example

        - +are thread-safe.

        + +

        Example

        +

        Here's a simplified thread for the server component that accepts incoming -connections:

        -
         
        +connections:

        +
         private class AcceptThread extends Thread {
             private final BluetoothServerSocket mmServerSocket;
        - 
        +
             public AcceptThread() {
                 // Use a temporary object that is later assigned to mmServerSocket,
                 // because mmServerSocket is final
        @@ -603,7 +603,7 @@ private class AcceptThread extends Thread {
                 } catch (IOException e) { }
                 mmServerSocket = tmp;
             }
        - 
        +
             public void run() {
                 BluetoothSocket socket = null;
                 // Keep listening until exception occurs or a socket is returned
        @@ -622,7 +622,7 @@ private class AcceptThread extends Thread {
                     }
                 }
             }
        - 
        +
             /** Will cancel the listening socket, and cause the thread to finish */
             public void cancel() {
                 try {
        @@ -630,37 +630,37 @@ private class AcceptThread extends Thread {
                 } catch (IOException e) { }
             }
         }
        -
        - +
        +

        In this example, only one incoming connection is desired, so as soon as a connection is accepted and the {@link android.bluetooth.BluetoothSocket} is acquired, the application sends the acquired {@link android.bluetooth.BluetoothSocket} to a separate thread, closes the -{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.

        - +{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.

        +

        Note that when {@link android.bluetooth.BluetoothServerSocket#accept()} returns the {@link android.bluetooth.BluetoothSocket}, the socket is already connected, so you should not call {@link android.bluetooth.BluetoothSocket#connect()} (as you do from the -client-side).

        - +client-side).

        +

        manageConnectedSocket() is a fictional method in the application that will initiate the thread for transferring data, which is discussed in the section -about Managing a Connection.

        - +about Managing a Connection.

        +

        You should usually close your {@link android.bluetooth.BluetoothServerSocket} as soon as you are done listening for incoming connections. In this example, {@link android.bluetooth.BluetoothServerSocket#close()} is called as soon as the {@link android.bluetooth.BluetoothSocket} is acquired. You may also want to provide a public method in your thread that can close the private {@link android.bluetooth.BluetoothSocket} in the event that you need to stop listening on the -server socket.

        - - -

        Connecting as a client

        - +server socket.

        + + +

        Connecting as a client

        +

        In order to initiate a connection with a remote device (a device holding an open server socket), you must first obtain a {@link @@ -669,11 +669,11 @@ android.bluetooth.BluetoothDevice} object that represents the remote device. section about Finding Devices.) You must then use the {@link android.bluetooth.BluetoothDevice} to acquire a {@link -android.bluetooth.BluetoothSocket} and initiate the connection.

        - -

        Here's the basic procedure:

        - -
          +android.bluetooth.BluetoothSocket} and initiate the connection.

          + +

          Here's the basic procedure:

          + +
          1. Using the {@link android.bluetooth.BluetoothDevice}, get a {@link android.bluetooth.BluetoothSocket} by calling {@link android.bluetooth.BluetoothDevice#createRfcommSocketToServiceRecord(UUID)}. @@ -684,9 +684,9 @@ must match the UUID used by the server device when it opened its android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String, UUID)}). Using the same UUID is simply a matter of hard-coding the UUID string into your application and then referencing it from both the server and client -code.

            -
          2. - +code.

            + +
          3. Initiate the connection by calling {@link android.bluetooth.BluetoothSocket#connect()}.

            Upon this call, the system will perform an SDP lookup on the remote device in @@ -697,34 +697,34 @@ android.bluetooth.BluetoothSocket#connect()} will return. This method is a blocking call. If, for any reason, the connection fails or the {@link android.bluetooth.BluetoothSocket#connect()} method times out (after about -12 seconds), then it will throw an exception.

            +12 seconds), then it will throw an exception.

            Because {@link android.bluetooth.BluetoothSocket#connect()} is a blocking call, this connection procedure should always be performed in a thread separate from the main activity -thread.

            +thread.

            Note: You should always ensure that the device is not performing device discovery when you call {@link android.bluetooth.BluetoothSocket#connect()}. If discovery is in progress, then the -connection attempt will be significantly slowed and is more likely to fail.

            -
          4. -
          - -

          Example

          - +connection attempt will be significantly slowed and is more likely to fail.

          + +
        + +

        Example

        +

        Here is a basic example of a thread that initiates a Bluetooth -connection:

        -
         
        +connection:

        +
         private class ConnectThread extends Thread {
             private final BluetoothSocket mmSocket;
             private final BluetoothDevice mmDevice;
        - 
        +
             public ConnectThread(BluetoothDevice device) {
                 // Use a temporary object that is later assigned to mmSocket,
                 // because mmSocket is final
                 BluetoothSocket tmp = null;
                 mmDevice = device;
        - 
        +
                 // Get a BluetoothSocket to connect with the given BluetoothDevice
                 try {
                     // MY_UUID is the app's UUID string, also used by the server code
        @@ -732,11 +732,11 @@ private class ConnectThread extends Thread {
                 } catch (IOException e) { }
                 mmSocket = tmp;
             }
        - 
        +
             public void run() {
                 // Cancel discovery because it will slow down the connection
                 mBluetoothAdapter.cancelDiscovery();
        - 
        +
                 try {
                     // Connect the device through the socket. This will block
                     // until it succeeds or throws an exception
        @@ -748,11 +748,11 @@ private class ConnectThread extends Thread {
                     } catch (IOException closeException) { }
                     return;
                 }
        - 
        +
                 // Do work to manage the connection (in a separate thread)
                 manageConnectedSocket(mmSocket);
             }
        - 
        +
             /** Will cancel an in-progress connection, and close the socket */
             public void cancel() {
                 try {
        @@ -760,42 +760,42 @@ private class ConnectThread extends Thread {
                 } catch (IOException e) { }
             }
         }
        -
        - +
        +

        Notice that {@link android.bluetooth.BluetoothAdapter#cancelDiscovery()} is called before the connection is made. You should always do this before connecting and it is safe to call without actually checking whether it is running or not (but if you do want to -check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).

        - +check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).

        +

        manageConnectedSocket() is a fictional method in the application that will initiate the thread for transferring data, which is discussed in the section -about Managing a Connection.

        - +about Managing a Connection.

        +

        When you're done with your {@link android.bluetooth.BluetoothSocket}, always call {@link android.bluetooth.BluetoothSocket#close()} to clean up. Doing so will immediately close the connected socket and clean up all internal -resources.

        - - -

        Managing a Connection

        - +resources.

        + + +

        Managing a Connection

        +

        When you have successfully connected two (or more) devices, each one will have a connected {@link android.bluetooth.BluetoothSocket}. This is where the fun begins because you can share data between devices. Using the {@link android.bluetooth.BluetoothSocket}, the general procedure to transfer arbitrary data is -simple:

        -
          +simple:

          +
          1. Get the {@link java.io.InputStream} and {@link java.io.OutputStream} that handle transmissions through the socket, via {@link android.bluetooth.BluetoothSocket#getInputStream()} and -{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively.
          2. - +{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively. +
          3. Read and write data to the streams with {@link -java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}.
          4. -
          - -

          That's it.

          - +java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}. +
        + +

        That's it.

        +

        There are, of course, implementation details to consider. First and foremost, you should use a dedicated thread for all stream reading and writing. This is important because both {@link java.io.InputStream#read(byte[])} and {@link @@ -806,37 +806,37 @@ block, but can block for flow control if the remote device is not calling {@link java.io.InputStream#read(byte[])} quickly enough and the intermediate buffers are full. So, your main loop in the thread should be dedicated to reading from the {@link java.io.InputStream}. A separate public method in the thread can be used to initiate -writes to the {@link java.io.OutputStream}.

        - -

        Example

        - -

        Here's an example of how this might look:

        -
         
        +writes to the {@link java.io.OutputStream}.

        + +

        Example

        + +

        Here's an example of how this might look:

        +
         private class ConnectedThread extends Thread {
             private final BluetoothSocket mmSocket;
             private final InputStream mmInStream;
             private final OutputStream mmOutStream;
        - 
        +
             public ConnectedThread(BluetoothSocket socket) {
                 mmSocket = socket;
                 InputStream tmpIn = null;
                 OutputStream tmpOut = null;
        - 
        +
                 // Get the input and output streams, using temp objects because
                 // member streams are final
                 try {
                     tmpIn = socket.getInputStream();
                     tmpOut = socket.getOutputStream();
                 } catch (IOException e) { }
        - 
        +
                 mmInStream = tmpIn;
                 mmOutStream = tmpOut;
             }
        - 
        +
             public void run() {
                 byte[] buffer = new byte[1024];  // buffer store for the stream
                 int bytes; // bytes returned from read()
        - 
        +
                 // Keep listening to the InputStream until an exception occurs
                 while (true) {
                     try {
        @@ -850,14 +850,14 @@ private class ConnectedThread extends Thread {
                     }
                 }
             }
        - 
        +
             /* Call this from the main activity to send data to the remote device */
             public void write(byte[] bytes) {
                 try {
                     mmOutStream.write(bytes);
                 } catch (IOException e) { }
             }
        - 
        +
             /* Call this from the main activity to shutdown the connection */
             public void cancel() {
                 try {
        @@ -865,44 +865,44 @@ private class ConnectedThread extends Thread {
                 } catch (IOException e) { }
             }
         }
        -
        - +
        +

        The constructor acquires the necessary streams and once executed, the thread will wait for data to come through the InputStream. When {@link java.io.InputStream#read(byte[])} returns with bytes from the stream, the data is sent to the main activity using a member Handler from the parent class. Then it goes back and waits for more bytes from -the stream.

        - +the stream.

        +

        Sending outgoing data is as simple as calling the thread's write() method from the main activity and passing in the bytes to be sent. This method then simply calls {@link -java.io.OutputStream#write(byte[])} to send the data to the remote device.

        - +java.io.OutputStream#write(byte[])} to send the data to the remote device.

        +

        The thread's cancel() method is important so that the connection can be terminated at any time by closing the {@link android.bluetooth.BluetoothSocket}. This should always be called when you're done using the Bluetooth -connection.

        - -
        +connection.

        + +

        For a demonstration of using the Bluetooth APIs, see the Bluetooth Chat sample app.

        -
        +href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample app.

        +
        -

        Working with Profiles

        +

        Working with Profiles

        Starting in Android 3.0, the Bluetooth API includes support for working with Bluetooth profiles. A Bluetooth profile is a wireless interface specification for Bluetooth-based communication between devices. An example is the Hands-Free profile. For a mobile phone to connect to a wireless headset, -both devices must support the Hands-Free profile.

        +both devices must support the Hands-Free profile.

        You can implement the interface {@link android.bluetooth.BluetoothProfile} to write your own classes to support a particular Bluetooth profile. The Android Bluetooth API provides implementations for the following Bluetooth -profiles:

        - -

        Here are the basic steps for working with a profile:

        -
          +

          Here are the basic steps for working with a profile:

          +
          1. Get the default adapter, as described in Setting Up - Bluetooth.
          2. + Bluetooth.
          3. Use {@link android.bluetooth.BluetoothAdapter#getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int) getProfileProxy()} to establish a connection to the profile proxy object associated with the profile. In the example below, the profile proxy object is an instance of {@link -android.bluetooth.BluetoothHeadset}.
          4. +android.bluetooth.BluetoothHeadset}.
          5. Set up a {@link android.bluetooth.BluetoothProfile.ServiceListener}. This listener notifies {@link android.bluetooth.BluetoothProfile} IPC clients when -they have been connected to or disconnected from the service.
          6. +they have been connected to or disconnected from the service.
          7. In {@link android.bluetooth.BluetoothProfile.ServiceListener#onServiceConnected(int, android.bluetooth.BluetoothProfile) onServiceConnected()}, get a handle -to the profile proxy object.
          8. +to the profile proxy object.
          9. Once you have the profile proxy object, you can use it to monitor the state of the connection and perform other operations that are relevant to that -profile.
          10. -
          +profile. +

        For example, this code snippet shows how to connect to a {@link android.bluetooth.BluetoothHeadset} proxy object so that you can control the -Headset profile:

        +Headset profile:

        BluetoothHeadset mBluetoothHeadset;
        - 
        +
         // Get the default adapter
         BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        - 
        +
         // Establish connection to the proxy.
         mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
        - 
        +
         private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
             public void onServiceConnected(int profile, BluetoothProfile proxy) {
                 if (profile == BluetoothProfile.HEADSET) {
        @@ -984,16 +984,16 @@ private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile
                 }
             }
         };
        - 
        +
         // ... call functions on mBluetoothHeadset
        - 
        +
         // Close proxy connection after use.
         mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);
        -
        + -

        Vendor-specific AT commands

        +

        Vendor-specific AT commands

        Starting in Android 3.0, applications can register to receive system broadcasts of pre-defined vendor-specific AT commands sent by headsets (such as @@ -1056,11 +1056,11 @@ such as an Android phone or tablet. object.

        Similar to regular headset and A2DP profile devices, you must call {@link android.bluetooth.BluetoothAdapter#getProfileProxy getProfileProxy()} with a {@link android.bluetooth.BluetoothProfile.ServiceListener} and the {@link -android.bluetooth.BluetoothProfile.ServiceListener#HEALTH} profile type to +android.bluetooth.BluetoothProfile#HEALTH} profile type to establish a connection with the profile proxy object.

      • Create a {@link android.bluetooth.BluetoothHealthCallback} and register an -application configuration +application configuration ({@link android.bluetooth.BluetoothHealthAppConfiguration}) that acts as a health sink.
      • diff --git a/docs/html/guide/topics/connectivity/nfc/index.jd b/docs/html/guide/topics/connectivity/nfc/index.jd index f12facf75ecc2bdc8b407cd465f87aefdedebae9..bc4f075c71f755d2bbd0afdaba464a0115c86c52 100644 --- a/docs/html/guide/topics/connectivity/nfc/index.jd +++ b/docs/html/guide/topics/connectivity/nfc/index.jd @@ -17,12 +17,12 @@ page.title=Near Field Communication

        Android-powered devices with NFC simultaneously support three main modes of operation:

          -
        1. Reader/writer mode, allowing the NFC device to read and/or write +
        2. Reader/writer mode, allowing the NFC device to read and/or write passive NFC tags and stickers.
        3. -
        4. P2P mode, allowing the NFC device to exchange data with other NFC +
        5. P2P mode, allowing the NFC device to exchange data with other NFC peers; this operation mode is used by Android Beam.
        6. -
        7. Card emulation mode, allowing the NFC device itself to act as an NFC -card. The emulated NFC card can then be accessed by an external NFC reader, +
        8. Card emulation mode, allowing the NFC device itself to act as an NFC +card. The emulated NFC card can then be accessed by an external NFC reader, such as an NFC point-of-sale terminal.
        diff --git a/docs/html/guide/topics/connectivity/nfc/nfc.jd b/docs/html/guide/topics/connectivity/nfc/nfc.jd index 520f520170976fbc135fdbeacd6260064274732c..881a75f2512dba2a090f6d07f60be70064cdb78c 100644 --- a/docs/html/guide/topics/connectivity/nfc/nfc.jd +++ b/docs/html/guide/topics/connectivity/nfc/nfc.jd @@ -487,19 +487,22 @@ intent. The following example checks for the {@link android.nfc.NfcAdapter#ACTIO intent and gets the NDEF messages from an intent extra.

        -public void onResume() {
        -    super.onResume();
        +@Override
        +protected void onNewIntent(Intent intent) {
        +    super.onNewIntent(intent);
             ...
        -    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
        -        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        -        if (rawMsgs != null) {
        -            msgs = new NdefMessage[rawMsgs.length];
        -            for (int i = 0; i < rawMsgs.length; i++) {
        -                msgs[i] = (NdefMessage) rawMsgs[i];
        +    if (intent != null && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
        +        Parcelable[] rawMessages =
        +            intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        +        if (rawMessages != null) {
        +            NdefMessage[] messages = new NdefMessage[rawMessages.length];
        +            for (int i = 0; i < rawMessages.length; i++) {
        +                messages[i] = (NdefMessage) rawMessages[i];
                     }
        +            // Process the messages array.
        +            ...
                 }
             }
        -    //process the msgs array
         }
         
        diff --git a/docs/html/guide/topics/connectivity/sip.jd b/docs/html/guide/topics/connectivity/sip.jd index d754894741e7f2af07c29012efbeb87b2f21f879..d8d6d277bbf990f93ef9eba488bdd39a2f88a7f2 100755 --- a/docs/html/guide/topics/connectivity/sip.jd +++ b/docs/html/guide/topics/connectivity/sip.jd @@ -12,10 +12,10 @@ page.tags=sipmanager,sipprofile,sipaudiocall,telephony
      • Creating a SIP Manager
      • Registering with a SIP Server
      • Making an Audio Call
      • -
      • Receiving Calls
      • +
      • Receiving Calls
      • Testing SIP Applications
      • - +

        Key classes

        1. {@link android.net.sip.SipManager}
        2. @@ -23,7 +23,7 @@ page.tags=sipmanager,sipprofile,sipaudiocall,telephony
        3. {@link android.net.sip.SipAudioCall}
        - +

        Related samples

        1. SipDemo
        2. @@ -46,9 +46,9 @@ record or playback directly.

          Requirements and Limitations

          Here are the requirements for developing a SIP application:

            - +
          • You must have a mobile device that is running Android 2.3 or higher.
          • - +
          • SIP runs over a wireless data connection, so your device must have a data connection (with a mobile data service or Wi-Fi). This means that you can't test on AVD—you can only test on a physical device. For details, see @@ -139,7 +139,7 @@ capable of supporting SIP, add the following to your application's manifest:

              -
            • <uses-sdk android:minSdkVersion="9" />. This +
            • <uses-sdk android:minSdkVersion="9" />. This indicates that your application requires Android 2.3 or higher. For more information, see API Levels and the documentation for the <uses- feature> element.
            • - +

            If your application is designed to receive calls, you must also define a receiver ({@link android.content.BroadcastReceiver} subclass) in the application's manifest:

            @@ -261,7 +261,7 @@ public void onRegistering(String localProfileUri) { public void onRegistrationDone(String localProfileUri, long expiryTime) { updateStatus("Ready"); } - + public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage) { updateStatus("Registration failed. Please check settings."); @@ -291,8 +291,8 @@ example:

          • A {@link android.net.sip.SipProfile} that is making the call (the "local profile"), and a valid SIP address to receive the call (the -"peer profile"). - +"peer profile"). +
          • A {@link android.net.sip.SipManager} object.
          @@ -304,7 +304,7 @@ established:

           SipAudioCall.Listener listener = new SipAudioCall.Listener() {
          -  
          +
              @Override
              public void onCallEstablished(SipAudioCall call) {
                 call.startAudio();
          @@ -312,7 +312,7 @@ SipAudioCall.Listener listener = new SipAudioCall.Listener() {
                 call.toggleMute();
                    ...
              }
          -   
          +
              @Override
              public void onCallEnded(SipAudioCall call) {
                 // Do something.
          @@ -326,12 +326,12 @@ make the  call. The {@link android.net.sip.SipManager} method
           
          • A local SIP profile (the caller).
          • A peer SIP profile (the user being called).
          • - +
          • A {@link android.net.sip.SipAudioCall.Listener} to listen to the call events from {@link android.net.sip.SipAudioCall}. This can be null, but as shown above, the listener is used to set things up once the call is established.
          • - +
          • The timeout value, in seconds.

          For example:

          @@ -349,15 +349,15 @@ your application:

          <receiver>. In SipDemo, this is <receiver android:name=".IncomingCallReceiver" android:label="Call Receiver"/>. - +
        3. Implement the receiver, which is a subclass of {@link android.content.BroadcastReceiver}. In SipDemo, this is IncomingCallReceiver.
        4. - +
        5. Initialize the local profile ({@link android.net.sip.SipProfile}) with a pending intent that fires your receiver when someone calls the local profile.
        6. - +
        7. Set up an intent filter that filters by the action that represents an incoming call. In SipDemo, this action is android.SipDemo.INCOMING_CALL.
        8. @@ -427,16 +427,16 @@ action string provided by the application. In SipDemo, this action string is android.net.sip.SipProfile} object gets created with a pending intent based on the action string android.SipDemo.INCOMING_CALL. The PendingIntent object will perform a broadcast when the {@link -android.net.sip.SipProfile} receives a call:

          +android.net.sip.SipProfile} receives a call:

           public SipManager mSipManager = null;
           public SipProfile mSipProfile = null;
           ...
           
          -Intent intent = new Intent(); 
          -intent.setAction("android.SipDemo.INCOMING_CALL"); 
          -PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA); 
          +Intent intent = new Intent();
          +intent.setAction("android.SipDemo.INCOMING_CALL");
          +PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
           mSipManager.open(mSipProfile, pendingIntent, null);

          The broadcast will be intercepted by the intent filter, which will then fire @@ -485,8 +485,8 @@ href="{@docRoot}tools/device.html">Developing on a Device. href="{@docRoot}tools/device.html">Developing on a Device.

        9. If you are using Android Studio, you can view the application log output by -opening the Event Log console (View > Tool Windows > Event Log). -
        10. Ensure your application is configured to launch Logcat automatically when it runs: +opening the Event Log console (View > Tool Windows > Event Log). +
        11. Ensure your application is configured to launch Logcat automatically when it runs:
          1. Select Run > Edit Configurations.
          2. Select the Miscellaneous tab in the Run/Debug Configurations window. diff --git a/docs/html/guide/topics/connectivity/usb/accessory.jd b/docs/html/guide/topics/connectivity/usb/accessory.jd index a2177678fc56dde241d9fecbf33b59e60c968133..3942b3a951b96e03db9c2442f13fa862443a99fc 100644 --- a/docs/html/guide/topics/connectivity/usb/accessory.jd +++ b/docs/html/guide/topics/connectivity/usb/accessory.jd @@ -169,7 +169,7 @@ UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXT include a <uses-feature> element that declares that your application uses the android.hardware.usb.accessory feature.
          3. -
          4. If you are using the +
          5. If you are using the add-on library, add the <uses-library> element specifying com.android.future.usb.accessory for the library.
          6. @@ -347,7 +347,7 @@ UsbAccessory[] accessoryList = manager.getAcccessoryList(); private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - + public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { @@ -444,7 +444,7 @@ private void openAccessory() {
             BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
                 public void onReceive(Context context, Intent intent) {
            -        String action = intent.getAction(); 
            +        String action = intent.getAction();
             
                     if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
                         UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
            diff --git a/docs/html/guide/topics/connectivity/usb/host.jd b/docs/html/guide/topics/connectivity/usb/host.jd
            index d2194e6d6f6dd89593fa69590e5d82fb0ce34b2a..856027d09d7f67509bb487a9a441f65902e625f6 100644
            --- a/docs/html/guide/topics/connectivity/usb/host.jd
            +++ b/docs/html/guide/topics/connectivity/usb/host.jd
            @@ -263,7 +263,7 @@ UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE
               obtain a device from the map.

             UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
            -...  
            +...
             HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
             UsbDevice device = deviceList.get("deviceName");
             
            @@ -317,7 +317,7 @@ private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { if(device != null){ //call method to set up device communication } - } + } else { Log.d(TAG, "permission denied for device " + device); } @@ -396,7 +396,7 @@ private boolean forceClaim = true; UsbInterface intf = device.getInterface(0); UsbEndpoint endpoint = intf.getEndpoint(0); -UsbDeviceConnection connection = mUsbManager.openDevice(device); +UsbDeviceConnection connection = mUsbManager.openDevice(device); connection.claimInterface(intf, forceClaim); connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread
            @@ -422,7 +422,7 @@ connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another
             BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
                 public void onReceive(Context context, Intent intent) {
            -        String action = intent.getAction(); 
            +        String action = intent.getAction();
             
                   if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                         UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
            diff --git a/docs/html/guide/topics/connectivity/wifip2p.jd b/docs/html/guide/topics/connectivity/wifip2p.jd
            index d7e1269696cf9ca6e23b4afd6d9379ddca47d9c8..2bcdf54821e7f3d362ef9266653886f6207dfee7 100644
            --- a/docs/html/guide/topics/connectivity/wifip2p.jd
            +++ b/docs/html/guide/topics/connectivity/wifip2p.jd
            @@ -66,7 +66,7 @@ a photo sharing application.

            methods. A {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} intent is also broadcast if the {@link android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()} method discovers that the peers list has changed.

            - +

            API Overview

            The {@link android.net.wifi.p2p.WifiP2pManager} class provides methods to allow you to interact with @@ -117,7 +117,7 @@ a photo sharing application.

            - {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()} + {@link android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()} Initiates peer discovery @@ -135,7 +135,7 @@ a photo sharing application.

            are described in the following table:

            Table 2. Wi-Fi P2P Listeners

            - + @@ -147,7 +147,7 @@ a photo sharing application.

            android.net.wifi.p2p.WifiP2pManager#cancelConnect cancelConnect()}, {@link android.net.wifi.p2p.WifiP2pManager#createGroup createGroup()}, {@link android.net.wifi.p2p.WifiP2pManager#removeGroup removeGroup()}, and {@link - android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()} + android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()} @@ -190,8 +190,8 @@ a photo sharing application.

            @@ -395,7 +395,7 @@ protected void onPause() { available peers that are in range. The call to this function is asynchronous and a success or failure is communicated to your application with {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess onSuccess()} and {@link - android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure onFailure()} if you created a + android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure onFailure()} if you created a {@link android.net.wifi.p2p.WifiP2pManager.ActionListener}. The {@link android.net.wifi.p2p.WifiP2pManager.ActionListener#onSuccess onSuccess()} method only notifies you that the discovery process succeeded and does not provide any information about the actual peers diff --git a/docs/html/guide/topics/data/autobackup.jd b/docs/html/guide/topics/data/autobackup.jd new file mode 100644 index 0000000000000000000000000000000000000000..3be09d712884ae3893c7c7816424868499dfaf2f --- /dev/null +++ b/docs/html/guide/topics/data/autobackup.jd @@ -0,0 +1,257 @@ +page.title=Auto Backup for Apps +page.tags=backup, marshmallow, androidm +page.keywords=backup, autobackup +page.image=images/cards/card-auto-backup_2x.png + +@jd:body + +
            + +
            + +Since Android 6.0 (API 23), Android has offered the Auto Backup for Apps feature as +a way for developers to quickly add backup functionality to their apps. Auto +Backup preserves app data by uploading it to the user’s Google Drive account. +The amount of data is limited to 25MB per user of your app and there is no +charge for storing backup data. + +

            Files that are backed up

            +

            By default, Auto Backup includes files in most of the directories that are +assigned to your app by the system: +

              +
            • Shared preferences files. +
            • Files in the directory returned by {@link android.content.Context#getFilesDir()}. +
            • Files in the directory returned by {@link android.content.Context#getDatabasePath(String)}, + which also includes files created with the + {@link android.database.sqlite.SQLiteOpenHelper} class. +
            • Files in directories created with {@link android.content.Context#getDir(String,int)}. +
            • Files on external storage in the directory returned by + {@link android.content.Context#getExternalFilesDir(String)}.
            + +

            Auto Backup excludes files in directories returned by + {@link android.content.Context#getCacheDir()}, + {@link android.content.Context#getCodeCacheDir()}, or + {@link android.content.Context#getNoBackupFilesDir()}. The files saved + in these locations are only needed temporarily, or are intentionally + excluded from backup operations. + +

            You can configure your app to include and exclude particular files. +For more information, see the Include and exclude files +section. + +

            Backup location

            +

            Backup data is stored in a private folder in the user's Google Drive account, +limited to 25MB per app. The saved data does not count towards the user's +personal Google Drive quota. Only the most recent backup is stored. When a +backup is made, the previous backup (if one exists) is deleted. + +

            Users can see a list of apps that have been backed up in the Google Drive app under +Settings -> Auto Backup for apps -> Manage backup. The +backup data cannot be read by the user or other applications on the device. + +

            Backups from each device-setup-lifetime are stored in separate datasets +as shown in the following examples: +

              +
            • If the user owns two devices, then a backup dataset exists for each device. +
            • If the user factory resets a device and then sets up the device with the + same account, the backup is stored in a new dataset. Obsolete datasets are + automatically deleted after a period of inactivity.
            + +

            Caution: Once the amount of data reaches +25MB, the app is banned from sending data to the +cloud, even if the amount of data later falls under the 25MB threshold. The ban +affects only the offending device (not other devices that the user owns) and +lasts for the entire device-setup-lifetime. For example, if the user removes and +reinstalls the application, the ban is still in effect. The ban is lifted when +the user performs factory reset on the device. + +

            Backup schedule

            +

            Backups occur automatically when all of the following conditions are met: +

              +
            • The user has enabled backup on the device in Settings > + Backup & Reset. +
            • At least 24 hours have elapsed since the last backup. +
            • The device is idle and charging. +
            • The device is connected to a Wi-Fi network. If the device is never connected + to a wifi network, then Auto Backup never occurs.
            + +

            In practice, these conditions occur roughly every night. To conserve network +bandwidth, upload takes place only if app data has changed. + +

            During Auto Backup, the system shuts down the app to make sure it is no longer +writing to the file system. By default, the backup system ignores apps that are +running in the foreground because users would notice their apps being shut down. +You can override the default behavior by setting the +backupInForeground +attribute to true. + +

            To simplify testing, Android includes tools that let you manually initiate +a backup of your app. For more information, see +Testing Backup and Restore. + +

            Restore schedule

            +

            Data is restored whenever the app is installed, either from the Play store, +during device setup (when the system installs previously installed apps), or +from running adb install. The restore operation occurs after the APK is +installed, but before the app is available to be launched by the user. + +

            During the initial device setup wizard, the user is shown a list of available backup +datasets and is asked which one to restore the data from. Whichever backup +dataset is selected becomes the ancestral dataset for the device. The device can +restore from either its own backups or the ancestral dataset. The device +prioritize its own backup if backups from both sources are available. If the +user didn't go through the device setup wizard, then the device can restore only from +its own backups. + +

            To simplify testing, Android includes tools that let you manually initiate +a restore of your app. For more information, see +Testing Backup and Restore. + +

            Enabling and disabling backup

            +

            Apps that target Android 6.0 (API level 23) or higher automatically participate +in Auto Backup. This is because the +android:allowBackup +attribute, which enables/disables backup, defaults to true if omitted. +To avoid confusion, we recommend you explicitly set the attribute in the <application> +element of your AndroidManifest.xml. For example: + +

            <application ...
            +    android:allowBackup="true">
            +</app>
            + +

            To disable Auto Backup, add either of the following attributes to the +application element in your manifest file: + +

              +
            • set android:allowBackup to false. This completely disables data + backup. You may want to disable backups when your app can recreate its state + through some other mechanism or when your app deals with sensitive + information that should not be backed up.
            • +
            • set android:allowBackup to true and + android:fullBackupOnly to false. With these settings, + your app always participates in Key/Value Backup, even when running on devices that + support Auto Backup.
            + +

            Including and excluding files

            +

            By default, the system backs up almost all app data. For more information, +see Files that are backed up. This section shows you how to +define custom XML rules to control what gets backed up. + +

              +
            1. In AndroidManifest.xml, add the android:fullBackupContent attribute to the + <application> element. This attribute points to an XML file that contains backup + rules. For example: +
              <application ...
              +    android:fullBackupContent="@xml/my_backup_rules">
              +  </app>
            2. +
            3. Create an XML file called my_backup_rules.xml in the res/xml/ directory. Inside the file, add rules with the <include> and <exclude> elements. The following sample backs up all shared preferences except device.xml: +
              <?xml version="1.0" encoding="utf-8"?>
              +<full-backup-content>
              +    <include domain="sharedpref" path="."/>
              +    <exclude domain="sharedpref" path="device.xml"/>
              +</full-backup-content>
            4. + +

              XML Config Syntax

              +

              The XML syntax for the configuration file is shown below: + +

              <full-backup-content>
              +    <include domain=["file" | "database" | "sharedpref" | "external" | "root"]
              +    path="string" />
              +    <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"]
              +    path="string" />
              +</full-backup-content>
              + +

              Inside the <full-backup-content> tag, you can define <include> and <exclude> +elements: + +

                +
              • <include> - Specifies a file or folder to backup. By default, Auto Backup +includes almost all app files. If you specify an <include> element, the system +no longer includes any files by default and backs up only the files +specified. To include multiple files, use multiple <include> elements. +

                note: Files in directories returned by getCacheDir(), getCodeCacheDir(), or +getNoBackupFilesDir() are always excluded even if you try to include them.

              • + +
              • <exclude> - Specifies a file or folder to exclude during backup. Here are +some files that are typically excluded from backup:
                  +
                • Files that have device specific identifiers, either issued by a server or +generated on the device. For example, Google Cloud Messaging (GCM) needs to +generate a registration token every time a user installs your app on a new +device. If the old registration token is restored, the app may behave +unexpectedly. +
                • Account credentials or other sensitive information. Consider asking the +user to reauthenticate the first time they launch a restored app rather than +allowing for storage of such information in the backup. +
                • Files related to app debugging, such as instant run files. To exclude instant run files, add the rule <exclude +domain="file" path="instant-run"/> +
                • Large files that cause the app to exceed the 25MB backup quota.
                +
              + +

              Note: If your configuration file specifies both elements, then the +backup contains everything captured by the <include> elements minus the +resources named in the <exclude> elements. In other words, +<exclude> takes precedence. + +

              Each element must include the following two attributes: +

                +
              • domain - specifies the location of resource. Valid values for this attribute +include the following:
                  +
                • root - the directory on the filesystem where all private files belonging to +this app are stored. +
                • file - directories returned by {@link android.content.Context#getFilesDir()}. +
                • database - directories returned by {@link android.content.Context#getDatabasePath(String) getDatabasePath()}. +Databases created with {@link android.database.sqlite.SQLiteOpenHelper} +are stored here. +
                • sharedpref - the directory where {@link android.content.SharedPreferences} +are stored. +
                • external the directory returned by {@link android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} +

                  Note: You cannot backup files outside of these locations.

                +
              • path: Specifies a file or folder to include in or exclude from backup. Note +that:
                  +
                • This attribute does not support wildcard or regex syntax. +
                • You can use . to reference the current directory, however, you cannot +reference the parent directory .. for security reasons. +
                • If you specify a directory, then the rule applies to all files in the +directory and recursive sub-directories.
              + +

              Implementing BackupAgent

              +

              Apps that implement Auto Backup do not need to implement {@link android.app.backup.BackupAgent}. However, you can optionally implement a custom {@link android.app.backup.BackupAgent}. Typically, there are two reasons for doing this: +

                +
              • You want to receive notification of backup events such as, +{@link android.app.backup.BackupAgent#onRestoreFinished()} or {@link android.app.backup.BackupAgent#onQuotaExceeded(long,long)}. These callback methods are executed +even if the app is not running. +
              • You can't easily express the set of files you want to backup with XML rules. +In these very rare cases, you can implement a BackupAgent that overrides {@link android.app.backup.BackupAgent#onFullBackup(FullBackupDataOutput)} to +store what you want. To retain the system's default implementation, call the +corresponding method on the superclass with super.onFullBackup().
              + +

              Note: Your BackupAgent must +implement the abstract methods +{@link android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) onBackup()} +and {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}. +Those methods are used for Key/Value Backup. So if +you are not using Key/Value Backup, implement those methods and leave them blank. + +

              For more information, see +Extending +BackupAgent. \ No newline at end of file diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd index 619c79021870b596df90ed9718931cb1f1c41e81..a688c6e9889b0d661de7a5215c370e274aa9342f 100644 --- a/docs/html/guide/topics/data/backup.jd +++ b/docs/html/guide/topics/data/backup.jd @@ -1,930 +1,34 @@ -page.title=Data Backup -@jd:body - - -

              -
              - -

              Quickview

              -
                -
              • Back up the user's data to the cloud in case the user loses it
              • -
              • If the user upgrades to a new Android-powered device, your app can restore the user's -data onto the new device
              • -
              • Easily back up SharedPreferences and private files with BackupAgentHelper
              • -
              • Requires API Level 8
              • -
              - -

              In this document

              -
                -
              1. The Basics
              2. -
              3. Declaring the Backup Agent in Your Manifest
              4. -
              5. Registering for Android Backup Service
              6. -
              7. Extending BackupAgent -
                  -
                1. Required Methods
                2. -
                3. Performing backup
                4. -
                5. Performing restore
                6. -
                -
              8. -
              9. Extending BackupAgentHelper -
                  -
                1. Backing up SharedPreferences
                2. -
                3. Backing up Private Files
                4. -
                -
              10. -
              11. Checking the Restore Data Version
              12. -
              13. Requesting Backup
              14. -
              15. Requesting Restore
              16. -
              17. Testing Your Backup Agent
              18. -
              - -

              Key classes

              -
                -
              1. {@link android.app.backup.BackupManager}
              2. -
              3. {@link android.app.backup.BackupAgent}
              4. -
              5. {@link android.app.backup.BackupAgentHelper}
              6. -
              - -

              See also

              -
                -
              1. {@code bmgr} tool
              2. -
              - -
              -
              - -

              Android's {@link android.app.backup backup} service allows you to copy your persistent -application data to remote "cloud" storage, in order to provide a restore point for the -application data and settings. If a user performs a factory reset or converts to a new -Android-powered device, the system automatically restores your backup data when the application -is re-installed. This way, your users don't need to reproduce their previous data or -application settings. This process is completely transparent to the user and does not affect the -functionality or user experience in your application.

              - -

              During a backup operation (which your application can request), Android's Backup Manager ({@link -android.app.backup.BackupManager}) queries your application for backup data, then hands it to -a backup transport, which then delivers the data to the cloud storage. During a -restore operation, the Backup Manager retrieves the backup data from the backup transport and -returns it to your application so your application can restore the data to the device. It's -possible for your application to request a restore, but that shouldn't be necessary—Android -automatically performs a restore operation when your application is installed and there exists -backup data associated with the user. The primary scenario in which backup data is restored is when -a user resets their device or upgrades to a new device and their previously installed -applications are re-installed.

              - -

              Note: The backup service is not designed for -synchronizing application data with other clients or saving data that you'd like to access during -the normal application lifecycle. You cannot read or write backup data on demand and cannot access -it in any way other than through the APIs provided by the Backup Manager.

              - -

              The backup transport is the client-side component of Android's backup framework, which is -customizable by -the device manufacturer and service provider. The backup transport may differ from device to device -and which backup transport is available on any given device is transparent to your application. The -Backup Manager APIs isolate your application from the actual backup transport available on a given -device—your application communicates with the Backup Manager through a fixed set of APIs, -regardless of the underlying transport.

              - -

              Data backup is not guaranteed to be available on all Android-powered -devices. However, your application is not adversely affected in the event -that a device does not provide a backup transport. If you believe that users will benefit from data -backup in your application, then you can implement it as described in this document, test it, then -publish your application without any concern about which devices actually perform backup. When your -application runs on a device that does not provide a backup transport, your application operates -normally, but will not receive callbacks from the Backup Manager to backup data.

              - -

              Although you cannot know what the current transport is, you are always assured that your -backup data cannot be read by other applications on the device. Only the Backup Manager and backup -transport have access to the data you provide during a backup operation.

              - -

              Caution: Because the cloud storage and transport service can -differ from device to device, Android makes no guarantees about the security of your data while -using backup. You should always be cautious about using backup to store sensitive data, such as -usernames and passwords.

              - - -

              The Basics

              - -

              To backup your application data, you need to implement a backup agent. Your backup -agent is called by the Backup Manager to provide the data you want to back up. It is also called -to restore your backup data when the application is re-installed. The Backup Manager handles all -your data transactions with the cloud storage (using the backup transport) and your backup agent -handles all your data transactions on the device.

              - -

              To implement a backup agent, you must:

              - -
                -
              1. Declare your backup agent in your manifest file with the {@code -android:backupAgent} attribute.
              2. -
              3. Register your application with a backup service. Google offers Android Backup Service as a backup -service for most Android-powered devices, which requires that you register your application in -order for it to work. Any other backup services available might also require you to register -in order to store your data on their servers.
              4. -
              5. Define a backup agent by either:

                -
                  -
                1. Extending BackupAgent -

                  The {@link android.app.backup.BackupAgent} class provides the central interface with -which your application communicates with the Backup Manager. If you extend this class -directly, you must override {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} to handle the backup and restore operations for your data.

                  -

                  Or

                  -
                2. Extending BackupAgentHelper -

                  The {@link android.app.backup.BackupAgentHelper} class provides a convenient -wrapper around the {@link android.app.backup.BackupAgent} class, which minimizes the amount of code -you need to write. In your {@link android.app.backup.BackupAgentHelper}, you must use one or more -"helper" objects, which automatically backup and restore certain types of data, so that you do not -need to implement {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}.

                  -

                  Android currently provides backup helpers that will backup and restore complete files -from {@link android.content.SharedPreferences} and internal storage.

                  -
                3. -
                -
              6. -
              - - - -

              Declaring the Backup Agent in Your Manifest

              - -

              This is the easiest step, so once you've decided on the class name for your backup agent, declare -it in your manifest with the {@code -android:backupAgent} attribute in the {@code -} tag.

              - -

              For example:

              - -
              -<manifest ... >
              -    ...
              -    <application android:label="MyApplication"
              -                 android:backupAgent="MyBackupAgent">
              -        <activity ... >
              -            ...
              -        </activity>
              -    </application>
              -</manifest>
              -
              - -

              Another attribute you might want to use is {@code -android:restoreAnyVersion}. This attribute takes a boolean value to indicate whether you -want to restore the application data regardless of the current application version compared to the -version that produced the backup data. (The default value is "{@code false}".) See Checking the Restore Data Version for more information.

              - -

              Note: The backup service and the APIs you must use are -available only on devices running API Level 8 (Android 2.2) or greater, so you should also -set your {@code android:minSdkVersion} -attribute to "8".

              - - - - -

              Registering for Android Backup Service

              - -

              Google provides a backup transport with Android Backup Service for most -Android-powered devices running Android 2.2 or greater.

              - -

              In order for your application to perform backup using Android Backup Service, you must -register your application with the service to receive a Backup Service Key, then -declare the Backup Service Key in your Android manifest.

              - -

              To get your Backup Service Key, register for Android Backup Service. -When you register, you will be provided a Backup Service Key and the appropriate {@code -} XML code for your Android manifest file, which you must include as a child of the -{@code } element. For example:

              - -
              -<application android:label="MyApplication"
              -             android:backupAgent="MyBackupAgent">
              -    ...
              -    <meta-data android:name="com.google.android.backup.api_key"
              -        android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" />
              -</application>
              -
              - -

              The android:name must be "com.google.android.backup.api_key" and -the android:value must be the Backup Service Key received from the Android Backup -Service registration.

              - -

              If you have multiple applications, you must register each one, using the respective package -name.

              - -

              Note: The backup transport provided by Android Backup Service is -not guaranteed to be available -on all Android-powered devices that support backup. Some devices might support backup -using a different transport, some devices might not support backup at all, and there is no way for -your application to know what transport is used on the device. However, if you implement backup for -your application, you should always include a Backup Service Key for Android Backup Service so -your application can perform backup when the device uses the Android Backup Service transport. If -the device does not use Android Backup Service, then the {@code } element with the -Backup Service Key is ignored.

              - - - - -

              Extending BackupAgent

              - -

              Most applications shouldn't need to extend the {@link android.app.backup.BackupAgent} class -directly, but should instead extend BackupAgentHelper to take -advantage of the built-in helper classes that automatically backup and restore your files. However, -you might want to extend {@link android.app.backup.BackupAgent} directly if you need to:

              -
                -
              • Version your data format. For instance, if you anticipate the need to revise the -format in which you write your application data, you can build a backup agent to cross-check your -application version during a restore operation and perform any necessary compatibility work if the -version on the device is different than that of the backup data. For more information, see Checking the Restore Data Version.
              • -
              • Instead of backing up an entire file, you can specify the portions of data the should be -backed up and how each portion is then restored to the device. (This can also help you manage -different versions, because you read and write your data as unique entities, rather than -complete files.)
              • -
              • Back up data in a database. If you have an SQLite database that you want to restore when -the user re-installs your application, you need to build a custom {@link -android.app.backup.BackupAgent} that reads the appropriate data during a backup operation, then -create your table and insert the data during a restore operation.
              • -
              - -

              If you don't need to perform any of the tasks above and want to back up complete files from -{@link android.content.SharedPreferences} or internal storage, you -should skip to Extending BackupAgentHelper.

              - - - -

              Required Methods

              - -

              When you create a backup agent by extending {@link android.app.backup.BackupAgent}, you -must implement the following callback methods:

              - -
              -
              {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}
              -
              The Backup Manager calls this method after you request a -backup. In this method, you read your application data from the device and pass the data you -want to back up to the Backup Manager, as described below in Performing -backup.
              - -
              {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}
              -
              The Backup Manager calls this method during a restore operation (you can request a restore, but the system automatically performs restore when -the user re-installs your application). When it calls this method, the Backup Manager delivers your -backup data, which you then restore to the device, as described below in Performing restore.
              -
              - - - -

              Performing backup

              - - -

              When it's time to back up your application data, the Backup Manager calls your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. This is where you must provide your application data to the Backup Manager so -it can be saved to cloud storage.

              - -

              Only the Backup Manager can call your backup agent's {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. Each time that your application data changes and you want to perform a backup, -you must request a backup operation by calling {@link -android.app.backup.BackupManager#dataChanged()} (see Requesting -Backup for more information). A backup request does not result in an immediate call to your -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. Instead, the Backup Manager waits for an appropriate time, then performs -backup for all applications that have requested a backup since the last backup was performed.

              - -

              Tip: While developing your application, you can initiate an -immediate backup operation from the Backup Manager with the {@code bmgr} tool.

              - -

              When the Backup Manager calls your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method, it passes three parameters:

              - -
              -
              {@code oldState}
              -
              An open, read-only {@link android.os.ParcelFileDescriptor} pointing to the last backup -state provided by your application. This is not the backup data from cloud storage, but a -local representation of the data that was backed up the last time {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} was called (as defined by {@code newState}, below, or from {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}—more about this in the next section). Because {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} does not allow you to read existing backup data in -the cloud storage, you can use this local representation to determine whether your data has changed -since the last backup.
              -
              {@code data}
              -
              A {@link android.app.backup.BackupDataOutput} object, which you use to deliver your backup -data to the Backup Manager.
              -
              {@code newState}
              -
              An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which -you must write a representation of the data that you delivered to {@code data} (a representation -can be as simple as the last-modified timestamp for your file). This object is -returned as {@code oldState} the next time the Backup Manager calls your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method. If you do not write your backup data to {@code newState}, then {@code oldState} -will point to an empty file next time Backup Manager calls {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}.
              -
              - -

              Using these parameters, you should implement your {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method to do the following:

              - -
                -
              1. Check whether your data has changed since the last backup by comparing {@code oldState} to -your current data. How you read data in {@code oldState} depends on how you originally wrote it to -{@code newState} (see step 3). The easiest way to record the state of a file is with its -last-modified timestamp. For example, here's how you can read and compare a timestamp from {@code -oldState}: -
                -// Get the oldState input stream
                -FileInputStream instream = new FileInputStream(oldState.getFileDescriptor());
                -DataInputStream in = new DataInputStream(instream);
                -
                -try {
                -    // Get the last modified timestamp from the state file and data file
                -    long stateModified = in.readLong();
                -    long fileModified = mDataFile.lastModified();
                -
                -    if (stateModified != fileModified) {
                -        // The file has been modified, so do a backup
                -        // Or the time on the device changed, so be safe and do a backup
                -    } else {
                -        // Don't back up because the file hasn't changed
                -        return;
                -    }
                -} catch (IOException e) {
                -    // Unable to read state file... be safe and do a backup
                -}
                -
                -

                If nothing has changed and you don't need to back up, skip to step 3.

                -
              2. -
              3. If your data has changed, compared to {@code oldState}, write the current data to -{@code data} to back it up to the cloud storage. -

                You must write each chunk of data as an "entity" in the {@link -android.app.backup.BackupDataOutput}. An entity is a flattened binary data -record that is identified by a unique key string. Thus, the data set that you back up is -conceptually a set of key-value pairs.

                -

                To add an entity to your backup data set, you must:

                -
                  -
                1. Call {@link android.app.backup.BackupDataOutput#writeEntityHeader(String,int) -writeEntityHeader()}, passing a unique string key for the data you're about to write and the data -size.
                2. -
                3. Call {@link android.app.backup.BackupDataOutput#writeEntityData(byte[],int) -writeEntityData()}, passing a byte buffer that contains your data and the number of bytes to write -from the buffer (which should match the size passed to {@link -android.app.backup.BackupDataOutput#writeEntityHeader(String,int) writeEntityHeader()}).
                4. -
                -

                For example, the following code flattens some data into a byte stream and writes it into a -single entity:

                -
                -// Create buffer stream and data output stream for our data
                -ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
                -DataOutputStream outWriter = new DataOutputStream(bufStream);
                -// Write structured data
                -outWriter.writeUTF(mPlayerName);
                -outWriter.writeInt(mPlayerScore);
                -// Send the data to the Backup Manager via the BackupDataOutput
                -byte[] buffer = bufStream.toByteArray();
                -int len = buffer.length;
                -data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len);
                -data.writeEntityData(buffer, len);
                -
                -

                Perform this for each piece of data that you want to back up. How you divide your data into -entities is up to you (and you might use just one entity).

                -
              4. -
              5. Whether or not you perform a backup (in step 2), write a representation of the current data to -the {@code newState} {@link android.os.ParcelFileDescriptor}. The Backup Manager retains this object -locally as a representation of the data that is currently backed up. It passes this back to you as -{@code oldState} the next time it calls {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} so you can determine whether another backup is necessary (as handled in step 1). If you -do not write the current data state to this file, then -{@code oldState} will be empty during the next callback. -

                The following example saves a representation of the current data into {@code newState} using -the file's last-modified timestamp:

                -
                -FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
                -DataOutputStream out = new DataOutputStream(outstream);
                -
                -long modified = mDataFile.lastModified();
                -out.writeLong(modified);
                -
                -
              6. -
              - -

              Caution: If your application data is saved to a file, make sure -that you use synchronized statements while accessing the file so that your backup agent does not -read the file while an Activity in your application is also writing the file.

              - - - - -

              Performing restore

              - -

              When it's time to restore your application data, the Backup Manager calls your backup -agent's {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} method. When it calls this method, the Backup Manager delivers your backup data so -you can restore it onto the device.

              - -

              Only the Backup Manager can call {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}, which happens automatically when the system installs your application and -finds existing backup data. However, you can request a restore operation for -your application by calling {@link -android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} (see Requesting restore for more information).

              - -

              Note: While developing your application, you can also request a -restore operation with the {@code bmgr} -tool.

              - -

              When the Backup Manager calls your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} method, it passes three parameters:

              - -
              -
              {@code data}
              -
              A {@link android.app.backup.BackupDataInput}, which allows you to read your backup -data.
              -
              {@code appVersionCode}
              -
              An integer representing the value of your application's {@code android:versionCode} -manifest attribute, as it was when this data was backed up. You can use this to cross-check the -current application version and determine if the data format is compatible. For more -information about using this to handle different versions of restore data, see the section -below about Checking the Restore Data Version.
              -
              {@code newState}
              -
              An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which -you must write the final backup state that was provided with {@code data}. This object is -returned as {@code oldState} the next time {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} is called. Recall that you must also write the same {@code newState} object in the -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} callback—also doing it here ensures that the {@code oldState} object given to -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} is valid even the first time {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} is called after the device is restored.
              -
              - -

              In your implementation of {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} on the -{@code data} to iterate -through all entities in the data set. For each entity found, do the following:

              - -
                -
              1. Get the entity key with {@link android.app.backup.BackupDataInput#getKey()}.
              2. -
              3. Compare the entity key to a list of known key values that you should have declared as static -final strings inside your {@link android.app.backup.BackupAgent} class. When the key matches one of -your known key strings, enter into a statement to extract the entity data and save it to the device: -
                  -
                1. Get the entity data size with {@link -android.app.backup.BackupDataInput#getDataSize()} and create a byte array of that size.
                2. -
                3. Call {@link android.app.backup.BackupDataInput#readEntityData(byte[],int,int) -readEntityData()} and pass it the byte array, which is where the data will go, and specify the -start offset and the size to read.
                4. -
                5. Your byte array is now full and you can read the data and write it to the device -however you like.
                6. -
                -
              4. -
              5. After you read and write your data back to the device, write the state of your data to the -{@code newState} parameter the same as you do during {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}. -
              +page.title=Backing up App Data to the Cloud +page.tags=cloud,sync,backup -

              For example, here's how you can restore the data backed up by the example in the previous -section:

              - -
              -@Override
              -public void onRestore(BackupDataInput data, int appVersionCode,
              -                      ParcelFileDescriptor newState) throws IOException {
              -    // There should be only one entity, but the safest
              -    // way to consume it is using a while loop
              -    while (data.readNextHeader()) {
              -        String key = data.getKey();
              -        int dataSize = data.getDataSize();
              -
              -        // If the key is ours (for saving top score). Note this key was used when
              -        // we wrote the backup entity header
              -        if (TOPSCORE_BACKUP_KEY.equals(key)) {
              -            // Create an input stream for the BackupDataInput
              -            byte[] dataBuf = new byte[dataSize];
              -            data.readEntityData(dataBuf, 0, dataSize);
              -            ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
              -            DataInputStream in = new DataInputStream(baStream);
              -
              -            // Read the player name and score from the backup data
              -            mPlayerName = in.readUTF();
              -            mPlayerScore = in.readInt();
              -
              -            // Record the score on the device (to a file or something)
              -            recordScore(mPlayerName, mPlayerScore);
              -        } else {
              -            // We don't know this entity key. Skip it. (Shouldn't happen.)
              -            data.skipEntityData();
              -        }
              -    }
              -
              -    // Finally, write to the state blob (newState) that describes the restored data
              -    FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
              -    DataOutputStream out = new DataOutputStream(outstream);
              -    out.writeUTF(mPlayerName);
              -    out.writeInt(mPlayerScore);
              -}
              -
              - -

              In this example, the {@code appVersionCode} parameter passed to {@link -android.app.backup.BackupAgent#onRestore onRestore()} is not used. However, you might want to use -it if you've chosen to perform backup when the user's version of the application has actually moved -backward (for example, the user went from version 1.5 of your app to 1.0). For more information, see -the section about Checking the Restore Data Version.

              - -
              -

              For an example implementation of {@link android.app.backup.BackupAgent}, see the {@code -ExampleAgent} class in the Backup and Restore sample -application.

              -
              - - - - - - -

              Extending BackupAgentHelper

              - -

              You should build your backup agent using {@link android.app.backup.BackupAgentHelper} if you want -to back up complete files (from either {@link android.content.SharedPreferences} or internal storage). -Building your backup agent with {@link android.app.backup.BackupAgentHelper} requires far less -code than extending {@link android.app.backup.BackupAgent}, because you don't have to implement -{@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}.

              - -

              Your implementation of {@link android.app.backup.BackupAgentHelper} must -use one or more backup helpers. A backup helper is a specialized -component that {@link android.app.backup.BackupAgentHelper} summons to perform backup and -restore operations for a particular type of data. The Android framework currently provides two -different helpers:

              -
                -
              • {@link android.app.backup.SharedPreferencesBackupHelper} to backup {@link -android.content.SharedPreferences} files.
              • -
              • {@link android.app.backup.FileBackupHelper} to backup files from internal storage.
              • -
              - -

              You can include multiple helpers in your {@link android.app.backup.BackupAgentHelper}, but only -one helper is needed for each data type. That is, if you have multiple {@link -android.content.SharedPreferences} files, then you need only one {@link -android.app.backup.SharedPreferencesBackupHelper}.

              - -

              For each helper you want to add to your {@link android.app.backup.BackupAgentHelper}, you must do -the following during your {@link android.app.backup.BackupAgent#onCreate()} method:

              -
                -
              1. Instantiate in instance of the desired helper class. In the class constructor, you must -specify the appropriate file(s) you want to backup.
              2. -
              3. Call {@link android.app.backup.BackupAgentHelper#addHelper(String,BackupHelper) addHelper()} -to add the helper to your {@link android.app.backup.BackupAgentHelper}.
              4. -
              - -

              The following sections describe how to create a backup agent using each of the available -helpers.

              - - - -

              Backing up SharedPreferences

              - -

              When you instantiate a {@link android.app.backup.SharedPreferencesBackupHelper}, you must -include the name of one or more {@link android.content.SharedPreferences} files.

              - -

              For example, to back up a {@link android.content.SharedPreferences} file named -"user_preferences", a complete backup agent using {@link android.app.backup.BackupAgentHelper} looks -like this:

              - -
              -public class MyPrefsBackupAgent extends BackupAgentHelper {
              -    // The name of the SharedPreferences file
              -    static final String PREFS = "user_preferences";
              -
              -    // A key to uniquely identify the set of backup data
              -    static final String PREFS_BACKUP_KEY = "prefs";
              -
              -    // Allocate a helper and add it to the backup agent
              -    @Override
              -    public void onCreate() {
              -        SharedPreferencesBackupHelper helper =
              -                new SharedPreferencesBackupHelper(this, PREFS);
              -        addHelper(PREFS_BACKUP_KEY, helper);
              -    }
              -}
              -
              - -

              That's it! That's your entire backup agent. The {@link -android.app.backup.SharedPreferencesBackupHelper} includes all the code -needed to backup and restore a {@link android.content.SharedPreferences} file.

              - -

              When the Backup Manager calls {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()}, {@link android.app.backup.BackupAgentHelper} calls your backup helpers to perform -backup and restore for your specified files.

              - -

              Note: {@link android.content.SharedPreferences} are threadsafe, so -you can safely read and write the shared preferences file from your backup agent and -other activities.

              - - - -

              Backing up other files

              - -

              When you instantiate a {@link android.app.backup.FileBackupHelper}, you must include the name of -one or more files that are saved to your application's internal storage -(as specified by {@link android.content.ContextWrapper#getFilesDir()}, which is the same -location where {@link android.content.Context#openFileOutput(String,int) openFileOutput()} writes -files).

              - -

              For example, to backup two files named "scores" and "stats," a backup agent using {@link -android.app.backup.BackupAgentHelper} looks like this:

              - -
              -public class MyFileBackupAgent extends BackupAgentHelper {
              -    // The name of the file
              -    static final String TOP_SCORES = "scores";
              -    static final String PLAYER_STATS = "stats";
              -
              -    // A key to uniquely identify the set of backup data
              -    static final String FILES_BACKUP_KEY = "myfiles";
              -
              -    // Allocate a helper and add it to the backup agent
              -    @Override
              -    public void onCreate() {
              -        FileBackupHelper helper = new FileBackupHelper(this,
              -                TOP_SCORES, PLAYER_STATS);
              -        addHelper(FILES_BACKUP_KEY, helper);
              -    }
              -}
              -
              - -

              The {@link android.app.backup.FileBackupHelper} includes all the code necessary to backup and -restore files that are saved to your application's internal storage..

              - -

              However, reading and writing to files on internal storage is not threadsafe. To -ensure that your backup agent does not read or write your files at the same time as your activities, -you must use synchronized statements each time you perform a read or write. For example, -in any Activity where you read and write the file, you need an object to use as the intrinsic -lock for the synchronized statements:

              - -
              -// Object for intrinsic lock
              -static final Object sDataLock = new Object();
              -
              - -

              Then create a synchronized statement with this lock each time you read or write the files. For -example, here's a synchronized statement for writing the latest score in a game to a file:

              - -
              -try {
              -    synchronized (MyActivity.sDataLock) {
              -        File dataFile = new File({@link android.content.Context#getFilesDir()}, TOP_SCORES);
              -        RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
              -        raFile.writeInt(score);
              -    }
              -} catch (IOException e) {
              -    Log.e(TAG, "Unable to write to file");
              -}
              -
              - -

              You should synchronize your read statements with the same lock.

              - -

              Then, in your {@link android.app.backup.BackupAgentHelper}, you must override {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} to synchronize the backup and restore operations with the same -intrinsic lock. For example, the {@code MyFileBackupAgent} example from above needs the following -methods:

              - -
              -@Override
              -public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
              -          ParcelFileDescriptor newState) throws IOException {
              -    // Hold the lock while the FileBackupHelper performs backup
              -    synchronized (MyActivity.sDataLock) {
              -        super.onBackup(oldState, data, newState);
              -    }
              -}
              -
              -@Override
              -public void onRestore(BackupDataInput data, int appVersionCode,
              -        ParcelFileDescriptor newState) throws IOException {
              -    // Hold the lock while the FileBackupHelper restores the file
              -    synchronized (MyActivity.sDataLock) {
              -        super.onRestore(data, appVersionCode, newState);
              -    }
              -}
              -
              - -

              That's it. All you need to do is add your {@link android.app.backup.FileBackupHelper} in the -{@link android.app.backup.BackupAgent#onCreate()} method and override {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} and {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) -onRestore()} to synchronize read and write operations.

              - -
              -

              For an example implementation of {@link -android.app.backup.BackupAgentHelper} with {@link android.app.backup.FileBackupHelper}, see the -{@code FileHelperExampleAgent} class in the Backup and Restore sample -application.

              -
              - - - - - - -

              Checking the Restore Data Version

              - -

              When the Backup Manager saves your data to cloud storage, it automatically includes the version -of your application, as defined by your manifest file's {@code android:versionCode} -attribute. Before the Backup Manager calls your backup agent to restore your data, it -looks at the {@code -android:versionCode} of the installed application and compares it to the value -recorded in the restore data set. If the version recorded in the restore data set is -newer than the application version on the device, then the user has downgraded their -application. In this case, the Backup Manager will abort the restore operation for your application -and not call your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method, because the restore set is considered meaningless to an older version.

              - -

              You can override this behavior with the {@code -android:restoreAnyVersion} attribute. This attribute is either "{@code true}" or "{@code -false}" to indicate whether you want to restore the application regardless of the restore set -version. The default value is "{@code false}". If you define this to be "{@code true}" then the -Backup Manager will ignore the {@code android:versionCode} -and call your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method in all cases. In doing so, you can manually check for the version difference in your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method and take any steps necessary to make the data compatible if the versions conflict.

              - -

              To help you handle different versions during a restore operation, the {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -method passes you the version code included with the restore data set as the {@code appVersionCode} -parameter. You can then query the current application's version code with the {@link -android.content.pm.PackageInfo#versionCode PackageInfo.versionCode} field. For example:

              - -
              -PackageInfo info;
              -try {
              -    String name = {@link android.content.ContextWrapper#getPackageName() getPackageName}();
              -    info = {@link android.content.ContextWrapper#getPackageManager
              -getPackageManager}().{@link android.content.pm.PackageManager#getPackageInfo(String,int)
              -getPackageInfo}(name,0);
              -} catch (NameNotFoundException nnfe) {
              -    info = null;
              -}
              -
              -int version;
              -if (info != null) {
              -    version = info.versionCode;
              -}
              -
              - -

              Then simply compare the {@code version} acquired from {@link android.content.pm.PackageInfo} -to the {@code appVersionCode} passed into {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}. -

              - -

              Caution: Be certain you understand the consequences of setting -{@code -android:restoreAnyVersion} to "{@code true}" for your application. If each version of your -application that supports backup does not properly account for variations in your data format during -{@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}, -then the data on the device could be saved in a format incompatible with the version currently -installed on the device.

              - - - -

              Requesting Backup

              - -

              You can request a backup operation at any time by calling {@link -android.app.backup.BackupManager#dataChanged()}. This method notifies the Backup Manager that you'd -like to backup your data using your backup agent. The Backup Manager then calls your backup -agent's {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()} method at an opportune time in the future. Typically, you should -request a backup each time your data changes (such as when the user changes an application -preference that you'd like to back up). If you call {@link -android.app.backup.BackupManager#dataChanged()} several times consecutively, before the Backup -Manager requests a backup from your agent, your agent still receives just one call to {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) -onBackup()}.

              - -

              Note: While developing your application, you can request a -backup and initiate an immediate backup operation with the {@code bmgr} -tool.

              - - -

              Requesting Restore

              - -

              During the normal life of your application, you shouldn't need to request a restore operation. -They system automatically checks for backup data and performs a restore when your application is -installed. However, you can manually request a restore operation by calling {@link -android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()}, if necessary. In -which case, the Backup Manager calls your {@link -android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} -implementation, passing the data from the current set of backup data.

              - -

              Note: While developing your application, you can request a -restore operation with the {@code bmgr} -tool.

              - - -

              Testing Your Backup Agent

              - -

              Once you've implemented your backup agent, you can test the backup and restore functionality -with the following procedure, using {@code bmgr}.

              - -
                -
              1. Install your application on a suitable Android system image -
                  -
                • If using the emulator, create and use an AVD with Android 2.2 (API Level 8).
                • -
                • If using a device, the device must be running Android 2.2 or greater and have Google -Play built in.
                • -
                -
              2. -
              3. Ensure that backup is enabled -
                  -
                • If using the emulator, you can enable backup with the following command from your SDK -{@code tools/} path: -
                  adb shell bmgr enable true
                  -
                • -
                • If using a device, open the system Settings, select - Backup & reset, then enable - Back up my data and Automatic restore.
                • -
                -
              4. -
              5. Open your application and initialize some data -

                If you've properly implemented backup in your application, then it should request a -backup each time the data changes. For example, each time the user changes some data, your app -should call {@link android.app.backup.BackupManager#dataChanged()}, which adds a backup request to -the Backup Manager queue. For testing purposes, you can also make a request with the following -{@code bmgr} command:

                -
                adb shell bmgr backup your.package.name
                -
              6. -
              7. Initiate a backup operation: -
                adb shell bmgr run
                -

                This forces the Backup Manager to perform all backup requests that are in its -queue.

                -
              8. Uninstall your application: -
                adb uninstall your.package.name
                -
              9. -
              10. Re-install your application.
              11. -
              - -

              If your backup agent is successful, all the data you initialized in step 4 is restored.

              +startpage=true +@jd:body +

              Users often invest significant time and effort creating data and setting +preferences within apps. Preserving that data for users if they replace a broken +device or upgrade to a new one is an important part of ensuring a great user +experience. This section covers techniques for backing up data to the cloud so +that users can restore their data. + +

              Android provides two ways for apps to backup their data to the cloud: +Auto Backup for Apps and +Key/Value Backup. +Auto Backup, which is available starting API 23, preserves app data by uploading +it to the user’s Google Drive account. The Key/Value Backup feature (formerly +known as the Backup API and the Android Backup Service) preserves app data by +uploading it to the Android Backup Service. + +

              Generally, we recommend Auto Backup because it requires no work to implement. +Apps that target Android 6.0 (API level 23) or higher are automatically enabled +for Auto Backup. The Auto Backup feature does have some limitations in terms of +what data it can backup and it's availability on Android 6.0 and higher devices. +Consider using the Key/Value Backup feature if you have more specific needs for +backing up your app data. For more information, see Comparison of Key/Value and Auto Backup

              + +

              Note: These data backup features are not designed for synchronizing app data with other clients or +saving data that you'd like to access during the normal application lifecycle. +You cannot read or write backup data on demand. For synchronizing app data, see +Transferring +Data Using Sync Adapters or Google Drive Android +API. \ No newline at end of file diff --git a/docs/html/guide/topics/data/data-storage.jd b/docs/html/guide/topics/data/data-storage.jd index a745d00f5e39cb4872f3cde4b22a8725f5a3e816..770340be2e003fe500ce7dc33c3daad189b2f821 100644 --- a/docs/html/guide/topics/data/data-storage.jd +++ b/docs/html/guide/topics/data/data-storage.jd @@ -252,6 +252,17 @@ external storage on a computer or removes the media, and there's no security enf save to the external storage. All applications can read and write files placed on the external storage and the user can remove them.

              +

              Using Scoped Directory Access

              + +On Android 7.0 or later, if you need access to a specific directory on +external storage, use scoped directory access. Scoped directory access +simplifies how your application accesses standard external storage directories, +such as the Pictures directory, and provides a simple +permissions UI that clearly details what directory the application is +requesting access to. For more details on scoped directory access, see +Using +Scoped Directory Access. +

              Getting access to external storage

              In order to read or write files on the external storage, your app must acquire the diff --git a/docs/html/guide/topics/data/images/backup-framework.png b/docs/html/guide/topics/data/images/backup-framework.png new file mode 100644 index 0000000000000000000000000000000000000000..2ba2e612c9bd34a5412141818a3817d38434b35c Binary files /dev/null and b/docs/html/guide/topics/data/images/backup-framework.png differ diff --git a/docs/html/guide/topics/data/index.jd b/docs/html/guide/topics/data/index.jd index 1e082b3fef95fd6bc53c75db6fde12e294d86782..2365f18aaeb813b643676cc920d6baf55b626f86 100644 --- a/docs/html/guide/topics/data/index.jd +++ b/docs/html/guide/topics/data/index.jd @@ -1,23 +1,7 @@ page.title=Data Storage page.landing=true -page.landing.intro=Store application data in databases, files, or preferences, in internal or removeable storage. You can also add a data backup service to let users store and recover application and system data. +page.landing.intro=Store application data in databases, files, or preferences, in internal or removeable storage. You can also add a data backup service to let users store and recover application and system data. page.landing.image= @jd:body -

              \ No newline at end of file diff --git a/docs/html/guide/topics/data/keyvaluebackup.jd b/docs/html/guide/topics/data/keyvaluebackup.jd new file mode 100644 index 0000000000000000000000000000000000000000..c7c5e2fd0ce15b24d5d7d98ea9c02e441a7b707e --- /dev/null +++ b/docs/html/guide/topics/data/keyvaluebackup.jd @@ -0,0 +1,884 @@ +page.title=Key/Value Backup +page.tags=backup, marshmallow, androidm +page.keywords=backup, kvbackup + +@jd:body + + + + +

              Since Android 2.2 (API 8), Android has offered the Key/Value Backup +feature as a way for developers to backup app data to the cloud. The Key/Value +Backup feature (formerly known as the Backup API and the Android Backup Service) +preserves app data by uploading it to +Android Backup Service. +The amount of data is limited to 5MB per user of your app and there is +no charge for storing backup data. + +

              Note: If your app implements Key/Value Backup +and targets API 23 or higher, you should set +android:fullBackupOnly. +This attribute indicates whether or not to use Auto Backup on devices where it is available. + +

              Comparison to Auto Backup

              +

              Like Auto Backup, Key/Value Backups are restored automatically whenever the app +is installed. The following table describes some of the key differences between Key/Value Backup and Auto Backup: + +

            Listener interface
            {@link android.net.wifi.p2p.WifiP2pManager#WIFI_P2P_PEERS_CHANGED_ACTION} Broadcast when you call {@link - android.net.wifi.p2p.WifiP2pManager.PeerListListener#discoverPeers discoverPeers()}. You - usually want to call {@link android.net.wifi.p2p.WifiP2pManager.PeerListListener#requestPeers + android.net.wifi.p2p.WifiP2pManager#discoverPeers discoverPeers()}. You + usually want to call {@link android.net.wifi.p2p.WifiP2pManager#requestPeers requestPeers()} to get an updated list of peers if you handle this intent in your application.
            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            Key/Value BackupAuto Backup
            Available in API 8, Android 2.2Available in API 23, Android 6.0
            Apps must implement a {@link android.app.backup.BackupAgent}. The backup agent defines what data to backup and how to +restore data.By default, Auto Backup includes almost all of the app's files. You can +use XML to include and exclude files. Under the hood, Auto Backup relies on a +backup agent that is built into the framework.
            Apps must issue a request when there is data +that is ready to be backed up. Requests +from multiple apps are batched and executed every few hours.Backups happen automatically roughly once a day.
            Backup data can be transmitted via wifi or cellular data.Backup data is tranmitted only via wifi. If the device is never connected to a +wifi network, then Auto Backup never occurs.
            Apps are not shut down during backup.The system shuts down the app during backup.
            Backup data is stored in Android Backup Service limited to 5MB per app.Backup data is stored in the user's Google Drive limited to 25MB per app.
            Related API methods are not filed based:
              +
            • {@link android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor) onBackup()} +
            • {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, ParcelFileDescriptor) onRestore()}
            Related API methods are filed based:
              +
            • {@link android.app.backup.BackupAgent#onFullBackup(FullBackupDataOutput) onFullBackup()} +
            • {@link android.app.backup.BackupAgent#onRestoreFile(ParcelFileDescriptor,long,File,int,long,long) onRestoreFile()}
            + +

            Implementing Key/Value Backup

            +

            To backup your application data, you need to implement a backup agent. Your backup +agent is called by the Backup Manager both during backup and restore.

            + +

            To implement a backup agent, you must:

            + +
              +
            1. Declare your backup agent in your manifest file with the {@code +android:backupAgent} attribute.
            2. +
            3. Register your application with Android + Backup Service
            4. +
            5. Define a backup agent by either:

              +
                +
              1. Extending BackupAgent +

                The {@link android.app.backup.BackupAgent} class provides the central interface with +which your application communicates with the Backup Manager. If you extend this class +directly, you must override {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} to handle the backup and restore operations for your data.

                +

                Or

                +
              2. Extending BackupAgentHelper +

                The {@link android.app.backup.BackupAgentHelper} class provides a convenient +wrapper around the {@link android.app.backup.BackupAgent} class, which minimizes the amount of code +you need to write. In your {@link android.app.backup.BackupAgentHelper}, you must use one or more +"helper" objects, which automatically backup and restore certain types of data, so that you do not +need to implement {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}.

                +

                Android currently provides backup helpers that will backup and restore complete files +from {@link android.content.SharedPreferences} and internal storage.

                +
              3. +
              +
            6. +
            + +

            Declaring the backup agent in your manifest

            + +

            This is the easiest step, so once you've decided on the class name for your backup agent, declare +it in your manifest with the {@code +android:backupAgent} attribute in the {@code +} tag.

            + +

            For example:

            + +
            +<manifest ... >
            +    ...
            +    <application android:label="MyApplication"
            +                 android:backupAgent="MyBackupAgent">
            +        <activity ... >
            +            ...
            +        </activity>
            +    </application>
            +</manifest>
            +
            + +

            Another attribute you might want to use is {@code +android:restoreAnyVersion}. This attribute takes a boolean value to indicate whether you +want to restore the application data regardless of the current application version compared to the +version that produced the backup data. (The default value is "{@code false}".) See Checking the Restore Data Version for more information.

            + +

            Note: The backup service and the APIs you must use are +available only on devices running API Level 8 (Android 2.2) or greater, so you should also +set your {@code android:minSdkVersion} +attribute to "8".

            + + + + +

            Registering for Android Backup Service

            + +

            Google provides a backup transport with Android Backup Service for most +Android-powered devices running Android 2.2 or greater.

            + +

            In order for your application to perform backup using Android Backup Service, you must +register your application with the service to receive a Backup Service Key, then +declare the Backup Service Key in your Android manifest.

            + +

            To get your Backup Service Key, register for Android Backup Service. +When you register, you will be provided a Backup Service Key and the appropriate {@code +} XML code for your Android manifest file, which you must include as a child of the +{@code } element. For example:

            + +
            +<application android:label="MyApplication"
            +             android:backupAgent="MyBackupAgent">
            +    ...
            +    <meta-data android:name="com.google.android.backup.api_key"
            +        android:value="AEdPqrEAAAAIDaYEVgU6DJnyJdBmU7KLH3kszDXLv_4DIsEIyQ" />
            +</application>
            +
            + +

            The android:name must be "com.google.android.backup.api_key" and +the android:value must be the Backup Service Key received from the Android Backup +Service registration.

            + +

            If you have multiple applications, you must register each one, using the respective package +name.

            + +

            Note: The backup transport provided by Android Backup Service is +not guaranteed to be available +on all Android-powered devices that support backup. Some devices might support backup +using a different transport, some devices might not support backup at all, and there is no way for +your application to know what transport is used on the device. However, if you implement backup for +your application, you should always include a Backup Service Key for Android Backup Service so +your application can perform backup when the device uses the Android Backup Service transport. If +the device does not use Android Backup Service, then the {@code } element with the +Backup Service Key is ignored.

            + + + + +

            Extending BackupAgent

            + +

            Most applications shouldn't need to extend the {@link android.app.backup.BackupAgent} class +directly, but should instead extend BackupAgentHelper to take +advantage of the built-in helper classes that automatically backup and restore your files. However, +you might want to extend {@link android.app.backup.BackupAgent} directly if you need to:

            +
              +
            • Version your data format. For instance, if you anticipate the need to revise the +format in which you write your application data, you can build a backup agent to cross-check your +application version during a restore operation and perform any necessary compatibility work if the +version on the device is different than that of the backup data. For more information, see Checking the Restore Data Version.
            • +
            • Instead of backing up an entire file, you can specify the portions of data the should be +backed up and how each portion is then restored to the device. (This can also help you manage +different versions, because you read and write your data as unique entities, rather than +complete files.)
            • +
            • Back up data in a database. If you have an SQLite database that you want to restore when +the user re-installs your application, you need to build a custom {@link +android.app.backup.BackupAgent} that reads the appropriate data during a backup operation, then +create your table and insert the data during a restore operation.
            • +
            + +

            If you don't need to perform any of the tasks above and want to back up complete files from +{@link android.content.SharedPreferences} or internal storage, you +should skip to Extending BackupAgentHelper.

            + + + +

            Required methods

            + +

            When you create a backup agent by extending {@link android.app.backup.BackupAgent}, you +must implement the following callback methods:

            + +
            +
            {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}
            +
            The Backup Manager calls this method after you request a +backup. In this method, you read your application data from the device and pass the data you +want to back up to the Backup Manager, as described below in Performing +backup.
            + +
            {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}
            +
            The Backup Manager calls this method during a restore operation (you can request a restore, but the system automatically performs restore when +the user re-installs your application). When it calls this method, the Backup Manager delivers your +backup data, which you then restore to the device, as described below in Performing restore.
            +
            + + + +

            Performing backup

            + + +

            When it's time to back up your application data, the Backup Manager calls your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. This is where you must provide your application data to the Backup Manager so +it can be saved to cloud storage.

            + +

            Only the Backup Manager can call your backup agent's {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. Each time that your application data changes and you want to perform a backup, +you must request a backup operation by calling {@link +android.app.backup.BackupManager#dataChanged()} (see Requesting +Backup for more information). A backup request does not result in an immediate call to your +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. Instead, the Backup Manager waits for an appropriate time, then performs +backup for all applications that have requested a backup since the last backup was performed.

            + +

            Tip: While developing your application, you can initiate an +immediate backup operation from the Backup Manager with the {@code bmgr} tool.

            + +

            When the Backup Manager calls your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method, it passes three parameters:

            + +
            +
            {@code oldState}
            +
            An open, read-only {@link android.os.ParcelFileDescriptor} pointing to the last backup +state provided by your application. This is not the backup data from cloud storage, but a +local representation of the data that was backed up the last time {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} was called (as defined by {@code newState}, below, or from {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}—more about this in the next section). Because {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} does not allow you to read existing backup data in +the cloud storage, you can use this local representation to determine whether your data has changed +since the last backup.
            +
            {@code data}
            +
            A {@link android.app.backup.BackupDataOutput} object, which you use to deliver your backup +data to the Backup Manager.
            +
            {@code newState}
            +
            An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which +you must write a representation of the data that you delivered to {@code data} (a representation +can be as simple as the last-modified timestamp for your file). This object is +returned as {@code oldState} the next time the Backup Manager calls your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method. If you do not write your backup data to {@code newState}, then {@code oldState} +will point to an empty file next time Backup Manager calls {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}.
            +
            + +

            Using these parameters, you should implement your {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method to do the following:

            + +
              +
            1. Check whether your data has changed since the last backup by comparing {@code oldState} to +your current data. How you read data in {@code oldState} depends on how you originally wrote it to +{@code newState} (see step 3). The easiest way to record the state of a file is with its +last-modified timestamp. For example, here's how you can read and compare a timestamp from {@code +oldState}: +
              +// Get the oldState input stream
              +FileInputStream instream = new FileInputStream(oldState.getFileDescriptor());
              +DataInputStream in = new DataInputStream(instream);
              +
              +try {
              +    // Get the last modified timestamp from the state file and data file
              +    long stateModified = in.readLong();
              +    long fileModified = mDataFile.lastModified();
              +
              +    if (stateModified != fileModified) {
              +        // The file has been modified, so do a backup
              +        // Or the time on the device changed, so be safe and do a backup
              +    } else {
              +        // Don't back up because the file hasn't changed
              +        return;
              +    }
              +} catch (IOException e) {
              +    // Unable to read state file... be safe and do a backup
              +}
              +
              +

              If nothing has changed and you don't need to back up, skip to step 3.

              +
            2. +
            3. If your data has changed, compared to {@code oldState}, write the current data to +{@code data} to back it up to the cloud storage. +

              You must write each chunk of data as an "entity" in the {@link +android.app.backup.BackupDataOutput}. An entity is a flattened binary data +record that is identified by a unique key string. Thus, the data set that you back up is +conceptually a set of key-value pairs.

              +

              To add an entity to your backup data set, you must:

              +
                +
              1. Call {@link android.app.backup.BackupDataOutput#writeEntityHeader(String,int) +writeEntityHeader()}, passing a unique string key for the data you're about to write and the data +size.
              2. +
              3. Call {@link android.app.backup.BackupDataOutput#writeEntityData(byte[],int) +writeEntityData()}, passing a byte buffer that contains your data and the number of bytes to write +from the buffer (which should match the size passed to {@link +android.app.backup.BackupDataOutput#writeEntityHeader(String,int) writeEntityHeader()}).
              4. +
              +

              For example, the following code flattens some data into a byte stream and writes it into a +single entity:

              +
              +// Create buffer stream and data output stream for our data
              +ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
              +DataOutputStream outWriter = new DataOutputStream(bufStream);
              +// Write structured data
              +outWriter.writeUTF(mPlayerName);
              +outWriter.writeInt(mPlayerScore);
              +// Send the data to the Backup Manager via the BackupDataOutput
              +byte[] buffer = bufStream.toByteArray();
              +int len = buffer.length;
              +data.writeEntityHeader(TOPSCORE_BACKUP_KEY, len);
              +data.writeEntityData(buffer, len);
              +
              +

              Perform this for each piece of data that you want to back up. How you divide your data into +entities is up to you (and you might use just one entity).

              +
            4. +
            5. Whether or not you perform a backup (in step 2), write a representation of the current data to +the {@code newState} {@link android.os.ParcelFileDescriptor}. The Backup Manager retains this object +locally as a representation of the data that is currently backed up. It passes this back to you as +{@code oldState} the next time it calls {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} so you can determine whether another backup is necessary (as handled in step 1). If you +do not write the current data state to this file, then +{@code oldState} will be empty during the next callback. +

              The following example saves a representation of the current data into {@code newState} using +the file's last-modified timestamp:

              +
              +FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
              +DataOutputStream out = new DataOutputStream(outstream);
              +
              +long modified = mDataFile.lastModified();
              +out.writeLong(modified);
              +
              +
            6. +
            + +

            Caution: If your application data is saved to a file, make sure +that you use synchronized statements while accessing the file so that your backup agent does not +read the file while an Activity in your application is also writing the file.

            + + + + +

            Performing restore

            + +

            When it's time to restore your application data, the Backup Manager calls your backup +agent's {@link android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} method. When it calls this method, the Backup Manager delivers your backup data so +you can restore it onto the device.

            + +

            Only the Backup Manager can call {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}, which happens automatically when the system installs your application and +finds existing backup data. However, you can request a restore operation for +your application by calling {@link +android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} (see Requesting restore for more information).

            + +

            Note: While developing your application, you can also request a +restore operation with the {@code bmgr} +tool.

            + +

            When the Backup Manager calls your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} method, it passes three parameters:

            + +
            +
            {@code data}
            +
            A {@link android.app.backup.BackupDataInput}, which allows you to read your backup +data.
            +
            {@code appVersionCode}
            +
            An integer representing the value of your application's {@code android:versionCode} +manifest attribute, as it was when this data was backed up. You can use this to cross-check the +current application version and determine if the data format is compatible. For more +information about using this to handle different versions of restore data, see the section +below about Checking the Restore Data Version.
            +
            {@code newState}
            +
            An open, read/write {@link android.os.ParcelFileDescriptor} pointing to a file in which +you must write the final backup state that was provided with {@code data}. This object is +returned as {@code oldState} the next time {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} is called. Recall that you must also write the same {@code newState} object in the +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} callback—also doing it here ensures that the {@code oldState} object given to +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} is valid even the first time {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} is called after the device is restored.
            +
            + +

            In your implementation of {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} on the +{@code data} to iterate +through all entities in the data set. For each entity found, do the following:

            + +
              +
            1. Get the entity key with {@link android.app.backup.BackupDataInput#getKey()}.
            2. +
            3. Compare the entity key to a list of known key values that you should have declared as static +final strings inside your {@link android.app.backup.BackupAgent} class. When the key matches one of +your known key strings, enter into a statement to extract the entity data and save it to the device: +
                +
              1. Get the entity data size with {@link +android.app.backup.BackupDataInput#getDataSize()} and create a byte array of that size.
              2. +
              3. Call {@link android.app.backup.BackupDataInput#readEntityData(byte[],int,int) +readEntityData()} and pass it the byte array, which is where the data will go, and specify the +start offset and the size to read.
              4. +
              5. Your byte array is now full and you can read the data and write it to the device +however you like.
              6. +
              +
            4. +
            5. After you read and write your data back to the device, write the state of your data to the +{@code newState} parameter the same as you do during {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}. +
            + +

            For example, here's how you can restore the data backed up by the example in the previous +section:

            + +
            +@Override
            +public void onRestore(BackupDataInput data, int appVersionCode,
            +                      ParcelFileDescriptor newState) throws IOException {
            +    // There should be only one entity, but the safest
            +    // way to consume it is using a while loop
            +    while (data.readNextHeader()) {
            +        String key = data.getKey();
            +        int dataSize = data.getDataSize();
            +
            +        // If the key is ours (for saving top score). Note this key was used when
            +        // we wrote the backup entity header
            +        if (TOPSCORE_BACKUP_KEY.equals(key)) {
            +            // Create an input stream for the BackupDataInput
            +            byte[] dataBuf = new byte[dataSize];
            +            data.readEntityData(dataBuf, 0, dataSize);
            +            ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
            +            DataInputStream in = new DataInputStream(baStream);
            +
            +            // Read the player name and score from the backup data
            +            mPlayerName = in.readUTF();
            +            mPlayerScore = in.readInt();
            +
            +            // Record the score on the device (to a file or something)
            +            recordScore(mPlayerName, mPlayerScore);
            +        } else {
            +            // We don't know this entity key. Skip it. (Shouldn't happen.)
            +            data.skipEntityData();
            +        }
            +    }
            +
            +    // Finally, write to the state blob (newState) that describes the restored data
            +    FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
            +    DataOutputStream out = new DataOutputStream(outstream);
            +    out.writeUTF(mPlayerName);
            +    out.writeInt(mPlayerScore);
            +}
            +
            + +

            In this example, the {@code appVersionCode} parameter passed to {@link +android.app.backup.BackupAgent#onRestore onRestore()} is not used. However, you might want to use +it if you've chosen to perform backup when the user's version of the application has actually moved +backward (for example, the user went from version 1.5 of your app to 1.0). For more information, see +the section about Checking the Restore Data Version.

            + +
            +

            For an example implementation of {@link android.app.backup.BackupAgent}, see the {@code +ExampleAgent} class in the Backup and Restore sample +application.

            +
            + + + + + + +

            Extending BackupAgentHelper

            + +

            You should build your backup agent using {@link android.app.backup.BackupAgentHelper} if you want +to back up complete files (from either {@link android.content.SharedPreferences} or internal storage). +Building your backup agent with {@link android.app.backup.BackupAgentHelper} requires far less +code than extending {@link android.app.backup.BackupAgent}, because you don't have to implement +{@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}.

            + +

            Your implementation of {@link android.app.backup.BackupAgentHelper} must +use one or more backup helpers. A backup helper is a specialized +component that {@link android.app.backup.BackupAgentHelper} summons to perform backup and +restore operations for a particular type of data. The Android framework currently provides two +different helpers:

            +
              +
            • {@link android.app.backup.SharedPreferencesBackupHelper} to backup {@link +android.content.SharedPreferences} files.
            • +
            • {@link android.app.backup.FileBackupHelper} to backup files from internal storage.
            • +
            + +

            You can include multiple helpers in your {@link android.app.backup.BackupAgentHelper}, but only +one helper is needed for each data type. That is, if you have multiple {@link +android.content.SharedPreferences} files, then you need only one {@link +android.app.backup.SharedPreferencesBackupHelper}.

            + +

            For each helper you want to add to your {@link android.app.backup.BackupAgentHelper}, you must do +the following during your {@link android.app.backup.BackupAgent#onCreate()} method:

            +
              +
            1. Instantiate in instance of the desired helper class. In the class constructor, you must +specify the appropriate file(s) you want to backup.
            2. +
            3. Call {@link android.app.backup.BackupAgentHelper#addHelper(String,BackupHelper) addHelper()} +to add the helper to your {@link android.app.backup.BackupAgentHelper}.
            4. +
            + +

            The following sections describe how to create a backup agent using each of the available +helpers.

            + + + +

            Backing up SharedPreferences

            + +

            When you instantiate a {@link android.app.backup.SharedPreferencesBackupHelper}, you must +include the name of one or more {@link android.content.SharedPreferences} files.

            + +

            For example, to back up a {@link android.content.SharedPreferences} file named +"user_preferences", a complete backup agent using {@link android.app.backup.BackupAgentHelper} looks +like this:

            + +
            +public class MyPrefsBackupAgent extends BackupAgentHelper {
            +    // The name of the SharedPreferences file
            +    static final String PREFS = "user_preferences";
            +
            +    // A key to uniquely identify the set of backup data
            +    static final String PREFS_BACKUP_KEY = "prefs";
            +
            +    // Allocate a helper and add it to the backup agent
            +    @Override
            +    public void onCreate() {
            +        SharedPreferencesBackupHelper helper =
            +                new SharedPreferencesBackupHelper(this, PREFS);
            +        addHelper(PREFS_BACKUP_KEY, helper);
            +    }
            +}
            +
            + +

            That's it! That's your entire backup agent. The {@link +android.app.backup.SharedPreferencesBackupHelper} includes all the code +needed to backup and restore a {@link android.content.SharedPreferences} file.

            + +

            When the Backup Manager calls {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()}, {@link android.app.backup.BackupAgentHelper} calls your backup helpers to perform +backup and restore for your specified files.

            + +

            Note: The methods of {@link android.content.SharedPreferences} +are threadsafe, so +you can safely read and write the shared preferences file from your backup agent and +other activities.

            + + + +

            Backing up other files

            + +

            When you instantiate a {@link android.app.backup.FileBackupHelper}, you must include the name of +one or more files that are saved to your application's internal storage +(as specified by {@link android.content.ContextWrapper#getFilesDir()}, which is the same +location where {@link android.content.Context#openFileOutput(String,int) openFileOutput()} writes +files).

            + +

            For example, to backup two files named "scores" and "stats," a backup agent using {@link +android.app.backup.BackupAgentHelper} looks like this:

            + +
            +public class MyFileBackupAgent extends BackupAgentHelper {
            +    // The name of the file
            +    static final String TOP_SCORES = "scores";
            +    static final String PLAYER_STATS = "stats";
            +
            +    // A key to uniquely identify the set of backup data
            +    static final String FILES_BACKUP_KEY = "myfiles";
            +
            +    // Allocate a helper and add it to the backup agent
            +    @Override
            +    public void onCreate() {
            +        FileBackupHelper helper = new FileBackupHelper(this,
            +                TOP_SCORES, PLAYER_STATS);
            +        addHelper(FILES_BACKUP_KEY, helper);
            +    }
            +}
            +
            + +

            The {@link android.app.backup.FileBackupHelper} includes all the code necessary to backup and +restore files that are saved to your application's internal storage..

            + +

            However, reading and writing to files on internal storage is not threadsafe. To +ensure that your backup agent does not read or write your files at the same time as your activities, +you must use synchronized statements each time you perform a read or write. For example, +in any Activity where you read and write the file, you need an object to use as the intrinsic +lock for the synchronized statements:

            + +
            +// Object for intrinsic lock
            +static final Object sDataLock = new Object();
            +
            + +

            Then create a synchronized statement with this lock each time you read or write the files. For +example, here's a synchronized statement for writing the latest score in a game to a file:

            + +
            +try {
            +    synchronized (MyActivity.sDataLock) {
            +        File dataFile = new File({@link android.content.Context#getFilesDir()}, TOP_SCORES);
            +        RandomAccessFile raFile = new RandomAccessFile(dataFile, "rw");
            +        raFile.writeInt(score);
            +    }
            +} catch (IOException e) {
            +    Log.e(TAG, "Unable to write to file");
            +}
            +
            + +

            You should synchronize your read statements with the same lock.

            + +

            Then, in your {@link android.app.backup.BackupAgentHelper}, you must override {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} to synchronize the backup and restore operations with the same +intrinsic lock. For example, the {@code MyFileBackupAgent} example from above needs the following +methods:

            + +
            +@Override
            +public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            +          ParcelFileDescriptor newState) throws IOException {
            +    // Hold the lock while the FileBackupHelper performs backup
            +    synchronized (MyActivity.sDataLock) {
            +        super.onBackup(oldState, data, newState);
            +    }
            +}
            +
            +@Override
            +public void onRestore(BackupDataInput data, int appVersionCode,
            +        ParcelFileDescriptor newState) throws IOException {
            +    // Hold the lock while the FileBackupHelper restores the file
            +    synchronized (MyActivity.sDataLock) {
            +        super.onRestore(data, appVersionCode, newState);
            +    }
            +}
            +
            + +

            That's it. All you need to do is add your {@link android.app.backup.FileBackupHelper} in the +{@link android.app.backup.BackupAgent#onCreate()} method and override {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} and {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) +onRestore()} to synchronize read and write operations.

            + +
            +

            For an example implementation of {@link +android.app.backup.BackupAgentHelper} with {@link android.app.backup.FileBackupHelper}, see the +{@code FileHelperExampleAgent} class in the Backup and Restore sample +application.

            +
            + + + + + + +

            Checking the restore data version

            + +

            When the Backup Manager saves your data to cloud storage, it automatically includes the version +of your application, as defined by your manifest file's {@code android:versionCode} +attribute. Before the Backup Manager calls your backup agent to restore your data, it +looks at the {@code +android:versionCode} of the installed application and compares it to the value +recorded in the restore data set. If the version recorded in the restore data set is +newer than the application version on the device, then the user has downgraded their +application. In this case, the Backup Manager will abort the restore operation for your application +and not call your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method, because the restore set is considered meaningless to an older version.

            + +

            You can override this behavior with the {@code +android:restoreAnyVersion} attribute. This attribute is either "{@code true}" or "{@code +false}" to indicate whether you want to restore the application regardless of the restore set +version. The default value is "{@code false}". If you define this to be "{@code true}" then the +Backup Manager will ignore the {@code android:versionCode} +and call your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method in all cases. In doing so, you can manually check for the version difference in your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method and take any steps necessary to make the data compatible if the versions conflict.

            + +

            To help you handle different versions during a restore operation, the {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +method passes you the version code included with the restore data set as the {@code appVersionCode} +parameter. You can then query the current application's version code with the {@link +android.content.pm.PackageInfo#versionCode PackageInfo.versionCode} field. For example:

            + +
            +PackageInfo info;
            +try {
            +    String name = {@link android.content.ContextWrapper#getPackageName() getPackageName}();
            +    info = {@link android.content.ContextWrapper#getPackageManager
            +getPackageManager}().{@link android.content.pm.PackageManager#getPackageInfo(String,int)
            +getPackageInfo}(name,0);
            +} catch (NameNotFoundException nnfe) {
            +    info = null;
            +}
            +
            +int version;
            +if (info != null) {
            +    version = info.versionCode;
            +}
            +
            + +

            Then simply compare the {@code version} acquired from {@link android.content.pm.PackageInfo} +to the {@code appVersionCode} passed into {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}. +

            + +

            Caution: Be certain you understand the consequences of setting +{@code +android:restoreAnyVersion} to "{@code true}" for your application. If each version of your +application that supports backup does not properly account for variations in your data format during +{@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()}, +then the data on the device could be saved in a format incompatible with the version currently +installed on the device.

            + + + +

            Requesting backup

            + +

            You can request a backup operation at any time by calling {@link +android.app.backup.BackupManager#dataChanged()}. This method notifies the Backup Manager that you'd +like to backup your data using your backup agent. The Backup Manager then calls your backup +agent's {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()} method at an opportune time in the future. Typically, you should +request a backup each time your data changes (such as when the user changes an application +preference that you'd like to back up). If you call {@link +android.app.backup.BackupManager#dataChanged()} several times consecutively, before the Backup +Manager requests a backup from your agent, your agent still receives just one call to {@link +android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor,BackupDataOutput,ParcelFileDescriptor) +onBackup()}.

            + +

            Note: While developing your application, you can request a +backup and initiate an immediate backup operation with the {@code bmgr} +tool.

            + + +

            Requesting restore

            + +

            During the normal life of your application, you shouldn't need to request a restore operation. +They system automatically checks for backup data and performs a restore when your application is +installed. However, you can manually request a restore operation by calling {@link +android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()}, if necessary. In +which case, the Backup Manager calls your {@link +android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor) onRestore()} +implementation, passing the data from the current set of backup data.

            + +

            Note: While developing your application, you can request a +restore operation with the {@code bmgr} +tool.

            + + +

            Migrating to Auto Backup

            +

            You can transition your app to full-data backups by setting android:fullBackupOnly to true in the <application> element in the manifest file. When +running on a device with Android 5.1 (API level 22) or lower, your app ignores +this value in the manifest, and continues performing Key/Value Backups. When +running on a device with Android 6.0 (API level 23) or higher, your app performs +Auto Backup instead of Key/Value Backup. \ No newline at end of file diff --git a/docs/html/guide/topics/data/testingbackup.jd b/docs/html/guide/topics/data/testingbackup.jd new file mode 100644 index 0000000000000000000000000000000000000000..6ff5837e2411ebfbb2e02135129edded3c2afc50 --- /dev/null +++ b/docs/html/guide/topics/data/testingbackup.jd @@ -0,0 +1,181 @@ +page.title=Testing Backup and Restore +page.tags=backup, marshmallow, androidm +page.keywords=backup, restore, testing + +@jd:body + +

            + +

            This page shows you how to manually trigger Auto Backup, Key/Value Backup, and restore operations to +ensure your app saves and restores data properly. + +

            How backup works

            +

            The section describes various pieces in the Android backup framework and how they +interact with apps that support Auto Backup and Key/Value Backup. During the app +development phase, most of the inner working of the framework were abstracted away, so you didn't need to know this information. However, during the +testing phase, an understanding of these concepts is important. + +

            The following diagram illustrates how data flows during backup and restore: + +backup-framework + +

            The Backup Manager Service is an Android system +service which orchestrates and initiates backup and restore operations. The service +is accessible through the {@link android.app.backup.BackupManager} +API. During a backup operation, the service queries your app for backup data, +then hands it to the backup transport, which then archives the data. +During a restore operation, the backup manager service retrieves the backup data +from the backup transport and restores the data to the device. + +

            Backup Transports are Android components that are responsible +for storing and retrieving backups. An Android device can have zero or more +backup transports, but only one of those transports can be marked active. The +available backup transports may differ from device to device (due to +customizations by device manufacturers and service providers), but most Google +Play enabled devices ship with the following transports: +

              +
            • Google GMS Transport(default) - the active backup +transport on most devices, part of Google Mobile Services. This documentation assumes that users are using the +Google GMS transport. This transport stores Auto Backup data in a private folder in the +user's Google Drive account. Key/Value Backup data is stored in the Android Backup Service. +
            • Local Transport - stores backup data locally on the device. +This transport is typically used for development/debugging purposes and is not +useful in the real world.
            + +

            If a device does not have any backup transports, then the data cannot be +backed up. Your app is not adversely affected. + +

            Caution: Because the backup transport +can differ from device to device, Android cannot guarantee the security +of your data while using backup. Be cautious about using backup to store +sensitive data, such as usernames and passwords. + +

            Prerequisites

            +

            You need to know a bit about the following tools: + +

              +
            • adb +- to run commands on the device or emulator +
            • bmgr - to +perform various backup and restore operations +
            • logcat +- to see the output of backup and restore operations.
            + +

            Preparing your device or +emulator

            +

            Prepare your device or emulator for backup testing by working through the +following checklist: +

              +
            • For Auto Backup, check that you are using a device or emulator running +Android 6.0 (API level 23) or higher.
            • +
            • For Key/Value Backup, check that you are using a device or emulator running +Android 2.2 (API level 8) or higher.
            • +
            • Check that backup and restore is enabled on the device or emulator. There +are two ways to check:
                +
              • On the device, go to Settings -> Backup & Restore. +
              • From adb shell, run bmgr enable
              +

              On physical devices, backup and restore is typically enabled during the +initial setup wizard. Emulators do not run the setup wizard, so don't forget to +enable backup and specify a backup account in device settings. +

            • Make sure the GMS Backup Transport is available and active by running the +command from adb shell: +
              $ bmgr list transports
              +

              Then, check the console for the following output: +

              android/com.android.internal.backup.LocalTransport
              +* com.google.android.gms/.backup.BackupTransportService
              +

              Physical devices without Google Play and emulators without Google APIs +might not include the GMS Backup Transport. This article assumes you are using +the GMS Backup Transport. You can test backup and restore with other backup +transports, but the procedure and output can differ. +

            + +

            Testing backup

            +

            To initiate a backup of your app, run the following command: + +

            $ bmgr backupnow <PACKAGE>
            + +

            The backupnow command runs either a Key/Value Backup or Auto Backup depending on +the package's manifest declarations. Check logcat to see the output of the +backup procedure. For example: + +

            D/BackupManagerService: fullTransportBackup()
            +I/GmsBackupTransport: Attempt to do full backup on <PACKAGE>
            +
            +---- or ----
            +
            +V/BackupManagerService: Scheduling immediate backup pass
            +D/PerformBackupTask: starting key/value Backup of BackupRequest{pkg=<PACKAGE>}
            +
            + +

            If the backupnow command is not available on your device, you need to run one +of the following commands: +

              +
            • For Auto Backups, run: bmgr fullbackup <PACKAGE> +
            • For Key/Value Backups, schedule and run your backup with the following +commands: +
              $ bmgr backup <PACKAGE>
              +$ bmgr run
              +

              bmgr backup adds your app to the Backup Manager's queue. bmgr run initiates the +backup operation, which forces the Backup Manager to perform all backup requests +that are in its queue. +

            + +

            Testing restore

            +

            To manually initiate a restore, run the following command: + +

            $ bmgr restore <PACKAGE>
            + +

            Warning: This action stops your app and wipes its data before performing the +restore operation. + +

            Then, check logcat to see the output of the restore procedure. For example: + +

            V/BackupManagerService: beginRestoreSession: pkg=<PACKAGE> transport=null
            +V/RestoreSession: restorePackage pkg=<PACKAGE> token=368abb4465c5c683
            +...
            +I/BackupManagerService: Restore complete.
            +
            + +

            You also can test automatic restore for your app by uninstalling and +reinstalling your app either with adb or through the Google +Play Store app. + +

            Troubleshooting

            +

            Exceeded Quota + +

            If you see the the following messages in logcat: + +

            I/PFTBT: Transport rejected backup of <PACKAGE>, skipping
            +
            +--- or ---
            +
            +I/PFTBT: Transport quota exceeded for package: <PACKAGE>
            +
            + +

            Your app has exceeded the quota and has been banned from backing up +data on this device. To lift the ban, either factory reset your device or change +the backup account. + +

            Full Backup Not Possible + +

            If you see the the following message in logcat: + +

            I/BackupManagerService: Full backup not currently possible -- key/value backup not yet run?
            +
            + +

            The fullbackup operation failed because no Key/Value Backup operation has yet +occurred on the device. Trigger a Key/Value Backup with the command bmgr +run and then try again. \ No newline at end of file diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd index 9cae53c06910fa766c5318601198892897acbba5..d7dd0381f2a8f95b68ebfed9849d4369b0b92030 100644 --- a/docs/html/guide/topics/graphics/2d-graphics.jd +++ b/docs/html/guide/topics/graphics/2d-graphics.jd @@ -21,6 +21,7 @@ parent.link=index.html

          7. Shape Drawable
          8. Nine-patch
          9. +
          10. Vector Drawables

          See also

          @@ -428,58 +429,66 @@ state of the object it's attached to. --> -

          Nine-patch

          - -

          A {@link android.graphics.drawable.NinePatchDrawable} graphic is a stretchable bitmap -image, which Android - will automatically resize to accommodate the contents of the View in which you have -placed it as the background. - An example use of a NinePatch is the backgrounds used by standard Android buttons — - buttons must stretch to accommodate strings of various lengths. A NinePatch drawable is a -standard PNG - image that includes an extra 1-pixel-wide border. It must be saved with the extension - .9.png, - and saved into the res/drawable/ directory of your project. -

          -

          - The border is used to define the stretchable and static areas of - the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide - black line(s) in the left and top part of the border (the other border pixels should - be fully transparent or white). You can have as many stretchable sections as you want: - their relative size stays the same, so the largest sections always remain the largest. -

          -

          - You can also define an optional drawable section of the image (effectively, - the padding lines) by drawing a line on the right and bottom lines. - If a View object sets the NinePatch as its background and then specifies the - View's text, it will stretch itself so that all the text fits inside only - the area designated by the right and bottom lines (if included). If the - padding lines are not included, Android uses the left and top lines to - define this drawable area. -

          -

          To clarify the difference between the different lines, the left and top lines define - which pixels of the image are allowed to be replicated in order to stretch the image. - The bottom and right lines define the relative area within the image that the contents - of the View are allowed to lie within.

          -

          - Here is a sample NinePatch file used to define a button: -

          - - -

          This NinePatch defines one stretchable area with the left and top lines - and the drawable area with the bottom and right lines. In the top image, the dotted grey - lines identify the regions of the image that will be replicated in order to stretch the -image. The pink - rectangle in the bottom image identifies the region in which the contents of the View are -allowed. - If the contents don't fit in this region, then the image will be stretched so that they -do. +

          Nine-patch

          + +

          + A {@link android.graphics.drawable.NinePatchDrawable} graphic is a + stretchable bitmap image, which Android will automatically resize to + accommodate the contents of the View in which you have placed it as the + background. An example use of a NinePatch is the backgrounds used by + standard Android buttons — buttons must stretch to accommodate strings of + various lengths. A NinePatch drawable is a standard PNG image that includes + an extra 1-pixel-wide border. It must be saved with the extension + .9.png, and saved into the res/drawable/ directory + of your project.

          -

          The Draw 9-patch tool offers - an extremely handy way to create your NinePatch images, using a WYSIWYG graphics editor. It -even raises warnings if the region you've defined for the stretchable area is at risk of -producing drawing artifacts as a result of the pixel replication. +

          + The border is used to define the stretchable and static areas of the image. + You indicate a stretchable section by drawing one (or more) 1-pixel-wide + black line(s) in the left and top part of the border (the other border + pixels should be fully transparent or white). You can have as many + stretchable sections as you want: their relative size stays the same, so the + largest sections always remain the largest. +

          + +

          + You can also define an optional drawable section of the image (effectively, + the padding lines) by drawing a line on the right and bottom lines. If a + View object sets the NinePatch as its background and then specifies the + View's text, it will stretch itself so that all the text fits inside only + the area designated by the right and bottom lines (if included). If the + padding lines are not included, Android uses the left and top lines to + define this drawable area. +

          + +

          + To clarify the difference between the different lines, the left and top + lines define which pixels of the image are allowed to be replicated in order + to stretch the image. The bottom and right lines define the relative area + within the image that the contents of the View are allowed to lie within. +

          + +

          + Here is a sample NinePatch file used to define a button: +

          + +

          + This NinePatch defines one stretchable area with the left and top lines and + the drawable area with the bottom and right lines. In the top image, the + dotted grey lines identify the regions of the image that will be replicated + in order to stretch the image. The pink rectangle in the bottom image + identifies the region in which the contents of the View are allowed. If the + contents don't fit in this region, then the image will be stretched so that + they do. +

          + +

          + The Draw 9-patch tool + offers an extremely handy way to create your NinePatch images, using a + WYSIWYG graphics editor. It even raises warnings if the region you've + defined for the stretchable area is at risk of producing drawing artifacts + as a result of the pixel replication.

          Example XML

          @@ -516,3 +525,265 @@ stretches to accommodate it.

          + +

          + Vector Drawables +

          + +

          + A {@link android.graphics.drawable.VectorDrawable} graphic replaces multiple + PNG assets with a single vector graphic. The vector graphic is defined in an + XML file as a set of points, lines, and curves along with its associated + color information. +

          + +

          + The major advantage of using a vector graphic is image scalability. Using + vector graphics resizes the same file for different screen densities without + loss of image quality. This results in smaller APK files and less developer + maintenance. You can also use vector images for animation by using multiple + XML files instead of multiple images for each display resolution. +

          + +

          + Let's go through an example to understand the benefits. An image of size 100 + x 100 dp may render good quality on a smaller display resolution. On larger + devices, the app might want to use a 400 x 400 dp version of the image. + Normally, developers create multiple versions of an asset to cater to + different screen densities. This approach consumes more development efforts, + and results in a larger APK, which takes more space on the device. +

          + +

          + As of Android 5.0 (API level 21), there are two classes that support vector + graphics as a drawable resource: {@link + android.graphics.drawable.VectorDrawable} and {@link + android.graphics.drawable.AnimatedVectorDrawable}. For more information + about using the VectorDrawable and the AnimatedVectorDrawable classes, read + the About VectorDrawable class and + About AnimatedVectorDrawable + class sections. +

          + +

          About VectorDrawable class

          +

          + {@link android.graphics.drawable.VectorDrawable} defines a static drawable + object. Similar to the SVG format, each vector graphic is defined as a tree + hierachy, which is made up of path and group objects. + Each path contains the geometry of the object's outline and + group contains details for transformation. All paths are drawn + in the same order as they appear in the XML file. +

          + + +

          + Figure 1. Sample hierarchy of a vector drawable asset +

          + + +

          + The Vector Asset + Studio tool offers a simple way to add a vector graphic to the project + as an XML file. +

          + +

          + Example XML +

          + +

          + Here is a sample VectorDrawable XML file that renders an image + of a battery in the charging mode. +

          + +
          +<!-- res/drawable/battery_charging.xml -->
          +<vector xmlns:android="http://schemas.android.com/apk/res/android"
          +    <!-- intrinsic size of the drawable -->
          +    android:height="24dp"
          +    android:width="24dp"
          +    <!-- size of the virtual canvas -->
          +    android:viewportWidth="24.0"
          +    android:viewportHeight="24.0">
          +   <group
          +         android:name="rotationGroup"
          +         android:pivotX="10.0"
          +         android:pivotY="10.0"
          +         android:rotation="15.0" >
          +      <path
          +        android:name="vect"
          +        android:fillColor="#FF000000"
          +        android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"
          +        android:fillAlpha=".3"/>
          +      <path
          +        android:name="draw"
          +        android:fillColor="#FF000000"
          +        android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z"/>
          +   </group>
          +</vector>
          +
          + +

          This XML renders the following image: +

          + + + +

          + About AnimatedVectorDrawable class +

          + +

          + {@link android.graphics.drawable.AnimatedVectorDrawable + AnimatedVectorDrawable} adds animation to the properties of a vector + graphic. You can define an animated vector graphic as three separate + resource files or as a single XML file defining the entire drawable. Let's + look at both the approaches for better understanding: Multiple XML files and Single + XML file. +

          + +

          + Multiple XML files +

          +

          + By using this approach, you can define three separate XML files: + +

            +
          • A {@link android.graphics.drawable.VectorDrawable} XML file. +
          • + +
          • + An {@link android.graphics.drawable.AnimatedVectorDrawable} XML file that +defines the target {@link android.graphics.drawable.VectorDrawable}, the +target paths and groups to animate, the properties, and the animations defined +as {@link android.animation.ObjectAnimator ObjectAnimator} objects or {@link +android.animation.AnimatorSet AnimatorSet} objects. +
          • + +
          • An animator XML file. +
          • +
          +

          + +
          + Example of multiple XML files +
          +

          + The following XML files demonstrate the animation of a vector graphic. + +

            +
          • VectorDrawable's XML file: vd.xml +
          • + +
          • +
            +<vector xmlns:android="http://schemas.android.com/apk/res/android"
            +   android:height="64dp"
            +   android:width="64dp"
            +   android:viewportHeight="600"
            +   android:viewportWidth="600" >
            +   <group
            +      android:name="rotationGroup"
            +      android:pivotX="300.0"
            +      android:pivotY="300.0"
            +      android:rotation="45.0" >
            +      <path
            +         android:name="vectorPath"
            +         android:fillColor="#000000"
            +         android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
            +   </group>
            +</vector>
            +
            +
          • + +
          • AnimatedVectorDrawable's XML file: avd.xml +
          • + +
          • +
            +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
            +   android:drawable="@drawable/vd" >
            +     <target
            +         android:name="rotationGroup"
            +         android:animation="@anim/rotation" />
            +     <target
            +         android:name="vectorPath"
            +         android:animation="@anim/path_morph" />
            +</animated-vector>
            +
            +
          • + +
          • Animator XML files that are used in the AnimatedVectorDrawable's XML + file: rotation.xml and path_morph.xml +
          • + +
          • +
            +<objectAnimator
            +   android:duration="6000"
            +   android:propertyName="rotation"
            +   android:valueFrom="0"
            +   android:valueTo="360" />
            +
            + +
            +<set xmlns:android="http://schemas.android.com/apk/res/android">
            +   <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"/>
            +</set>
            +
            +
          • +
          +

          +

          + Single XML file +

          + +

          + By using this approach, you can merge the related XML files into a single + XML file through the XML Bundle Format. At the time of building the app, the + aapt tag creates separate resources and references them in the + animated vector. This approach requires Build Tools 24 or higher, and the + output is backward compatible. +

          + +
          + Example of a single XML file +
          +
          +<animated-vector
          +    xmlns:android="http://schemas.android.com/apk/res/android"
          +    xmlns:aapt="http://schemas.android.com/aapt">
          +    <aapt:attr name="android:drawable">
          +        <vector
          +            android:width="24dp"
          +            android:height="24dp"
          +            android:viewportWidth="24"
          +            android:viewportHeight="24">
          +            <path
          +                android:name="root"
          +                android:strokeWidth="2"
          +                android:strokeLineCap="square"
          +                android:strokeColor="?android:colorControlNormal"
          +                android:pathData="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7" />
          +        </vector>
          +    </aapt:attr>
          +    <target android:name="root">
          +        <aapt:attr name="android:animation">
          +            <objectAnimator
          +                android:propertyName="pathData"
          +                android:valueFrom="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7"
          +                android:valueTo="M6.4,6.4 L17.6,17.6 M6.4,17.6 L17.6,6.4"
          +                android:duration="300"
          +                android:interpolator="@android:interpolator/fast_out_slow_in"
          +                android:valueType="pathType" />
          +        </aapt:attr>
          +    </target>
          +</animated-vector>
          +
          \ No newline at end of file diff --git a/docs/html/guide/topics/graphics/index.jd b/docs/html/guide/topics/graphics/index.jd index 17f630994952f6ccb3443e6cf9d1b50db32b4e55..a87e404503ed1ef9ac1f619b1b069bf806cf6f55 100644 --- a/docs/html/guide/topics/graphics/index.jd +++ b/docs/html/guide/topics/graphics/index.jd @@ -17,7 +17,7 @@ support hardware acceleration on tablets. With this new pipeline, all drawing op by the UI toolkit are carried out using the GPU. You’ll be happy to hear that Android 4.0, Ice Cream Sandwich, brings an improved version of the hardware-accelerated 2D rendering pipeline.

          - +

          Introducing ViewPropertyAnimator

          @@ -25,7 +25,7 @@ href="http://android-developers.blogspot.com/2011/05/introducing-viewpropertyani including the new properties added to the View class in 3.0. In the 3.1 release, we added a small utility class that makes animating these properties even easier.

          - +

          Android 3.0 Hardware Acceleration

          @@ -43,7 +43,7 @@ applications can benefit from an extra boost in performance.

          that keeps your user interface (UI) components responsive and avoids exceeding your application memory limit.

          - + \ No newline at end of file diff --git a/docs/html/guide/topics/graphics/overview.jd b/docs/html/guide/topics/graphics/overview.jd index 66a675dc6491b249169b5ccf7730985c911e93f7..98d80a0f51bf9ab2483e058652cc2e8bda3266e5 100644 --- a/docs/html/guide/topics/graphics/overview.jd +++ b/docs/html/guide/topics/graphics/overview.jd @@ -6,7 +6,7 @@ page.title=Animation and Graphics Overview and help you decide with approach is best for your needs.

          Animation

          - +

          The Android framework provides two animation systems: property animation and view animation. Both animation systems are viable options, but the property animation system, in general, is the preferred method to use, because it diff --git a/docs/html/guide/topics/graphics/prop-animation.jd b/docs/html/guide/topics/graphics/prop-animation.jd index aed533de16ca10a041bfe1248757c3800fa3e77e..2be2b09ffea3920c8f8c26a4d3b418662bf7466b 100755 --- a/docs/html/guide/topics/graphics/prop-animation.jd +++ b/docs/html/guide/topics/graphics/prop-animation.jd @@ -165,9 +165,9 @@ page.tags=valueanimator,objectanimator,layouttransition,ViewPropertyAnimator "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API Demos sample project provides many examples on how to use the property animation system.

          - +

          How Property Animation Differs from View Animation

          - +

          The view animation system provides the capability to only animate {@link android.view.View} objects, so if you wanted to animate non-{@link android.view.View} objects, you have to implement your own code to do so. The view animation system is also constrained in the fact that it only @@ -594,7 +594,7 @@ implementations of the methods that you can choose to override.

          for just the {@link android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()} callback:

          -ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
          +ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
           fadeAnim.setDuration(250);
           fadeAnim.addListener(new AnimatorListenerAdapter() {
           public void onAnimationEnd(Animator animation) {
          diff --git a/docs/html/guide/topics/location/strategies.jd b/docs/html/guide/topics/location/strategies.jd
          index 32be463e687cb8942928811b4cee12cf1531c808..548ed9c99f34b04340e6999e3bbdeb1d1b3c3f6f 100755
          --- a/docs/html/guide/topics/location/strategies.jd
          +++ b/docs/html/guide/topics/location/strategies.jd
          @@ -133,36 +133,69 @@ notifications and the third is the minimum change in distance between notificati
           both to zero requests location notifications as frequently as possible. The last parameter is your
           {@link android.location.LocationListener}, which receives callbacks for location updates.

          -

          To request location updates from the GPS provider, -substitute GPS_PROVIDER for NETWORK_PROVIDER. You can also request -location updates from both the GPS and the Network Location Provider by calling {@link -android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} twice—once -for NETWORK_PROVIDER and once for GPS_PROVIDER.

          +

          To request location updates from the GPS provider, use {@link +android.location.LocationManager#GPS_PROVIDER} instead of {@link +android.location.LocationManager#NETWORK_PROVIDER}. You can also request +location updates from both the GPS and the Network Location Provider by calling +{@link android.location.LocationManager#requestLocationUpdates +requestLocationUpdates()} twice—once for {@link +android.location.LocationManager#NETWORK_PROVIDER} and once for {@link +android.location.LocationManager#GPS_PROVIDER}.

          Requesting User Permissions

          -

          In order to receive location updates from NETWORK_PROVIDER or -GPS_PROVIDER, you must request user permission by declaring either the {@code -ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permission, respectively, in your Android -manifest file. For example:

          +

          + In order to receive location updates from {@link + android.location.LocationManager#NETWORK_PROVIDER} or {@link + android.location.LocationManager#GPS_PROVIDER}, you must request the user's + permission by declaring either the {@code ACCESS_COARSE_LOCATION} or {@code + ACCESS_FINE_LOCATION} permission, respectively, in your Android manifest file. + Without these permissions, your application will fail at runtime when + requesting location updates. +

          + +

          + If you are using both {@link + android.location.LocationManager#NETWORK_PROVIDER} and {@link + android.location.LocationManager#GPS_PROVIDER}, then you need to request only + the {@code ACCESS_FINE_LOCATION} permission, because it includes permission + for both providers. Permission for {@code ACCESS_COARSE_LOCATION} allows + access only to {@link android.location.LocationManager#NETWORK_PROVIDER}. +

          + +

          + Caution: If your app targets Android 5.0 (API level 21) or + higher, you must declare that your app uses the + android.hardware.location.network or + android.hardware.location.gps hardware feature in the manifest + file, depending on whether your app receives location updates from {@link + android.location.LocationManager#NETWORK_PROVIDER} or from {@link + android.location.LocationManager#GPS_PROVIDER}. If your app receives location + information from either of these location provider sources, you need to + declare that the app uses these hardware features in your app manifest. + On devices running verions prior to Android 5.0 (API 21), requesting the + {@code ACCESS_FINE_LOCATION} or {@code ACCESS_COARSE_LOCATION} permission + includes an implied request for location hardware features. However, + requesting those permissions does not automatically request location + hardware features on Android 5.0 (API level 21) and higher. +

          +

          + The following code sample demonstrates how to declare the permission and + hardware feature in the manifest file of an app that reads data from the + device's GPS: +

           <manifest ... >
               <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
               ...
          +    <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
          +    <uses-feature android:name="android.hardware.location.gps" />
          +    ...
           </manifest>
           
          -

          Without these permissions, your application will fail at runtime when requesting -location updates.

          - -

          Note: If you are using both NETWORK_PROVIDER and -GPS_PROVIDER, then you need to request only the {@code ACCESS_FINE_LOCATION} -permission, because it includes permission for both providers. (Permission for {@code -ACCESS_COARSE_LOCATION} includes permission only for NETWORK_PROVIDER.)

          - -

          Defining a Model for the Best Performance

          Location-based applications are now commonplace, but due to the less than optimal @@ -404,19 +437,20 @@ don't have a device, you can still test your location-based features by mocking the Android emulator. There are three different ways to send your application mock location data: using Android Studio, DDMS, or the "geo" command in the emulator console.

          -

          Note: Providing mock location data is injected as GPS location -data, so you must request location updates from GPS_PROVIDER in order for mock location -data to work.

          +

          Note: Providing mock location data is injected +as GPS location data, so you must request location updates from {@link +android.location.LocationManager#GPS_PROVIDER} in order for mock location data +to work.

          Using Android Studio

          Select Tools > Android > AVD Manager. In the Android Virtual -Device Manager window, choose your AVD and launch it in the emulator by selecting the green +Device Manager window, choose your AVD and launch it in the emulator by selecting the green play arrow in the Actions column.

          Then, select Tools > Android > Android Device Monitor. -Select the Emulator Control tab in the Android Device Monitor window, and enter GPS coordinates -under Location Controls as individual lat/long coordinates, with a GPX file for route playback, +Select the Emulator Control tab in the Android Device Monitor window, and enter GPS coordinates +under Location Controls as individual lat/long coordinates, with a GPX file for route playback, or a KML file for multiple place marks.

          diff --git a/docs/html/guide/topics/manifest/action-element.jd b/docs/html/guide/topics/manifest/action-element.jd index fc6ce440579da4df3b12af3025ad95f767d8568d..f3b340e2737ac3c1f524a9206ac1051f9c0cab5c 100644 --- a/docs/html/guide/topics/manifest/action-element.jd +++ b/docs/html/guide/topics/manifest/action-element.jd @@ -13,10 +13,10 @@ parent.link=manifest-intro.html

          description:
          Adds an action to an intent filter. -An <intent-filter> element must contain +An <intent-filter> element must contain one or more {@code } elements. If it doesn't contain any, no -Intent objects will get through the filter. See -Intents and +Intent objects will get through the filter. See +Intents and Intent Filters for details on intent filters and the role of action specifications within a filter.
          @@ -25,16 +25,16 @@ specifications within a filter.
          {@code android:name}
          The name of the action. Some standard actions are defined in the -{@link android.content.Intent#ACTION_CHOOSER Intent} class as +{@link android.content.Intent#ACTION_CHOOSER Intent} class as ACTION_string constants. To assign one of these actions to -this attribute, prepend "{@code android.intent.action.}" to the +this attribute, prepend "{@code android.intent.action.}" to the string that follows {@code ACTION_}. For example, for {@code ACTION_MAIN}, use "{@code android.intent.action.MAIN}" and for {@code ACTION_WEB_SEARCH}, use "{@code android.intent.action.WEB_SEARCH}".

          For actions you define, it's best to use the package name as a prefix to -ensure uniqueness. For example, a {@code TRANSMOGRIFY} action might be specified +ensure uniqueness. For example, a {@code TRANSMOGRIFY} action might be specified as follows:

          diff --git a/docs/html/guide/topics/manifest/activity-alias-element.jd b/docs/html/guide/topics/manifest/activity-alias-element.jd index 1427b55219bdc49a765a03a4dc97cda375b60dbd..adb9937899fd2eafbf6b18cef7b6fb8d51448476 100644 --- a/docs/html/guide/topics/manifest/activity-alias-element.jd +++ b/docs/html/guide/topics/manifest/activity-alias-element.jd @@ -29,62 +29,62 @@ alias and it must be declared before the alias in the manifest.

          The alias presents the target activity as a independent entity. -It can have its own set of intent filters, and they, rather than the -intent filters on the target activity itself, determine which intents +It can have its own set of intent filters, and they, rather than the +intent filters on the target activity itself, determine which intents can activate the target through the alias and how the system -treats the alias. For example, the intent filters on the alias may -specify the "{@link android.content.Intent#ACTION_MAIN -android.intent.action.MAIN}" -and "{@link android.content.Intent#CATEGORY_LAUNCHER -android.intent.category.LAUNCHER}" flags, causing it to be -represented in the application launcher, even though none of the +treats the alias. For example, the intent filters on the alias may +specify the "{@link android.content.Intent#ACTION_MAIN +android.intent.action.MAIN}" +and "{@link android.content.Intent#CATEGORY_LAUNCHER +android.intent.category.LAUNCHER}" flags, causing it to be +represented in the application launcher, even though none of the filters on the target activity itself set these flags.

          With the exception of {@code targetActivity}, {@code } -attributes are a subset of <activity> attributes. +attributes are a subset of <activity> attributes. For attributes in the subset, none of the values set for the target carry over -to the alias. However, for attributes not in the subset, the values set for +to the alias. However, for attributes not in the subset, the values set for the target activity also apply to the alias.

          attributes:
          {@code android:enabled}
          -
          Whether or not the target activity can be instantiated by the system through -this alias — "{@code true}" if it can be, and "{@code false}" if not. +
          Whether or not the target activity can be instantiated by the system through +this alias — "{@code true}" if it can be, and "{@code false}" if not. The default value is "{@code true}".

          -The <application> element has its own -enabled attribute that applies to all -application components, including activity aliases. The +The <application> element has its own +enabled attribute that applies to all +application components, including activity aliases. The <application> and {@code } -attributes must both be "{@code true}" for the system to be able to instantiate -the target activity through the alias. If either is "{@code false}", the alias +attributes must both be "{@code true}" for the system to be able to instantiate +the target activity through the alias. If either is "{@code false}", the alias does not work.

          {@code android:exported}
          -
          Whether or not components of other applications can launch the target activity -through this alias — "{@code true}" if they can, and "{@code false}" if not. -If "{@code false}", the target activity can be launched through the alias only by -components of the same application as the alias or applications with the same user ID. +
          Whether or not components of other applications can launch the target activity +through this alias — "{@code true}" if they can, and "{@code false}" if not. +If "{@code false}", the target activity can be launched through the alias only by +components of the same application as the alias or applications with the same user ID.

          -The default value depends on whether the alias contains intent filters. The +The default value depends on whether the alias contains intent filters. The absence of any filters means that the activity can be invoked through the alias -only by specifying the exact name of the alias. This implies that the alias -is intended only for application-internal use (since others would not know its name) +only by specifying the exact name of the alias. This implies that the alias +is intended only for application-internal use (since others would not know its name) — so the default value is "{@code false}". -On the other hand, the presence of at least one filter implies that the alias +On the other hand, the presence of at least one filter implies that the alias is intended for external use — so the default value is "{@code true}".

          {@code android:icon}
          -
          An icon for the target activity when presented to users through the alias. -See the <activity> element's +
          An icon for the target activity when presented to users through the alias. +See the <activity> element's icon attribute for more information.
          {@code android:label}
          @@ -95,31 +95,31 @@ See the &l
          {@code android:name}
          A unique name for the alias. The name should resemble a fully -qualified class name. But, unlike the name of the target activity, -the alias name is arbitrary; it does not refer to an actual class. +qualified class name. But, unlike the name of the target activity, +the alias name is arbitrary; it does not refer to an actual class.

          {@code android:permission}
          -
          The name of a permission that clients must have to launch the target activity -or get it to do something via the alias. If a caller of +
          The name of a permission that clients must have to launch the target activity +or get it to do something via the alias. If a caller of {@link android.content.Context#startActivity startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()} has not been granted the specified permission, the target activity will not be -activated. +activated.

          This attribute supplants any permission set for the target activity itself. If it is not set, a permission is not needed to activate the target through the alias.

          -For more information on permissions, see the -Permissions +For more information on permissions, see the +Permissions section in the introduction.

          {@code android:targetActivity}
          The name of the activity that can be activated through the alias. -This name must match the {@code name} attribute of an +This name must match the {@code name} attribute of an <activity> element that precedes the alias in the manifest.

          diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd index f30263e8983c2e47646499fcd5c1c9ff45d095b7..6deb14b6581101d50d22ca69b11817ecb5586b20 100644 --- a/docs/html/guide/topics/manifest/activity-element.jd +++ b/docs/html/guide/topics/manifest/activity-element.jd @@ -25,7 +25,7 @@ parent.link=manifest-intro.html android:hardwareAccelerated=["true" | "false"] android:icon="drawable resource" android:label="string resource" - android:launchMode=["multiple" | "singleTop" | + android:launchMode=["standard" | "singleTop" | "singleTask" | "singleInstance"] android:maxRecents="integer" android:multiprocess=["true" | "false"] @@ -35,6 +35,7 @@ parent.link=manifest-intro.html android:permission="string" android:process="string" android:relinquishTaskIdentity=["true" | "false"] + android:resizeableActivity=["true" | "false"] android:screenOrientation=["unspecified" | "behind" | "landscape" | "portrait" | "reverseLandscape" | "reversePortrait" | @@ -43,6 +44,7 @@ parent.link=manifest-intro.html "sensor" | "fullSensor" | "nosensor" | "user" | "fullUser" | "locked"] android:stateNotNeeded=["true" | "false"] + android:supportsPictureInPicture=["true" | "false"] android:taskAffinity="string" android:theme="resource or theme" android:uiOptions=["none" | "splitActionBarWhenNarrow"] @@ -794,9 +796,39 @@ to "{@code false}". The default value is "{@code false}". and icons in the overview screen.

          +
          resizeableActivity
          + +
          +

          + Specifies whether the app supports multi-window display. You + can set this attribute in either the <activity> or + <application> + element. +

          + +

          + If you set this attribute to true, the user can launch the activity in + split-screen and freeform modes. If you set the attribute to false, the + activity does not support multi-window mode. If this value is false, and the + user attempts to launch the activity in multi-window mode, the activity takes + over the full screen. +

          + +

          + If your app targets API level 24 or higher, but you do not specify a value + for this attribute, the attribute's value defaults to true. +

          + +

          + This attribute was added in API level 24. +

          +
          {@code android:screenOrientation}
          -
          The orientation of the activity's display on the device. +
          The orientation of the activity's display on the device. The system ignores + this attribute if the activity is running in multi-window mode.

          The value can be any one of the following strings:

          @@ -921,6 +953,19 @@ home screen uses this setting to make sure that it does not get removed if it crashes for some reason.

          +
          supportsPictureInPicture
          + +
          +

          + Specifies whether the activity supports Picture-in-Picture + display. The system ignores this attribute if android:resizeableActivity is false. +

          + +

          This attribute was added in API level 24.

          +
          +
          {@code android:taskAffinity}
          The task that the activity has an affinity for. Activities with the same affinity conceptually belong to the same task (to the same diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd index 56d61f3f7235d6e129c69c4dcd787f1e881d74a4..f8e251ed73827fba00f89a3b8a81184efcdf2a1d 100644 --- a/docs/html/guide/topics/manifest/application-element.jd +++ b/docs/html/guide/topics/manifest/application-element.jd @@ -26,6 +26,7 @@ page.title=<application> android:process="string" android:restoreAnyVersion=["true" | "false"] android:requiredAccountType="string" + android:resizeableActivity=["true" | "false"] android:restrictedAccountType="string" android:supportsRtl=["true" | "false"] android:taskAffinity="string" @@ -358,6 +359,34 @@ your app to access personal information that belongs to the owner user.

          +
          resizeableActivity
          + +
          +

          + Specifies whether the app supports multi-window display. You + can set this attribute in either the + <activity> or <application> element. +

          + +

          + If you set this attribute to true, the user can launch the activity in + split-screen and freeform modes. If you set the attribute to false, the + activity does not support multi-window mode. If this value is false, and the + user attempts to launch the activity in multi-window mode, the activity takes + over the full screen. +

          + +

          + If your app targets API level 24 or higher, but you do not specify a value + for this attribute, the attribute's value defaults to true. +

          + +

          + This attribute was added in API level 24. +

          +
          +
          {@code android:restrictedAccountType}
          Specifies the account type required by this application and indicates that restricted profiles are allowed to access such accounts that belong to the owner user. If your app requires an diff --git a/docs/html/guide/topics/manifest/category-element.jd b/docs/html/guide/topics/manifest/category-element.jd index 0034119fe7b220c760c0aa48c32fc21e189880ae..d0f0edf6dd8c4ddeace55efc6880413d01020fc8 100644 --- a/docs/html/guide/topics/manifest/category-element.jd +++ b/docs/html/guide/topics/manifest/category-element.jd @@ -12,19 +12,19 @@ parent.link=manifest-intro.html
          description:
          Adds a category name to an intent filter. See -Intents and +Intents and Intent Filters for details on intent filters and the role of category specifications within a filter.
          attributes:
          {@code android:name}
          -
          The name of the category. Standard categories are defined in the +
          The name of the category. Standard categories are defined in the {@link android.content.Intent} class as CATEGORY_name -constants. The name assigned here can be derived from those constants -by prefixing "{@code android.intent.category.}" to the +constants. The name assigned here can be derived from those constants +by prefixing "{@code android.intent.category.}" to the name that follows {@code CATEGORY_}. For example, -the string value for {@code CATEGORY_LAUNCHER} is +the string value for {@code CATEGORY_LAUNCHER} is "{@code android.intent.category.LAUNCHER}".

          Note: In order to receive implicit intents, you must include the @@ -39,7 +39,7 @@ your activity.

          Custom categories should use the package name as a prefix, to ensure that they are unique.

          -
          +
          introduced in:
          diff --git a/docs/html/guide/topics/manifest/grant-uri-permission-element.jd b/docs/html/guide/topics/manifest/grant-uri-permission-element.jd index b2d9bb7a104e9eafdd499e8b6bf7422e48a15ea1..a464e552c47dc8389c69a6d7ee156df11732f26c 100644 --- a/docs/html/guide/topics/manifest/grant-uri-permission-element.jd +++ b/docs/html/guide/topics/manifest/grant-uri-permission-element.jd @@ -14,24 +14,24 @@ parent.link=manifest-intro.html
          description:
          Specifies which data subsets of the parent content provider permission -can be granted for. Data subsets are indicated by the path part of a +can be granted for. Data subsets are indicated by the path part of a {@code content:} URI. (The authority part of the URI identifies the -content provider.) -Granting permission is a way of enabling clients of the provider that don't -normally have permission to access its data to overcome that restriction on +content provider.) +Granting permission is a way of enabling clients of the provider that don't +normally have permission to access its data to overcome that restriction on a one-time basis. -

          -If a content provider's grantUriPermissions -attribute is "{@code true}", permission can be granted for any the data under -the provider's purview. However, if that attribute is "{@code false}", permission -can be granted only to data subsets that are specified by this element. +

          +If a content provider's grantUriPermissions +attribute is "{@code true}", permission can be granted for any the data under +the provider's purview. However, if that attribute is "{@code false}", permission +can be granted only to data subsets that are specified by this element. A provider can contain any number of {@code } elements. Each one can specify only one path (only one of the three possible attributes).

          -For information on how permission is granted, see the +For information on how permission is granted, see the <intent-filter> element's grantUriPermissions attribute.

          @@ -41,34 +41,34 @@ For information on how permission is granted, see the
          {@code android:path}
          {@code android:pathPrefix}
          {@code android:pathPattern}
          -
          A path identifying the data subset or subsets that permission can be -granted for. The {@code path} attribute specifies a complete path; -permission can be granted only to the particular data subset identified -by that path. -The {@code pathPrefix} attribute specifies the initial part of a path; -permission can be granted to all data subsets with paths that share that -initial part. -The {@code pathPattern} attribute specifies a complete path, but one +
          A path identifying the data subset or subsets that permission can be +granted for. The {@code path} attribute specifies a complete path; +permission can be granted only to the particular data subset identified +by that path. +The {@code pathPrefix} attribute specifies the initial part of a path; +permission can be granted to all data subsets with paths that share that +initial part. +The {@code pathPattern} attribute specifies a complete path, but one that can contain the following wildcards:
          • An asterisk ('{@code *}') matches a sequence of 0 to many occurrences of the immediately preceding character.
          • -
          • A period followed by an asterisk ("{@code .*}") matches any sequence of +

          • A period followed by an asterisk ("{@code .*}") matches any sequence of 0 to many characters.

          -Because '{@code \}' is used as an escape character when the string is read -from XML (before it is parsed as a pattern), you will need to double-escape: -For example, a literal '{@code *}' would be written as "{@code \\*}" and a -literal '{@code \}' would be written as "{@code \\\\}". This is basically +Because '{@code \}' is used as an escape character when the string is read +from XML (before it is parsed as a pattern), you will need to double-escape: +For example, a literal '{@code *}' would be written as "{@code \\*}" and a +literal '{@code \}' would be written as "{@code \\\\}". This is basically the same as what you would need to write if constructing the string in Java code.

          -For more information on these types of patterns, see the descriptions of +For more information on these types of patterns, see the descriptions of {@link android.os.PatternMatcher#PATTERN_LITERAL}, {@link android.os.PatternMatcher#PATTERN_PREFIX}, and {@link android.os.PatternMatcher#PATTERN_SIMPLE_GLOB} in the @@ -81,10 +81,10 @@ For more information on these types of patterns, see the descriptions of

          API Level 1
          see also:
          -
          the +
          the grantUriPermissions -attribute of the -<provider> +attribute of the +<provider> element
          diff --git a/docs/html/guide/topics/manifest/instrumentation-element.jd b/docs/html/guide/topics/manifest/instrumentation-element.jd index 74be559db1374d4b14d3f92d89dfe161f519dd32..a476be3b72f1aeacbbaf2d0636de1e8aa8550d41 100644 --- a/docs/html/guide/topics/manifest/instrumentation-element.jd +++ b/docs/html/guide/topics/manifest/instrumentation-element.jd @@ -23,15 +23,15 @@ object is instantiated before any of the application's components.
          attributes:
          {@code android:functionalTest}
          -
          Whether or not the Instrumentation class should run as a functional test +
          Whether or not the Instrumentation class should run as a functional test — "{@code true}" if it should, and "{@code false}" if not. The default value is "{@code false}".
          {@code android:handleProfiling}
          -
          Whether or not the Instrumentation object will turn profiling on and -off — "{@code true}" if it determines when profiling starts and -stops, and "{@code false}" if profiling continues the entire time it is -running. A value of "{@code true}" enables the object to target profiling +
          Whether or not the Instrumentation object will turn profiling on and +off — "{@code true}" if it determines when profiling starts and +stops, and "{@code false}" if profiling continues the entire time it is +running. A value of "{@code true}" enables the object to target profiling at a specific set of operations. The default value is "{@code false}".
          {@code android:icon}
          @@ -43,11 +43,11 @@ be set as a reference to a drawable resource.
          be set as a raw string or a reference to a string resource.
          {@code android:name}
          -
          The name of the {@link android.app.Instrumentation} subclass. -This should be a fully qualified class name (such as, -"{@code com.example.project.StringInstrumentation}"). However, as a shorthand, -if the first character of the name is a period, it is appended to the package -name specified in the <manifest> element. +
          The name of the {@link android.app.Instrumentation} subclass. +This should be a fully qualified class name (such as, +"{@code com.example.project.StringInstrumentation}"). However, as a shorthand, +if the first character of the name is a period, it is appended to the package +name specified in the <manifest> element.

          There is no default. The name must be specified. diff --git a/docs/html/guide/topics/manifest/intent-filter-element.jd b/docs/html/guide/topics/manifest/intent-filter-element.jd index 14b4e03b64a8f39cddafeee11897e43790b0893a..13956c9ad430d80d8c48be1748b65178d0e39912 100644 --- a/docs/html/guide/topics/manifest/intent-filter-element.jd +++ b/docs/html/guide/topics/manifest/intent-filter-element.jd @@ -27,23 +27,23 @@ parent.link=manifest-intro.html

          description:
          Specifies the types of intents that an activity, service, or broadcast receiver can respond to. An intent filter declares the capabilities of its -parent component — what an activity or service can do and what types -of broadcasts a receiver can handle. It opens the component to receiving -intents of the advertised type, while filtering out those that are not +parent component — what an activity or service can do and what types +of broadcasts a receiver can handle. It opens the component to receiving +intents of the advertised type, while filtering out those that are not meaningful for the component.

          -Most of the contents of the filter are described by its -<action>, +Most of the contents of the filter are described by its +<action>, <category>, and <data> subelements.

          -For a more detailed discussion of filters, see the separate -Intents -and Intent Filters document, as well as the -Intents Filters +For a more detailed discussion of filters, see the separate +Intents +and Intent Filters document, as well as the +Intents Filters section in the introduction.

          @@ -51,19 +51,19 @@ section in the introduction.
          {@code android:icon}
          An icon that represents the parent activity, service, or broadcast -receiver when that component is presented to the user as having the +receiver when that component is presented to the user as having the capability described by the filter.

          -This attribute must be set as a reference to a drawable resource -containing the image definition. The default value is the icon set -by the parent component's {@code icon} attribute. If the parent +This attribute must be set as a reference to a drawable resource +containing the image definition. The default value is the icon set +by the parent component's {@code icon} attribute. If the parent does not specify an icon, the default is the icon set by the <application> element.

          -For more on intent filter icons, see +For more on intent filter icons, see Icons and Labels in the introduction.

          @@ -75,44 +75,44 @@ to the user as having the capability described by the filter.

          The label should be set as a reference to a string resource, so that -it can be localized like other strings in the user interface. -However, as a convenience while you're developing the application, +it can be localized like other strings in the user interface. +However, as a convenience while you're developing the application, it can also be set as a raw string.

          -The default value is the label set by the parent component. If the +The default value is the label set by the parent component. If the parent does not specify a label, the default is the label set by the -<application> element's +<application> element's label attribute.

          -For more on intent filter labels, see +For more on intent filter labels, see Icons and Labels in the introduction.

          {@code android:priority}
          The priority that should be given to the parent component with regard -to handling intents of the type described by the filter. This attribute has +to handling intents of the type described by the filter. This attribute has meaning for both activities and broadcast receivers:
            -
          • It provides information about how able an activity is to respond to +
          • It provides information about how able an activity is to respond to an intent that matches the filter, relative to other activities that could -also respond to the intent. When an intent could be handled by multiple +also respond to the intent. When an intent could be handled by multiple activities with different priorities, Android will consider only those with higher priority values as potential targets for the intent.
          • It controls the order in which broadcast receivers are executed to -receive broadcast messages. Those with higher priority -values are called before those with lower values. (The order applies only +receive broadcast messages. Those with higher priority +values are called before those with lower values. (The order applies only to synchronous messages; it's ignored for asynchronous messages.)

          -Use this attribute only if you really need to impose a specific order in +Use this attribute only if you really need to impose a specific order in which the broadcasts are received, or want to force Android to prefer one activity over others.

          diff --git a/docs/html/guide/topics/manifest/manifest-intro.jd b/docs/html/guide/topics/manifest/manifest-intro.jd index c843567488e5c4f517c95d670dcc90d10e784e45..851674c0f78050cb779ab010cf4a753b22b3fbf4 100644 --- a/docs/html/guide/topics/manifest/manifest-intro.jd +++ b/docs/html/guide/topics/manifest/manifest-intro.jd @@ -6,50 +6,53 @@ page.title=App Manifest

          In this document

            -
          1. Structure of the Manifest File
          2. -
          3. File Conventions -
          4. File Features -
              -
            1. Intent Filters
            2. -
            3. Icons and Labels
            4. -
            5. Permissions
            6. -
            7. Libraries
            8. -
          5. +
          6. Manifest file structure
          7. +
          8. File conventions +
          9. File features +
              +
            1. Intent filters
            2. +
            3. Icons and labels
            4. +
            5. Permissions
            6. +
            7. Libraries
            8. +

          - Every application must have an AndroidManifest.xml file (with precisely that + Every application must have an {@code AndroidManifest.xml} file (with precisely that name) in its root directory. The manifest file - presents essential information about your app to the Android system, - information the system must have before it can run any of the app's - code. Among other things, the manifest does the following: + provides essential information about your app to the Android system, which + the system must have before it can run any of the app's + code. +

          + +

          +Among other things, the manifest file does the following:

          • It names the Java package for the application. The package name serves as a unique identifier for the application.
          • -
          • It describes the components of the application — the activities, -services, broadcast receivers, and content providers that the application is -composed of. It names the classes that implement each of the components and -publishes their capabilities (for example, which {@link android.content.Intent -Intent} messages they can handle). These declarations let the Android system -know what the components are and under what conditions they can be launched.
          • +
          • It describes the components of the application, which include the activities, +services, broadcast receivers, and content providers that compose the application. +It also names the classes that implement each of the components and +publishes their capabilities, such as the {@link android.content.Intent +Intent} messages that they can handle. These declarations inform the Android system +of the components and the conditions in which they can be launched.
          • -
          • It determines which processes will host application components.
          • +
          • It determines the processes that host the application components.
          • -
          • It declares which permissions the application must have in order to -access protected parts of the API and interact with other applications.
          • - -
          • It also declares the permissions that others are required to have in +
          • It declares the permissions that the application must have in order to +access protected parts of the API and interact with other applications. It also declares +the permissions that others are required to have in order to interact with the application's components.
          • It lists the {@link android.app.Instrumentation} classes that provide -profiling and other information as the application is running. These declarations +profiling and other information as the application runs. These declarations are present in the manifest only while the application is being developed and -tested; they're removed before the application is published.
          • +are removed before the application is published.
          • It declares the minimum level of the Android API that the application requires.
          • @@ -57,16 +60,27 @@ requires.
          • It lists the libraries that the application must be linked against.
          +

          Note: As you prepare your Android app to run on Chromebooks, +there are some important hardware and software feature limitations that you should consider. See +the +App Manifest Compatibility for Chromebooks document for more information. +

          + +

          Manifest file structure

          -

          Structure of the Manifest File

          +

          +The code snippet below shows the general structure of the manifest file and +every element that it can contain. Each element, along with all of its +attributes, is fully documented in a separate file. +

          + +

          Tip: To view detailed +information about any of the elements that are mentioned within the text of this document, +simply click the element name. +

          -The diagram below shows the general structure of the manifest file and -every element that it can contain. Each element, along with all of its -attributes, is documented in full in a separate file. To view detailed -information about any element, click on the element name in the diagram, -in the alphabetical list of elements that follows the diagram, or on any -other mention of the element name. +Here is an example of the manifest file:

          @@ -126,45 +140,45 @@ other mention of the element name.
           

          -All the elements that can appear in the manifest file are listed below -in alphabetical order. These are the only legal elements; you cannot -add your own elements or attributes. +The following list contains all of the elements that can appear in the manifest file, +in alphabetical order:

          -

          -<action> -
          <activity> -
          <activity-alias> -
          <application> -
          <category> -
          <data> -
          <grant-uri-permission> -
          <instrumentation> -
          <intent-filter> -
          <manifest> -
          <meta-data> -
          <permission> -
          <permission-group> -
          <permission-tree> -
          <provider> -
          <receiver> -
          <service> -
          <supports-screens> -
          <uses-configuration> -
          <uses-feature> -
          <uses-library> -
          <uses-permission> -
          <uses-sdk> -

          - - + +

          Note: These are the only legal elements – you cannot +add your own elements or attributes. +

          -

          File Conventions

          +

          File conventions

          -Some conventions and rules apply generally to all elements and attributes -in the manifest: +This section describes the conventions and rules that apply generally to all of the elements and +attributes in the manifest file.

          @@ -172,29 +186,28 @@ in the manifest:
          Only the <manifest> and <application> -elements are required, they each must be present and can occur only once. -Most of the others can occur many times or not at all — although at -least some of them must be present for the manifest to accomplish anything -meaningful. +elements are required. They each must be present and can occur only once. +Most of the other elements can occur many times or not at all. However, at +least some of them must be present before the manifest file becomes useful.

          If an element contains anything at all, it contains other elements. -All values are set through attributes, not as character data within an element. +All of the values are set through attributes, not as character data within an element.

          -Elements at the same level are generally not ordered. For example, +Elements at the same level are generally not ordered. For example, the <activity>, <provider>, and <service> elements can be intermixed in any sequence. There are two key exceptions to this -rule, however: +rule:

          Attributes
          -
          In a formal sense, all attributes are optional. However, there are some -that must be specified for an element to accomplish its purpose. Use the -documentation as a guide. For truly optional attributes, it mentions a default +
          In a formal sense, all attributes are optional. However, there are some attributes +that must be specified so that an element can accomplish its purpose. Use the +documentation as a guide. For truly optional attributes, it mentions a default value or states what happens in the absence of a specification.

          Except for some attributes of the root <manifest> -element, all attribute names begin with an {@code android:} prefix — -for example, {@code android:alwaysRetainTaskState}. Because the prefix is +element, all attribute names begin with an {@code android:} prefix. +For example, {@code android:alwaysRetainTaskState}. Because the prefix is universal, the documentation generally omits it when referring to attributes by name.

          @@ -223,7 +236,7 @@ by name.

          Many elements correspond to Java objects, including elements for the application itself (the <application> -element) and its principal components — activities +element) and its principal components: activities (<activity>), services (<service>), @@ -238,7 +251,7 @@ If you define a subclass, as you almost always would for the component classes {@link android.content.BroadcastReceiver}, and {@link android.content.ContentProvider}), the subclass is declared through a {@code name} attribute. The name must include the full package designation. -For example, an {@link android.app.Service} subclass might be declared as follows: +For example, a {@link android.app.Service} subclass might be declared as follows:

          <manifest . . . >
          @@ -251,12 +264,12 @@ For example, an {@link android.app.Service} subclass might be declared as follow
           </manifest>

          -However, as a shorthand, if the first character of the string is a period, the -string is appended to the application's package name (as specified by the +However, if the first character of the string is a period, the +application's package name (as specified by the <manifest> element's package -attribute). The following assignment is the same as the one above: +attribute) is appended to the string. The following assignment is the same as that shown above:

          <manifest package="com.example.project" . . . >
          @@ -269,13 +282,13 @@ attribute).  The following assignment is the same as the one above:
           </manifest>

          -When starting a component, Android creates an instance of the named subclass. +When starting a component, the Android system creates an instance of the named subclass. If a subclass isn't specified, it creates an instance of the base class.

          Multiple values
          If more than one value can be specified, the element is almost always -repeated, rather than listing multiple values within a single element. +repeated, rather than multiple values being listed within a single element. For example, an intent filter can list several actions:
          <intent-filter . . . >
          @@ -286,108 +299,105 @@ For example, an intent filter can list several actions:
           </intent-filter>
          Resource values
          -
          Some attributes have values that can be displayed to users — for -example, a label and an icon for an activity. The values of these attributes -should be localized and therefore set from a resource or theme. Resource -values are expressed in the following format,

          +
          Some attributes have values that can be displayed to users, such as +a label and an icon for an activity. The values of these attributes +should be localized and set from a resource or theme. Resource +values are expressed in the following format:

          {@code @[package:]type/name}

          -where the package name can be omitted if the resource is in the same package -as the application, type is a type of resource — such as "string" or -"drawable" — and name is the name that identifies the specific resource. -For example: +You can ommit the package name if the resource is in the same package +as the application. The type is a type of resource, such as string or +drawable, and the name is the name that identifies the specific resource. +Here is an example:

          <activity android:icon="@drawable/smallPic" . . . >

          -Values from a theme are expressed in a similar manner, but with an initial '{@code ?}' -rather than '{@code @}': +The values from a theme are expressed similarly, but with an initial {@code ?} +instead of {@code @}:

          {@code ?[package:]type/name}

          String values
          -
          Where an attribute value is a string, double backslashes ('{@code \\}') -must be used to escape characters — for example, '{@code \\n}' for -a newline or '{@code \\uxxxx}' for a Unicode character.
          +
          Where an attribute value is a string, you must use double backslashes ({@code \\}) +to escape characters, such as {@code \\n} for +a newline or {@code \\uxxxx} for a Unicode character.
          - -

          File Features

          +

          File features

          -The following sections describe how some Android features are reflected +The following sections describe the way that some Android features are reflected in the manifest file.

          -

          Intent Filters

          +

          Intent filters

          -The core components of an application (its activities, services, and broadcast -receivers) are activated by intents. An intent is a +The core components of an application, such as its activities, services, and broadcast +receivers, are activated by intents. An intent is a bundle of information (an {@link android.content.Intent} object) describing a -desired action — including the data to be acted upon, the category of +desired action, including the data to be acted upon, the category of component that should perform the action, and other pertinent instructions. -Android locates an appropriate component to respond to the intent, launches +The Android system locates an appropriate component that can respond to the intent, launches a new instance of the component if one is needed, and passes it the -Intent object. +{@link android.content.Intent} object.

          -Components advertise their capabilities — the kinds of intents they can -respond to — through intent filters. Since the Android system -must learn which intents a component can handle before it launches the component, +The components advertise the types of intents that they can +respond to through intent filters. Since the Android system +must learn the intents that a component can handle before it launches the component, intent filters are specified in the manifest as <intent-filter> -elements. A component may have any number of filters, each one describing +elements. A component can have any number of filters, each one describing a different capability.

          -An intent that explicitly names a target component will activate that component; -the filter doesn't play a role. But an intent that doesn't specify a target by +An intent that explicitly names a target component activates that component, so +the filter doesn't play a role. An intent that doesn't specify a target by name can activate a component only if it can pass through one of the component's filters.

          -For information on how Intent objects are tested against intent filters, -see a separate document, -Intents -and Intent Filters. +For information about how {@link android.content.Intent} objects are tested against intent filters, +see the Intents +and Intent Filters document.

          - -

          Icons and Labels

          +

          Icons and labels

          A number of elements have {@code icon} and {@code label} attributes for a -small icon and a text label that can be displayed to users. Some also have a -{@code description} attribute for longer explanatory text that can also be -shown on-screen. For example, the +small icon and a text label that can be displayed to users. Some also have a +{@code description} attribute for longer, explanatory text that can also be +shown on-screen. For example, the <permission> -element has all three of these attributes, so that when the user is asked whether +element has all three of these attributes so that when the user is asked whether to grant the permission to an application that has requested it, an icon representing the permission, the name of the permission, and a description of what it -entails can all be presented to the user. +entails are all presented to the user.

          -In every case, the icon and label set in a containing element become the default +In every case, the icon and label that are set in a containing element become the default {@code icon} and {@code label} settings for all of the container's subelements. -Thus, the icon and label set in the +Thus, the icon and label that are set in the <application> element are the default icon and label for each of the application's components. -Similarly, the icon and label set for a component — for example, an +Similarly, the icon and label that are set for a component, such as an <activity> -element — are the default settings for each of the component's +element, are the default settings for each of the component's <intent-filter> -elements. If an +elements. If an <application> element sets a label, but an activity and its intent filter do not, the application label is treated as the label for both the activity and @@ -395,62 +405,62 @@ the intent filter.

          -The icon and label set for an intent filter are used to represent a component -whenever the component is presented to the user as fulfilling the function -advertised by the filter. For example, a filter with -"{@code android.intent.action.MAIN}" and -"{@code android.intent.category.LAUNCHER}" settings advertises an activity -as one that initiates an application — that is, as -one that should be displayed in the application launcher. The icon and label -set in the filter are therefore the ones displayed in the launcher. +The icon and label that are set for an intent filter represent a component +whenever the component is presented to the user and fulfills the function +that is advertised by the filter. For example, a filter with +{@code android.intent.action.MAIN} and +{@code android.intent.category.LAUNCHER} settings advertises an activity +as one that initiates an application. That is, as +one that should be displayed in the application launcher. The icon and label +that are set in the filter are displayed in the launcher.

          -

          Permissions

          -A permission is a restriction limiting access to a part of the code -or to data on the device. The limitation is imposed to protect critical +A permission is a restriction that limits access to a part of the code +or to data on the device. The limitation is imposed to protect critical data and code that could be misused to distort or damage the user experience.

          -Each permission is identified by a unique label. Often the label indicates -the action that's restricted. For example, here are some permissions defined +Each permission is identified by a unique label. Often the label indicates +the action that's restricted. Here are some permissions that are defined by Android:

          -

          {@code android.permission.CALL_EMERGENCY_NUMBERS} -
          {@code android.permission.READ_OWNER_DATA} -
          {@code android.permission.SET_WALLPAPER} -
          {@code android.permission.DEVICE_POWER}

          +
            +
          • {@code android.permission.CALL_EMERGENCY_NUMBERS}
          • +
          • {@code android.permission.READ_OWNER_DATA}
          • +
          • {@code android.permission.SET_WALLPAPER}
          • +
          • {@code android.permission.DEVICE_POWER}
          • +

          -A feature can be protected by at most one permission. +A feature can be protected by only one permission.

          -If an application needs access to a feature protected by a permission, -it must declare that it requires that permission with a +If an application needs access to a feature that is protected by a permission, +it must declare that it requires the permission with a <uses-permission> -element in the manifest. Then, when the application is installed on -the device, the installer determines whether or not to grant the requested +element in the manifest. When the application is installed on +the device, the installer determines whether to grant the requested permission by checking the authorities that signed the application's certificates and, in some cases, asking the user. If the permission is granted, the application is able to use the protected -features. If not, its attempts to access those features will simply fail +features. If not, its attempts to access those features fail without any notification to the user.

          -An application can also protect its own components (activities, services, -broadcast receivers, and content providers) with permissions. It can employ -any of the permissions defined by Android (listed in -{@link android.Manifest.permission android.Manifest.permission}) or declared -by other applications. Or it can define its own. A new permission is declared +An application can also protect its own components with permissions. It can employ +any of the permissions that are defined by Android, as listed in +{@link android.Manifest.permission android.Manifest.permission}, or declared +by other applications. It can also define its own. A new permission is declared with the <permission> -element. For example, an activity could be protected as follows: +element. For example, an activity could be protected as follows:

          @@ -474,34 +484,34 @@ declared with the
           <permission>
           element, its use is also requested with the
           <uses-permission>
          -element.  Its use must be requested in order for other components of the
          +element. You must request its use in order for other components of the
           application to launch the protected activity, even though the protection
           is imposed by the application itself.
           

          -If, in the same example, the {@code permission} attribute was set to a -permission declared elsewhere -(such as {@code android.permission.CALL_EMERGENCY_NUMBERS}, it would not -have been necessary to declare it again with a +If, in the same example shown above, the {@code permission} attribute was set to a +permission that is declared elsewhere, +such as {@code android.permission.CALL_EMERGENCY_NUMBERS}, it would not +be necessary to declare it again with a <permission> -element. However, it would still have been necessary to request its use with +element. However, it would still be necessary to request its use with <uses-permission>.

          The <permission-tree> -element declares a namespace for a group of permissions that will be defined in -code. And +element declares a namespace for a group of permissions that are defined in +code, and the <permission-group> -defines a label for a set of permissions (both those declared in the manifest with +defines a label for a set of permissions, both those declared in the manifest with <permission> -elements and those declared elsewhere). It affects only how the permissions are -grouped when presented to the user. The +elements and those declared elsewhere. This affects only how the permissions are +grouped when presented to the user. The <permission-group> -element does not specify which permissions belong to the group; -it just gives the group a name. A permission is placed in the group +element does not specify the permissions that belong to the group, but +it gives the group a name. You can place a permission in the group by assigning the group name to the <permission> element's @@ -515,15 +525,14 @@ attribute.

          Every application is linked against the default Android library, which includes the basic packages for building applications (with common classes -such as Activity, Service, Intent, View, Button, Application, ContentProvider, -and so on). +such as Activity, Service, Intent, View, Button, Application, and ContentProvider).

          -However, some packages reside in their own libraries. If your application -uses code from any of these packages, it must explicitly asked to be linked -against them. The manifest must contain a separate +However, some packages reside in their own libraries. If your application +uses code from any of these packages, it must explicitly ask to be linked +against them. The manifest must contain a separate <uses-library> -element to name each of the libraries. (The library name can be found in the -documentation for the package.) +element to name each of the libraries. You can find the library name in the +documentation for the package.

          diff --git a/docs/html/guide/topics/manifest/meta-data-element.jd b/docs/html/guide/topics/manifest/meta-data-element.jd index d3b41c391195bfdb576252aebb6235116f32a453..2d1bdfe59259c8b4be0f614ce446297f3796c9ef 100644 --- a/docs/html/guide/topics/manifest/meta-data-element.jd +++ b/docs/html/guide/topics/manifest/meta-data-element.jd @@ -19,18 +19,18 @@ parent.link=manifest-intro.html
          description:
          A name-value pair for an item of additional, arbitrary data that can -be supplied to the parent component. A component element can contain any +be supplied to the parent component. A component element can contain any number of {@code } subelements. The values from all of -them are collected in a single {@link android.os.Bundle} object and made -available to the component as the -{@link android.content.pm.PackageItemInfo#metaData +them are collected in a single {@link android.os.Bundle} object and made +available to the component as the +{@link android.content.pm.PackageItemInfo#metaData PackageItemInfo.metaData} field.

          -Ordinary values are specified through the value -attribute. However, to assign a resource ID as the value, use the -resource attribute instead. For example, -the following code assigns whatever value is stored in the {@code @string/kangaroo} +Ordinary values are specified through the value +attribute. However, to assign a resource ID as the value, use the +resource attribute instead. For example, +the following code assigns whatever value is stored in the {@code @string/kangaroo} resource to the "{@code zoo}" name:

          @@ -44,22 +44,22 @@ the numeric ID of the resource, not the value stored in the resource:
          <meta-data android:name="zoo" android:resource="@string/kangaroo" />

          -It is highly recommended that you avoid supplying related data as +It is highly recommended that you avoid supplying related data as multiple separate {@code } entries. Instead, if you -have complex data to associate with a component, store it as a resource and +have complex data to associate with a component, store it as a resource and use the {@code resource} attribute to inform the component of its ID.

          attributes:
          {@code android:name}
          -
          A unique name for the item. To ensure that the name is unique, use a -Java-style naming convention — for example, +
          A unique name for the item. To ensure that the name is unique, use a +Java-style naming convention — for example, "{@code com.example.project.activity.fred}".
          {@code android:resource}
          -
          A reference to a resource. The ID of the resource is the value assigned -to the item. The ID can be retrieved from the meta-data Bundle by the +
          A reference to a resource. The ID of the resource is the value assigned +to the item. The ID can be retrieved from the meta-data Bundle by the {@link android.os.Bundle#getInt Bundle.getInt()} method.
          {@code android:value}
          @@ -70,7 +70,7 @@ to the item. The ID can be retrieved from the meta-data Bundle by the Type Bundle method - String value, using double backslashes ({@code \\}) to escape characters + String value, using double backslashes ({@code \\}) to escape characters — such as "{@code \\n}" and "{@code \\uxxxxx}" for a Unicode character. {@link android.os.Bundle#getString(String) getString()} @@ -80,7 +80,7 @@ to the item. The ID can be retrieved from the meta-data Bundle by the Boolean value, either "{@code true}" or "{@code false}" {@link android.os.Bundle#getBoolean(String) getBoolean()} - Color value, in the form "{@code #rgb}", "{@code #argb}", + Color value, in the form "{@code #rgb}", "{@code #argb}", "{@code #rrggbb}", or "{@code #aarrggbb}" {@link android.os.Bundle#getInt(String) getInt()} diff --git a/docs/html/guide/topics/manifest/path-permission-element.jd b/docs/html/guide/topics/manifest/path-permission-element.jd index cdaf82b00f2928f509839a1ec8c9cc910e292ee7..47747073315145911dbe4ad2d1bcd39f6fd75fc7 100644 --- a/docs/html/guide/topics/manifest/path-permission-element.jd +++ b/docs/html/guide/topics/manifest/path-permission-element.jd @@ -33,9 +33,9 @@ specified multiple times to supply multiple paths.
          {@code android:path}
          -
          A complete URI path for a subset of content provider data. -Permission can be granted only to the particular data identified by this path. -When used to provide search suggestion content, it must be appended +
          A complete URI path for a subset of content provider data. +Permission can be granted only to the particular data identified by this path. +When used to provide search suggestion content, it must be appended with "/search_suggest_query".
          @@ -47,24 +47,24 @@ Permission can be granted to all data subsets with paths that share this initial
          {@code android:pathPattern}
          A complete URI path for a subset of content provider data, but one that can use the following wildcards: - -
            + +
            • An asterisk ('*'). This matches a sequence of 0 to many occurrences of -the immediately preceding character.
            • - -
            • A period followed by an asterisk (".*"). This matches any sequence of -0 or more characters.
            • -
            - -

            -Because '\' is used as an escape character when the string is read +the immediately preceding character. + +

          • A period followed by an asterisk (".*"). This matches any sequence of +0 or more characters.
          • +
          + +

          +Because '\' is used as an escape character when the string is read from XML (before it is parsed as a pattern), you will need to double-escape. -For example, a literal '*' would be written as "\\*" and a -literal '\' would be written as "\\". This is basically +For example, a literal '*' would be written as "\\*" and a +literal '\' would be written as "\\". This is basically the same as what you would need to write if constructing the string in Java code. -

          -

          -For more information on these types of patterns, see the descriptions of +

          +

          +For more information on these types of patterns, see the descriptions of PATTERN_LITERAL, PATTERN_PREFIX, and PATTERN_SIMPLE_GLOB in the @@ -74,20 +74,20 @@ For more information on these types of patterns, see the descriptions of

          {@code android:permission}
          The name of a permission that clients must have in order to read or write the -content provider's data. This attribute is a convenient way of setting a -single permission for both reading and writing. However, the -readPermission and +content provider's data. This attribute is a convenient way of setting a +single permission for both reading and writing. However, the +readPermission and writePermission attributes take precedence over this one. -
          +
          {@code android:readPermission}
          A permission that clients must have in order to query the content provider. -
          +
          {@code android:writePermission}
          A permission that clients must have in order to make changes to the data controlled by the content provider. -
          + diff --git a/docs/html/guide/topics/manifest/permission-group-element.jd b/docs/html/guide/topics/manifest/permission-group-element.jd index 3221d4b68c3640a228b3b17eda2427b7711fda0c..85452b534fcfc1d19b31422a17e7ffd57a028a74 100644 --- a/docs/html/guide/topics/manifest/permission-group-element.jd +++ b/docs/html/guide/topics/manifest/permission-group-element.jd @@ -20,17 +20,17 @@ permission join the group through the {@code permissionGroup} attribute of the presented together in the user interface.

          -Note that this element does not declare a permission itself, only a category in -which permissions can be placed. See the -<permission> element for element for information +Note that this element does not declare a permission itself, only a category in +which permissions can be placed. See the +<permission> element for element for information on declaring permissions and assigning them to groups.

          attributes:
          {@code android:description}
          -
          User-readable text that describes the group. The text should be -longer and more explanatory than the label. This attribute must be +
          User-readable text that describes the group. The text should be +longer and more explanatory than the label. This attribute must be set as a reference to a string resource. Unlike the {@code label} attribute, it cannot be a raw string.
          @@ -39,10 +39,10 @@ attribute, it cannot be a raw string.
          as a reference to a drawable resource containing the image definition.
          {@code android:label}
          -
          A user-readable name for the group. As a convenience, the label can -be directly set as a raw string while you're developing the application. -However, when the application is ready to be published, it should be set -as a reference to a string resource, so that it can be localized like other +
          A user-readable name for the group. As a convenience, the label can +be directly set as a raw string while you're developing the application. +However, when the application is ready to be published, it should be set +as a reference to a string resource, so that it can be localized like other strings in the user interface.
          {@code android:name}
          diff --git a/docs/html/guide/topics/manifest/permission-tree-element.jd b/docs/html/guide/topics/manifest/permission-tree-element.jd index 21d7352331f3b0a924e032181b862ac76ed02bbb..cbfd72cd8465a8e90d2e878c13c01bbd0a701c4a 100644 --- a/docs/html/guide/topics/manifest/permission-tree-element.jd +++ b/docs/html/guide/topics/manifest/permission-tree-element.jd @@ -14,7 +14,7 @@ parent.link=manifest-intro.html
          description:
          Declares the base name for a tree of permissions. The application takes -ownership of all names within the tree. It can dynamically add new permissions +ownership of all names within the tree. It can dynamically add new permissions to the tree by calling {@link android.content.pm.PackageManager#addPermission PackageManager.addPermission()}. Names within the tree are separated by periods ('{@code .}'). For example, if the base name is {@code com.example.project.taxes}, permissions like the following might be @@ -25,30 +25,30 @@ added:
          {@code com.example.project.taxes.deductions.EXAGGERATE}

          -Note that this element does not declare a permission itself, only a -namespace in which further permissions can be placed. See the -<permission> +Note that this element does not declare a permission itself, only a +namespace in which further permissions can be placed. See the +<permission> element for information on declaring permissions.

          attributes:
          {@code android:icon}
          -
          An icon representing all the permissions in the tree. This attribute -must be set as a reference to a drawable resource containing the image +
          An icon representing all the permissions in the tree. This attribute +must be set as a reference to a drawable resource containing the image definition.
          {@code android:label}
          -
          A user-readable name for the group. As a convenience, the label can -be directly set as a raw string for quick and dirty programming. However, -when the application is ready to be published, it should be set as a -reference to a string resource, so that it can be localized like other +
          A user-readable name for the group. As a convenience, the label can +be directly set as a raw string for quick and dirty programming. However, +when the application is ready to be published, it should be set as a +reference to a string resource, so that it can be localized like other strings in the user interface.
          {@code android:name}
          -
          The name that's at the base of the permission tree. It serves as -a prefix to all permission names in the tree. Java-style scoping should -be used to ensure that the name is unique. The name must have more than -two period-separated segments in its path — for example, +
          The name that's at the base of the permission tree. It serves as +a prefix to all permission names in the tree. Java-style scoping should +be used to ensure that the name is unique. The name must have more than +two period-separated segments in its path — for example, {@code com.example.base} is OK, but {@code com.example} is not.
          diff --git a/docs/html/guide/topics/manifest/provider-element.jd b/docs/html/guide/topics/manifest/provider-element.jd index 4b5c0c35bc2cdcdeea139b9f11e7c23524a05a4a..0e729c36f37e6db901f435d98253dcfaa518a2f7 100644 --- a/docs/html/guide/topics/manifest/provider-element.jd +++ b/docs/html/guide/topics/manifest/provider-element.jd @@ -37,41 +37,41 @@ parent.link=manifest-intro.html
          description:
          - Declares a content provider component. A content provider is a subclass of - {@link android.content.ContentProvider} that supplies structured access to data managed by the - application. All content providers in your application must be defined in a + Declares a content provider component. A content provider is a subclass of + {@link android.content.ContentProvider} that supplies structured access to data managed by the + application. All content providers in your application must be defined in a {@code } element in the manifest file; otherwise, the system is unaware of them and doesn't run them.

          You only declare content providers that are part of your application. Content providers in other applications that you use in your application should not be declared. -

          +

          The Android system stores references to content providers according to an authority - string, part of the provider's content URI. For example, suppose you want to + string, part of the provider's content URI. For example, suppose you want to access a content provider that stores information about health care professionals. To do - this, you call the method + this, you call the method {@link android.content.ContentResolver#query ContentResolver.query()}, which among other arguments takes a URI that identifies the provider: -

          +

           content://com.example.project.healthcareprovider/nurses/rn
           

          The content: scheme identifies the URI as a content URI pointing to - an Android content provider. The authority + an Android content provider. The authority com.example.project.healthcareprovider identifies the provider itself; the - Android system looks up the authority in its list of known providers and their authorities. - The substring nurses/rn is a path, which the content provider can use + Android system looks up the authority in its list of known providers and their authorities. + The substring nurses/rn is a path, which the content provider can use to identify subsets of the provider data.

          - Notice that when you define your provider in the <provider> element, you + Notice that when you define your provider in the <provider> element, you don't include the scheme or the path in the android:name argument, only the - authority. + authority.

          - For information on using and developing content providers, see the API Guide, + For information on using and developing content providers, see the API Guide, Content Providers.

          @@ -82,8 +82,8 @@ content://com.example.project.healthcareprovider/nurses/rn
          {@code android:authorities}
          A list of one or more URI authorities that identify data offered by the content provider. - Multiple authorities are listed by separating their names with a semicolon. - To avoid conflicts, authority names should use a Java-style naming convention + Multiple authorities are listed by separating their names with a semicolon. + To avoid conflicts, authority names should use a Java-style naming convention (such as {@code com.example.provider.cartoonprovider}). Typically, it's the name of the {@link android.content.ContentProvider} subclass that implements the provider

          @@ -92,92 +92,92 @@ content://com.example.project.healthcareprovider/nurses/rn

          {@code android:enabled}
          -
          Whether or not the content provider can be instantiated by the system — - "{@code true}" if it can be, and "{@code false}" if not. The default value +
          Whether or not the content provider can be instantiated by the system — + "{@code true}" if it can be, and "{@code false}" if not. The default value is "{@code true}".

          -The <application> element has its own -enabled attribute that applies to all -application components, including content providers. The +The <application> element has its own +enabled attribute that applies to all +application components, including content providers. The <application> and {@code } attributes must both be "{@code true}" (as they both -are by default) for the content provider to be enabled. If either is +are by default) for the content provider to be enabled. If either is "{@code false}", the provider is disabled; it cannot be instantiated.

          {@code android:exported}
          Whether the content provider is available for other applications to use: -
            +
            • true: The provider is available to other applications. Any application can use the provider's content URI to access it, subject to the permissions specified for the provider.
            • - false: The provider is not available to other applications. Set + false: The provider is not available to other applications. Set android:exported="false" to limit access to the provider to your applications. Only applications that have the same user ID (UID) as the provider will have access to it.

            - The default value is "true" for applications that set either + The default value is "true" for applications that set either android:minSdkVersion - or -android:targetSdkVersion to + or +android:targetSdkVersion to "16" or lower. For applications that - set either of these attributes to "17" or higher, the default is + set either of these attributes to "17" or higher, the default is "false".

            You can set android:exported="false" and still limit access to your - provider by setting permissions with the + provider by setting permissions with the permission attribute.

            -
          +
          {@code android:grantUriPermissions}
          -
          Whether or not those who ordinarily would not have permission to +
          Whether or not those who ordinarily would not have permission to access the content provider's data can be granted permission to do so, temporarily overcoming the restriction imposed by the readPermission, -writePermission, and -permission attributes -— -"{@code true}" if permission can be granted, and "{@code false}" if not. -If "{@code true}", permission can be granted to any of the content -provider's data. If "{@code false}", permission can be granted only -to the data subsets listed in -<grant-uri-permission> subelements, +writePermission, and +permission attributes +— +"{@code true}" if permission can be granted, and "{@code false}" if not. +If "{@code true}", permission can be granted to any of the content +provider's data. If "{@code false}", permission can be granted only +to the data subsets listed in +<grant-uri-permission> subelements, if any. The default value is "{@code false}".

          -Granting permission is a way of giving an application component one-time -access to data protected by a permission. For example, when an e-mail -message contains an attachment, the mail application may call upon the -appropriate viewer to open it, even though the viewer doesn't have general -permission to look at all the content provider's data. +Granting permission is a way of giving an application component one-time +access to data protected by a permission. For example, when an e-mail +message contains an attachment, the mail application may call upon the +appropriate viewer to open it, even though the viewer doesn't have general +permission to look at all the content provider's data.

          -

          -In such cases, permission is granted by -{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} -and {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} -flags in the Intent object that activates the component. For example, the -mail application might put {@code FLAG_GRANT_READ_URI_PERMISSION} in the -Intent passed to {@code Context.startActivity()}. The permission is specific -to the URI in the Intent. +

          +In such cases, permission is granted by +{@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} +and {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} +flags in the Intent object that activates the component. For example, the +mail application might put {@code FLAG_GRANT_READ_URI_PERMISSION} in the +Intent passed to {@code Context.startActivity()}. The permission is specific +to the URI in the Intent.

          If you enable this feature, either by setting this attribute to "{@code true}" -or by defining <grant-uri-permission> -subelements, you must call -{@link android.content.Context#revokeUriPermission -Context.revokeUriPermission()} when a covered URI is deleted from +or by defining <grant-uri-permission> +subelements, you must call +{@link android.content.Context#revokeUriPermission +Context.revokeUriPermission()} when a covered URI is deleted from the provider.

          @@ -187,52 +187,50 @@ element.

          {@code android:icon}
          -
          An icon representing the content provider. -This attribute must be set as a reference to a drawable resource containing -the image definition. If it is not set, the icon specified for the application -as a whole is used instead (see the <application> +
          An icon representing the content provider. +This attribute must be set as a reference to a drawable resource containing +the image definition. If it is not set, the icon specified for the application +as a whole is used instead (see the <application> element's icon attribute).
          {@code android:initOrder}
          -
          The order in which the content provider should be instantiated, -relative to other content providers hosted by the same process. -When there are dependencies among content providers, setting this -attribute for each of them ensures that they are created in the order -required by those dependencies. The value is a simple integer, +
          The order in which the content provider should be instantiated, +relative to other content providers hosted by the same process. +When there are dependencies among content providers, setting this +attribute for each of them ensures that they are created in the order +required by those dependencies. The value is a simple integer, with higher numbers being initialized first.
          {@code android:label}
          -
          A user-readable label for the content provided. -If this attribute is not set, the label set for the application as a whole is -used instead (see the <application> element's +
          A user-readable label for the content provided. +If this attribute is not set, the label set for the application as a whole is +used instead (see the <application> element's label attribute).

          The label should be set as a reference to a string resource, so that -it can be localized like other strings in the user interface. -However, as a convenience while you're developing the application, +it can be localized like other strings in the user interface. +However, as a convenience while you're developing the application, it can also be set as a raw string.

          {@code android:multiprocess}
          -
          Whether or not an instance of the content provider can be created in -every client process — "{@code true}" if instances can run in multiple -processes, and "{@code false}" if not. The default value is "{@code false}". +
          If the app runs in multiple processes, this attribute determines whether +multiple instances of the content provder are created. If true, +each of the app's processes has its own content provider object. If +false, the app's processes share only one content provider object. +The default value is false. -

          -Normally, a content provider is instantiated in the process of the -application that defined it. However, if this flag is set to "{@code true}", -the system can create an instance in every process where there's a client -that wants to interact with it, thus avoiding the overhead of interprocess -communication. -

          +

          Setting this flag to true may improve performance by reducing +the overhead of interprocess communication, but it also increases the memory +footprint of each process.

          {@code android:name}
          -
          The name of the class that implements the content provider, a subclass of -{@link android.content.ContentProvider}. This should be a fully qualified -class name (such as, "{@code com.example.project.TransportationProvider}"). -However, as a shorthand, if the first character of the name is a period, -it is appended to the package name specified in the +
          The name of the class that implements the content provider, a subclass of +{@link android.content.ContentProvider}. This should be a fully qualified +class name (such as, "{@code com.example.project.TransportationProvider}"). +However, as a shorthand, if the first character of the name is a period, +it is appended to the package name specified in the <manifest> element.

          @@ -242,58 +240,58 @@ There is no default. The name must be specified.

          {@code android:permission}
          The name of a permission that clients must have to read or write the -content provider's data. This attribute is a convenient way of setting a -single permission for both reading and writing. However, the -readPermission and +content provider's data. This attribute is a convenient way of setting a +single permission for both reading and writing. However, the +readPermission and writePermission attributes take precedence -over this one. If the readPermission +over this one. If the readPermission attribute is also set, it controls access for querying the content provider. And if the writePermission attribute is set, it controls access for modifying the provider's data.

          -For more information on permissions, see the -Permissions -section in the introduction and a separate document, +For more information on permissions, see the +Permissions +section in the introduction and a separate document, Security and Permissions.

          {@code android:process}
          -
          The name of the process in which the content provider should run. Normally, -all components of an application run in the default process created for the -application. It has the same name as the application package. The -<application> element's -process -attribute can set a different +
          The name of the process in which the content provider should run. Normally, +all components of an application run in the default process created for the +application. It has the same name as the application package. The +<application> element's +process +attribute can set a different default for all components. But each component can override the default -with its own {@code process} attribute, allowing you to spread your +with its own {@code process} attribute, allowing you to spread your application across multiple processes.

          -If the name assigned to this attribute begins with a colon (':'), a new -process, private to the application, is created when it's needed and +If the name assigned to this attribute begins with a colon (':'), a new +process, private to the application, is created when it's needed and the activity runs in that process. -If the process name begins with a lowercase character, the activity will run +If the process name begins with a lowercase character, the activity will run in a global process of that name, provided that it has permission to do so. -This allows components in different applications to share a process, reducing +This allows components in different applications to share a process, reducing resource usage.

          {@code android:readPermission}
          -
          A permission that clients must have to query the content provider. -See also the permission and +
          A permission that clients must have to query the content provider. +See also the permission and writePermission attributes.
          {@code android:syncable}
          -
          Whether or not the data under the content provider's control -is to be synchronized with data on a server — "{@code true}" +
          Whether or not the data under the content provider's control +is to be synchronized with data on a server — "{@code true}" if it is to be synchronized, and "{@code false}" if not.
          {@code android:writePermission}
          -
          A permission that clients must have to make changes to the data -controlled by the content provider. -See also the permission and +
          A permission that clients must have to make changes to the data +controlled by the content provider. +See also the permission and readPermission attributes.
          diff --git a/docs/html/guide/topics/manifest/receiver-element.jd b/docs/html/guide/topics/manifest/receiver-element.jd index 081a191c38e199aaa3710bbdc74f0989996696e8..c866047447e08f56f5432e9665aa8b8ac8029b67 100644 --- a/docs/html/guide/topics/manifest/receiver-element.jd +++ b/docs/html/guide/topics/manifest/receiver-element.jd @@ -24,30 +24,40 @@ parent.link=manifest-intro.html
          description:
          Declares a broadcast receiver (a {@link android.content.BroadcastReceiver} -subclass) as one of the application's components. Broadcast receivers enable -applications to receive intents that are broadcast by the system or by other +subclass) as one of the application's components. Broadcast receivers enable +applications to receive intents that are broadcast by the system or by other applications, even when other components of the application are not running.

          There are two ways to make a broadcast receiver known to the system: One is declare it in the manifest file with this element. The other is to create -the receiver dynamically in code and register it with the {@link +the receiver dynamically in code and register it with the {@link android.content.Context#registerReceiver Context.registerReceiver()} -method. See the {@link android.content.BroadcastReceiver} class description -for more on dynamically created receivers. +method. For more information about how to dynamically create receivers, see the +{@link android.content.BroadcastReceiver} class description. +

          + +

          + Warning: Limit how many broadcast + receivers you set in your app. Having too many broadcast receivers can + affect your app's performance and the battery life of users' devices. + For more information about APIs you can use instead of the + {@link android.content.BroadcastReceiver} class for scheduling background + work, see + Background Optimizations.

          attributes:
          {@code android:enabled}
          -
          Whether or not the broadcast receiver can be instantiated by the system — -"{@code true}" if it can be, and "{@code false}" if not. The default value +
          Whether or not the broadcast receiver can be instantiated by the system — +"{@code true}" if it can be, and "{@code false}" if not. The default value is "{@code true}".

          -The <application> element has its own -enabled attribute that applies to all -application components, including broadcast receivers. The +The <application> element has its own +enabled attribute that applies to all +application components, including broadcast receivers. The <application> and {@code } attributes must both be "{@code true}" for the broadcast receiver to be enabled. If either is "{@code false}", it is @@ -55,72 +65,72 @@ disabled; it cannot be instantiated.

          {@code android:exported}
          -
          Whether or not the broadcast receiver can receive messages from sources -outside its application — "{@code true}" if it can, and "{@code false}" -if not. If "{@code false}", the only messages the broadcast receiver can -receive are those sent by components of the same application or applications -with the same user ID. +
          Whether or not the broadcast receiver can receive messages from sources +outside its application — "{@code true}" if it can, and "{@code false}" +if not. If "{@code false}", the only messages the broadcast receiver can +receive are those sent by components of the same application or applications +with the same user ID.

          -The default value depends on whether the broadcast receiver contains intent filters. +The default value depends on whether the broadcast receiver contains intent filters. The absence of any filters means that it can be invoked only by Intent objects that -specify its exact class name. This implies that the receiver is intended only for -application-internal use (since others would not normally know the class name). +specify its exact class name. This implies that the receiver is intended only for +application-internal use (since others would not normally know the class name). So in this case, the default value is "{@code false}". -On the other hand, the presence of at least one filter implies that the broadcast -receiver is intended to receive intents broadcast by the system or other applications, +On the other hand, the presence of at least one filter implies that the broadcast +receiver is intended to receive intents broadcast by the system or other applications, so the default value is "{@code true}".

          -This attribute is not the only way to limit a broadcast receiver's external exposure. -You can also use a permission to limit the external entities that can send it messages +This attribute is not the only way to limit a broadcast receiver's external exposure. +You can also use a permission to limit the external entities that can send it messages (see the permission attribute).

          {@code android:icon}
          -
          An icon representing the broadcast receiver. This attribute must be set -as a reference to a drawable resource containing the image definition. -If it is not set, the icon specified for the application as a whole is used -instead (see the <application> +
          An icon representing the broadcast receiver. This attribute must be set +as a reference to a drawable resource containing the image definition. +If it is not set, the icon specified for the application as a whole is used +instead (see the <application> element's icon attribute).

          -The broadcast receiver's icon — whether set here or by the -<application> element — is also the -default icon for all the receiver's intent filters (see the -<intent-filter> element's -icon attribute). +The broadcast receiver's icon — whether set here or by the +<application> element — is also the +default icon for all the receiver's intent filters (see the +<intent-filter> element's +icon attribute).

          {@code android:label}
          -
          A user-readable label for the broadcast receiver. If this attribute is not -set, the label set for the application as a whole is -used instead (see the <application> element's +
          A user-readable label for the broadcast receiver. If this attribute is not +set, the label set for the application as a whole is +used instead (see the <application> element's label attribute).

          -The broadcast receiver's label — whether set here or by the -<application> element — is also the -default label for all the receiver's intent filters (see the -<intent-filter> element's -label attribute). +The broadcast receiver's label — whether set here or by the +<application> element — is also the +default label for all the receiver's intent filters (see the +<intent-filter> element's +label attribute).

          The label should be set as a reference to a string resource, so that -it can be localized like other strings in the user interface. -However, as a convenience while you're developing the application, +it can be localized like other strings in the user interface. +However, as a convenience while you're developing the application, it can also be set as a raw string.

          {@code android:name}
          -
          The name of the class that implements the broadcast receiver, a subclass of -{@link android.content.BroadcastReceiver}. This should be a fully qualified -class name (such as, "{@code com.example.project.ReportReceiver}"). However, -as a shorthand, if the first character of the name is a period (for example, -"{@code . ReportReceiver}"), it is appended to the package name specified in -the <manifest> element. +
          The name of the class that implements the broadcast receiver, a subclass of +{@link android.content.BroadcastReceiver}. This should be a fully qualified +class name (such as, "{@code com.example.project.ReportReceiver}"). However, +as a shorthand, if the first character of the name is a period (for example, +"{@code . ReportReceiver}"), it is appended to the package name specified in +the <manifest> element.

          Once you publish your application, you should not @@ -132,38 +142,38 @@ There is no default. The name must be specified.

          {@code android:permission}
          -
          The name of a permission that broadcasters must have to send a +
          The name of a permission that broadcasters must have to send a message to the broadcast receiver. -If this attribute is not set, the permission set by the +If this attribute is not set, the permission set by the <application> element's -permission attribute applies -to the broadcast receiver. If neither attribute is set, the receiver +permission attribute applies +to the broadcast receiver. If neither attribute is set, the receiver is not protected by a permission.

          -For more information on permissions, see the -Permissions -section in the introduction and a separate document, +For more information on permissions, see the +Permissions +section in the introduction and a separate document, Security and Permissions.

          {@code android:process}
          -
          The name of the process in which the broadcast receiver should run. -Normally, all components of an application run in the default process created -for the application. It has the same name as the application package. The -<application> element's -process attribute can set a different +
          The name of the process in which the broadcast receiver should run. +Normally, all components of an application run in the default process created +for the application. It has the same name as the application package. The +<application> element's +process attribute can set a different default for all components. But each component can override the default -with its own {@code process} attribute, allowing you to spread your +with its own {@code process} attribute, allowing you to spread your application across multiple processes.

          -If the name assigned to this attribute begins with a colon (':'), a new -process, private to the application, is created when it's needed and +If the name assigned to this attribute begins with a colon (':'), a new +process, private to the application, is created when it's needed and the broadcast receiver runs in that process. -If the process name begins with a lowercase character, the receiver will run +If the process name begins with a lowercase character, the receiver will run in a global process of that name, provided that it has permission to do so. -This allows components in different applications to share a process, reducing +This allows components in different applications to share a process, reducing resource usage.

          diff --git a/docs/html/guide/topics/manifest/service-element.jd b/docs/html/guide/topics/manifest/service-element.jd index fca85f5793c87a0f135fa3b3e9c5a5d533ae38fd..9197a7f0343575f46bbfafe94fab68cad402d56d 100644 --- a/docs/html/guide/topics/manifest/service-element.jd +++ b/docs/html/guide/topics/manifest/service-element.jd @@ -25,108 +25,108 @@ parent.link=manifest-intro.html
          description:
          Declares a service (a {@link android.app.Service} subclass) as one -of the application's components. Unlike activities, services lack a -visual user interface. They're used to implement long-running background -operations or a rich communications API that can be called by other +of the application's components. Unlike activities, services lack a +visual user interface. They're used to implement long-running background +operations or a rich communications API that can be called by other applications.

          All services must be represented by {@code } elements in -the manifest file. Any that are not declared there will not be seen +the manifest file. Any that are not declared there will not be seen by the system and will never be run.

          attributes:
          {@code android:enabled}
          -
          Whether or not the service can be instantiated by the system — -"{@code true}" if it can be, and "{@code false}" if not. The default value +
          Whether or not the service can be instantiated by the system — +"{@code true}" if it can be, and "{@code false}" if not. The default value is "{@code true}".

          -The <application> element has its own -enabled attribute that applies to all -application components, including services. The +The <application> element has its own +enabled attribute that applies to all +application components, including services. The <application> and {@code } attributes must both be "{@code true}" (as they both -are by default) for the service to be enabled. If either is +are by default) for the service to be enabled. If either is "{@code false}", the service is disabled; it cannot be instantiated.

          {@code android:exported}
          -
          Whether or not components of other applications can invoke -the service or interact with it — "{@code true}" if they can, and -"{@code false}" if not. When the value is "{@code false}", only -components of the same application or applications +
          Whether or not components of other applications can invoke +the service or interact with it — "{@code true}" if they can, and +"{@code false}" if not. When the value is "{@code false}", only +components of the same application or applications with the same user ID can start the service or bind to it.

          -The default value depends on whether the service contains intent filters. The -absence of any filters means that it can be invoked only by specifying -its exact class name. This implies that the service is intended only for -application-internal use (since others would not know the class name). So in +The default value depends on whether the service contains intent filters. The +absence of any filters means that it can be invoked only by specifying +its exact class name. This implies that the service is intended only for +application-internal use (since others would not know the class name). So in this case, the default value is "{@code false}". -On the other hand, the presence of at least one filter implies that the service +On the other hand, the presence of at least one filter implies that the service is intended for external use, so the default value is "{@code true}".

          This attribute is not the only way to limit the exposure of a service to other -applications. You can also use a permission to limit the external entities that -can interact with the service (see the permission +applications. You can also use a permission to limit the external entities that +can interact with the service (see the permission attribute).

          {@code android:icon}
          -
          An icon representing the service. This attribute must be set as a -reference to a drawable resource containing the image definition. -If it is not set, the icon specified for the application -as a whole is used instead (see the <application> +
          An icon representing the service. This attribute must be set as a +reference to a drawable resource containing the image definition. +If it is not set, the icon specified for the application +as a whole is used instead (see the <application> element's icon attribute).

          -The service's icon — whether set here or by the -<application> element — is also the -default icon for all the service's intent filters (see the -<intent-filter> element's +The service's icon — whether set here or by the +<application> element — is also the +default icon for all the service's intent filters (see the +<intent-filter> element's icon attribute). -

          +

          {@code android:isolatedProcess}
          If set to true, this service will run under a special process that is isolated from the rest of the system and has no permissions of its own. - The only communication with it is through the Service API + The only communication with it is through the Service API (binding and starting).
          {@code android:label}
          -
          A name for the service that can be displayed to users. -If this attribute is not set, the label set for the application as a whole is -used instead (see the <application> element's +
          A name for the service that can be displayed to users. +If this attribute is not set, the label set for the application as a whole is +used instead (see the <application> element's label attribute).

          -The service's label — whether set here or by the -<application> element — is also the -default label for all the service's intent filters (see the -<intent-filter> element's -label attribute). +The service's label — whether set here or by the +<application> element — is also the +default label for all the service's intent filters (see the +<intent-filter> element's +label attribute).

          The label should be set as a reference to a string resource, so that -it can be localized like other strings in the user interface. -However, as a convenience while you're developing the application, +it can be localized like other strings in the user interface. +However, as a convenience while you're developing the application, it can also be set as a raw string.

          {@code android:name}
          -
          The name of the {@link android.app.Service} subclass that implements -the service. This should be a fully qualified class name (such as, -"{@code com.example.project.RoomService}"). However, as a shorthand, if +
          The name of the {@link android.app.Service} subclass that implements +the service. This should be a fully qualified class name (such as, +"{@code com.example.project.RoomService}"). However, as a shorthand, if the first character of the name is a period (for example, "{@code .RoomService}"), -it is appended to the package name specified in the -<manifest> element. +it is appended to the package name specified in the +<manifest> element.

          Once you publish your application, you should not @@ -138,8 +138,8 @@ There is no default. The name must be specified.

          {@code android:permission}
          -
          The name of a permission that an entity must have in order to -launch the service or bind to it. If a caller of +
          The name of a permission that an entity must have in order to +launch the service or bind to it. If a caller of {@link android.content.Context#startService startService()}, {@link android.content.Context#bindService bindService()}, or {@link android.content.Context#stopService stopService()}, @@ -147,38 +147,38 @@ has not been granted this permission, the method will not work and the Intent object will not be delivered to the service.

          -If this attribute is not set, the permission set by the +If this attribute is not set, the permission set by the <application> element's -permission +permission attribute applies to the service. If neither attribute is set, the service is not protected by a permission.

          -For more information on permissions, see the -Permissions -section in the introduction and a separate document, +For more information on permissions, see the +Permissions +section in the introduction and a separate document, Security and Permissions.

          {@code android:process}
          -
          The name of the process where the service is to run. Normally, -all components of an application run in the default process created for the -application. It has the same name as the application package. The -<application> element's -process -attribute can set a different +
          The name of the process where the service is to run. Normally, +all components of an application run in the default process created for the +application. It has the same name as the application package. The +<application> element's +process +attribute can set a different default for all components. But component can override the default -with its own {@code process} attribute, allowing you to spread your +with its own {@code process} attribute, allowing you to spread your application across multiple processes.

          -If the name assigned to this attribute begins with a colon (':'), a new -process, private to the application, is created when it's needed and +If the name assigned to this attribute begins with a colon (':'), a new +process, private to the application, is created when it's needed and the service runs in that process. -If the process name begins with a lowercase character, the service will run +If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. -This allows components in different applications to share a process, reducing +This allows components in different applications to share a process, reducing resource usage.

          diff --git a/docs/html/guide/topics/manifest/supports-gl-texture-element.jd b/docs/html/guide/topics/manifest/supports-gl-texture-element.jd index ab751c217f05c7676e54180ee2d7427f6441a151..a72fc818b74b82e3a77d4d71db75b8a1fb8476e2 100644 --- a/docs/html/guide/topics/manifest/supports-gl-texture-element.jd +++ b/docs/html/guide/topics/manifest/supports-gl-texture-element.jd @@ -3,16 +3,16 @@ parent.title=The AndroidManifest.xml File parent.link=manifest-intro.html @jd:body -
          @@ -928,9 +928,9 @@ while (cur.moveToNext()) {
          {@link android.content.Intent#ACTION_VIEW VIEW}

          content://com.android.calendar/time/<ms_since_epoch>

          - You can also refer to the URI with -{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. -For an example of using this intent, see Using intents to view calendar data. + You can also refer to the URI with +{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. +For an example of using this intent, see Using intents to view calendar data. Open calendar to the time specified by <ms_since_epoch>. @@ -941,11 +941,11 @@ For an example of using this intent, see Using intents to view calendar data. - + View the event specified by <event_id>. @@ -958,12 +958,12 @@ For an example of using this intent, see Using an intent to edit an event. - - + + Edit the event specified by <event_id>. @@ -978,11 +978,11 @@ For an example of using this intent, see Using an intent to insert an event. - + Create an event. @@ -1002,7 +1002,7 @@ For an example of using this intent, see manifest file.

          - +

          When users run an application that uses this approach, the application sends them to the Calendar to finish adding the event. The {@link android.content.Intent#ACTION_INSERT INSERT} Intent uses extra fields to pre-populate a form with the details of the event in the Calendar. Users can then cancel the event, edit the form as needed, or save the event to their calendars.

          - +

          Here is a code snippet that schedules an event on January 19, 2012, that runs from 7:30 a.m. to 8:30 a.m. Note the following about this code snippet:

            -
          • It specifies {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} +
          • It specifies {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} as the Uri.
          • - +
          • It uses the {@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} and {@link @@ -1090,10 +1090,10 @@ android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} extra fields to pre-populate the form with the time of the event. The values for these times must be in UTC milliseconds from the epoch.
          • - +
          • It uses the {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL} extra field to provide a comma-separated list of invitees, specified by email address.
          • - +
           Calendar beginTime = Calendar.getInstance();
          @@ -1166,18 +1166,18 @@ access the Calendar Provider:

          • A sync adapter needs to specify that it's a sync adapter by setting {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} to true.
          • - - + +
          • A sync adapter needs to provide an {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} and an {@link android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} as query parameters in the URI.
          • - +
          • A sync adapter has write access to more columns than an application or widget. - For example, an application can only modify a few characteristics of a calendar, + For example, an application can only modify a few characteristics of a calendar, such as its name, display name, visibility setting, and whether the calendar is synced. By comparison, a sync adapter can access not only those columns, but many others, such as calendar color, time zone, access level, location, and so on. -However, a sync adapter is restricted to the ACCOUNT_NAME and +However, a sync adapter is restricted to the ACCOUNT_NAME and ACCOUNT_TYPE it specified.

          Here is a helper method you can use to return a URI for use with a sync adapter:

          @@ -1188,5 +1188,5 @@ However, a sync adapter is restricted to the ACCOUNT_NAME and .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }
          -

          For a sample implementation of a sync adapter (not specifically related to Calendar), see +

          For a sample implementation of a sync adapter (not specifically related to Calendar), see SampleSyncAdapter. diff --git a/docs/html/guide/topics/providers/content-provider-basics.jd b/docs/html/guide/topics/providers/content-provider-basics.jd index b7ae3d2cb85cfc309b4b56e248f8c58da6079fbb..37df4e92c66e8457192d50d966cf565256822097 100644 --- a/docs/html/guide/topics/providers/content-provider-basics.jd +++ b/docs/html/guide/topics/providers/content-provider-basics.jd @@ -238,7 +238,7 @@ page.title=Content Provider Basics For example, to get a list of the words and their locales from the User Dictionary Provider, you call {@link android.content.ContentResolver#query ContentResolver.query()}. The {@link android.content.ContentResolver#query query()} method calls the - {@link android.content.ContentProvider#query ContentProvider.query()} method defined by the + {@link android.content.ContentProvider#query ContentProvider.query()} method defined by the User Dictionary Provider. The following lines of code show a {@link android.content.ContentResolver#query ContentResolver.query()} call:

          @@ -253,7 +253,7 @@ mCursor = getContentResolver().query(

          Table 2 shows how the arguments to - {@link android.content.ContentResolver#query + {@link android.content.ContentResolver#query query(Uri,projection,selection,selectionArgs,sortOrder)} match an SQL SELECT statement:

          @@ -361,8 +361,8 @@ Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

          For the sake of clarity, the code snippets in this section call - {@link android.content.ContentResolver#query ContentResolver.query()} on the "UI thread"". In - actual code, however, you should do queries asynchronously on a separate thread. One way to do + {@link android.content.ContentResolver#query ContentResolver.query()} on the "UI thread"". In + actual code, however, you should do queries asynchronously on a separate thread. One way to do this is to use the {@link android.content.CursorLoader} class, which is described in more detail in the Loaders guide. Also, the lines of code are snippets only; they don't show a complete @@ -430,7 +430,7 @@ String[] mSelectionArgs = {""};

          The next snippet shows how to use {@link android.content.ContentResolver#query ContentResolver.query()}, using the User Dictionary - Provider as an example. A provider client query is similar to an SQL query, and it contains a + Provider as an example. A provider client query is similar to an SQL query, and it contains a set of columns to return, a set of selection criteria, and a sort order.

          @@ -440,8 +440,8 @@ String[] mSelectionArgs = {""};

          The expression that specifies the rows to retrieve is split into a selection clause and selection arguments. The selection clause is a combination of logical and Boolean expressions, - column names, and values (the variable mSelectionClause). If you specify the - replaceable parameter ? instead of a value, the query method retrieves the value + column names, and values (the variable mSelectionClause). If you specify the + replaceable parameter ? instead of a value, the query method retrieves the value from the selection arguments array (the variable mSelectionArgs).

          @@ -567,14 +567,14 @@ selectionArgs[0] = mUserInput;

          Displaying query results

          - The {@link android.content.ContentResolver#query ContentResolver.query()} client method always - returns a {@link android.database.Cursor} containing the columns specified by the query's - projection for the rows that match the query's selection criteria. A - {@link android.database.Cursor} object provides random read access to the rows and columns it - contains. Using {@link android.database.Cursor} methods, you can iterate over the rows in the + The {@link android.content.ContentResolver#query ContentResolver.query()} client method always + returns a {@link android.database.Cursor} containing the columns specified by the query's + projection for the rows that match the query's selection criteria. A + {@link android.database.Cursor} object provides random read access to the rows and columns it + contains. Using {@link android.database.Cursor} methods, you can iterate over the rows in the results, determine the data type of each column, get the data out of a column, and examine other - properties of the results. Some {@link android.database.Cursor} implementations automatically - update the object when the provider's data changes, or trigger methods in an observer object + properties of the results. Some {@link android.database.Cursor} implementations automatically + update the object when the provider's data changes, or trigger methods in an observer object when the {@link android.database.Cursor} changes, or both.

          @@ -705,14 +705,14 @@ if (mCursor != null) {

          To get the permissions needed to access a provider, an application requests them with a <uses-permission> - element in its manifest file. When the Android Package Manager installs the application, a user - must approve all of the permissions the application requests. If the user approves all of them, + element in its manifest file. When the Android Package Manager installs the application, a user + must approve all of the permissions the application requests. If the user approves all of them, Package Manager continues the installation; if the user doesn't approve them, Package Manager aborts the installation.

          The following -<uses-permission> +<uses-permission> element requests read access to the User Dictionary Provider:

          @@ -795,8 +795,8 @@ content://user_dictionary/words/<id_value>
               To update a row, you use a {@link android.content.ContentValues} object with the updated
               values just as you do with an insertion, and selection criteria just as you do with a query.
               The client method you use is
          -    {@link android.content.ContentResolver#update ContentResolver.update()}. You only need to add 
          -    values to the {@link android.content.ContentValues} object for columns you're updating. If you 
          +    {@link android.content.ContentResolver#update ContentResolver.update()}. You only need to add
          +    values to the {@link android.content.ContentValues} object for columns you're updating. If you
               want to clear the contents of a column, set the value to null.
           

          @@ -830,7 +830,7 @@ mRowsUpdated = getContentResolver().update(

          You should also sanitize user input when you call - {@link android.content.ContentResolver#update ContentResolver.update()}. To learn more about + {@link android.content.ContentResolver#update ContentResolver.update()}. To learn more about this, read the section Protecting against malicious input.

          Deleting data

          @@ -860,7 +860,7 @@ mRowsDeleted = getContentResolver().delete(
        12. You should also sanitize user input when you call - {@link android.content.ContentResolver#delete ContentResolver.delete()}. To learn more about + {@link android.content.ContentResolver#delete ContentResolver.delete()}. To learn more about this, read the section Protecting against malicious input.

          @@ -948,9 +948,9 @@ mRowsDeleted = getContentResolver().delete( To access a provider in "batch mode", you create an array of {@link android.content.ContentProviderOperation} objects and then dispatch them to a content provider with - {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. You pass the - content provider's authority to this method, rather than a particular content URI. - This allows each {@link android.content.ContentProviderOperation} object in the array to work + {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()}. You pass the + content provider's authority to this method, rather than a particular content URI. + This allows each {@link android.content.ContentProviderOperation} object in the array to work against a different table. A call to {@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()} returns an array of results.

          @@ -1013,7 +1013,7 @@ mRowsDeleted = getContentResolver().delete(

          A provider defines URI permissions for content URIs in its manifest, using the android:grantUriPermission - attribute of the + attribute of the <provider> element, as well as the <grant-uri-permission> diff --git a/docs/html/guide/topics/providers/content-provider-creating.jd b/docs/html/guide/topics/providers/content-provider-creating.jd index baa92e131dc74c046486615c80e59d56dc64af30..59dc108e3b36b0068a5256bf7d0173fb4cc9bd43 100755 --- a/docs/html/guide/topics/providers/content-provider-creating.jd +++ b/docs/html/guide/topics/providers/content-provider-creating.jd @@ -422,7 +422,7 @@ public class ExampleProvider extends ContentProvider { * in the path */ sUriMatcher.addURI("com.example.app.provider", "table3", 1); - + /* * Sets the code for a single row to 2. In this case, the "#" wildcard is * used. "content://com.example.app.provider/table3/3" matches, but @@ -460,7 +460,7 @@ public class ExampleProvider extends ContentProvider { * present. Get the last path segment from the URI; this is the _ID value. * Then, append the value to the WHERE clause for the query */ - selection = selection + "_ID = " uri.getLastPathSegment(); + selection = selection + "_ID = " + uri.getLastPathSegment(); break; default: @@ -881,7 +881,7 @@ vnd.android.cursor.item/vnd.com.example.provider.table1 A contract class also helps developers because it usually has mnemonic names for its constants, so developers are less likely to use incorrect values for column names or URIs. Since it's a class, it can contain Javadoc documentation. Integrated development environments such as - Android Studio can auto-complete constant names from the contract class and display Javadoc for + Android Studio can auto-complete constant names from the contract class and display Javadoc for the constants.

          diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd index b30c74104bc1b0d69a2aa6ff23cff7ac07e5b8b3..89cfff93514c72262aa15a55aaa38b8f9b2a9bc0 100755 --- a/docs/html/guide/topics/renderscript/compute.jd +++ b/docs/html/guide/topics/renderscript/compute.jd @@ -185,7 +185,7 @@ Allocations} but no output {@link android.renderscript.Allocation Allocations}.<

          Reduction kernels are explained in more detail here.

          -

          Reduction kernels are supported in Android Nougat (API level 24) and later.

          +

          Reduction kernels are supported in Android 7.0 (API level 24) and later.

      @@ -578,7 +578,7 @@ following:

    • searching for a specific value or for the coordinate of a specific value within the data
    -

    In Android Nougat (API level 24) and later, RenderScript supports reduction kernels to allow +

    In Android 7.0 (API level 24) and later, RenderScript supports reduction kernels to allow efficient user-written reduction algorithms. You may launch reduction kernels on inputs with 1, 2, or 3 dimensions.

    diff --git a/docs/html/guide/topics/resources/accessing-resources.jd b/docs/html/guide/topics/resources/accessing-resources.jd index b971238c177324e524142cfb9dec72cb4bef1667..953b27418efcbf473ae7c407d1cf38bf2df61760 100644 --- a/docs/html/guide/topics/resources/accessing-resources.jd +++ b/docs/html/guide/topics/resources/accessing-resources.jd @@ -264,8 +264,8 @@ reference a system resource, you would need to include the package name. For exa android:text="@string/hello" /> -

    Note: You should use string resources at -all times, so that your application can be localized for other languages. +

    Note: You should use string resources at +all times, so that your application can be localized for other languages. For information about creating alternative resources (such as localized strings), see Providing Alternative diff --git a/docs/html/guide/topics/resources/animation-resource.jd b/docs/html/guide/topics/resources/animation-resource.jd index e5cac8874afb91a9ac70910b17a2090cb1dbb2b1..05582f0e366d2fa94fcbfe1bf3214780d791ee50 100644 --- a/docs/html/guide/topics/resources/animation-resource.jd +++ b/docs/html/guide/topics/resources/animation-resource.jd @@ -12,7 +12,7 @@ parent.link=available-resources.html

    1. Tween animation
    2. Frame animation
    3. -
    +
  • See also

    @@ -94,7 +94,7 @@ In XML: @[package:]animator/filename </set> -

    The file must have a single root element: either +

    The file must have a single root element: either <set>, <objectAnimator>, or <valueAnimator>. You can group animation elements together inside the <set> element, including other <set> elements. @@ -109,7 +109,7 @@ group animation elements together inside the <set> element, i <valueAnimator>, or other <set> elements). Represents an {@link android.animation.AnimatorSet}.

    You can specify nested <set> tags to further - group animations together. Each <set> can define its own + group animations together. Each <set> can define its own ordering attribute.

    attributes:

    @@ -119,11 +119,11 @@ group animation elements together inside the <set> element, i
    Keyword. Specifies the play ordering of animations in this set. - - - - -
    ValueDescription
    sequentiallyPlay animations in this set sequentially
    together (default)Play animations in this set at the same time.
    + + + + +
    ValueDescription
    sequentiallyPlay animations in this set sequentially
    together (default)Play animations in this set at the same time.
    @@ -131,11 +131,11 @@ group animation elements together inside the <set> element, i
    <objectAnimator>
    Animates a specific property of an object over a specific amount of time. Represents an {@link android.animation.ObjectAnimator}.

    - +

    attributes:

    - android:propertyName + android:propertyName
    String. Required. The object's property to animate, referenced by its name. For example you can specify @@ -206,11 +206,11 @@ group animation elements together inside the <set> element, i
    Keyword. Do not specify this attribute if the value is a color. The animation framework automatically handles color values - - - - -
    ValueDescription
    intTypeSpecifies that the animated values are integers
    floatType (default)Specifies that the animated values are floats
    + + + + +
    ValueDescription
    intTypeSpecifies that the animated values are integers
    floatType (default)Specifies that the animated values are floats
    @@ -279,11 +279,11 @@ group animation elements together inside the <set> element, i
    Keyword. Do not specify this attribute if the value is a color. The animation framework automatically handles color values. - - - - -
    ValueDescription
    intTypeSpecifies that the animated values are integers
    floatType (default)Specifies that the animated values are floats
    + + + + +
    ValueDescription
    intTypeSpecifies that the animated values are integers
    floatType (default)Specifies that the animated values are floats
    @@ -320,7 +320,7 @@ group animation elements together inside the <set> element, i before starting the animation set. Calling {@link android.animation.AnimatorSet#setTarget setTarget()} sets a single target object for all children of the {@link android.animation.AnimatorSet} as a convenience. The following code shows how to do this:

    - +
     AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
         R.anim.property_animator);
    diff --git a/docs/html/guide/topics/resources/complex-xml-resources.jd b/docs/html/guide/topics/resources/complex-xml-resources.jd
    index 66dcb58347ab2179167b6c0e1fdc4359a0231f8c..ebf7bc3f02280bc5e987eb20284008bf576ae401 100644
    --- a/docs/html/guide/topics/resources/complex-xml-resources.jd
    +++ b/docs/html/guide/topics/resources/complex-xml-resources.jd
    @@ -93,8 +93,7 @@ Since we’re making an animated vector drawable, we put the file under re
             </vector>
         <aapt:attr />
     
    -    <target
    -        android:name="rotationGroup" />
    +    <target android:name="rotationGroup">
             <aapt:attr name="android:animation" >
                 <objectAnimator
                     android:duration="6000"
    @@ -102,6 +101,7 @@ Since we’re making an animated vector drawable, we put the file under re
                     android:valueFrom="0"
     
               android:valueTo="360" />
             <aapt:attr>
    +    </target>
     </animated-vector>
     
    diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd index aae0cbae99b32ef055c29c49a6c946c64a154e48..4587ae4ec5dbb75418886b521a9b1e3bcf63a8b1 100644 --- a/docs/html/guide/topics/resources/drawable-resource.jd +++ b/docs/html/guide/topics/resources/drawable-resource.jd @@ -1270,7 +1270,7 @@ the right edge, a right gravity clips the left edge, and neither clips both edge progressively reveal the image:

     ImageView imageview = (ImageView) findViewById(R.id.image);
    -ClipDrawable drawable = (ClipDrawable) imageview.getDrawable();
    +ClipDrawable drawable = (ClipDrawable) imageview.getBackground();
     drawable.setLevel(drawable.getLevel() + 1000);
     
    diff --git a/docs/html/preview/features/icu4j-framework.jd b/docs/html/guide/topics/resources/icu4j-framework.jd similarity index 92% rename from docs/html/preview/features/icu4j-framework.jd rename to docs/html/guide/topics/resources/icu4j-framework.jd index 839c077d3f6ad161937cac3d419eeaa54e7073ad..e7cbe72e9c6ba8c0215e4d6f3ecf1320ac6f41c6 100644 --- a/docs/html/preview/features/icu4j-framework.jd +++ b/docs/html/guide/topics/resources/icu4j-framework.jd @@ -30,14 +30,16 @@ page.image=images/cards/card-nyc_2x.jpg

    ICU4J is an open-source, widely used set of Java libraries providing Unicode - and globalization support for software applications. Android N - exposes a subset of the ICU4J APIs in the Android framework for app developers + and globalization support for software applications. Starting in Android 7.0 + (API level 24), Android + exposes a subset of the ICU4J APIs for app developers to use under the {@code android.icu} package. These APIs use localization data present on the device. As a result, you can reduce your APK footprint by not compiling the ICU4J libraries into your APK; instead, you can simply call out to them in the framework. (In this case, you may want to provide multiple versions - of your APK, so users running versions of Android lower than Android N + of your APK, so users running versions of Android lower than + Android 7.0 (API level 24) can download a version of the app that contains the ICU4J libraries.)

    @@ -51,17 +53,17 @@ page.image=images/cards/card-nyc_2x.jpg

    Relationship to ICU4J

    - Android N exposes a subset of the ICU4J APIs via the + Android exposes a subset of the ICU4J APIs via the android.icu package, rather than com.ibm.icu. The Android framework may choose not to - expose ICU4J APIs for various reasons; for example, Android N does not expose + expose ICU4J APIs for various reasons; for example, Android does not expose some deprecated APIs or those that the ICU team have not yet declared as stable. As the ICU team deprecates APIs in the future, Android will also mark them as deprecated but will continue to include them.

    Table 1. ICU and CLDR versions used - in Android N.

    + in Android].

    @@ -69,7 +71,7 @@ page.image=images/cards/card-nyc_2x.jpg - + diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd index 8c5708a4b122a86d2ab52b140e2839c47dd13242..ab381c33fb845c925f4d2554c00ee38052d66486 100644 --- a/docs/html/guide/topics/resources/layout-resource.jd +++ b/docs/html/guide/topics/resources/layout-resource.jd @@ -33,16 +33,17 @@ In XML: @[package:]layout/filename
    syntax:
    -<?xml version="1.0" encoding="utf-8"?>
    -<ViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
    +<?xml version="1.0" encoding="utf-8"?>
    +<ViewGroup
    +    xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@[+][package:]id/resource_name"
    -    android:layout_height=["dimension" | "fill_parent" | "wrap_content"]
    -    android:layout_width=["dimension" | "fill_parent" | "wrap_content"]
    +    android:layout_height=["dimension" | "match_parent" | "wrap_content"]
    +    android:layout_width=["dimension" | "match_parent" | "wrap_content"]
         [ViewGroup-specific attributes] >
         <View
             android:id="@[+][package:]id/resource_name"
    -        android:layout_height=["dimension" | "fill_parent" | "wrap_content"]
    -        android:layout_width=["dimension" | "fill_parent" | "wrap_content"]
    +        android:layout_height=["dimension" | "match_parent" | "wrap_content"]
    +        android:layout_width=["dimension" | "match_parent" | "wrap_content"]
             [View-specific attributes] >
             <requestFocus/>
         </View>
    @@ -82,15 +83,17 @@ about the value for {@code android:id} below.
             
    android:layout_height
    Dimension or keyword. Required. The height for the group, as a -dimension value (or dimension resource) or a keyword ({@code "fill_parent"} -or {@code "wrap_content"}). See the valid values below. +dimension value (or +dimension resource) or a keyword +({@code "match_parent"} or {@code "wrap_content"}). See the valid values below.
    android:layout_width
    Dimension or keyword. Required. The width for the group, as a -dimension value (or dimension resource) or a keyword ({@code "fill_parent"} -or {@code "wrap_content"}). See the valid values below. +dimension value (or +dimension resource) or a keyword +({@code "match_parent"} or {@code "wrap_content"}). See the valid values below.

    More attributes are supported by the {@link android.view.ViewGroup} @@ -114,15 +117,17 @@ the value for {@code android:id} below.

    android:layout_height
    Dimension or keyword. Required. The height for the element, as -a dimension value (or dimension resource) or a keyword ({@code "fill_parent"} -or {@code "wrap_content"}). See the valid values below. +a dimension value (or +dimension resource) or a keyword +({@code "match_parent"} or {@code "wrap_content"}). See the valid values below.
    android:layout_width
    Dimension or keyword. Required. The width for the element, as -a dimension value (or dimension resource) or a keyword ({@code "fill_parent"} -or {@code "wrap_content"}). See the valid values below. +a dimension value (or +dimension resource) or a keyword +({@code "match_parent"} or {@code "wrap_content"}). See the valid values below.

    More attributes are supported by the {@link android.view.View} @@ -221,9 +226,6 @@ plus symbol in the android:id value.

    deprecate fill_parent. - - - @@ -245,8 +247,8 @@ guide.
     <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -              android:layout_width="fill_parent" 
    -              android:layout_height="fill_parent" 
    +              android:layout_width="match_parent"
    +              android:layout_height="match_parent"
                   android:orientation="vertical" >
         <TextView android:id="@+id/text"
                   android:layout_width="wrap_content"
    @@ -279,4 +281,4 @@ public void onCreate(Bundle savedInstanceState) {
     
     
     
    -
    +
    \ No newline at end of file
    diff --git a/docs/html/guide/topics/resources/more-resources.jd b/docs/html/guide/topics/resources/more-resources.jd
    index 1afbf70731e40451065417a28a284adcf6bd4e00..8488cdee7620505bcac711bd036121def39a9921 100644
    --- a/docs/html/guide/topics/resources/more-resources.jd
    +++ b/docs/html/guide/topics/resources/more-resources.jd
    @@ -760,7 +760,7 @@ int color = colors.{@link android.content.res.TypedArray#getColor(int,int) getCo
         
     
     
    - 
    +
     
     
    example:
    @@ -781,7 +781,7 @@ int color = colors.{@link android.content.res.TypedArray#getColor(int,int) getCo
    - +
    see also:
    diff --git a/docs/html/preview/features/multilingual-support.jd b/docs/html/guide/topics/resources/multilingual-support.jd similarity index 58% rename from docs/html/preview/features/multilingual-support.jd rename to docs/html/guide/topics/resources/multilingual-support.jd index ff21b52d5a8b1680363cf90dde8dcad52c69221e..28699fe01a06615108137ea853757bd853fb1ded 100644 --- a/docs/html/preview/features/multilingual-support.jd +++ b/docs/html/guide/topics/resources/multilingual-support.jd @@ -18,25 +18,21 @@ page.image=images/cards/card-nyc_2x.jpg -

    Android N provides enhanced support for multilingual users, -allowing them to select multiple locales in settings. Android N +

    Starting in Android 7.0 (API level 24), +Android provides enhanced support for multilingual users, +allowing them to select multiple locales in settings. Android provides this capability by greatly expanding the number of locales supported -and changing the way the system resolves resources. The new method of resolving -resources is more robust and designed to be compatible with existing APKs, but -you should take extra care to spot any unexpected behavior. For example, you -should test to make sure that your app defaults to the expected language. Also, -if your app supports multiple languages, you should ensure that this support works as -intended. Finally, you should try to ensure that your app gracefully handles -languages that you didn't explicitly design it to support.

    - -

    This document starts by explaining the resource resolution strategy prior to -Android N. Next, it describes Android N's improved -resource-resolution strategy. Last, it explains how to take advantage of +and changing the way the system resolves resources.

    + +

    This document starts by explaining the resource resolution strategy in +versions of Android lower than 7.0 (API level 24). Next, it describes +the improved resource-resolution strategy in Android 7.0. +Last, it explains how to take advantage of the expanded number of locales to support more multilingual users.

    Challenges in Resolving Language Resources

    -

    Prior to Android N, Android could not always successfully +

    Prior to Android 7.0, Android could not always successfully match app and system locales.

    For example, assume that you have the following situation:

    @@ -88,25 +84,29 @@ Use default (en)

    In this example, the system displays English strings without knowing whether the user can understand English. This behavior is pretty common -today. Android N should substantially reduce the frequency -of outcomes like this one.

    +today.

    Improvements to Resource-Resolution Strategy

    -

    Android N brings more robust resource resolution, and -finds better fallbacks automatically. However, to speed up resolution and improve +

    Android 7.0 (API level 24) brings more robust resource resolution, and + finds better fallbacks automatically. + However, to speed up resolution and improve maintainability, you should store resources in the most common parent dialect. - For example, if you were storing Spanish resources in the {@code es-US} directory - before, move them into the {@code es-419} directory, which contains Latin American Spanish. - Similarly, if you have resource strings in a folder named {@code en-GB}, rename - the folder to {@code en-001} (international English), because the most common + For example, if you were storing Spanish resources + in the {@code values-es-rUS} directory + before, move them into the {@code values-b+es+419} directory, + which contains Latin American Spanish. + Similarly, if you have resource strings in a + directory named {@code values-en-rGB}, rename + the directory to {@code values-b+en+001} (International + English), because the most common parent for en-GB strings is {@code en-001}. The following examples explain why these practices improve performance and reliability of resource resolution.

    Resource resolution examples

    -

    With Android N, the case described in Table 1 is resolved -differently:

    +

    With versions of Android greater than 7.0, the case described in + Table 1 is resolved differently:

    Table 2. An improved resolution strategy for when there is no @@ -142,7 +142,8 @@ Use fr_FR

    Now the user gets French resources instead of English. This example also shows why you should store French strings in {@code fr} rather than {@code fr_FR} - for Android N. Here the course of action is to match the closest parent dialect, + for Android 7.0 or higher. Here the course of action is + to match the closest parent dialect, making resolution faster and more predictable.

    In addition to this improved resolution logic, Android now offers more @@ -184,38 +185,48 @@ Use it_IT

    Android API levelCLDR version
    Android NAndroid 7.0 (API level 24) 56 28
    fill_parentSets the dimension to match that of the parent element.
    wrap_content Sets the dimension only to the size required to fit the content of this element.
    -

    The user still gets a language they understand, even though the app doesn’t -support French.

    +

    + The user still gets a language they understand, even though the app doesn’t + support French. +

    Designing your App to Support Additional Locales

    LocaleList API

    -

    Android N adds a new API {@code LocaleList.getDefault()} -that lets apps directly query the list of languages a user has specified. This API -allows you to create more sophisticated - app behavior and better-optimized display of content. For example, Search +

    + Starting with Android 7.0 (API level 24), Android exposes the + {@code LocaleList.getDefault()} API + that lets apps directly query the list of languages a user has specified. This API + allows you to create more sophisticated + app behavior and better-optimized display of content. For example, Search can show results in multiple languages based on user’s settings. Browser apps can avoid offering to translate pages in a language the user already knows, - and keyboard apps can auto-enable all appropriate layouts.

    + and keyboard apps can auto-enable all appropriate layouts. +

    Formatters

    -

    Up through Android 6.0 (API level 23), Android supported only one or two locales - for many common languages -(en, es, ar, fr, ru). Because there were only a few variants of each language, -apps could get away with storing some numbers and dates as hard coded strings -in resource files. However, with Android's broadened set of supported locales, -there can be -significant differences in formats for dates, times, currencies, and similar -information even within a single locale. Hard-coding your formats can produce a -confusing experience for end users. Therefore, when developing for Android N -make sure to use formatters instead of hard coding numbers and date strings.

    - -

    A prime example is Arabic, whose support Android N expands from -one {@code ar_EG} to 27 Arabic locales. These locales can share most resources, -but some prefer ASCII digits, while others prefer native digits. For example, -when you want to create a sentence with a digit variable, such as -"Choose a 4 digit pin", use formatters as shown below:

    +

    + Up through Android 6.0 (API level 23), Android supported only one or + two locales + for many common languages + (en, es, ar, fr, ru). Because there were only a few variants of each language, + apps could get away with storing some numbers and dates as hard coded strings + in resource files. However, with Android's broadened set of supported + locales, there can be + significant differences in formats for dates, times, currencies, and similar + information even within a single locale. Hard-coding your formats can produce + a confusing experience for end users. + Therefore, when developing for Android 7.0 or higher versions, + make sure to use formatters instead of hard coding numbers and date strings.

    + +

    + For example, Android 7.0 and higher includes support for + 27 Arabic locales. These locales can share most resources, + but some prefer ASCII digits, while others prefer native digits. For example, + when you want to create a sentence with a digit variable, such as + "Choose a 4 digit pin", use formatters as shown below: +

     format(locale, "Choose a %d-digit PIN", 4)
    diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd index c919ed5e777dd9d83ce0d1d2627de6eee4d87678..80a989a57e2846160c0bdeb2ceb1045d70eeea45 100644 --- a/docs/html/guide/topics/resources/providing-resources.jd +++ b/docs/html/guide/topics/resources/providing-resources.jd @@ -523,7 +523,7 @@ is larger than the current screen, the system will not application will crash at runtime (for example, if all layout resources are tagged with the {@code xlarge} qualifier, but the device is a normal-size screen).

    Added in API level 4.

    - +

    See Supporting Multiple Screens for more information.

    Also see the {@link android.content.res.Configuration#screenLayout} configuration field, @@ -608,7 +608,7 @@ which indicates the current device orientation.

    Added in API level 8, television added in API 13, watch added in API 20.

    For information about how your app can respond when the device is inserted into or - removed from a dock, read Determining and Monitoring the Docking State and Type.

    This can change during the life of your application if the user places the device in a @@ -659,8 +659,8 @@ application during runtime.

    Level 8
  • {@code xxhdpi}: Extra-extra-high-density screens; approximately 480dpi. Added in API Level 16
  • -
  • {@code xxxhdpi}: Extra-extra-extra-high-density uses (launcher icon only, see the - note +
  • {@code xxxhdpi}: Extra-extra-extra-high-density uses (launcher icon only, see the + note in Supporting Multiple Screens); approximately 640dpi. Added in API Level 18
  • {@code nodpi}: This can be used for bitmap resources that you do not want to be scaled diff --git a/docs/html/guide/topics/resources/runtime-changes.jd b/docs/html/guide/topics/resources/runtime-changes.jd index 8781d208d6eacc6266fc86fc73ce5fbf4794a5a1..3444e167cfbaecfde4b3e5376ccca41d29c412a0 100644 --- a/docs/html/guide/topics/resources/runtime-changes.jd +++ b/docs/html/guide/topics/resources/runtime-changes.jd @@ -17,6 +17,8 @@ page.tags=activity,lifecycle
  • Accessing Resources
  • Faster Screen Orientation Change
  • +
  • + Multi-Window Lifecycle
  • @@ -84,12 +86,12 @@ your activity to preserve stateful objects.

    To retain stateful objects in a fragment during a runtime configuration change:

      -
    1. Extend the {@link android.app.Fragment} class and declare references to your stateful +
    2. Extend the {@link android.app.Fragment} class and declare references to your stateful objects.
    3. Call {@link android.app.Fragment#setRetainInstance(boolean)} when the fragment is created.
    4. Add the fragment to your activity.
    5. -
    6. Use {@link android.app.FragmentManager} to retrieve the fragment when the activity is +
    7. Use {@link android.app.FragmentManager} to retrieve the fragment when the activity is restarted.
    @@ -127,8 +129,8 @@ leak all the views and resources of the original activity instance. (Leaking res means that your application maintains a hold on them and they cannot be garbage-collected, so lots of memory can be lost.)

    -

    Then use {@link android.app.FragmentManager} to add the fragment to the activity. -You can obtain the data object from the fragment when the activity starts again during runtime +

    Then use {@link android.app.FragmentManager} to add the fragment to the activity. +You can obtain the data object from the fragment when the activity starts again during runtime configuration changes. For example, define your activity as follows:

    @@ -170,7 +172,7 @@ public class MyActivity extends Activity {
     

    In this example, {@link android.app.Activity#onCreate(Bundle) onCreate()} adds a fragment or restores a reference to it. {@link android.app.Activity#onCreate(Bundle) onCreate()} also stores the stateful object inside the fragment instance. -{@link android.app.Activity#onDestroy() onDestroy()} updates the stateful object inside the +{@link android.app.Activity#onDestroy() onDestroy()} updates the stateful object inside the retained fragment instance.

    diff --git a/docs/html/guide/topics/security/permissions.jd b/docs/html/guide/topics/security/permissions.jd index e7bf760bb84a4fcb3309f3cb5df5a9d4d9325a36..39a1f814e49a291abbd5a5eda9929ea452d8621a 100644 --- a/docs/html/guide/topics/security/permissions.jd +++ b/docs/html/guide/topics/security/permissions.jd @@ -675,7 +675,7 @@ Services that cost you money: send SMS messages, directly call phone numbers

    Enforcing Permissions in AndroidManifest.xml

    -

    TYou can apply high-level permissions restricting access to entire components +

    You can apply high-level permissions restricting access to entire components of the system or application through your AndroidManifest.xml. To do this, include an {@link android.R.attr#permission android:permission} attribute on the desired diff --git a/docs/html/guide/topics/sensors/index.jd b/docs/html/guide/topics/sensors/index.jd index 09d27e7a9bd594bd27559712884e5413e3460984..36d3adcb48a3df368a6ba24983e763980a358294 100644 --- a/docs/html/guide/topics/sensors/index.jd +++ b/docs/html/guide/topics/sensors/index.jd @@ -1,7 +1,7 @@ page.title=Location and Sensors APIs page.landing=true page.tags=location,sensors -page.landing.intro=Use sensors on the device to add rich location and motion capabilities to your app, from GPS or network location to accelerometer, gyroscope, temperature, barometer, and more. +page.landing.intro=Use sensors on the device to add rich location and motion capabilities to your app, from GPS or network location to accelerometer, gyroscope, temperature, barometer, and more. page.landing.image= @jd:body @@ -10,7 +10,7 @@ page.landing.image=

    -

    The Android platform provides two sensors that let you determine the position of a device: the -geomagnetic field sensor and the orientation sensor. The Android platform also -provides a sensor that lets you determine how close the face of a device is to an object (known as -the proximity sensor). The geomagnetic field sensor and the proximity sensor are hardware-based. -Most -handset and tablet manufacturers include a geomagnetic field sensor. Likewise, handset manufacturers -usually include a proximity sensor to determine when a handset is being held close to a user's face -(for example, during a phone call). The orientation sensor is software-based and derives its data -from the accelerometer and the geomagnetic field sensor.

    - -

    Note: The orientation sensor was deprecated in Android 2.2 (API -Level 8).

    - -

    Position sensors are useful for determining a device's physical position in the -world's frame of reference. For example, you can use the geomagnetic field sensor in -combination with the accelerometer to determine a device's position relative to -the magnetic North Pole. You can also use the orientation sensor (or similar sensor-based -orientation methods) to determine a device's position in your application's frame of reference. -Position sensors are not typically used to monitor device movement or motion, such as shake, tilt, -or thrust (for more information, see Motion Sensors).

    - -

    The geomagnetic field sensor and orientation sensor return multi-dimensional arrays of sensor -values -for each {@link android.hardware.SensorEvent}. For example, the orientation sensor provides -geomagnetic -field strength values for each of the three coordinate axes during a single sensor event. Likewise, -the orientation sensor provides azimuth (yaw), pitch, and roll values during a single sensor event. -For more information about the coordinate systems that are used by sensors, see Sensor Coordinate -Systems. The proximity sensor provides a single value for each sensor event. Table 1 summarizes -the position sensors that are supported on the Android platform.

    +

    + The Android platform provides two sensors that let you determine the position + of a device: the geomagnetic field sensor and the accelerometer. The Android + platform also provides a sensor that lets you determine how close the face of + a device is to an object (known as the proximity sensor). The + geomagnetic field sensor and the proximity sensor are hardware-based. Most + handset and tablet manufacturers include a geomagnetic field sensor. Likewise, + handset manufacturers usually include a proximity sensor to determine when a + handset is being held close to a user's face (for example, during a phone + call). For determining a device's orientation, you can use the readings from + the device's accelerometer and the geomagnetic field sensor. +

    + +

    + Note: The orientation sensor was deprecated in Android 2.2 + (API level 8), and the orientation sensor type was deprecated in Android 4.4W + (API level 20). +

    + +

    + Position sensors are useful for determining a device's physical position in + the world's frame of reference. For example, you can use the geomagnetic field + sensor in combination with the accelerometer to determine a device's position + relative to the magnetic north pole. You can also use these sensors to + determine a device's orientation in your application's frame of reference. + Position sensors are not typically used to monitor device movement or motion, + such as shake, tilt, or thrust (for more information, see Motion Sensors). +

    + +

    + The geomagnetic field sensor and accelerometer return multi-dimensional arrays + of sensor values for each {@link android.hardware.SensorEvent}. For example, + the geomagnetic field sensor provides geomagnetic field strength values for + each of the three coordinate axes during a single sensor event. Likewise, the + accelerometer sensor measures the acceleration applied to the device during a + sensor event. For more information about the coordinate systems that are used + by sensors, see + Sensor Coordinate Systems. The proximity sensor provides a single value + for each sensor event. Table 1 summarizes the position sensors that are + supported on the Android platform. +

    Table 1. Position sensors that are supported on the Android platform.

    @@ -174,14 +185,17 @@ the position sensors that are supported on the Android platform.

    -

    1 This sensor was deprecated in Android 2.2 (API Level - 8). The sensor framework provides alternate methods for acquiring device orientation, which are -discussed in Using the Orientation Sensor.

    +

    + 1This sensor was deprecated in Android 2.2 (API + level 8), and this sensor type was deprecated in Android 4.4W (API level 20). + The sensor framework provides alternate methods for acquiring device + orientation, which are discussed in Computing + the Device's Orientation. +

    2 Some proximity sensors provide only binary values representing near and far.

    -

    Using the Game Rotation Vector Sensor

    The game rotation vector sensor is identical to the @@ -228,71 +242,106 @@ mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTO

    -

    Using the Orientation Sensor

    - -

    The orientation sensor lets you monitor the position of a device relative to the earth's frame of -reference (specifically, magnetic north). The following code shows you how to get an instance of the -default orientation sensor:

    +

    Computing the Device's Orientation

    +

    By computing a device's orientation, you can monitor the position of the + device relative to the earth's frame of reference (specifically, the magnetic + north pole). The following code shows you how to compute a device's + orientation: +

     private SensorManager mSensorManager;
    -private Sensor mSensor;
     ...
    -mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    -mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    +// Rotation matrix based on current readings from accelerometer and magnetometer.
    +final float[] rotationMatrix = new float[9];
    +mSensorManager.getRotationMatrix(rotationMatrix, null,
    +  accelerometerReading, magnetometerReading);
    +
    +// Express the updated rotation matrix as three orientation angles.
    +final float[] orientationAngles = new float[3];
    +mSensorManager.getOrientation(rotationMatrix, orientationAngles);
     
    - -

    The orientation sensor derives its data by using a device's geomagnetic field sensor in -combination with a device's accelerometer. Using these two hardware sensors, an orientation sensor -provides data for the following three dimensions:

    - +

    The system computes the orientation angles by using a device's geomagnetic + field sensor in combination with the device's accelerometer. Using these two + hardware sensors, the system provides data for the following three + orientation angles: +

      -
    • Azimuth (degrees of rotation around the z axis). This is the angle between magnetic north -and the device's y axis. For example, if the device's y axis is aligned with magnetic north -this value is 0, and if the device's y axis is pointing south this value is 180. Likewise, when -the y axis is pointing east this value is 90 and when it is pointing west this value is 270.
    • -
    • Pitch (degrees of rotation around the x axis). This value is positive when the positive z axis -rotates toward the positive y axis, and it is negative when the positive z axis -rotates toward the negative y axis. The range of values is 180 degrees to -180 -degrees.
    • -
    • Roll (degrees of rotation around the y axis). This value is positive when the positive z axis -rotates toward the positive x axis, and it is negative when the positive z axis -rotates toward the negative x axis. The range of values is 90 degrees to -90 -degrees.
    • +
    • + Azimuth (degrees of rotation about the -z axis). This is + the angle between the device's current compass direction and magnetic north. + If the top edge of the device faces magnetic north, the azimuth is 0 + degrees; if the top edge faces south, the azimuth is 180 degrees. Similarly, + if the top edge faces east, the azimuth is 90 degrees, and if the top edge + faces west, the azimuth is 270 degrees. +
    • +
    • + Pitch (degrees of rotation about the x axis). This is the + angle between a plane parallel to the device's screen and a plane parallel + to the ground. If you hold the device parallel to the ground with the bottom + edge closest to you and tilt the top edge of the device toward the ground, + the pitch angle becomes positive. Tilting in the opposite direction— + moving the top edge of the device away from the ground—causes + the pitch angle to become negative. The range of values is -180 degrees to + 180 degrees. +
    • +
    • + Roll (degrees of rotation about the y axis). This is the + angle between a plane perpendicular to the device's screen and a plane + perpendicular to the ground. If you hold the device parallel to the ground + with the bottom edge closest to you and tilt the left edge of the device + toward the ground, the roll angle becomes positive. Tilting in the opposite + direction—moving the right edge of the device toward the ground— + causes the roll angle to become negative. The range of values is -90 degrees + to 90 degrees. +
    -

    This definition is different from yaw, pitch, and roll used in aviation, where the X axis is -along the long side of the plane (tail to nose). Also, for historical reasons the roll angle is -positive in the clockwise direction (mathematically speaking, it should be positive in the -counter-clockwise direction).

    - -

    The orientation sensor derives its data by processing the raw sensor data from the accelerometer -and the geomagnetic field sensor. Because of the heavy processing that is involved, the accuracy and -precision of the orientation sensor is diminished (specifically, this sensor is only reliable when -the roll component is 0). As a result, the orientation sensor was deprecated in Android 2.2 (API -level 8). Instead of using raw data from the orientation sensor, we recommend that you use the -{@link android.hardware.SensorManager#getRotationMatrix getRotationMatrix()} method in conjunction -with the {@link android.hardware#getOrientation getOrientation()} method to compute orientation -values. You can also use the {@link android.hardware.SensorManager#remapCoordinateSystem -remapCoordinateSystem()} method to translate the orientation values to your application's frame of -reference.

    - -

    The following code sample shows how to acquire orientation data directly from the orientation -sensor. We recommend that you do this only if a device has negligible roll.

    - +

    + Note:The sensor's roll definition has changed to reflect the + vast majority of implementations in the geosensor ecosystem. +

    + +

    + Note that these angles work off of a different coordinate system than the + one used in aviation (for yaw, pitch, and roll). In the aviation system, the + x axis is along the long side of the plane, from tail to nose. +

    + +

    + The orientation sensor derives its data by processing the raw sensor data + from the accelerometer and the geomagnetic field sensor. Because of the heavy + processing that is involved, the accuracy and precision of the orientation + sensor is diminished. Specifically, this sensor is reliable only when the roll + angle is 0. As a result, the orientation sensor was deprecated in Android + 2.2 (API level 8), and the orientation sensor type was deprecated in Android + 4.4W (API level 20). + + Instead of using raw data from the orientation sensor, we recommend that you + use the {@link android.hardware.SensorManager#getRotationMatrix getRotationMatrix()} + method in conjunction with the + {@link android.hardware.SensorManager#getOrientation getOrientation()} method + to compute orientation values, as shown in the following code sample. As part + of this process, you can use the + {@link android.hardware.SensorManager#remapCoordinateSystem remapCoordinateSystem()} + method to translate the orientation values to your application's frame of + reference. +

     public class SensorActivity extends Activity implements SensorEventListener {
     
       private SensorManager mSensorManager;
    -  private Sensor mOrientation;
    +  private final float[] mAccelerometerReading = new float[3];
    +  private final float[] mMagnetometerReading = new float[3];
    +
    +  private final float[] mRotationMatrix = new float[9];
    +  private final float[] mOrientationAngles = new float[3];
     
       @Override
       public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
    -
         mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    -    mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
       }
     
       @Override
    @@ -304,31 +353,63 @@ public class SensorActivity extends Activity implements SensorEventListener {
       @Override
       protected void onResume() {
         super.onResume();
    -    mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_NORMAL);
    +
    +    // Get updates from the accelerometer and magnetometer at a constant rate.
    +    // To make batch operations more efficient and reduce power consumption,
    +    // provide support for delaying updates to the application.
    +    //
    +    // In this example, the sensor reporting delay is small enough such that
    +    // the application receives an update before the system checks the sensor
    +    // readings again.
    +    mSensorManager.registerListener(this, Sensor.TYPE_ACCELEROMETER,
    +      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
    +    mSensorManager.registerListener(this, Sensor.TYPE_MAGNETIC_FIELD,
    +      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
       }
     
       @Override
       protected void onPause() {
         super.onPause();
    +
    +    // Don't receive any more updates from either sensor.
         mSensorManager.unregisterListener(this);
       }
     
    +  // Get readings from accelerometer and magnetometer. To simplify calculations,
    +  // consider storing these readings as unit vectors.
       @Override
       public void onSensorChanged(SensorEvent event) {
    -    float azimuth_angle = event.values[0];
    -    float pitch_angle = event.values[1];
    -    float roll_angle = event.values[2];
    -    // Do something with these orientation angles.
    +    if (event.sensor == Sensor.TYPE_ACCELEROMETER) {
    +      System.arraycopy(event.values, 0, mAccelerometerReading,
    +        0, mAccelerometerReading.length);
    +    }
    +    else if (event.sensor == Sensor.TYPE_MAGNETIC_FIELD) {
    +      System.arraycopy(event.values, 0, mMagnetometerReading,
    +        0, mMagnetometerReading.length);
    +    }
    +  }
    +
    +  // Compute the three orientation angles based on the most recent readings from
    +  // the device's accelerometer and magnetometer.
    +  public void updateOrientationAngles() {
    +    // Update rotation matrix, which is needed to update orientation angles.
    +    mSensorManager.getRotationMatrix(mRotationMatrix, null,
    +      mAccelerometerReading, mMagnetometerReading);
    +
    +    // "mRotationMatrix" now has up-to-date information.
    +
    +    mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles);
    +
    +    // "mOrientationAngles" now has up-to-date information.
       }
     }
     
    -

    You do not usually need to perform any data processing or filtering of the raw data that you -obtain from an orientation sensor, other than translating the sensor's coordinate system to your -application's frame of reference. The Accelerometer Play sample shows -you how to translate acceleration sensor data into another frame of reference; the technique is -similar to the one you might use with the orientation sensor.

    +

    + You don't usually need to perform any data processing or filtering of the + device's raw orientation angles other than translating the sensor's + coordinate system to your application's frame of reference. +

    Using the Geomagnetic Field Sensor

    diff --git a/docs/html/guide/topics/text/index.jd b/docs/html/guide/topics/text/index.jd index 3865f25aee71481fb072c7653f820ac79aff4ccd..2bf46967339e8561871e7513dae16b6eb684b815 100644 --- a/docs/html/guide/topics/text/index.jd +++ b/docs/html/guide/topics/text/index.jd @@ -9,7 +9,7 @@ page.landing.image=

    - The Android platform offers a spelling checker framework that lets you implement - and access spell checking in your application. The framework is one of the + The Android platform offers a spelling checker framework that lets you implement + and access spell checking in your application. The framework is one of the Text Service APIs offered by the Android platform.

    - To use the framework in your app, you create a special type of Android service that + To use the framework in your app, you create a special type of Android service that generates a spelling checker session object. Based on text you provide, the session object returns spelling suggestions generated by the spelling checker.

    diff --git a/docs/html/guide/topics/ui/accessibility/apps.jd b/docs/html/guide/topics/ui/accessibility/apps.jd index 90781f7e81ae8a28cac3c7659be5f812bc3a8ebf..ab8c792cd24b67a52be41cc0fa4179b0868f8457 100644 --- a/docs/html/guide/topics/ui/accessibility/apps.jd +++ b/docs/html/guide/topics/ui/accessibility/apps.jd @@ -160,7 +160,7 @@ focus navigation.

    {@code android:focusable} attribute is set to {@code true}. This setting allows users to focus on the element using the directional controls and then interact with it. The user interface controls provided by the Android framework are focusable by default and visually indicate focus by changing -the control’s appearance.

    +the control's appearance.

    Android provides several APIs that let you control whether a user interface control is focusable and even request that a control be given focus:

    @@ -436,7 +436,7 @@ public boolean onKeyUp (int keyCode, KeyEvent event) {

    Populating accessibility events

    Each {@link android.view.accessibility.AccessibilityEvent} has a set of required properties that -describe the current state of the view. These properties include things such as the view’s class +describe the current state of the view. These properties include things such as the view's class name, content description and checked state. The specific properties required for each event type are described in the {@link android.view.accessibility.AccessibilityEvent} reference documentation. The {@link android.view.View} implementation provides default values for these properties. Many of @@ -454,10 +454,10 @@ following example code demonstrates a basic implementation of this method.

     @Override
    -public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
    -    super.dispatchPopulateAccessibilityEvent(event);
    +public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
         // Call the super implementation to populate its text to the event, which
         // calls onPopulateAccessibilityEvent() on API Level 14 and up.
    +    boolean completed = super.dispatchPopulateAccessibilityEvent(event);
     
         // In case this is running on a API revision earlier that 14, check
         // the text content of the event and add an appropriate text
    @@ -465,7 +465,9 @@ public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
         CharSequence text = getText();
         if (!TextUtils.isEmpty(text)) {
             event.getText().add(text);
    +        return true;
         }
    +    return completed;
     }
     
    diff --git a/docs/html/guide/topics/ui/accessibility/services.jd b/docs/html/guide/topics/ui/accessibility/services.jd index f91a9791a4696cb1eba7496db78656cf1b75c1ba..dbc69ef884ee2aee01b7e425755baf9d3ccee951 100644 --- a/docs/html/guide/topics/ui/accessibility/services.jd +++ b/docs/html/guide/topics/ui/accessibility/services.jd @@ -79,22 +79,15 @@ must also request the {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERV as shown in the following sample:

    -<manifest>
    -  ...
    -  <uses-permission ... />
    -  ...
       <application>
    -    ...
         <service android:name=".MyAccessibilityService"
    -        android:label="@string/accessibility_service_label"
    -        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    +        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
    +        android:label="@string/accessibility_service_label">
           <intent-filter>
             <action android:name="android.accessibilityservice.AccessibilityService" />
           </intent-filter>
         </service>
    -    <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
       </application>
    -</manifest>
     

    These declarations are required for all accessibility services deployed on Android 1.6 (API Level @@ -124,7 +117,7 @@ your accessibility service, as shown in the following example:

    </service> -

    This meta-data element refers to an XML file that you create in your application’s resource +

    This meta-data element refers to an XML file that you create in your application's resource directory ({@code /res/xml/accessibility_service_config.xml}). The following code shows example contents for the service configuration file:

    @@ -267,7 +260,7 @@ this way, the Android system can provide much richer detail about accessibility accessibility services to provide more useful feedback to users.

    An accessibility service gets information about an user interface event through an {@link -android.view.accessibility.AccessibilityEvent} passed by the system to the service’s +android.view.accessibility.AccessibilityEvent} passed by the system to the service's {@link android.accessibilityservice.AccessibilityService#onAccessibilityEvent onAccessibilityEvent()} callback method. This object provides details about the event, including the type of object being acted upon, its descriptive text and other details. Starting in Android 4.0 @@ -335,7 +328,7 @@ user actions). If your service requires all views, it can request them by settin of a user. This feature, added in Android 4.1 (API Level 16), and requires that your accessibility service request activation of the Explore by Touch feature. Your service can request this activation by setting the - {@link android.accessibilityservice.AccessibilityServiceInfo#flags flags} member of the service’s + {@link android.accessibilityservice.AccessibilityServiceInfo#flags flags} member of the service's {@link android.accessibilityservice.AccessibilityServiceInfo} instance to {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE}, as shown in the following example. diff --git a/docs/html/guide/topics/ui/binding.jd b/docs/html/guide/topics/ui/binding.jd index a4fd25c2825e9f6fa4255549c23fe0cff50ca7e5..48a1d409ef21ec487a7f75deaee66471a317a2e3 100644 --- a/docs/html/guide/topics/ui/binding.jd +++ b/docs/html/guide/topics/ui/binding.jd @@ -16,7 +16,7 @@ parent.link=index.html

    -// Get a Spinner and bind it to an ArrayAdapter that 
    +// Get a Spinner and bind it to an ArrayAdapter that
     // references a String array.
     Spinner s1 = (Spinner) findViewById(R.id.spinner1);
     ArrayAdapter adapter = ArrayAdapter.createFromResource(
    @@ -31,7 +31,7 @@ private static String[] PROJECTION = new String[] {
     
     Spinner s2 = (Spinner) findViewById(R.id.spinner2);
     Cursor cur = managedQuery(People.CONTENT_URI, PROJECTION, null, null);
    -     
    +
     SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this,
         android.R.layout.simple_spinner_item, // Use a template
                                               // that displays a
    @@ -41,7 +41,7 @@ SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this,
                                              // people database to...
         new int[] {android.R.id.text1}); // The "text1" view defined in
                                          // the XML template
    -					 
    +
     adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
     s2.setAdapter(adapter2);
     
    @@ -70,7 +70,7 @@ private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() { // Now hook into our object and set its onItemClickListener member // to our class handler object. mHistoryView = (ListView)findViewById(R.id.history); -mHistoryView.setOnItemClickListener(mMessageClickedHandler); +mHistoryView.setOnItemClickListener(mMessageClickedHandler);
    diff --git a/docs/html/guide/topics/ui/controls.jd b/docs/html/guide/topics/ui/controls.jd index a58d9f9b380f31386be3237034e2fb541a43b3d4..bb8c1a77958881c304fab0c0bb961eaac07ab1fb 100644 --- a/docs/html/guide/topics/ui/controls.jd +++ b/docs/html/guide/topics/ui/controls.jd @@ -71,7 +71,7 @@ href="{@docRoot}guide/topics/ui/custom-components.html">custom components. Radio button Similar to checkboxes, except that only one option can be selected in the group. - {@link android.widget.RadioGroup RadioGroup} + {@link android.widget.RadioGroup RadioGroup}
    {@link android.widget.RadioButton RadioButton} diff --git a/docs/html/guide/topics/ui/controls/button.jd b/docs/html/guide/topics/ui/controls/button.jd index 295044f0b55d08ba30be50716c38c6b2573d251d..a529d533de7930ed3abb9c5b7f6e399e2af8d828 100644 --- a/docs/html/guide/topics/ui/controls/button.jd +++ b/docs/html/guide/topics/ui/controls/button.jd @@ -214,7 +214,7 @@ pressed (activated).
  • The second <item> defines the bitmap to use when the button is focused (when the button is highlighted using the trackball or directional pad).
  • -
  • The third <item> defines the bitmap to use when the button is in the +
  • The third <item> defines the bitmap to use when the button is in the default state (it's neither pressed nor focused).
  • Note: The order of the <item> elements is diff --git a/docs/html/guide/topics/ui/controls/checkbox.jd b/docs/html/guide/topics/ui/controls/checkbox.jd index 2a64e38d3bf43b5e5d2348ec964a408ea56efd4d..f5feeb106a3806e6a42c83d0e27d73e75708c0bd 100644 --- a/docs/html/guide/topics/ui/controls/checkbox.jd +++ b/docs/html/guide/topics/ui/controls/checkbox.jd @@ -65,7 +65,7 @@ click event for both checkboxes:

    public void onCheckboxClicked(View view) { // Is the view now checked? boolean checked = ((CheckBox) view).isChecked(); - + // Check which checkbox was clicked switch(view.getId()) { case R.id.checkbox_meat: diff --git a/docs/html/guide/topics/ui/controls/pickers.jd b/docs/html/guide/topics/ui/controls/pickers.jd index c0667add65aaadea50794574fe96d9a2f0cd4b7a..9788f084022ae691cdd68316a1177c787dbc5b57 100644 --- a/docs/html/guide/topics/ui/controls/pickers.jd +++ b/docs/html/guide/topics/ui/controls/pickers.jd @@ -123,15 +123,15 @@ android.support.v4.app.DialogFragment#show show()}.

    For example, here's a button that, when clicked, calls a method to show the dialog:

    -<Button 
    -    android:layout_width="wrap_content" 
    +<Button
    +    android:layout_width="wrap_content"
         android:layout_height="wrap_content"
    -    android:text="@string/pick_time" 
    +    android:text="@string/pick_time"
         android:onClick="showTimePickerDialog" />
     

    When the user clicks this button, the system calls the following method:

    - +
     public void showTimePickerDialog(View v) {
         DialogFragment newFragment = new TimePickerFragment();
    @@ -224,15 +224,15 @@ android.support.v4.app.DialogFragment#show show()}.

    For example, here's a button that, when clicked, calls a method to show the dialog:

    -<Button 
    -    android:layout_width="wrap_content" 
    +<Button
    +    android:layout_width="wrap_content"
         android:layout_height="wrap_content"
    -    android:text="@string/pick_date" 
    +    android:text="@string/pick_date"
         android:onClick="showDatePickerDialog" />
     

    When the user clicks this button, the system calls the following method:

    - +
     public void showDatePickerDialog(View v) {
         DialogFragment newFragment = new DatePickerFragment();
    diff --git a/docs/html/guide/topics/ui/controls/radiobutton.jd b/docs/html/guide/topics/ui/controls/radiobutton.jd
    index b2556e1956ab387de1fe987d11f217523829d6bc..e1441d3f5fbff0d3efac8c81ffce6b0afc93ff36 100644
    --- a/docs/html/guide/topics/ui/controls/radiobutton.jd
    +++ b/docs/html/guide/topics/ui/controls/radiobutton.jd
    @@ -72,7 +72,7 @@ click event for both radio buttons:

    public void onRadioButtonClicked(View view) { // Is the button now checked? boolean checked = ((RadioButton) view).isChecked(); - + // Check which radio button was clicked switch(view.getId()) { case R.id.radio_pirates: diff --git a/docs/html/guide/topics/ui/controls/spinner.jd b/docs/html/guide/topics/ui/controls/spinner.jd index 3b8aaad4613c1539ffbce9308df8e0d79a5fd65f..00b0432f9f7081621ea178cc2f3a4498a122575e 100644 --- a/docs/html/guide/topics/ui/controls/spinner.jd +++ b/docs/html/guide/topics/ui/controls/spinner.jd @@ -4,7 +4,7 @@ page.tags=adapterview,spinneradapter
    - +

    In this document

    1. Populate the Spinner with User Choices
    2. @@ -113,8 +113,8 @@ For example, here's an implementation of the interface in an {@link android.app.
       public class SpinnerActivity extends Activity implements OnItemSelectedListener {
           ...
      -    
      -    public void onItemSelected(AdapterView<?> parent, View view, 
      +
      +    public void onItemSelected(AdapterView<?> parent, View view,
                   int pos, long id) {
               // An item was selected. You can retrieve the selected item using
               // parent.getItemAtPosition(pos)
      diff --git a/docs/html/guide/topics/ui/controls/text.jd b/docs/html/guide/topics/ui/controls/text.jd
      index f4d72b2a80f6ff59d6bbb60f30db3c13361ba2d1..f5c2a4251788dc01117aa5f1029d4d1a7b3bc3c5 100644
      --- a/docs/html/guide/topics/ui/controls/text.jd
      +++ b/docs/html/guide/topics/ui/controls/text.jd
      @@ -4,7 +4,7 @@ page.tags=edittext,autocompletetextview
       
       
      - +

      In this document

      1. Specifying the Keyboard Type @@ -279,7 +279,7 @@ that provides suggestions from an array, using {@link android.widget.ArrayAdapte layout with only the text field:
         <?xml version="1.0" encoding="utf-8"?>
        -<AutoCompleteTextView xmlns:android="http://schemas.android.com/apk/res/android" 
        +<AutoCompleteTextView xmlns:android="http://schemas.android.com/apk/res/android"
             android:id="@+id/autocomplete_country"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content" />
        @@ -313,8 +313,8 @@ code to specify the adapter that supplies the suggestions:
         AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete_country);
         // Get the string array
         String[] countries = getResources().getStringArray(R.array.countries_array);
        -// Create the adapter and set it to the AutoCompleteTextView 
        -ArrayAdapter<String> adapter = 
        +// Create the adapter and set it to the AutoCompleteTextView
        +ArrayAdapter<String> adapter =
                 new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, countries);
         textView.setAdapter(adapter);
         
        diff --git a/docs/html/guide/topics/ui/controls/togglebutton.jd b/docs/html/guide/topics/ui/controls/togglebutton.jd index e0549ecb28f43510dc113d5eea84592fc37b8598..181647c218495a6c2baac2562ad289720c7aa883 100644 --- a/docs/html/guide/topics/ui/controls/togglebutton.jd +++ b/docs/html/guide/topics/ui/controls/togglebutton.jd @@ -14,6 +14,7 @@ page.tags=switch,togglebutton
        1. {@link android.widget.ToggleButton}
        2. {@link android.widget.Switch}
        3. +
        4. {@link android.support.v7.widget.SwitchCompat}
        5. {@link android.widget.CompoundButton}
      @@ -21,9 +22,12 @@ page.tags=switch,togglebutton

      A toggle button allows the user to change a setting between two states.

      -

      You can add a basic toggle button to your layout with the {@link android.widget.ToggleButton} -object. Android 4.0 (API level 14) introduces another kind of toggle button called a switch that -provides a slider control, which you can add with a {@link android.widget.Switch} object.

      +

      You can add a basic toggle button to your layout with the +{@link android.widget.ToggleButton} object. Android 4.0 (API level 14) +introduces another kind of toggle button called a switch that provides a slider +control, which you can add with a {@link android.widget.Switch} object. +{@link android.support.v7.widget.SwitchCompat} is a version of the Switch +widget which runs on devices back to API 7.

      If you need to change a button's state yourself, you can use the {@link diff --git a/docs/html/guide/topics/ui/custom-components.jd b/docs/html/guide/topics/ui/custom-components.jd index b7249c56ea0ba22618a5945c32235c9a7b1ffbfa..bd3de1c29a24e7a72c6c68382b0637870a0bc2a1 100755 --- a/docs/html/guide/topics/ui/custom-components.jd +++ b/docs/html/guide/topics/ui/custom-components.jd @@ -14,37 +14,37 @@ page.tags=view,widget

    -

    Android offers a sophisticated and powerful componentized model for building your UI, -based on the fundamental layout classes: {@link android.view.View} and -{@link android.view.ViewGroup}. To start with, the platform includes a variety of prebuilt -View and ViewGroup subclasses — called widgets and layouts, respectively — +

    Android offers a sophisticated and powerful componentized model for building your UI, +based on the fundamental layout classes: {@link android.view.View} and +{@link android.view.ViewGroup}. To start with, the platform includes a variety of prebuilt +View and ViewGroup subclasses — called widgets and layouts, respectively — that you can use to construct your UI.

    -

    A partial list of available widgets includes {@link android.widget.Button Button}, -{@link android.widget.TextView TextView}, -{@link android.widget.EditText EditText}, +

    A partial list of available widgets includes {@link android.widget.Button Button}, +{@link android.widget.TextView TextView}, +{@link android.widget.EditText EditText}, {@link android.widget.ListView ListView}, -{@link android.widget.CheckBox CheckBox}, -{@link android.widget.RadioButton RadioButton}, -{@link android.widget.Gallery Gallery}, -{@link android.widget.Spinner Spinner}, and the more special-purpose -{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, +{@link android.widget.CheckBox CheckBox}, +{@link android.widget.RadioButton RadioButton}, +{@link android.widget.Gallery Gallery}, +{@link android.widget.Spinner Spinner}, and the more special-purpose +{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, {@link android.widget.ImageSwitcher ImageSwitcher}, and {@link android.widget.TextSwitcher TextSwitcher}.

    -

    Among the layouts available are {@link android.widget.LinearLayout LinearLayout}, -{@link android.widget.FrameLayout FrameLayout}, {@link android.widget.RelativeLayout RelativeLayout}, +

    Among the layouts available are {@link android.widget.LinearLayout LinearLayout}, +{@link android.widget.FrameLayout FrameLayout}, {@link android.widget.RelativeLayout RelativeLayout}, and others. For more examples, see Common Layout Objects.

    -

    If none of the prebuilt widgets or layouts meets your needs, you can create your own View subclass. -If you only need to make small adjustments to an existing widget or layout, you can simply subclass +

    If none of the prebuilt widgets or layouts meets your needs, you can create your own View subclass. +If you only need to make small adjustments to an existing widget or layout, you can simply subclass the widget or layout and override its methods.

    -

    Creating your own View subclasses gives you precise control over the appearance and function -of a screen element. To give an idea of the control you get with custom views, here are some +

    Creating your own View subclasses gives you precise control over the appearance and function +of a screen element. To give an idea of the control you get with custom views, here are some examples of what you could do with them:

    - +
    • You could create a completely custom-rendered View type, for example a "volume @@ -60,7 +60,7 @@ examples of what you could do with them:

    • You could override the way that an EditText component is rendered on the screen - (the Notepad Tutorial uses this to good effect, + (the Notepad Tutorial uses this to good effect, to create a lined-notepad page).
    • @@ -69,7 +69,7 @@ examples of what you could do with them:

    -The sections below explain how to create custom Views and use them in your application. +The sections below explain how to create custom Views and use them in your application. For detailed reference information, see the {@link android.view.View} class.

    @@ -77,26 +77,26 @@ For detailed reference information, see the {@link android.view.View} class.

    Here is a high level overview of what you need to know to get started in creating your own View components:

    - +
    1. - Extend an existing {@link android.view.View View} class or subclass + Extend an existing {@link android.view.View View} class or subclass with your own class.
    2. - Override some of the methods from the superclass. The superclass methods + Override some of the methods from the superclass. The superclass methods to override start with 'on', for - example, {@link android.view.View#onDraw onDraw()}, - {@link android.view.View#onMeasure onMeasure()}, and + example, {@link android.view.View#onDraw onDraw()}, + {@link android.view.View#onMeasure onMeasure()}, and {@link android.view.View#onKeyDown onKeyDown()}. - This is similar to the on... events in {@link android.app.Activity Activity} + This is similar to the on... events in {@link android.app.Activity Activity} or {@link android.app.ListActivity ListActivity} that you override for lifecycle and other functionality hooks.
    3. - Use your new extension class. Once completed, your new extension class + Use your new extension class. Once completed, your new extension class can be used in place of the view upon which it was based.
    4. -
    +

    Tip: Extension classes can be defined as inner classes inside the activities that use them. This is useful because it controls access to them but @@ -119,7 +119,7 @@ way you like, limited perhaps only by your imagination, the size of the screen, and the available processing power (remember that ultimately your application might have to run on something with significantly less power than your desktop workstation).

    -

    To create a fully customized component:

    +

    To create a fully customized component:

    1. The most generic view you can extend is, unsurprisingly, {@link @@ -170,11 +170,11 @@ slightly more complex by the requirements of limits from the parent (which are passed in to the onMeasure() method) and by the requirement to call the setMeasuredDimension() method with the measured width and height once they have been calculated. If you fail to -call this method from an overridden onMeasure() method, the +call this method from an overridden onMeasure() method, the result will be an exception at measurement time.

      -

      At a high level, implementing onMeasure() looks something +

      At a high level, implementing onMeasure() looks something like this:

      - +
      1. The overridden onMeasure() method is called with width and @@ -193,7 +193,7 @@ result will be an exception at measurement time.

        measurement width and height which will be required to render the component. It should try to stay within the specifications passed in, although it can choose to exceed them (in this case, the parent can - choose what to do, including clipping, scrolling, throwing an exception, + choose what to do, including clipping, scrolling, throwing an exception, or asking the onMeasure() to try again, perhaps with different measurement specifications).
      2. @@ -212,7 +212,7 @@ Here's a summary of some of the other standard methods that the framework calls Category Methods Description - + Creation @@ -228,7 +228,7 @@ Here's a summary of some of the other standard methods that the framework calls Called after a view and all of its children has been inflated from XML. - + Layout {@link android.view.View#onMeasure} @@ -247,14 +247,14 @@ Here's a summary of some of the other standard methods that the framework calls Called when the size of this view has changed. - + Drawing {@link android.view.View#onDraw} Called when the view should render its content. - + Event processing {@link android.view.View#onKeyDown} @@ -265,58 +265,58 @@ Here's a summary of some of the other standard methods that the framework calls {@link android.view.View#onKeyUp} Called when a key up event occurs. - + {@link android.view.View#onTrackballEvent} Called when a trackball motion event occurs. - + {@link android.view.View#onTouchEvent} Called when a touch screen motion event occurs. - - + + Focus {@link android.view.View#onFocusChanged} Called when the view gains or loses focus. - + {@link android.view.View#onWindowFocusChanged} Called when the window containing the view gains or loses focus. - + Attaching {@link android.view.View#onAttachedToWindow()} Called when the view is attached to a window. - + {@link android.view.View#onDetachedFromWindow} Called when the view is detached from its window. - - + + {@link android.view.View#onWindowVisibilityChanged} Called when the visibility of the window containing the view has changed. - + - +

        A Custom View Example

        -

        The CustomView sample in the +

        The CustomView sample in the API Demos provides an example of a customized View. The custom View is defined in the LabelView @@ -359,9 +359,9 @@ combination of a single line EditText field and an adjacent button with an attac something from the list, it populates the EditText field, but the user can also type something directly into the EditText if they prefer.

        In Android, there are actually two other Views readily available to do -this: {@link android.widget.Spinner Spinner} and -{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, but -regardless, the concept of a Combo Box makes an easy-to-understand +this: {@link android.widget.Spinner Spinner} and +{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, but +regardless, the concept of a Combo Box makes an easy-to-understand example.

        To create a compound component:

          @@ -397,7 +397,7 @@ example.

        1. In the case of extending a Layout, you don't need to override the onDraw() and onMeasure() methods since the - layout will have default behavior that will likely work just fine. However, + layout will have default behavior that will likely work just fine. However, you can still override them if you need to.
        2. @@ -409,7 +409,7 @@ example.

          To summarize, the use of a Layout as the basis for a Custom Control has a number of advantages, including:

          - +
        - +

        See also

        1. Dialogs design guide
        2. @@ -238,8 +238,8 @@ AlertDialog dialog = builder.create();

    The set...Button() methods require a title for the button (supplied -by a string resource) and a -{@link android.content.DialogInterface.OnClickListener} that defines the action to take +by a string resource) and a +{@link android.content.DialogInterface.OnClickListener} that defines the action to take when the user presses the button.

    There are three different action buttons you can add:

    @@ -251,7 +251,7 @@ when the user presses the button.

    Neutral
    You should use this when the user may not want to proceed with the action, but doesn't necessarily want to cancel. It appears between the positive and negative - buttons. For example, the action might be "Remind me later."
    + buttons. For example, the action might be "Remind me later."

    You can add only one of each button type to an {@link @@ -274,7 +274,7 @@ A dialog with a title and list.

  • A persistent multiple-choice list (checkboxes)
  • -

    To create a single-choice list like the one in figure 3, +

    To create a single-choice list like the one in figure 3, use the {@link android.app.AlertDialog.Builder#setItems setItems()} method:

    @@ -294,7 +294,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
     
     

    Because the list appears in the dialog's content area, the dialog cannot show both a message and a list and you should set a title for the -dialog with {@link android.app.AlertDialog.Builder#setTitle setTitle()}. +dialog with {@link android.app.AlertDialog.Builder#setTitle setTitle()}. To specify the items for the list, call {@link android.app.AlertDialog.Builder#setItems setItems()}, passing an array. Alternatively, you can specify a list using {@link @@ -320,11 +320,11 @@ A list of multiple-choice items.

    Adding a persistent multiple-choice or single-choice list

    -

    To add a list of multiple-choice items (checkboxes) or +

    To add a list of multiple-choice items (checkboxes) or single-choice items (radio buttons), use the {@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String, -DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} or -{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} or +{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} methods, respectively.

    For example, here's how you can create a multiple-choice list like the @@ -349,7 +349,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // 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 + // Else, if the item is already in the array, remove it mSelectedItems.remove(Integer.valueOf(which)); } } @@ -376,7 +376,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {

    Although both a traditional list and a list with radio buttons provide a "single choice" action, you should use {@link -android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) +android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener) setSingleChoiceItems()} if you want to persist the user's choice. That is, if opening the dialog again later should indicate what the user's current choice is, then you create a list with radio buttons.

    @@ -445,7 +445,7 @@ you should change its font family to {@code "sans-serif"} so that both text fiel a matching font style.

    To inflate the layout in your {@link android.support.v4.app.DialogFragment}, -get a {@link android.view.LayoutInflater} with +get a {@link android.view.LayoutInflater} with {@link android.app.Activity#getLayoutInflater()} and call {@link android.view.LayoutInflater#inflate inflate()}, where the first parameter is the layout resource ID and the second parameter is a parent view for the layout. @@ -473,7 +473,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { public void onClick(DialogInterface dialog, int id) { LoginDialogFragment.this.getDialog().cancel(); } - }); + }); return builder.create(); }

    @@ -508,7 +508,7 @@ interface through which it delivers the events back to the host activity:

     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. */
    @@ -516,10 +516,10 @@ public class NoticeDialogFragment extends DialogFragment {
             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
         @Override
         public void onAttach(Activity activity) {
    @@ -546,7 +546,7 @@ events through an implementation of the {@code NoticeDialogListener} interface:<
     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();
    @@ -659,7 +659,7 @@ public class CustomDialogFragment extends DialogFragment {
             // 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. */
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
    @@ -681,7 +681,7 @@ or a fullscreen UI, based on the screen size:

    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"); @@ -781,7 +781,7 @@ android.support.v4.app.DialogFragment#onDismiss onDismiss()} method in your {@li android.support.v4.app.DialogFragment}.

    You can also cancel a dialog. This is a special event that indicates the user -explicitly left the dialog without completing the task. This occurs if the user presses the +explicitly left the dialog without completing the task. This occurs if the user presses the Back button, touches the screen outside the dialog area, or if you explicitly call {@link android.app.Dialog#cancel()} on the {@link android.app.Dialog} (such as in response to a "Cancel" button in the dialog).

    diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd index 4eb54f2325682cf56c1d02d4ccf419bb12169cb3..8e4297f8ce1b738950e58b18bb141965ffd287e5 100644 --- a/docs/html/guide/topics/ui/drag-drop.jd +++ b/docs/html/guide/topics/ui/drag-drop.jd @@ -152,7 +152,7 @@ DraggableDot.java in
    The user releases the drag shadow within the bounding box of a View that can accept the - data. The system sends the View object's listener a drag event with action type + data, but not within its descendant view that can accept the data. The system sends the View + object's listener a drag event with action type {@link android.view.DragEvent#ACTION_DROP}. The drag event contains the data that was passed to the system in the call to {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()} @@ -317,6 +318,10 @@ DraggableDot.java in A View object's drag event listener receives this event action type when the drag shadow has just entered the bounding box of the View. This is the first event action type the - listener receives when the drag shadow enters the bounding box. If the listener wants to - continue receiving drag events for this operation, it must return boolean - true to the system. + listener receives when the drag shadow enters the bounding box. @@ -334,7 +337,8 @@ DraggableDot.java in @@ -395,7 +400,7 @@ DraggableDot.java in X X X -   + X     @@ -711,8 +716,7 @@ imageView.setOnLongClickListener(new View.OnLongClickListener() { If the listener can accept a drop, it should return true. This tells the system to continue to send drag events to the listener. If it can't accept a drop, it should return false, and the system - will stop sending drag events until it sends out - {@link android.view.DragEvent#ACTION_DRAG_ENDED}. + will stop sending drag events for the current drag operation.

    @@ -754,7 +758,8 @@ imageView.setOnLongClickListener(new View.OnLongClickListener() {

  • {@link android.view.DragEvent#ACTION_DRAG_EXITED}: This event is sent to a listener that previously received {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, after - the drag shadow is no longer within the bounding box of the listener's View. + the drag shadow is no longer within the bounding box of the listener's View or it's within + the bounding box of a descendant view that can accept the data.
  • @@ -978,7 +983,7 @@ protected class myDragEventListener implements View.OnDragListener { Log.e("DragDrop Example","Unknown action type received by OnDragListener."); break; } - + return false; } }; diff --git a/docs/html/guide/topics/ui/how-android-draws.jd b/docs/html/guide/topics/ui/how-android-draws.jd index 168f77b265cfaa7512d9fd3c448bf215770965a8..79563692d493b0d8398f508908be710773838642 100644 --- a/docs/html/guide/topics/ui/how-android-draws.jd +++ b/docs/html/guide/topics/ui/how-android-draws.jd @@ -4,18 +4,18 @@ parent.link=index.html @jd:body -

    When an {@link android.app.Activity} receives focus, it will be requested to +

    When an {@link android.app.Activity} receives focus, it will be requested to draw its layout. -The Android framework will handle the procedure for drawing, but the +The Android framework will handle the procedure for drawing, but the {@link android.app.Activity} must provide the root node of its layout hierarchy.

    -

    Drawing begins with the root node of the layout. It is requested to measure and -draw the layout tree. Drawing is handled by walking the tree and rendering each -{@link android.view.View} that intersects the invalid region. In turn, each +

    Drawing begins with the root node of the layout. It is requested to measure and +draw the layout tree. Drawing is handled by walking the tree and rendering each +{@link android.view.View} that intersects the invalid region. In turn, each {@link android.view.ViewGroup} is responsible for requesting -each of its children to be drawn -(with the {@link android.view.View#draw(Canvas) draw()} method) +each of its children to be drawn +(with the {@link android.view.View#draw(Canvas) draw()} method) and each {@link android.view.View} is responsible for drawing itself. Because the tree is traversed in-order, this means that parents will be drawn before (i.e., behind) their children, with @@ -24,55 +24,55 @@ and each {@link android.view.View} is responsible for drawing itself.

    - Drawing the layout is a two pass process: a measure pass and a layout pass. -The measuring pass is implemented in {@link android.view.View#measure(int, int)} -and is a top-down traversal of the {@link android.view.View} tree. Each {@link android.view.View} + Drawing the layout is a two pass process: a measure pass and a layout pass. +The measuring pass is implemented in {@link android.view.View#measure(int, int)} +and is a top-down traversal of the {@link android.view.View} tree. Each {@link android.view.View} pushes dimension specifications down the tree - during the recursion. At the end of the measure pass, every + during the recursion. At the end of the measure pass, every {@link android.view.View} has stored its measurements. The second pass happens in {@link android.view.View#layout(int,int,int,int)} and is also top-down. During this pass each parent is responsible for positioning all of its children using the sizes computed in the measure pass.

    - +

    - When a {@link android.view.View} object's -{@link android.view.View#measure(int, int) measure()} method + When a {@link android.view.View} object's +{@link android.view.View#measure(int, int) measure()} method returns, its {@link android.view.View#getMeasuredWidth()} and - {@link android.view.View#getMeasuredHeight()} values must be set, along - with those for all of that {@link android.view.View} object's descendants. -A {@link android.view.View} object's measured width and -measured height values must respect the constraints imposed by the + {@link android.view.View#getMeasuredHeight()} values must be set, along + with those for all of that {@link android.view.View} object's descendants. +A {@link android.view.View} object's measured width and +measured height values must respect the constraints imposed by the {@link android.view.View} object's parents. This guarantees that at the end of the measure pass, all parents accept all of their - children's measurements. A parent {@link android.view.View} may call + children's measurements. A parent {@link android.view.View} may call {@link android.view.View#measure(int, int) measure()} more than once on its children. For example, the parent may measure each child once with unspecified dimensions to find out how big they want to be, then call - {@link android.view.View#measure(int, int) measure()} on them again with + {@link android.view.View#measure(int, int) measure()} on them again with actual numbers if the sum of all the children's - unconstrained sizes is too big or too small (that is, if the children + unconstrained sizes is too big or too small (that is, if the children don't agree among themselves - as to how much space they each get, the parent will intervene and set + as to how much space they each get, the parent will intervene and set the rules on the second pass).

    - +
    diff --git a/docs/html/guide/topics/ui/layout/grid.jd b/docs/html/guide/topics/ui/layout/grid.jd index 3474f48c9d86469aee49b989d17732be5476736d..cc536517ea09c4323b0b729d55ec807e436ee637 100644 --- a/docs/html/guide/topics/ui/layout/grid.jd +++ b/docs/html/guide/topics/ui/layout/grid.jd @@ -23,17 +23,32 @@ displays child {@link android.view.View} elements in rows and columns.

    -

    {@link android.widget.TableLayout} positions its children into rows - and columns. TableLayout containers do not display border lines for their rows, columns, - or cells. The table will have as many columns as the row with the most cells. A table can leave -cells empty, but cells cannot span columns, as they can in HTML.

    -

    {@link android.widget.TableRow} objects are the child views of a TableLayout -(each TableRow defines a single row in the table). -Each row has zero or more cells, each of which is defined by any kind of other View. So, the cells of a row may be -composed of a variety of View objects, like ImageView or TextView objects. -A cell may also be a ViewGroup object (for example, you can nest another TableLayout as a cell).

    -

    The following sample layout has two rows and two cells in each. The accompanying screenshot shows the -result, with cell borders displayed as dotted lines (added for visual effect).

    +

    + {@link android.widget.TableLayout} positions its children into rows and + columns. TableLayout containers do not display border lines for their rows, + columns, or cells. The table will have as many columns as the row with the + most cells. A table can leave cells empty. Cells can span multiple columns, + as they can in HTML. You can span columns by using the span + field in the {@link android.widget.TableRow.LayoutParams} class. +

    + +

    + Note: Cells cannot span multiple rows. +

    + +

    + {@link android.widget.TableRow} objects are the child views of a TableLayout + (each TableRow defines a single row in the table). Each row has zero or more + cells, each of which is defined by any kind of other View. So, the cells of + a row may be composed of a variety of View objects, like ImageView or + TextView objects. A cell may also be a ViewGroup object (for example, you + can nest another TableLayout as a cell). +

    +

    + The following sample layout has two rows and two cells in each. The + accompanying screenshot shows the result, with cell borders displayed as + dotted lines (added for visual effect). +

    @@ -71,7 +86,7 @@ result, with cell borders displayed as dotted lines (added for visual effect). <

    Columns can be hidden, marked to stretch and fill the available screen space, or can be marked as shrinkable to force the column to shrink until the table - fits the screen. See the {@link android.widget.TableLayout TableLayout reference} + fits the screen. See the {@link android.widget.TableLayout TableLayout reference} documentation for more details.

    diff --git a/docs/html/guide/topics/ui/layout/linear.jd b/docs/html/guide/topics/ui/layout/linear.jd index 7441782f5e6fdb1872a4a3b1fcd30b4e1d1090a4..4224d17d07a70ba79aec6484e67c5dd1964fb700 100644 --- a/docs/html/guide/topics/ui/layout/linear.jd +++ b/docs/html/guide/topics/ui/layout/linear.jd @@ -59,7 +59,7 @@ href="{@docRoot}reference/android/widget/LinearLayout.LayoutParams.html#attr_and >{@code android:layout_weight} attribute. This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger weight value allows it to expand -to fill any remaining space in the parent view. +to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero.

    diff --git a/docs/html/guide/topics/ui/layout/listview.jd b/docs/html/guide/topics/ui/layout/listview.jd index 3c6e32ca41cfe002920e09d2c24dbeda72389545..e6e5578e6fd88fd3be137576be96a50d6ca05e6b 100644 --- a/docs/html/guide/topics/ui/layout/listview.jd +++ b/docs/html/guide/topics/ui/layout/listview.jd @@ -80,7 +80,7 @@ public class ListViewLoader extends ListActivity ContactsContract.Data.DISPLAY_NAME}; // This is the select criteria - static final String SELECTION = "((" + + static final String SELECTION = "((" + ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.Data.DISPLAY_NAME + " != '' ))"; @@ -105,7 +105,7 @@ public class ListViewLoader extends ListActivity // Create an empty adapter we will use to display the loaded data. // We pass null for the cursor, then update it in onLoadFinished() - mAdapter = new SimpleCursorAdapter(this, + mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, fromColumns, toViews, 0); setListAdapter(mAdapter); @@ -138,7 +138,7 @@ public class ListViewLoader extends ListActivity mAdapter.swapCursor(null); } - @Override + @Override public void onListItemClick(ListView l, View v, int position, long id) { // Do something when a list item is clicked } diff --git a/docs/html/guide/topics/ui/layout/relative.jd b/docs/html/guide/topics/ui/layout/relative.jd index ca5cb4838036813bde2aff6d8a233225a0c338a1..92735ae808bf150b136a38cf640d98a2b718f4b1 100644 --- a/docs/html/guide/topics/ui/layout/relative.jd +++ b/docs/html/guide/topics/ui/layout/relative.jd @@ -38,7 +38,7 @@ make one below another, centered in the screen, centered left, and so on. By def views are drawn at the top-left of the layout, so you must define the position of each view using the various layout properties available from {@link android.widget.RelativeLayout.LayoutParams}.

    - +

    Some of the many layout properties available to views in a {@link android.widget.RelativeLayout} include:

    diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd index ad2aa9b8bf290b1659bea0baaaff2dd4f1a00170..3325c0e8b1206353e0c75e24cb35941814ce5609 100644 --- a/docs/html/guide/topics/ui/menus.jd +++ b/docs/html/guide/topics/ui/menus.jd @@ -77,9 +77,9 @@ activity. It's where you should place actions that have a global impact on the a "Search," "Compose email," and "Settings."

    See the section about Creating an Options Menu.

    - +
    Context menu and contextual action mode
    - +
    A context menu is a floating menu that appears when the user performs a long-click on an element. It provides actions that affect the selected content or context frame. @@ -88,7 +88,7 @@ action items that affect the selected content in a bar at the top of the screen to select multiple items.

    See the section about Creating Contextual Menus.

    - +
    Popup menu
    A popup menu displays a list of items in a vertical list that's anchored to the view that invoked the menu. It's good for providing an overflow of actions that relate to specific content or @@ -130,9 +130,9 @@ directory and build the menu with the following elements:

    <item>
    Creates a {@link android.view.MenuItem}, which represents a single item in a menu. This element may contain a nested <menu> element in order to create a submenu.
    - +
    <group>
    -
    An optional, invisible container for {@code <item>} elements. It allows you to +
    An optional, invisible container for {@code } elements. It allows you to categorize menu items so they share properties such as active state and visibility. For more information, see the section about Creating Menu Groups.
    @@ -172,8 +172,8 @@ when the user selects it. For information about all the supported attributes, see the Menu Resource document.

    -

    You can add a submenu to an item in any menu (except a submenu) by adding a {@code <menu>} -element as the child of an {@code <item>}. Submenus are useful when your application has a lot +

    You can add a submenu to an item in any menu (except a submenu) by adding a {@code

    } +element as the child of an {@code }. Submenus are useful when your application has a lot of functions that can be organized into topics, like items in a PC application's menu bar (File, Edit, View, etc.). For example:

    @@ -224,13 +224,13 @@ the sixth item and the rest into the overflow menu, which the user can open by s More.
  • If you've developed your application for Android 3.0 (API level 11) and -higher, items from the options menu are available in the +higher, items from the options menu are available in the app bar. By default, the system places all items in the action overflow, which the user can reveal with the action overflow icon on the right side of the app bar (or by pressing the device Menu button, if available). To enable quick access to important actions, you can promote a few items to appear in the app bar by adding -{@code android:showAsAction="ifRoom"} to the corresponding {@code <item>} elements (see figure +{@code android:showAsAction="ifRoom"} to the corresponding {@code } elements (see figure 2).

    For more information about action items and other app bar behaviors, see the Adding the App Bar training class.

  • @@ -246,7 +246,7 @@ subclass or a {@link android.app.Fragment} subclass. If both your activity and f declare items for the options menu, they are combined in the UI. The activity's items appear first, followed by those of each fragment in the order in which each fragment is added to the activity. If necessary, you can re-order the menu items with the {@code android:orderInCategory} -attribute in each {@code <item>} you need to move.

    +attribute in each {@code } you need to move.

    To specify the options menu for an activity, override {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} (fragments provide their @@ -343,7 +343,7 @@ again unless the menu is invalidated for some reason. However, you should use {@ android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} only to create the initial menu state and not to make changes during the activity lifecycle.

    -

    If you want to modify the options menu based on +

    If you want to modify the options menu based on events that occur during the activity lifecycle, you can do so in the {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()} method. This method passes you the {@link android.view.Menu} object as it currently exists so you can modify it, @@ -360,7 +360,7 @@ presented in the app bar. When an event occurs and you want to perform a menu up call {@link android.app.Activity#invalidateOptionsMenu invalidateOptionsMenu()} to request that the system call {@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()}.

    -

    Note: +

    Note: You should never change items in the options menu based on the {@link android.view.View} currently in focus. When in touch mode (when the user is not using a trackball or d-pad), views cannot take focus, so you should never use focus as the basis for modifying @@ -738,8 +738,8 @@ that shows a popup menu:

     <ImageButton
    -    android:layout_width="wrap_content" 
    -    android:layout_height="wrap_content" 
    +    android:layout_width="wrap_content"
    +    android:layout_height="wrap_content"
         android:src="@drawable/ic_overflow_holo_dark"
         android:contentDescription="@string/descr_overflow_button"
         android:onClick="showPopup" />
    @@ -814,7 +814,7 @@ setGroupEnabled()}
     android.view.Menu#setGroupCheckable(int,boolean,boolean) setGroupCheckable()}
     
     
    -

    You can create a group by nesting {@code <item>} elements inside a {@code <group>} +

    You can create a group by nesting {@code } elements inside a {@code } element in your menu resource or by specifying a group ID with the {@link android.view.Menu#add(int,int,int,int) add()} method.

    @@ -863,8 +863,8 @@ you must manually indicate the checked state by swapping the icon and/or text each time the state changes.

    You can define the checkable behavior for individual menu items using the {@code -android:checkable} attribute in the {@code <item>} element, or for an entire group with -the {@code android:checkableBehavior} attribute in the {@code <group>} element. For +android:checkable} attribute in the {@code } element, or for an entire group with +the {@code android:checkableBehavior} attribute in the {@code } element. For example, all items in this menu group are checkable with a radio button:

    @@ -890,7 +890,7 @@ example, all items in this menu group are checkable with a radio button:

    You can apply a default checked state to an item using the {@code android:checked} attribute in -the {@code <item>} element and change it in code with the {@link +the {@code } element and change it in code with the {@link android.view.MenuItem#setChecked(boolean) setChecked()} method.

    When a checkable item is selected, the system calls your respective item-selected callback method @@ -1023,6 +1023,6 @@ category. For example:

    Read more about writing intent filters in the Intents and Intent Filters document.

    -

    For a sample application using this technique, see the +

    For a sample application using this technique, see the Note Pad sample code.

    diff --git a/docs/html/preview/features/multi-window.jd b/docs/html/guide/topics/ui/multi-window.jd similarity index 77% rename from docs/html/preview/features/multi-window.jd rename to docs/html/guide/topics/ui/multi-window.jd index ca5bd0da292ecfed59283d1c7b370d22a991492f..bab582dd0b8c3c1d0b496e12c74b868091429a4d 100644 --- a/docs/html/preview/features/multi-window.jd +++ b/docs/html/guide/topics/ui/multi-window.jd @@ -17,6 +17,8 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

    See Also

      +
    1. Adding + Picture-in-Picture
    2. Multi-Window Playground sample app
    3. @@ -28,7 +30,7 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      - Android N adds support for displaying more than one app at the + Android 7.0 adds support for displaying more than one app at the same time. On handheld devices, two apps can run side-by-side or one-above-the-other in split-screen mode. On TV devices, apps can use picture-in-picture mode to continue video playback while users @@ -36,7 +38,7 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      - If you build your app with the N Preview SDK, you can configure how your app + If your app targets Android 7.0 (API level 24) or higher, you can configure how your app handles multi-window display. For example, you can specify your activity's minimum allowable dimensions. You can also disable multi-window display for your app, ensuring that the system only shows your app in full-screen @@ -46,20 +48,20 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      Overview

      - Android N allows several apps to share the screen at once. For + Android 7.0 allows several apps to share the screen at once. For example, a user could split the screen, viewing a web page on the left side while composing an email on the right side. The user experience depends on the device:

        -
      • Handheld devices running Android N offer split-screen +
      • Handheld devices running Android 7.0 offer split-screen mode. In this mode, the system fills the screen with two apps, showing them either side-by-side or one-above-the-other. The user can drag the dividing line separating the two to make one app larger and the other smaller.
      • -
      • On Nexus Player running Android N, apps can put themselves +
      • On TV devices, apps can put themselves in picture-in-picture mode, allowing them to continue showing content while the user browses or interacts with other apps. @@ -72,9 +74,9 @@ page.keywords="multi-window", "android N", "split screen", "free-form"
      -

      Figure 1. Two apps running side-by-side in split-screen mode. @@ -100,9 +102,7 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      Users can drag and drop data from one activity to another while the activities are sharing - the screen. (Previously, users could only drag and drop data within a single - activity.) -

      + the screen.

      Multi-Window Lifecycle

      @@ -163,18 +163,18 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      Configuring Your App for Multi-Window Mode

      - If your app targets Android N, you can configure how and + If your app targets API level 24 or higher, you can configure how and whether your app's activities support multi-window display. You can set attributes in your manifest to control both size and layout. A root activity's attribute settings apply to all activities within its task stack. For example, if the root activity has android:resizeableActivity set to true, then all activities - in the task stack are resizeable. + in the task stack are resizable.

      - Note: If you build a multi-orientation app with a version of the - SDK lower than Android N, and the user uses the app in + Note: If you build a multi-orientation app that targets API + level 23 or lower, and the user uses the app in multi-window mode, the system forcibly resizes the app. The system presents a dialog box warning the user that the app may behave unexpectedly. The system does not resize fixed-orientation apps; if @@ -183,10 +183,13 @@ page.keywords="multi-window", "android N", "split screen", "free-form"

      android:resizeableActivity

      +

      - Set this attribute in your manifest's <activity> or - <application> node to enable or disable multi-window - display: + Set this attribute in your manifest's <activity> + or <application> + element to enable or disable multi-window display:

      @@ -202,16 +205,19 @@ android:resizeableActivity=["true" | "false"]
       

      - If your app targets Android N, but you do not specify a value + If your app targets API level 24, but you do not specify a value for this attribute, the attribute's value defaults to true.

      android:supportsPictureInPicture

      - Set this attribute in your manifest's <activity> node to - indicate whether the activity supports picture-in-picture display. This - attribute is ignored if android:resizeableActivity is false. + Set this attribute in your manifest's <activity> + node to indicate whether the activity supports Picture-in-Picture + display. This attribute is ignored if android:resizeableActivity + is false.

      @@ -221,7 +227,7 @@ android:supportsPictureInPicture=["true" | "false"]
       

      Layout attributes

      - With Android N, the <layout> manifest element + With Android 7.0, the <layout> manifest element supports several attributes that affect how an activity behaves in multi-window mode:

      @@ -283,8 +289,8 @@ android:supportsPictureInPicture=["true" | "false"]

      Running Your App in Multi-Window Mode

      - Android N offers new functionality to support apps that can run - in multi-window mode. + Beginning with Android 7.0, the system offers functionality to support apps + that can run in multi-window mode.

      Disabled features in multi-window mode

      @@ -309,15 +315,13 @@ android:supportsPictureInPicture=["true" | "false"]

      Multi-window change notification and querying

      - The following new methods have been added to the {@link android.app.Activity} - class to support multi-window display. For details on each method, see the - N Preview SDK - Reference. + {@link android.app.Activity} offers the following methods to support + multi-window display.

      - Activity.isInMultiWindowMode() + {@link android.app.Activity#isInMultiWindowMode isInMultiWindowMode()}
      @@ -325,12 +329,14 @@ android:supportsPictureInPicture=["true" | "false"]
      - Activity.isInPictureInPictureMode() + {@link android.app.Activity#isInPictureInPictureMode + isInPictureInPictureMode()}
      - Call to find out if the activity is in picture-in-picture mode. - + Call to find out if the activity is in picture-in-picture + mode.

      Note: Picture-in-picture mode is a special case of multi-window mode. If myActivity.isInPictureInPictureMode() @@ -340,7 +346,8 @@ android:supportsPictureInPicture=["true" | "false"]

      - Activity.onMultiWindowModeChanged() + {@link android.app.Activity#onMultiWindowModeChanged + onMultiWindowModeChanged()}
      @@ -351,7 +358,8 @@ android:supportsPictureInPicture=["true" | "false"]
      - Activity.onPictureInPictureModeChanged() + {@link android.app.Activity#onPictureInPictureModeChanged + onPictureInPictureModeChanged()}
      @@ -363,17 +371,21 @@ android:supportsPictureInPicture=["true" | "false"]

      - There are also {@link android.app.Fragment} versions of each of these - methods, for example Fragment.isInMultiWindowMode(). + The {@link android.app.Fragment} class exposes versions of many of these + methods, for example {@link android.app.Fragment#onMultiWindowModeChanged + Fragment.onMultiWindowModeChanged()}.

      Entering picture-in-picture mode

      - To put an activity in picture-in-picture mode, call the new method - Activity.enterPictureInPictureMode(). This method has no effect if - the device does not support picture-in-picture mode. For more information, - see the Picture-in-Picture documentation. + To put an activity in picture-in-picture mode, call {@link + android.app.Activity#enterPictureInPictureMode + Activity.enterPictureInPictureMode()}. This method has no effect if the + device does not support picture-in-picture mode. For more information, see + the Picture-in-Picture + documentation.

      Launch New Activities in Multi-Window Mode

      @@ -381,8 +393,8 @@ android:supportsPictureInPicture=["true" | "false"]

      When you launch a new activity, you can hint to the system that the new activity should be displayed adjacent to the current one, if possible. To do - this, use the flag - Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT. Passing + this, use the intent flag + {@link android.content.Intent#FLAG_ACTIVITY_LAUNCH_ADJACENT}. Passing this flag requests the following behavior:

      @@ -400,7 +412,8 @@ android:supportsPictureInPicture=["true" | "false"]

      If a device is in freeform mode and you are launching a new activity, you can specify the new activity's dimensions and screen location by calling - ActivityOptions.setLaunchBounds(). This method has no effect if + {@link android.app.ActivityOptions#setLaunchBounds + ActivityOptions.setLaunchBounds()}. This method has no effect if the device is not in multi-window mode.

      @@ -416,22 +429,15 @@ android:supportsPictureInPicture=["true" | "false"]

      Users can drag and drop data from one activity to another while the two activities are - sharing the screen. (Previously, users could only drag and drop data within a - single activity.) For this reason, you may want to add drag and drop + sharing the screen. (Prior to Android 7.0, users could only drag and drop data + within a single activity.) For this reason, you may want to add drag and drop functionality to your app if your app does not currently support it.

      -

      - The N Preview SDK extends the android.view - package to support cross-app drag and drop. For details on the following - classes and methods, see the N - Preview SDK Reference. -

      - android.view.DropPermissions + {@link android.view.DragAndDropPermissions}
      @@ -440,20 +446,20 @@ android:supportsPictureInPicture=["true" | "false"]
      - View.startDragAndDrop() + {@link android.view.View#startDragAndDrop View.startDragAndDrop()}
      - New alias for {@link android.view.View#startDrag View.startDrag()}. To - enable cross-activity drag and drop, pass the new flag - View.DRAG_FLAG_GLOBAL. If you need to give URI permissions to - the recipient activity, pass the new flags - View.DRAG_FLAG_GLOBAL_URI_READ or - View.DRAG_FLAG_GLOBAL_URI_WRITE, as appropriate. + Alias for {@link android.view.View#startDrag View.startDrag()}. To enable + cross-activity drag and drop, pass the flag {@link + android.view.View#DRAG_FLAG_GLOBAL}. If you need to give URI permissions to + the recipient activity, pass the flags {@link + android.view.View#DRAG_FLAG_GLOBAL_URI_READ} or {@link + android.view.View#DRAG_FLAG_GLOBAL_URI_WRITE}, as appropriate.
      - View.cancelDragAndDrop() + {@link android.view.View#cancelDragAndDrop View.cancelDragAndDrop()}
      @@ -462,7 +468,7 @@ android:supportsPictureInPicture=["true" | "false"]
      - View.updateDragShadow() + {@link android.view.View#updateDragShadow View.updateDragShadow()}
      @@ -471,7 +477,8 @@ android:supportsPictureInPicture=["true" | "false"]
      - Activity.requestDragAndDropPermissions() + {@link android.app.Activity#requestDragAndDropPermissions + Activity.requestDragAndDropPermissions()}
      @@ -483,29 +490,29 @@ android:supportsPictureInPicture=["true" | "false"]

      Testing Your App's Multi-Window Support

      - Whether or not you update your app for Android N, you should + Whether or not your app targets API level 24 or higher, you should verify how it behaves in multi-window mode in case a user tries to launch it - in multiwindow mode on a device running Android N. + in multi-window mode on a device running Android 7.0 or higher.

      Configuring a Test Device

      - If you install Android N on a device, split-screen mode is - automatically supported. + If a device runs Android 7.0 or higher, it automatically supports split-screen + mode.

      -

      If your app was not built with the N Preview SDK

      +

      If your app targets API level 23 or lower

      - If you did not build your app with the N Preview SDK and the user attempts to use - the app in multi-window mode, the system forcibly resizes the app unless the app - declares a fixed orientation. + If your app targets API level 23 or lower and the user attempts to use + the app in multi-window mode, the system forcibly resizes the app unless the + app declares a fixed orientation.

      If your app does not declare a fixed orientation, you should launch your app - on a device running Android N and attempt to put the app in + on a device running Android 7.0 or higher and attempt to put the app in split-screen mode. Verify that the user experience is acceptable when the app is forcibly resized.

      @@ -519,7 +526,7 @@ android:supportsPictureInPicture=["true" | "false"]

      If you support multi-window mode

      - If you built your app with the N Preview SDK and have not disabled + If your app targets API level 24 or higher and does not disable multi-window support, verify the following behavior under both split-screen and freeform modes.

      @@ -592,8 +599,8 @@ android:supportsPictureInPicture=["true" | "false"]

      If you disabled multi-window support by setting - android:resizableActivity="false", you should launch your app on - a device running Android N and attempt to put the app in + android:resizeableActivity="false", you should launch your app on + a device running Android 7.0 or higher and attempt to put the app in freeform and split-screen modes. Verify that when you do so, the app remains in full-screen mode.

      diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd index 6cd63f384a425c2cba1ae399dda71b2f59787805..373d0a173c9135b6c3ba53f1f4dbacec59eee650 100644 --- a/docs/html/guide/topics/ui/notifiers/notifications.jd +++ b/docs/html/guide/topics/ui/notifiers/notifications.jd @@ -1,4 +1,6 @@ page.title=Notifications +page.image=images/android-7.0/notifications-card.png +page.tags="notifications", "alerts" @jd:body

    Key classes

    @@ -60,7 +70,7 @@ page.title=Notifications

    See also

    1. - Android Design: Notifications + Material Design: Notifications
    @@ -97,7 +107,7 @@ The class {@link android.app.Notification.Builder Notification.Builder} was adde The material design changes introduced in Android 5.0 (API level 21) are of particular importance, and you should review the Material Design training for more information. To learn how to design notifications and their interactions, -read the Notifications design guide.

    +read the Notifications design guide.

    Creating a Notification

    @@ -184,7 +194,7 @@ notification, you pass the {@link android.app.Notification} object to the system

    For information about setting an appropriate priority level, see "Correctly set and manage notification priority" in the Notifications Design + href="https://material.google.com/patterns/notifications.html">Notifications Design guide.

    @@ -323,7 +333,7 @@ mBuilder.setStyle(inBoxStyle); For example, Gmail notifies the user that new emails have arrived by increasing its count of unread messages and by adding a summary of each email to the notification. This is called "stacking" the notification; it's described in more detail in the - Notifications Design guide. + Notifications Design guide.

    Note: This Gmail feature requires the "inbox" expanded layout, which is part @@ -394,6 +404,305 @@ numMessages = 0; all of the notifications you previously issued. + + +

    Replying to notifications

    + +

    + Starting in Android 7.0 (API level 24), + users can respond directly to text messages or update task lists + from within the notification + dialog. On a handheld, the inline reply action appears as an additional + button + displayed in the notification. When a user replies via keyboard, the system + attaches the text response to the intent + you had specified for the notification action and sends the intent to your + handheld app. +

    + + +

    + Figure 1. The Reply action button. +

    + +

    Adding inline reply actions

    + +

    To create a notification action that supports direct reply: +

    + +
      +
    1. Create an instance of {@link android.support.v4.app.RemoteInput.Builder} + that you can add to your notification +action. This class's constructor accepts a string that the system uses as the key + for the text input. Later, your handheld app uses that key to retrieve the text + of the input. + +
      +// Key for the string that's delivered in the action's intent.
      +private static final String KEY_TEXT_REPLY = "key_text_reply";
      +String replyLabel = getResources().getString(R.string.reply_label);
      +RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
      +        .setLabel(replyLabel)
      +        .build();
      +
      +
    2. +
    3. Attach the {@link android.support.v4.app.RemoteInput} + object to an action using addRemoteInput(). + +
      +// Create the reply action and add the remote input.
      +Notification.Action action =
      +        new Notification.Action.Builder(R.drawable.ic_reply_icon,
      +                getString(R.string.label), replyPendingIntent)
      +                .addRemoteInput(remoteInput)
      +                .build();
      +
      +
    4. + +
    5. Apply the action to a notification and issue the notification. + +
      +// Build the notification and add the action.
      +Notification newMessageNotification =
      +        new Notification.Builder(mContext)
      +                .setSmallIcon(R.drawable.ic_message)
      +                .setContentTitle(getString(R.string.title))
      +                .setContentText(getString(R.string.content))
      +                .addAction(action))
      +                .build();
      +
      +// Issue the notification.
      +NotificationManager notificationManager =
      +        NotificationManager.from(mContext);
      +notificationManager.notify(notificationId, newMessageNotification);
      +
      +
      +
    6. + +
    + + +

    The system prompts the user to input a response when they trigger the +notification action.

    + + +

    + Figure 2. The user inputs text from the notification shade. +

    + +

    + Retrieving user input from the inline reply +

    + +

    + To receive user input from the notification interface to the activity you + declared in the reply action's intent: +

    + +
      +
    1. Call {@link android.support.v4.app.RemoteInput#getResultsFromIntent + getResultsFromIntent()} by passing the notification action’s intent as the + input parameter. This method returns a {@link android.os.Bundle} that + contains the text response. + +
      +Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
      +
      +
    2. + +
    3. Query the bundle using the result key (provided to the {@link + android.support.v4.app.RemoteInput.Builder} constructor). You can complete + this process and retrieve the input text by creating a method, as in the + following code snippet: + +
      +// Obtain the intent that started this activity by calling
      +// Activity.getIntent() and pass it into this method to
      +// get the associated string.
      +
      +private CharSequence getMessageText(Intent intent) {
      +    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
      +    if (remoteInput != null) {
      +        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
      +    }
      +    return null;
      + }
      +
      +
    4. + +
    5. Build and issue another notification, using the same notification ID that + you provided for the previous notification. The progress indicator + disappears from the notification interface to inform users of a successful + reply. When working with this new notification, use the context that gets + passed to the receiver's {@code onReceive()} method. + +
      +// Build a new notification, which informs the user that the system
      +// handled their interaction with the previous notification.
      +Notification repliedNotification =
      +        new Notification.Builder(context)
      +                .setSmallIcon(R.drawable.ic_message)
      +                .setContentText(getString(R.string.replied))
      +                .build();
      +
      +// Issue the new notification.
      +NotificationManager notificationManager =
      +        NotificationManager.from(context);
      +notificationManager.notify(notificationId, repliedNotification);
      +
      +
    6. +
    + +

    + For interactive apps, such as chats, you can include additional + context when handling retrieved text. For example, these apps could show + multiple lines of chat history. When the user responds via {@link + android.support.v4.app.RemoteInput}, you can update the reply history + using the {@code setRemoteInputHistory()} method. +

    + +

    + The notification must be either updated or cancelled after the app has + received remote input. When the user replies to a remote update + using Direct Reply, + do not cancel the notification. Instead, update the notification + to display the user's reply. + For notifications using {@code MessagingStyle}, you should add + the reply as the latest message. When using other templates, you can + append the user's reply to the remote-input history. +

    + + + +

    Bundling notifications

    + +

    + Starting in Android 7.0 (API level 24), + Android provides developers with a new way to represent + a queue of notifications: bundled notifications. This is similar to the + Notification + Stacks feature in Android Wear. For example, if your app + creates notifications + for received messages, when more than one message is received, bundle the + notifications together as a single group. You can + use the {@link android.support.v4.app.NotificationCompat.Builder#setGroup + Builder.setGroup()} method to bundle similar notifications.

    + +

    + A notification group imposes a hierarchy on the notifications comprising it. + At the top of that hierarchy is a parent notification that displays summary + information for the group. The user can progressively + expand the notification group, and the system shows more information as the + user drills deeper. When the user expands the bundle, the system reveals more + information for all its child notifications; when the user + expands one of those notifications, the system reveals its entire content. +

    + + +

    + Figure 3. The user can progressively expand the notification + group. +

    + +

    + Note: If the same app sends four or more notifications + and does not specify a grouping, the + system automatically groups them together. +

    + +

    To learn how to add notifications to a group, see +Add +Each Notification to a Group.

    + + +

    Best practices for bundled notifications

    +

    This section provides guidelines about when to use notification groups instead +of the {@link android.app.Notification.InboxStyle InboxStyle} +notifications available in Android 6.0 and previous versions.

    + +

    When to use bundled notifications

    + +

    You should use notification groups only if all of the following conditions are +true for your use case:

    + +
      +
    • The child notifications are complete notifications and can be displayed + individually without the need for a group summary.
    • +
    • There is a benefit to surfacing the child notifications individually. For + example: +
    • +
        +
      • They are actionable, with actions specific to each child.
      • +
      • There is more information to the child that the user wants to read.
      • +
      +
    + +

    Examples of good use cases for notification groups include: a messaging app +displaying a list of incoming messages, or an email app displaying a list of +received emails.

    + +

    +Examples of cases where a single notification is preferable + include individual messages from a single person, or a list representation of + single-line text items. You can use +({@link android.app.Notification.InboxStyle InboxStyle} or +{@link android.app.Notification.BigTextStyle BigTextStyle}) to accomplish +this. +

    + +

    Displaying bundled notifications

    + +

    + The app should always post a group summary, even if the group contains just a + single child. The system will suppress the summary and directly display the + child notification if it only contains a single notification. This ensures + that the system can provide a consistent experience when the user swipes away + children of a group. +

    + +

    Peeking notifications

    + +

    While the system usually displays child notifications as a group, you can set + them to temporarily appear as + + heads-up notifications. This feature is especially useful because it allows + immediate access to the most recent child and the actions associated with it. +

    + + +

    Backwards compatibility

    + +

    + Both notification groups and remote input have been a part of the {@link + android.app.Notification} API since Android 5.0 (API level 21) to support + Android Wear devices. If you've already built notifications with these APIs, + the only action you must take is to verify that the app behavior corresponds + to the guidelines described above, and to consider implementing {@code + setRemoteInputHistory()}. +

    + +

    + In order to support backward compatibility, the same APIs are available with + the support library's {@link android.support.v4.app.NotificationCompat} + class, allowing you to build notifications that works on versions of Android + less than 5.0 (API level 21). + On handhelds and tablets, users only see the summary notification, + so an app should still have an inbox style or an equivalent notification + representative for the whole information content of the group. As Android + Wear devices allow users to see all child notifications even on older + platform levels, you should build child notifications regardless of API + level. +

    +

    Preserving Navigation when Starting an Activity

    @@ -886,35 +1195,38 @@ method.

    Controlling Media Playback on the Lock Screen

    -

    In Android 5.0 (API level 21) the lock screen no longer displays media controls -based on the {@link android.media.RemoteControlClient}, which is now deprecated. Instead, use the -{@link android.app.Notification.MediaStyle} template with the -{@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()} -method, which converts actions into clickable icons.

    - -

    Note: The template and the -{@link android.app.Notification.Builder#addAction(android.app.Notification.Action) addAction()} -method are not included in the support library, so these features run in Android 5.0 and higher -only.

    +

    + In Android 5.0 (API level 21) the lock screen no longer displays media + controls based on the {@link android.media.RemoteControlClient}, which is + now deprecated. Instead, use the {@link + android.support.v7.app.NotificationCompat.MediaStyle} template with the + {@link + android.support.v4.app.NotificationCompat.Builder#addAction(android.support.v4.app.NotificationCompat.Action) + addAction()} method, which converts actions into clickable icons. +

    -

    To display media playback controls on the lock screen in Android 5.0, set the visibility -to {@link android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, as described above. Then add -the actions and set the {@link android.app.Notification.MediaStyle} template, as described in the -following sample code:

    +

    + To display media playback controls on the lock screen in Android 5.0, set + the visibility to {@link + android.support.v4.app.NotificationCompat#VISIBILITY_PUBLIC}, as described + above. Then add the actions and set the {@link + android.support.v7.app.NotificationCompat.MediaStyle} template, as described + in the following sample code: +

    -Notification notification = new Notification.Builder(context)
    +Notification notification = new NotificationCompat.Builder(context)
         // Show controls on lock screen even when user hides sensitive content.
    -    .setVisibility(Notification.VISIBILITY_PUBLIC)
    +    .setVisibility(NotificationCompat.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())
    +    .setStyle(new NotificationCompat.MediaStyle()
    +        .setShowActionsInCompactView(1 /* #1: pause button */)
    +        .setMediaSession(mMediaSession.getSessionToken()))
         .setContentTitle("Wonderful music")
         .setContentText("My Awesome Band")
         .setLargeIcon(albumArtBitmap)
    @@ -984,3 +1296,69 @@ for more information about the new APIs for managing the media session and contr
         standard notification layout text. If you use the same style in applications that target Android
         2.3 or higher, you'll ensure that your text is visible against the display background.
     

    + + +

    Custom Views

    +

    + Starting from Android 7.0 (API level 24), + you can customize notification views and + still obtain system decorations like notification headers, actions, and + expandable layouts. +

    + +

    To enable this capability, Android provides the following APIs to style your + custom view:

    + +
    +
    +{@code DecoratedCustomViewStyle()}
    +
    Styles notifications other than media +notifications.
    +
    +{@code DecoratedMediaCustomViewStyle()}
    +
    Styles media notifications.
    +
    + +

    To use this API, call the {@code setStyle()} method, passing to it +the desired custom view style.

    + +

    This snippet shows how to construct a custom notification object with the +{@code DecoratedCustomViewStyle()} method.

    + +
    +Notification notification = new Notification.Builder()
    +           .setSmallIcon(R.drawable.ic_stat_player)
    +           .setLargeIcon(albumArtBitmap))
    +           .setCustomContentView(contentView);
    +           .setStyle(new Notification.DecoratedCustomViewStyle())
    +           .build();
    +
    +
    + + + +

    Messaging Style

    +

    + Starting in Android 7.0 (API level 24), + Android provides an API for customizing the style of a notification. + Using the MessagingStyle class, you can change several of the + labels displayed on the notification, including the conversation title, + additional messages, and the content view for the notification. +

    + +

    + The following code snippet demonstrates how to customize a notification's + style using the MessagingStyle class. +

    + +
    +  Notification notification = new Notification.Builder()
    +             .setStyle(new Notification.MessagingStyle("Me")
    +                 .setConversationTitle("Team lunch")
    +                 .addMessage("Hi", timestamp1, null) // Pass in null for user.
    +                 .addMessage("What's up?", timestamp2, "Coworker")
    +                 .addMessage("Not much", timestamp3, null)
    +                 .addMessage("How about lunch?", timestamp4, "Coworker"))
    +             .build();
    +
    + diff --git a/docs/html/guide/topics/ui/notifiers/toasts.jd b/docs/html/guide/topics/ui/notifiers/toasts.jd index e5d4a0a356516c09539ac47023731ecab74b5d29..2262a9ab956735bcd365cce46715ef9715a928c8 100644 --- a/docs/html/guide/topics/ui/notifiers/toasts.jd +++ b/docs/html/guide/topics/ui/notifiers/toasts.jd @@ -2,14 +2,14 @@ page.title=Toasts @jd:body
    -
    +

    In this document

    1. The Basics
    2. Positioning your Toast
    3. Creating a Custom Toast View
    - +

    Key classes

    1. {@link android.widget.Toast}
    2. @@ -19,14 +19,14 @@ page.title=Toasts

      A toast provides simple feedback about an operation in a small popup. It only fills the amount of space required for the message and the current -activity remains visible and interactive. -For example, navigating away from an email before you send it triggers a -"Draft saved" toast to let you know that you can continue editing later. +activity remains visible and interactive. +For example, navigating away from an email before you send it triggers a +"Draft saved" toast to let you know that you can continue editing later. Toasts automatically disappear after a timeout.

      -

      If user response to a status message is required, consider instead using a +

      If user response to a status message is required, consider instead using a Notification.

      @@ -49,8 +49,8 @@ toast.show();

    This example demonstrates everything you need for most toast notifications. -You should rarely need anything else. You may, however, want to position the -toast differently or even use your own layout instead of a simple text message. +You should rarely need anything else. You may, however, want to position the +toast differently or even use your own layout instead of a simple text message. The following sections describe how you can do these things.

    You can also chain your methods and avoid holding on to the Toast object, like this:

    @@ -61,7 +61,7 @@ The following sections describe how you can do these things.

    A standard toast notification appears near the bottom of the screen, centered horizontally. You can change this position with the {@link android.widget.Toast#setGravity(int,int,int)} -method. This accepts three parameters: a {@link android.view.Gravity} constant, +method. This accepts three parameters: a {@link android.view.Gravity} constant, an x-position offset, and a y-position offset.

    For example, if you decide that the toast should appear in the top-left corner, you can set the @@ -70,22 +70,28 @@ gravity like this:

    toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
    -

    If you want to nudge the position to the right, increase the value of the second parameter. +

    If you want to nudge the position to the right, increase the value of the second parameter. To nudge it down, increase the value of the last parameter.

    Creating a Custom Toast View

    -

    If a simple text message isn't enough, you can create a customized layout for your -toast notification. To create a custom layout, define a View layout, -in XML or in your application code, and pass the root {@link android.view.View} object -to the {@link android.widget.Toast#setView(View)} method.

    - -

    For example, you can create the layout for the toast visible in the screenshot to the right -with the following XML (saved as toast_layout.xml):

    +

    + If a simple text message isn't enough, you can create a customized layout + for your toast notification. To create a custom layout, define a View + layout, in XML or in your application code, and pass the root {@link + android.view.View} object to the {@link android.widget.Toast#setView(View)} + method. +

    + +

    + For example, you can create the layout for the toast visible in the + screenshot to the right with the following XML (saved as + layout/custom_toast.xml): +

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -              android:id="@+id/toast_layout_root"
    +              android:id="@+id/custom_toast_container"
                   android:orientation="horizontal"
                   android:layout_width="fill_parent"
                   android:layout_height="fill_parent"
    @@ -103,15 +109,18 @@ with the following XML (saved as toast_layout.xml):

    android:textColor="#FFF" /> </LinearLayout> -
    +
    -

    Notice that the ID of the LinearLayout element is "toast_layout_root". You must use this -ID to inflate the layout from the XML, as shown here:

    +

    + Notice that the ID of the LinearLayout element is "custom_toast_container". + You must use this ID and the ID of the XML layout file "custom_toast" to + inflate the layout, as shown here: +

     LayoutInflater inflater = getLayoutInflater();
     View layout = inflater.inflate(R.layout.custom_toast,
    -                               (ViewGroup) findViewById(R.id.toast_layout_root));
    +                (ViewGroup) findViewById(R.id.custom_toast_container));
     
     TextView text = (TextView) layout.findViewById(R.id.text);
     text.setText("This is a custom toast");
    @@ -123,21 +132,21 @@ toast.setView(layout);
     toast.show();
     
    -

    First, retrieve the {@link android.view.LayoutInflater} with -{@link android.app.Activity#getLayoutInflater()} +

    First, retrieve the {@link android.view.LayoutInflater} with +{@link android.app.Activity#getLayoutInflater()} (or {@link android.content.Context#getSystemService(String) getSystemService()}), -and then inflate the layout from XML using +and then inflate the layout from XML using {@link android.view.LayoutInflater#inflate(int, ViewGroup)}. The first parameter is the layout resource ID and the second is the root View. You can use -this inflated layout to find more View objects in the layout, so now capture and +this inflated layout to find more View objects in the layout, so now capture and define the content for the ImageView and TextView elements. Finally, create a new Toast with {@link android.widget.Toast#Toast(Context)} and set some properties of the toast, such as the gravity and duration. Then call {@link android.widget.Toast#setView(View)} and pass it the inflated layout. -You can now display the toast with your custom layout by calling +You can now display the toast with your custom layout by calling {@link android.widget.Toast#show()}.

    -

    Note: Do not use the public constructor for a Toast +

    Note: Do not use the public constructor for a Toast unless you are going to define the layout with {@link android.widget.Toast#setView(View)}. If you do not have a custom layout to use, you must use {@link android.widget.Toast#makeText(Context,int,int)} to create the Toast.

    diff --git a/docs/html/guide/topics/ui/overview.jd b/docs/html/guide/topics/ui/overview.jd index 85c5756de35c0e913acbb0f8e93672b466e7209b..f323d6c4926d4a39c6627a592fced12772abc509 100644 --- a/docs/html/guide/topics/ui/overview.jd +++ b/docs/html/guide/topics/ui/overview.jd @@ -39,7 +39,7 @@ group.

     <?xml version="1.0" encoding="utf-8"?>
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    -              android:layout_width="fill_parent" 
    +              android:layout_width="fill_parent"
                   android:layout_height="fill_parent"
                   android:orientation="vertical" >
         <TextView android:id="@+id/text"
    @@ -60,7 +60,7 @@ layout.

    For a complete guide to creating a UI layout, see XML Layouts. - +

    User Interface Components

    You don't have to build all of your UI using {@link android.view.View} and {@link diff --git a/docs/html/guide/topics/ui/settings.jd b/docs/html/guide/topics/ui/settings.jd index 243c1c340eb32f9c6011ebc65eb9ce7a1e20793b..619fd268aef90a713590307f5ee41181501d8484 100644 --- a/docs/html/guide/topics/ui/settings.jd +++ b/docs/html/guide/topics/ui/settings.jd @@ -84,7 +84,7 @@ href="{@docRoot}design/patterns/settings.html">Settings design guide.

    Figure 1. Screenshots from the Android Messaging app's -settings. Selecting an item defined by a {@link android.preference.Preference} +settings. Selecting an item defined by a {@link android.preference.Preference} opens an interface to change the setting.

    @@ -230,7 +230,7 @@ android.preference.ListPreference}. Both items include the following three attri
    {@code android:key}
    This attribute is required for preferences that persist a data value. It specifies the unique key (a string) the system uses when saving this setting's value in the {@link -android.content.SharedPreferences}. +android.content.SharedPreferences}.

    The only instances in which this attribute is not required is when the preference is a {@link android.preference.PreferenceCategory} or {@link android.preference.PreferenceScreen}, or the preference specifies an {@link android.content.Intent} to invoke (with an

     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    -    <PreferenceCategory 
    +    <PreferenceCategory
             android:title="@string/pref_sms_storage_title"
             android:key="pref_key_storage_settings">
             <CheckBoxPreference
    @@ -299,12 +299,12 @@ android.preference.PreferenceCategory}.

    android:summary="@string/pref_summary_auto_delete" android:title="@string/pref_title_auto_delete" android:defaultValue="false"... /> - <Preference + <Preference android:key="pref_key_sms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" android:title="@string/pref_title_sms_delete"... /> - <Preference + <Preference android:key="pref_key_mms_delete_limit" android:dependency="pref_key_auto_delete" android:summary="@string/pref_summary_delete_limit" @@ -594,11 +594,11 @@ element inside a root {@code } element. For example:

     <?xml version="1.0" encoding="utf-8"?>
     <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one" />
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" >
    @@ -678,15 +678,15 @@ the {@link android.preference.PreferenceActivity} that specifies which preferenc
     load.

    For example, here's an XML file for preference headers that is used on Android 3.0 -and higher ({@code res/xml/preference_headers.xml}):

    +and higher ({@code res/xml/preference_headers.xml}):

     <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsFragmentOne"
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one" />
    -    <header 
    +    <header
             android:fragment="com.example.prefs.SettingsFragmentTwo"
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" />
    @@ -698,18 +698,18 @@ Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):

     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    -    <Preference 
    +    <Preference
             android:title="@string/prefs_category_one"
             android:summary="@string/prefs_summ_category_one"  >
    -        <intent 
    +        <intent
                 android:targetPackage="com.example.prefs"
                 android:targetClass="com.example.prefs.SettingsActivity"
                 android:action="com.example.prefs.PREFS_ONE" />
         </Preference>
    -    <Preference 
    +    <Preference
             android:title="@string/prefs_category_two"
             android:summary="@string/prefs_summ_category_two" >
    -        <intent 
    +        <intent
                 android:targetPackage="com.example.prefs"
                 android:targetClass="com.example.prefs.SettingsActivity"
                 android:action="com.example.prefs.PREFS_TWO" />
    @@ -943,8 +943,8 @@ uses.

    The Android framework includes a variety of {@link android.preference.Preference} subclasses that allow you to build a UI for several different types of settings. -However, you might discover a setting you need for which there’s no built-in solution, such as a -number picker or date picker. In such a case, you’ll need to create a custom preference by extending +However, you might discover a setting you need for which there's no built-in solution, such as a +number picker or date picker. In such a case, you'll need to create a custom preference by extending the {@link android.preference.Preference} class or one of the other subclasses.

    When you extend the {@link android.preference.Preference} class, there are a few important @@ -982,11 +982,11 @@ default positive and negative dialog buttons:

    public class NumberPickerPreference extends DialogPreference { public NumberPickerPreference(Context context, AttributeSet attrs) { super(context, attrs); - + setDialogLayoutResource(R.layout.numberpicker_dialog); setPositiveButtonText(android.R.string.ok); setNegativeButtonText(android.R.string.cancel); - + setDialogIcon(null); } ... @@ -1201,7 +1201,7 @@ protected void onRestoreInstanceState(Parcelable state) { // Cast state to custom BaseSavedState and pass to superclass SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); - + // Set this Preference's widget to reflect the restored state mNumberPicker.setValue(myState.value); } diff --git a/docs/html/guide/topics/ui/themes.jd b/docs/html/guide/topics/ui/themes.jd index f932dbdec191c58699d07b70663fdf928444acb2..436b789ea51fa32630b0f2685e78ce8b0fa83335 100644 --- a/docs/html/guide/topics/ui/themes.jd +++ b/docs/html/guide/topics/ui/themes.jd @@ -177,7 +177,7 @@ You're probably familiar with some already, such as {@link android.R.attr#layout

    The best place to find properties that apply to a specific {@link android.view.View} is the corresponding class reference, which lists all of the supported XML attributes. For example, all of the attributes listed in the table of -TextView XML +TextView XML attributes can be used in a style definition for a {@link android.widget.TextView} element (or one of its subclasses). One of the attributes listed in the reference is {@code @@ -279,14 +279,14 @@ does not use the android: namespace prefix.

    Apply a theme to an Activity or application

    To set a theme for all the activities of your application, open the {@code AndroidManifest.xml} file and -edit the <application> tag to include the android:theme attribute with the +edit the <application> tag to include the android:theme attribute with the style name. For example:

     <application android:theme="@style/CustomTheme">
     
    -

    If you want a theme applied to just one Activity in your application, then add the +

    If you want a theme applied to just one Activity in your application, then add the android:theme attribute to the <activity> tag instead.

    Just as Android provides other built-in resources, there are many pre-defined themes that you can use, to avoid @@ -374,9 +374,9 @@ keeps your program code focused on application functionality, rather than style. for you to change your theme programatically (perhaps based on a user preference), you can.

    To set the theme in your program code, use the {@link android.content.ContextWrapper#setTheme(int)} -method and pass it the theme resource ID. Note that, when doing so, you must be sure to set the theme before -instantiating any Views in the context, for example, before calling -setContentView(View) or inflate(int, ViewGroup). This ensures that +method and pass it the theme resource ID. Note that, when doing so, you must be sure to set the theme before +instantiating any Views in the context, for example, before calling +setContentView(View) or inflate(int, ViewGroup). This ensures that the system applies the same theme for all of your UI screens. Here's an example:

    @@ -391,7 +391,7 @@ the system applies the same theme for all of your UI screens. Here's an example:
     

    If you are considering loading a theme programmatically for the main screen of your application, note that the theme would not be applied in any animations the system would use to start the activity, which -would take place before your application opens. In most cases, if +would take place before your application opens. In most cases, if you want to apply a theme to your main screen, doing so in XML is a better approach.

    diff --git a/docs/html/guide/topics/ui/ui-events.jd b/docs/html/guide/topics/ui/ui-events.jd index 6d41b15f6c17e726840aaa2979e1de4c26a32250..7dd24a44fa89e26dc6b43e9593da95b48eaf633e 100644 --- a/docs/html/guide/topics/ui/ui-events.jd +++ b/docs/html/guide/topics/ui/ui-events.jd @@ -20,8 +20,8 @@ parent.link=index.html When considering events within your user interface, the approach is to capture the events from the specific View object that the user interacts with. The View class provides the means to do so.

    -

    Within the various View classes that you'll use to compose your layout, you may notice several public callback -methods that look useful for UI events. These methods are called by the Android framework when the +

    Within the various View classes that you'll use to compose your layout, you may notice several public callback +methods that look useful for UI events. These methods are called by the Android framework when the respective action occurs on that object. For instance, when a View (such as a Button) is touched, the onTouchEvent() method is called on that object. However, in order to intercept this, you must extend the class and override the method. However, extending every View object @@ -30,7 +30,7 @@ a collection of nested interfaces with callbacks that you can much more easily d called event listeners, are your ticket to capturing the user interaction with your UI.

    While you will more commonly use the event listeners to listen for user interaction, there may -come a time when you do want to extend a View class, in order to build a custom component. +come a time when you do want to extend a View class, in order to build a custom component. Perhaps you want to extend the {@link android.widget.Button} class to make something more fancy. In this case, you'll be able to define the default event behaviors for your class using the class event handlers.

    @@ -38,7 +38,7 @@ class using the class event handlers.

    Event Listeners

    -

    An event listener is an interface in the {@link android.view.View} class that contains a single +

    An event listener is an interface in the {@link android.view.View} class that contains a single callback method. These methods will be called by the Android framework when the View to which the listener has been registered is triggered by user interaction with the item in the UI.

    @@ -46,27 +46,27 @@ been registered is triggered by user interaction with the item in the UI.

    onClick()
    -
    From {@link android.view.View.OnClickListener}. - This is called when the user either touches the item +
    From {@link android.view.View.OnClickListener}. + This is called when the user either touches the item (when in touch mode), or focuses upon the item with the navigation-keys or trackball and presses the suitable "enter" key or presses down on the trackball.
    onLongClick()
    -
    From {@link android.view.View.OnLongClickListener}. - This is called when the user either touches and holds the item (when in touch mode), or +
    From {@link android.view.View.OnLongClickListener}. + This is called when the user either touches and holds the item (when in touch mode), or focuses upon the item with the navigation-keys or trackball and presses and holds the suitable "enter" key or presses and holds down on the trackball (for one second).
    onFocusChange()
    -
    From {@link android.view.View.OnFocusChangeListener}. +
    From {@link android.view.View.OnFocusChangeListener}. This is called when the user navigates onto or away from the item, using the navigation-keys or trackball.
    onKey()
    -
    From {@link android.view.View.OnKeyListener}. +
    From {@link android.view.View.OnKeyListener}. This is called when the user is focused on the item and presses or releases a hardware key on the device.
    onTouch()
    -
    From {@link android.view.View.OnTouchListener}. +
    From {@link android.view.View.OnTouchListener}. This is called when the user performs an action qualified as a touch event, including a press, a release, or any movement gesture on the screen (within the bounds of the item).
    onCreateContextMenu()
    -
    From {@link android.view.View.OnCreateContextMenuListener}. +
    From {@link android.view.View.OnCreateContextMenuListener}. This is called when a Context Menu is being built (as the result of a sustained "long click"). See the discussion on context menus in the Menus developer guide.
    @@ -75,8 +75,8 @@ been registered is triggered by user interaction with the item in the UI.

    These methods are the sole inhabitants of their respective interface. To define one of these methods and handle your events, implement the nested interface in your Activity or define it as an anonymous class. Then, pass an instance of your implementation -to the respective View.set...Listener() method. (E.g., call -{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()} +to the respective View.set...Listener() method. (E.g., call +{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()} and pass it your implementation of the {@link android.view.View.OnClickListener OnClickListener}.)

    The example below shows how to register an on-click listener for a Button.

    @@ -121,17 +121,17 @@ public class ExampleActivity extends Activity implements OnClickListener { no return value, but some other event listener methods must return a boolean. The reason depends on the event. For the few that do, here's why:

      -
    • {@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()} - - This returns a boolean to indicate whether you have consumed the event and it should not be carried further. - That is, return true to indicate that you have handled the event and it should stop here; +
    • {@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()} - + This returns a boolean to indicate whether you have consumed the event and it should not be carried further. + That is, return true to indicate that you have handled the event and it should stop here; return false if you have not handled it and/or the event should continue to any other on-click listeners.
    • -
    • {@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()} - +
    • {@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()} - This returns a boolean to indicate whether you have consumed the event and it should not be carried further. - That is, return true to indicate that you have handled the event and it should stop here; + That is, return true to indicate that you have handled the event and it should stop here; return false if you have not handled it and/or the event should continue to any other on-key listeners.
    • -
    • {@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()} - +
    • {@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()} - This returns a boolean to indicate whether your listener consumes this event. The important thing is that this event can have multiple actions that follow each other. So, if you return false when the down action event is received, you indicate that you have not consumed the event and are also @@ -142,7 +142,7 @@ depends on the event. For the few that do, here's why:

      Remember that hardware key events are always delivered to the View currently in focus. They are dispatched starting from the top of the View hierarchy, and then down, until they reach the appropriate destination. If your View (or a child of your View) currently has focus, then you can see the event travel through the {@link android.view.View#dispatchKeyEvent(KeyEvent) -dispatchKeyEvent()} method. As an alternative to capturing key events through your View, you can also receive +dispatchKeyEvent()} method. As an alternative to capturing key events through your View, you can also receive all of the events inside your Activity with {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()} and {@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}.

      @@ -176,19 +176,19 @@ including:

    • {@link android.view.View#onTouchEvent} - Called when a touch screen motion event occurs.
    • {@link android.view.View#onFocusChanged} - Called when the view gains or loses focus.
    -

    There are some other methods that you should be aware of, which are not part of the View class, -but can directly impact the way you're able to handle events. So, when managing more complex events inside +

    There are some other methods that you should be aware of, which are not part of the View class, +but can directly impact the way you're able to handle events. So, when managing more complex events inside a layout, consider these other methods:

    • {@link android.app.Activity#dispatchTouchEvent(MotionEvent) - Activity.dispatchTouchEvent(MotionEvent)} - This allows your {@link + Activity.dispatchTouchEvent(MotionEvent)} - This allows your {@link android.app.Activity} to intercept all touch events before they are dispatched to the window.
    • {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent) ViewGroup.onInterceptTouchEvent(MotionEvent)} - This allows a {@link android.view.ViewGroup} to watch events as they are dispatched to child Views.
    • {@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean) ViewParent.requestDisallowInterceptTouchEvent(boolean)} - Call this - upon a parent View to indicate that it should not intercept touch events with {@link + upon a parent View to indicate that it should not intercept touch events with {@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}.
    @@ -199,7 +199,7 @@ necessary to give focus to actionable items (like buttons) so the user can see what will accept input. If the device has touch capabilities, however, and the user begins interacting with the interface by touching it, then it is no longer necessary to highlight items, or give focus to a particular View. Thus, there is a mode -for interaction named "touch mode." +for interaction named "touch mode."

    For a touch-capable device, once the user touches the screen, the device @@ -214,7 +214,7 @@ exit touch mode, and find a view to take focus. Now, the user may resume interac with the user interface without touching the screen.

    -The touch mode state is maintained throughout the entire system (all windows and activities). +The touch mode state is maintained throughout the entire system (all windows and activities). To query the current state, you can call {@link android.view.View#isInTouchMode} to see whether the device is currently in touch mode.

    @@ -254,10 +254,10 @@ the focus is leaving. Define the value of the attribute to be the id of the View

    Ordinarily, in this vertical layout, navigating up from the first Button would not go anywhere, nor would navigating down from the second Button. Now that the top Button has -defined the bottom one as the nextFocusUp (and vice versa), the navigation focus will +defined the bottom one as the nextFocusUp (and vice versa), the navigation focus will cycle from top-to-bottom and bottom-to-top.

    -

    If you'd like to declare a View as focusable in your UI (when it is traditionally not), +

    If you'd like to declare a View as focusable in your UI (when it is traditionally not), add the android:focusable XML attribute to the View, in your layout declaration. Set the value true. You can also declare a View as focusable while in Touch Mode with android:focusableInTouchMode.

    @@ -282,7 +282,7 @@ as discussed in the Event Listeners section, above the framework will take care of measuring, laying out, and drawing the tree as appropriate. - +

    Note: 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 diff --git a/docs/html/guide/webapps/debugging.jd b/docs/html/guide/webapps/debugging.jd index a74797df3bd3609c842deff78e53a13a495d448a..9e8e11337b73a8f3f0b20faf0ee9f7616b75b65b 100755 --- a/docs/html/guide/webapps/debugging.jd +++ b/docs/html/guide/webapps/debugging.jd @@ -92,7 +92,7 @@ expect from other web browsers.

    Using Console APIs in WebView

    All the console APIs shown above are also -supported when debugging in {@link android.webkit.WebView}. +supported when debugging in {@link android.webkit.WebView}. If you're targeting Android 2.1 (API level 7) and higher, you must provide a {@link android.webkit.WebChromeClient} that implements the {@link android.webkit.WebChromeClient#onConsoleMessage(String,int,String) diff --git a/docs/html/guide/webapps/targeting.jd b/docs/html/guide/webapps/targeting.jd index 4a2ea1773c952a5dea688dcfbf5c6e8c52c91372..10259b115b29db657f57e4460e6613c0341f971f 100644 --- a/docs/html/guide/webapps/targeting.jd +++ b/docs/html/guide/webapps/targeting.jd @@ -108,7 +108,7 @@ should exactly match the device screen's width and that the ability to zoom shou

    When optimizing your site for mobile devices, you should usually set the width to -{@code "device-width"} so the size fits exactly on all devices, then use CSS media queries to +{@code "device-width"} so the size fits exactly on all devices, then use CSS media queries to flexibly adapt layouts to suit different screen sizes.

    Note: You should disable user scaling only when you're certain diff --git a/docs/html/preview/images/bundles.png b/docs/html/images/android-7.0/bundles.png similarity index 100% rename from docs/html/preview/images/bundles.png rename to docs/html/images/android-7.0/bundles.png diff --git a/docs/html/preview/images/bundles_2x.png b/docs/html/images/android-7.0/bundles_2x.png similarity index 100% rename from docs/html/preview/images/bundles_2x.png rename to docs/html/images/android-7.0/bundles_2x.png diff --git a/docs/html/preview/images/datasaver.png b/docs/html/images/android-7.0/datasaver.png similarity index 100% rename from docs/html/preview/images/datasaver.png rename to docs/html/images/android-7.0/datasaver.png diff --git a/docs/html/preview/images/doze-diagram-1.png b/docs/html/images/android-7.0/doze-diagram-1.png similarity index 100% rename from docs/html/preview/images/doze-diagram-1.png rename to docs/html/images/android-7.0/doze-diagram-1.png diff --git a/docs/html/preview/images/doze-diagram-2.png b/docs/html/images/android-7.0/doze-diagram-2.png similarity index 100% rename from docs/html/preview/images/doze-diagram-2.png rename to docs/html/images/android-7.0/doze-diagram-2.png diff --git a/docs/html/preview/images/inline-reply.png b/docs/html/images/android-7.0/inline-reply.png similarity index 100% rename from docs/html/preview/images/inline-reply.png rename to docs/html/images/android-7.0/inline-reply.png diff --git a/docs/html/preview/images/inline-reply_2x.png b/docs/html/images/android-7.0/inline-reply_2x.png similarity index 100% rename from docs/html/preview/images/inline-reply_2x.png rename to docs/html/images/android-7.0/inline-reply_2x.png diff --git a/docs/html/preview/images/inline-type-reply.png b/docs/html/images/android-7.0/inline-type-reply.png similarity index 100% rename from docs/html/preview/images/inline-type-reply.png rename to docs/html/images/android-7.0/inline-type-reply.png diff --git a/docs/html/preview/images/inline-type-reply_2x.png b/docs/html/images/android-7.0/inline-type-reply_2x.png similarity index 100% rename from docs/html/preview/images/inline-type-reply_2x.png rename to docs/html/images/android-7.0/inline-type-reply_2x.png diff --git a/docs/html/preview/images/m-preview-timeline-crop.png b/docs/html/images/android-7.0/m-preview-timeline-crop.png similarity index 100% rename from docs/html/preview/images/m-preview-timeline-crop.png rename to docs/html/images/android-7.0/m-preview-timeline-crop.png diff --git a/docs/html/preview/images/m-preview-timeline.png b/docs/html/images/android-7.0/m-preview-timeline.png similarity index 100% rename from docs/html/preview/images/m-preview-timeline.png rename to docs/html/images/android-7.0/m-preview-timeline.png diff --git a/docs/html/preview/images/mw-portrait.png b/docs/html/images/android-7.0/mw-portrait.png similarity index 100% rename from docs/html/preview/images/mw-portrait.png rename to docs/html/images/android-7.0/mw-portrait.png diff --git a/docs/html/preview/images/mw-splitscreen.png b/docs/html/images/android-7.0/mw-splitscreen.png similarity index 100% rename from docs/html/preview/images/mw-splitscreen.png rename to docs/html/images/android-7.0/mw-splitscreen.png diff --git a/docs/html/preview/images/mw-splitscreen_2x.png b/docs/html/images/android-7.0/mw-splitscreen_2x.png similarity index 100% rename from docs/html/preview/images/mw-splitscreen_2x.png rename to docs/html/images/android-7.0/mw-splitscreen_2x.png diff --git a/docs/html/preview/images/n-preview-setup.png b/docs/html/images/android-7.0/n-preview-setup.png similarity index 100% rename from docs/html/preview/images/n-preview-setup.png rename to docs/html/images/android-7.0/n-preview-setup.png diff --git a/docs/html/preview/images/notifications-1.png b/docs/html/images/android-7.0/notifications-1.png similarity index 100% rename from docs/html/preview/images/notifications-1.png rename to docs/html/images/android-7.0/notifications-1.png diff --git a/docs/html/preview/images/notifications-2.png b/docs/html/images/android-7.0/notifications-2.png similarity index 100% rename from docs/html/preview/images/notifications-2.png rename to docs/html/images/android-7.0/notifications-2.png diff --git a/docs/html/preview/images/notifications-3.png b/docs/html/images/android-7.0/notifications-3.png similarity index 100% rename from docs/html/preview/images/notifications-3.png rename to docs/html/images/android-7.0/notifications-3.png diff --git a/docs/html/preview/images/notifications-card.png b/docs/html/images/android-7.0/notifications-card.png similarity index 100% rename from docs/html/preview/images/notifications-card.png rename to docs/html/images/android-7.0/notifications-card.png diff --git a/docs/html/preview/images/pip-active.png b/docs/html/images/android-7.0/pip-active.png similarity index 100% rename from docs/html/preview/images/pip-active.png rename to docs/html/images/android-7.0/pip-active.png diff --git a/docs/html/preview/images/pip-button.png b/docs/html/images/android-7.0/pip-button.png similarity index 100% rename from docs/html/preview/images/pip-button.png rename to docs/html/images/android-7.0/pip-button.png diff --git a/docs/html/preview/images/quicksettings.png b/docs/html/images/android-7.0/quicksettings.png similarity index 100% rename from docs/html/preview/images/quicksettings.png rename to docs/html/images/android-7.0/quicksettings.png diff --git a/docs/html/preview/images/sample-activenotifications.png b/docs/html/images/android-7.0/sample-activenotifications.png similarity index 100% rename from docs/html/preview/images/sample-activenotifications.png rename to docs/html/images/android-7.0/sample-activenotifications.png diff --git a/docs/html/preview/images/sample-directboot.png b/docs/html/images/android-7.0/sample-directboot.png similarity index 100% rename from docs/html/preview/images/sample-directboot.png rename to docs/html/images/android-7.0/sample-directboot.png diff --git a/docs/html/preview/images/sample-messagingservice.png b/docs/html/images/android-7.0/sample-messagingservice.png similarity index 100% rename from docs/html/preview/images/sample-messagingservice.png rename to docs/html/images/android-7.0/sample-messagingservice.png diff --git a/docs/html/preview/images/sample-multiwindow.png b/docs/html/images/android-7.0/sample-multiwindow.png similarity index 100% rename from docs/html/preview/images/sample-multiwindow.png rename to docs/html/images/android-7.0/sample-multiwindow.png diff --git a/docs/html/preview/images/sample-scopeddirectoryaccess.png b/docs/html/images/android-7.0/sample-scopeddirectoryaccess.png similarity index 100% rename from docs/html/preview/images/sample-scopeddirectoryaccess.png rename to docs/html/images/android-7.0/sample-scopeddirectoryaccess.png diff --git a/docs/html/images/android-7.0/scoped-directory-access-dont-ask.png b/docs/html/images/android-7.0/scoped-directory-access-dont-ask.png new file mode 100644 index 0000000000000000000000000000000000000000..66829484f2aba74d40e3ec2d9226069a83d20d35 Binary files /dev/null and b/docs/html/images/android-7.0/scoped-directory-access-dont-ask.png differ diff --git a/docs/html/images/android-7.0/scoped-directory-access-dont-ask_2x.png b/docs/html/images/android-7.0/scoped-directory-access-dont-ask_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be717f96ac0aa232f49722b726e87b16ae42364c Binary files /dev/null and b/docs/html/images/android-7.0/scoped-directory-access-dont-ask_2x.png differ diff --git a/docs/html/images/android-7.0/scoped-directory-access-framed.png b/docs/html/images/android-7.0/scoped-directory-access-framed.png new file mode 100644 index 0000000000000000000000000000000000000000..e4d619ad1d8b43b4d8b6c269542f9d6b6dd4cdb0 Binary files /dev/null and b/docs/html/images/android-7.0/scoped-directory-access-framed.png differ diff --git a/docs/html/images/android-7.0/scoped-directory-access-framed_2x.png b/docs/html/images/android-7.0/scoped-directory-access-framed_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe17bce12b0c363420dce76908127dc4a69f0795 Binary files /dev/null and b/docs/html/images/android-7.0/scoped-directory-access-framed_2x.png differ diff --git a/docs/html/preview/images/scoped-folder-access-dont-ask.png b/docs/html/images/android-7.0/scoped-folder-access-dont-ask.png similarity index 100% rename from docs/html/preview/images/scoped-folder-access-dont-ask.png rename to docs/html/images/android-7.0/scoped-folder-access-dont-ask.png diff --git a/docs/html/preview/images/scoped-folder-access-dont-ask_2x.png b/docs/html/images/android-7.0/scoped-folder-access-dont-ask_2x.png similarity index 100% rename from docs/html/preview/images/scoped-folder-access-dont-ask_2x.png rename to docs/html/images/android-7.0/scoped-folder-access-dont-ask_2x.png diff --git a/docs/html/preview/images/scoped-folder-access-framed.png b/docs/html/images/android-7.0/scoped-folder-access-framed.png similarity index 100% rename from docs/html/preview/images/scoped-folder-access-framed.png rename to docs/html/images/android-7.0/scoped-folder-access-framed.png diff --git a/docs/html/preview/images/scoped-folder-access-framed_2x.png b/docs/html/images/android-7.0/scoped-folder-access-framed_2x.png similarity index 100% rename from docs/html/preview/images/scoped-folder-access-framed_2x.png rename to docs/html/images/android-7.0/scoped-folder-access-framed_2x.png diff --git a/docs/html/preview/images/screen-zoom-1.png b/docs/html/images/android-7.0/screen-zoom-1.png similarity index 100% rename from docs/html/preview/images/screen-zoom-1.png rename to docs/html/images/android-7.0/screen-zoom-1.png diff --git a/docs/html/preview/images/screen-zoom-2.png b/docs/html/images/android-7.0/screen-zoom-2.png similarity index 100% rename from docs/html/preview/images/screen-zoom-2.png rename to docs/html/images/android-7.0/screen-zoom-2.png diff --git a/docs/html/preview/images/studio-jdk-location.jpg b/docs/html/images/android-7.0/studio-jdk-location.jpg similarity index 100% rename from docs/html/preview/images/studio-jdk-location.jpg rename to docs/html/images/android-7.0/studio-jdk-location.jpg diff --git a/docs/html/images/brand/android_logo_no.png b/docs/html/images/brand/android_logo_no.png index 8de22d87d9a25340539ec04e8d22c0f2f59a7b56..946bc49a4c784272ffc92d3582e2c3209f205b53 100644 Binary files a/docs/html/images/brand/android_logo_no.png and b/docs/html/images/brand/android_logo_no.png differ diff --git a/docs/html/images/brand/android_logo_no_2x.png b/docs/html/images/brand/android_logo_no_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8434c795ab799485f599e56413519607367ba1f4 Binary files /dev/null and b/docs/html/images/brand/android_logo_no_2x.png differ diff --git a/docs/html/images/cards/card-drive-conversions_16-9_2x.png b/docs/html/images/cards/card-drive-conversions_16-9_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..34480124567b3b96ef17e45174fa0bf6b35034fe Binary files /dev/null and b/docs/html/images/cards/card-drive-conversions_16-9_2x.png differ diff --git a/docs/html/images/cards/card-notifications_2x.png b/docs/html/images/cards/card-notifications_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e56c1df344194016a993d1f261de1fd3a1ea2e95 Binary files /dev/null and b/docs/html/images/cards/card-notifications_2x.png differ diff --git a/docs/html/images/cards/distribute/stories/aftenposten.png b/docs/html/images/cards/distribute/stories/aftenposten.png new file mode 100644 index 0000000000000000000000000000000000000000..60cb85104f8cafba4b7e7374f0a7c31d35d3dc12 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/aftenposten.png differ diff --git a/docs/html/images/cards/distribute/stories/animoca.jpg b/docs/html/images/cards/distribute/stories/animoca.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1886bcef0268252f608c4dfd3c678d1ff86509ce Binary files /dev/null and b/docs/html/images/cards/distribute/stories/animoca.jpg differ diff --git a/docs/html/images/cards/distribute/stories/drupe.jpg b/docs/html/images/cards/distribute/stories/drupe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..52956956744c4da0bb3feddf08b91d5604f94bf0 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/drupe.jpg differ diff --git a/docs/html/images/cards/distribute/stories/economist-espresso.png b/docs/html/images/cards/distribute/stories/economist-espresso.png new file mode 100644 index 0000000000000000000000000000000000000000..923bf5769d3fd04ade4971cac40b9d472a5b2c7e Binary files /dev/null and b/docs/html/images/cards/distribute/stories/economist-espresso.png differ diff --git a/docs/html/images/cards/distribute/stories/el-mundo.png b/docs/html/images/cards/distribute/stories/el-mundo.png new file mode 100644 index 0000000000000000000000000000000000000000..23db783d47dd45deb855e67924f9c4d6440da629 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/el-mundo.png differ diff --git a/docs/html/images/cards/distribute/stories/expressen-sport.png b/docs/html/images/cards/distribute/stories/expressen-sport.png new file mode 100644 index 0000000000000000000000000000000000000000..842ed3da77a8082bca7b2939e3954a6d4be95b52 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/expressen-sport.png differ diff --git a/docs/html/images/cards/distribute/stories/glamour.png b/docs/html/images/cards/distribute/stories/glamour.png new file mode 100644 index 0000000000000000000000000000000000000000..770b03fc7df5fad88f83fda2a42b5b9817e6bd21 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/glamour.png differ diff --git a/docs/html/images/cards/distribute/stories/happylabs-logo.png b/docs/html/images/cards/distribute/stories/happylabs-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ea20e71a6ed6caad9deb6f651b332e1608ddafde Binary files /dev/null and b/docs/html/images/cards/distribute/stories/happylabs-logo.png differ diff --git a/docs/html/images/cards/distribute/stories/lifesum.png b/docs/html/images/cards/distribute/stories/lifesum.png new file mode 100644 index 0000000000000000000000000000000000000000..3975ff260ed4f6eada0a2c95fc02ca8963920569 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/lifesum.png differ diff --git a/docs/html/images/cards/distribute/stories/noom.jpg b/docs/html/images/cards/distribute/stories/noom.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dde18a21e417e9a99fa9a4be1e49fce2dce85da6 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/noom.jpg differ diff --git a/docs/html/images/cards/distribute/stories/playlab.jpg b/docs/html/images/cards/distribute/stories/playlab.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b641e63871de7c56d51df3434c0b447c0713e85 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/playlab.jpg differ diff --git a/docs/html/images/cards/distribute/stories/segundamano.png b/docs/html/images/cards/distribute/stories/segundamano.png new file mode 100644 index 0000000000000000000000000000000000000000..60e873c0c8cbaa160b63788d3b8dd4c64f77d5f4 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/segundamano.png differ diff --git a/docs/html/images/cards/distribute/stories/tapps.png b/docs/html/images/cards/distribute/stories/tapps.png new file mode 100644 index 0000000000000000000000000000000000000000..e01e3adf596d361e2fa120cba97f7206d1ed08b2 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/tapps.png differ diff --git a/docs/html/images/cards/distribute/stories/witch-puzzle.png b/docs/html/images/cards/distribute/stories/witch-puzzle.png new file mode 100644 index 0000000000000000000000000000000000000000..c336f1bf16ef9d85b6ce24319b221b4fb37bb3c9 Binary files /dev/null and b/docs/html/images/cards/distribute/stories/witch-puzzle.png differ diff --git a/docs/html/images/develop/hero-layout-editor.png b/docs/html/images/develop/hero-layout-editor.png new file mode 100644 index 0000000000000000000000000000000000000000..195150e77c191aad1a3de80c6f022f77b3929d64 Binary files /dev/null and b/docs/html/images/develop/hero-layout-editor.png differ diff --git a/docs/html/images/develop/hero-layout-editor_2x.png b/docs/html/images/develop/hero-layout-editor_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..60c3d2415a079c8eb78b47b750dd1f90d7d510ac Binary files /dev/null and b/docs/html/images/develop/hero-layout-editor_2x.png differ diff --git a/docs/html/images/distribute/google-sign-in-banner.png b/docs/html/images/distribute/google-sign-in-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..ba046861a770cb9aae45df802e67daf8fa4e2c72 Binary files /dev/null and b/docs/html/images/distribute/google-sign-in-banner.png differ diff --git a/docs/html/images/distribute/nearby_beacons.png b/docs/html/images/distribute/nearby_beacons.png new file mode 100644 index 0000000000000000000000000000000000000000..aba2f39e7b1acf0610f4f4a58806d00e23506702 Binary files /dev/null and b/docs/html/images/distribute/nearby_beacons.png differ diff --git a/docs/html/images/distribute/nearby_connections.png b/docs/html/images/distribute/nearby_connections.png new file mode 100644 index 0000000000000000000000000000000000000000..52e6daa7028eef9c9b8ebdb4d488e052367e99f2 Binary files /dev/null and b/docs/html/images/distribute/nearby_connections.png differ diff --git a/docs/html/images/distribute/nearby_messaging.png b/docs/html/images/distribute/nearby_messaging.png new file mode 100644 index 0000000000000000000000000000000000000000..6ae2d00505fd97c086e34c26bcd688dad5f9f56d Binary files /dev/null and b/docs/html/images/distribute/nearby_messaging.png differ diff --git a/docs/html/images/distribute/promote_ads_apps.png b/docs/html/images/distribute/promote_ads_apps.png index 2f578651e7f4ee808a9d610dfa7df3fed9ff7382..1c25be34e80cd778d4bb95ebb6106e9968a4b8f2 100644 Binary files a/docs/html/images/distribute/promote_ads_apps.png and b/docs/html/images/distribute/promote_ads_apps.png differ diff --git a/docs/html/images/distribute/promote_ads_gmail.png b/docs/html/images/distribute/promote_ads_gmail.png index 1d21b4a3cdf9cf8725ef3eeecc8535e4254b3431..c1013fc7603484524dfa9eb755e53ffcaf0d8609 100644 Binary files a/docs/html/images/distribute/promote_ads_gmail.png and b/docs/html/images/distribute/promote_ads_gmail.png differ diff --git a/docs/html/images/distribute/promote_ads_play.png b/docs/html/images/distribute/promote_ads_play.png index 1cf51b273f9c3040bb9cfc5608b6194e4fc146ea..ae0f84bf87f9cd9055fc5405c62f515806251e12 100644 Binary files a/docs/html/images/distribute/promote_ads_play.png and b/docs/html/images/distribute/promote_ads_play.png differ diff --git a/docs/html/images/distribute/promote_ads_search.png b/docs/html/images/distribute/promote_ads_search.png index 27c0b38e2f04f3d76b2fc79f6d3ecc39ff35fb6b..adcede154e3f90ee6c3f9eb9a5e46d86814375f1 100644 Binary files a/docs/html/images/distribute/promote_ads_search.png and b/docs/html/images/distribute/promote_ads_search.png differ diff --git a/docs/html/images/distribute/promote_ads_web.png b/docs/html/images/distribute/promote_ads_web.png index 588a3d4487a19a73e60e5dad35b1a04e5bd32726..8fefed167848138fe173f51f29a1696e0ed0a3f5 100644 Binary files a/docs/html/images/distribute/promote_ads_web.png and b/docs/html/images/distribute/promote_ads_web.png differ diff --git a/docs/html/images/distribute/promote_ads_youtube.png b/docs/html/images/distribute/promote_ads_youtube.png index e88a7965f6dee46f267dc1f88c185548a9483f83..ad44e512f9d6352f35967de5b67f8fb9fecc9b1e 100644 Binary files a/docs/html/images/distribute/promote_ads_youtube.png and b/docs/html/images/distribute/promote_ads_youtube.png differ diff --git a/docs/html/images/distribute/stories/aftenposten-icon.png b/docs/html/images/distribute/stories/aftenposten-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..60cb85104f8cafba4b7e7374f0a7c31d35d3dc12 Binary files /dev/null and b/docs/html/images/distribute/stories/aftenposten-icon.png differ diff --git a/docs/html/images/distribute/stories/animoca-flow.jpg b/docs/html/images/distribute/stories/animoca-flow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d2aa2f692edf8f1a73ccdd51edcd86407d48b0bb Binary files /dev/null and b/docs/html/images/distribute/stories/animoca-flow.jpg differ diff --git a/docs/html/images/distribute/stories/animoca-graph.jpg b/docs/html/images/distribute/stories/animoca-graph.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2a42f436d48d2cd084811e1c4b620ed236b7896 Binary files /dev/null and b/docs/html/images/distribute/stories/animoca-graph.jpg differ diff --git a/docs/html/images/distribute/stories/animoca-logo.png b/docs/html/images/distribute/stories/animoca-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4b5b6b53c7502bed66a126907f805a202f78b306 Binary files /dev/null and b/docs/html/images/distribute/stories/animoca-logo.png differ diff --git a/docs/html/images/distribute/stories/drupe-icon.png b/docs/html/images/distribute/stories/drupe-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1b75ccae83189d984e8e049709676a46143fbfe5 Binary files /dev/null and b/docs/html/images/distribute/stories/drupe-icon.png differ diff --git a/docs/html/images/distribute/stories/drupe-screenshot.png b/docs/html/images/distribute/stories/drupe-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..6fd4445348e8f60af4141155a56246e0aa82fb61 Binary files /dev/null and b/docs/html/images/distribute/stories/drupe-screenshot.png differ diff --git a/docs/html/images/distribute/stories/economist-espresso-icon.png b/docs/html/images/distribute/stories/economist-espresso-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..923bf5769d3fd04ade4971cac40b9d472a5b2c7e Binary files /dev/null and b/docs/html/images/distribute/stories/economist-espresso-icon.png differ diff --git a/docs/html/images/distribute/stories/el-mundo-icon.png b/docs/html/images/distribute/stories/el-mundo-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..23db783d47dd45deb855e67924f9c4d6440da629 Binary files /dev/null and b/docs/html/images/distribute/stories/el-mundo-icon.png differ diff --git a/docs/html/images/distribute/stories/expressen-icon.png b/docs/html/images/distribute/stories/expressen-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4547ce77576040febf73a5b60ce940db49435bbf Binary files /dev/null and b/docs/html/images/distribute/stories/expressen-icon.png differ diff --git a/docs/html/images/distribute/stories/glamour-icon.png b/docs/html/images/distribute/stories/glamour-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..770b03fc7df5fad88f83fda2a42b5b9817e6bd21 Binary files /dev/null and b/docs/html/images/distribute/stories/glamour-icon.png differ diff --git a/docs/html/images/distribute/stories/happylabs-happy_pet_icon.png b/docs/html/images/distribute/stories/happylabs-happy_pet_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9b24c4ad685925a20f692308e37d49a75dce4bc2 Binary files /dev/null and b/docs/html/images/distribute/stories/happylabs-happy_pet_icon.png differ diff --git a/docs/html/images/distribute/stories/happylabs-logo.png b/docs/html/images/distribute/stories/happylabs-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ea20e71a6ed6caad9deb6f651b332e1608ddafde Binary files /dev/null and b/docs/html/images/distribute/stories/happylabs-logo.png differ diff --git a/docs/html/images/distribute/stories/happylabs-variant.png b/docs/html/images/distribute/stories/happylabs-variant.png new file mode 100644 index 0000000000000000000000000000000000000000..3ce5342091573cde65caa9299f663edd60887c53 Binary files /dev/null and b/docs/html/images/distribute/stories/happylabs-variant.png differ diff --git a/docs/html/images/distribute/stories/japanese-witch-puzzle.png b/docs/html/images/distribute/stories/japanese-witch-puzzle.png new file mode 100644 index 0000000000000000000000000000000000000000..6a7ef13dd9f96265917aeb30c1a9782c5f68d7ac Binary files /dev/null and b/docs/html/images/distribute/stories/japanese-witch-puzzle.png differ diff --git a/docs/html/images/distribute/stories/lifesum-icon.png b/docs/html/images/distribute/stories/lifesum-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3975ff260ed4f6eada0a2c95fc02ca8963920569 Binary files /dev/null and b/docs/html/images/distribute/stories/lifesum-icon.png differ diff --git a/docs/html/images/distribute/stories/noom-icon.png b/docs/html/images/distribute/stories/noom-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a85321878f0fbffda70d911ae388dcd73a3de358 Binary files /dev/null and b/docs/html/images/distribute/stories/noom-icon.png differ diff --git a/docs/html/images/distribute/stories/noom-screenshot.png b/docs/html/images/distribute/stories/noom-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..0293eea85d68bbd98fd8685f848f8862b05618bf Binary files /dev/null and b/docs/html/images/distribute/stories/noom-screenshot.png differ diff --git a/docs/html/images/distribute/stories/playlab-icon.png b/docs/html/images/distribute/stories/playlab-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..af8018348df34723c15c7f56a03fbc582ebfdef1 Binary files /dev/null and b/docs/html/images/distribute/stories/playlab-icon.png differ diff --git a/docs/html/images/distribute/stories/playlab-screenshot.png b/docs/html/images/distribute/stories/playlab-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..42ffb6ae93a6a9fe0df254c4a6c32a8fa6ba281f Binary files /dev/null and b/docs/html/images/distribute/stories/playlab-screenshot.png differ diff --git a/docs/html/images/distribute/stories/segundamano-icon.png b/docs/html/images/distribute/stories/segundamano-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..60e873c0c8cbaa160b63788d3b8dd4c64f77d5f4 Binary files /dev/null and b/docs/html/images/distribute/stories/segundamano-icon.png differ diff --git a/docs/html/images/distribute/stories/tapps-candy-hills.png b/docs/html/images/distribute/stories/tapps-candy-hills.png new file mode 100644 index 0000000000000000000000000000000000000000..14dcb9447ba6273eaf29aa2c12510fcaaff3a27a Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-candy-hills.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-1.png b/docs/html/images/distribute/stories/tapps-icon-orig-1.png new file mode 100644 index 0000000000000000000000000000000000000000..44af423f3795a79760314da9bf34c4dd78ad7969 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-orig-1.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-2.png b/docs/html/images/distribute/stories/tapps-icon-orig-2.png new file mode 100644 index 0000000000000000000000000000000000000000..1b362557b2b0b7e9d74a590e0b21abe9f304f498 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-orig-2.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-3.png b/docs/html/images/distribute/stories/tapps-icon-orig-3.png new file mode 100644 index 0000000000000000000000000000000000000000..2f393f8ba965aae28d9c05474a23842ba6a42508 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-orig-3.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-var-1-2.png b/docs/html/images/distribute/stories/tapps-icon-var-1-2.png new file mode 100644 index 0000000000000000000000000000000000000000..fecab6e06f9014a09d05f4cf35f2bdb9c092b7a4 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-var-1-2.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-var-1.png b/docs/html/images/distribute/stories/tapps-icon-var-1.png new file mode 100644 index 0000000000000000000000000000000000000000..77bd02a17f6372310629e0a4c504766e7b57e193 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-var-1.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-var-2-2.png b/docs/html/images/distribute/stories/tapps-icon-var-2-2.png new file mode 100644 index 0000000000000000000000000000000000000000..84166c43c9f1b5d07c5842a0a96f7a861098d929 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-var-2-2.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-var-2.png b/docs/html/images/distribute/stories/tapps-icon-var-2.png new file mode 100644 index 0000000000000000000000000000000000000000..939c2fdf1b34fbe7484f50c567a4c3714cacb1cf Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-var-2.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-var-3-2.png b/docs/html/images/distribute/stories/tapps-icon-var-3-2.png new file mode 100644 index 0000000000000000000000000000000000000000..4aa782d0b9f9cedae19bad54c93980be3b53d891 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-var-3-2.png differ diff --git a/docs/html/images/distribute/stories/tapps-icon-var-3.png b/docs/html/images/distribute/stories/tapps-icon-var-3.png new file mode 100644 index 0000000000000000000000000000000000000000..1e44fdf7cfbcb27bec63f845ccb95412704d7c76 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-icon-var-3.png differ diff --git a/docs/html/images/distribute/stories/tapps-logic-pic.png b/docs/html/images/distribute/stories/tapps-logic-pic.png new file mode 100644 index 0000000000000000000000000000000000000000..5029f79ca610e725c94e747c8ec8558a3a45286d Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-logic-pic.png differ diff --git a/docs/html/images/distribute/stories/tapps-logo.png b/docs/html/images/distribute/stories/tapps-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e01e3adf596d361e2fa120cba97f7206d1ed08b2 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-logo.png differ diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-1.png b/docs/html/images/distribute/stories/tapps-screen-orig-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d54e75c8dd8091ed80785c31ea1974485441d634 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-screen-orig-1.png differ diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-2.png b/docs/html/images/distribute/stories/tapps-screen-orig-2.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d18e3cd0da3f91a240b9a2c0ec73d4c364551f Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-screen-orig-2.png differ diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-3.png b/docs/html/images/distribute/stories/tapps-screen-orig-3.png new file mode 100644 index 0000000000000000000000000000000000000000..e01fe20fb6b2fd6d1b5ac092b9c1d59d73e33d3d Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-screen-orig-3.png differ diff --git a/docs/html/images/distribute/stories/tapps-screen-var-1.png b/docs/html/images/distribute/stories/tapps-screen-var-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b93035093d3fa753513287041b4ece412927fc88 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-screen-var-1.png differ diff --git a/docs/html/images/distribute/stories/tapps-screen-var-2.png b/docs/html/images/distribute/stories/tapps-screen-var-2.png new file mode 100644 index 0000000000000000000000000000000000000000..9ccb8a647e4440e007b7d84494360ff0b4666ff1 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-screen-var-2.png differ diff --git a/docs/html/images/distribute/stories/tapps-screen-var-3.png b/docs/html/images/distribute/stories/tapps-screen-var-3.png new file mode 100644 index 0000000000000000000000000000000000000000..8eb58e1cb6d104da1af386ce1f567f816eea64cc Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-screen-var-3.png differ diff --git a/docs/html/images/distribute/stories/tapps-villains-corp.png b/docs/html/images/distribute/stories/tapps-villains-corp.png new file mode 100644 index 0000000000000000000000000000000000000000..6e037dad4f2321d3ae947e460e8eb47d67503129 Binary files /dev/null and b/docs/html/images/distribute/stories/tapps-villains-corp.png differ diff --git a/docs/html/images/distribute/stories/witch-puzzle-icon.png b/docs/html/images/distribute/stories/witch-puzzle-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c336f1bf16ef9d85b6ce24319b221b4fb37bb3c9 Binary files /dev/null and b/docs/html/images/distribute/stories/witch-puzzle-icon.png differ diff --git a/docs/html/images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png b/docs/html/images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..44a4e8688e87a41595eb004ad387d8d951552e9d Binary files /dev/null and b/docs/html/images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png differ diff --git a/docs/html/images/guide/topics/graphics/vectorpath.png b/docs/html/images/guide/topics/graphics/vectorpath.png new file mode 100644 index 0000000000000000000000000000000000000000..592bab67ecd933e7a7006a855ad3c189b111bf5b Binary files /dev/null and b/docs/html/images/guide/topics/graphics/vectorpath.png differ diff --git a/docs/html/images/home/nougat_bg.jpg b/docs/html/images/home/nougat_bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f2a239dee36aade44dee15e2c29f29ec388ae888 Binary files /dev/null and b/docs/html/images/home/nougat_bg.jpg differ diff --git a/docs/html/images/home/nougat_bg_2x.jpg b/docs/html/images/home/nougat_bg_2x.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5c7295e7438e92548c875d1d8031531f330de150 Binary files /dev/null and b/docs/html/images/home/nougat_bg_2x.jpg differ diff --git a/docs/html/images/paypal-logo.png b/docs/html/images/paypal-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..3e08b95cb52e80cb91611b42036a325650cbda63 Binary files /dev/null and b/docs/html/images/paypal-logo.png differ diff --git a/docs/html/images/tools/sdk-manager-support-libs.png b/docs/html/images/tools/sdk-manager-support-libs.png deleted file mode 100644 index 37968005c789e3126444af98a71743977cc5611d..0000000000000000000000000000000000000000 Binary files a/docs/html/images/tools/sdk-manager-support-libs.png and /dev/null differ diff --git a/docs/html/images/tools/studio-sdk-manager-packages.png b/docs/html/images/tools/studio-sdk-manager-packages.png deleted file mode 100644 index 79ea912e183a0ed0e8f93280f1f0063a06a252ca..0000000000000000000000000000000000000000 Binary files a/docs/html/images/tools/studio-sdk-manager-packages.png and /dev/null differ diff --git a/docs/html/images/topic/arc/sideload_figure_1.jpg b/docs/html/images/topic/arc/sideload_figure_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8eb5085041854762ead6e71368d4cb5797d2e579 Binary files /dev/null and b/docs/html/images/topic/arc/sideload_figure_1.jpg differ diff --git a/docs/html/images/training/ctl-config.png b/docs/html/images/training/ctl-config.png index 82f63c85274d7b50ed0ca6dd0c7ed24dd1f784d5..3a4f7385183c6917a7773d0010101c0a342beb5d 100644 Binary files a/docs/html/images/training/ctl-config.png and b/docs/html/images/training/ctl-config.png differ diff --git a/docs/html/images/training/performance/animation-frames.png b/docs/html/images/training/performance/animation-frames.png new file mode 100644 index 0000000000000000000000000000000000000000..846c9fe42159f1537696aef58c0016aa3006e999 Binary files /dev/null and b/docs/html/images/training/performance/animation-frames.png differ diff --git a/docs/html/images/training/performance/animation-frames_2x.png b/docs/html/images/training/performance/animation-frames_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0aba2a57931642048500ab687b93d6f6e317e484 Binary files /dev/null and b/docs/html/images/training/performance/animation-frames_2x.png differ diff --git a/docs/html/images/training/performance/apk-structure.png b/docs/html/images/training/performance/apk-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..75a180cd4711a451d66b5ab991751cb7e9e17e88 Binary files /dev/null and b/docs/html/images/training/performance/apk-structure.png differ diff --git a/docs/html/images/training/tv/playback/onboarding-fragment-diagram.png b/docs/html/images/training/tv/playback/onboarding-fragment-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..5839a50d572c6b112d898d1276060c503bca0575 Binary files /dev/null and b/docs/html/images/training/tv/playback/onboarding-fragment-diagram.png differ diff --git a/docs/html/images/training/tv/playback/onboarding-fragment.png b/docs/html/images/training/tv/playback/onboarding-fragment.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7da55c8422caced861259c1d666f6c5c4128e2 Binary files /dev/null and b/docs/html/images/training/tv/playback/onboarding-fragment.png differ diff --git a/docs/html/images/training/tv/playback/onboarding-fragment_2x.png b/docs/html/images/training/tv/playback/onboarding-fragment_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0034be44fbc861c99a75a3fbacb9076d3bb55b02 Binary files /dev/null and b/docs/html/images/training/tv/playback/onboarding-fragment_2x.png differ diff --git a/docs/html/images/training/tv/tif/app-link-2x.png b/docs/html/images/training/tv/tif/app-link-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d9d058231b142f74ae6e8dfc72275460551cb367 Binary files /dev/null and b/docs/html/images/training/tv/tif/app-link-2x.png differ diff --git a/docs/html/images/training/tv/tif/app-link-diagram.png b/docs/html/images/training/tv/tif/app-link-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..92328adfcd7c86db64da30557dcdb3f32e967e70 Binary files /dev/null and b/docs/html/images/training/tv/tif/app-link-diagram.png differ diff --git a/docs/html/images/training/tv/tif/app-link.png b/docs/html/images/training/tv/tif/app-link.png new file mode 100644 index 0000000000000000000000000000000000000000..7573a188b03e6476e1a16e15e651f5f3590351ed Binary files /dev/null and b/docs/html/images/training/tv/tif/app-link.png differ diff --git a/docs/html/index.jd b/docs/html/index.jd index b1248afa799edd3645a2e7b233646c3840fcfdd8..78fc84852f7c52b4654932cf2d76a95e37df0fd1 100644 --- a/docs/html/index.jd +++ b/docs/html/index.jd @@ -6,50 +6,36 @@ nonavpage=true @jd:body - - -

    -
    -
    - -

    Android N Developer Preview

    -

    - Android N final SDK is now available! - Get ready for the next version of Android! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. +

    +
    -
    +

    Build Beautiful Apps

    diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js deleted file mode 100644 index aa0620aefd0c3cf35a57ccfed3fd797d7f12785d..0000000000000000000000000000000000000000 --- a/docs/html/jd_collections.js +++ /dev/null @@ -1,1919 +0,0 @@ -/* - * THIS FILE IS DEPRECATED. - * - * Please add and edit resource collections in jd_extras_.js - * where lang matches the language code appropriate for the resource. - * Last sync'd with jd_extras_.js on 29 Apr 2016. - * - */ -var RESOURCE_COLLECTIONS = { - "index/carousel": { - "title": "", - "resources": [ - "about/versions/lollipop.html" - ] - }, - "index/primary": { - "title": "", - "resources": [ - "training/building-wearables.html", - "training/material/index.html", - "studio/index.html" - ] - }, - "index/secondary/carousel": { - "title": "", - "resources": [ - "http://www.youtube.com/watch?v=9m6MoBM-sFI", - "http://www.youtube.com/watch?v=Pms0pcyPbAM", - "http://www.youtube.com/watch?v=e7t3svG9PTk", - "http://www.youtube.com/watch?v=J3IvOfvH1ys" - ] - }, - "index/multiscreen": { - "title": "", - "resources": [ - "wear/index.html", - "tv/index.html", - "auto/index.html" - ] - }, - "index/primary/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/resources.html", - "intl/zh-cn/distribute/tools/launch-checklist.html", - "intl/zh-cn/distribute/tools/localization-checklist.html" - ] - }, - "design/landing/latest": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=p4gmvHyuZzw", - "https://www.youtube.com/watch?v=YaG_ljfzeUw", - "https://www.youtube.com/watch?v=XOcCOBe8PTc" - ] - }, - "design/landing/materialdesign": { - "title": "", - "resources": [ - "https://www.google.com/design/spec/animation/", - "https://www.google.com/design/spec/style/", - "https://www.google.com/design/spec/layout/", - "https://www.google.com/design/spec/components/", - "https://www.google.com/design/spec/patterns/", - "https://www.google.com/design/spec/usability/" - ] - }, - "design/landing/pureandroid": { - "title": "", - "resources": [ - "design/get-started/creative-vision.html", - "design/material/index.html", - "training/material/index.html", - "design/patterns/pure-android.html", - "design/patterns/new.html", - "design/devices.html" - ] - }, - "design/landing/resources": { - "title": "", - "resources": [ - "https://www.google.com/design/spec/resources/color-palettes.html", - "https://www.google.com/design/spec/resources/layout-templates.html", - "https://www.google.com/design/spec/resources/sticker-sheets-icons.html", - "https://www.google.com/design/spec/resources/roboto-noto-fonts.html", - "https://www.google.com/design/icons/index.html", - "design/downloads/index.html#Wear" - ] - }, - "develop/landing/mainlinks": { - "title": "", - "resources": [ - "tools/studio/index.html", - "samples/new/index.html", - "tools/projects/templates.html" - ] - }, - "develop/landing/latest": { - "title": "", - "resources": [ - "https://android-developers.blogspot.com/2015/04/new-android-code-samples.html", - "https://android-developers.blogspot.com/2015/04/android-support-library-221.html", - "https://android-developers.blogspot.com/2015/03/a-new-reference-app-for-multi-device.html" - ] - }, - "develop/landing/devpatterns": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=kmUGLURRPkI", - "https://www.youtube.com/watch?v=HGElAW224dE", - "https://www.youtube.com/watch?v=zQekzaAgIlQ" - ] - }, - "develop/landing/performance": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=fEEulSk1kNY", - "https://www.youtube.com/watch?v=-3ry8PxcJJA", - "https://www.youtube.com/watch?v=_kKTGK-Cb_4" - ] - }, - "develop/landing/buildwithgoogle": { - "title": "", - "resources": [ - ] - }, - "develop/landing/ubicomp": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=AK38PJZmIW8&list=PLWz5rJ2EKKc-kIrPiq098QH9dOle-fLef", - "https://www.youtube.com/watch?v=6K_jxccHv5M&index=1&list=PLOU2XLYxmsILFBfx66ens76VMLMEPJAB0", - "https://www.youtube.com/watch?v=ctiaVxgclsg&list=PLWz5rJ2EKKc9BdE_PSLNIGjXXr3h_orXM" - ] - }, - "develop/landing/tools": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=K2dodTXARqc&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "https://www.youtube.com/watch?v=cD7NPxuuXYY&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "https://www.youtube.com/watch?v=JLLnhwtDoHw&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "https://www.youtube.com/watch?v=2I6fuD20qlY&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "https://www.youtube.com/watch?v=5Be2mJzP-Uw&list=PLWz5rJ2EKKc9e0d55YHgJFHXNZbGHEXJX" - ] - }, - "preview/landing/resources": { - "title": "", - "resources": [ - "preview/overview.html", - "preview/api-overview.html", - "preview/behavior-changes.html", - "preview/setup-sdk.html", - "preview/samples.html", - "preview/support.html" - ] - }, - "preview/landing/more": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=CsulIu3UaUM", - "preview/features/multi-window.html", - "preview/features/notification-updates.html", - "preview/features/background-optimization.html", - "preview/features/data-saver.html", - "preview/features/direct-boot.html", - "preview/features/icu4j-framework.html", - "preview/features/multilingual-support.html", - "preview/features/scoped-folder-access.html", - "preview/features/picture-in-picture.html", - "preview/features/tv-recording-api.html" - ] - }, - "wear/preview/landing": { - "title": "", - "resources": [ - "wear/preview/api-overview.html", - "wear/preview/downloads.html", - "wear/preview/start.html" - ] - }, - "wear/preview/landing/resources": { - "title": "", - "resources": [ - "wear/preview/features/complications.html", - "wear/preview/features/notifications.html", - "wear/preview/features/ui-nav-actions.html" - ] - }, - "google/landing/services": { - "title": "", - "resources": [ - "https://developers.google.com/analytics/devguides/collection/android/", - "https://developers.google.com/maps/documentation/android/", - "https://developers.google.com/identity/sign-in/android/", - "https://developers.google.com/mobile-ads-sdk/download", - "https://developers.google.com/cloud-messaging/gcm", - "https://developers.google.com/app-indexing/" - ] - }, - "google/landing/videos": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=M3Udfu6qidk&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf", - "https://www.youtube.com/watch?v=FOn64iqlphk&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf", - "https://www.youtube.com/watch?v=F0Kh_RnSM0w&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf", - "https://www.youtube.com/watch?v=fvtMtfCuEpw&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf" - ] - }, - "google/landing/googleplay": { - "title": "", - "resources": [ - "google/play/billing/index.html", - "google/play/billing/billing_subscriptions.html", - "google/play/developer-api.html" - ] - }, - "develop/landing/courses": { - "title": "", - "resources": [ - "https://www.udacity.com/course/ud849", - "https://www.udacity.com/course/ud853", - "https://www.udacity.com/course/ud825", - "https://www.udacity.com/android", - "https://www.udacity.com/course/ud855", - "https://www.udacity.com/course/ud875A", - "https://www.udacity.com/course/ud875B", - "https://www.udacity.com/course/ud875C", - "https://www.udacity.com/course/ud876--1", - "https://www.udacity.com/course/ud876--2", - "https://www.udacity.com/course/ud876--3", - "https://www.udacity.com/course/ud876--4", - "https://www.udacity.com/course/ud876--5", - "https://www.udacity.com/course/ud862", - "https://www.udacity.com/course/ud837", - "https://www.udacity.com/course/ud867" - ] - }, - "distribute/landing/carousel": { - "title": "", - "resources": [ - "distribute/googleplay/guide.html", - "https://www.youtube.com/watch?v=JrR6o5tYMWQ", - "https://www.youtube.com/watch?v=B6ydLpkhq04&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS", - "https://www.youtube.com/watch?v=yJisuP94lHU", - ] - }, - "distribute/landing/googleplay": { - "title": "", - "resources": [ - "distribute/googleplay/about.html", - "distribute/googleplay/developer-console.html", - "distribute/googleplay/index.html#opportunities" - ] - }, - "distribute/landing/more": { - "title": "", - "resources": [ - "distribute/users/promote-with-ads.html", - "distribute/monetize/ads.html", - "distribute/analyze/index.html", - "distribute/engage/deep-linking.html", - "distribute/engage/easy-signin.html", - "https://cloud.google.com/docs/" - ] - }, - "distribute/edu/videos/stories": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=Idu7VcTTXfk", - "https://www.youtube.com/watch?v=iokH4SAIfRw" - ] - }, - "distribute/edu/videos/bestpractices": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=iulXz8QTD1g", - "https://www.youtube.com/watch?v=IKhU180eJMo", - "https://www.youtube.com/watch?v=_AZ6UcPz-_g", - "https://www.youtube.com/watch?v=Eh2adsAyTKc" - ] - }, - "distribute/edu/videos/experience": { - "title": "", - "resources": [ - "https://youtu.be/vzvpcEffvaE" - ] - }, -/* "launch/static": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=1RIz-cmTQB4", - "https://www.youtube.com/watch?v=MVBMWDzyHAI", - "https://android-developers.blogspot.com/2013/11/app-translation-service-now-available.html", - "https://android-developers.blogspot.com/2013/10/more-visibility-for-tablet-apps-in.html", - "https://android-developers.blogspot.com/2013/11/bring-your-apps-into-classroom-with.html", - "distribute/essentials/quality/tablets.html", - "distribute/users/build-buzz.html", - "distribute/monetize/premium.html", - "distribute/monetize/freemium.html", - "distribute/monetize/ads.html", - "distribute/essentials/best-practices/apps.html", - "distribute/essentials/best-practices/games.html", - "distribute/users/know-your-user.html", - "distribute/googleplay/developer-console.html" - ] - }, */ - "launch/static/ja": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=xelYnWcYkuE", - "https://www.youtube.com/playlist?list=PLCOC_kP3nqGIHEgwm9mybvA04Vn4Cg9nn", - "https://googledevjp.blogspot.jp/2014/12/android-wear.html", - "https://googledevjp.blogspot.jp/2014/12/android-studio-10.html", - "https://googledevjp.blogspot.jp/2014/12/google-play-65.html", - "intl/ja/distribute/googleplay/developer-console.html#alpha-beta", - "intl/ja/distribute/googleplay/guide.html", - "intl/ja/distribute/essentials/quality/core.html", - "https://support.google.com/googleplay/android-developer/answer/4430948?hl=ja", - "intl/ja/support.html", - "intl/ja/distribute/essentials/quality/wear.html", - "intl/ja/training/tv/start/index.html", - "https://googleforwork-japan.blogspot.jp/2014/12/gcp-google-cloud-platform-rpg-gcp.html", - "intl/ja/distribute/monetize/ads.html" - ] - }, - "launch/static/ko": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=7X9Ue0Nfdh4&index=2&list=PL_WJkTbDHdBksDBRoqfeyLchEQqBAOlNl", - "https://www.youtube.com/watch?v=83FpwuschCQ", - "https://googledevkr.blogspot.com/2014/11/android50guidefordevelopers.html", - "https://googledevkr.blogspot.com/2014/10/material-design-on-android-checklist.html", - "https://googledevkr.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html", - "intl/ko/distribute/googleplay/developer-console.html#alpha-beta", - "intl/ko/distribute/googleplay/guide.html", - "intl/ko/distribute/essentials/quality/core.html", - "https://support.google.com/googleplay/android-developer/answer/4430948?hl=ko", - "intl/ko/support.html", - "intl/ko/distribute/essentials/quality/wear.html", - "intl/ko/tv/index.html", - "intl/ko/google/play-services/games.html", - "intl/ko/distribute/monetize/ads.html" - ] - }, - "distribute/gp/gplanding": { - "resources": [ - "distribute/googleplay/about.html", - "distribute/googleplay/start.html", - "distribute/googleplay/developer-console.html" - ] - }, - "distribute/gp/gpfelanding": { - "resources": [ - "distribute/googleplay/wear.html", - "distribute/googleplay/tv.html", - "distribute/googleplay/auto.html", - "distribute/googleplay/families/about.html", - "distribute/googleplay/work/about.html", - "distribute/googleplay/edu/about.html", - "distribute/googleplay/cast.html", - "distribute/googleplay/cardboard.html", - "distribute/googleplay/guide.html" - ] - }, - "distribute/googleplay/gpfw": { - "resources": [ - "https://www.android.com/work/", - "https://www.youtube.com/watch?v=jQWB_-o1kz4&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX", - "work/index.html" - ] - }, - "distribute/essentials": { - "resources": [ - "distribute/essentials/quality/core.html", - "distribute/essentials/quality/tablets.html", - "distribute/essentials/quality/tv.html", - "distribute/essentials/quality/wear.html", - "distribute/essentials/quality/auto.html", - "distribute/essentials/quality/billions.html" - ] - }, - "distribute/essentials/zhcn": { - "resources": [ - "intl/zh-cn/distribute/essentials/quality/core.html", - "intl/zh-cn/distribute/essentials/quality/tablets.html", - "distribute/essentials/quality/tv.html", - "distribute/essentials/quality/wear.html", - "https://developers.google.com/edu/guidelines", - "distribute/essentials/optimizing-your-app.html" - ] - }, - "distribute/users": { - "title": "", - "resources": [ - "distribute/users/your-listing.html", - "distribute/users/promote-with-ads.html", - "distribute/googleplay/index.html#opportunities", - "distribute/analyze/improve-roi.html", - "distribute/users/expand-to-new-markets.html", - "distribute/analyze/index.html", - "distribute/users/app-invites.html", - "distribute/users/ota-installs.html", - "distribute/users/youtube.html", - "distribute/users/house-ads.html", - "distribute/users/experiments.html", - "distribute/users/user-acquisition.html", - "distribute/users/banners.html", - "distribute/users/beta.html" - ] - }, - "distribute/engagelanding": { - "resources": [ - "distribute/engage/intents.html", - "distribute/engage/widgets.html", - "distribute/engage/translate.html", - "distribute/engage/notifications.html", - "distribute/engage/deep-linking.html", - "distribute/engage/ads.html", - "distribute/engage/game-services.html", - "distribute/engage/easy-signin.html", - "distribute/analyze/build-better-apps.html", - "distribute/engage/gcm.html", - "distribute/engage/beta.html" - ] - }, - "distribute/monetize": { - "resources": [ - "distribute/monetize/premium.html", - "distribute/monetize/freemium.html", - "distribute/monetize/subscriptions.html", - "distribute/monetize/ads.html", - "distribute/monetize/ecommerce.html", - "distribute/monetize/payments.html", - "distribute/analyze/understand-user-value.html", - ] - }, - "distribute/analyzelanding": { - "resources": [ - "distribute/analyze/start.html", - "distribute/analyze/measure.html", - "distribute/analyze/understand-user-value.html", - "distribute/analyze/improve-roi.html", - "distribute/analyze/build-better-apps.html", - "distribute/analyze/google-services.html" - ] - }, - "distribute/analyzestart": { - "resources": [ - "https://analyticsacademy.withgoogle.com/course04", - "google/play-services/index.html", - "https://developers.google.com/analytics/solutions/mobile-implementation-guide", - "https://developers.google.com/analytics/devguides/collection/android/", - "https://www.google.com/tagmanager/", - "https://github.com/googleanalytics/google-analytics-plugin-for-unity" - ] - }, - "distribute/analyzemeasure": { - "resources": [ - - "https://developers.google.com/analytics/solutions/mobile-implementation-guide", - "https://developers.google.com/analytics/devguides/collection/android/v4/enhanced-ecommerce", - "https://support.google.com/analytics/answer/1032415", - "https://developers.google.com/analytics/devguides/collection/android/v4/events", - "https://developers.google.com/analytics/devguides/collection/android/v4/customdimsmets", - "https://developers.google.com/analytics/devguides/collection/android/v4/user-id" - ] - }, - "distribute/analyzeunderstand": { - "resources": [ - "https://developers.google.com/analytics/devguides/collection/android/v4/display-features", - "https://support.google.com/analytics/answer/3123906", - "https://support.google.com/analytics/answer/2568874?ref_topic=6012392", - "https://developers.google.com/analytics/devguides/collection/android/v4/enhanced-ecommerce", - "https://support.google.com/analytics/answer/1032415", - ] - }, - "distribute/analyzeimprove": { - "resources": [ - - "https://developers.google.com/analytics/devguides/collection/android/v4/campaigns", - "https://support.google.com/analytics/answer/2956981", - "https://support.google.com/analytics/answer/1033961", - "https://developers.google.com/analytics/devguides/collection/android/v4/campaigns#google-play-url-builder", - "https://developers.google.com/analytics/solutions/mobile-campaign-deep-link" - ] - }, - "distribute/analyzebuild": { - "resources": [ - "https://support.google.com/tagmanager/answer/6003007", - "https://support.google.com/analytics/answer/2785577", - "https://support.google.com/analytics/answer/1151300" - ] - }, - "distribute/analyzeact": { - "resources": [ - "https://support.google.com/analytics/answer/2611268", - "https://support.google.com/analytics/answer/1033961", - "https://support.google.com/admob/answer/3508177", - "https://support.google.com/analytics/answer/2956981", - "https://support.google.com/tagmanager/answer/6003007" - ] - }, - "distribute/essentials/guidelines": { - "title": "", - "resources": [ - "distribute/essentials/quality/core.html", - "distribute/essentials/quality/tablets.html", - "distribute/essentials/quality/wear.html", - "distribute/essentials/quality/tv.html", - "distribute/essentials/quality/auto.html", - "distribute/essentials/quality/billions.html" - ] - }, - "distribute/essentials/tools": { - "title": "", - "resources": [ - "distribute/tools/launch-checklist.html", - "distribute/tools/localization-checklist.html", - "https://support.google.com/googleplay/android-developer", - "distribute/tools/promote/brand.html", - "distribute/tools/promote/device-art.html", - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/linking.html", - "distribute/tools/open-distribution.html", - "about/dashboards/index.html" - ] - }, - "distribute/tools/checklists": { - "title": "", - "resources": [ - "distribute/tools/launch-checklist.html", - "distribute/tools/localization-checklist.html" - ] - }, - "distribute/tools/checklists/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/distribute/tools/launch-checklist.html", - "intl/zh-cn/distribute/tools/localization-checklist.html" - ] - }, - "distribute/tools/promote": { - "resources": [ - "distribute/tools/promote/device-art.html", - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/linking.html" - ] - }, - "distribute/tools/promote/zhcn": { - "resources": [ - "intl/zh-cn/distribute/tools/promote/device-art.html", - "https://play.google.com/intl/en_us/badges/", - "intl/zh-cn/distribute/tools/promote/linking.html" - ] - }, - "distribute/tools/support": { - "title": "Google Play", - "resources": [ - "https://support.google.com/googleplay/android-developer", - "https://support.google.com/googleplay/android-developer/answer/4430948", - "support.html" - ] - }, - "distribute/tools/support/zhcn": { - "title": "Google Play", - "resources": [ - "https://support.google.com/googleplay/android-developer?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/4430948?hl=zh-Hans", - "support.html" - ] - }, - "distribute/tools/news": { - "title": "", - "resources": [ - "https://android-developers.blogspot.com/", - "https://plus.google.com/+AndroidDevelopers/" - ] - }, - "distribute/tools/more": { - "title": "Google Play", - "resources": [ - "distribute/tools/promote/brand.html", - "distribute/tools/open-distribution.html", - "about/dashboards/index.html" - ] - }, - "distribute/tools/more/zhcn": { - "title": "Google Play", - "resources": [ - "intl/zh-cn/distribute/tools/promote/brand.html", - "distribute/tools/open-distribution.html", - "about/dashboards/index.html" - ] - }, - "distribute/googleplay": { - "title": "Google Play", - "resources": [ - "distribute/googleplay/developer-console.html", - "distribute/essentials/best-practices/apps.html", - "distribute/tools/launch-checklist.html", - "distribute/essentials/best-practices/games.html", - ] - }, - "distribute/googleplay/gettingstarted": { - "title": "Get Started", - "resources": [ - "distribute/googleplay/developer-console.html", - "https://support.google.com/googleplay/android-developer/answer/113468", - "https://support.google.com/googleplay/android-developer/answer/138294", - "https://support.google.com/googleplay/android-developer" - ] - }, - "distribute/googleplay/developerconsole/related": { - "title": "Developer Console", - "resources": [ - "google/play/billing/index.html", - "https://support.google.com/googleplay/android-developer/answer/138294" - ] - }, - "distribute/googleplay/beta": { - "title": "Alpha and Beta Testing", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/3131213", - "https://support.google.com/googleplay/android-developer/answer/3131213#games", - "distribute/googleplay/experiments.html" - ] - }, - "distribute/googleplay/experiments/successes": { - "title": "Store Listing Experiment successes", - "resources": [ - ] - }, - "distribute/googleplay/experiments/related": { - "title": "Store Listing Experiments", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/6227309", - "https://www.youtube.com/watch?v=B6ydLpkhq04", - "https://support.google.com/tagmanager/answer/6003007" - ] - }, - "distribute/googleplay/banners/related": { - "title": "App Install Banners", - "resources": [ - "https://developers.google.com/web/updates/2015/03/increasing-engagement-with-app-install-banners-in-chrome-for-android#native" - ] - }, - "distribute/googleplay/useracquisition/related": { - "title": "User Acquisition", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/6263332" - ] - }, - "distribute/googleplay/cast": { - "title": "Google Cast", - "resources": [ - "https://developers.google.com/cast/docs/ux_guidelines", - "https://developers.google.com/cast/docs/android_sender", - "https://www.github.com/googlecast" - ] - }, - "distribute/googleplay/cardboard": { - "title": "Google Cast", - "resources": [ - "https://www.google.com/get/cardboard/get-cardboard/", - "https://developers.google.com/cardboard/android/download", - "https://www.google.com/design/spec-vr" - ] - }, - "distribute/googleplay/gpfe/highlight": { - "title": "About Google Play for Education", - "resources": [ - "https://youtu.be/vzvpcEffvaE" - ] - }, - "distribute/googleplay/gpfe/dev/about": { - "title": "About Google Play for Education / Developers", - "resources": [ - "distribute/googleplay/edu/start.html", - "https://developers.google.com/edu/guidelines", - "https://developers.google.com/edu/faq", - "distribute/essentials/quality/tablets.html", - "https://developers.google.com/edu/", - "https://www.google.com/edu/tablets/#tablets-family" - ] - }, - "distribute/googleplay/gpfe/dev": { - "title": "About Google Play for Education / Developers", - "resources": [ - "distribute/googleplay/edu/about.html", - "https://developers.google.com/edu/guidelines", - "distribute/essentials/quality/tablets.html", - "distribute/googleplay/developer-console.html", - "https://play.google.com/about/developer-distribution-agreement-addendum.html", - ] - }, - "distribute/googleplay/aboutgpfe/educators/about": { - "title": "About Google Play for Education / Educators", - "resources": [ - "https://www.google.com/edu/tablets/", - "https://www.youtube.com/watch?v=haEmsMo0f3w" - ] - }, - "distribute/googleplay/aboutgpfe/educators": { - "title": "About Google Play for Education / Educators", - "resources": [ - "https://www.google.com/edu/tablets/", - "https://youtu.be/vzvpcEffvaE" - ] - }, - "distribute/googleplay/gettingstartedgpfe/educators": { - "title": "About Google Play for Education / Educators", - "resources": [ - "https://www.google.com/edu/tablets/", - "https://youtu.be/vzvpcEffvaE" - ] - }, - "distribute/essentials/eduessentials/developers": { - "title": "", - "resources": [ - "distribute/googleplay/developer-console.html", - "distribute/googleplay/edu/start.html", - "https://developers.google.com/edu/faq" - ] - }, - "distribute/essentials/eduessentials/educators": { - "title": "", - "resources": [ - "https://www.google.com/edu/tablets/", - "distribute/essentials/quality/tablets.html", - ] - }, - "distribute/essentials/optimizing": { - "title": "Optimizing Your App", - "resources": [ - "design/index.html", - "training/articles/perf-anr.html", - "https://android-developers.blogspot.com/2013/10/improved-app-insight-by-linking-google.html" - ] - }, - "distribute/users/appinvites": { - "title": "", - "resources": [ - "https://developers.google.com/app-invites/", - "https://developers.google.com/identity/sign-in/android/", - "https://developers.google.com/app-indexing/" - ] - }, - "distribute/users/knowyouruser": { - "title": "", - "resources": [ - "distribute/essentials/optimizing-your-app.html", - "http://www.youtube.com/watch?v=RRelFvc6Czo", - "distribute/stories/games/rvappstudios-zombie.html" - ] - }, - "distribute/users/promotewithads": { - "title": "", - "resources": [ - "https://support.google.com/adwords/answer/6032059", - "https://support.google.com/adwords/answer/6032073", - "https://support.google.com/adwords/answer/6167164", - "https://support.google.com/adwords/answer/6167162" - ] - }, - "distribute/users/buildbuzz": { - "title": "", - "resources": [ - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/linking.html", - "distribute/tools/promote/device-art.html", - "https://plus.google.com/+GooglePlay" - ] - }, - "distribute/users/createagreatlisting": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/1078870", - "https://android-developers.blogspot.com/2011/10/android-market-featured-image.html", - "distribute/tools/launch-checklist.html", - "https://android-developers.blogspot.com/2013/07/making-beautiful-android-app-icons.html", - "https://android-developers.blogspot.com/2012/12/localize-your-promotional-graphics-on.html", - "https://android-developers.blogspot.com/2013/10/making-your-app-content-more-accessible.html" - ] - }, - "distribute/users/buildcommunity": { - "title": "", - "resources": [ - "distribute/googleplay/developer-console.html", - "https://support.google.com/groups/answer/46601", - "https://support.google.com/plus/topic/2888488", - "https://www.youtube.com/yt/dev/" - ] - }, - "distribute/users/appindexing": { - "title": "", - "resources": [ - "https://developers.google.com/app-indexing/", - "https://developers.google.com/app-indexing/webmasters/details", - "distribute/engage/deep-linking.html", - "training/app-indexing/index.html" - ] - }, - "distribute/users/otas": { - "title": "", - "resources": [ - "https://developers.google.com/identity/sign-in/android/", - "https://developers.google.com/+/features/play-installs", - "https://developers.google.com/+/features/analytics" - ] - }, - "distribute/users/houseads": { - "title": "", - "resources": [ - "https://support.google.com/admob/topic/2784623", - "https://developers.google.com/mobile-ads-sdk/download", - "https://support.google.com/googleplay/android-developer/topic/2985714", - "https://analyticsacademy.withgoogle.com/mobile-app", - "https://support.google.com/analytics/answer/2611404", - "https://support.google.com/admob/answer/3111064" - ] - }, - "distribute/users/youtube": { - "title": "", - "resources": [ - "https://support.google.com/youtube/answer/6140493", - "https://support.google.com/youtube/answer/2797387" - ] - }, - "distribute/toolsreference/bestpractices/apps": { - "title": "", - "resources": [ - "distribute/googleplay/developer-console.html", - "https://android-developers.blogspot.com/" - ] - }, - "distribute/toolsreference/bestpractices/games": { - "title": "", - "resources": [ - "google/play-services/games.html", - "https://android-developers.blogspot.com/", - "distribute/googleplay/developer-console.html", - "https://www.youtube.com/watch?v=1RIz-cmTQB4" - ] - }, - "distribute/essentials/corequalityguidelines/visualdesign": { - "title": "", - "resources": [ - "design/index.html", - "design/patterns/navigation.html", - "design/patterns/actionbar.html", - "design/style/iconography.html", - "design/patterns/notifications.html" - ] - }, - "distribute/essentials/corequalityguidelines/functionality": { - "title": "", - "resources": [ - "https://android-developers.blogspot.com/2011/11/making-android-games-that-play-nice.html", - "guide/components/tasks-and-back-stack.html", - "training/basics/activity-lifecycle/recreating.html" - ] - }, - "distribute/essentials/tvqualityguidelines/visualdesign": { - "title": "", - "resources": [ - "design/tv/index.html", - "training/tv/start/index.html" - ] - }, - "distribute/essentials/tvqualityguidelines/functionality": { - "title": "", - "resources": [ - "training/tv/start/hardware.html", - "training/tv/games/index.html" - ] - }, - "distribute/essentials/wearqualityguidelines/visualdesign": { - "title": "", - "resources": [ - "design/wear/index.html", - "training/building-wearables.html", - "training/wearables/ui/index.html" - ] - }, - "distribute/essentials/wearqualityguidelines/functionality": { - "title": "", - "resources": [ - "training/wearables/notifications/index.html", - "training/wearables/apps/index.html", - "training/wearables/notifications/voice-input.html" - ] - }, - "distribute/essentials/autoqualityguidelines/visualdesign": { - "title": "", - "resources": [ - "training/auto/messaging/index.html", - "training/auto/start/index.html" - ] - }, - "distribute/essentials/core/performance": { - "title": "", - "resources": [ - "https://android-developers.blogspot.com/2010/12/new-gingerbread-api-strictmode.html", - "training/articles/perf-anr.html", - "https://android-developers.blogspot.com/2010/07/multithreading-for-performance.html" - ] - }, - "distribute/essentials/core/play": { - "title": "", - "resources": [ - "distribute/tools/launch-checklist.html", - "https://play.google.com/about/developer-content-policy.html?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/188189?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/1078870?hl=zh-Hans", - "https://android-developers.blogspot.com/2011/10/android-market-featured-image.html", - "https://support.google.com/googleplay/android-developer/answer/113477?hl=zh-Hans" - ] - }, - "distribute/essentials/core/play/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/distribute/tools/launch-checklist.html", - "https://play.google.com/about/developer-content-policy.html", - "https://support.google.com/googleplay/android-developer/answer/188189?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/1078870?hl=zh-Hans", - "https://android-developers.blogspot.com/2011/10/android-market-featured-image.html", - "https://support.google.com/googleplay/android-developer/answer/113477?hl=zh-Hans" - ] - }, - "distribute/essentials/tabletguidelines/optimize": { - "title": "", - "resources": [ - "design/style/metrics-grids.html", - "design/style/devices-displays.html", - "guide/practices/screens_support.html", - //"guide/practices/screens_support.html#ConfigurationExamples", - ] - }, - "distribute/essentials/tabletguidelines/extrascreen": { - "title": "", - "resources": [ - "design/patterns/multi-pane-layouts.html", - "training/design-navigation/multiple-sizes.html", - "training/multiscreen/index.html", - ] - }, - "distribute/essentials/tabletguidelines/assets": { - "title": "", - "resources": [ - "design/style/iconography.html", - "guide/topics/resources/providing-resources.html", - "guide/practices/screens_support.html", - "training/basics/supporting-devices/screens.html" - ] - }, - "distribute/essentials/tabletguidelines/fonts": { - "title": "", - "resources": [ - "design/style/metrics-grids.html", - "design/style/typography.html", - "guide/practices/screens_support.html", - "training/multiscreen/screendensities.html" - ] - }, - "distribute/essentials/tabletguidelines/widgets": { - "title": "", - "resources": [ - "guide/topics/appwidgets/index.html#MetaData", - "guide/topics/appwidgets/index.html", - "design/patterns/widgets.html" - ] - }, - "distribute/essentials/tabletguidelines/versions": { - "title": "", - "resources": [ - "guide/topics/manifest/uses-sdk-element.html#ApiLevels", - "guide/topics/manifest/uses-sdk-element.html", - "training/basics/supporting-devices/platforms.html" - ] - }, - "distribute/essentials/tabletguidelines/hardware": { - "title": "", - "resources": [ - "guide/topics/manifest/uses-feature-element.html", - "guide/topics/manifest/uses-feature-element.html#testing" - ] - }, - "distribute/essentials/tabletguidelines/tabletscreens": { - "title": "", - "resources": [ - "guide/practices/screens_support.html#DeclaringScreenSizeSupport", - "guide/practices/screens_support.html" - ] - }, - "distribute/essentials/tabletguidelines/showcase": { - "title": "", - "resources": [ - "distribute/tools/launch-checklist.html", - "https://play.google.com/apps/publish/", - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/device-art.html" - ] - }, - "distribute/essentials/tabletguidelines/showcase/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/distribute/tools/launch-checklist.html", - "https://play.google.com/apps/publish/?hl=zh-Hans", - "https://play.google.com/intl/en_us/badges/", - "intl/zh-cn/distribute/tools/promote/device-art.html" - ] - }, - "distribute/essentials/tabletguidelines/googleplay": { - "title": "", - "resources": [ - "https://android-developers.blogspot.com/2013/10/more-visibility-for-tablet-apps-in.html", - "google/play/filters.html" - ] - }, - "distribute/essentials/billionsquality/connectivity": { - "title": "", - "resources": [ - "training/basics/network-ops/managing.html", - "training/monitoring-device-state/connectivity-monitoring.html", - "guide/topics/providers/content-providers.html" - ] - }, - "distribute/essentials/billionsquality/capability": { - "title": "", - "resources": [ - "guide/practices/screens_support.html", - "training/multiscreen/screendensities.html", - "training/articles/memory.html" - ] - }, - "distribute/essentials/billionsquality/cost": { - "title": "", - "resources": [ - "https://medium.com/@wkalicinski/smallerapk-part-6-image-optimization-zopfli-webp-4c462955647d#.23hlddo3x", - "training/basics/network-ops/managing.html" - ] - }, - "distribute/essentials/billionsquality/consumption": { - "title": "", - "resources": [ - "training/efficient-downloads/efficient-network-access.html", - "training/monitoring-device-state/index.html" - ] - }, - "distribute/essentials/billionsquality/content": { - "title": "", - "resources": [ - "training/material/animations.html#Touch", - "training/articles/perf-anr.html", - "training/improving-layouts/index.html" - ] - }, - "distribute/essentials/tabletguidelines": { - "title": "", - "resources": [ - "distribute/essentials/quality/core.html", - "https://android-developers.blogspot.com/2013/10/more-visibility-for-tablet-apps-in.html", - "distribute/tools/launch-checklist.html", - "distribute/tools/promote/device-art.html" - ] - }, - "distribute/getusers/notifications": { - "title": "", - "resources": [ - "design/patterns/notifications.html", - "distribute/engage/gcm.html", - "https://play.google.com/about/developer-content-policy.html" - ] - }, - "distribute/engage/analytics": { - "title": "", - "resources": [ - "https://www.google.com/analytics/mobile/", - "https://android-developers.blogspot.com/2013/10/improved-app-insight-by-linking-google.html", - "https://developers.google.com/analytics/devguides/collection/android/" - ] - }, - "distribute/engage/widgets": { - "title": "", - "resources": [ - "design/patterns/widgets.html", - "guide/topics/appwidgets/index.html" - ] - }, - "distribute/engage/translate": { - "title": "", - "resources": [ - "https://support.google.com/l10n/answer/6359997" - ] - }, - "distribute/engage/reengage": { - "title": "", - "resources": [ - "https://support.google.com/adwords/answer/6032073", - "distribute/engage/deep-linking.html", - "https://support.google.com/adwords/answer/6167162", - "distribute/users/promote-with-ads.html" - ] - }, - "distribute/engage/appindexing": { - "title": "", - "resources": [ - "distribute/engage/intents.html", - "distribute/engage/deep-linking.html", - "training/app-indexing/index.html" - ] - }, - "distribute/engage/intents": { - "title": "", - "resources": [ - "guide/components/intents-filters.html", - "distribute/engage/deep-linking.html", - "distribute/engage/ads.html" - ] - }, - "distribute/getusers/expandnewmarkets": { - "title": "", - "resources": [ - "distribute/tools/localization-checklist.html", - "https://support.google.com/googleplay/android-developer/table/3541286", - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/device-art.html", - "https://www.youtube.com/watch?v=SkHHPf3EdzE" - ] - }, - "distribute/engage/gcm": { - "title": "", - "resources": [ - "https://developers.google.com/cloud-messaging/gcm", - "https://developers.google.com/cloud-messaging/android/client", - ] - }, - "distribute/engage/gamesservices/related": { - "title": "", - "resources": [ - "https://developers.google.com/games/services/", - "distribute/analyze/start.html", - "distribute/googleplay/cardboard.html", - "https://www.google.com/admob/" - ] - }, - "distribute/engage/gplus": { - "title": "", - "resources": [ - "distribute/users/ota-installs.html", - "https://developers.google.com/identity/sign-in/android/people", - "https://developers.google.com/+/mobile/android/" - ] - }, - "distribute/engage/community": { - "title": "", - "resources": [ - "distribute/users/build-community.html", - "distribute/engage/video.html" - ] - }, - "distribute/engage/deeplinks": { - "title": "", - "resources": [ - "distribute/engage/easy-signin.html", - "https://developers.google.com/app-indexing/", - "https://developers.google.com/+/mobile/android/share/interactive-post" - ] - }, - "distribute/engage/appupdates": { - "title": "", - "resources": [ - "distribute/essentials/optimizing-your-app.html", - "distribute/tools/launch-checklist.html", - "distribute/googleplay/developer-console.html", - "design/patterns/notifications.html" - ] - }, - "distribute/engage/video/more": { - "title": "", - "resources": [ - "https://www.youtube.com/yt/dev/", - "distribute/essentials/best-practices/games.html", - "https://www.youtube.com/watch?v=RRelFvc6Czo" - ] - }, - "distribute/engage/community": { - "title": "", - "resources": [ - "distribute/users/build-community.html", - "distribute/engage/video.html" - ] - }, - "distribute/engage/kiwi": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=WWArLD6nqrk" - ] - }, - "distribute/toolsreference/gpfefaq": { - "title": "", - "resources": [ - "https://www.google.com/edu/tablets/", - "distribute/googleplay/edu/start.html", - "https://play.google.com/about/developer-distribution-agreement-addendum.html", - "distribute/essentials/quality/core.html", - "distribute/essentials/quality/tablets.html" - ] - }, - "distribute/toolsreference/localizationchecklist/identifylocales": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/138294" - ] - }, - "distribute/toolsreference/localizationchecklist/identifylocales/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/138294?hl=zh-Hans" - ] - }, - "distribute/tools/loc/designforloc": { - "title": "", - "resources": [ - "https://android-developers.blogspot.com/2013/03/native-rtl-support-in-android-42.html", - "guide/topics/resources/string-resource.html#Plurals", - "guide/topics/resources/string-resource.html", - "reference/java/util/Locale.html" - ] - }, - "distribute/toolsreference/localizationchecklist/managestrings": { - "title": "", - "resources": [ - "guide/topics/resources/string-resource.html", - "design/style/writing.html", - "https://en.wikipedia.org/wiki/XLIFF" - ] - }, - "distribute/toolsreference/localizationchecklist/managestrings/zhcn": { - "title": "", - "resources": [ - "guide/topics/resources/string-resource.html", - "intl/zh-cn/design/style/writing.html", - "https://en.wikipedia.org/wiki/XLIFF" - ] - }, - "distribute/toolsreference/localizationchecklist/preplaunch": { - "title": "", - "resources": [ - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/device-art.html" - ] - }, - "distribute/toolsreference/localizationchecklist/preplaunch/zhcn": { - "title": "", - "resources": [ - "https://play.google.com/intl/en_us/badges/", - "intl/zh-cn/distribute/tools/promote/device-art.html" - ] - }, - "distribute/toolsreference/localizationchecklist/supportlaunch": { - "title": "", - "resources": [ - "distribute/tools/launch-checklist.html", - ] - }, - "distribute/toolsreference/localizationchecklist/supportlaunch/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/distribute/tools/launch-checklist.html", - ] - }, - "distribute/toolsreference/launchchecklist/understanding": { - "title": "", - "resources": [ - "tools/publishing/publishing_overview.html", - "tools/publishing/preparing.html" - ] - }, - "distribute/toolsreference/launchchecklist/policies": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/4430948", - "https://support.google.com/googleplay/android-developer/topic/2364761", - "https://support.google.com/googleplay/android-developer" - ] - }, - "distribute/toolsreference/launchchecklist/quality": { - "title": "", - "resources": [ - "distribute/essentials/quality/core.html", - "distribute/essentials/quality/tablets.html", - "https://developers.google.com/edu/guidelines" - ] - }, - "distribute/toolsreference/launchchecklist/rating": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/188189", - ] - }, - "distribute/toolsreference/launchchecklist/country": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/138294" - ] - }, - "distribute/toolsreference/launchchecklist/size": { - "title": "", - "resources": [ - "google/play/expansion-files.html", - "tools/help/proguard.html" - ] - }, - "distribute/toolsreference/launchchecklist/platform": { - "title": "", - "resources": [ - "guide/practices/screens_support.html", - "about/dashboards/index.html", - "guide/topics/manifest/uses-sdk-element.html" - ] - }, - "distribute/toolsreference/launchchecklist/price": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/table/3541286", - ] - }, - "distribute/toolsreference/launchchecklist/purchasemethod": { - "title": "", - "resources": [ - "google/play/billing/index.html", - "google/play/billing/billing_subscriptions.html" - ] - }, - "distribute/toolsreference/launchchecklist/setprice": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/1169947", - "https://support.google.com/googleplay/android-developer/answer/138412", - "https://support.google.com/googleplay/android-developer/answer/112622", - "https://support.google.com/googleplay/android-developer/answer/138000" - ] - }, - "distribute/toolsreference/launchchecklist/localization": { - "title": "", - "resources": [ - "distribute/tools/localization-checklist.html", - "https://support.google.com/l10n/answer/6359997" - ] - }, - "distribute/toolsreference/launchchecklist/graphics": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/1078870", - "https://android-developers.blogspot.com/2011/10/android-market-featured-image.html" - ] - }, - "distribute/toolsreference/launchchecklist/productdetails": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/113475", - "https://support.google.com/googleplay/android-developer/answer/1078870" - ] - }, - "distribute/toolsreference/launchchecklist/badges": { - "title": "", - "resources": [ - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/linking.html" - ] - }, - "distribute/toolsreference/launchchecklist/finalchecks": { - "title": "", - "resources": [ - "https://play.google.com/about/developer-content-policy.html", - "https://support.google.com/googleplay/android-developer/answer/113476", - "support.html" - ] - }, - "distribute/toolsreference/launchchecklist/afterlaunch": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/113477", - "https://support.google.com/googleplay/android-developer/answer/1153479", - "https://support.google.com/payments/answer/2741495", - "distribute/essentials/optimizing-your-app.html" - ] - }, - "distribute/toolsreference/launchchecklist/understanding/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/tools/publishing/publishing_overview.html", - "intl/zh-cn/tools/publishing/preparing.html" - ] - }, - "distribute/toolsreference/launchchecklist/policies/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/4430948?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/topic/2364761?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer?hl=zh-Hans" - ] - }, - "distribute/toolsreference/launchchecklist/quality/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/distribute/essentials/quality/core.html", - "intl/zh-cn/distribute/essentials/quality/tablets.html", - "https://developers.google.com/edu/guidelines?hl=zh-Hans" - ] - }, - - "distribute/toolsreference/launchchecklist/rating/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/188189?hl=zh-Hans", - ] - }, - "distribute/toolsreference/launchchecklist/country/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/138294?hl=zh-Hans" - ] - }, - "distribute/toolsreference/launchchecklist/size/zhcn": { - "title": "", - "resources": [ - "google/play/expansion-files.html", - "intl/zh-cn/tools/help/proguard.html" - ] - }, - "distribute/toolsreference/launchchecklist/price/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/table/3541286?hl=zh-Hans", - ] - }, - "distribute/toolsreference/launchchecklist/purchasemethod/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/google/play/billing/index.html", - "google/play/billing/billing_subscriptions.html" - ] - }, - "distribute/toolsreference/launchchecklist/setprice/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/1169947?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/138412?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/112622?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/138000?hl=zh-Hans" - ] - }, - "distribute/stories/localization": { - "title": "", - "resources": [ - "distribute/stories/games/rvappstudios-zombie.html", - "distribute/stories/games/g4a-indian-rummy.html", - "distribute/stories/apps/sayhi.html" - ] - }, - "distribute/toolsreference/launchchecklist/localization/zhcn": { - "title": "", - "resources": [ - "intl/zh-cn/distribute/tools/localization-checklist.html", - ] - }, - "distribute/toolsreference/launchchecklist/graphics/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/1078870?hl=zh-Hans", - "https://android-developers.blogspot.com/2011/10/android-market-featured-image.html" - ] - }, - "distribute/toolsreference/launchchecklist/productdetails/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/113475?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/1078870?hl=zh-Hans" - ] - }, - "distribute/toolsreference/launchchecklist/badges/zhcn": { - "title": "", - "resources": [ - "https://play.google.com/intl/en_us/badges/", - "intl/zh-cn/distribute/tools/promote/linking.html" - ] - }, - "distribute/toolsreference/launchchecklist/finalchecks/zhcn": { - "title": "", - "resources": [ - "https://play.google.com/about/developer-content-policy.html", - "https://support.google.com/googleplay/android-developer/answer/113476?hl=zh-Hans", - "support.html" - ] - }, - "distribute/toolsreference/launchchecklist/afterlaunch/zhcn": { - "title": "", - "resources": [ - "https://support.google.com/googleplay/android-developer/answer/113477?hl=zh-Hans", - "https://support.google.com/googleplay/android-developer/answer/1153479?hl=zh-Hans", - "https://support.google.com/payments/answer/2741495?hl=zh-Hans", - "distribute/essentials/optimizing-your-app.html" - ] - }, - "distribute/monetize/premium": { - "title": "", - "resources": [ - "google/play/billing/index.html", - "https://support.google.com/googleplay/android-developer/answer/4407611" - ] - }, - "distribute/monetize/freemium": { - "title": "", - "resources": [ - "google/play/billing/index.html", - "https://support.google.com/googleplay/android-developer/answer/4407611" - ] - }, - "distribute/monetize/subscriptions": { - "title": "", - "resources": [ - "google/play/billing/billing_subscriptions.html", - "https://support.google.com/googleplay/android-developer/answer/4407611" - ] - }, - "distribute/monetize/ecommerce": { - "title": "", - "resources": [ - "https://developers.google.com/wallet/instant-buy/", - "https://support.google.com/googleplay/android-developer/answer/4407611" - ] - }, - "distribute/monetize/advertising": { - "title": "", - "resources": [ - "https://www.google.com/ads/admob/#subid=us-en-et-dac", - "https://www.google.com/doubleclick/publishers/small-business/index.html", - "https://support.google.com/googleplay/android-developer/topic/2985714", - "training/monetization/ads-and-ux.html" - ] - }, - "distribute/monetize/admob": { - "title": "", - "resources": [ - "https://support.google.com/admob/topic/2784623", - "https://admob.blogspot.com/", - "https://analyticsacademy.withgoogle.com/mobile-app", - "https://www.udacity.com/courses/ud876-3" - ] - }, - "distribute/monetize/paymentmethods": { - "title": "", - "resources": [ - "https://play.google.com/about/giftcards/", - "https://support.google.com/googleplay/answer/2651410" - ] - }, - "autolanding": { - "title": "", - "resources": [ - "auto/index.html", - "design/auto/index.html", - "training/auto/index.html" - ] - }, - "tvlanding": { - "title": "", - "resources": [ - "tv/index.html", - "design/tv/index.html", - "training/tv/index.html" - ] - }, - "wearlanding": { - "title": "", - "resources": [ - "design/wear/index.html", - "training/building-wearables.html", - "training/wearables/ui/index.html" - ] - }, - "design/auto/auto_ui_guidelines": { - "title": "", - "resources": [ - "shareables/auto/AndroidAuto-audio-apps.pdf", - "shareables/auto/AndroidAuto-messaging-apps.pdf", - "shareables/auto/AndroidAuto-custom-colors.pdf" - ] - }, - "training/auto/overview": { - "title": "", - "resources": [ - "training/auto/start/index.html", - "design/auto/index.html", - "shareables/auto/AndroidAuto-custom-colors.pdf" - ] - }, - "training/auto/messaging": { - "title": "", - "resources": [ - "training/auto/messaging/index.html", - "shareables/auto/AndroidAuto-messaging-apps.pdf", - "samples/MessagingService/index.html" - ] - }, - "training/auto/media": { - "title": "", - "resources": [ - "training/auto/audio/index.html", - "shareables/auto/AndroidAuto-audio-apps.pdf", - "samples/MediaBrowserService/index.html" - ] - }, - "training/auto/distribute": { - "title": "", - "resources": [ - "distribute/essentials/quality/auto.html", - "distribute/googleplay/auto.html" - ] - }, - "training/testing/overview": { - "title": "", - "resources": [ - "training/testing/start/index.html", - "tools/testing/testing_android.html", - "https://www.youtube.com/watch?v=vdasFFfXKOY" - ] - }, - "training/testing/tools": { - "title": "", - "resources": [ - "tools/testing-support-library/index.html", - "tools/help/monkey.html", - "tools/help/monkeyrunner_concepts.html", - "tools/testing/testing_otheride.html", - "https://source.android.com/devices/tech/debug/dumpsys.html" - ] - }, - "training/testing/techniques": { - "title": "", - "resources": [ - "training/testing/ui-testing/index.html", - "training/testing/unit-testing/index.html", - "training/testing/performance.html" - ] - }, - "training/testing/resources": { - "title": "", - "resources": [ - "https://github.com/googlesamples/android-testing", - "https://www.youtube.com/watch?v=2I6fuD20qlY", - "https://codelabs.developers.google.com/codelabs/android-testing/index.html", - "https://github.com/googlesamples/android-testing-templates", - "https://google.github.io/android-testing-support-library" - ] - }, - "distribute/stories/games": { - "title": "", - "resources": [ - "https://storage.googleapis.com/androiddevelopers/shareables/stories/Glu_Deerhunter2014_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/ConcreteSoftware_PBABowling_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/Dragonplay_DragonplaySlots_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/Gameloft_Asphalt8_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/Glu_EternityWarriors3_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/HotheadGames_RivalsatWar_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/TMSOFT_Compulsive_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/Noodlecake_SuperStickmanGolf2_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/TinyRebel_DoctorWhoLegacy_gpgs.pdf", - "https://storage.googleapis.com/androiddevelopers/shareables/stories/Senri_LeosFortune_gpgs.pdf" - ] - }, - "overview/zhcn/1": { - "title": "", - "resources": [ - "intl/zh-cn/distribute/essentials/quality/core.html", - "intl/zh-cn/distribute/essentials/quality/tablets.html", - "intl/zh-cn/distribute/tools/launch-checklist.html", - "intl/zh-cn/tools/publishing/publishing_overview.html", - "intl/zh-cn/distribute/tools/localization-checklist.html" - ] - }, - "overview/zhcn/2": { - "title": "", - "resources": [ - "intl/zh-cn/google/play/billing/index.html", - "intl/zh-cn/google/play/billing/api.html", - "intl/zh-cn/google/play/billing/billing_admin.html", - "intl/zh-cn/google/play/billing/billing_testing.html", - "intl/zh-cn/google/play/billing/billing_best_practices.html" - ] - }, - "overview/zhcn/3": { - "title": "", - "resources": [ - "https://play.google.com/intl/en_us/badges/", - - "intl/zh-cn/distribute/tools/promote/device-art.html", - "intl/zh-cn/distribute/tools/promote/linking.html", - "intl/zh-cn/distribute/tools/promote/brand.html", - "intl/zh-cn/tools/help/proguard.html" - ] - }, - "overview/zhcn/4": { - "title": "", - "resources": [ - "intl/zh-cn/design/style/writing.html", - "intl/zh-cn/training/basics/fragments/fragment-ui.html", - "intl/zh-cn/training/multiscreen/index.html", - "intl/zh-cn/training/monitoring-device-state/index.html" - ] - }, - "overview/carousel/zhcn": { - "title": "", - "resources": [ - "https://www.youtube.com/watch?v=vGV7FHGzpFU", - "https://www.youtube.com/watch?v=aqc3ZOTzpdk", - "https://www.youtube.com/watch?v=jaNrJ8uyLSc" - ] - }, - "overview/1": { - "title": "", - "resources": [ - "distribute/essentials/quality/core.html", - "distribute/essentials/quality/tablets.html", - "distribute/tools/launch-checklist.html", - "tools/publishing/publishing_overview.html", - "distribute/tools/localization-checklist.html" - ] - }, - "overview/2": { - "title": "", - "resources": [ - "google/play/billing/index.html", - "google/play/billing/api.html", - "google/play/billing/billing_admin.html", - "google/play/billing/billing_testing.html", - "google/play/billing/billing_best_practices.html" - ] - }, - "overview/3": { - "title": "", - "resources": [ - "https://play.google.com/intl/en_us/badges/", - "distribute/tools/promote/device-art.html", - "distribute/tools/promote/linking.html", - "distribute/tools/promote/brand.html", - "tools/help/proguard.html" - ] - }, - "overview/4": { - "title": "", - "resources": [ - "design/style/writing.html", - "training/basics/fragments/fragment-ui.html", - "training/multiscreen/index.html", - "training/monitoring-device-state/index.html" - ] - }, -"tools/help/log": { - "title": "", - "resources": [ - "tools/help/am-logcat.html" - ] - }, -"tools/help/monitor": { - "title": "", - "resources": [ - "tools/help/am-memory.html", - "tools/help/am-cpu.html", - "tools/help/am-gpu.html", - "tools/help/am-network.html" - ] - }, - "tools/help/data": { - "title": "", - "resources": [ - "tools/help/am-hprof.html", - "tools/help/am-allocation.html", - "tools/help/am-methodtrace.html", - "tools/help/am-sysinfo.html" - ] - }, - "tools/help/shot": { - "title": "", - "resources": [ - "tools/help/am-screenshot.html", - "tools/help/am-video.html" - ] - }, - "tools/performance/rendering": { - "title": "", - "resources": [ - "tools/performance/debug-gpu-overdraw/index.html", - "tools/performance/profile-gpu-rendering/index.html", - "tools/performance/hierarchy-viewer/setup.html", - "tools/performance/hierarchy-viewer/index.html", - "tools/performance/hierarchy-viewer/profiling.html" - ] - }, - "tools/performance/memory": { - "title": "", - "resources": [ - "tools/performance/memory-monitor/index.html", - "tools/performance/heap-viewer/index.html", - "tools/performance/allocation-tracker/index.html", - "tools/performance/comparison.html" - ] - }, - "tools/performance/cpu": { - "title": "", - "resources": [ - "tools/performance/traceview/index.html", - "tools/performance/systrace/index.html" - ] - }, - "tools/performance/battery": { - "title": "", - "resources": [ - "tools/performance/batterystats-battery-historian/index.html", - "tools/performance/batterystats-battery-historian/charts.html" - ] - }, - "marshmallow/landing/resources": { - "title": "", - "resources": [ - "about/versions/marshmallow/android-6.0-changes.html", - "about/versions/marshmallow/android-6.0.html", - "about/versions/marshmallow/samples.html" - ] - }, - "marshmallow/landing/videos": { - "title": "", - "resources": [ - "https://youtu.be/U9tw5ypqEN0", - "https://youtu.be/N72ksDKrX6c", - "https://youtu.be/iZqDdvhTZj0", - "https://www.youtube.com/watch?v=vcSj8ln-BlE", - "https://youtu.be/LQoohRwojmw", - "https://www.youtube.com/watch?v=VOn7VrTRlA4", - "https://youtu.be/5sCQjeGoE7M", - "https://www.youtube.com/watch?v=C8lUdPVSzDk", - "https://www.youtube.com/watch?v=HXacyy0HSW0", - "https://www.youtube.com/watch?v=OW1A4XFRuyc", - "https://www.youtube.com/watch?v=j3QC6hcpy90", - "https://www.youtube.com/watch?v=f17qe9vZ8RM", - "https://www.youtube.com/watch?v=ndBdf1_oOGA" - ] - }, - "marshmallow/landing/more": { - "title": "", - "resources": [ - "training/permissions/requesting.html", - "training/backup/autosyncapi.html", - "training/monitoring-device-state/doze-standby.html", - "training/app-links/index.html", - "training/articles/assistant.html", - "training/testing/performance.html", - "https://developers.google.com/android/nexus/images" - ] - }, - "tools/landing/resources": { - "title": "", - "resources": [ - "tools/studio/index.html", - "tools/studio/studio-features.html", - "studio/intro/index.html", - ] - }, - "tools/landing/latest": { - "title": "", - "resources": [ - "https://medium.com/google-developers/how-often-should-you-update-android-studio-db25785c488e#.8blbql35x", - "http://android-developers.blogspot.com/2016/04/android-studio-2-0.html", - "https://medium.com/google-developers/writing-more-code-by-writing-less-code-with-android-studio-live-templates-244f648d17c7#.hczcm02du", - ] - }, - "work/landing/primary": { - "title": "", - "resources": [ - "work/overview.html", - "work/guide.html", - "https://www.google.com/work/android/developers/applyDevHub/", - "work/managed-configurations.html", - "work/cosu.html", - "work/managed-profiles.html" - ] - }, - "work/landing/resources": { - "title": "", - "resources": [ - "https://developers.google.com/android/work/", - "https://www.google.com/work/android/", - "https://developers.google.com/android/work/build-dpc", - "https://www.youtube.com/watch?v=jQWB_-o1kz4&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX", - "https://www.youtube.com/watch?v=Za0OQo8DRM4", - "https://www.youtube.com/watch?v=dH41OutAMNM&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX" - ] - }, - "work/apps": { - "title": "", - "resources": [ - "work/managed-profiles.html", - "work/managed-configurations.html", - "work/cosu.html", - "https://www.youtube.com/watch?v=39NkpWkaH8M&index=2&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX", - "samples/AppRestrictionSchema/index.html", - "samples/AppRestrictionEnforcer/index.html" - ] - }, - "work/admin": { - "title": "", - "resources": [ - "https://developers.google.com/android/work/build-dpc", - "samples/BasicManagedProfile/index.html", - "https://www.youtube.com/watch?v=j3QC6hcpy90" - ] - } -}; diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js deleted file mode 100644 index e5347d9704921d9576d30bc4ef659623fa701f68..0000000000000000000000000000000000000000 --- a/docs/html/jd_extras.js +++ /dev/null @@ -1,4029 +0,0 @@ -/* - * THIS FILE IS DEPRECATED. - * - * Please add and edit resource collections in jd_extras_.js - * where lang matches the language code appropriate for the resource. - * Last sync'd with jd_extras_.js on 29 Apr 2016. - * - */ -DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([ - /* TODO Remove standard resources from here, such as below - */ - { - "title":"Writing More Code by Writing Less Code with Android Studio Live Templates", - "titleFriendly":"", - "summary":"Unless you’re getting paid by the keystroke, no one wants to write repetitive boilerplate code.", - "url":"https://medium.com/google-developers/writing-more-code-by-writing-less-code-with-android-studio-live-templates-244f648d17c7#.hczcm02du", - "group":"", - "keywords": [], - "tags": ['studio'], - "image":"https://cdn-images-1.medium.com/max/800/1*JkrYXGs1AxZAbK0sCLrJAQ.gif", - "type":"medium" - }, - { - "title":"How Often Should You Update Android Studio?", - "titleFriendly":"", - "summary":"One of the beauties of Android Studio is how quickly is evolves and improves.", - "url":"https://medium.com/google-developers/how-often-should-you-update-android-studio-db25785c488e#.8blbql35x", - "group":"", - "keywords": [], - "tags": ['studio'], - "image":"https://cdn-images-1.medium.com/max/2000/1*chMiA9mGa_FBUOoesHHk3Q.png", - "type":"medium" - }, - { - "title":"SmallerAPK, Part 6: Image optimization, Zopfli & WebP", - "category":"", - "summary":"Series of posts on minimizing your APK size.", - "url":"https://medium.com/@wkalicinski/smallerapk-part-6-image-optimization-zopfli-webp-4c462955647d#.23hlddo3x", - "group":"", - "keywords": [], - "tags": [], - "image":"https://cdn-images-1.medium.com/max/2000/1*chMiA9mGa_FBUOoesHHk3Q.png", - "type":"medium" - }, - { - "title":"Measure your app’s user acquisition channels", - "titleFriendly":"", - "summary":"Get details on how to use the Developer Console User Acquisitions reports to discover where your users come from.", - "url":"https://support.google.com/googleplay/android-developer/answer/6263332", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Set up native app install banners in Chrome", - "titleFriendly":"", - "summary":"Get the details you need to add your native app or game to your site’s web app manifest file.", - "url":"https://developers.google.com/web/updates/2015/03/increasing-engagement-with-app-install-banners-in-chrome-for-android#native", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Optimize your store listing pages with experiments", - "titleFriendly":"", - "summary":"You can run experiments to find the most effective graphics and localized text for your app.", - "url":"https://support.google.com/googleplay/android-developer/answer/6227309", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Content Experiments for Mobile Apps", - "titleFriendly":"", - "summary":"Google Analytics Content Experiments allows you to test multiple variations of a given web page.", - "url":"https://support.google.com/tagmanager/answer/6003007", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Store Listing Experiments for Google Play", - "titleFriendly":"", - "summary":"Learn how to use Google Play’s new store listing optimization feature to get more installs of your app.", - "url":"https://www.youtube.com/watch?v=B6ydLpkhq04", - "group":"", - "keywords": [], - "tags": [], - "image":"https://i1.ytimg.com/vi/B6ydLpkhq04/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Use alpha/beta testing & staged rollouts", - "titleFriendly":"", - "summary":"Using the Google Play Developer Console, you can choose groups of users to test different versions of your app.", - "url":"https://support.google.com/googleplay/android-developer/answer/3131213", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Quizlet Developer Story", - "titleFriendly":"", - "summary":"Quizlet is an extremely popular online learning tool for students. See how they optimized for the classroom with Android and the power of Google Play for Education.", - "url":"https://www.youtube.com/watch?v=Idu7VcTTXfk", - "group":"", - "keywords": [], - "tags": [ - "#gpfe", - "#googleplay" - ], - "image":"https://i1.ytimg.com/vi/Idu7VcTTXfk/maxresdefault.jpg", - "type":"video" - }, - { - "title":"What's New in GPFE", - "titleFriendly":"", - "summary":"Learn about the vision and philosophy behind Google Play for Education", - "url":"https://www.youtube.com/watch?v=IKhU180eJMo", - "group":"", - "keywords": [], - "tags": [ - "#gpfe", - "#googleplay" - ], - "image":"https://i1.ytimg.com/vi/IKhU180eJMo/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Get started with Google Cast", - "titleFriendly":"", - "summary":"Build multi-screen experiences, let the user send video and audio content to TVs and speakers.", - "url":"https://developers.google.com/cast/docs/ux_guidelines", - "group":"", - "keywords": ["cast", "chromecast", "video", "audio"], - "tags": [], - "image":"images/cards/card-cast_2x.jpg", - "type":"Guide" - }, - { - "title":"Android Sender Applications", - "titleFriendly":"", - "summary":"Get an overview of how your Android app can act as a Google Cast sender app.", - "url":"https://developers.google.com/cast/docs/android_sender", - "group":"", - "keywords": ["cast", "sender"], - "tags": [], - "image":"images/cards/card-cast_2x.jpg", - "type":"Guide" - }, - { - "title":"Cast sample apps", - "titleFriendly":"", - "summary":"Get example Google Cast applications for both senders and receivers.", - "url":"https://www.github.com/googlecast", - "group":"", - "keywords": ["cast", "samples"], - "tags": [], - "image":"images/cards/card-cast_2x.jpg", - "type":"Samples" - }, - { - "title":"Get Cardboard", - "titleFriendly":"", - "summary":"Get your own Cardboard, today. Buy one from a manufacturer or build your own, and start developing.", - "url":"https://www.google.com/get/cardboard/get-cardboard/", - "group":"", - "keywords": ["carboard","vr"], - "tags": [], - "image":"images/cards/card-cardboard_2x.png", - "type":"Guide" - }, - { - "title":"Download the Cardboard SDK", - "titleFriendly":"", - "summary":"Grab the Cardboard libraries from GitHub and start creating VR apps in your favorite development environment.", - "url":"https://developers.google.com/cardboard/android/download", - "group":"", - "keywords": ["carboard","vr"], - "tags": [], - "image":"images/cards/card-cardboard_2x.png", - "type":"Guide" - }, - { - "title":"Cardboard design guidelines", - "titleFriendly":"", - "summary":"Focus on overall usability and avoiding common VR pitfalls while creating an immersive experience of your own.", - "url":"https://www.google.com/design/spec-vr", - "group":"", - "keywords": ["carboard","vr"], - "tags": [], - "image":"images/cards/card-cardboard_2x.png", - "type":"Design" - }, - { - "title":"Maps", - "titleFriendly":"", - "summary":"Give users the map that more than a billion people use every month.", - "url":"https://developers.google.com/maps/documentation/android/", - "group":"", - "keywords": ["maps"], - "tags": [], - "image":"images/google/gps-maps.png", - "type":"Guide" - }, - { - "title":"Places API", - "titleFriendly":"", - "summary":"give your users contextual information about where they are, when they’re there.", - "url":"https://developers.google.com/places/android/", - "group":"", - "keywords": ["places","location", "context"], - "tags": [], - "image":"images/cards/card-places_2x.png", - "type":"Guide" - }, - { - "title":"GCM Client for Android", - "titleFriendly":"", - "summary":"Send push notifications and pubsub from your server to Android devices around the world.", - "url":"https://developers.google.com/cloud-messaging/android/client", - "group":"", - "keywords": ["push","gcm"], - "tags": [], - "image":"images/cards/card-google-cloud-messaging_16-9_2x.png", - "type":"Guide" - }, - { - "title":"Google Cloud Messaging", - "titleFriendly":"", - "summary":"Learn about GCM and the kinds of services you can offer to users through push notifications", - "url":"https://developers.google.com/cloud-messaging/gcm", - "group":"", - "keywords": ["push","gcm"], - "tags": [], - "image":"images/cards/card-google-cloud-messaging_16-9_2x.png", - "type":"Guide" - }, - { - "title":"ClassDojo Developer Story", - "titleFriendly":"", - "summary":"ClassDojo is a classroom tool that helps teachers improve behavior in their classrooms quickly and easily. See how they optimized for the classroom with Android and the power of Google Play for Education.", - "url":"https://www.youtube.com/watch?v=iokH4SAIfRw", - "group":"", - "keywords": [], - "tags": [ - "#gpfe", - "#googleplay" - ], - "image":"https://i1.ytimg.com/vi/iokH4SAIfRw/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Plan for Success", - "titleFriendly":"", - "summary":"5 tips from developers on creating great EDU apps.", - "url":"https://www.youtube.com/watch?v=Eh2adsAyTKc", - "group":"", - "keywords": [], - "tags": [ - "#gpfe", - "#googleplay" - ], - "image":"https://i1.ytimg.com/vi/Eh2adsAyTKc/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Optimizing Apps for Education", - "titleFriendly":"", - "summary":"Learn how to optimize your app for teachers and students.", - "url":"https://www.youtube.com/watch?v=_AZ6UcPz-_g", - "group":"", - "keywords": [], - "tags": [ - "#gpfe", - "#googleplay" - ], - "image":"https://i1.ytimg.com/vi/_AZ6UcPz-_g/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Ideas and Tools for Building Innovative Education Apps", - "titleFriendly":"", - "summary":"Are you hungry to build an awesome app for education but don't quite know where to start? Come hear about apps that teachers want, and the APIs you're going to need to build them! In particular, we'll talk about app ideas that combine APIs for Google Drive, Google Login, Android Single Task Mode and more to build transformative Educational apps that will delight educators and kids in and out of the classroom.", - "url":"https://www.youtube.com/watch?v=iulXz8QTD1g", - "group":"", - "keywords": [], - "tags": [ - "#gpfe", - "#googleplay" - ], - "image":"https://i1.ytimg.com/vi/iulXz8QTD1g/maxresdefault.jpg", - "type":"video" - }, - { - "title":"DesignBytes: Intro To Material Design", - "titleFriendly":"", - "summary":"These days, UI designers need to be thinking about phones, tablets, laptops, TVs, smartwatches, and beyond. In this DesignByte we talk about how Google designers have been working on making cross-platform and multi-screen design easier. We wanted to build a design system that felt at home on every screen, from the smallest watch to the largest TV.", - "url":"https://www.youtube.com/watch?v=p4gmvHyuZzw", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/p4gmvHyuZzw/maxresdefault.jpg", - "type":"video" - }, - { - "title":"DesignBytes: Paper and Ink: The Materials that Matter", - "titleFriendly":"", - "summary":"Join Rich Fulcher to learn about the materials of material design. See how virtual paper and ink form the foundation of your tactile user interface and master the rules that govern their behaviour.", - "url":"https://www.youtube.com/watch?v=YaG_ljfzeUw", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/YaG_ljfzeUw/maxresdefault.jpg", - "type":"video" - }, - { - "title":"DesignBytes: Material Design in the Google I/O App", - "titleFriendly":"", - "summary":"Roman Nurik shares details on the design process for the Google I/O 2014 app. To check out the app's source code, visit github.com/google/iosched.", - "url":"https://www.youtube.com/watch?v=XOcCOBe8PTc", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/XOcCOBe8PTc/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Toolbars for a flexible Action Bar & more", - "titleFriendly":"", - "summary":"Toolbars are a flexible View you can add to your Android app which provides many of the same APIs as the system provided Action Bar, but can also do so much more such as reacting to scrolling or being integrated directly into your layouts.", - "url":"https://www.youtube.com/watch?v=kmUGLURRPkI", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/kmUGLURRPkI/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Protecting Implicit Intents with Runtime Checks", - "titleFriendly":"", - "summary":"Make sure you protect your implicit intents with a simple runtime check.", - "url":"https://www.youtube.com/watch?v=HGElAW224dE", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/HGElAW224dE/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Tabs and ViewPager", - "titleFriendly":"", - "summary":"Showing multiple screens or pages of content is easy with the help of ViewPager and a PagerAdapter. Combining that with tabs make for an effective top level navigation strategy for your app or for moving between content at the same level of hierarchy within your app.", - "url":"https://www.youtube.com/watch?v=zQekzaAgIlQ", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/zQekzaAgIlQ/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Battery Drain and Networking", - "titleFriendly":"", - "summary":"Let’s take a moment to make something insanely clear: As far as battery is concerned, NETWORKING is the biggest, baddest, dirtiest offender there is. And optimizing performance here isn’t easy. Since the chip isn’t always awake and draining power, means you can optimize how it wakes up, sends traffic, and saves battery.", - "url":"https://www.youtube.com/watch?v=fEEulSk1kNY", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/fEEulSk1kNY/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Batching Background Work Until Later", - "titleFriendly":"", - "summary":"Yes, your app is special. But when it comes to battery use, sometimes it’s better to be part of the crowd. Why not spread the battery blame around a bit? Ian Ni-Lewis shows you how ridiculously easy it is to go from battery hog to team player in this video.", - "url":"https://www.youtube.com/watch?v=-3ry8PxcJJA", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/-3ry8PxcJJA/maxresdefault.jpg", - "type":"video" - }, - { - "title":"The Performance Lifecycle", - "titleFriendly":"", - "summary":"Performance problems surface in your application at the least-wanted times (like right before you’re about to ship your first build). But don’t freak out: There’s a simple process that you can follow to help get your performance back under control.", - "url":"https://www.youtube.com/watch?v=_kKTGK-Cb_4", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/_kKTGK-Cb_4/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Introduction to Android Studio", - "titleFriendly":"", - "summary":"Learn why you should migrate your projects to Android Studio now and how it can help you be more productive as a developer. Rich layout editor, handy suggestions and fixes, new Android project view - these are just some of the things you can expect from the IDE, which is built on the successful IntelliJ IDEA.", - "url":"https://www.youtube.com/watch?v=K2dodTXARqc&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "group":"", - "keywords": ["studio", "tools"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/K2dodTXARqc/maxresdefault.jpg", - "type":"video" - }, - - { - "title":"Google Play Services 7.5", - "titleFriendly":"", - "summary":"This update brings App Invites, topics to GCM, GCMNetworkManager, Cast Remote Display API, Smart Lock for Passwords, Maps API for Android Wear, Google Fit extensions and more.", - "url":"https://www.youtube.com/watch?v=M3Udfu6qidk&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf", - "group":"", - "keywords": ["google play services"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/M3Udfu6qidk/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Google Play Services 7.3", - "titleFriendly":"", - "summary":"This update brings the ability to connect multiple wearables simultaneously to a single phone. There are also some great new updates to Google Fit, including nutrition types, and to Location.", - "url":"https://www.youtube.com/watch?v=FOn64iqlphk&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf", - "group":"", - "keywords": ["google play services"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/FOn64iqlphk/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Google Play Services 6.5", - "titleFriendly":"", - "summary":"Google Play services 6.5 includes new features in Google Maps, Google Drive and Google Wallet as well as the recently launched Google Fit API. ", - "url":"https://www.youtube.com/watch?v=fvtMtfCuEpw&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf", - "group":"", - "keywords": ["google play services"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/fvtMtfCuEpw/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Google Play Services 7.0", - "titleFriendly":"", - "summary":"Google Play services 7.0 is here! we've added the Places API, made enhancements to Location and Google Fit, and you can also remote control your Android TV through the new Nearby Connections API.", - "url":"https://www.youtube.com/watch?v=F0Kh_RnSM0w&list=PLWz5rJ2EKKc9Qk1_iCZNbBp6adYnJf9Vf", - "group":"", - "keywords": ["google play services"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/F0Kh_RnSM0w/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Running a Successful Games Business with Google", - "titleFriendly":"", - "summary":"Sure, we all want to make the next great gaming masterpiece. But we also want to feed our families and/or dogs. Join Bob Meese from the Google Play team as he gives you some key pointers on how to make sure you're best taking advantage of Google Play and running a successful games business.", - "url":"https://www.youtube.com/watch?v=tDmnGNkTtlE", - "group":"", - "keywords": [], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/tDmnGNkTtlE/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Introduction to Android TV", - "titleFriendly":"", - "summary":"Android TV brings the Android platform to the living room with rich content and entertaining app experiences. In this video, Timothy introduces the design philosophy and developer components that make building TV experiences easier than ever before.", - "url":"https://www.youtube.com/watch?v=6K_jxccHv5M&index=1&list=PLOU2XLYxmsILFBfx66ens76VMLMEPJAB0", - "group":"", - "keywords": ["tv"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/6K_jxccHv5M/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Introduction to Android Auto", - "titleFriendly":"", - "summary":"Android Auto brings the Android platform to the car in a way that's optimized for the driving experience. It's the same platform you already use for phones, tablets, televisions, wearables, and more. ", - "url":"https://www.youtube.com/watch?v=ctiaVxgclsg&list=PLWz5rJ2EKKc9BdE_PSLNIGjXXr3h_orXM", - "group":"", - "keywords": ["auto"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/ctiaVxgclsg/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Debugging and testing in Android Studio", - "titleFriendly":"", - "summary":"This video introduces the state of unit testing support in Studio and Google’s new Android Testing Support Library for functional UI testing and running instrumented tests on a device.", - "url":"https://www.youtube.com/watch?v=2I6fuD20qlY", - "group":"", - "keywords": ["testing"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/2I6fuD20qlY/maxresdefault.jpg", - "type":"video" - }, - { - "title":"Android Testing (Android Dev Summit 2015)", - "titleFriendly":"", - "summary":"Overview of the testing tools and frameworks provided by Google and how they can help you to iterate more quickly and maintain a more healthy codebase.", - "url":"https://www.youtube.com/watch?v=vdasFFfXKOY", - "group":"", - "keywords": ["testing"], - "tags": [ - ], - "image":"https://i1.ytimg.com/vi/vdasFFfXKOY/maxresdefault.jpg", - "type":"video" - }, - { - "title":"dumpsys", - "titleFriendly":"", - "summary":"A tool that runs on the device and provides information about the status of system services.", - "url":"https://source.android.com/devices/tech/debug/dumpsys.html", - "group":"", - "keywords": ["testing"], - "tags": [ - ], - "image":"", - "type":"google" - }, - { - "title":"Android Testing Samples", - "titleFriendly":"", - "summary":"A collection of samples demonstrating different frameworks and techniques for automated testing.", - "url":"https://github.com/googlesamples/android-testing", - "group":"", - "keywords": ["testing"], - "tags": [ - ], - "image":"images/testing/testing-icon.png", - "type":"Samples" - }, - { - "title":"Android Testing Templates", - "titleFriendly":"", - "summary":"A collection of Google's Android testing tools and frameworks, all integrated in a single application project.", - "url":"https://github.com/googlesamples/android-testing-templates", - "group":"", - "keywords": ["testing"], - "tags": [ - ], - "image":"images/testing/testing-icon.png", - "type":"Samples" - }, - { - "title":"Android Testing Support Library (GitHub)", - "titleFriendly":"", - "summary":"A resource page on GitHub for the Android Testing Support Library.", - "url":"https://google.github.io/android-testing-support-library", - "group":"", - "keywords": ["testing"], - "tags": [ - ], - "image":"images/testing/testing-icon.png", - "type":"Samples" - }, - { - "title":"Android Testing Codelab", - "titleFriendly":"", - "summary":"This codelab shows how to build an Android app from the ground up in Android Studio, using a Model View Presenter architecture, Unit Tests and Instrumentation Tests.", - "url":"https://codelabs.developers.google.com/codelabs/android-testing/index.html", - "group":"", - "keywords": ["testing"], - "tags": [ - ], - "image":"images/testing/testing-icon.png", - "type":"google" - }, - { - "title":"Developer Registration", - "titleFriendly":"", - "summary":"Additional information about the registration process.", - "url":"https://support.google.com/googleplay/android-developer/answer/113468", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title": "Google Play Distribution and Seller Countries", - "titleFriendly":"", - "summary": "List of countries and territories where you can distribute your apps in Google Play.", - "url":"https://support.google.com/googleplay/android-developer/answer/138294", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title": "支持向Google Play用户发布应用的地区", - "lang": "zh-cn", - "titleFriendly":"", - "summary": "支持向Google Play用户发布应用的国家/地区。", - "url":"https://support.google.com/googleplay/android-developer/answer/138294?hl=zh-Hans", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Google Play Content Policies", - "titleFriendly":"", - "summary":"Details on policies relating to your developer account and app distribution is governed.", - "url":"https://support.google.com/googleplay/android-developer/topic/3453577", - "group":"", - "keywords": [], - "tags": ["#developersupport"], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Google Play Badge Generator", - "titleFriendly":"", - "summary":"Build badges for your app in just a few clicks, or download hi-res badge assets localized for a variety of languages.", - "url":"https://play.google.com/intl/en_us/badges/", - "group":"", - "keywords": [], - "tags": ["#developersupport"], - "image":"images/gp-badges-set.png", - "type":"google" - }, - { - "lang": "en", - "group": "", - "tags": ["#developersupport #termsandpolicies"], - "url": "https://support.google.com/googleplay/android-developer/answer/4407611", - "timestamp": 1194884220000, - "image": 'images/play_dev.jpg', - "title": "Google Play Terms and Policies", - "summary": "Developer terms and policies that apply when you distribute apps in Google Play.", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "title":"Google Play Policy Center", - "titleFriendly":"", - "summary":"A central resource for you to learn about Google Play policies and guidelines.", - "url":"https://support.google.com/googleplay/android-developer/answer/4430948", - "group":"", - "keywords": [], - "tags": [], - "image":"https://storage.googleapis.com/support-kms-prod/SNP_712EA2784949DDF085C46E3BE7B1DC618A09_4389397_en_v0", - "type":"google" - }, - { - "title":"Google Play应用政策中心", - "titleFriendly":"", - "summary":"一个方便你了解Google Play政策和指南的中心资源。", - "url":"https://support.google.com/googleplay/android-developer/answer/4430948?hl=zh-Hans", - "group":"", - "keywords": [], - "tags": [], - "image":"https://storage.googleapis.com/support-kms-prod/SNP_712EA2784949DDF085C46E3BE7B1DC618A09_4389397_en_v0", - "type":"google" - }, - { - "title":"Developer Help Center", - "titleFriendly":"", - "summary":"Complete details on getting started, publishing, troubleshooting, and more.", - "url":"https://support.google.com/googleplay/android-developer", - "group":"", - "keywords": [], - "tags": [], - "image":"images/cards/google-play_2x.png", - "type":"google" - }, - { - "title":"开发者帮助中心", - "titleFriendly":"", - "summary":"完整资料帮助开发者新手入手,发布,故障排除,等等", - "url":"https://support.google.com/googleplay/android-developer?hl=zh-Hans", - "group":"", - "keywords": [], - "tags": [], - "image":"images/play_dev.jpg", - "type":"google" - }, - { - "title":"Google for Education", - "titleFriendly":"", - "summary":"Find out more about how Google can support your work with apps and tablets.", - "url":"https://www.google.com/edu/tablets/", - "group":"", - "keywords": [], - "tags": [], - "image":"distribute/images/gp-edu-apps-image.jpg", - "type":"google" - }, - { - "title":"Keeping Your App Responsive", - "titleFriendly":"", - "summary":"This document describes how the Android system determines whether an application is not responding and provides guidelines for ensuring that your application stays responsive.", - "url":"training/articles/perf-anr.html", - "group":"", - "keywords": [], - "tags": [], - "image":"", - "type":"google" - }, - { - "title":"Google Play Game Services", - "titleFriendly":"", - "summary":"Make your games social with Google Play game services. Add achievements, leaderboards, real-time multiplayer, and other popular features using the Google Play game services SDK.", - "url":"https://developers.google.com/games/services/", - "group":"", - "keywords": ["games","play games"], - "tags": [], - "image":"images/google/gps-play_games_logo.png", - "type":"google" - }, - { - "title":"Get Started with Analytics", - "titleFriendly":"", - "summary":"Get advanced insight into how players discover and play your games.", - "url":"distribute/analyze/start.html", - "group":"", - "keywords": ["analytics"], - "tags": [], - "image": "images/cards/analytics-mobile_2x.jpg", - "type": "distribute" - }, - { - "title":"Build VR with Google Cardboard", - "titleFriendly":"", - "summary":"Turn any phone into a virtual reality headset with a Cardboard viewer and experiment with adding virtual reality to your games with the Cardboard SDK.", - "url":"distribute/googleplay/cardboard.html", - "group":"", - "keywords": ["cardboard"], - "tags": [], - "image":"images/cards/card-cardboard_2x.png", - "type": "distribute" - }, - { - "title":"Monetize your apps intelligently", - "titleFriendly":"", - "summary":"Generate revenue from your free games with ads tailored to match your game's look and feel.", - "url":"https://www.google.com/admob/", - "group":"", - "keywords": ["AdMob"], - "tags": [], - "image":"images/cards/admob-analytics_2x.png", - "type": "distribute" - }, - { - "lang": "en", - "group": "", - "tags": [ - "versions", "blog", "googleplay" - ], - "url": "https://android-developers.blogspot.com/", - "timestamp": 1004884220000, - "image": "images/blog.jpg", - "title": "Android Developers Blog", - "summary": "Follow the latest news on Android design, development, and distribution.", - "keywords": [], - "type": "blog", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://android-developers.blogspot.com/2011/11/making-android-games-that-play-nice.html", - "timestamp": 1194884220000, - "image": null, - "title": "Making Android Apps that Play Nice", - "summary": "Audio lifecycle and expected audio behaviors for Android apps.", - "keywords": [], - "type": "blog", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://android-developers.blogspot.com/2010/07/multithreading-for-performance.html", - "timestamp": 1194884220000, - "image": null, - "title": "Multithreading for Performance", - "summary": "Ways to improve performance through multi-threading.", - "keywords": [], - "type": "blog", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://play.google.com/about/developer-content-policy.html", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Developer Program Policies", - "summary": "Guidelines acceptable content in Google Play. Please read and understand the policies before publishing.", - "keywords": [], - "type": "google", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/188189", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Rating your application content for Google Play", - "summary": "How to choose the appropriate content ratings level for your apps.", - "keywords": [], - "type": "support", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["devices", "nexus", "testing"], - "url": "https://developers.google.com/android/nexus/images", - "timestamp": 1194884220000, - "image": "images/cards/card-download_16-9_2x.png", - "title": "Factory Images for Nexus Devices", - "summary": "System image files for Android 6.0 and other Android releases.", - "keywords": ["nexus, downloads"], - "type": "support", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/188189?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "针对Google Play为你的应用内容分级", - "summary": "如何为你的应用内容分级。", - "keywords": [], - "type": "support", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://android-developers.blogspot.com/2011/10/android-market-featured-image.html", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Google Play Featured Image Guidelines", - "summary": "How to create attractive, effective Featured Images for your apps.", - "keywords": [], - "type": "support", - "titleFriendly": "" - }, -{ - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/113477", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Supporting your users", - "summary": "Options for supporting users.", - "keywords": [], - "type": "support", - "titleFriendly": "" - }, -{ - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/113477?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "为用户提供支持", - "summary": "为用户提供支持的各种选择。", - "keywords": [], - "type": "support", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/practices/screens_support.html#ConfigurationExamples", - "timestamp": 1194884220000, - "image": null, - "title": "Configuration examples", - "summary": "How to declare layouts and other resources for specific screen sizes.", - "keywords": [], - "type": "design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "training/design-navigation/multiple-sizes.html", - "timestamp": 1194884220000, - "image": null, - "title": "Planning for Multiple Touchscreen Sizes", - "summary": "", - "keywords": [], - "type": "design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "training/multiscreen/index.html", - "timestamp": 1194884220000, - "image": null, - "title": "Designing for Multiple Screens", - "summary": "Designing an intuitive, effective navigation for tablets and other devices.", - "keywords": [], - "type": "design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/topics/resources/providing-resources.html", - "timestamp": 1194884220000, - "image": null, - "title": "Providing Resources", - "summary": "Layouts and drawable resources for specific ranges of device screens.", - "keywords": [], - "type": "design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "training/basics/supporting-devices/screens.html", - "timestamp": 1194884220000, - "image": null, - "title": "Supporting Different Screens", - "summary": "Optimizing the user experience for different screen sizes and densities.", - "keywords": [], - "type": "design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/topics/appwidgets/index.html#MetaData", - "timestamp": 1194884220000, - "image": null, - "title": "Adding the AppWidgetProviderInfo Metadata", - "summary": "How to set the height and width dimensions of a widget.", - "keywords": [], - "type": "design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/topics/manifest/uses-sdk-element.html#ApiLevels", - "timestamp": 1194884220000, - "image": null, - "title": "Android API Levels", - "summary": "Introduction to API levels and how they relate to compatibility.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/practices/screens_support.html#DeclaringScreenSizeSupport", - "timestamp": 1194884220000, - "image": null, - "title": "Declaring screen size support", - "summary": "How to declare support for screen sizes in your app\'s manifest.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "training/material/animations.html#Touch", - "timestamp": 1194884220000, - "image": null, - "title": "Customize Touch Feedback", - "summary": "Provide visual confirmation when users interact with your UI.", - "keywords": [], - "type": "develop", - "category": "guide" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/topics/manifest/uses-feature-element.html#testing", - "timestamp": 1194884220000, - "image": null, - "title": "Checking for hardware feature requirements", - "summary": "Determining an app’s hardware and software requirements.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://play.google.com/apps/publish/", - "timestamp": 1194884220000, - "image": null, - "title": "Google Play Developer Console", - "summary": "The tools console for publishing your app.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://play.google.com/apps/publish/?hl=zh-Hans", - "timestamp": 1194884220000, - "image": null, - "title": "Google Play 开发者控制台", - "summary": "发布应用的开发者控制台", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://youtu.be/SkHHPf3EdzE", - "timestamp": 1194884220000, - "image": "https://i1.ytimg.com/vi/SkHHPf3EdzE/maxresdefault.jpg", - "title": "Level Up Your Android Game", - "summary": "Learn how to take your game to the next level on Google Play.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/+/mobile/android/share/interactive-post", - "timestamp": 1194884220000, - "image": 'images/google/gps-googleplus.png', - "title": "Sharing interactive posts to Google+ from your Android app", - "summary": "Interactive posts provide an easy and prominent way to allow users to share your site or app with their friends and invite them to take a specific action.", - "keywords": ["Interactive", "Google+"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://play.google.com/about/developer-distribution-agreement.html", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Developer Distribution Agreement", - "summary": "Terms for distributing and selling apps and in-app products in Google Play.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/113417", - "timestamp": 1194884220000, - "image": null, - "title": "Inappropriate content in comments and applications", - "summary": "More details on what content is appropriate.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/legal/troubleshooter/1114905", - "timestamp": 1194884220000, - "image": null, - "title": "Removing content from Google", - "summary": "Find how how to request the removal of content that infringes on your trademark.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://play.google.com/about/developer-distribution-agreement-addendum.html", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Google Play for Education Addendum", - "summary": "Review the education-specific requirements.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://android-developers.blogspot.com/2013/03/native-rtl-support-in-android-42.html", - "timestamp": null, - "image": null, - "title": "Native RTL Support in Android 4.2", - "summary": "Blog post that explains how to support RTL in your UI.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/topics/resources/string-resource.html#Plurals", - "timestamp": 1194884220000, - "image": null, - "title": "Quantity Strings (Plurals)", - "summary": "How to work with string plurals according to rules of grammar in a given locale.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "reference/java/util/Locale.html", - "timestamp": 1194884220000, - "image": null, - "title": "Locale", - "summary": "Determine what CLDR data or version of the Unicode spec a particular Android platform version uses.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/topics/resources/string-resource.html", - "timestamp": 1194884220000, - "image": null, - "title": "String Resources", - "summary": "Explains how to use string resources in your UI.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "distribute/tools/localization-checklist.html#strings", - "timestamp": 1194884220000, - "image": null, - "title": "Manage strings for localization", - "summary": "Guidance on having your strings translation ready.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "tools/publishing/publishing_overview.html", - "timestamp": 1194884220000, - "image": null, - "title": "General Publishing Overview", - "summary": "Start here for an overview of publishing options for Android apps.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "tools/publishing/preparing.html", - "timestamp": 1194884220000, - "image": null, - "title": "Preparing for Release", - "summary": "Developer documentation on how to build the signed, release-ready APK. This process is the same for all Android apps.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "distribute/googleplay/policies/index.html", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Google Play Policies and Guidelines", - "summary": "An overview of Google Play policies for spam, intellectual property, and ads, with examples of common problems.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/topic/2364761", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Policy and Best Practices", - "summary": "Help Center document describing various content policies and processes.", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/topic/2364761?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "政策和最佳做法", - "summary": "内容政策和流程", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "google/play/expansion-files.html", - "timestamp": 1194884220000, - "image": null, - "title": "APK Expansion Files", - "summary": "Developer documentation describing APK Expansion Files and how to support them in your app.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "tools/help/proguard.html", - "timestamp": 1194884220000, - "image": null, - "title": "ProGuard", - "summary": "Developer documentation describing how to use ProGuard to shrink, optimize, and obfuscate your code prior to release.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "title":"Dashboards", - "titleFriendly":"", - "summary":"This page provides information about the relative number of devices that share a certain characteristic, such as Android version or screen size. This information may help you prioritize efforts for supporting different devices by revealing which devices…", - "url":"about/dashboards/index.html", - "group":"", - "keywords": ["android","dashboard","platforms","versions"], - "tags": ["#ecosystem","#versions","#whatsnew"], - "image":"https://chart.googleapis.com/chart?chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chf=bg%2Cs%2C00000000&chd=t%3A0.1%2C93.5%2C6.4&chco=c4df9b%2C6fad0c&chs=400x250&cht=p", - "lang":"en", - "type":"about" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/wallet/instant-buy/", - "timestamp": 1194884220000, - "image": "", - "title": "Android Pay APIs", - "summary": "Developer documentation describing Instant Buy and how to support it in your apps.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/1169947", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Selling Apps in Multiple Currencies", - "summary": "Help Center document describing how pricing works in Google Play.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/1169947?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "以多种货币销售应用", - "summary": "如何在Google Play为应用定价", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/138412", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Prices and supported currencies", - "summary": "Help Center document listing supported currencies for pricing your apps.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/138412?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "各国家/地区获许定价范围和货币", - "summary": "各国家/地区获许定价范围和货币列表", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/112622", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Transaction Fees", - "summary": "Help Center document describing transaction fees for priced apps and in-app products.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/112622?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "交易费用", - "summary": "销售的应用和应用内产品的交易费。", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/138000", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Specifying tax rates", - "summary": "Help Center document describing how to set tax rates for different countries.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/138000?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "税率", - "summary": "如何设置不同国家/地区的税率", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "guide/topics/resources/localization.html", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Localizing with Resources", - "summary": "Developer guide to localizing resources in your app.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/113475", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Category types", - "summary": "Help Center document listing available categories for apps.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/113475?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "类别", - "summary": "应用的类别列表。", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/113476", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Updates", - "summary": "Requirements for app updates in Google Play.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/113476?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "更新应用", - "summary": "更新Google Play应用的要求。", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/1153479", - "timestamp": 1194884220000, - "image": null, - "title": "In-app Billing", - "summary": "Help Center document describing how to correctly set up In-app Billing.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/1153479?hl=zh-Hans", - "timestamp": 1194884220000, - "image": null, - "title": "应用内结算", - "summary": "如何正确设置应用内商品和订阅结算。", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "#gpfe", - "#googleplay" - ], - "url": "https://youtu.be/vzvpcEffvaE", - "timestamp": 1383243492000, - "image": "https://i1.ytimg.com/vi/vzvpcEffvaE/maxresdefault.jpg", - "title": "Introducing Tablets with Google Play for Education", - "summary": "Schools in Hillsborough, New Jersey were among the first to try out Nexus 7 tablets with Google Play for Education. See the difference it made for students, teachers, and administrators.", - "keywords": [], - "type": "video", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "#engagement", - ], - "url": "https://www.youtube.com/yt/dev/", - "timestamp": 1383243492000, - "image": "https://www.youtube.com/yt/dev/media/images/yt-dev-home-hero.jpg", - "title": "YouTube for Developers", - "summary": "The YouTube APIs and Tools enable you to integrate YouTube's video content and functionality into your website, app, or device.", - "keywords": [], - "type": "youtube", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "#engagement", - ], - "url": "https://www.google.com/analytics/mobile/", - "timestamp": 1383243492000, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Mobile App Analytics", - "summary": "Mobile App Analytics measures what matters most at all key stages: from first discovery and download to in-app purchases. ", - "keywords": ["analytics,user behavior"], - "type": "Guide", - "titleFriendly": "" - }, - - - { - "lang": "en", - "group": "", - "tags": [ - "#gcm", - ], - "url": "https://www.youtube.com/watch?v=y76rjidm8cU", - "timestamp": 1383243492000, - "image": "https://1.bp.blogspot.com/-IF-1-1kA0sg/UYwTidxdi3I/AAAAAAAAAEU/ellLeQ-E1vs/s800/google-io-lockup-2.png", - "title": "Google Cloud Messaging at I/O 2013", - "summary": "Google Cloud Messaging allows your services to efficiently send data to applications on Android devices. See what's new, and learn how to use GCM to make your apps more efficient.", - "keywords": ["gcm"], - "type": "youtube", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "#gcm", - ], - "url": "https://developer.chrome.com/apps/cloudMessagingV2", - "timestamp": 1383243492000, - "image": "images/kk-chromium-icon.png", - "title": "Google Cloud Messaging for Chrome", - "summary": "Google Cloud Messaging for Chrome (GCM) is a service for signed-in Chrome users that helps developers send message data from servers to their Chrome apps and extensions.", - "keywords": ["gcm"], - "type": "guide", - "titleFriendly": "" - }, - - { - "lang": "en", - "group": "", - "tags": [ - "#sdkupdates" - ], - "url": "https://android-developers.blogspot.com/2013/07/making-beautiful-android-app-icons.html", - "timestamp": 1194884220000, - "image": null, - "title": "Make Beautiful Android App Icons", - "summary": "Follow these in-depth launcher icon tips on the Android Developers blog.", - "keywords": [], - "type": "blog", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "#sdkupdates" - ], - "url": "https://android-developers.blogspot.com/2012/12/localize-your-promotional-graphics-on.html", - "timestamp": 1194884220000, - "image": null, - "title": "Localize Your Promotional Graphics", - "summary": "Learn how to capitalise on international audiences.", - "keywords": [], - "type": "blog", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "#sdkupdates" - ], - "url": "https://android-developers.blogspot.com/2013/10/making-your-app-content-more-accessible.html", - "timestamp": 1194884220000, - "image": null, - "title": "Make your App Content more Accessible with App Linking", - "summary": "About using search and deep linking to get more users.", - "keywords": [], - "type": "blog", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/+/mobile/android/share/interactive-post", - "timestamp": 1194884220000, - "image": 'images/google/gps-googleplus.png', - "title": "Sharing interactive posts to Google+ from your Android app", - "summary": "Interactive posts provide an easy and prominent way to allow users to share your site or app with their friends and invite them to take a specific action.", - "keywords": ["Interactive", "Google+"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/+/mobile/android/", - "timestamp": 1194884220000, - "image": 'images/google/gps-googleplus.png', - "title": "Google+ Platform", - "summary": "Find out about features such as interactive posts, Hangouts, accessing basic user details and their social graphs to make your app more personal.", - "keywords": ["Google+"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/2528691", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "How to add multiple user accounts to your Developer Console for testing and more.", - "summary": "", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/+/mobile/android/share/deep-link", - "timestamp": 1194884220000, - "image": null, - "title": "Adding deep linking to Google+ posts shared from your Android app", - "summary": "", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "google/play/licensing/index.html", - "timestamp": 1194884220000, - "image": null, - "title": "Application Licensing", - "summary": "Information on the features of Google Play to protect your apps’ licences.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "design/style/writing.html", - "timestamp": 1194884220000, - "image": null, - "title": "Writing Style", - "summary": "Android Design guidelines for voice and style in your UI.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://en.wikipedia.org/wiki/XLIFF", - "timestamp": 1194884220000, - "image": null, - "title": "XML Localisation Interchange File Format (XLIFF)", - "summary": "Background information on XLIFF.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/1078870", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "Graphic Assets for your Application", - "summary": "Details about the graphics you can add to your product listing.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/googleplay/android-developer/answer/1078870?hl=zh-Hans", - "timestamp": 1194884220000, - "image": "images/play_dev.jpg", - "title": "为你的应用的图片资源", - "summary": "如何在你的应用的商品详情页面上添加图片资源。", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/payments/answer/2741495", - "timestamp": null, - "image": null, - "title": "Issuing Refunds", - "summary": "Help Center document describing how to issue refunds.", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://support.google.com/payments/answer/2741495?hl=zh-Hans", - "timestamp": null, - "image": null, - "title": "退回訂單款項", - "summary": "如何退还已收取的订单款项。", - "keywords": [], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://android-developers.blogspot.com/2013/11/bring-your-apps-into-classroom-with.html", - "timestamp": null, - "image": "distribute/images/gp-edu-apps-image.jpg", - "title": "Google play for education", - "summary": " ", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["localization", "pricing", "developer support"], - "url": "https://support.google.com/googleplay/android-developer/table/3541286", - "timestamp": null, - "image": "images/play_dev.jpg", - "title": "Supported locations for distributing your apps in Google Play", - "summary": "Countries and regions where you can distribute your app in Google Play.", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": ["localization", "pricing", "developer support"], - "url": "https://support.google.com/googleplay/android-developer/table/3541286?hl=zh-Hans", - "timestamp": null, - "image": "images/play_dev.jpg", - "title": "支持向Google Play用户发布应用的地区", - "summary": "支持向Google Play用户发布应用的国家/地区。", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["games", "localization", "quality"], - "url": "https://www.youtube.com/watch?v=SkHHPf3EdzE", - "timestamp": null, - "image": "https://developers.google.com/apps/images/io_2013/google-io-logo.png", - "title": "Level Up Your Android Game", - "summary": "Learn how to take your game to the next level in this Google I/O session.", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["support"], - "url": "https://support.google.com/groups/answer/46601", - "timestamp": null, - "image": null, - "title": "Google Groups", - "summary": "Create a group for your community.", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["support"], - "url": "https://support.google.com/plus/topic/2888488", - "timestamp": null, - "image": null, - "title": "Google+ Communities", - "summary": "Host a Google+ community for testers or users.", - "keywords": [], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["monetize", "ads"], - "url": "https://www.google.com/doubleclick/publishers/small-business/index.html", - "timestamp": null, - "image": "https://www.google.com/doubleclick/publishers/small-business/images/define_ad.png", - "title": "DoubleClick for Publishers", - "summary": "A free ad management solution that helps growing publishers sell, schedule, deliver, and measure all of their digital ad inventory.", - "keywords": ["ads"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["monetize", "ads"], - "url": "https://support.google.com/googleplay/android-developer/topic/2985714", - "timestamp": null, - "image":"images/play_dev.jpg", - "title": "Policy Center: Ads", - "summary": "Introduction to ads and system interference policies in Google Play.", - "keywords": ["ads"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/2611404", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Create Audience lists in Google Analytics", - "summary": "Find out how to use your analytics data to discover high value users and create remarketing audiences to use in AdMob.", - "keywords": ["ads, analytics, monetize"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://admob.blogspot.com/", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Inside Admob", - "summary": "Google’s official blog for news, tips, and information on the AdMob developer platform.", - "keywords": ["ads, analytics, monetize"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/admob/answer/3111064", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "AdMob in-app conversion tracking", - "summary": "Use in-app conversion tracking to attribute revenue back to your IAP promotion campaigns and determine which ones earn you the most.", - "keywords": ["ads, analytics, conversions"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["monetize", "giftcards"], - "url": "https://play.google.com/about/giftcards/", - "timestamp": null, - "image": "images/gp-balance.png", - "title": "Google Play Gift Cards", - "summary": "Buy Google Play gift cards online or at a variety of retail stores.", - "keywords": ["gift card"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["monetize", "paymentmethods"], - "url": "https://support.google.com/googleplay/answer/2651410", - "timestamp": null, - "image": "images/play_dev.jpg", - "title": "Google Play Accepted Payment Methods", - "summary": "Support details on the payment methods supported in Google Play.", - "keywords": ["gift card"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["plus", "social"], - "url": "https://plus.google.com/+AndroidDevelopers/", - "timestamp": null, - "image": "images/plus.jpg", - "title": "+Android Developers", - "summary": "Sharing news, ideas, and techniques for success.", - "keywords": ["+AndroidDevelopers"], - "type": "Google+", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["plus", "social"], - "url": "https://plus.google.com/+GooglePlay", - "timestamp": null, - "image": "https://lh4.googleusercontent.com/-IKezweZlcXI/AAAAAAAAAAI/AAAAAAABOvg/uK8Z0jekVE4/s120-c/photo.jpg", - "title": "+Google Play", - "summary": "News and discussion about Google Play, apps, and other content in Google+.", - "keywords": ["+GooglePlay"], - "type": "Google+", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["support", "android"], - "url": "support.html", - "timestamp": null, - "image": null, - "title": "Developer Support", - "summary": "Links to community and support resources for Android developers.", - "keywords": ["support"], - "type": "Google+", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Mobile App Analytics SDK", - "summary": "Measure everything about your app. Get started with the Google Analytics SDK for Android.", - "keywords": ["analytics, user behavior"], - "type": "sdk", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/edu/guidelines", - "timestamp": null, - "image": "https://developer.android.com/distribute/images/edu-guidelines.jpg", - "title": "Education Guidelines", - "summary": "These guidelines and requirements help you develop great apps for students, which offer compelling content and an intuitive user experience on Android tablets.", - "keywords": [], - "type": "", - "titleFriendly": "" - }, - { - "lang": "zh-cn", - "group": "", - "tags": [], - "url": "https://developers.google.com/edu/guidelines?hl=zh-Hans", - "timestamp": null, - "image": "https://developer.android.com/distribute/images/edu-guidelines.jpg", - "title": "Education Guidelines", - "summary": "These guidelines and requirements help you develop great apps for students, which offer compelling content and an intuitive user experience on Android tablets.", - "keywords": [], - "type": "", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/edu/faq", - "timestamp": null, - "image": "https://developer.android.com/distribute/images/gpfe-faq.jpg", - "title": "Education FAQ", - "summary": "Answers to common questions you might have about Google Play for Education.", - "keywords": [], - "type": "", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/edu/", - "timestamp": null, - "image": "https://developers.google.com/edu/images/home-android.png", - "title": "Chrome Apps in Google Play for Education", - "summary": "Find out more about Chrome apps in Google Play for Education.", - "keywords": [], - "type": "", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/edu/tablets/#tablets-family", - "timestamp": null, - "image": "https://www.google.com/edu/images/tablets/big-tablet.png", - "title": "Google Play for Education Tablets", - "summary": "Google Play for Education leverages a diverse set up tablets approved for the classroom which may help inform you how to build educational apps.", - "keywords": [], - "type": "", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Glu_Deerhunter2014_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Glu_Deerhunter2014_gpgs.png", - "title": "Deer Hunter 2014 by Glu — Sign-in", - "summary": "Glu finds that Google Play Game Services helps improve the user experience which leads to increased player happiness. They also find that Play Games Services signed in users tend to play longer and have a higher lifetime value.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/ConcreteSoftware_PBABowling_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/ConcreteSoftware_PBABowling_gpgs.png", - "title": "PBA® Bowling Challenge by Concrete Software — Quests", - "summary": "Concrete Software finds that Google Play Game Services' quests are a great way to create new content for users that leads to higher engagement.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Dragonplay_DragonplaySlots_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Dragonplay_DragonplaySlots_gpgs.png", - "title": "Dragonplay Slots by Dragonplay — Sign-in", - "summary": "Dragonplay finds that players who sign in with Google Play Games services tend to be high quality users who were highly engaged. They also tend to be easier to convert to paying users.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Gameloft_Asphalt8_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Gameloft_Asphalt8_gpgs.png", - "title": "Asphalt 8 by Gameloft — Friends invitations", - "summary": "Gameloft finds that Google Play Game Services users are more engaged than the average Android user and more likely to convert to paying players.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Glu_EternityWarriors3_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Glu_EternityWarriors3_gpgs.png", - "title": "Eternity Warriors 3 by Glu — Gifting", - "summary": "Glu finds that Google Play Game Services gifting outperforms other implementations (including those with incentives) because of its seamless flow and consistent performance.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/HotheadGames_RivalsatWar_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/HotheadGames_RivalsatWar_gpgs.jpg", - "title": "Rivals at War: Firefight by Hothead Games — Leaderboards", - "summary": "Hothead Games is planning to include Google Play Game Services features in all their games going forwards after seeing that players that signed in with Play Games Services tend to show higher retention and a higher average revenue.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/TMSOFT_Compulsive_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/TMSOFT_Compulsive_gpgs.png", - "title": "Compulsive by TMSOFT — Cross-platform", - "summary": "TMSOFT finds that users who authenticate with Play Games Services on Android and iOS play Compulsive twice as much and purchase in-app products over four times as much.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Noodlecake_SuperStickmanGolf2_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Noodlecake_SuperStickmanGolf2_gpgs.png", - "title": "Super Stickman Golf 2 by Noodlecake Studios — Multiplayer", - "summary": "Noodlecake Studios finds that Google Play Game Services’ multiplayer feature helps reduce attrition.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/TinyRebel_DoctorWhoLegacy_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/TinyRebelGames_DrWhoLegacy_pgps.png", - "title": "Dr. Doctor Who: Legacy by Tiny Rebel Games — Achievements", - "summary": "After integrating achievements and cloud services from Google Play Game Services, Tiny Rebel Games saw a dramatic increase in daily revenues as a result of an increase in daily installs and an increase in the average revenue per install.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Senri_LeosFortune_gpgs.pdf", - "timestamp": null, - "image": "https://storage.googleapis.com/androiddevelopers/shareables/stories/Senri_LeosFortune_gpgs.png", - "title": "Leo’s Fortune by 1337 & Senri — Saved games", - "summary": "1337 + Senri finds that Google Play Game Services is easy to integrate and provides essential game functions like cloud saved games, achievements and leaderboards which have a very large adoption rate amongst players.", - "keywords": ["stories"], - "type": "Case Study Deck", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": ["play,protips"], - "url": "shareables/distribute/secrets_play/v2/web/secrets_to_app_success_v2_en.pdf", - "timestamp": 1447437450, - "image": "images/distribute/secrets_v2_banner.jpg", - "title": "The Secrets to App Success on Google Play", - "summary": "Get the updated guide full of useful features, tips, and best practices that will help you grow a successful app or game business on Google Play.", - "keywords": ["secrets, success, play, google"], - "type": "Book", - "category": "distribute" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "shareables/auto/AndroidAuto-audio-apps.pdf", - "timestamp": null, - "image": "auto/images/assets/icons/media_app_playback.png", - "title": "Android Auto Audio Apps UI Guidelines", - "summary": "Guidelines for designing audio apps that work with Auto. ", - "keywords": ["design", "Auto", "Automotive"], - "type": "Design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "shareables/auto/AndroidAuto-messaging-apps.pdf", - "timestamp": null, - "image": "auto/images/assets/icons/messaging_app_notifications.png", - "title": "Android Auto Messaging Apps UI Guidelines", - "summary": "Guidelines for designing messaging apps that work with Auto. ", - "keywords": ["design", "Auto", "Automotive"], - "type": "Design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "shareables/auto/AndroidAuto-custom-colors.pdf", - "timestamp": null, - "image": "auto/images/ui/gearhead_generic_UI.png", - "title": "Android Auto Color Customization UI Guidelines", - "summary": "Guidelines for color-customizing apps that work with Auto. ", - "keywords": ["design", "Auto", "Automotive"], - "type": "Design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "http://www.youtube.com/watch?v=RRelFvc6Czo", - "timestamp": null, - "image": "https://i1.ytimg.com/vi/RRelFvc6Czo/maxresdefault.jpg", - "title": "Android Developer Story: Smule", - "summary": "The creators of AutoRap, Magic Piano, and Songify talk about their experiences launching on Android and the explosive global growth they've seen on Google Play.", - "keywords": ["success", "users"], - "type": "video", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/solutions/mobile-implementation-guide", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Mobile Analytics Implementation Guide", - "summary": "Learn how you can implement additional Google Analytics features to better understand your users and their behavior.", - "keywords": ["analytics", "Play", "users"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/tagmanager/", - "timestamp": null, - "image": "https://www.google.com/tagmanager/images/gtm-hero-illustration-small.png", - "title": "Google Tag Manager", - "summary": "Google Tag Manager enables you to change configuration values in your mobile apps using the Google Tag Manager interface, without having to rebuild and resubmit application binaries to app marketplaces.", - "keywords": ["analytics", "tagmanager"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://analyticsacademy.withgoogle.com/course04", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Mobile App Analytics Fundamentals", - "summary": "This self-paced online course on mobile app measurement shows you how Google Analytics data can help you make your app more discoverable and profitable.", - "keywords": ["analytics"], - "type": "Open Source Project", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://github.com/googleanalytics/google-analytics-plugin-for-unity", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Analytics Plugin for Unity", - "summary": "If you're building games with Unity, you can now implement Analytics once and ship it on multiple platforms automatically.", - "keywords": ["analytics", "unity"], - "type": "Open Source Project", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/v4/enhanced-ecommerce", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "In-App Purchases & Ecommerce", - "summary": "If your app sells virtual or real goods, ecommerce tracking can help you understand what behaviors lead to purchases.", - "keywords": ["analytics, ecommerce"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/1032415", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Goals", - "summary": "Track important actions in your app as goals and measure performance against your objectives.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/2568874?ref_topic=6012392", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Active Users", - "summary": "The active user report displays your 1-day, 7-day, 14-day and 30-day trailing active users next to each other, to help you analyze performance over time.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/v4/events", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Events", - "summary": "Events let you measure granular in-app activities and understand user journeys.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/v4/customdimsmets", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Custom Dimensions", - "summary": "Custom dimensions enable the association of metadata with hits, users, and sessions in Google Analytics.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/v4/user-id", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "User ID", - "summary": "The User ID feature enables Google Analytics to measure user activities that span across devices.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/v4/display-features", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Demographic Reporting", - "summary": "By enabling display features, you can see just how different user segments engage and monetize.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/3123906", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "User Segmentation", - "summary": "Segments let you compare metrics for different subsets of users to identify trends and opportunities for your apps.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/v4/campaigns", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Campaign Tracking", - "summary": "Measuring campaigns in Google Analytics enables the attribution of campaigns and traffic sources to user activity within your app.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/2956981", - "timestamp": null, - "image": "images/play_dev.jpg", - "title": "Google Play Integration", - "summary": "By linking Analytics and the Play Developer Console, you can gain additional insights into the acquisition flow.", - "keywords": ["play, analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/1033961", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "AdWords Integration", - "summary": "Link Analytics and AdWords to see the entire picture of customer behavior, from ad click or impression through your site to conversion. ", - "keywords": ["adwords, analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/devguides/collection/android/v4/campaigns#google-play-url-builder", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Campaign URL builder for Google Play", - "summary": "Easily create your URLs to track install campaigns.", - "keywords": ["play, analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/tagmanager/answer/6003007", - "timestamp": null, - "image": "https://www.google.com/tagmanager/images/gtm-hero-illustration-small.png", - "title": "In-App A/B Testing", - "summary": "With content experiments in Google Tag Manager you can test multiple variations of your app to find which works best.", - "keywords": ["tagmanager"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/2785577", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Behavior Flow", - "summary": "The Behavior Flow report visualizes the path users traveled from one Screen or Event to the next. This report can help you discover what content keeps users engaged with your app.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/1151300", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Custom Reports", - "summary": "Custom Reports let you create your own reports in your Google Analytics account.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/2611268", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Audience Lists & Remarketing", - "summary": "Remarketing with Google Analytics lets you deliver targeted ads to users who've already been to your site or app. You can even base those ads on the behavior those users displayed during their sessions.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/admob/answer/3508177", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "AdMob Integration", - "summary": "With Google Analytics in AdMob, you can view Google Analytics data for your linked apps from within your AdMob account.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/analytics/solutions/mobile-campaign-deep-link", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Deep-Linking", - "summary": "Google Analytics gives you a full view of how returning users are interacting with your app, for a holistic view beyond the install.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/admob/answer/3508177", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "AdMob Integration", - "summary": "With Google Analytics in AdMob, you can view Google Analytics data for your linked apps from within your AdMob account.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/analytics/answer/2568874", - "timestamp": null, - "image": "images/cards/analytics-mobile_2x.jpg", - "title": "Active User Report", - "summary": "Active user report displays your 1-day, 7-day, 14-day and 30-day trailing active users next to each other, to help you run benchmark analyses of their performance over time.", - "keywords": ["analytics"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/animation/", - "timestamp": null, - "image": "images/cards/material-animation_2x.png", - "title": "Animation", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/style/", - "timestamp": null, - "image": "images/cards/material-style_2x.jpg", - "title": "Style", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/layout/", - "timestamp": null, - "image": "images/cards/material-layout_2x.png", - "title": "Layout", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/components/", - "timestamp": null, - "image": "images/cards/material-components_2x.jpg", - "title": "Components", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/patterns/", - "timestamp": null, - "image": "images/cards/material-patterns_2x.png", - "title": "Patterns", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/usability/", - "timestamp": null, - "image": "images/cards/material-usability_2x.png", - "title": "Usability", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/resources/color-palettes.html", - "timestamp": null, - "image": "images/cards/material-color-palette_2x.jpg", - "title": "Color Palettes", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/resources/layout-templates.html", - "timestamp": null, - "image": "images/cards/material-layout-template_2x.jpg", - "title": "Layout Templates", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/resources/sticker-sheets-icons.html", - "timestamp": null, - "image": "images/cards/material-sticker-sheet_2x.jpg", - "title": "Sticker Sheets & Icons", - "summary": "", - "keywords": [], - "type": "material design", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.google.com/design/spec/resources/roboto-noto-fonts.html", - "timestamp": null, - "image": "images/cards/material-typography_2x.jpg", - "title": "Typography: Roboto and Noto Sans fonts", - "summary": "", - "keywords": [], - "type": "materialdesign", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "icons", - "material", - "iconography" - ], - "url": "https://www.google.com/design/icons/index.html", - "timestamp": null, - "image": "images/cards/card-material-icons-16x9_2x.jpg", - "title": "Material icon collection", - "summary": "", - "keywords": ["icons"], - "type": "material design", - "titleFriendly": "" - }, - - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/adwords/answer/6032059", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "Setting up Mobile App Install Ads", - "summary": "With Mobile app installs campaigns on the Search and Display Networks, and TrueView for mobile app promotion on YouTube, you can create custom app install ads that run exclusively on phones and tablets.", - "keywords": ["marketing", "admob"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/adwords/answer/6167164", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "Best practices for Mobile App Engagement", - "summary": "Learn how to market to your user base to drive re-engagement with your app. ", - "keywords": ["marketing", "admob"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "marketing", - "engagement", - "adwords1" - ], - "url": "https://support.google.com/adwords/answer/6032073", - "timestamp": null, - "image": "https://www.gstatic.com/images/icons/material/product/2x/adwords_64dp.png", - "title": "Setting up Mobile App Engagement Ads", - "summary": "Mobile app engagement campaigns are a great choice for advertisers focused on connecting with people who already have their app.", - "keywords": [ - "marketing", - "engagement", - "adwords" - ], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "marketing", - "engagement", - "translate" - ], - "url": "https://support.google.com/l10n/answer/6359997", - "timestamp": null, - "image": "images/play_dev.jpg", - "title": "Use the App Translation Service", - "summary": "The App Translation Service is a human translation service. It makes it easy to order translations for app UI strings, Play Store text, in-app purchase products, and universal app campaign ads.", - "keywords": [ - "marketing", - "engagement", - "translate" - ], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [ - "marketing", - "engagement" - ], - "url": "https://support.google.com/adwords/answer/6167162", - "timestamp": null, - "image": "https://www.gstatic.com/images/icons/material/product/2x/adwords_64dp.png", - "title": "Best Practices for Mobile App Installs", - "summary": "Getting your mobile app discovered can be challenging. Learn how to drive downloads of your app and grow a valuable user base.", - "keywords": ["marketing", "adwords"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/admob/topic/2784623", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "Set up your AdMob account", - "summary": "Setting up your AdMob account in the right way will help you get the most value, check out the Setup and Basics guide.", - "keywords": ["marketing", "admob"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://analyticsacademy.withgoogle.com/mobile-app", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "Analytics Academy for Mobile Apps", - "summary": "Learn how to use Google Analytics to make your app more discoverable and profitable.", - "keywords": ["marketing", "analytics"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://www.udacity.com/courses/ud876-3", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "Learn how to show ads in your Android app", - "summary": "Take this online course to learn how to use AdMob to display ads in your Android app.", - "keywords": ["marketing", "analytics"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/mobile-ads-sdk/download", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "Admob Ads", - "summary": "Use the Mobile Ads SDK to start showing AdMob ads in your apps.", - "keywords": ["marketing", "adwords"], - "type": "Guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/admob/", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "AdMob Help Center", - "summary": "For setup assistance, general info, and fixes for specific problems check out the AdMob Help Center.", - "keywords": ["admob"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://support.google.com/admob/answer/2753860", - "timestamp": null, - "image": "distribute/images/advertising.jpg", - "title": "AdMob Policy Guidelines", - "summary": "Learn about best practices for displaying AdMob ads in your apps to maximize revenue.", - "keywords": ["admob"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/app-invites/", - "timestamp": 1383243492000, - "image": "images/cards/google-search_2x.png", - "title": "Set up App Invites", - "summary": "Bring new users to your apps with personal recommendations, incentives, and offers.", - "keywords": ["invites", "appinvites", "engagement", "getusers"], - "type": "guide", - "titleFriendly": "" - }, - - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/app-indexing/", - "timestamp": 1383243492000, - "image": "images/cards/google-search_2x.png", - "title": "Set Up App Indexing", - "summary": "Surface your app content in Google seaerch. Deep link direct to your apps.", - "keywords": ["search", "appindexing", "engagement", "getusers"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/app-indexing/webmasters/details", - "timestamp": null, - "image": "images/cards/google-search_2x.png", - "title": "Index your app", - "summary": "Index your app today by adding deep links and verifying its official web site to ensure it starts appearing in Google Search results. ", - "keywords": ["appindexing","search","getusers"], - "type": "distribute", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/identity/sign-in/android/people", - "timestamp": 1383243492000, - "image": "images/cards/google-sign-in_2x.png", - "title": "Get user profile details", - "summary": "After users sign-in with Google, you can access their age range, language, and public profile information.", - "keywords": ["signin", "identity", "google"], - "type": "guide", - "titleFriendly": "" - }, - - - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/identity/sign-in/android/", - "timestamp": "", - "image": "images/cards/google-sign-in_2x.png", - "title": "Google Sign-In", - "summary": "Discover how you can enhance user experiences on your website or in your app using information provided by their Google identity.", - "keywords": ["signin", "identity", "google"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/+/features/play-installs", - "timestamp": 1383243492000, - "image": "images/cards/google-sign-in_2x.png", - "title": "Over-the-air installs", - "summary": "Follow this step-by-step guide to quickly add Google Sign-in and over-the-air app installs to your website.", - "keywords": ["signin", "google", "installs"], - "type": "guide", - "titleFriendly": "" - }, - { - "lang": "en", - "group": "", - "tags": [], - "url": "https://developers.google.com/+/features/analytics", - "timestamp": 1383243492000, - "image": 'images/google/gps-googleplus.png', - "title": "Google+ Insights", - "summary": "Measure impressions of the over-the-air install prompt, resulting installs, and success rate by day, week, and month.", - "keywords": ["signin", "identity"], - "type": "guide", - "titleFriendly": "" - }, - - // Online courses - - { - "title":"UX Design for Mobile Developers", - "titleFriendly":"", - "summary":"Learn how to design a 5-star app.", - "url":"https://www.udacity.com/course/ud849", - "group":"", - "keywords": ["mobile","ux","design"], - "tags": ["courses, start"], - "image":"images/cards/courses/mobile_ux_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Developing Android Apps", - "titleFriendly":"", - "summary":"Learn Android and build an app!", - "url":"https://www.udacity.com/course/ud853", - "group":"", - "keywords": ["android", "start","firstapp","sdk"], - "tags": ["courses, start"], - "image":"images/cards/courses/android_fundamentals_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Android Performance", - "titleFriendly":"", - "summary":"Optimize your apps for speed and usability.", - "url":"https://www.udacity.com/course/ud825", - "group":"", - "keywords": ["android, performance","battery"], - "tags": ["courses, performance"], - "image":"images/cards/courses/android_performance_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Enroll in the Android Nanodegree", - "titleFriendly":"", - "summary":"Enroll in the Android Nanodegree to build the skills to work as an Android developer.", - "url":"https://www.udacity.com/android", - "group":"", - "keywords": ["android, nanodegree"], - "tags": ["courses"], - "image":"images/cards/courses/android_nanodegree.png", - "lang":"en", - "type":"online course" - }, - { - "title":"Advanced Android App Development", - "titleFriendly":"", - "summary":"Productionize and publish your apps.", - "url":"https://www.udacity.com/course/ud855", - "group":"", - "keywords": ["android, experts"], - "tags": ["courses, expert"], - "image":"images/cards/courses/advanced_android_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Material Design for Android Developers", - "titleFriendly":"", - "summary":"Learn how to make your apps material.", - "url":"https://www.udacity.com/course/ud862", - "group":"", - "keywords": ["android, design, pure, material"], - "tags": ["courses, start, material"], - "image":"images/cards/courses/android_design_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Android for Beginners", - "titleFriendly":"", - "summary":"Make your first Android app, even if you don't write code.", - "url":"https://www.udacity.com/course/ud837", - "group":"", - "keywords": ["android, sdk, firstapp"], - "tags": ["courses, start"], - "image":"images/cards/courses/beginning_android_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Gradle for Android and Java", - "titleFriendly":"", - "summary":"Build better apps through automation", - "url":"https://www.udacity.com/course/ud867", - "group":"", - "keywords": ["gradle","studio", "sdk"], - "tags": ["courses, gradle, sdk"], - "image":"images/cards/courses/gradle_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Add Location and Context to your app", - "titleFriendly":"", - "summary":"Make Your Android App Location Aware.", - "url":"https://www.udacity.com/course/ud876-1", - "group":"", - "keywords": ["google services, context, location"], - "tags": ["courses, google, location, context"], - "image":"images/cards/courses/android_location_course.png", - "lang":"en", - "type":"online course" - }, - { - "title":"Analytics and Tag Manager for Android", - "titleFriendly":"", - "summary":"Use Analytics and Tag Manager in Your Apps.", - "url":"https://www.udacity.com/course/ud876-2", - "group":"", - "keywords": ["google services, analytics, tag manager"], - "tags": ["courses, google, analytics"], - "image":"images/cards/courses/android_analytics_course.png", - "lang":"en", - "type":"online course" - }, - { - "title":"AdMob for Android", - "titleFriendly":"", - "summary":"Monetize Your App by Displaying Ads.", - "url":"https://www.udacity.com/course/ud876-3", - "group":"", - "keywords": ["monetize, google services, ads, admob"], - "tags": ["courses, google, ads, admob"], - "image":"images/cards/courses/admob_course.png", - "lang":"en", - "type":"online course" - }, - { - "title":"Add Maps to your Android app", - "titleFriendly":"", - "summary":"Use maps, cameras, markers and more in your app.", - "url":"https://www.udacity.com/course/ud876-4", - "group":"", - "keywords": ["google, maps, marker, camera"], - "tags": ["courses, google, maps"], - "image":"images/cards/courses/android_maps_course.png", - "lang":"en", - "type":"online course" - }, - { - "title":"Add Sign-in to your Android app", - "titleFriendly":"", - "summary":"Build a Seamless Sign-In Experience.", - "url":"https://www.udacity.com/course/ud876-5", - "group":"", - "keywords": ["google services, signin, authorization"], - "tags": ["courses, google, auth"], - "image":"images/cards/courses/android_identity_course.png", - "lang":"en", - "type":"online course" - }, - { - "title":"Android Wear Development", - "titleFriendly":"", - "summary":"Extend your Apps to Android Smartwatches.", - "url":"https://www.udacity.com/course/ud875A", - "group":"", - "keywords": ["wear, wearables, smartwatch"], - "tags": ["courses, wear, wearable"], - "image":"images/cards/courses/android_wear_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Android TV and Google Cast Development", - "titleFriendly":"", - "summary":"Extend your Apps to the Big Screen.", - "url":"https://www.udacity.com/course/ud875B", - "group":"", - "keywords": ["cast, living room"], - "tags": ["courses, cast, tv"], - "image":"images/cards/courses/android_tv_cast_course.jpg", - "lang":"en", - "type":"online course" - }, - { - "title":"Android Auto Development", - "titleFriendly":"", - "summary":"Put your apps in the driver's seat.", - "url":"https://www.udacity.com/course/ud875C", - "group":"", - "keywords": ["auto"], - "tags": ["courses, auto"], - "image":"images/cards/courses/android_auto_course.jpg", - "lang":"en", - "type":"online course" - }, - - - // TODO remove this? - { - "title":"Android Wear Materials", - "titleFriendly":"", - "summary":"Drag and drop your way to beautifully designed Android Wear apps.", - "url":"design/downloads/index.html#Wear", - "group":"", - "keywords": ["icons","stencils","color swatches"], - "tags": ["icons","stencils","colorswatches"], - "image":"images/cards/android-wear-materials_2x.jpg", - "lang":"en", - "type":"design" - }, - { - "title":"Watch Faces for Android Wear", - "titleFriendly":"", - "summary":"Watch faces let you customize the most prominent UI feature of Android wearables. The API is simple enough for rapid development and flexible enough to build something awesome.", - "url":"https://www.youtube.com/watch?v=AK38PJZmIW8&list=PLWz5rJ2EKKc-kIrPiq098QH9dOle-fLef", - "group":"", - "keywords": ["wear", "wearable", "watch face"], - "tags": [], - "image":"https://i1.ytimg.com/vi/AK38PJZmIW8/maxresdefault.jpg", - "lang":"en", - "type":"video" - }, - { - "title":"Android Support Library", - "titleFriendly":"", - "summary":"These essential components help you build a great app that works on the huge variety of Android devices, faster.", - "url":"https://www.youtube.com/watch?v=3PIc-DuEU2s&list=PLWz5rJ2EKKc9e0d55YHgJFHXNZbGHEXJX", - "group":"", - "keywords": ["support", "compatibility"], - "tags": [], - "image":"https://i1.ytimg.com/vi/3PIc-DuEU2s/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Consistent Design with the AppCompat Support Library", - "titleFriendly":"", - "summary":"Getting a great looking app doesn't have to be hard: AppCompat, part of the Android Support Library, gives you a consistent design baseline that works on all Android 2.1 or higher devices.", - "url":"https://www.youtube.com/watch?v=5Be2mJzP-Uw&list=PLWz5rJ2EKKc9e0d55YHgJFHXNZbGHEXJX", - "group":"", - "keywords": ["support", "compatibility","design-code"], - "tags": [], - "image":"https://i1.ytimg.com/vi/5Be2mJzP-Uw/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Introducing Gradle", - "titleFriendly":"", - "summary":"Android Studio uses an entirely new and flexible Gradle-based build system. You will be able to create multiple build variants for a single project, manage library dependencies and always be sure that your application builds correctly across different environments.", - "url":"https://www.youtube.com/watch?v=cD7NPxuuXYY&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "group":"", - "keywords": ["tools", "studio","gradle"], - "tags": [], - "image":"https://i1.ytimg.com/vi/cD7NPxuuXYY/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Android Studio Layout Editor", - "titleFriendly":"", - "summary":"Android Studio includes a rich, visual layout editor that helps developers create better user interfaces. It eliminates the need to deploy the APK on a real device with each change, making iterations faster and helping eliminate common errors earlier in the development process.", - "url":"https://www.youtube.com/watch?v=JLLnhwtDoHw&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "group":"", - "keywords": ["tools", "studio","layout"], - "tags": [], - "image":"https://i1.ytimg.com/vi/JLLnhwtDoHw/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Debugging and testing in Android Studio", - "titleFriendly":"", - "summary":"Learn about new debugger features in Android Studio 1.2: value inlining, quick access to referring objects and a Java .class decompiler, just to name a few. See some new tools and views that let you monitor the CPU and memory performance of your app from within the IDE. ", - "url":"https://www.youtube.com/watch?v=2I6fuD20qlY&list=PLWz5rJ2EKKc8I9gHTMh5yKkwRRGE8BjbQ", - "group":"", - "keywords": ["tools", "studio","debugging","profiling","performance"], - "tags": [], - "image":"https://i1.ytimg.com/vi/2I6fuD20qlY/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Scale with Google Cloud Platform", - "titleFriendly":"", - "summary":"Build, test, and deploy applications on Google's highly-scalable and reliable infrastructure for your web, mobile and backend solutions.", - "url":"https://cloud.google.com/docs/", - "group":"", - "keywords": [], - "tags": [], - "image":"images/cards/cloud-platform_2x.png", - "lang":"en", - "type":"distribute" - }, - { - "title":"Opportunities & Programs", - "titleFriendly":"", - "summary":"Take advantage of the many ways you can distribute your app to consumers, students, and businesses through Google Play.", - "url":"distribute/googleplay/index.html#opportunities", - "group":"", - "keywords": [], - "tags": [], - "image":"images/cards/program-edu_2x.jpg", - "lang":"en", - "type":"distribute" - }, - { - "title":"Join the Android for Work DevHub", - "titleFriendly":"", - "summary":"The Android for Work DevHub is a place to help developers keep up with Android in the workplace.", - "url":"https://www.google.com/work/android/developers/applyDevHub/", - "group":"", - "keywords": ["work", "enterprise", "isv", "devhub"], - "tags": [], - "image":"images/work/cards/work-devhub_600px.png", - "lang":"en", - "type":"Community" - }, - { - "title":"Enterprise Mobility Managers", - "titleFriendly":"", - "summary":"Integrate Android for Work into your enterprise mobility management (EMM) solution.", - "url":"https://developers.google.com/android/work/", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"images/work/cards/work-cloud_600px.png", - "lang":"en", - "type":"guide" - }, - { - "title":"Learn More About Android for Work", - "titleFriendly":"", - "summary":"Android for Work makes your favorite phones and tablets the perfect business tools.", - "url":"https://www.google.com/work/android/", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"images/work/cards/work-profile_600px.png", - "lang":"en", - "type":"about" - }, - { - "title":"Build a Device Policy Controller", - "titleFriendly":"", - "summary":"Create and administer a managed profile on an employee's device.", - "url":"https://developers.google.com/android/work/build-dpc", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"images/work/cards/work-folder_600px.png", - "lang":"en", - "type":"guide" - }, - { - "title":"Android for Work for Developers", - "titleFriendly":"", - "summary":"Watch the videos in this playlist to understand more about Android for Work and get tips on developing enterprise apps.", - "url":"https://www.youtube.com/watch?v=jQWB_-o1kz4&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"https://i1.ytimg.com/vi/jQWB_-o1kz4/maxresdefault.jpg", - "lang":"en", - "type":"youtube" - }, - { - "title":"App Configurations, Testing and Launchers", - "titleFriendly":"", - "summary":"With Android for Work you can make your apps remotely configurable. We also cover how to test your app in a managed environment.", - "url":"https://www.youtube.com/watch?v=39NkpWkaH8M&index=2&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"https://i1.ytimg.com/vi/39NkpWkaH8M/maxresdefault.jpg", - "lang":"en", - "type":"youtube" - }, - { - "title":"Building an Enterprise Ready App", - "titleFriendly":"", - "summary":"A holistic view of Android for Work for developers.", - "url":"https://www.youtube.com/watch?v=dH41OutAMNM&list=PLOU2XLYxmsIKAK2Bhv19H2THwF-22O5WX", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"https://i1.ytimg.com/vi/dH41OutAMNM/maxresdefault.jpg", - "lang":"en", - "type":"youtube" - }, - { - "title":"Android for Work: Single Use Devices", - "titleFriendly":"", - "summary":"Single-purpose computers are everywhere, and Android can meet that need.", - "url":"https://www.youtube.com/watch?v=j3QC6hcpy90", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"https://i1.ytimg.com/vi/j3QC6hcpy90/maxresdefault.jpg", - "lang":"en", - "type":"youtube" - }, - { - "title":"Your Apps at Work", - "titleFriendly":"", - "summary":"In this Google I/O 2016 session we’ll give you details for making your app more attractive to businesses.", - "url":"https://www.youtube.com/watch?v=Za0OQo8DRM4", - "group":"", - "keywords": ["work", "enterprise", "emm"], - "tags": [], - "image":"https://i1.ytimg.com/vi/Za0OQo8DRM4/maxresdefault.jpg", - "lang":"en", - "type":"youtube" - }, - { - "title":"Discover YouTube cards", - "titleFriendly":"", - "summary":"Find out more about YouTube cards, the options available, and how to use them to get the most from your YouTube content.", - "url":"https://support.google.com/youtube/answer/6140493", - "group":"", - "keywords": ["youtube", "video", "users", "installs"], - "tags": [], - "image":"images/cards/card-youtube_2x.png", - "lang":"en", - "type":"distribute" - }, - { - "title":"What is YouTube account good standing?", - "titleFriendly":"", - "summary":"Learn what it means for an account to be in good standing from the YouTube Help Center.", - "url":"https://support.google.com/youtube/answer/2797387", - "group":"", - "keywords": ["youtube", "video", "users", "installs"], - "tags": [], - "image":"images/cards/card-youtube_2x.png", - "lang":"en", - "type":"distribute" - }, - { - "title":"What’s New in Android N Developer Preview", - "titleFriendly":"", - "summary":"Learn all about the new features in the Android N Preview.", - "url":"https://www.youtube.com/watch?v=CsulIu3UaUM", - "group":"", - "keywords": ["n preview"], - "tags": [], - "image":"https://i1.ytimg.com/vi/CsulIu3UaUM/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Developing for Android 6.0 (Marshmallow)", - "titleFriendly":"", - "summary":"This video covers how to get started with the preview, important APIs to test and how to provide feedback on the preview.", - "url":"https://www.youtube.com/watch?v=yYU4DHLwoRk", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/yYU4DHLwoRk/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Google I/O 2015 - What's new in Android", - "titleFriendly":"", - "summary":"This session will highlight the most exciting new developer features of the Android platform.", - "url":"https://www.youtube.com/watch?v=ndBdf1_oOGA", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/ndBdf1_oOGA/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Fingerprint and payments APIs", - "titleFriendly":"", - "summary":"New fingerprint and payments APIs are introduced in M, to enable enhanced UX and security for online purchasing, banking, and retail payments.", - "url":"https://www.youtube.com/watch?v=VOn7VrTRlA4", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/VOn7VrTRlA4/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Introduction to Voice Interaction API", - "titleFriendly":"", - "summary":"This video covers how to use the Voice Interaction API to support system or custom voice actions.", - "url":"https://www.youtube.com/watch?v=OW1A4XFRuyc", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/OW1A4XFRuyc/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Android Auto Backup for Apps", - "titleFriendly":"", - "summary":"Android Backup is the automatic, cloud-based backup and restore of users’ apps when they set up a new device.", - "url":"https://www.youtube.com/watch?v=HXacyy0HSW0", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/HXacyy0HSW0/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"New APIs in M for Android for Work", - "titleFriendly":"", - "summary":"Android M extends Android for Work functionality with a new set of APIs for Enterprise Mobility Management providers to offer new features and policy controls to IT Departments.", - "url":"https://www.youtube.com/watch?v=vcSj8ln-BlE", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/vcSj8ln-BlE/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Runtime Permissions in Android 6.0 Marshmallow", - "titleFriendly":"", - "summary":"Learn how to integrate runtime permissions into your Android app.", - "url":"https://www.youtube.com/watch?v=C8lUdPVSzDk", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/C8lUdPVSzDk/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Introduction to Doze", - "titleFriendly":"", - "summary":"An overview of Doze and how to make sure that your app behaves as expected both in and out of Doze mode. ", - "url":"https://youtu.be/N72ksDKrX6c", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/N72ksDKrX6c/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"The Nexus 5X, Nexus 6P and Android Marshmallow", - "titleFriendly":"", - "summary":"The new Nexus 5X and Nexus 6P along with some of the most significant developer features in the latest Android release,.", - "url":"https://youtu.be/U9tw5ypqEN0", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/U9tw5ypqEN0/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Asking For Permission Fine", - "titleFriendly":"", - "summary":"Picking the right way and time to ask for a permission is critical to it being granted. ", - "url":"https://youtu.be/iZqDdvhTZj0", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/iZqDdvhTZj0/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Data Binding Library", - "titleFriendly":"", - "summary":"Data Binding Library is a way to write declarative layouts and minimize the glue code necessary to bind your application logic and layouts. ", - "url":"https://youtu.be/5sCQjeGoE7M", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/5sCQjeGoE7M/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"App Links", - "titleFriendly":"", - "summary":"App Links is a new feature of Android Marshmallow that brings a faster way of opening website links for domains that you own.", - "url":"https://youtu.be/LQoohRwojmw", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/LQoohRwojmw/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "title":"Android M Permissions", - "titleFriendly":"", - "summary":"An introduction to Android M runtime permissions in Android M from Google I/O 2015. ", - "url":"https://www.youtube.com/watch?v=f17qe9vZ8RM", - "group":"", - "keywords": ["Marshmallow"], - "tags": [], - "image":"https://i1.ytimg.com/vi/f17qe9vZ8RM/maxresdefault.jpg", - "lang":"en", - "type":"Video" - }, - { - "lang": "ja", - "title": "Gaming Everywhere", - "titleFriendly": "", - "summary": "東京ゲームショウ 2014 の基調講演より。", - "url": "https://www.youtube.com/watch?v=xelYnWcYkuE", - "group": "", - "keywords": [], - "tags": [], - "image": "https://img.youtube.com/vi/xelYnWcYkuE/hqdefault.jpg", - "type": "youtube" - }, - { - "lang": "ja", - "title": "Playtime Tokyo", - "titleFriendly": "", - "summary": "アプリビジネスのノウハウを各担当者が講演しました。", - "url": "https://www.youtube.com/playlist?list=PLCOC_kP3nqGIHEgwm9mybvA04Vn4Cg9nn", - "group": "", - "keywords": [], - "tags": [], - "image": "https://img.youtube.com/vi/lJdjY3z6-LY/hqdefault.jpg", - "type": "youtube" - }, - { - "lang": "ja", - "title": "Android Wear 関連の動画に日本語字幕が付きました", - "titleFriendly": "", - "summary": "", - "url": "https://googledevjp.blogspot.jp/2014/12/android-wear.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://i1.ytimg.com/vi/4JcDYkgqksY/maxresdefault.jpg", - "type": "blog" - }, - { - "lang": "ja", - "title": "Android Studio 1.0 をリリースしました", - "titleFriendly": "", - "summary": "", - "url": "https://googledevjp.blogspot.jp/2014/12/android-studio-10.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://3.bp.blogspot.com/-1hV3sD1At74/VIaQSWBasUI/AAAAAAAABAU/9vYLJMsmMuQ/s1600/studio-logo.png", - "type": "blog" - }, - { - "lang": "ja", - "title": "Google Play 開発者サービス 6.5 のご紹介", - "titleFriendly": "", - "summary": "", - "url": "https://googledevjp.blogspot.jp/2014/12/google-play-65.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://1.bp.blogspot.com/-4BNREC0Jojo/VGo7ahW35wI/AAAAAAAABAc/9thZl94F6fY/s1600/GMS%2B-%2BRelease%2BBlog%2BNacho%2B-%2BMap%2BToolbar.png", - "type": "blog" - }, - { - "lang": "ja", - "title": "Alpha and Beta Testing", - "titleFriendly": "", - "summary": "アプリのローンチにまつわるリスクを最小限にするために必須のツールです。[英語コンテンツ]", - "url": "intl/ja/distribute/googleplay/developer-console.html#alpha-beta", - "group": "", - "keywords": [], - "tags": [], - "image": "images/gp-dc-ab.png", - "type": "distribute" - }, - { - "lang": "ja", - "title": "Finding Success on Google Play", - "titleFriendly": "", - "summary": "Google Play での成功の秘訣がこの一冊に。[英語コンテンツ]", - "url": "intl/ja/distribute/googleplay/guide.html", - "group": "", - "keywords": [], - "tags": [], - "image": "distribute/images/play_dev_guide_b.jpg", - "type": "distribute" - }, - { - "lang": "ja", - "title": "Core App Quality", - "titleFriendly": "", - "summary": "", - "url": "intl/ja/distribute/essentials/quality/core.html", - "group": "", - "keywords": [], - "tags": [], - "image": "images/gp-core-quality.png", - "type": "distribute" - }, - { - "lang": "ja", - "title": "Google Play アプリ ポリシー センター", - "titleFriendly": "", - "summary": "", - "url": "https://support.google.com/googleplay/android-developer/answer/4430948?hl=ja", - "group": "", - "keywords": [], - "tags": [], - "image": "https://storage.googleapis.com/support-kms-prod/SNP_712EA2784949DDF085C46E3BE7B1DC618A09_4389356_en_v0", - "type": "distribute" - }, - { - "lang": "ja", - "title": "Developer Support", - "titleFriendly": "", - "summary": "", - "url": "intl/ja/support.html", - "group": "", - "keywords": [], - "tags": [], - "image": "", - "type": "distribute" - }, - { - "lang": "ja", - "title": "Wear App Quality", - "titleFriendly": "", - "summary": "いよいよウェアラブルの時代が到来。[英語コンテンツ]", - "url": "intl/ja/distribute/essentials/quality/wear.html", - "group": "", - "keywords": [], - "tags": [], - "image": "distribute/images/gp-wear-quality.png", - "type": "distribute" - }, - { - "lang": "ja", - "title": "Google Cloud Platform が支える、新感覚リアルタイム RPG ユニゾンリーグ - 株式会社エイチームの GCP 導入事例", - "titleFriendly": "", - "summary": "スケーラブルなバックエンドを実現する Google Cloud Platform の最新導入事例。", - "url": "https://googleforwork-japan.blogspot.jp/2014/12/gcp-google-cloud-platform-rpg-gcp.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://3.bp.blogspot.com/-xp7KoPkbne4/VI_PfoFil3I/AAAAAAAAA3U/-k1UZ0zjCBc/s1600/unison-league.jpeg", - "type": "distribute" - }, - { - "lang": "ja", - "title": "Monetize with Ads", - "titleFriendly": "", - "summary": "アプリ内広告成功のコツがここに。[英語コンテンツ]", - "url": "intl/ja/distribute/monetize/ads.html", - "group": "", - "keywords": [], - "tags": [], - "image": "distribute/images/advertising.jpg", - "type": "distribute" - }, - { - "lang": "ko", - "title": "구글 플레이 2015년 비전", - "titleFriendly": "", - "summary": "G-Star 구글 컨퍼런스", - "url": "https://www.youtube.com/watch?v=7X9Ue0Nfdh4&index=2&list=PL_WJkTbDHdBksDBRoqfeyLchEQqBAOlNl", - "group": "", - "keywords": [], - "tags": [], - "image": "https://img.youtube.com/vi/7X9Ue0Nfdh4/hqdefault.jpg", - "type": "youtube" - }, - { - "lang": "ko", - "title": "구글 플레이 게임", - "titleFriendly": "", - "summary": "게임 프로필, 퀘스트, 세이브드 게임 등의 신기능 소개", - "url": "https://www.youtube.com/watch?v=83FpwuschCQ", - "group": "", - "keywords": [], - "tags": [], - "image": "https://img.youtube.com/vi/83FpwuschCQ/hqdefault.jpg", - "type": "youtube" - }, - { - "lang": "ko", - "title": "안드로이드 5.0 롤리팝을 맞이하는 개발자를 위한 안내서", - "titleFriendly": "", - "summary": "", - "url": "https://googledevkr.blogspot.com/2014/11/android50guidefordevelopers.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://lh5.googleusercontent.com/0Gx4Ob_WvIgNOMv3hVMuUm4O7KuSWyxCEFIvy39_6fgXh2q2azqjZf3bpZoEk-LMW-K8GwYMfyYfMUAwp38hhPQ6WFNnddhN2E2_GF3-XBQI_qjhISviz10h_mGgDWsZKA", - "type": "blog" - }, - { - "lang": "ko", - "title": "안드로이드 앱을 위한 머티리얼 디자인 체크 리스트", - "titleFriendly": "", - "summary": "", - "url": "https://googledevkr.blogspot.com/2014/10/material-design-on-android-checklist.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://lh4.googleusercontent.com/JKoxeDdmsj6gYHV8rmp96U1jHj7FKeMzGBaaFu35kXp5EpJR9Ei9MQFAYghjwJoycdgydw-FZTuFNY8pDx63MWhy37rKC96ajoDXEMzvo9W0sj5yC2-uSYJdhpazVOP2cA", - "type": "blog" - }, - { - "lang": "ko", - "title": "App Compat 라이브러리", - "titleFriendly": "", - "summary": "", - "url": "https://googledevkr.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://2.bp.blogspot.com/-7fF9ayZ6PgI/U9iFpk5FNEI/AAAAAAAAAs0/4P4SCvdB_4M/s640/image00.png", - "type": "blog" - }, - { - "lang": "ko", - "title": "Alpha and Beta Testing", - "titleFriendly": "", - "summary": "출시 전에 완벽한 사전 테스트 [영문]", - "url": "intl/ko/distribute/googleplay/developer-console.html#alpha-beta", - "group": "", - "keywords": [], - "tags": [], - "image": "images/gp-dc-ab.png", - "type": "distribute" - }, - { - "lang": "ko", - "title": "Finding Success on Google Play", - "titleFriendly": "", - "summary": "구글 플레이에서 성공하는 비결 [영문]", - "url": "intl/ko/distribute/googleplay/guide.html", - "group": "", - "keywords": [], - "tags": [], - "image": "distribute/images/play_dev_guide_b.jpg", - "type": "distribute" - }, - { - "lang": "ko", - "title": "Core App Quality", - "titleFriendly": "", - "summary": "고품질 안드로이드 앱 개발 가이드 [영문]", - "url": "intl/ko/distribute/essentials/quality/core.html", - "group": "", - "keywords": [], - "tags": [], - "image": "images/gp-core-quality.png", - "type": "distribute" - }, - { - "lang": "ko", - "title": "Policy Guidelines and Practices", - "titleFriendly": "", - "summary": "숙지해야할 중요한 정책 [영문]", - "url": "https://support.google.com/googleplay/android-developer/answer/4430948?hl=ko", - "group": "", - "keywords": [], - "tags": [], - "image": "https://storage.googleapis.com/support-kms-prod/SNP_712EA2784949DDF085C46E3BE7B1DC618A09_4389356_en_v0", - "type": "distribute" - }, - { - "lang": "ko", - "title": "Developer Support", - "titleFriendly": "", - "summary": "개발자 지원 센터 활용 [영문]", - "url": "intl/ko/support.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://lh3.googleusercontent.com/-mGTYed3Uh-E/AAAAAAAAAAI/AAAAAAAAF58/qNYbk4mMhI0/s120-c/photo.jpg", - "type": "distribute" - }, - { - "lang": "ko", - "title": "Wear App Quality", - "titleFriendly": "", - "summary": "웨어러블 앱 개발 가이드 [영문]", - "url": "intl/ko/distribute/essentials/quality/wear.html", - "group": "", - "keywords": [], - "tags": [], - "image": "distribute/images/gp-wear-quality.png", - "type": "distribute" - }, - { - "lang": "ko", - "title": "Android TV 어플리케이션 개발", - "titleFriendly": "", - "summary": "앱과 게임을 거실에서 가족과 함께 [영문]", - "url": "intl/ko/tv/index.html", - "group": "", - "keywords": [], - "tags": [], - "image": "design/tv/images/atv-home.jpg", - "type": "distribute" - }, - { - "lang": "ko", - "title": "구글 플레이 게임 서비스", - "titleFriendly": "", - "summary": "다양한 구글 플레이 게임 서비스 기능 알아보기 [영문]", - "url": "intl/ko/google/play-services/games.html", - "group": "", - "keywords": [], - "tags": [], - "image": "https://developers.google.com/games/services/images/gamescreen3.jpg", - "type": "distribute" - }, - { - "lang": "ko", - "title": "Monetize with Ads", - "titleFriendly": "", - "summary": "광고로 수익 창출하기 [영문]", - "url": "intl/ko/distribute/monetize/ads.html", - "group": "", - "keywords": [], - "tags": [], - "image": "distribute/images/advertising.jpg", - "type": "distribute" - }, - { - "url":"https://www.youtube.com/watch?v=QDM52bblwlg", - "image": "images/distribute/hero-family-discovery.jpg", - "title": "Introducing the new family discovery experience on Google Play", - "summary": "Help families create little moments on Google Play. Opt-in your apps now.", - "tags":["families","googleplay"], - "type":"youtube" - }, - { - "url":"https://www.youtube.com/watch?v=wcjqBSei3a0&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS", - "image": "https://i1.ytimg.com/vi/wcjqBSei3a0/maxresdefault.jpg", - "title": "Developers connecting the world through Google Play", - "summary": "The mobile ecosystem is empowering developers to make good on the dream of connecting the world through technology to improve people's lives.", - "tags":["io15","googleplay"], - "keywords":["Google I/O 2015","io"], - "type":"youtube" - }, - { - "url":"https://www.youtube.com/watch?v=B6ydLpkhq04&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS", - "image": "https://i1.ytimg.com/vi/B6ydLpkhq04/maxresdefault.jpg", - "title": "Store Listing Experiments for Google Play", - "summary": "Learn how to use Google Play’s new store listing optimization feature to get more installs of your app, and how to test different graphics and text to find out which options perform the best. ", - "tags":["io15","googleplay","store listing"], - "tags":["google i/o","google play","store listing"], - "type":"youtube" - }, - { - "url":"https://www.youtube.com/watch?v=jyO3-rF4Mu0&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS", - "image": "https://i1.ytimg.com/vi/jyO3-rF4Mu0/maxresdefault.jpg", - "title": "Growing games with Google", - "summary": "The games industry has never been more promising and full of opportunities. This talk covers how Google is helping developers across a broad range of existing and emerging platforms.", - "tags":["io15","android", "googleplay","games"], - "keywords":["Google I/O","google play","games"], - "type":"youtube" - }, - { - "url":"https://www.youtube.com/watch?v=yJisuP94lHU", - "image": "images/distribute/hero-playtime-opener.jpg", - "title": "Playtime 2015: Innovation happens everywhere", - "type":"Video", - "tags":["googleplay"], - "summary": "Watch the opening video from Google Play's annual event series, Playtime, which celebrates inspirational developers who are changing the world around them.", - }, -{ - "url":"https://www.youtube.com/watch?v=JrR6o5tYMWQ", - "image": "images/distribute/hero-acquisition-devbyte.jpg", - "title": "User acquisition and tracking on Google Play", - "type" : "Video", - "tags" : "users,googleplay,googleio", - "summary": "Learn how to get new users, using Universal app campaigns directly within the Google Play Developer Console to increase your installs from ads, and find out how your acquisition channels perform.", - }, -]); - -var CAROUSEL_OVERRIDE = { - "distribute/googleplay/guide.html": { - "image": "images/distribute/hero-secrets-to-app-success.jpg", - "title": "The Secrets to App Success on Google Play", - "summary": "Get the updated guide full of useful features, tips, and best practices that will help you grow a successful app or game business on Google Play.", - }, - "about/versions/lollipop.html": { - "image": "images/home/hero-lollipop_2x.png", - "heroColor": "#263238", - "heroInvert": true, - "title": "Android 5.0 Lollipop", - "summary": "The Android 5.0 update adds a variety of new features for your apps, such as notifications on the lock screen, an all-new camera API, OpenGL ES 3.1, the new naterial design interface, and much more.", - }, - "http://www.youtube.com/watch?v=Pms0pcyPbAM": { - "url":"https://www.youtube.com/watch?v=Pms0pcyPbAM&list=PLWz5rJ2EKKc9ofd2f-_-xmUi07wIGZa1c]", - "image": "images/distribute/hero-carousel-giftedmom.jpg", - "title": "Gifted Mom reaches more mothers across Africa with Android", - "type":"youtube", - "summary": "Gifted Mom is an app developed in Cameroon which provides users with critical information about pregnancy, breastfeeding and child vaccinations. Hear the creators explain how they built their business on Google Play.", - }, - "http://www.youtube.com/watch?v=9m6MoBM-sFI": { - "url":"https://www.youtube.com/watch?v=9m6MoBM-sFI&list=PLWz5rJ2EKKc9ofd2f-_-xmUi07wIGZa1c&index=3", - "image": "images/distribute/hero-carousel-sgn.jpg", - "title": "SGN increases installs with Store Listing Experiments", - "type" : "youtube", - "summary": "Watch mobile game developer SGN talk about how using Store Listing Experiments to test multiple variants across their portfolio of games helped improve their ROI, conversion rates and gamer retention.", - }, - "http://www.youtube.com/watch?v=e7t3svG9PTk": { - "url":"https://www.youtube.com/watch?v=e7t3svG9PTk&index=2&list=PLWz5rJ2EKKc9ofd2f-_-xmUi07wIGZa1c", - "image": "images/distribute/hero-carousel-djit.jpg", - "title": "DJiT builds higher quality experiences on Android", - "type" : "youtube", - "summary": "Learn how Music app developer DJiT create higher quality apps with improved latency on Android Marshmallow, as well as other Android and Google Play features.", - }, - "http://www.youtube.com/watch?v=J3IvOfvH1ys": { - "url":"https://www.youtube.com/watch?v=J3IvOfvH1ys&list=PLWz5rJ2EKKc9ofd2f-_-xmUi07wIGZa1c&index=1", - "image": "images/distribute/hero-carousel-wego.jpg", - "title": "Wego increases user retention with material design", - "type" : "youtube", - "summary": "Hear how online travel marketplace Wego, increased monthly user retention by 300% and reduced uninstall rates by up to 25% with material design.", - }, - "https://www.youtube.com/watch?v=QDM52bblwlg": { - "url":"distribute/googleplay/families/about.html", - "image": "images/distribute/hero-family-discovery.jpg", - "title": "Designed for families", - "summary": "Introducing the new family discovery experience in Google Play. Your apps can benefit from enhanced discoverability and maintain their existing categories, rankings, and reviews elsewhere in the store. Opt-in your apps today.", - "type":"distribute", - }, - "https://www.youtube.com/watch?v=wcjqBSei3a0&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS": { - "url":"https://www.youtube.com/watch?v=wcjqBSei3a0&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS", - "image": "images/distribute/hero-IO15-google-play.jpg", - "title": "Connecting the world through Google Play", - "tags":["io15"], - "summary": "In this this Google I/O talk, hear how the mobile ecosystem is empowering developers to connect the world through technology and improve people's lives.", - }, - "https://www.youtube.com/watch?v=B6ydLpkhq04&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS": { - "image": "images/distribute/hero-store-listing-experience.jpg", - "title": "Using Google Play store listing experiments", - "tags":["io15"], - "summary": "Learn how to use Google Play store listing experiments to get more installs in this Google I/O talk. Test different graphics and text to find out which options perform the best. ", - }, - "https://www.youtube.com/watch?v=jyO3-rF4Mu0&list=PLOU2XLYxmsIKLNUPiFCWVtcO7mZRZ9MmS": { - "image": "images/distribute/hero-IO15-growing-games.jpg", - "title": "Growing games with Google", - "tags":["io15"], - "summary": "The games industry has never been more promising and full of opportunities. This talk from Google I/O 2015 covers how Google is helping developers across a broad range of existing and emerging platforms.", - } -}; diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js index 5e271b978580164e4534378df19fd9b983058363..1a97db4dc94ec53ee630500102b60728e76baf9b 100644 --- a/docs/html/jd_extras_en.js +++ b/docs/html/jd_extras_en.js @@ -155,6 +155,16 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "tags": ["monitor"], "lang":"en" }, + { + "title":"GPU Debugger", + "summary":"Use the GPU Debugger to analyze and debug your OpenGL ES apps. Inspect the GPU state and understand what caused a specific rendering outcome.", + "url":"studio/debug/am-gpu-debugger.html", + "image":"images/tools/thumbnails/am-gpu-debugger_2-2_2x.png", + "type":"tools", + "keywords": ["android","performance","profiling","tools","monitor","debug"], + "tags": ["android","performance","profiling","tools","monitor","debug"], + "lang":"en" + }, { "title":"HPROF Viewer and Analyzer", "summary":"Use the Memory Monitor to dump the Java heap to an HPROF file. The HPROF Viewer displays classes, instances of each class, and a reference tree to help you track memory usage and find memory leaks.", @@ -1021,6 +1031,17 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "image":"images/google/gps-play_games_logo.png", "type":"distribute" }, + { + "title": "Play Games Quality", + "category": "google", + "summary": "Meet the basic expectations of game players through compelling features and an intuitive, well-designed UI.", + "url": "https://developers.google.com/games/services/checklist", + "group": "", + "keywords": ["games", "play games", "quality"], + "tags": [], + "image": "images/cards/distribute/engage/card-game-services.png", + "type": "distribute" + }, { "title":"Get Started with Analytics", "category":"google", @@ -1943,12 +1964,64 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "url": "https://support.google.com/googleplay/answer/2651410", "timestamp": null, "image": "images/cards/google-play_2x.png", - "title": "Google Play Accepted Payment Methods", + "title": "Google Play accepted payment methods", "summary": "Support details on the payment methods supported in Google Play.", "keywords": ["gift card"], "type": "distribute", "category": "google play" }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://support.google.com/adwords/answer/2471188", + "timestamp": null, + "image": "images/play_dev.jpg", + "title": "AdWords Conversion Optimizer", + "summary": "Learn how Conversion Optimizer works to find the users who are most likely to convert and to serve them your conversion ads.", + "keywords": [], + "type": "distribute", + "titleFriendly": "" + }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://developers.google.com/app-conversion-tracking/", + "timestamp": null, + "image": "images/play_dev.jpg", + "title": "Track conversions with the AdWords SDK or server API", + "summary": "Use the lightweight AdWords app SDK or server-to-server API to track remarketing conversions.", + "keywords": [], + "type": "distribute", + "titleFriendly": "" + }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://support.google.com/analytics/answer/2611404", + "timestamp": null, + "image": "images/play_dev.jpg", + "title": "Create Remarketing Audiences in Google Analytics", + "summary": "Learn how to use preconfigured audiences created by the Analytics team or create your own to use in your conversion campaigns.", + "keywords": [], + "type": "distribute", + "titleFriendly": "" + }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://support.google.com/adwords/answer/1704341", + "timestamp": null, + "image": "images/play_dev.jpg", + "title": "Link your Google Analytics and AdWords accounts", + "summary": "Gain greater insight into how AdWords is driving app engagement and conversions, and use this insight to improve your ads and app.", + "keywords": [], + "type": "distribute", + "titleFriendly": "" + }, { "lang": "en", "group": "", @@ -2599,6 +2672,19 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "type": "design", "category": "material design" }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://material.google.com/patterns/notifications.html", + "timestamp": "1469639720", + "image": "images/cards/card-notifications_2x.png", + "title": "Notifications", + "summary": "Notifications inform your app’s users about relevant and timely events in your app.", + "keywords": ["notifications", "design"], + "type": "design", + "category": "material design" + }, { "lang": "en", "group": "", @@ -2681,7 +2767,6 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "type": "design", "category": "material design" }, - { "lang": "en", "group": "", @@ -2695,6 +2780,45 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "type": "distribute", "category": "google" }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://developers.google.com/nearby/", + "timestamp": null, + "image": "images/play_dev.jpg", + "title": "Create features based on proximity", + "summary": "Build simple interactions between nearby devices and people.", + "keywords": ["nearby", "engage"], + "type": "distribute", + "titleFriendly": "" + }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://www.youtube.com/watch?v=hultDpBS22s", + "timestamp": null, + "image": "images/play_dev.jpg", + "title": "Use Nearby Messages to collaborate", + "summary": "Nearby Messages is perfect for setting up ad-hoc groups, collaborative sessions, or sharing resources with people in a co-located space.", + "keywords": ["nearby", "engage"], + "type": "distribute", + "titleFriendly": "" + }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://developers.google.com/beacons", + "timestamp": null, + "image": "images/play_dev.jpg", + "title": "Mark up the world using beacons", + "summary": "Give your users better location and proximity experiences by providing a strong context signal for their devices in the form of Bluetooth low energy (BLE) beacons with Eddystone.", + "keywords": ["nearby", "engage"], + "type": "distribute", + "titleFriendly": "" + }, { "lang": "en", "group": "", @@ -2792,6 +2916,19 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "type": "distribute", "category": "google" }, + { + "lang": "en", + "group": "", + "tags": [], + "url": "https://www.udacity.com/courses/ud876-3", + "timestamp": null, + "image": "distribute/images/advertising.jpg", + "title": "Learn how to show ads in your Android app", + "summary": "Take this online course to learn how to use AdMob to display ads in your Android app.", + "keywords": ["marketing", "analytics"], + "type": "distribute", + "titleFriendly": "" + }, { "lang": "en", "group": "", @@ -2844,7 +2981,6 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "type": "distribute", "category": "google" }, - { "lang": "en", "group": "", @@ -2853,7 +2989,7 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "timestamp": 1383243492000, "image": "images/cards/google-search_2x.png", "title": "Set Up App Indexing", - "summary": "Surface your app content in Google seaerch. Deep link direct to your apps.", + "summary": "Surface your app content in Google search. Deep link direct to your apps.", "keywords": ["search", "appindexing", "engagement", "getusers"], "type": "distribute", "category": "google" @@ -2878,7 +3014,7 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "url": "https://developers.google.com/identity/sign-in/android/people", "timestamp": 1383243492000, "image": "images/cards/google-sign-in_2x.png", - "title": "Get user profile details", + "title": "Get User Profile Details", "summary": "After users sign-in with Google, you can access their age range, language, and public profile information.", "keywords": ["signin", "identity", "google"], "type": "distribute", @@ -3613,6 +3749,59 @@ METADATA['en'].extras = METADATA['en'].extras.concat([ "lang":"en", "type":"Video" }, + + { + "title":"Android Performance Testing Codelab", + "titleFriendly":"", + "summary":"This codelab shows how to create a stable and reusable testing harness to run performance tests on a very simple existing app.", + "url":"https://codelabs.developers.google.com/codelabs/android-perf-testing/index.html", + "group":"", + "keywords": ["testing"], + "tags": [ + ], + "image":"images/testing/testing-icon.png", + "type":"google" + }, + + { + "title":"Introduction to Doze", + "category":"android developers", + "summary":"A new way for the device to preserve battery by entering into an idle state.", + "url":"https://www.youtube.com/watch?v=N72ksDKrX6c", + "group":"", + "keywords": ["android, performance","battery"], + "tags": ["video, performance"], + "image":"https://i1.ytimg.com/vi/N72ksDKrX6c/maxresdefault.jpg", + "lang":"en", + "type":"develop" + }, + + { + "title":"Performance Profiling Tools", + "category":"training", + "summary":"Take a look under the hood to identify performance bottlenecks.", + "url":"https://developer.android.com/tools/performance/index.html", + "group":"", + "keywords": ["android, performance","profiling"], + "tags": ["android, performance"], + "image": null, + "lang":"en", + "type":"develop" + }, + + { + "title":"Managing Your App's Memory", + "category":"training", + "summary":"Learn how you can proactively reduce memory usage while developing for Android.", + "url":"https://developer.android.com/training/articles/memory.html", + "group":"", + "keywords": ["android, performance","profiling"], + "tags": ["android, performance"], + "image": null, + "lang":"en", + "type":"develop" + }, + { "url":"https://www.youtube.com/watch?v=QDM52bblwlg", "image": "images/distribute/hero-family-discovery.jpg", @@ -3948,8 +4137,8 @@ METADATA['en'].collections = { "develop/landing/tools": { "title": "", "resources": [ - "https://www.youtube.com/watch?v=ZOz_yr8Yxq8&list=PLWz5rJ2EKKc_w6fodMGrA1_tsI3pqPbqa", - "https://www.youtube.com/watch?v=eOV2owswDkE&list=PLWz5rJ2EKKc_w6fodMGrA1_tsI3pqPbqa", + "https://www.youtube.com/watch?v=NbHsi3-uR8E&list=PLWz5rJ2EKKc_w6fodMGrA1_tsI3pqPbqa", + "https://www.youtube.com/watch?v=-SY5nkNVUn0&list=PLWz5rJ2EKKc_w6fodMGrA1_tsI3pqPbqa", "https://www.youtube.com/watch?v=StqAZ1OQbqA&list=PLWz5rJ2EKKc_w6fodMGrA1_tsI3pqPbqa", "https://www.youtube.com/watch?v=-SY5nkNVUn0&list=PLWz5rJ2EKKc_w6fodMGrA1_tsI3pqPbqa", "https://www.youtube.com/watch?v=4rI4tTd7-J8&list=PLWz5rJ2EKKc_w6fodMGrA1_tsI3pqPbqa", @@ -4107,7 +4296,8 @@ METADATA['en'].collections = { "distribute/engage/easy-signin.html", "distribute/analyze/build-better-apps.html", "distribute/engage/gcm.html", - "distribute/engage/beta.html" + "distribute/engage/beta.html", + "distribute/engage/nearby.html" ] }, "distribute/monetize": { @@ -4118,6 +4308,7 @@ METADATA['en'].collections = { "distribute/monetize/ads.html", "distribute/monetize/ecommerce.html", "distribute/monetize/payments.html", + "distribute/monetize/conversions.html", "distribute/analyze/understand-user-value.html", ] }, @@ -4195,6 +4386,7 @@ METADATA['en'].collections = { "distribute/essentials/quality/wear.html", "distribute/essentials/quality/tv.html", "distribute/essentials/quality/auto.html", + "https://developers.google.com/games/services/checklist", "distribute/essentials/quality/billions.html", "https://developers.google.com/edu/guidelines" ] @@ -4427,6 +4619,14 @@ METADATA['en'].collections = { "https://support.google.com/adwords/answer/6167162" ] }, + "distribute/users/nearby": { + "title": "", + "resources": [ + "https://developers.google.com/nearby/", + "https://www.youtube.com/watch?v=hultDpBS22s", + "https://developers.google.com/beacons" + ] + }, "distribute/users/buildbuzz": { "title": "", "resources": [ @@ -4505,7 +4705,7 @@ METADATA['en'].collections = { "design/patterns/navigation.html", "design/patterns/actionbar.html", "design/style/iconography.html", - "design/patterns/notifications.html" + "https://material.google.com/patterns/notifications.html" ] }, "distribute/essentials/corequalityguidelines/functionality": { @@ -4702,7 +4902,7 @@ METADATA['en'].collections = { "distribute/getusers/notifications": { "title": "", "resources": [ - "design/patterns/notifications.html", + "https://material.google.com/patterns/notifications.html", "distribute/engage/gcm.html", "https://play.google.com/about/developer-content-policy.html" ] @@ -4818,7 +5018,7 @@ METADATA['en'].collections = { "distribute/essentials/optimizing-your-app.html", "distribute/tools/launch-checklist.html", "distribute/googleplay/developer-console.html", - "design/patterns/notifications.html" + "https://material.google.com/patterns/notifications.html" ] }, "distribute/engage/video/more": { @@ -5064,6 +5264,15 @@ METADATA['en'].collections = { "https://support.google.com/googleplay/answer/2651410" ] }, + "distribute/monetize/conversions": { + "title": "", + "resources": [ + "https://support.google.com/adwords/answer/2471188", + "https://developers.google.com/app-conversion-tracking/", + "https://support.google.com/analytics/answer/2611404", + "https://support.google.com/adwords/answer/1704341" + ] + }, "topic/libraries": { "title": "", "resources": [ @@ -5166,6 +5375,47 @@ METADATA['en'].collections = { "https://storage.googleapis.com/androiddevelopers/shareables/stories/Senri_LeosFortune_gpgs.pdf" ] }, + "distribute/stories/games/docs": { + "title": "", + "resources": [ + "distribute/stories/games/animoca-star-girl.html", + "distribute/stories/games/happy-labs-experiment.html", + "distribute/stories/games/playlab-puzzles.html", + "distribute/stories/games/upbeat-games.html", + "distribute/stories/games/tapps.html", + "distribute/stories/games/noodlecake-super-stickman.html", + "distribute/stories/games/glu-tap-baseball.html", + "distribute/stories/games/doctor-who-legacy.html", + "distribute/stories/games/glu-dh.html", + "distribute/stories/games/dots.html", + "distribute/stories/games/kongregate-adv-cap.html", + "distribute/stories/games/kongregate-global-assault.html", + "distribute/stories/games/leos-fortune.html", + "distribute/stories/games/tiny-co.html", + "distribute/stories/games/g4a-indian-rummy.html", + "distribute/stories/games/rvappstudios-zombie.html", + "distribute/stories/games/glu-eternity-warriors.html", + "distribute/stories/games/hotheadgames-firefight.html", + "distribute/stories/games/concrete-bowling.html", + "distribute/stories/games/gameloft-asphalt8.html" + ] + }, + "distribute/stories/apps/docs": { + "title": "", + "resources": [ + "distribute/stories/apps/condenast-shopping.html", + "distribute/stories/apps/economist-espresso.html", + "distribute/stories/apps/expressen-sports.html", + "distribute/stories/apps/drupe-communications.html", + "distribute/stories/apps/noom-health.html", + "distribute/stories/apps/aftenposten.html", + "distribute/stories/apps/el-mundo.html", + "distribute/stories/apps/segundamano.html", + "distribute/stories/apps/remember-the-milk.html", + "distribute/stories/apps/intuit-mint.html", + "distribute/stories/apps/sayhi.html", + ] + }, "training/testing/overview": { "title": "", "resources": [ @@ -5265,6 +5515,12 @@ METADATA['en'].collections = { "studio/profile/am-sysinfo.html" ] }, +"tools/help/gpu": { + "title": "", + "resources": [ + "studio/debug/am-gpu-debugger.html" + ] + }, "tools/help/shot": { "title": "", "resources": [ @@ -5364,36 +5620,51 @@ METADATA['en'].collections = { "title": "", "resources": [ "https://medium.com/google-developers/how-often-should-you-update-android-studio-db25785c488e#.8blbql35x", - "http://android-developers.blogspot.com/2016/04/android-studio-2-0.html", + "https://android-developers.blogspot.com/2016/09/android-studio-2-2.html", "https://medium.com/google-developers/writing-more-code-by-writing-less-code-with-android-studio-live-templates-244f648d17c7#.hczcm02du", ] }, - "preview/landing/resources": { + "nougat/landing/resources": { "title": "", "resources": [ - "preview/overview.html", - "preview/api-overview.html", - "preview/behavior-changes.html", - "preview/setup-sdk.html", - "preview/samples.html", - "preview/support.html" + "about/versions/nougat/android-7.0.html", + "about/versions/nougat/android-7.0-changes.html", + "about/versions/nougat/android-7.0-samples.html", ] }, - "preview/landing/more": { + + "nougat/landing/videos/first": { "title": "", "resources": [ - "https://www.youtube.com/watch?v=CsulIu3UaUM", - "preview/features/multi-window.html", - "preview/features/notification-updates.html", - "preview/features/background-optimization.html", - "preview/features/data-saver.html", - "preview/features/direct-boot.html", - "preview/features/icu4j-framework.html", - "preview/features/multilingual-support.html", - "preview/features/scoped-folder-access.html", - "preview/features/security-config.html", - "preview/features/picture-in-picture.html", - "preview/features/tv-recording-api.html" + "https://www.youtube.com/watch?v=CsulIu3UaUM" + ] + }, + + "develop/performance/landing": { + "title": "", + "resources": [ + "https://android-developers.blogspot.com/2010/07/multithreading-for-performance.html", + "https://www.udacity.com/course/ud825", + "https://www.youtube.com/watch?v=N72ksDKrX6c", + "tools/performance/index.html", + "https://codelabs.developers.google.com/codelabs/android-perf-testing/index.html", + "training/articles/memory.html", + ] + }, + "nougat/landing/more": { + "title": "", + "resources": [ + "guide/topics/ui/multi-window.html", + "guide/topics/ui/notifiers/notifications.html", + "topic/performance/background-optimization.html", + "training/basics/network-ops/data-saver.html", + "training/articles/direct-boot.html", + "guide/topics/resources/icu4j-framework.html", + "guide/topics/resources/multilingual-support.html", + "training/articles/scoped-directory-access.html", + "training/articles/security-config.html", + "training/tv/playback/picture-in-picture.html", + "training/tv/tif/content-recording.html" ] }, "work/landing/primary": { diff --git a/docs/html/jd_extras_zh-cn.js b/docs/html/jd_extras_zh-cn.js index cb1ccb7d6ee3d551e2d4d5167d73860b0954869e..866a87efed8f6184af980c723d7f2d083ad51c3d 100644 --- a/docs/html/jd_extras_zh-cn.js +++ b/docs/html/jd_extras_zh-cn.js @@ -244,40 +244,40 @@ METADATA['zh-cn'].collections = { "overview/zhcn/1": { "title": "", "resources": [ - "intl/zh-cn/distribute/essentials/quality/core.html", - "intl/zh-cn/distribute/essentials/quality/tablets.html", - "intl/zh-cn/distribute/tools/launch-checklist.html", - "intl/zh-cn/tools/publishing/publishing_overview.html", - "intl/zh-cn/distribute/tools/localization-checklist.html" + "distribute/essentials/quality/core.html", + "distribute/essentials/quality/tablets.html", + "distribute/tools/launch-checklist.html", + "tools/publishing/publishing_overview.html", + "distribute/tools/localization-checklist.html" ] }, "overview/zhcn/2": { "title": "", "resources": [ - "intl/zh-cn/google/play/billing/index.html", - "intl/zh-cn/google/play/billing/api.html", - "intl/zh-cn/google/play/billing/billing_admin.html", - "intl/zh-cn/google/play/billing/billing_testing.html", - "intl/zh-cn/google/play/billing/billing_best_practices.html" + "google/play/billing/index.html", + "google/play/billing/api.html", + "google/play/billing/billing_admin.html", + "google/play/billing/billing_testing.html", + "google/play/billing/billing_best_practices.html" ] }, "overview/zhcn/3": { "title": "", "resources": [ "https://play.google.com/intl/en_us/badges/", - "intl/zh-cn/distribute/tools/promote/device-art.html", - "intl/zh-cn/distribute/tools/promote/linking.html", - "intl/zh-cn/distribute/tools/promote/brand.html", - "intl/zh-cn/tools/help/proguard.html" + "distribute/tools/promote/device-art.html", + "distribute/tools/promote/linking.html", + "distribute/tools/promote/brand.html", + "tools/help/proguard.html" ] }, "overview/zhcn/4": { "title": "", "resources": [ - "intl/zh-cn/design/style/writing.html", - "intl/zh-cn/training/basics/fragments/fragment-ui.html", - "intl/zh-cn/training/multiscreen/index.html", - "intl/zh-cn/training/monitoring-device-state/index.html" + "design/style/writing.html", + "training/basics/fragments/fragment-ui.html", + "training/multiscreen/index.html", + "training/monitoring-device-state/index.html" ] }, "overview/carousel/zhcn": { diff --git a/docs/html/license.jd b/docs/html/license.jd index 4f4036b412117add2e4d54344dd5535f8089a62f..e843c6b35e07b9271c58b239a389933028a5aadb 100644 --- a/docs/html/license.jd +++ b/docs/html/license.jd @@ -9,7 +9,7 @@ excludeFromSuggestions=true

    For the purposes of licensing, the content of this web site is divided into two categories:

      -
    • Documentation content, including both static documentation and content extracted from source +
    • Documentation content, including both static documentation and content extracted from source code modules, as well as sample code, and
    • All other site content
    @@ -66,7 +66,7 @@ it as an audiobook for the visually impaired, or even translate it.

    license, note that proprietary trademarks and brand features are not included in that license. -
  • Google's trademarks and other brand features (including the +
  • Google's trademarks and other brand features (including the Android stylized typeface logo) are not included in the license. @@ -74,7 +74,7 @@ Please see Brand Guidelines for information about this usage.
  • -
  • In some cases, a page may include content, such as an image, that is not +
  • In some cases, a page may include content, such as an image, that is not covered by the license. In that case, we will label the content that is not licensed.
  • In addition, content linked from a page on this site is not covered @@ -92,22 +92,22 @@ Proper attribution is required when you reuse or create modified versions of content that appears on a page made available under the terms of the Creative Commons Attribution license. On this site, the requirement for attribution applies only to the non-documentation -content, as described earlier in this document. The complete -requirements for attribution can be found in section 4b of the +content, as described earlier in this document. The complete +requirements for attribution can be found in section 4b of the Creative Commons legal code.

    In practice we ask that you provide attribution to the Android Open - Source project to the best of the ability of the medium in which you - are producing the work. There are several typical ways in which this + Source project to the best of the ability of the medium in which you + are producing the work. There are several typical ways in which this might apply:

    Exact Reproductions

    If your online work exactly reproduces text or images from this site, in whole or in part, please include a paragraph at the bottom - of your page that reads: + of your page that reads:

    Portions of this page are reproduced from work created and - -

    - - - - diff --git a/docs/html/ndk/downloads/index.jd b/docs/html/ndk/downloads/index.jd deleted file mode 100644 index 28860b28894c01d8b1d7830831c5b4e492c55e27..0000000000000000000000000000000000000000 --- a/docs/html/ndk/downloads/index.jd +++ /dev/null @@ -1,530 +0,0 @@ -ndk=true -page.template=sdk -page.title=NDK Downloads - -@jd:body - - - -
    -
    -
    -
    -
    - -
    -
    -

    Download the Android NDK

    -
    -
    -
    -
    -
    -
    -
    -

    Before installing the Android - NDK, - you must agree to the following terms - and conditions.

    -
    -
    -

    Terms and Conditions

    -This is the Android Software Development Kit License Agreement - -

    1. Introduction

    -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. - - -

    2. Accepting this License Agreement

    -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. - - -

    3. SDK License from Google

    -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. - - -

    4. Use of the SDK by You

    -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. - - -

    5. Your Developer Credentials

    -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. - - -

    6. Privacy and Information

    -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. - - -

    7. Third Party Applications

    -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. - - -

    8. Using Android APIs

    -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. - - -

    9. Terminating this License Agreement

    -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. - - -

    10. DISCLAIMER OF WARRANTIES

    -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. - - -

    11. LIMITATION OF LIABILITY

    -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. - - -

    12. Indemnification

    -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. - - -

    13. Changes to the License Agreement

    -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. - - -

    14. General Legal Terms

    -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. - -November 20, 2015 -
    - - - -
    -

    - - -

    -

    -
    - -
    -
    - -
  • - - - - - - - - -

    Select, from the table above, the NDK package for your development platform. For information - about the changes in the newest version of the NDK, see Release Notes. For - information about earlier revisions, see - NDK Revision History.

    - - - - -

    Release Notes

    - -

    - Android NDK, Revision 12 (June 2016) -

    - -
    -
    - Announcements -
    - -
      -
    • The ndk-build command will default to using - Clang in an upcoming release. GCC will be removed in a later release. -
    • -
    • The make-standalone-toolchain.sh script will be removed - in an upcoming release. If you use this script, please plan to migrate to the - make_standalone_toolchain.py as soon as possible. -
    • -
    - -
    - NDK -
    - -
      -
    • Removed support for the armeabi-v7a-hard ABI. See the explanation in the - - documentation. -
    • - -
    • Removed all sysroots for platform levels prior to Android 2.3 (API level 9). - We dropped support for them in NDK r11, but neglected to actually remove them. -
    • - -
    • Updated exception handling when using c++_shared on ARM32 so that it - mostly works (see Known Issues). The unwinder - is now linked into each linked object rather than into libc++ itself. -
    • - -
    • Pruned the default compiler flags (NDK Issue 27). You can see - details of this update in Change 207721. -
    • - -
    • Added a Python implementation of standalone toolchains in - build/tools/make_standalone_toolchain.py. On Windows, you no longer - need Cygwin to use this feature. Note that the bash flavor will be removed - in an upcoming release, so please test the new one now. -
    • - -
    • Configured Clang debug builds to have the -fno-limit-debug-info - option is enabled by default. This change enables better debugging with LLDB. -
    • - -
    • Enabled the --build-id as a default option. This option - causes an identifier to be shown in native crash reports so you can easily - identify which version of your code was running. -
    • - -
    • Fixed issue with NDK_USE_CYGPATH so that it no longer causes - problems with libgcc - (Issue 195486). -
    • - -
    • Enabled the following options as default: - -Wl,--warn-shared-textrel and -Wl,--fatal-warnings. - If you have shared text relocations, your app does not load on Android 6.0 - (API level 23) and higher. Note that this configuration has never been - allowed for 64-bit apps. -
    • - -
    • Fixed a few issues so that precompiled headers work better - (NDK Issue 14, - NDK Issue 16). -
    • - -
    • Removed unreachable ARM (non-thumb) STL libraries. -
    • - -
    • Added Vulkan support to android-24. -
    • - -
    • Added Choreographer API to android-24. -
    • - -
    • Added libcamera2 APIs for devices that support the - INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED feature level or higher. - For more information, see the - - CameraCharacteristics reference. -
    • - -
    - -
    - Clang -
    - -
      -
    • Clang has been updated to 3.8svn (r256229, build 2812033). Note that - Clang packaged in the Windows 64-bit NDK is actually 32-bit. -
    • - -
    • Fixed __thread so that it works for real this time. -
    • -
    - -
    - GCC -
    - -
      -
    • Synchronized the compiler with the ChromeOS GCC @ google/gcc-4_9 r227810. -
    • - -
    • Backported coverage sanitizer patch from ToT (r231296). -
    • - -
    • Fixed libatomic to not use ifuncs (NDK Issue 31). -
    • -
    - -
    - Binutils -
    - -
      -
    • Silenced the "Erratum 843419 found and fixed" info messages. -
    • - -
    • Introduced option --long-plt to fix an internal linker error - when linking huge arm32 binaries. -
    • - -
    • Fixed wrong run time stubs for AArch64. This problem was - causing jump addresses to be calculated incorrectly for very large - dynamic shared objects (DSOs). -
    • - -
    • Introduced default option --no-apply-dynamic to work around - a dynamic linker bug for earlier Android releases. -
    • - -
    • Fixed a known issue with NDK r11 where dynamic_cast was not - working with Clang, x86, stlport_static and optimization. -
    • -
    - -
    - GDB -
    - -
      -
    • Updated to GDB version 7.11. For more information about this release, see - GDB News. -
    • - -
    • Fixed a number of bugs in the ndk-gdb.py script. -
    • -
    - -
    - Known Issues -
    - -
      -
    • The x86 Address - Sanitizer (ASAN) currently does not work. For more information, see - Issue 186276. -
    • - -
    • Exception unwinding with c++_shared does not work for ARM on - Android 2.3 (API level 9) or Android 4.0 (API level 14). -
    • - -
    • Bionic headers and libraries for Android 6.0 (API level 23) and higher - are not yet exposed despite the presence of android-24. Those platforms still - have the Android 5.0 (API level 21) headers and libraries, which is consistent - with NDK r11. -
    • - -
    • The RenderScript tools are not present, which is consistent with - NDK r11. - (NDK Issue 7) -
    • - -
    • In NdkCameraMetadataTags.h header file, the camera metadata - tag enum value ACAMERA_STATISTICS_LENS_SHADING_CORRECTION_MAP - was listed by accident and will be removed in next release. Use - the ACAMERA_STATISTICS_LENS_SHADING_MAP value instead. -
    • - -
    - -
    diff --git a/docs/html/ndk/downloads/revision_history.jd b/docs/html/ndk/downloads/revision_history.jd deleted file mode 100644 index 211b64e5be4b28a3ae77542dcdc6b31617c7a9d8..0000000000000000000000000000000000000000 --- a/docs/html/ndk/downloads/revision_history.jd +++ /dev/null @@ -1,3766 +0,0 @@ -page.title=NDK Revision History -@jd:body - -

    This page provides information on previous releases of the NDK, enumerating the changes that -took place in each new version.

    - - -
    - -

    - Android NDK, Revision 11c (March 2016) -

    -
    - -
    -
    -
      -
    • Changes -
        -
      • Applied additional fixes to the {@code ndk-gdb.py} script. -
      • -
      • Added an optional package name argument to the {@code ndk-gdb} - command {@code --attach} option. - (Issue 13) -
      • -
      • Fixed invalid toolchain paths for 32-bit Windows platform. - (Issue 45) -
      • -
      • Fixed the relative path for the {@code ndk-which} command. - (Issue 29) -
      • -
      • Fixed use of cygpath for the libgcc compiler. - (Android Issue 195486) -
      • -
      -
    • -
    -
    -
    - -
    -
    - -
    - -

    - Android NDK, Revision 11b (March 2016) -

    -
    - -
    -
    NDK
    -
    -
      -
    • Important announcements - -
    • - -
    • Changes -
        -
      • {@code ndk-gdb.py} is fixed. It had - regressed entirely - in r11.
      • -
      • {@code ndk-gdb} for Mac - is fixed.
      • -
      • Added more top-level shortcuts for command line tools: -
          -
        • {@code ndk-depends}.
        • -
        • {@code ndk-gdb}.
        • -
        • {@code ndk-stack}.
        • -
        • {@code ndk-which}. This command had been entirely absent from previous - releases.
        • -
        -
      • -
      • Fixed standalone toolchains for libc++, which had been missing - {@code __cxxabi_config.h}.
      • -
      • Fixed help documentation for {@code --toolchain} in - {@code make-standalone-toolchain.sh}.
      • - -
      -
    - -
    Clang
    -
    -
      -
    • Errata
    • -
        -
      • Contrary to what we reported in the r11 Release Notes, {@code __thread} - does not work. This is because the version of Clang we ship is missing a bug fix for - emulated TLS support.
      • -
      -
    -
    -
    - - -
    -
    - -
    - -

    - Android NDK, Revision 11 (March 2016) -

    -
    -
    -
    Clang
    -
    -
      -
    • Important announcements -
        -
      • We strongly recommend switching to Clang. -
          -
        • If you experience problems with Clang, file bugs - here for issues - specific to Clang in the NDK. For more general Clang issues, - file bugs by following the instructions on - this page.
        • -
        -
      • -
      • Clang has been updated to 3.8svn (r243773, build 2481030). -
          -
        • This version is a nearly pure upstream Clang.
        • -
        • The Windows 64-bit downloadable NDK package contains a 32-bit - version of Clang.
        • -
        -
      • -
      -
    • - -
    • Additions -
        -
      • Clang now provides support for emulated TLS. -
          -
        • The compiler now supports {@code __thread} by emulating - ELF TLS with pthread thread-specific data.
        • -
        • C++11 {@code thread_local} works in some cases, but not - for data with non-trivial destructors, because those cases - require support from libc. This limitation does not - apply when running on Android 6.0 (API level 23) or newer.
        • -
        • Emulated TLS does not yet work with Aarch64 when - TLS variables are accessed from a shared library.
        • -
        -
      • -
      -
    -
    - -
    -
    GCC
    -
    -
      -
    • Important announcements
    • -
        -
      • GCC in the NDK is now deprecated in favor of Clang. -
          -
        • The NDK will neither be upgrading to 5.x, nor accept - non-critical backports.
        • -
        • Maintenance for miscompiles and internal compiler errors - in 4.9 will be handled on a case by case basis.
        • -
        -
      • -
      -
    • Removals -
        -
      • Removed GCC 4.8. All targets now use GCC 4.9.
      • -
      -
    • -
    • Other changes -
        -
      • Synchronized google/gcc-4_9 to r224707. Previously, it had been - synchronized with r214835.
      • -
      -
    • -
    -
    -
    -
    -
    NDK
    -
    -
      -
    • Important announcements -
        -
      • The samples are no longer included in the NDK package. - They are instead available on - GitHub. -
      • -
      • The documentation is no longer included in the NDK package. - Instead, it is on the Android - developer website.
      • -
      -
    • - -
    • Additions -
        -
      • Added a native tracing API to {@code android-23}.
      • -
      • Added a native multinetwork API to {@code android-23}.
      • -
      • Enabled libc, m, and dl to provide versioned symbols, starting - from API level 21.
      • -
      • Added Vulkan headers and library to API level N.
      • -
      -
    • - -
    • Removals -
        -
      • Removed support for {@code _WCHAR_IS_8BIT}.
      • -
      • Removed sed.
      • -
      • Removed mclinker.
      • -
      • Removed Perl.
      • -
      • Removed from all versions of NDK libc, m, and dl all symbols which - the platform versions of those libs do not support.
      • -
      • Partially removed support for mips64r2. The rest will be removed - in the future.
      • -
      -
    • - -
    • Other changes -
        -
      • Changed ARM standalone toolchains to default to arm7. -
          -
        • You can restore the old behavior by passing specifying the - {@code -target} option as {@code armv5te-linux-androideabi}. -
        • -
        -
      • -
      • Changed the build system to use {@code -isystem} for platform - includes. -
          -
        • Warnings that bionic causes no longer break app builds.
        • -
        -
      • -
      • Fixed a segfault that occurred when a binary threw exceptions - via gabi++. (Issue 179410) -
      • -
      • Changed libc++’s inline namespace to {@code std::__ndk1} - to prevent ODR issues with platform libc++.
      • - -
      • All libc++ libraries are now built with libc++abi. -
      • Bumped default {@code APP_PLATFORM} to Gingerbread. -
          -
        • Expect support for Froyo and older to be dropped in a - future release.
        -
      -
    • Updated gabi++ {@code _Unwind_Exception} struct for 64 bits. -
    • Added the following capabilities to cpufeatures: -
        -
      • Detect SSE4.1 and SSE4.2.
      • -
      • Detect cpu features on x86_64.
      • -
      -
    • -
    • Updated libc++abi to upstream - - r231075. -
    • Updated {@code byteswap.h}, {@code endian.h}, {@code sys/procfs.h}, - {@code sys/ucontext.h}, {@code sys/user.h}, and {@code uchar.h} from - ToT Bionic. -
    • Synchronized {@code sys/cdefs.h} across all API levels. - -
    • Fixed {@code fegetenv and fesetenv} for arm. -
    • Fix end pointer size/alignment of {@code crtend_*} for mips64 - and x86_64. -
    - - - -
    -
    -
    -
    Binutils
    -
    -
      -
    • Additions -
        -
      • Added a new option: {@code --pic-veneer}.
      • -
      -
    • - -
    • Removals -
        -
      • The 32-bit Windows package no longer contains ld.gold. - You can instead get ld.gold from the 64-bit Windows package.
      • -
      -
    • - -
    • Changes -
        -
      • Unified binutils source between Android and ChromiumOS. - For more information on this change, see the comments - - here.
      • -
      • Improved reliability of Gold for aarch64. Use - {@code -fuse-ld=gold} at link time to use gold instead of bfd. - The default will likely switch in the next release.
      • -
      • Improved linking time for huge binaries for Gold ARM back end - (up to 50% linking time reduction for debuggable Chrome Browser). -
      • -
      -
    • -
    -
    -
    -
    -
    GDB
    -
    -
      - -
    • Removals -
        -
      • Removed ndk-gdb in favor of ndk-gdb.py.
      • -
      -
    • - -
    • Changes -
        -
      • Updated gdb to version 7.10.
      • -
      • Improved performance.
      • -
      • Improved error messages.
      • -
      • Fixed relative project paths.
      • -
      • Stopped Ctrl-C from killing the backgrounded gdbserver.
      • -
      • Improved Windows support.
      • -
      -
    • -
    -
    - -
    -
    -
    YASM
    -
    -
      - -
    • Changes -
        -
      • Updated YASM to version 1.3.0.
      • -
      -
    • -
    -
    - -
    -
    -
    Known issues
    -
    -
      -
    • x86 ASAN does not currently work. For more information, see the - discussion - here.
    • -
    • The combination of Clang, x86, stlport_static, and optimization - levels higher than {@code -O0} causes test failures with - {@code dynamic_cast}. For more information, see the comments - here. -
    • -
    • Exception handling often fails with c++_shared on ARM32. The root - cause is incompatibility between the LLVM unwinder that libc++abi uses - for ARM32 and libgcc. This behavior is not a regression from r10e.
    • -
    -
    -
    - -
    -
    - -
    - -

    - Android NDK, Revision 10e (May 2015) -

    -
    -
    -
    Important changes:
    -
    -
      -
    • Integrated the workaround for Cortex-A53 Erratum 843419 into the - {@code aarch64-linux-android-4.9} linker. For more information on this workaround, see - Workaround for cortex-a53 - erratum 843419.
    • - -
    • Added Clang 3.6; {@code NDK_TOOLCHAIN_VERSION=clang} now picks that version - of Clang by default.
    • - -
    • Removed Clang 3.4.
    • - -
    • Removed GCC 4.6.
    • - -
    • Implemented multithreading support in {@code ld.gold} for all architectures. It can - now link with or without support for multithreading; the default is to do it without. -
        -
      • To compile with multithreading, use the {@code --threads} option.
      • -
      • To compile without multithreading, use the {@code --no-threads} option.
      • -
      -
    • - -
    • Upgraded GDB/gdbserver to 7.7 for all architectures.
    • - -
    • Removed the NDK package for 32-bit Darwin.
    • -
    -
    -
    - - -
    Important bug fixes:
    -
    -
      -
    • Fixed a crash that occurred when there were OpenMP loops outside of the main thread.
    • - -
    • Fixed a GCC 4.9 internal compiler error (ICE) that occured when the user declared - {@code #pragma GCC optimize ("O0")}, but had a different level of optimization specified - on the command line. The {@code pragma} takes precedence.
    • - -
    • Fixed an error that used to produce a crash with the following error message: -
      -in add_stores, at var-tracking.c:6000
      -
      -
    • - -
    • Implemented a workaround for a Clang 3.5 issue in which LLVM auto-vectorization - generates {@code llvm.cttz.v2i64()}, an instruction with no counterpart in the ARM - instruction set.
    • -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Made the following header and library fixes:
    • -
        -
      • Fixed {@code PROPERTY_*} in {@code media/NdkMediaDrm.h}.
      • -
      • Fixed {@code sys/ucontext.h} for {@code mips64}.
      • -
      • Dropped the Clang version check for {@code __builtin_isnan} and - {@code __builtin_isinf}.
      • -
      • Added {@code android-21/arch-mips/usr/include/asm/reg.h} - and {@code android-21/arch-mips64/usr/include/asm/reg.h}.
      • -
      - - -
    • Fixed a spurious array-bounds warning that GCC 4.9 produced for x86, and reenabled the - array bounds warning that GCC 4.9 had produced for ARM. The warning for ARM had - previously been unconditionally disabled.
    • - -
    • Fixed Clang 3.5 for {@code mips} and {@code mips64} to create a writable - {@code .gcc_except_table} section, thus matching GCC behavior. This change allows you - to avoid the following linker warning: - -
      -.../ld: warning: creating a DT_TEXTREL in a shared object
      -
      -
    • - -
    • Backported a fix for {@code compiler-rt} issues that were causing crashes when Clang - compiled for {@code mips64}. For more information, see LLVM Issue - 20098.
    • - -
    • Fixed Clang 3.5 crashes that occurred on non-ASCII comments. (Issue - 81440)
    • - -
    • Fixed {@code stlport collate::compare} to return {@code -1} and {@code 1}. Previously, - it had returned arbitrary signed numbers.
    • - -
    • Fixed {@code ndk-gdb} for 64-bit ABIs. (Issue - 118300)
    • - -
    • Fixed the crash that the HelloComputeNDK sample for RenderScript was producing on - Android 4.4 (Android API level 19). For more information, see - this page.
    • - -
    • Fixed {@code libc++ __wrap_iter} for GCC. For more information, see LLVM Issue - 22355.
    • - -
    • Fixed {@code .asm} support for ABI {@code x86_64}.
    • - -
    • Implemented a workaround for the GCC 4.8 {@code stlport} issue. (Issue - 127773)
    • - -
    • Removed the trailing directory separator {@code \\} from the project path in Windows. - (Issue 160584) -
    • - -
    • Fixed a {@code no rule to make target} error that occurred when compiling a single - {@code .c} file by executing the {@code ndk-build.cmd} command from {@code gradle}. (Issue - 66937)
    • - -
    • Added the {@code libatomic.a} and {@code libgomp.a} libraries that had been missing from - the following host toolchains: -
        -
      • {@code aarch64-linux-android-4.9}
      • -
      • {@code mips64el-linux-android-4.9}
      • -
      • {@code mipsel-linux-android-4.9}
      • -
      • {@code x86_64-4.9}
      • -
      -
    -
    - -
    Other changes:
    -
    -
      -
    • Added {@code ld.gold} for {@code aarch64}. The default linker remains {@code ld.bfd}. - To explicitly enable {@code ld.gold}, add {@code -fuse-ld=gold} to the - {@code LOCAL_LDFLAGS} or {@code APP_LDFLAGS} variable.
    • - -
    • Built the MIPS and MIPS64 toolchains with {@code binutils-2.25}, which provides improved - R6 support.
    • - -
    • Made {@code -fstandalone-debug} (full debug info) a default option for Clang.
    • - -
    • Replaced {@code -fstack-protector} with {@code -fstack-protector-strong} for - the ARM, AArch64, X86, and X86_64 toolchains for GCC 4.9, Clang 3.5, and - Clang 3.6.
    • - -
    • Added the {@code --package} command-line switch to {@code ndk-gdb} to allow the build - system to override the package name. (Issue - 56189)
    • - -
    • Deprecated {@code -mno-ldc1-stc1} for MIPS. This option may not work with the new - {@code -fpxx} and {@code -mno-odd-spreg} options, or with the FPXX ABI.
    • - -
    • Added MIPS MSA and R6 detection to {@code cpu-features}.
    • - -
    -
    -
    - -
    -
    - -
    - -

    - Android NDK, Revision 10d (December 2014) -

    -
    -
    -
    Important changes:
    -
    -
      -
    • Made GCC 4.8 the default for all 32-bit ABIs. Deprecated GCC 4.6, and - will remove it next release. To restore previous behavior, either add - NDK_TOOLCHAIN_VERSION=4.6 to ndk-build, or - add --toolchain=arm-linux-androideabi-4.6 when executing - make-standalone-toolchain.sh on the command line. GCC 4.9 remains the - default for 64-bit ABIs.
    • - -
    • Stopped all x86[_64] toolchains from adding -mstackrealign by default. The - NDK toolchain assumes a 16-byte stack alignment. The tools and options used by default - enforce this rule. A user writing assembly code must make sure to preserve stack - alignment, and ensure that other compilers also comply with this rule. - (GCC bug 38496)
    • - -
    • Added Address Sanitizer functionality to Clang 3.5 support to the ARM and x86 ABIs. - For more information on this change, see the - Address - Sanitizer project.
    • - -
    • Introduced the requirement, starting from API level 21, to use -fPIE -pie - when building. In API levels 16 and higher, ndk-build uses PIE - when building. This change has a number of implications, which are discussed in - - Developer Preview Issue 888. - These implications do not apply to shared libraries.
    • -
    -
    -
    - - -
    Important bug fixes:
    -
    -
      -
    • Made more fixes related to - - A53 Errata #835769 in the aarch64-linux-android-4.9 linker. As part of this, GCC - passes a new option, --fix-cortex-a53-835769, when - -mfix-cortex-a53-835769 (enabled by default) is specified. - For more information, see this - binutils message - and this - binutils message. -
    • - -
    • Documented a fix to a libc++ sscanf/vsscanf hang that occurred in API level - 21. The fix itself had been implemented in r10c. - (Issue 77988)
    • - -
    • Fixed an AutoFDO (-fauto-profile) crash that occurred with GCC 4.9 when - -Os was specified. (Issue 77571)
    • -
    -
    - - -
    Other bug fixes:
    -
    -
      -
    • Made the following header and library fixes:
    • -
        -
      • Added posix_memalign to API level 16. Also, added a prototype in - stdlib.h to API levels 16 to 19. - (Issue 77861)
      • -
      • Fixed stdatomic.h so that it includes <atomic> only for - C++11.
      • -
      • Modified the following headers for standalone use: sys/user.h, and - gl2ext.h, dlext.h, fts.h, sgidefs.h - for API level 21.
      • -
      • Modified sys/user.h to rename mxcsr_mask as mxcr_mask, - and to change the data type for u_ar0
      • from unsigned long - to
        struct user_regs_struct*. -
      • Changed sysconf() return value type from int to - long.
      • -
      - -
    • Fixed ndk-build's handling of thumb for LOCAL_ARM_MODE: In - r10d, ndk-build adds LOCAL_LDFLAGS+=-mthumb by default, unless one of the - following conditions applies:
    • -
        -
      • You have set LOCAL_ARM_MODE equal to arm.
      • -
      • You are doing a debug build (with settings such as APP_OPTIM=debug and - AndroidManifest.xml containing android:debuggable="true"), - where ARM mode is the default in order to retain compatibility with earlier toolchains. - (Issue 74040)
      • -
      - -
    • Fixed LOCAL_SRC_FILES in ndk-build to use Windows absolute paths. - (Issue 74333)
    • - -
    • Removed bash-specific code from ndk-gdb. (Issue 73338)
    • - -
    • Removed bash-specific code from make-standalone-toolchain.sh. - (Issue 74145)
    • - -
    • Revised documentation concerning a fix for System.loadLibrary() transitive - dependencies. (Issue 41790)
    • - -
    • Fixed a problem that was preventing 64-bit packages from extracting on Ubuntu 14.04 and - OS X 10.10 (Yosemite). (Issue 78148)
    • - -
    • Fixed an issue with LOCAL_PCH to improve Clang support. (Issue - 77575)
    • - -
    • Clarified "requires executable stack" warning from ld.gold. (Issue - 79115)
    • -
    -
    - -
    -
    -
    - - - - - - - -
    - -

    - Android NDK, Revision 10c (October 2014) -

    -
    -
    -
    Important changes:
    -
    -
      -
    • Made the following changes to download structure:
    • -
        -
      • Each package now contains both the 32- and the 64-bit headers, libraries, and tools for - its respective platform.
      • -
      • STL libraries with debugging info no longer need be downloaded separately.
      • -
      -
    • Changed everything previously called Android-L to the official release - designation: android-21.
    • -
    • Updated GCC 4.9 by rebasing to the google branch - of the GCC repository. Major differences from the upstream version of GCC 4.9 include:
    • - -
        -
      • The -O2 option now turns on vectorization, without loop peeling but with more - aggressive unrolling.
      • -
      • Enhancements to FDO and - LIPO
      • -

        For more detailed information, see Important bug fixes below.

        -
      - -
    • Added Clang 3.5 support to all hosts: NDK_TOOLCHAIN_VERSION=clang - now picks Clang 3.5. Note that:
    • -
        - -
      • ARM and x86 default to using the integrated assembler. If this causes issues, use - -fno-integrated-as as a workaround. -
      • Clang 3.5 issues more warnings for unused flags, such as the -finline-functions - option that GCC supports.
      • -

        When migrating from projects using GCC, you can use - -Wno-invalid-command-line-argument and -Wno-unused-command-line-argument - to ignore the unused flags until you're able decide on what to do with them longer-term.

        - -
      -
    • Made it possible to enter ART debugging mode, when debugging on an Android 5.0 device using - ART as its virtual machine, by specifying the art-on option. For more information, - see prebuilt/common/gdb/common.setup in the directory containing the NDK.
    • -
    • Removed support for Clang 3.3.
    • -
    • Deprecated GCC 4.6, and may remove it from future releases.
    • -
    • Updated mclinker to 2.8 with Identical Code Folding ("ICF") support. Specify ICF using the - --icf option.
    • -
    • Broadened arm_neon.h support in x86 and x86_64, attaining coverage of ~93% of - NEON intrinsics. For more information about NEON support: -
        -
      • Navigate to the NDK Programmer's Guide (docs/Programmers_Guide/html/), and see - Architectures and CPUs > Neon.
      • -
      • Examine the updated hello-neon sample in samples/. -
      • See Intel's guide to porting from ARM NEON to Intel SSE.
      • -
      -
    • Documented support for _FORTIFY_SOURCE in headers/libs/android-21, - which appeared in r10 (when android-21 was still called Android-L), - but had no documentation.
    • -
    -
    -
    - - -
    Important bug fixes:
    -
    - -
    - - -
    Other bug fixes:
    -
    -
      -
    • Made the following header and library fixes to android-21: -
        - -
      • Added more TV keycodes: android/keycodes.h
      • -
      • Added more constants and six new sensor functions to android/sensor.h: - ASensorManager_getDefaultSensorEx, ASensor_getFifoMaxEventCount, - ASensor_getFifoReservedEventCount, ASensor_getStringType, - ASensor_getReportingMode, and ASensor_isWakeUpSensor.
      • -
      • Fixed stdatomic.h to improve compatibility with GCC 4.6, and provide support - for the <atomic> header.
      • -
      • Added sys/ucontext.h and sys/user.h to all API levels. The - signal.h header now includes <sys/ucontext.h>. You may - remove any existing definition of struct ucontext.
      • -
      • Added posix_memalign to API levels 17, 18, and 19.
      • -
      • Added the following functions to all architectures: - android_set_abort_message, posix_fadvise, - posix_fadvise64, pthread_gettid_np.
      • -
      • Added the required permissions to the native-media/AndroidManifest.xml - sample. - (Issue 106640)
      • -
      • Added clock_nanosleep and clock_settime to API level 21. (Issue - 77372) -
      • Removed the following symbols from all architectures: - get_malloc_leak_info, free_malloc_leak_info, - __srget, __swbuf, __srefill, __swsetup, - __sdidinit, __sflags, __sfp, - __sinit, __smakebuf, __sflush, __sread, - __swrite, __sseek, __sclose, - _fwalk, __sglue, __get_thread, __wait4, - __futex_wake, __open, __get_tls, - __getdents64, and dlmalloc.
      • -
      • Removed the following functions from the 64-bit architectures: basename_r, - dirname_r, __isthreaded, _flush_cache (mips64).
      • -
      • Removed the following function from the 32-bit architectures: - __signalfd4.
      • -
      • Changed the type of the third argument from size_t to int in - the following functions: strtoll_l, strtoull_l, - wcstoll_l, and wcstoull_l.
      • -
      • Restored the following functions to the 64-bit architecture: arc4random, - arc4random_buf, and arc4random_uniform.
      • -
      • Moved cxa_* and the new and delete operators back - to libstdc++.so. This change restores r9d behavior; previous versions of r10 - contained dummy files.
      • - -
      -
    • Restored MXU support in GCC 4.8 and 4.9 for mips. This support had been absent from - r10 and r10b because those versions of GCC had been compiled with binutils-2.24, which did - not support MXU. It now does.
    • -
    • Fixed --toolchain= in make-standalone-toolchain.sh so that it - now properly supports use of a suffix specifying a version of Clang.
    • -
    • Fixed the libc++/armeabi strtod() functions.
    • -
    • Made fixes to NDK documentation in docs/.
    • -
    -
    - -
    Other changes:
    -
    -
      -
    • Enhanced cpu-features to detect ARMv8 support for the following - instruction sets: AES, CRC32, SHA2, SHA1, and 64-bit PMULL/PMULL2. (Issue - 106360)
    • - -
    • Modified ndk-build to use *-gcc-ar, which is available in GCC 4.8, GCC 4.9, and - Clang. Clang specifies it, instead of *-ar. This setting brings improved LTO - support.
    • - -
    • Removed the include-fixed/linux/a.out.h and - include-fixed/linux/compiler.h headers from the GCC compiler. - (Issue 73728)
    • - -
    • Fixed an issue related to -flto with GCC 4.8 on Mac OS X. The error message - read:
    • - -
      -.../ld: error: .../libexec/gcc/arm-linux-androideabi/4.9/liblto_plugin.so
      -Symbol not found: _environ
      -
      - -
    • Fixed a typo in build-binary.mk. (Issue - 76992)
    • -
    -
    - -
    Important known issues:
    -
    -
      -
    • Specifying -Os (-fauto-profile) in GCC4.9 may cause crashing. - (Issue 77571)
    • -
    -
    - -
    -
    -
    - -
    - -

    - Android NDK, Revision 10b (September 2014) -

    -
    -
    - -
    Important notes:
    -
    -
      -
    • Because of the 512MB size restriction on downloadable packages, the following 32-bit items are not in the 32-bit NDK download packages. Instead, they reside in the 64-bit ones:
    • -
        -
      • Android-L headers
      • -
      • GCC 4.9
      • -
      -
    • Currently, the only Renderscript support provided by the NDK is for 32-bit Renderscript with Android 4.4 (API level 19). You cannot build HelloComputeNDK (the only Renderscript sample) with any other combination of Renderscript (32- or 64-bit) and Android version.
    • -
    • To compile native-codec, you must use a 64-bit NDK package, which is where all the Android-L headers are located.
    • -
    -
    - - -
    Important bug fixes:
    -
    -
      -
    • Fixed gdb 7.6 in GCC 4.8/4.9. (Issues 74112 and 74371.)
    • -
    • Fixed GCC 4.8/4.9 for x86, so that they no longer enable -msse4.2 and -mpopcnt by default. (Issue 73843.)
    • -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Removed stdio.h from the include-fixed/ directories of all versions of GCC. (Issue 73728.)
    • -
    • Removed duplicate header files from the Windows packages in the platforms/android-L/arch-*/usr/include/linux/netfilter*/ directories. (Issue 73704.)
    • -
    • Fixed a problem that prevented Clang from building HelloComputeNDK.
    • -
    • Fixed atexit. (Issue 66595.)
    • -
    • Made various fixes to the docs in docs/ and sources/third_party/googletest/README.NDK. (Issue 74069.)
    • -
    • Made the following fixes to the Android-L headers:
    • -
        -
      1. Added the following functions to ctype.h and wchar.h: dn_expand(), grantpt(), inet_nsap_addr(), inet_nsap_ntoa(), insque(), nsdispatch(), posix_openpt(), __pthread_cleanup_pop(), __pthread_cleanup_push(), remque(), setfsgid(), setfsuid(), splice(), tee(), twalk() (Issue 73719), and 42 *_l() functions.
      2. - -
      3. Renamed cmsg_nxthdr to __cmsg_nxthdr.
      4. - -
      5. Removed __libc_malloc_dispatch.
      6. - -
      7. Changed the ptrace() prototype to long ptrace(int, ...);.
      8. - -
      9. Removed sha1.h.
      10. - -
      11. Extended android_dlextinfo in android/dlext.h.
      12. - -
      13. Annotated __NDK_FPABI__ for functions receiving or returning float- or double-type values in stdlib.h, time.h, wchar.h, and complex.h.
      14. -
      -
    -
    - -
    Other changes:
    -
    -
      -
    • Updated mipsel-linux-android-4.9 and mips64el-linux-android-4.9, implementing a new multilib directory layout, and providing support for gdb-7.7
    • -
    • Enhanced cpu-features to detect more arm64 features. (Change list 100339.)
    • -
    - - -
    -
    -
    - -
    - -

    - Android NDK, Revision 10 (July 2014) -

    -
    -
    -
    Important changes:
    -
    -
      -
    • Added 3 new ABIs, all 64-bit: arm64-v8a, x86_64, mips64.
    • Note that: -
        -
      • GCC 4.9 is the default compiler for 64-bit ABIs. Clang is currently version 3.4. -NDK_TOOLCHAIN_VERSION=clang - may not work for arm64-v8a and mips64.
      • -
      • Android-L is the first level with 64-bit support. Note that this API -level is a temporary one, and only for L-preview. An actual API level number will replace it at -L-release.
      • -
      • This release includes now includes all32 and all64 -settings for APP_ABI. -
          -
        • APP_ABI=all32 is equivalent to -APP_ABI=armeabi,armeabi-v7a,x86,mips.
        • -
        • APP_ABI=all64 is equivalent to -APP_ABI=arm64-v8a,x86_64,mips64.
        • -
        • APP_ABI=all selects all ABIs.
        • -
        -
      • The new GNU libstdc++ in Android-L contains all <tr1/cmath> -Before defining your own math function, check _GLIBCXX_USE_C99_MATH_TR1 to see a -function with that name already exists, in order to avoid "multiple definition" errors from the -linker.
      • -
      • The cpu-features library has been updated for the ARMv8 kernel. The existing -cpu-features library may fail to detect the presence of NEON on the ARMv8 platform. Recompile your -code with the new version.
      • -
      -
    • Added a new platforms/android-L/ API directory. It includes:
    • -
        -
      • Updated Bionic headers, which had not changed from Android API levels 3 -(Cupcake) to 19 (KitKat). This new version, for level L, is to be synchronized with AOSP.
      • -
      • New media APIs and a native-codec sample.
      • -
      • An updated Android.h header for SLES/OpenSLES, enabling support for -single-precision, floating-point audio format in AudioPlayer.
      • -
      • GLES 3.1 and AEP extensions to libGLESv3.so.
      • -
      • GLES2 and GLES3 headers updated to the latest official Khronos versions.
      • -
      -
    • Added GCC 4.9 compilers to the 32-/64-bit ABIs. GCC 4.9 is the default (only) compiler -for 64-bit ABIs, as previously mentioned. For 32-bit ABIs, you must explcitly enable GCC 4.9, as -GCC 4.6 is still the default.
    • -
        -
      • For ndk-build, enable 32-bit, GCC 4.9 building either by adding -NDK_TOOLCHAIN_VERSION=4.9 to Application.mk, or exporting it as an -environment variable from the command line.
      • -
      • For a standalone toolchain, use the --toolchain= option in the -make-standalone-toolchain.sh script. For example: --toolchain=arm-linux-androideabi-4.9.
      • -
      -
    • Upgraded GDB to version 7.6 in GCC 4.8/4.9 and x86*. Since GDB is still at version GDB-7.3.x in -GCC 4.6 (the default for ARM and MIPS), you must set -NDK_TOOLCHAIN_VERSION=4.8 or 4.9 to enable ndk-gdb to select GDB 7.6.
    • -
    • Added the -mssse3 build option to provide SSSE3 support, and made it the default for ABI x86 -(upgrading from SSE3). The image released by Google does not contain SSSE3 instructions.
    • -
    • Updated GCC 4.8 to 4.8.3.
    • -
    • Improved ARM libc++ EH support by switching from gabi++ to libc++abi. For details, see the "C++ Support" section of the documentation. - Note that:
    • -
        -
      • All tests except for locale now pass for Clang 3.4 and GCC 4.8. For more -information, see the "C++ Support" section of the documentation.
      • -
      • The libc++ libraries for X86 and MIPS libc++ still use gabi++.
      • -
      • GCC 4.7 and later can now use <atomic>.
      • -
      • You must add -fno-strict-aliasing if you use <list>, because __list_imp::_end_ breaks - TBAA rules. (Issue 61571.)
      • -
      • As of GCC 4.6, LIBCXX_FORCE_REBUILD:=true no longer rebuilds libc++. Rebuilding it -requires the use of a different compiler. Note that Clang 3.3 is untested.
      • -
      -
    • mclinker is now version 2.7, and has aarch64 Linux support.
    • -
    • Added precompiled header support for headers specified by LOCAL_PCH. (Issue 25412).
    • -
    -
    - - -
    Important bug fixes:
    -
    -
      -
    • Fixed libc++ so that it now compiles std::feof, etc. (Issue 66668).
    • -
    • Fixed a Clang 3.3/3.4 atomic library call that caused crashes in some of the libc++ -tests for ABI armeabi.
    • -
    • Fixed Clang 3.4 crashes that were occurring on reading precompiled headers. (Issue 66657).
    • -
    • Fixed the Clang 3.3/3.4 -O3 assert on:
    • - llvm-3.2/llvm/include/llvm/MDBuilder.h:64: llvm::MDNode* -llvm::MDBuilder::createBranchWeights(llvm::ArrayRef): Assertion Weights.size() >= 2 -&& "Need at least two branch weights!" (Issue 57381). -
    • Fixed the following Clang 3.3/3.4 crash:
    • - Assertion failed: (!Fn && "cast failed but able to resolve overload expression!!"), function CheckCXXCStyleCast, file -Volumes/data/ndk-toolchain/src/llvm-3.3/llvm/tools/clang/lib/Sema/SemaCast.cpp, line 2018. -(Issue 66950). -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Fixed headers:
    • -
        -
      • Fixed 32-bit ssize_t to be int instead of long -int.
      • -
      • Fixed WCHAR_MIN and WCHAR_MAX so that they they take -appropriate signs according to the architecture they're running on:
      • -
          -
        • X86/MIPS: signed. -
        • ARM: unsigned. -
        • To force X86/MIPS to default to unsigned, use --D__WCHAR_UNSIGNED__.
        • -
        • To force wchar_t to be 16 bits, use -fshort-wchar.
        • -
        -
      • Removed non-existent symbols from 32-bit libc.so, and added pread64, -pwrite64, ftruncate64 for -Android API level 12 and higher. (Issue 69319). For more -information, see the commit message accompanying AOSP change list - 94137.
      • -
      -
    • Fixed GCC warning about redefinition of putchar. Warning message reads:
    • - include/stdio.h:236:5: warning: conflicts with previous declaration here -[-Wattributes] int putchar(int); (Change list 91185). -
    • Fixed make-standalone-toolchain.sh --stl=libc++ so that it:
    • -
        -
      • Copies cxxabi.h. (Issue 68001).
      • -
      • Runs in directories other than the NDK install directory. (Issues 67690 and 68647).
      • -
      -
    • Fixed GCC/Windows to quote arguments only when necessary for spawning processes in -external programs. This change decreases the likelihood of exceeding the 32K length limit.
    • -
    • Fixed an issue that made it impossible to adjust the APP_PLATFORM -environment variable.
    • -
    • Fixed the implementation of IsSystemLibrary() in crazy_linker so that it -uses strrchr() - instead of strchr() to find the library path's true basename.
    • -
    • Fixed native-audio's inability to build in debug mode.
    • -
    • Fixed gdb's inability to print extreme floating-point numbers. (Issue 69203).
    • -
    • Fixed Clang 3.4 inability to compile with -Wl,-shared (as opposed to --shared, which - had no compilation issues). The problem was that Clang added -pie for Android -targets if neither -shared nor -static existed. This behavior, which was -incorrect, caused the linker to complain that -shared and -pie could not -co-exist.
    • - -
    -
    - - -
    Other changes:
    -
    -
      -
    • Added arm_neon.h to the x86 toolchain so that it now emulates ~47% of -Neon. There is currently no support for 64-bit types. For more information, see the section on ARM -Neon intrinsics support in the x86 documentation.
    • -
    • Ported ARM/GOT_PREL optimization (present in GCC 4.6 built from the GCC google branch) to -ARM GCC 4.8/4.9. This optimization sometimes reduces instruction count when accessing global -variables. As an example, see the build.sh script in -$NDK/tests/build/b14811006-GOT_PREL-optimization/.
    • -
    • Added ARM version for STL gabi++, stlport, and libc++. They now have both it and Thumb -mode.
    • -
    • It is now possible to call the make-standalone-toolchain.sh script with ---toolchain=x86_64-linux-android-4.9, which is equivalent to ---toolchain=x86_64-4.9.
    • -
    - -
    -
    -
    - - -
    - -

    - Android NDK, Revision 9d (March 2014) -

    -
    -
    -
    Important changes:
    -
    -
      -
    • Added support for the Clang 3.4 compiler. The -NDK_TOOLCHAIN_VERSION=clang option now picks Clang 3.4. GCC 4.6 is -still the default compiler.
    • -
    • Added APP_ABI=armeabi-v7a-hard, with -additional multilib option -mfloat-abi=hard. These options are for -use with ARM GCC 4.6/4.8 and Clang 3.3/3.4 (which use 4.8's assembler, linker, -and libs). When using these options, note the following changes:
    • -
        -
      • When executing the ndk-build script, add the -following options for armeabi-v7a target: -
        TARGET_CFLAGS += -mhard-float -D_NDK_MATH_NO_SOFTFP=1
        -TARGET_LDFLAGS += -Wl,--no-warn-mismatch -lm_hard
        -The built library is copied to libs/armeabi-v7a. For make to -behave as expected, you cannot specify both armeabi-v7a and -armeabi-v7a-hard as make targets (i.e., on the APP_ABI= line). -Doing so causes one of them to be ignored. Note that APP_ABI=all -is still equivalent to -armeabi armeabi-v7a x86 mips.
      • -
      • The make-standalone-toolchain.sh script copies -additional libaries under /hard directories. - Add the above CFLAGS and LFLAGS to your -makefile to enable GCC or Clang to link with - libraries in /hard.
      • -
      -
    • Added the yasm assembler, as well as LOCAL_ASMFLAGS -and EXPORT_ASMFLAGS flags for x86 -targets. The ndk-build script uses -prebuilts/*/bin/yasm* to build LOCAL_SRC_FILES that -have the .asm extension.
    • -
    • Updated MClinker to 2.6.0, which adds -gc-sections -support.
    • -
    • Added experimental libc++ support (upstream r201101). Use this new -feature by following these steps: -
        -
      • Add APP_STL := c++_static or APP_STL := -c++_shared in Application.mk. - You may rebuild from source via LIBCXX_FORCE_REBUILD := -true
      • -
      • Execute make-standalone-toolchain.sh --stl=libc++ -to create a standalone toolchain with libc++ headers/lib.
      • -
      - For more information, see -CPLUSPLUS-SUPPORT.html. -(Issue 36496)
    • -
    -
    -
    -
    Important bug fixes:
    -
    -
      -
    • Fixed an uncaught throw from an unexpected -exception handler for GCC 4.6/4.8 ARM EABI. (GCC Issue 59392)
    • -
    • Fixed GCC 4.8 so that it now correctly resolves partial -specialization of a template with - a dependent, non-type template argument. (GCC Issue 59052)
    • -
    • Added more modules to prebuilt python (Issue 59902): -
        -
      • Mac OS X: zlib, bz2, -_curses, _curses_panel, _hashlib, -_ssl
      • -
      • Linux: zlib, nis, -crypt, _curses, and _curses_panel
      • -
      -
    • Fixed the x86 and MIPS gdbserver -event_getmsg_helper.
    • -
    • Fixed numerous issues in the RenderScript NDK toolchain, including -issues with compatibility across older devices and C++ reflection.
    • -
      -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Header fixes: -
        -
      • Fixed a missing #include <sys/types.h> in -android/asset_manager.h for Android API level 13 and higher. - (Issue 64988)
      • -
      • Fixed a missing #include in -android/rect_manager.h for Android API level 14 and higher.
      • -
      • Added JNICALL to JNI_OnLoad and -JNI_OnUnload in jni.h. Note that JNICALL - is defined as __NDK_FPABI__ For more information, see -sys/cdefs.h.
      • -
      • Updated the following headers so that they can be included -without the need to -manually include their dependencies (Issue 64679):
      • -
        -android/tts.h
        -EGL/eglext.h
        -fts.h
        -GLES/glext.h
        -GLES2/gl2ext.h
        -OMXAL/OpenMAXSL_Android.h
        -SLES/OpenSLES_Android.h
        -sys/prctl.h
        -sys/utime.h
        -
        -
      • Added sys/cachectl.h for all architectures. MIPS -developers can now include this header instead of writing #ifdef -__mips__.
      • -
      • Fixed platforms/android-18/include/android/input.h - by adding __NDK_FPABI__ to functions taking or returning -float or double values.
      • -
      • Fixed MIPS struct stat, which was incorrectly set -to its 64-bit counterpart for Android API level 12 and later. This wrong -setting was a -regression introduced in release r9c.
      • -
      • Defined __PTHREAD_MUTEX_INIT_VALUE, -__PTHREAD_RECURSIVE_MUTEX_INIT_VALUE, - and __PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE for Android API -level 9 and lower.
      • -
      • Added scalbln, scalblnf, and -scalblnl to x86 libm.so for APIs 18 and later.
      • -
      • Fixed a typo in -sources/android/support/include/iconv.h. - (Issue 63806)
      • - -
      -
    • -
    • Fixed gabi++ std::unexpected() to call -std::terminate() so that - a user-defined std::terminate() handler has a chance to run. -
    • -
    • Fixed gabi++ to catch std::nullptr.
    • -
    • Fixed samples Teapot and MoreTeapots: -
        -
      • Solved a problem with Tegra 2 and 3 chips by changing specular -variables to use medium precision. Values for specular power can now be less -than 1.0.
      • -
      • Changed the samples so that pressing the volume button restores -immersive mode and invalidates -SYSTEM_UI_FLAG_IMMERSIVE_STICKY. Screen rotation does not -trigger onSystemUiVisibilityChange, and so does not restore -immersive mode.
      • -
      -
    • -
    • Fixed the ndk-build script to add --rpath-link=$SYSROOT/usr/lib and --rpath-link=$TARGET_OUT in order to use ld.bfd to -link executables. (Issue 64266)
    • -
    • Removed -Bsymbolic from all STL builds.
    • -
    • Fixed ndk-gdb-py.cmd by setting SHELL as -an environment variable -instead of passing it to - python.exe, which ignores the setting. - (Issue 63054)
    • -
    • Fixed the make-standalone-toolchain.sh script so that -the --stl=stlport option copies the gabi++ headers instead of -symlinking them; the cmd.exe and MinGW shells do not understand -symlinks created by cygwin.
    • -
    -
    - -
    Other changes:
    -
    -
      -
    • Applied execution permissions to all *cmd scripts -previously intended for use only in the cmd.exe shell, in case -developers prefer to use ndk-build.cmd in cygwin instead of the -recommended ndk-build script.
    • -
    • Improved the speed of the make-standalone-toolchain.sh -script by moving instead of copying if the specified destination directory does -not exist.
    • -
    - -
    -
    -
    - -
    - -

    - Android NDK, Revision 9c (December 2013) -

    -
    -

    This is a bug-fix-only release.

    -
    -
    Important bug fixes:
    -
    -
      -
    • Fixed a problem with GCC 4.8 ARM, in which the stack pointer is -restored too early. This problem prevented the frame pointer from reliably -accessing a variable in the stack frame. (GCC Issue 58854)
    • -
    • Fixed a problem with GCC 4.8 libstdc++, in which a bug in -std::nth_element was causing generation of code that produced a random -segfault. (Issue 62910)
    • -
    • Fixed GCC 4.8 ICE in cc1/cc1plus with --fuse-ld=mcld, so that the following error no longer occurs: -
      cc1: internal compiler error: in common_handle_option, at
      -opts.c:1774
    • -
    • Fixed -mhard-float support for -__builtin math functions. For ongoing information on fixes for --mhard-float with STL, please follow Issue 61784.
    • -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Header fixes: -
        -
      • Changed prototype of poll to poll(struct -pollfd *, nfds_t, int); in poll.h.
      • -
      • Added utimensat to libc.so for Android -API levels 12 and 19. These libraries are now included for all Android API -levels 12 through 19.
      • -
      • Introduced futimens into libc.so, for Android API -level 19.
      • -
      • Added missing clock_settime() and -clock_nanosleep() to time.h for Android API level 8 -and higher.
      • -
      • Added CLOCK_MONOTONIC_RAW, CLOCK_REALTIME_COARSE, -CLOCK_MONOTONIC_COARSE, CLOCK_BOOTTIME, CLOCK_REALTIME_ALARM, and -CLOCK_BOOTTIME_ALARM in time.h.
      • -
      • Removed obsolete CLOCK_REALTIME_HR and -CLOCK_MONOTONIC_HR.
      • -
      -
    • -
    • In samples Teapot, MoreTeapots, and -source/android/ndk_helper: -
        -
      • Changed them so that they now use a hard-float abi for armeabi-v7a.
      • -
      • Updated them to use immersive mode on Android API level 19 and -higher.
      • -
      • Fixed a problem with Check_ReleaseStringUTFChars in -/system/lib/libdvm.so that was causing crashes on x86 devices.
      • -
      -
    • -
    • Fixed ndk-build fails that happen in cygwin when the NDK -package is -referenced via symlink.
    • -
    • Fixed ndk-build.cmd fails that happen in windows -cmd.exe when -LOCAL_SRC_FILES contains absolute paths. (Issue 69992)
    • -
    • Fixed the ndk-stack script to proceed even when it can't parse -a frame due to inability to find a routine, filename, or line number. In any of -these cases, it prints ??.
    • -
    • Fixed the ndk-stack stack for windows-x64_64 targets so that -it no longer erroneously matches a frame line with a line in the -stack: section that doesn't contain pc, -eip, or ip. For example: -
      I/DEBUG   ( 1151):     #00  5f09db68  401f01c4
      -/system/lib/libc.so
    • -
    • Fixed gabi++ so that it: -
        -
      • Does not use malloc() to allocate C++ thread-local - objects.
      • -
      • Avoids deadlocks in gabi++ in cases where libc.debug.malloc is -non-zero in userdebug/eng Android platform builds.
      • -
      -
    -
    - -
    Other changes:
    -
    -
      -
    • Added LOCAL_EXPORT_LDFLAGS.
    • -
    • Introduced the NDK_PROJECT_PATH=null setting for use in an -integrated build system where options are explicitly passed to -ndk-build. With this setting, ndk-build makes no -attempt to look for NDK_PROJECT_PATH. This setting also prevents -variables from deriving default settings from NDK_PROJECT_PATH. As a result, -the following variables must now be explicitly specified (with their default -values if such exist): NDK_OUT, NDK_LIBS_OUT, APP_BUILD_SCRIPT, -NDK_DEBUG (optional, default to 0), and other APP_*'s -contained in Application.mk.
    • -
    • APP_ABI can now be enumerated in a comma-delimited list. For -example: -
      APP_ABI := "armeabi,armeabi-v7a"
    • -
    • Provided the ability to rebuild all of STL with debugging info in an -optional, separate package called -android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip, using the --g option. This option -helps the ndk-stack script provide better a stack dump across STL. -This change should not affect the code/size of the final, stripped file.
    • -
    • Enhanced hello-jni samples to report APP_ABI at -compilation.
    • -
    • Used the ar tool in Deterministic mode (option --D) to build static libraries. (Issue 60705)
    • -
    -
    - -
    -
    -
    - -
    - -

    - Android NDK, Revision 9b (October 2013) -

    -
    -
    -
    Important changes:
    -
    -
      -
    • Updated {@code include/android/*h} and {@code math.h} for all Android API levels up to - 18, including the addition of levels 13, 15, 16 and 17. - For information on added APIs, see commit messages for Changes - 68012 and - 68014. - (Issues 47150, - 58528, and - 38423)
    • -
    • Added support for Android API level 19, including Renderscript binding.
    • -
    • Added support for -mhard-float in the existing armeabi-v7a ABI. For more - information and current restrictions on Clang, see - {@code tests/device/hard-float/jni/Android.mk}.
    • -
    • Migrated from GNU Compiler Collection (GCC) 4.8 to 4.8.2, and added diagnostic color - support. To enable diagnostic colors, set -fdiagnostics-color=auto, - -fdiagnostics-color=always, or export {@code GCC_COLORS} as shown below: -
      -GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
      -
      - For more information, see - GCC - Language Independent Options. -
    • -
    • Added two new samples to demonstrate OpenGL ES 3.0 features: Teapot and MoreTeapots. - These samples run on devices with Android 4.1 (API level 16) and higher.
    • -
    • Deprecated GCC 4.7 and Clang 3.2 support, which will be removed in the next - release.
    • -
    -
    - -
    Important bug fixes:
    -
    -
      -
    • Fixed problem with ARM GCC 4.6 {@code thumb2} failing to generate 16-bit relative jump - tables. (GCC Issue)
    • -
    • Fixed GCC 4.8 internal compiler error (ICE) on - {@code g++.dg/cpp0x/lambda/lambda-defarg3.C}. - (Change 62770, - GCC Issue)
    • -
    • Fixed a problem with Windows 32-bit {@code *-gdb.exe} executables failing to launch. - (Issue 58975)
    • -
    • Fixed GCC 4.8 ICE when building bullet library. The error message is as follows: -
      internal compiler error: verify_flow_info failed
      - (Issue 58916, - GCC Issue)
    • -
    • Modified GDB/ARM build to skip {@code ARM.exidx} data for unwinding in prologue code and - added a command ({@code set arm exidx-unwinding}) to control exidx-based stack unwinding. - (Issue 55826)
    • -
    • Fixed Clang 3.3 MIPS compiler problem where HI and LO registers are incorrectly - reused.
    • -
    • Fixed issue with MIPS 4.7 ICE in {@code dbx_reg_number}. The error message is as -follows: -
      -external/icu4c/i18n/decimfmt.cpp:1322:1:
      -internal compiler error: in dbx_reg_number, at dwarf2out.c:10185
      -
      - (GCC Patch) - -
    • - -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Header fixes -
        -
      • Fixed the ARM {@code WCHAR_MIN} and {@code WCHAR_MAX} to be unsigned according to - spec (the X86/MIPS versions are signed). Define {@code _WCHAR_IS_ALWAYS_SIGNED} to - restore old behavior. (Issue 57749)
      • -
      • Fixed {@code include/netinet/tcp.h} to contain {@code TCP_INFO} state enum. - (Issue 38881)
      • -
      • Fixed the {@code cdefs_elh.h} macro {@code _C_LABEL_STRING} to stop generating - warnings in the GCC 4.8 toolchain when using c++11 mode. - (Issue 58135, - Issue 58652)
      • -
      • Removed non-existent functions {@code imaxabs} and {@code imaxdiv} from header - {@code inttypes.h}.
      • -
      • Fixed issue with {@code pthread_exit()} return values and {@code pthread_self()}. - (Issue 60686)
      • -
      • Added missing {@code mkdtemp()} function, which already exists in {@code bionic} - header {@code stdlib.h}.
      • -
      -
    • -
    • Fixed problem building {@code samples/gles3jni} with Clang on Android API level 11.
    • -
    • Fixed MCLinker to allow multiple occurrences of the following options: - {@code -gc-sections} and {@code --eh-frame-hdr}.
    • -
    • Fixed MCLinker to accept the {@code --no-warn-mismatch} option.
    • -
    • Modified {@code cpu-features} option to not assume all VFPv4 devices support IDIV. - Now this option only adds IDIV to white-listed devices, including Nexus 4. - (Issue 57637)
    • -
    • Fixed problem with {@code android_native_app_glue.c} erroneously logging errors on event - predispatch operations.
    • -
    • Fixed all operations on {@code gabi++} terminate and unexpected_handler to be - thread-safe.
    • -
    • Fixed several issues with Clang -integrated-as option so it can pass - tests for {@code ssax-instructions} and {@code fenv}.
    • -
    • Fixed GCC 4.6/4.7/4.8 compiler to pass the linker option {@code --eh-frame-hdr} even - for static executables. For more information, see the - GCC patch.
    • -
    • Fixed extra apostrophe in CPU-ARCH-ABIS.html. For more information, see - NDK-DEPENDS.html. (Issue 60142)
    • -
    • Fixed extra quotes in ndk-build output on Windows. - (Issue 60649)
    • -
    • Fixed Clang 3.3 to compile ARM's built-in, atomic operations such as - {@code __atomic_fetch_add}, {@code __atomic_fetch_sub}, and {@code __atomic_fetch_or}. -
    • -
    • Fixed Clang 3.3 ICE with customized {@code vfprintf}. - (Clang issue) -
    • -
    -
    - -
    Other changes:
    -
    -
      -
    • Enabled OpenMP for all GCC builds. To use this feature, add the following flags to your - build settings: -
      -LOCAL_CFLAGS += -fopenmp
      -LOCAL_LDFLAGS += -fopenmp
      -
      - For code examples, see {@code tests/device/test-openmp}
    • -
    • Reduced the size of {@code ld.mcld} significantly (1.5MB vs. {@code ld.bfd} 3.5MB and - {@code ld.gold} 7.5MB), resulting in a speed improvement of approximately 20%.
    • -
    • Added LOCAL_CONLYFLAGS and APP_CONLYFLAGS to specify - options applicable to C only but not C++. The existing LOCAL_CFLAGS - and APP_CFLAGS are also used for C++ compilation (to save trouble of - specifying most options twice), so options such as -std=gnu99 may fail in - g++ builds with a warning and clang++ builds with an error.
    • -
    • Added {@code gabi++} array helper functions.
    • -
    • Modified GCC builds so that all {@code libgcc.a} files are built with - -funwind-tables to allow the stack to be unwound past previously blocked - points, such as __aeabi_idiv0.
    • -
    • Added Ingenic MXU support in MIPS GCC4.6/4.7/4.8 with new -mmxu -option.
    • -
    • Extended MIPS GCC4.6/4.7/4.8 -mldc1-sdc1 to control ldxc1/sdxc1 too
    • -
    • Added crazy linker. For more information, see - {@code sources/android/crazy_linker/README.TXT}.
    • -
    • Fixed {@code bitmap-plasma} to draw to full screen rather than a 200x200 pixel -area.
    • -
    • Reduced linux and darwin toolchain sizes by 25% by creating symlinks to identical files. -
    • -
    -
    - -
    -
    -
    - - -
    - -

    - Android NDK, Revision 9 (July 2013) -

    -
    -
    -
    Important changes:
    -
    -
      -
    • Added support for Android 4.3 (API level 18). For more information, see - {@code STABLE-APIS.html} and new code examples in {@code samples/gles3jni/README}. -
    • Added headers and libraries for OpenGL ES 3.0, which is supported by Android 4.3 - (API level 18) and higher.
    • -
    • Added GNU Compiler Collection (GCC) 4.8 compiler to the NDK. Since GCC 4.6 is still - the default, you must explicitly enable this option: -
        -
      • For {@code ndk-build} builds, export {@code NDK_TOOLCHAIN_VERSION=4.8} or - add it in {@code Application.mk}.
      • -
      • For standalone builds, use the {@code --toolchain=} option in - {@code make-standalone-toolchain.sh}, for example:
        - {@code --toolchain=arm-linux-androideabi-4.8}
      • -
      -

      Note: - The {@code -Wunused-local-typedefs} option is enabled by {@code -Wall}. Be - sure to add {@code __attribute__((unused))} if you use compile-time asserts like - {@code sources/cxx-stl/stlport/stlport/stl/config/features.h}, line #311. For more - information, see - Change 55460

      -

      Note: - In the GCC 4.7 release and later, ARM compilers generate unaligned access code by - default for ARMv6 and higher build targets. You may need to add the - {@code -mno-unaligned-access} build option when building for kernels that do not support - this feature.

      -
    • -
    • Added Clang 3.3 support. The {@code NDK_TOOLCHAIN_VERSION=clang} build option - now picks Clang 3.3 by default. -

      Note: - Both GCC 4.4.3 and Clang 3.1 are deprecated, and will be removed from the next NDK - release.

    • -
    • Updated GNU Project Debugger (GDB) to support python 2.7.5.
    • -
    • Added MCLinker to support Windows hosts. Since {@code ld.gold} - is the default where available, you must add {@code -fuse-ld=mcld} in - {@code LOCAL_LDFLAGS} or {@code APP_LDFLAGS} to enable MCLinker.
    • -
    • Added {@code ndk-depends} tool which prints ELF library dependencies. - For more information, see {@code NDK-DEPENDS.html}. - (Issue 53486)
    • -
    -
    - -
    Important bug fixes:
    -
    -
      -
    • Fixed potential event handling issue in {@code android_native_app_glue}. - (Issue 41755)
    • -
    • Fixed ARM/GCC-4.7 build to generate sufficient alignment for NEON load and store - instructions VST and VLD. - (GCC Issue 57271)
    • -
    • Fixed a GCC 4.4.3/4.6/4.7 internal compiler error (ICE) for a constant negative index - value on a string literal. - (Issue 54623)
    • -
    • Fixed GCC 4.7 segmentation fault for constant initialization with an object address. - (Issue 56508)
    • -
    • Fixed GCC 4.6 ARM segmentation fault for -O values when using Boost - 1.52.0. (Issue 42891) -
    • Fixed {@code libc.so} and {@code libc.a} to support the {@code wait4()} function. - (Issue 19854)
    • -
    • Updated the x86 libc.so and libc.a files to include the {@code clone()} - function.
    • -
    • Fixed {@code LOCAL_SHORT_COMMANDS} bug where the {@code linker.list} file is - empty or not used.
    • -
    • Fixed GCC MIPS build on Mac OS to use CFI directives, without which - {@code ld.mcld --eh-frame-hdr} fails frequently.
    • -
    • Fixed Clang 3.2 X86/MIPS internal compiler error in {@code llvm/lib/VMCore/Value.cpp}. - (Change 59021)
    • -
    • Fixed GCC 4.7 64-bit Windows assembler crash. (Error: {@code out of memory allocating - 4294967280 bytes}).
    • -
    • Updated {@code ndk-gdb} script so that the {@code --start} or {@code --launch} actions - now wait for the GNU Debug Server, so that it can more reliably hit breakpoints set - early in the execution path (such as breakpoints in JNI code). - (Issue 41278) -

      Note: - This feature requires jdb and produces warning about pending breakpoints. - Specify the {@code --nowait} option to restore previous behavior. -

      -
    • -
    • Fixed GDB crash when library list is empty.
    • -
    • Fixed GDB crash when using a {@code stepi} command past a {@code bx pc} or - {@code blx pc} Thumb instruction. - (Issue 56962, - Issue 36149)
    • -
    • Fixed MIPS {@code gdbserver} to look for {@code DT_MIPS_RLD_MAP} instead of - {@code DT_DEBUG}. (Issue 56586)
    • -
    • Fixed a circular dependency in the ndk-build script, for example: If A->B and - B->B, then B was dropped from build. - (Issue 56690)
    • -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Fixed the {@code ndk-build} script to enable you to specify a version of Clang as a - command line option (e.g., {@code NDK_TOOLCHAIN_VERSION=clang3.2}). Previously, only - specifying the version as an environment variable worked.
    • -
    • Fixed gabi++ size of {@code _Unwind_Exception} to be 24 for MIPS build targets when - using the Clang compiler. - (Change 54141)
    • -
    • Fixed the {@code ndk-build} script to ensure that built libraries are actually - removed from projects that include prebuilt static libraries when using the - {@code ndk-build clean} command. - (Change 54461, - Change 54480)
    • -
    • Modified the {@code NDK_ANALYZE=1} option to be less verbose.
    • -
    • Fixed {@code gnu-libstdc++/Android.mk} to include a {@code backward/} path for builds - that use backward compability. - (Issue 53404)
    • -
    • Fixed a problem where {@code stlport new} sometimes returned random values.
    • -
    • Fixed {@code ndk-gdb} to match the order of {@code CPU_ABIS}, not {@code APP_ABIS}. - (Issue 54033)
    • -
    • Fixed a problem where the NDK 64-bit build on MacOSX choses the wrong path for - compiler. - (Issue 53769)
    • -
    • Fixed build scripts to detect 64-bit Windows Vista. - (Issue 54485)
    • -
    • Fixed x86 {@code ntonl/swap32} error: {@code invalid 'asm': operand number - out of range}. - (Issue 54465, - Change 57242)
    • -
    • Fixed {@code ld.gold} to merge string literals.
    • -
    • Fixed {@code ld.gold} to handle large symbol alignment.
    • -
    • Updated {@code ld.gold} to enable the {@code --sort-section=name} option.
    • -
    • Fixed GCC 4.4.3/4.6/4.7 to suppress the {@code -export-dynamic} option for - statically linked programs. GCC no longer adds an {@code .interp} section for statically - linked programs.
    • -
    • Fixed GCC 4.4.3 {@code stlport} compilation error about inconsistent {@code typedef} - of {@code _Unwind_Control_Block}. - (Issue 54426)
    • -
    • Fixed {@code awk} scripts to handle {@code AndroidManifest.xml} files created on - Windows which may contain trailing {@code \r} characters and cause build errors. - (Issue 42548)
    • -
    • Fixed {@code make-standalone-toolchain.sh} to probe the {@code prebuilts/} - directory to detect if the host is 32 bit or 64 bit.
    • -
    • Fixed the Clang 3.2 {@code -integrated-as} option.
    • -
    • Fixed the Clang 3.2 ARM EHABI compact model {@code pr1} and {@code pr2} handler data. -
    • -
    • Added Clang {@code -mllvm -arm-enable-ehabi} option to fix the following Clang error: -
      clang: for the -arm-enable-ehabi option: may only occur zero or one times!
      -
    • -
    • Fixed build failure when there is no {@code uses-sdk} element in application - manifest. (Issue 57015)
    • -
    - -
    -
    Other changes:
    -
    -
      -
    • Header Fixes -
        -
      • Modified headers to make {@code __set_errno} an inlined function, since - {@code __set_errno} in {@code errno.h} is deprecated, and {@code libc.so} no longer - exports it.
      • -
      • Modified {@code elf.h} to include {@code stdint.h}. - (Issue 55443)
      • -
      • Fixed {@code sys/un.h} to be included independently of other headers. - (Issue 53646)
      • -
      • Fixed all of the {@code MotionEvent_getHistorical} API family to take the - {@code const AInputEvent* motion_event}. - (Issue 55873)
      • -
      • Fixed {@code malloc_usable_size} to take {@code const void*}. - (Issue 55725)
      • -
      • Fixed stdint.h to be more compatible with C99. - (Change 46821)
      • -
      • Modified {@code wchar.h} to not redefine {@code WCHAR_MAX} and - {@code WCHAR_MIN}
      • -
      • Fixed {@code } declaration for pointer-related {@code PRI} and - {@code SCN} macros. (Issue 57218)
      • -
      • Changed the {@code sys/cdefs.h} header so that {@code __WCHAR_TYPE__} is 32-bit - for API levels less than 9, which means that {@code wchat_t} is 32-bit for all - API levels. To restore the previous behavior, define the {@code _WCHAR_IS_8BIT} - boolean variable. (Issue 57267)
      • -
      -
    • -
    • Added more formatting in NDK {@code docs/} and miscellaneous documentation fixes. -
    • -
    • Added support for a thin archive technique when building static libraries. - (Issue 40303)
    • -
    • Updated script {@code make-standalone-toolchain.sh} to support the {@code stlport} - library in addition to {@code gnustl}, when you specify the option - {@code --stl=stlport}. For more information, see {@code STANDALONE-TOOLCHAIN.html}.
    • -
    • Updated the {@code make-standalone-toolchain.sh} script so that the - {@code --llvm-version=} option creates the {@code $TOOLCHAIN_PREFIX-clang} and - {@code $TOOLCHAIN_PREFIX-clang++} scripts in addition to {@code clang} and - {@code clang++}, to avoid using the host's clang and clang++ definitions by accident. -
    • -
    • Added two flags to re-enable two optimizations in upstream Clang but disabled in - NDK for better compatibility with code compiled by GCC: -
        -
      • Added a {@code -fcxx-missing-return-semantics} flag to re-enable missing -return - semantics in Clang 3.2+. Normally, all paths should terminate with a return - statement for a value-returning function. If this is not the case, clang inserts - an undefined instruction (or trap in debug mode) at the path without a return - statement. If you are sure your code is correct, use this flag to allow the - optimizer to take advantage of the undefined behavior. If you are not sure, do not - use this flag. The caller may still receive a random incorrect value, but the - optimizer will not exploit it and make your code harder to debug.
      • -
      • Added a {@code -fglobal-ctor-const-promotion} flag to re-enable - promoting global variables with static constructor to be constants. With this flag, - the global variable optimization pass of LLVM tries to evaluate the global - variables with static constructors and promote them to global constants. Although - this optimization is correct, it may cause some incompatability with code compiled - by GCC. For example, code may do {@code const_cast} to cast the constant to mutable - and modify it. In GCC, the variable is in read-write and the code is run by - accident. In Clang, the const variable is in read-only memory and may cause your - application to crash.
      • -
      -
    • -
    • Added {@code -mldc1-sdc1} to the MIPS GCC and Clang compilers. By default, compilers - align 8-byte objects properly and emit the {@code ldc1} and {@code sdc1} instructions - to move them around. If your app uses a custom allocator that does not always align - with a new object's 8-byte boundary in the same way as the default allocator, your app - may crash due to {@code ldc1} and {@code sdc1} operations on unaligned memory. In this - case, use the {@code -mno-ldc1-sdc1} flag to workaround the problem.
    • -
    • Downgraded the event severity from warning to info if {@code APP_PLATFORM_LEVEL} is - larger than {@code APP_MIN_PLATFORM_LEVEL}. The {@code APP_PLATFORM_LEVEL} may be lower - than {@code APP_PLATFORM} in {@code jni/Application.mk} because the NDK does not have - headers for all levels. In this case, the actual level is shifted downwards. The - {@code APP_MIN_PLATFORM_LEVEL} is specified by the {@code android:minSdkVersion} in - your application's manifest. - (Issue 39752)
    • -
    • Added the {@code android_getCpuIdArm()} and {@code android_setCpuArm()} methods to - {@code cpu-features.c}. This addition enables easier retrieval of the ARM CPUID - information. (Issue 53689)
    • -
    • Modified {@code ndk-build} to use GCC 4.7's {@code as/ld} for Clang compiling. -

      Note: - In GCC 4.7, {@code monotonic_clock} and {@code is_monotonic} have been renamed to - {@code steady_clock} and {@code is_steady}, respectively.

    • -
    • Added the following new warnings to the {@code ndk-build} script: -
        -
      • Added warnings if {@code LOCAL_LDLIBS/LDFLAGS} are used in static library - modules.
      • -
      • Added a warning if a configuration has no module to build.
      • -
      • Added a warning for non-system libraries being used in - {@code LOCAL_LDLIBS/LDFLAGS} of a shared library or executable modules.
      • -
      -
    • -
    • Updated build scripts, so that if {@code APP_MODULES} is not defined and only static - libraries are listed in {@code Android.mk}, the script force-builds all of them. - (Issue 53502)
    • -
    • Updated {@code ndk-build} to support absolute paths in {@code LOCAL_SRC_FILES}.
    • -
    • Removed the {@code *-gdbtui} executables, which are duplicates of the {@code *-gdb} - executables with the {@code -tui} option enabled.
    • -
    • Updated the build scripts to warn you when the Edison Design Group (EDG) compiler - front-end turns {@code _STLP_HAS_INCLUDE_NEXT} back on. - (Issue 53646)
    • -
    • Added the environment variable {@code NDK_LIBS_OUT} to allow overriding of the - path for {@code libraries/gdbserver} from the default {@code $PROJECT/libs}. - For more information, see {@code OVERVIEW.html}.
    • -
    • Changed ndk-build script defaults to compile code with format string protection - {@code -Wformat -Werror=format-security}. You may set - {@code LOCAL_DISABLE_FORMAT_STRING_CHECKS=true} to disable it. - For more information, see {@code ANDROID-MK.html}
    • -
    • Added STL pretty-print support in {@code ndk-gdb-py}. For more information, see - {@code NDK-GDB.html}.
    • -
    • Added tests based on the googletest frameworks.
    • -
    • Added a notification to the toolchain build script that warns you if the current shell - is not {@code bash}.
    • -
    -
    -
    -
    -
    - - -
    - -

    - Android NDK, Revision 8e (March 2013) -

    - -
    -
    -
    Important changes:
    -
    -
      -
    • Added 64-bit host toolchain set (package name suffix {@code *-x86_64.*}). For more - information, see {@code CHANGES.HTML} and {@code NDK-BUILD.html}.
    • -
    • Added Clang 3.2 compiler. GCC 4.6 is still the default. For information on using the - Clang compiler, see {@code CHANGES.HTML}.
    • -
    • Added static code analyzer for Linux/MacOSX hosts. For information on using the - analyzer, see {@code CHANGES.HTML}.
    • -
    • Added MCLinker for Linux/MacOSX hosts as an experimental feature. The {@code ld.gold} - linker is the default where available, so you must explicitly enable it. For more - information, see {@code CHANGES.HTML}.
    • -
    • Updated ndk-build to use topological sort for module dependencies, which means the - build automatically sorts out the order of libraries specified in - {@code LOCAL_STATIC_LIBRARIES}, {@code LOCAL_WHOLE_STATIC_LIBRARIES} and - {@code LOCAL_SHARED_LIBRARIES}. For more information, see {@code CHANGES.HTML}. - (Issue 39378)
    • -
    -
    - -
    Important bug fixes:
    -
    -
      -
    • Fixed build script to build all toolchains in {@code -O2}. Toolchains in previous - releases were incorrectly built without optimization.
    • -
    • Fixed build script which unconditionally builds Clang/llvm for MacOSX in 64-bit.
    • -
    • Fixed GCC 4.6/4.7 internal compiler error: - {@code gen_thumb_movhi_clobber at config/arm/arm.md:5832}. - (Issue 52732)
    • -
    • Fixed build problem where GCC/ARM 4.6/4.7 fails to link code using 64-bit atomic - built-in functions. - (Issue 41297)
    • -
    • Fixed GCC 4.7 linker DIV usage mismatch errors. - (Sourceware Issue) -
    • Fixed GCC 4.7 internal compiler error {@code build_data_member_initialization, at - cp/semantics.c:5790}.
    • -
    • Fixed GCC 4.7 internal compiler error {@code redirect_eh_edge_1, at tree-eh.c:2214}. - (Issue 52909)
    • -
    • Fixed a GCC 4.7 segfault. - (GCC Issue)
    • -
    • Fixed {@code } clock resolution and enabled {@code steady_clock}. - (Issue 39680)
    • -
    • Fixed toolchain to enable {@code _GLIBCXX_HAS_GTHREADS} for GCC 4.7 libstdc++. - (Issue 41770, - Issue 41859)
    • -
    • Fixed problem with the X86 MXX/SSE code failing to link due to missing - {@code posix_memalign}. - (Change 51872)
    • -
    • Fixed GCC4.7/X86 segmentation fault in {@code i386.c}, function - {@code distance_non_agu_define_in_bb()}. - (Change 50383)
    • -
    • Fixed GCC4.7/X86 to restore earlier {@code cmov} behavior. - (GCC Issue)
    • -
    • Fixed handling NULL return value of {@code setlocale()} in libstdc++/GCC4.7. - (Issue 46718) -
    • Fixed {@code ld.gold} runtime undefined reference to {@code __exidx_start} and - {@code __exidx_start_end}. - (Change 52134)
    • -
    • Fixed Clang 3.1 internal compiler error when using Eigen library. - (Issue 41246)
    • -
    • Fixed Clang 3.1 internal compiler error including {@code } in C++11 -mode. - (Issue 39600)
    • -
    • Fixed Clang 3.1 internal compiler error when generating object code for a method - call to a uniform initialized {@code rvalue}. - (Issue 41387)
    • -
    • Fixed Clang 3.1/X86 stack realignment. - (Change 52154)
    • -
    • Fixed problem with GNU Debugger (GDB) SIGILL when debugging on Android 4.1.2. - (Issue 40941)
    • -
    • Fixed problem where GDB cannot set {@code source:line} breakpoints when symbols -contain - long, indirect file paths. - (Issue 42448)
    • -
    • Fixed GDB {@code read_program_header} for MIPS PIE executables. - (Change 49592)
    • -
    • Fixed {@code STLport} segmentation fault in {@code uncaught_exception()}. - (Change 50236)
    • -
    • Fixed {@code STLport} bus error in exception handling due to unaligned access of - {@code DW_EH_PE_udata2}, {@code DW_EH_PE_udata4}, and {@code DW_EH_PE_udata8}.
    • -
    • Fixed Gabi++ infinite recursion problem with {@code nothrow new[]} operator. - (Issue 52833)
    • -
    • Fixed Gabi++ wrong offset to exception handler pointer. - (Change 53446)
    • -
    • Removed Gabi++ redundant free on exception object - (Change 53447)
    • -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • Fixed NDK headers: -
        -
      • Removed redundant definitions of {@code size_t}, {@code ssize_t}, and - {@code ptrdiff_t}.
      • -
      • Fixed MIPS and ARM {@code fenv.h} header.
      • -
      • Fixed {@code stddef.h} to not redefine {@code offsetof} since it already exists - in the toolchain.
      • -
      • Fixed {@code elf.h} to contain {@code Elf32_auxv_t} and {@code Elf64_auxv_t}. - (Issue 38441) -
      • -
      • Fixed the {@code #ifdef} C++ definitions in the - {@code OpenSLES_AndroidConfiguration.h} header file. - (Issue 53163) -
      • -
      -
    • -
    • Fixed {@code STLport} to abort after out of memory error instead of silently exiting. -
    • -
    • Fixed system and Gabi++ headers to be able to compile with API level 8 and lower.
    • -
    • Fixed {@code cpufeatures} to not parse {@code /proc/self/auxv}. - (Issue 43055)
    • -
    • Fixed {@code ld.gold} to not depend on host libstdc++ and on Windows platforms, - to not depend on the {@code libgcc_sjlj_1.dll} library.
    • -
    • Fixed Clang 3.1 which emits inconsistent register list in {@code .vsave} and fails - assembler. - (Change 49930)
    • -
    • Fixed Clang 3.1 to be able to compile libgabi++ and pass the {@code test-stlport} - tests for MIPS build targets. - (Change 51961)
    • -
    • Fixed Clang 3.1 to only enable exception by default for C++, not for C.
    • -
    • Fixed several issues in Clang 3.1 to pass most GNU exception tests.
    • -
    • Fixed scripts {@code clang} and {@code clang++} in standalone NDK compiler to detect - {@code -cc1} and to not specify {@code -target} when found.
    • -
    • Fixed {@code ndk-build} to observe {@code NDK_APP_OUT} set in {@code Application.mk}. -
    • -
    • Fixed X86 {@code libc.so} and {@code lib.a} which were missing the {@code sigsetjmp} - and {@code siglongjmp} functions already declared in {@code setjmp.h}. - (Issue 19851)
    • -
    • Patched GCC 4.4.3/4.6/4.7 libstdc++ to work with Clang in C++ 11. - (Clang Issue)
    • -
    • Fixed cygwin path in argument passed to {@code HOST_AWK}.
    • -
    • Fixed {@code ndk-build} script warning in windows when running from project's JNI - directory. - (Issue 40192)
    • -
    • Fixed problem where the {@code ndk-build} script does not build if makefile has - trailing whitespace in the {@code LOCAL_PATH} definition. - (Issue 42841)
    • -
    -
    - -
    Other changes:
    -
    -
      -
    • Enabled threading support in GCC/MIPS toolchain.
    • -
    • Updated GCC exception handling helpers {@code __cxa_begin_cleanup} and - {@code __cxa_type_match} to have default visibility from the previous - hidden visibility in GNU libstdc++. For more information, see - {@code CHANGES.HTML}.
    • -
    • Updated build scripts so that Gabi++ and STLport static libraries are now built with - hidden visibility except for exception handling helpers.
    • -
    • Updated build so that {@code STLport} is built for ARM in Thumb mode.
    • -
    • Added support for {@code std::set_new_handler} in Gabi++. - (Issue 52805)
    • -
    • Enabled {@code FUTEX} system call in GNU libstdc++.
    • -
    • Updated {@code ndk-build} so that it no longer copies prebuilt static library to - a project's {@code obj/local//} directory. - (Issue 40302)
    • -
    • Removed {@code __ARM_ARCH_5*__} from ARM {@code toolchains/*/setup.mk} script. - (Issue 21132)
    • -
    • Built additional GNU libstdc++ libraries in thumb for ARM.
    • -
    • Enabled MIPS floating-point {@code madd/msub/nmadd/nmsub/recip/rsqrt} - instructions with 32-bit FPU.
    • -
    • Enabled graphite loop optimizer in GCC 4.6 and 4.7 to allow more optimizations: - {@code -fgraphite}, {@code -fgraphite-identity}, {@code -floop-block}, {@code --floop-flatten}, - {@code -floop-interchange}, {@code -floop-strip-mine}, {@code -floop-parallelize-all}, - and {@code -ftree-loop-linear}. - (info)
    • -
    • Enabled {@code polly} for Clang 3.1 on Linux and Max OS X 32-bit hosts which analyzes - and optimizes memory access. (info)
    • -
    • Enabled {@code -flto} in GCC 4.7, 4.6, Clang 3.2 and Clang 3.1 on linux (Clang LTO - via LLVMgold.so). MIPS compiler targets are not supported because {@code ld.gold} - is not available.
    • -
    • Enabled {@code --plugin} and {@code --plugin-opt} for {@code ld.gold} in GCC 4.6/4.7. -
    • -
    • Enabled {@code --text-reorder} for {@code ld.gold} in GCC 4.7.
    • -
    • Configured GNU libstdc++ with {@code _GLIBCXX_USE_C99_MATH} which undefines the - {@code isinf} script in the bionic header. For more information, see - {@code CHANGES.html}.
    • -
    • Added {@code APP_LDFLAGS} to the build scripts. For more information, see - {@code ANDROID-MK.html}.
    • -
    • Updated build scripts to allow {@code NDK_LOG=0} to disable the {@code NDK_LOG}.
    • -
    • Updated build scripts to allow {@code NDK_HOST_32BIT=0} to disable the host developer - environment 32-bit toolchain.
    • -
    • Changed the default GCC/X86 flags {@code -march=} and {@code -mtune=} from - {@code pentiumpro} and {@code generic} to {@code i686} and {@code atom}.
    • -
    • Enhanced toolchain build scripts: -
        -
      • Fixed a race condition in {@code build-gcc.sh} for the {@code mingw} build type - which was preventing a significant amount of parallel build processing.
      • -
      • Updated {@code build-gabi++.sh} and {@code build-stlport.sh} so they can now run - from the NDK package. - (Issue 52835) -
      • -
      • Fixed {@code run-tests.sh} in the {@code MSys} utilities collection.
      • -
      • Improved 64-bit host toolchain and Canadian Cross build support.
      • -
      • Updated {@code build-mingw64-toolchain.sh} script to more recent version.
      • -
      • Added option to build {@code libgnustl_static.a} and {@code stlport_static.a} - without hidden visibility.
      • -
      -
    • -
    - -
    -
    -
    -
    - - -
    -

    - Android NDK, Revision 8d (December 2012) -

    - -
    -
    -
    Important changes:
    -
    -
      -
    • Added the GNU Compiler Collection (GCC) 4.7 compiler to the NDK. The GCC 4.6 compiler - is still the default, so you must to explicitly enable the new version as follows: -
        -
      • For {@code ndk-build}, export the {@code NDK_TOOLCHAIN_VERSION=4.7} variable - or add it to {@code Application.mk}.
      • -
      • For standalone builds, add the {@code --toolchain=} option to - {@code make-standalone-toolchain.sh}, for example: -
        --toolchain=arm-linux-androideabi-4.7
      • -
      -

      - Note: This feature is experimental. Please try it and - report any issues.

      -
    • -
    • Added {@code stlport} exception support via gabi++. Note that the new gabi++ - depends on {@code dlopen} and related code, meaning that: -
        -
      • You can no longer build a static executable using the {@code -static} - option or include {@code libstlport_static.a} using - {@code APP_STL := stlport_static}. (You can still use the {@code -static} option - with a standalone toolchain.) Compiling a dynamic executable using - {@code include $(BUILD_EXECUTABLE)} continues to work because the compiler - automatically adds the {@code -ldl} option.
      • -
      • If your project links using {@code -nostdlib} and {-Wl,--no-undefined}, you - must manually include the {@code -ldl} option.
      • -
      - For more information, see {@code CPLUSPLUS-SUPPORT.html}. - -

      - Note: This feature is experimental and works better with the GCC - 4.6/4.7 compilers than with GCC 4.4.3 or Clang 3.1. Please try it and - report any issues.

      -
    • -
    • Added a {@code -mstack-protector-guard=} option for x86 to choose between a - global default path which is compatible with older Android C library (bionic) - and a new tls path (%gs:20) for {@code -fstack-protector}, - {@code -fstack-protector-all} and {@code -fstack-protector-strong} using the GCC 4.6 - and higher compilers. - -

      - Note: The {@code -mstack-protector-guard} setting itself does not - enable any {@code -fstack-protector*} options.

      -
    • -
    • Added {@code android_setCpu()} function to - {@code sources/android/cpufeatures/cpu-features.c} for use when auto-detection via - {@code /proc} is not possible in Android 4.1 and higher. - (Chromium Issue - 164154)
    • -
    -
    - -
    Important bug fixes:
    -
    -
      -
    • Fixed unnecessary rebuild of object files when using the {@code ndk-build} script. - (Issue 39810)
    • -
    • Fixed a linker failure with the NDK 8c release for Mac OS X 10.6.x that produced the - following error: -
      -dyld: lazy symbol binding failed: Symbol not found: _memmem
      -Referenced from: ...../arm-linux-androideabi/bin/ld
      -Expected in: /usr/lib/libSystem.B.dylib
      - This problem was caused by building on Mac OS X 10.7, which produced binaries that were - not compatible with Mac OS 10.6.x and the NDK. -
    • -
    • Removed the {@code -x c++} options from the Clang++ standalone build script. - (Issue 39089)
    • -
    • Fixed issues using the {@code NDK_TOOLCHAIN_VERSION=clang3.1} option in Cygwin. - (Issue 39585)
    • -
    • Fixed the {@code make-standalone-toolchain.sh} script to allow generation of a - standalone toolchain using the Cygwin or MinGW environments. The resulting toolchain - can be used in Cygwin, MingGW or CMD.exe environments. - (Issue 39915, - Issue 39585)
    • -
    • Added missing {@code SL_IID_ANDROIDBUFFERQUEUESOURCE} option in android-14 builds for - ARM and X86. - (Issue 40625)
    • -
    • Fixed x86 CPU detection for the {@code ANDROID_CPU_X86_FEATURE_MOVBE} feature. - (Issue 39317)
    • -
    • Fixed an issue preventing the Standard Template Library (STL) from using C++ - sources that do not have a {@code .cpp} file extension.
    • -
    • Fixed GCC 4.6 ARM internal compiler error at reload1.c:1061. - (Issue 20862)
    • -
    • Fixed GCC 4.4.3 ARM internal compiler error at emit-rtl.c:1954. - (Issue 22336)
    • -
    • Fixed GCC 4.4.3 ARM internal compiler error at postreload.c:396. - (Issue 22345)
    • -
    • Fixed problem with GCC 4.6/4.7 skipping lambda functions. - (Issue 35933)
    • -
    -
    - -
    Other bug fixes:
    -
    -
      -
    • NDK header file fixes: -
        -
      • Fixed {@code __WINT_TYPE__} and {@code wint_t} to be the same type.
      • -
      • Corrected typo in {@code android/bitmap.h}. - (Issue 15134) -
      • -
      • Corrected typo in {@code errno.h}.
      • -
      • Added check for the presence of {@code __STDC_VERSION__} in {@code sys/cdefs.h}. - (Issue 14627) -
      • -
      • Reorganized headers in {@code byteswap.h} and {@code dirent.h}.
      • -
      • Fixed {@code limits.h} to include {@code page.h} which provides {@code PAGE_SIZE} - settings. - (Issue 39983) -
      • -
      • Fixed return type of {@code glGetAttribLocation()} and - {@code glGetUniformLocation()} from {@code int} to {@code GLint}.
      • -
      • Fixed {@code __BYTE_ORDER} constant for x86 builds. - (Issue 39824) -
      • -
      -
    • -
    • Fixed {@code ndk-build} script to not overwrite {@code -Os} with {@code -O2} for ARM - builds.
    • -
    • Fixed build scripts to allow overwriting of {@code HOST_AWK}, {@code HOST_SED}, and - {@code HOST_MAKE} settings.
    • -
    • Fixed issue for {@code ld.gold} on {@code fsck_msdos} builds linking objects built by - the Intel C/C++ compiler (ICC).
    • -
    • Fixed ARM EHABI support in Clang to conform to specifications.
    • -
    • Fixed GNU Debugger (GDB) to shorten the time spent on walking the target's link map - during {@code solib} events. - (Issue 38402)
    • -
    • Fixed missing {@code libgcc.a} file when linking shared libraries.
    • -
    -
    - -
    Other changes:
    -
    -
      -
    • Backported 64-bit built-in atomic functions for ARM to GCC 4.6.
    • -
    • Added documentation for audio output latency, along with other documentation and - fixes.
    • -
    • Fixed debug builds with Clang so that non-void functions now raise a {@code SIGILL} - signal for paths without a return statement.
    • -
    • Updated {@code make-standalone-toolchain.sh} to accept the suffix {@code -clang3.1} - which is equivalent to adding {@code --llvm-version=3.1} to the GCC 4.6 toolchain.
    • -
    • Updated GCC and Clang bug report URL to: - http://source.android.com/source/report-bug -s.html
    • -
    • Added ARM ELF support to {@code llvm-objdump}.
    • -
    • Suppressed treating c input as c++ warning for Clang builds.
    • -
    • Updated build so that only the 32-bit version of {@code libiberty.a} is built and - placed in {@code lib32/}.
    • -
    -
    -
    -
    -
    - - -
    -

    - Android NDK, Revision 8c (November 2012) -

    - -
    -
    -
    Important changes:
    - -
    -
      -
    • Added the Clang 3.1 compiler to the NDK. The GNU Compiler Collection (GCC) 4.6 is - still the default, so you must explicitly enable the Clang compiler option as follows: -
        -
      • For {@code ndk-build}, export {@code NDK_TOOLCHAIN_VERSION=clang3.1} or - add this environment variable setting to {@code Application.mk}.
      • -
      • For standalone builds, add {@code --llvm-version=3.1} to - {@code make-standalone-toolchain.sh} and replace {@code CC} and {@code CXX} in your - makefile with {@code /bin/clang} and - {@code /bin/clang++}. See {@code STANDALONE-TOOLCHAIN.html} for - details.
      • -
      -

      Note: This feature is experimental. Please try it and - report any issues.

    • -
    • Added Gold linker {@code ld.gold} for the Windows toolchain. Gold linker is also the - default for ARM and X86 on all hosts. You may override it to use the {@code ld.bfd} - linker by adding {@code LOCAL_LDFLAGS += -fuse-ld=bfd} to {@code Android.mk}, or by -passing - {@code -fuse-ld=bfd} to the g++/clang++ command line that does the linking.
    • -
    • Added checks for spaces in the NDK path to the {@code ndk-build[.cmd]} and - {@code ndk-gdb} scripts, to prevent build errors that are difficult to diagnose.
    • -
    • Made the following changes to API level handling: -
        -
      • Modified build logic so that projects that specify {@code android-10} through - {@code android-13} in {@code APP_PLATFORM}, {@code project.properties} or - {@code default.properties} link against {@code android-9} instead of - {@code android-14}. -
      • Updated build so that executables using android-16 (Jelly Bean) or higher are - compiled with the {@code -fPIE} option for position-independent executables (PIE). - A new {@code APP_PIE} option allows you to control this behavior. See {@code - APPLICATION-MK.html} for details. -

        - Note: All API levels above 14 still link against {@code - platforms/android-14} and no new {@code platforms/android-N} have been added. -

      • -
      • Modified {@code ndk-build} to provide warnings if the adjusted API level is larger - than {@code android:minSdkVersion} in the project's {@code AndroidManifest.xml}.
      • -
      -
    • -
    • Updated the {@code cpu-features} helper library to include more ARM-specific features. - See {@code sources/android/cpufeatures/cpu-features.h} for details.
    • -
    • Modified the long double on the X86 platform to be 8 bytes. This data type is now the - same size as a double, but is still treated as a distinct type.
    • -
    • Updated build for {@code APP_ABI=armeabi-v7a}: -
        -
      • Modified this build type to pass the {@code -march=armv7-a} parameter - to the linker. This change ensures that v7-specific libraries and {@code crt*.o} are - linked correctly.
      • -
      • Added {@code -mfpu=vfpv3-d16} to {@code ndk-build} instead of the - {@code -mfpu=vfp} option used in previous releases.
      • -
      -
    • -
    -
    -
    - -
    -
    Important bug fixes:
    - -
    -
      -
    • Fixed an issue where running {@code make-standalone-toolchain.sh} with root privileges - resulted in the stand alone tool chain being inaccessible to some users. - (Issue 35279) -
        -
      • All files and executables in the NDK release package are set to have read and - execute permissions for all.
      • -
      • The ownership/group of {@code libstdc++.a} is now preserved when copied.
      • -
      -
    • -
    • Removed redundant {@code \r} from Windows prebuilt {@code echo.exe}. The redundant - {@code \r} caused {@code gdb.setup} to fail in the GNU Debugger (GDB) because it - incorrectly became part of the path. - (Issue 36054)
    • -
    • Fixed Windows parallel builds that sometimes failed due to timing issues in the - {@code host-mkdir} implementation. - (Issue 25875)
    • -
    • Fixed GCC 4.4.3 GNU {@code libstdc++} to not merge {@code typeinfo} names by - default. For more details, see - {@code toolchain repo gcc/gcc-4.4.3/libstdc++-v3/libsupc++/typeinfo}. - (Issue 22165)
    • -
    • Fixed problem on {@code null} context in GCC 4.6 - {@code cp/mangle.c::write_unscoped_name}, where GCC may crash when the context is - {@code null} and dereferenced in {@code TREE_CODE}.
    • -
    • Fixed GCC 4.4.3 crashes on ARM NEON-specific type definitions for floats. - (Issue 34613)
    • -
    • Fixed the {@code STLport} internal {@code _IteWrapper::operator*()} implementation - where a stale stack location holding the dereferenced value was returned and caused - runtime crashes. - (Issue 38630)
    • - -
    • ARM-specific fixes: -
        -
      • Fixed ARM GCC 4.4.3/4.6 {@code g++} to not warn that the mangling of - <va_list> was changed in GCC 4.4. The workaround using the - {@code -Wno-psabi} switch to avoid this warning is no longer required.
      • -
      • Fixed an issue when a project with {@code .arm} or {@code .neon} suffixes in - {@code LOCAL_SRC_FILES} also used {@code APP_STL}. With {@code APP_STL}, the - {@code ndk-build} script searches for C++ files in {@code LOCAL_SRC_FILES} before - adding STL {@code header/lib} paths to compilation. Modified {@code ndk-build} to - filter out {@code .arm} and {@code .neon} suffixes before the search, otherwise items - in {@code LOCAL_SRC_FILES} like {@code myfile.cpp.arm.neon} won't be compiled as C++ - code.
      • -
      • Fixed {@code binutils-2.21/ld.bfd} to be capable of linking object from older - binutils without {@code tag_FP_arch}, which was producing assertion fail - error messages in GNU Binutils. - (Issue 35209) -
      • -
      • Removed Unknown EABI object attribute 44 warning when - {@code binutils-2.19/ld} links prebuilt object by newer {@code binutils-2.21}
      • -
      • Fixed an issue in GNU {@code stdc++} compilation with both {@code -mthumb} and - {@code -march=armv7-a}, by modifying {@code make-standalone-toolchain.sh} to populate - {@code headers/libs} in sub-directory {@code armv7-a/thumb}. - (Issue 35616) -
      • -
      • Fixed unresolvable R_ARM_THM_CALL relocation error. - (Issue 35342) -
      • -
      • Fixed internal compiler error at {@code reload1.c:3633}, caused by the ARM - back-end expecting the wrong operand type when sign-extend from {@code char}. - (GCC Issue 50099)
      • -
      • Fixed internal compiler error with negative shift amount. - (GCC Issue)
      • -
      -
    • - -
    • Fixed {@code -fstack-protector} for X86, which is also the default for the - {@code ndk-build} x86 ABI target.
    • - -
    • MIPS-specific fixes: -
        -
      • Fixed {@code STLport} endian-ness by setting {@code _STLP_LITTLE_ENDIAN} to 1 when - compiling MIPS {@code libstlport_*}.
      • -
      • Fixed GCC {@code __builtin_unreachable} issue when compiling LLVM. - (GCC Issue 54369)
      • -
      • Backported fix for {@code cc1} compile process consuming 100% CPU. - (GCC Issue 50380)
      • -
      -
    • - -
    • GNU Debugger-specific fixes: -
        -
      • Disabled Python support in gdb-7.x at build, otherwise the gdb-7.x configure - function may pick up whatever Python version is available on the host and build - {@code gdb} with a hard-wired dependency on a specific version of Python. - (Issue 36120) -
      • -
      • Fixed {@code ndk-gdb} when {@code APP_ABI} contains {@code all} and matchs none - of the known architectures. - (Issue 35392) -
      • -
      • Fixed Windows pathname support, by keeping the {@code :} character if it looks - like it could be part of a Windows path starting with a drive letter. - (GDB Issue 12843) -
      • -
      • Fixed adding of hardware breakpoint support for ARM in {@code gdbserver}. - (GDB Issue) -
      • -
      • Added fix to only read the current {@code solibs} when the linker is consistent. - This change speeds up {@code solib} event handling. - (Issue 37677) -
      • -
      • Added fix to make repeated attempts to find {@code solib} breakpoints. GDB now - retries {@code enable_break()} during every call to {@code svr4_current_sos()} until - it succeeds. - (Change 43563)
      • -
      • Fixed an issue where {@code gdb} would not stop on breakpoints placed in - {@code dlopen-ed} libraries. - (Issue 34856) -
      • -
      • Fixed {@code SIGILL} in dynamic linker when calling {@code dlopen()}, on system - where {@code /system/bin/linker} is stripped of symbols and - {@code rtld_db_dlactivity()} is implemented as {@code Thumb}, due to not preserving - {@code LSB} of {@code sym_addr}. - (Issue 37147) -
      • -
      -
    • -
    -
    -
    - -
    -
    Other bug fixes:
    - -
    -
      -
    • Fixed NDK headers: -
        -
      • Fixed {@code arch-mips/include/asm/*} code that was incorrectly removed from - original kernel. (Change - 43335)
      • -
      • Replaced struct member data {@code __unused} with {@code __linux_unused} in - {@code linux/sysctl.h} and {@code linux/icmp.h} to avoid conflict with - {@code #define __unused} in {@code sys/cdefs.h}.
      • -
      • Fixed {@code fenv.h} for enclosed C functions with {@code __BEGIN_DECLS} and - {@code __END_DECLS}.
      • -
      • Removed unimplemented functions in {@code malloc.h}.
      • -
      • Fixed {@code stdint.h} defintion of {@code uint64_t} for ANSI compilers. - (Issue 1952)
      • -
      • Fixed preprocessor macros in {@code /include/machine/*}.
      • -
      • Replaced {@code link.h} for MIPS with new version supporting all platforms.
      • -
      • Removed {@code linux-unistd.h}
      • -
      • Move GLibc-specific macros {@code LONG_LONG_MIN}, {@code LONG_LONG_MAX} and - {@code ULONG_LONG_MAX} from {@code } to {@code -}.
      • -
      -
    • -
    • Fixed a buffer overflow in {@code ndk-stack-parser}.
    • -
    • Fixed {@code _STLP_USE_EXCEPTIONS}, when not defined, to omit all declarations - and uses of {@code __Named_exception}. Compiling and use of {@code __Named_exception} - settings only occurs when {@code STLport} is allowed to use exceptions.
    • -
    • Fixed building of Linux-only NDK packages without also building Windows code. Use the - following settings to perform this type of build: -
      ./build/tools/make-release.sh --force --systems=linux-x86
    • -
    • Fixed {@code libc.so} so it does not export {@code atexit()} and {@code __do_handler}. - These symbols are exported for ARM builds by the system version of the C library to - support legacy native libraries. NDK-generated should never reference them directly. - Instead, each shared library or executable should embed its own version of these symbols, - provided by {@code crtbegin_*.o}. -

      If your project is linked with the {@code -nostdlib -Wl,--no-undefined} options, you - must provide your own {@code __dso_handle} because {@code crtbegin_so.o} is not linked in - this case. The content of {@code __dso_handle} does not matter, as shown in the following - example code:

      -
      -extern "C" {
      -  extern void *__dso_handle __attribute__((__visibility__ ("hidden")));
      -  void *__dso_handle;
      -}
      -
      -
    • -
    • Fixed symbol decoder for ARM used in {@code objdump} for {@code plt} entries to - generate a more readable form {@code function@plt}.
    • -
    • Removed the following symbols, introduced in GCC 4.6 {@code libgcc.a}, from - the X86 platform {@code libc.so} library: {@code __aeabi_idiv0}, {@code __aeabi_ldiv0}, - {@code __aeabi_unwind_cpp_pr1}, and {@code __aeabi_unwind_cpp_pr2}.
    • -
    • Removed unused {@code .ctors}, {@code .dtors}, and {@code .eh_frame} in MIPS - {@code crt*_so.S}.
    • -
    • Updated {@code ndk-gdb} so that it only takes the last line of output for - {@code ndk-build} {@code DUMP_XXXX}. This change ensures that if {@code Application.mk} or - {@code Android.mk} print something with {@code $(info ...)} syntax, it does not get - injected into the result of {@code DUMP_XXXX}. - (More info)
    • -
    -
    -
    - -
    -
    Other changes:
    - -
    -
      -
    • Removed {@code arch-x86} and {@code arch-mips} headers from - {@code platforms/android-[3,4,5,8]}. Those headers were incomplete, since both X86 and - MIPS ABIs are only supported at API 9 or higher.
    • -
    • Simplified c++ include path in standalone packages, as shown below. - (Issue 35279) -
      -<path>/arm-linux-androideabi/include/c++/4.6.x-google
      -  to:
      -<path>/include/c++/4.6/
      -
    • -
    • Fixed {@code ndk-build} to recognize more C++ file extensions by default: - {@code .cc .cp .cxx .cpp .CPP .c++ .C}. You may still use {@code LOCAL_CPP_EXTENSION} to - overwrite these extension settings.
    • -
    • Fixed an issue in {@code samples/san-angeles} that caused a black screen or freeze - frame on re-launch.
    • -
    • Replaced deprecated APIs in NDK samples. - (Issue 20017) -
        -
      • {@code hello-gl2} from android-5 to android-7
      • -
      • {@code native-activity} from android-9 to android-10
      • -
      • {@code native-audio} from android-9 to android-10
      • -
      • {@code native-plasma} from android-9 to android-10
      • -
      -
    • -
    • Added new branding for Android executables with a simpler scheme in section - {@code .note.android.ident} (defined in {@code crtbegin_static/dynamic.o}) so that - debugging tools can act accordingly. The structure member and values are defined as - follows: -
      -static const struct {
      -  int32_t namesz;  /* = 8,  sizeof ("Android") */
      -  int32_t descsz;  /* = 1 * sizeof(int32_t) */
      -  int32_t type;    /* = 1, ABI_NOTETYPE */
      -  char name[sizeof "Android"];  /* = "Android" */
      -  int32_t android_api; /* = 3, 4, 5, 8, 9, 14 */
      -}
      -
      -

      The previous branding options in section {@code .note.ABI-tag} are deprecated.

      -
    • -
    • Added a new script {@code run-tests-all.sh} which calls {@code run-tests.sh} and - {@code standalone/run.sh} with various conditions. The script {@code run-tests.sh} runs - without the {@code --abi} option, and is enhanced to compile most of the tests for all - supported ABIs and run on all attached devices
    • -
    -
    -
    - -
    -
    - -
    -

    - Android NDK, Revision 8b (July 2012) -

    - -
    -

    The main features of this release are a new GNU Compiler Collection (GCC) 4.6 toolchain and -GNU Debugger (GDB) 7.3.x which adds debugging support for the Android 4.1 (API Level 16) system -image.

    - -
    -
    Important bug fixes:
    - -
    -
      -
    • Fixed {@code LOCAL_SHORT_COMMANDS} issues on Mac OS, Windows Cygwin environments for -static libraries. List file generation is faster, and it is not regenerated to avoid repeated -project rebuilds.
    • -
    • Fixed several issues in {@code ndk-gdb}: -
        -
      • Updated tool to pass flags {@code -e}, {@code -d} and {@code -s} to adb more -consistently.
      • -
      • Updated tool to accept device serial names containing spaces.
      • -
      • Updated tool to retrieve {@code /system/bin/link} information, so {@code gdb} on -the host can set a breakpoint in {@code __dl_rtld_db_dlactivity} and be aware of linker activity -(e.g., rescan {@code solib} symbols when {@code dlopen()} is called).
      • -
      -
    • -
    • Fixed {@code ndk-build clean} on Windows, which was failing to remove -{@code ./libs/*/lib*.so}.
    • -
    • Fixed {@code ndk-build.cmd} to return a non-zero {@code ERRORLEVEL} when {@code make} -fails.
    • -
    • Fixed {@code libc.so} to stop incorrectly exporting the {@code __exidx_start} and -{@code __exidx_end} symbols.
    • -
    • Fixed {@code SEGV} when unwinding the stack past {@code __libc_init} for ARM and -MIPS.
    • -
    -
    -
    - -
    -
    Important changes:
    - -
    -
      -
    • Added GCC 4.6 toolchain ({@code binutils} 2.21 with {@code gold} and GDB 7.3.x) to -co-exist with the original GCC 4.4.3 toolchain ({@code binutils} 2.19 and GDB 6.6). -
        -
      • GCC 4.6 is now the default toolchain. You may set {@code -NDK_TOOLCHAIN_VERSION=4.4.3} in {@code Application.mk} to select the original one.
      • -
      • Support for the {@code gold} linker is only available for ARM and x86 -architectures on Linux and Mac OS hosts. This support is disabled by default. Add {@code -LOCAL_LDLIBS += -fuse-ld=gold} in {@code Android.mk} to enable it.
      • -
      • Programs compiled with {@code -fPIE} require the new {@code GDB} for debugging, -including binaries in Android 4.1 (API Level 16) system images.
      • -
      • The {@code binutils} 2.21 {@code ld} tool contains back-ported fixes from -version 2.22: -
          -
        • Fixed {@code ld --gc-sections}, which incorrectly retains zombie references to -external libraries. (more -info).
        • -
        • Fixed ARM {@code strip} command to preserve the original {@code p_align} and -{@code p_flags} in {@code GNU_RELRO} section if they are valid. Without this fix, programs -built with {@code -fPIE} could not be debugged. (mor -e info)
        • -
        -
      • -
      • Disabled {@code sincos()} optimization for compatibility with older - platforms.
      • -
      -
    • - -
    • Updated build options to enable the Never eXecute (NX) bit and {@code relro}/{@code -bind_now} protections by default: -
        -
      • Added {@code --noexecstack} to assembler and {@code -z noexecstack} to linker -that provides NX protection against buffer overflow attacks by enabling NX bit on stack and -heap.
      • -
      • Added {@code -z relro} and {@code -z now} to linker for hardening of internal -data sections after linking to guard against security vulnerabilities caused by memory corruption. -(more info: 1, -2)
      • - -
      • These features can be disabled using the following options: -
          -
        1. Disable NX protection by setting the {@code --execstack} option for the -assembler and {@code -z execstack} for the linker.
        2. -
        3. Disable hardening of internal data by setting the {@code -z norelro} and -{@code -z lazy} options for the linker.
        4. -
        5. Disable these protections in the NDK {@code jni/Android.mk} by setting the -following options: -
          -LOCAL_DISABLE_NO_EXECUTE=true  # disable "--noexecstack" and "-z noexecstack"
          -DISABLE_RELRO=true             # disable "-z relro" and "-z now"
          -
          -
        6. -
        -

        See {@code docs/ANDROID-MK.html} for more details.

        -
      • -
      -
    • - -
    • Added branding for Android executables with the {@code .note.ABI-tag} section (in -{@code crtbegin_static/dynamic.o}) so that debugging tools can act accordingly. The structure -member and values are defined as follows: -
      -static const struct {
      -  int32_t namesz;  /* = 4,  sizeof ("GNU") */
      -  int32_t descsz;  /* = 6 * sizeof(int32_t) */
      -  int32_t type;    /* = 1 */
      -  char  name[sizeof "GNU"];  /* = "GNU" */
      -  int32_t os;      /* = 0 */
      -  int32_t major;   /* = 2 */
      -  int32_t minor;   /* = 6 */
      -  int32_t teeny;   /* = 15 */
      -  int32_t os_variant;  /* = 1 */
      -  int32_t android_api; /* = 3, 4, 5, 8, 9, 14 */
      -}
      -
    • -
    -
    -
    - -
    -
    Other bug fixes:
    - -
    -
      -
    • Fixed {@code mips-linux-gnu} relocation truncated to fit {@code R_MIPS_TLS_LDM} issue. - (more info)
    • -
    • Fixed {@code ld} tool segfaults when using {@code --gc-sections}. - (more info) -
    • -
    • Fixed MIPS {@code GOT_PAGE} counting issue. - (more info)
    • -
    • Fixed follow warning symbol link for {@code mips_elf_count_got_symbols}.
    • -
    • Fixed follow warning symbol link for {@code mips_elf_allocate_lazy_stub}.
    • -
    • Moved MIPS {@code .dynamic} to the data segment, so that it is writable.
    • -
    • Replaced hard-coded values for symbols with correct segment sizes for MIPS.
    • -
    • Removed the {@code -mno-shared} option from the defaults in the MIPS toolchain. -The default for Android toolchain is {@code -fPIC} (or {@code -fpic} if supported). If you do not -explicitly specify {@code -mshared}, {@code -fpic}, {@code -fPIC}, {@code -fpie}, or {@code -fPIE}, -the MIPS compiler adds {@code -mno-shared} that turns off PIC. Fixed compiler not to add -{@code -mno-shared} in this case.
    • -
    • Fixed wrong package names in samples {@code hello-jni} and {@code two-libs} so that -the {@code tests} project underneath it can compile.
    • -
    -
    -
    - -
    -
    Other Changes:
    - -
    -
      -
    • Changed locations of binaries: -
        -
      • Moved {@code gdbserver} from -{@code toolchain//prebuilt/gdbserver} to -{@code prebuilt/android-/gdbserver/gdbserver}.
      • -
      • Renamed x86 toolchain prefix from {@code i686-android-linux-} to -{@code i686-linux-android-}.
      • -
      • Moved {@code sources/cxx-stl/gnu-libstdc++/include} and {@code lib} to -{@code sources/cxx-stl/gnu-libstdc++/4.6} when compiled with GCC 4.6, or -{@code sources/cxx-stl/gnu-libstdc++/4.4.3} when compiled with GCC 4.4.3.
      • -
      • Moved {@code libbfd.a} and {@code libintl.a} from {@code lib/} to {@code -lib32/}.
      • -
      -
    • - -
    • Added and improved various scripts in the rebuild and test NDK toolchain: -
        -
      • Added {@code build-mingw64-toolchain.sh} to generate a new Linux-hosted toolchain -that generates Win32 and Win64 executables.
      • -
      • Improved speed of {@code download-toolchain-sources.sh} by using the {@code -clone} command and only using {@code checkout} for the directories that are needed to build the NDK -toolchain binaries.
      • -
      • Added {@code build-host-gcc.sh} and {@code build-host-gdb.sh} scripts.
      • -
      • Added {@code tests/check-release.sh} to check the content of a given NDK -installation directory, or an existing NDK package.
      • -
      • Rewrote the {@code tests/standalone/run.sh} standalone tests .
      • -
      -
    • -
    • Removed {@code if_dl.h} header from all platforms and architectures. The {@code -AF_LINK} and {@code sockaddr_dl} elements it describes are specific to BSD (i.e., they don't exist -in Linux).
    • -
    -
    -
    - -
    -
    - -
    -

    - Android NDK, Revision 8 (May 2012) -

    - -
    -

    This release of the NDK includes support for MIPS ABI and a few additional fixes.

    - -
    -
    New features:
    - -
    -
      -
    • Added support for the MIPS ABI, which allows you to generate machine code that runs on - compatible MIPS-based Android devices. Major features for MIPS include MIPS-specific - toolchains, system headers, libraries and debugging support. For more details regarding - MIPS support, see {@code docs/CPU-MIPS.html} in the NDK package. - -

      By default, code is generated for ARM-based devices. You can add {@code mips} to - your {@code APP_ABI} definition in your {@code Application.mk} file to build - for MIPS platforms. For example, the following line instructs {@code ndk-build} - to build your code for three distinct ABIs:

      - -
      APP_ABI := armeabi armeabi-v7a mips
      - -

      Unless you rely on architecture-specific assembly sources, such as ARM assembly - code, you should not need to touch your {@code Android.mk} files to build MIPS - machine code.

      -
    • - -
    • You can build a standalone MIPS toolchain using the {@code --arch=mips} - option when calling make-standalone-toolchain.sh. See - {@code docs/STANDALONE-TOOLCHAIN.html} for more details. -
    • -
    - -

    Note: To ensure that your applications are available -to users only if their devices are capable of running them, Google Play filters applications based -on the instruction set information included in your application ? no action is needed on your part -to enable the filtering. Additionally, the Android system itself also checks your application at -install time and allows the installation to continue only if the application provides a library that -is compiled for the device's CPU architecture.

    -
    - -
    Important bug fixes:
    - -
    -
      -
    • Fixed a typo in GAbi++ implementation where the result of {@code - dynamic_cast(b)} of base class object {@code b} to derived class {@code D} is - incorrectly adjusted in the opposite direction from the base class. - (Issue 28721) -
    • -
    • Fixed an issue in which {@code make-standalone-toolchain.sh} fails to copy - {@code libsupc++.*}.
    • -
    -
    - -
    Other bug fixes:
    - -
    -
      -
    • Fixed {@code ndk-build.cmd} to ensure that {@code ndk-build.cmd} works correctly even - if the user has redefined the {@code SHELL} environment variable, which may be changed - when installing a variety of development tools in Windows environments. -
    • -
    -
    -
    -
    -
    - -
    -

    - Android NDK, Revision 7c (April 2012) -

    - -
    -

    This release of the NDK includes an important fix for Tegra2-based devices, and a few -additional fixes and improvements:

    - -
    -
    Important bug fixes:
    - -
    -
      -
    • Fixed GNU STL armeabi-v7a binaries to not crash on non-NEON - devices. The files provided with NDK r7b were not configured properly, - resulting in crashes on Tegra2-based devices and others when trying to use - certain floating-point functions (e.g., {@code cosf}, {@code sinf}, {@code expf}).
    • -
    -
    - -
    Important changes:
    - -
    -
      -
    • Added support for custom output directories through the {@code NDK_OUT} - environment variable. When defined, this variable is used to store all - intermediate generated files, instead of {@code $PROJECT_PATH/obj}. The variable is - also recognized by {@code ndk-gdb}.
    • -
    • Added support for building modules with hundreds or even thousands of source - files by defining {@code LOCAL_SHORT_COMMANDS} to {@code true} in your {@code Android.mk}. -

      This change forces the NDK build system to put most linker or archiver options - into list files, as a work-around for command-line length limitations. - See {@code docs/ANDROID-MK.html} for details.

      -
    • -
    -
    - -
    Other bug fixes:
    - -
    -
      -
    • Fixed {@code android_getCpuCount()} implementation in the {@code cpufeatures} -helper library. On certain devices, where cores are enabled dynamically by the system, the previous -implementation would report the total number of active cores the first time the function -was called, rather than the total number of physically available cores.
    • -
    -
    -
    -
    -
    - - -
    -

    - Android NDK, Revision 7b (February 2012) -

    - -
    -

    This release of the NDK includes fixes for native Windows builds, Cygwin and many other - improvements:

    - -
    -
    Important bug fixes:
    - -
    -
      -
    • Updated {@code sys/atomics.h} to avoid correctness issues - on some multi-core ARM-based devices. Rebuild your unmodified sources with this - version of the NDK and this problem should be completely eliminated. - For more details, read {@code docs/ANDROID-ATOMICS.html}.
    • -
    • Reverted to {@code binutils} 2.19 to fix debugging issues that - appeared in NDK r7 (which switched to {@code binutils} 2.20.1).
    • -
    • Fixed {@code ndk-build} on 32-bit Linux. A packaging error put a 64-bit version - of the {@code awk} executable under {@code prebuilt/linux-x86/bin} in NDK r7.
    • -
    • Fixed native Windows build ({@code ndk-build.cmd}). Other build modes were not - affected. The fixes include: -
        -
      • Removed an infinite loop / stack overflow bug that happened when trying - to call {@code ndk-build.cmd} from a directory that was not the top of - your project path (e.g., in any sub-directory of it).
      • -
      • Fixed a problem where the auto-generated dependency files were ignored. This - meant that updating a header didn't trigger recompilation of sources that included - it.
      • -
      • Fixed a problem where special characters in files or paths, other than spaces and - quotes, were not correctly handled.
      • -
      -
    • -
    • Fixed the standalone toolchain to generate proper binaries when using - {@code -lstdc++} (i.e., linking against the GNU {@code libstdc++} C++ runtime). You - should use {@code -lgnustl_shared} if you want to link against the shared library - version or {@code -lstdc++} for the static version. - -

      See {@code docs/STANDALONE-TOOLCHAIN.html} for more details about this fix.

      -
    • -
    • Fixed {@code gnustl_shared} on Cygwin. The linker complained that it couldn't find - {@code libsupc++.a} even though the file was at the right location.
    • -
    • Fixed Cygwin C++ link when not using any specific C++ runtime through - {@code APP_STL}.
    • -
    -
    -
    - -
    -
    Other changes:
    - -
    -
      -
    • When your application uses the GNU {@code libstdc++} runtime, the compiler will - no longer forcibly enable exceptions and RTTI. This change results in smaller code. -

      If you need these features, you must do one of the following:

      -
        -
      • Enable exceptions and/or RTTI explicitly in your modules or - {@code Application.mk}. (recommended)
      • -
      • Define {@code APP_GNUSTL_FORCE_CPP_FEATURES} to {@code 'exceptions'}, - {@code 'rtti'} or both in your {@code Application.mk}. See - {@code docs/APPLICATION-MK.html} for more details.
      • -
      -
    • -
    • {@code ndk-gdb} now works properly when your application has private services - running in independent processes. It debugs the main application process, instead of the - first process listed by {@code ps}, which is usually a service process.
    • -
    • Fixed a rare bug where NDK r7 would fail to honor the {@code LOCAL_ARM_MODE} value - and always compile certain source files (but not all) to 32-bit instructions.
    • -
    • {@code STLport}: Refresh the sources to match the Android platform version. This - update fixes a few minor bugs: -
        -
      • Fixed instantiation of an incomplete type
      • -
      • Fixed minor "==" versus "=" typo
      • -
      • Used {@code memmove} instead of {@code memcpy} in {@code string::assign}
      • -
      • Added better handling of {@code IsNANorINF}, {@code IsINF}, {@code IsNegNAN}, - etc.
      • -
      -

      For complete details, see the commit log.

      -
    • -
    • {@code STLport}: Removed 5 unnecessary static initializers from the library.
    • -
    • The GNU libstdc++ libraries for armeabi-v7a were mistakenly compiled for - armeabi instead. This change had no impact on correctness, but using the right - ABI should provide slightly better performance.
    • -
    • The {@code cpu-features} helper library was updated to report three optional - x86 CPU features ({@code SSSE3}, {@code MOVBE} and {@code POPCNT}). See - {@code docs/CPU-FEATURES.html} for more details.
    • -
    • {@code docs/NDK-BUILD.html} was updated to mention {@code NDK_APPLICATION_MK} instead - of {@code NDK_APP_APPLICATION_MK} to select a custom {@code Application.mk} file.
    • -
    • Cygwin: {@code ndk-build} no longer creates an empty "NUL" file in the current - directory when invoked.
    • -
    • Cygwin: Added better automatic dependency detection. In the previous version, it - didn't work properly in the following cases: -
        -
      • When the Cygwin drive prefix was not {@code /cygdrive}.
      • -
      • When using drive-less mounts, for example, when Cygwin would translate - {@code /home} to {@code \\server\subdir} instead of {@code C:\Some\Dir}.
      • -
      -
    • -
    • Cygwin: {@code ndk-build} does not try to use the native Windows tools under - {@code $NDK/prebuilt/windows/bin} with certain versions of Cygwin and/or GNU Make.
    • -
    -
    -
    -
    -
    - - -
    -

    - Android NDK, Revision 7 (November 2011) -

    - -
    -

    This release of the NDK includes new features to support the Android 4.0 platform as well - as many other additions and improvements:

    - -
    -
    New features
    - -
    -
      -
    • Added official NDK APIs for Android 4.0 (API level 14), which adds the following - native features to the platform: - -
        -
      • Added native multimedia API based on the Khronos Group OpenMAX AL? 1.0.1 - standard. The new <OMXAL/OpenMAXAL.h> and - <OMXAL/OpenMAXAL_Android.h> headers allow applications targeting - API level 14 to perform multimedia output directly from native code by using a new - Android-specific buffer queue interface. For more details, see - docs/openmaxal/index.html and http://www.khronos.org/openmax/.
      • - -
      • Updated the native audio API based on the Khronos Group OpenSL ES 1.0.1? - standard. With API Level 14, you can now decode compressed audio (e.g. MP3, AAC, - Vorbis) to PCM. For more details, see docs/opensles/index.html and - http://www.khronos.org/opensles/.
      • -
      -
    • - -
    • Added CCache support. To speed up large rebuilds, define the - NDK_CCACHE environment variable to ccache (or the path to - your ccache binary). When declared, the NDK build system automatically - uses CCache when compiling any source file. For example: -
      -export NDK_CCACHE=ccache
      -
      -

      Note: CCache is not included in the NDK release - so you must have it installed prior to using it. For more information about CCache, see - http://ccache.samba.org.

      -
    • - -
    • Added support for setting APP_ABI to all to indicate that - you want to build your NDK modules for all the ABIs supported by your given NDK - release. This means that either one of the following two lines in your - Application.mk are equivalent with this release: -
      -APP_ABI := all
      -APP_ABI := armeabi armeabi-v7a x86
      -
      - -

      This also works if you define APP_ABI when calling - ndk-build from the command-line, which is a quick way to check that your - project builds for all supported ABIs without changing the project's - Application.mk file. For example:

      -
      -ndk-build APP_ABI=all
      -
      -
    • - -
    • Added a LOCAL_CPP_FEATURES variable in Android.mk that - allows you to declare which C++ features (RTTI or Exceptions) your module uses. This - ensures that the final linking works correctly if you have prebuilt modules that depend - on these features. See docs/ANDROID-MK.html and - docs/CPLUSPLUS-SUPPORT.html for more details.
    • - -
    • Shortened paths to source and object files that are used in build commands. When - invoking $NDK/ndk-build from your project path, the paths to the source, - object, and binary files that are passed to the build commands are significantly - shorter now, because they are passed relative to the current directory. This is useful - when building projects with a lot of source files, to avoid limits on the maximum - command line length supported by your host operating system. The behavior is unchanged - if you invoke ndk-build from a sub-directory of your project tree, or if - you define NDK_PROJECT_PATH to point to a specific directory.
    • -
    -
    - -
    Experimental features
    - -
    - You can now build your NDK source files on Windows without Cygwin by calling the - ndk-build.cmd script from the command line from your project path. The - script takes exactly the same arguments as the original ndk-build script. - The Windows NDK package comes with its own prebuilt binaries for GNU Make, Awk and other - tools required by the build. You should not need to install anything else to get a - working build system. - -

    Important: ndk-gdb does not work on - Windows, so you still need Cygwin to debug.

    - -

    This feature is still experimental, so feel free to try it and report issues on the - public bug database or public forum. All samples and unit tests - shipped with the NDK succesfully compile with this feature.

    -
    - -
    Important bug fixes
    - -
    -
      -
    • Imported shared libraries are now installed by default to the target installation - location (libs/<abi>) if APP_MODULES is not defined in - your Application.mk. For example, if a top-level module foo - imports a module bar, then both libfoo.so and - libbar.so are copied to the install location. Previously, only - libfoo.so was copied, unless you listed bar in your - APP_MODULES too. If you define APP_MODULES explicitly, the - behavior is unchanged.
    • - -
    • ndk-gdb now works correctly for activities with multiple categories in - their MAIN intent filters.
    • - -
    • Static library imports are now properly transitive. For example, if a top-level - module foo imports static library bar that imports static - library zoo, the libfoo.so will now be linked against both - libbar.a and libzoo.a.
    • -
    -
    - -
    Other changes
    - -
    -
      -
    • docs/NATIVE-ACTIVITY.HTML: Fixed typo. The minimum API level should be - 9, not 8 for native activities.
    • - -
    • docs/STABLE-APIS.html: Added missing documentation listing EGL as a - supported stable API, starting from API level 9.
    • - -
    • download-toolchain-sources.sh: Updated to download the toolchain - sources from android.googlesource.com, - which is the new location for the AOSP servers.
    • - -
    • Added a new C++ support runtime named gabi++. More details about it - are available in the updated docs/CPLUSPLUS-SUPPORT.html.
    • - -
    • Added a new C++ support runtime named gnustl_shared that corresponds - to the shared library version of GNU libstdc++ v3 (GPLv3 license). See more info at - docs/CPLUSPLUS-SUPPORT.html
    • - -
    • Added support for RTTI in the STLport C++ runtimes (no support for - exceptions).
    • - -
    • Added support for multiple file extensions in LOCAL_CPP_EXTENSION. For - example, to compile both foo.cpp and bar.cxx as C++ sources, - declare the following: -
      -LOCAL_CPP_EXTENSION := .cpp .cxx
      -
      -
    • - -
    • Removed many unwanted exported symbols from the link-time shared system libraries - provided by the NDK. This ensures that code generated with the standalone toolchain - doesn't risk to accidentally depend on a non-stable ABI symbol (e.g. any libgcc.a - symbol that changes each time the toolchain used to build the platform is changed)
    • - -
    • Refreshed the EGL and OpenGLES Khronos headers to support more extensions. Note - that this does not change the NDK ABIs for the corresponding libraries, - because each extension must be probed at runtime by the client application. - -

      The extensions that are available depend on your actual device and GPU drivers, - not the platform version the device runs on. The header changes simply add new - constants and types to make it easier to use the extensions when they have been - probed with eglGetProcAddress() or glGetProcAddress(). The - following list describes the newly supported extensions:

      - -
      -
      GLES 1.x
      - -
      -
        -
      • GL_OES_vertex_array_object
      • - -
      • GL_OES_EGL_image_external
      • - -
      • GL_APPLE_texture_2D_limited_npot
      • - -
      • GL_EXT_blend_minmax
      • - -
      • GL_EXT_discard_framebuffer
      • - -
      • GL_EXT_multi_draw_arrays
      • - -
      • GL_EXT_read_format_bgra
      • - -
      • GL_EXT_texture_filter_anisotropic
      • - -
      • GL_EXT_texture_format_BGRA8888
      • - -
      • GL_EXT_texture_lod_bias
      • - -
      • GL_IMG_read_format
      • - -
      • GL_IMG_texture_compression_pvrtc
      • - -
      • GL_IMG_texture_env_enhanced_fixed_function
      • - -
      • GL_IMG_user_clip_plane
      • - -
      • GL_IMG_multisampled_render_to_texture
      • - -
      • GL_NV_fence
      • - -
      • GL_QCOM_driver_control
      • - -
      • GL_QCOM_extended_get
      • - -
      • GL_QCOM_extended_get2
      • - -
      • GL_QCOM_perfmon_global_mode
      • - -
      • GL_QCOM_writeonly_rendering
      • - -
      • GL_QCOM_tiled_rendering
      • -
      -
      - -
      GLES 2.0
      - -
      -
        -
      • GL_OES_element_index_uint
      • - -
      • GL_OES_get_program_binary
      • - -
      • GL_OES_mapbuffer
      • - -
      • GL_OES_packed_depth_stencil
      • - -
      • GL_OES_texture_3D
      • - -
      • GL_OES_texture_float
      • - -
      • GL_OES_texture_float_linear
      • - -
      • GL_OES_texture_half_float_linear
      • - -
      • GL_OES_texture_npot
      • - -
      • GL_OES_vertex_array_object
      • - -
      • GL_OES_EGL_image_external
      • - -
      • GL_AMD_program_binary_Z400
      • - -
      • GL_EXT_blend_minmax
      • - -
      • GL_EXT_discard_framebuffer
      • - -
      • GL_EXT_multi_draw_arrays
      • - -
      • GL_EXT_read_format_bgra
      • - -
      • GL_EXT_texture_format_BGRA8888
      • - -
      • GL_EXT_texture_compression_dxt1
      • - -
      • GL_IMG_program_binary
      • - -
      • GL_IMG_read_format
      • - -
      • GL_IMG_shader_binary
      • - -
      • GL_IMG_texture_compression_pvrtc
      • - -
      • GL_IMG_multisampled_render_to_texture
      • - -
      • GL_NV_coverage_sample
      • - -
      • GL_NV_depth_nonlinear
      • - -
      • GL_QCOM_extended_get
      • - -
      • GL_QCOM_extended_get2
      • - -
      • GL_QCOM_writeonly_rendering
      • - -
      • GL_QCOM_tiled_rendering
      • -
      -
      - -
      EGL
      - -
      -
        -
      • EGL_ANDROID_recordable
      • - -
      • EGL_NV_system_time
      • -
      -
      -
      -
    • -
    -
    -
    -
    -
    - - -
    -

    - Android NDK, Revision 6b (August 2011) -

    - -
    -

    This release of the NDK does not include any new features compared to r6. The r6b release - addresses the following issues in the r6 release:

    -
    -
    Important bug fixes
    -
    -
      -
    • Fixed the build when APP_ABI="armeabi x86" is used for - multi-architecture builds.
    • -
    • Fixed the location of prebuilt STLport binaries in the NDK release package. - A bug in the packaging script placed them in the wrong location.
    • -
    • Fixed atexit() usage in shared libraries with the x86standalone - toolchain.
    • -
    • Fixed make-standalone-toolchain.sh --arch=x86. It used to fail - to copy the proper GNU libstdc++ binaries to the right location.
    • -
    • Fixed the standalone toolchain linker warnings about missing the definition and - size for the __dso_handle symbol (ARM only).
    • -
    • Fixed the inclusion order of $(SYSROOT)/usr/include for x86 builds. - See the bug for - more information.
    • -
    • Fixed the definitions of ptrdiff_t and size_t in - x86-specific systems when they are used with the x86 standalone toolchain.
    • -
    -
    -
    -
    -
    - -
    -

    - Android NDK, Revision 6 (July 2011) -

    - -
    -

    This release of the NDK includes support for the x86 ABI and other minor changes. - For detailed information describing the changes in this release, read the - CHANGES.HTML document included in the NDK package. -

    -
    -
    General notes:
    -
    -
      -
    • Adds support for the x86 ABI, which allows you to generate machine code - that runs on compatible x86-based Android devices. Major features for x86 - include x86-specific toolchains, system headers, libraries and - debugging support. For all of the details regarding x86 support, - see docs/CPU-X86.html in the NDK package. - -

      By default, code is generated for ARM-based devices, but you can add x86 to your - APP_ABI definition in your Application.mk file to build - for x86 platforms. For example, the following line instructs ndk-build - to build your code for three distinct ABIs:

      - -
      APP_ABI := armeabi armeabi-v7a x86
      - -

      Unless you rely on ARM-based assembly sources, you shouldn't need to touch - your Android.mk files to build x86 machine code.

      - -
    • - -
    • You can build a standalone x86 toolchain using the ---toolchain=x86-4.4.3 - option when calling make-standalone-toolchain.sh. See - docs/STANDALONE-TOOLCHAIN.html for more details. -
    • -
    • The new ndk-stack tool lets you translate stack traces in - logcat that are generated by native code. The tool translates - instruction addresses into a readable format that contains things such - as the function, source file, and line number corresponding to each stack frame. - For more information and a usage example, see docs/NDK-STACK.html. -
    • -
    -
    -
    Other changes:
    -
    arm-eabi-4.4.0, which had been deprecated since NDK r5, has been - removed from the NDK distribution.
    - -
    -
    -
    - -
    -

    - Android NDK, Revision 5c (June 2011) -

    - -
    -

    This release of the NDK does not include any new features compared to r5b. The r5c release - addresses the following problems in the r5b release:

    -
    -
    Important bug fixes:
    -
    -
      -
    • ndk-build: Fixed a rare bug that appeared when trying to perform parallel - builds of debuggable projects.
    • - -
    • Fixed a typo that prevented LOCAL_WHOLE_STATIC_LIBRARIES to work - correctly with the new toolchain and added documentation for this in - docs/ANDROID-MK.html.
    • - -
    • Fixed a bug where code linked against gnustl_static crashed when run on - platform releases older than API level 8 (Android 2.2).
    • - -
    • ndk-gdb: Fixed a bug that caused a segmentation fault when debugging -Android 3.0 - or newer devices.
    • - -
    • <android/input.h>: Two functions that were introduced in API level - 9 (Android 2.3) were incorrect and are fixed. While this breaks the source API, the - binary interface to the system is unchanged. The incorrect functions were missing a - history_index parameter, and the correct definitions are shown below: -
      -float AMotionEvent_getHistoricalRawX(const AInputEvent* motion_event,
      -                                           size_t pointer_index,
      -                                           size_t history_index);
      -
      -float AMotionEvent_getHistoricalRawY(const AInputEvent* motion_event,
      -                                           size_t pointer_index,
      -                                           size_t history_index);
      -
      -
    • - -
    • Updated the C library ARM binary for API level 9 (Android 2.3) to correctly expose at - link time new functions that were added in that API level (for example, - pthread_rwlock_init).
    • - -
    -
    - -
    Minor improvements and fixes:
    -
    -
      -
    • Object files are now always linked in the order they appear in - LOCAL_SRC_FILES. This was not the case previously because the files were - grouped by source extensions instead.
    • - -
    • When import-module fails, it now prints the list of directories that - were searched. This is useful to check that the NDK_MODULE_PATH definition - used by the build system is correct.
    • - -
    • When import-module succeeds, it now prints the directory where the - module was found to the log (visible with NDK_LOG=1).
    • - -
    • Increased the build speed of debuggable applications when there is a very large number - of include directories in the project.
    • - -
    • ndk-gdb: Better detection of adb shell failures and improved - error messages.
    • - -
    • <pthread.h>: Fixed the definition of - PTHREAD_RWLOCK_INITIALIZER for API level 9 (Android 2.3) and higher.
    • - -
    • Fixed an issue where a module could import itself, resulting in an infinite loop in - GNU Make.
    • - -
    • Fixed a bug that caused the build to fail if LOCAL_ARM_NEON was set to - true (typo in build/core/build-binary.mk).
    • - -
    • Fixed a bug that prevented the compilation of .s assembly files - (.S files were okay).
    • -
    -
    -
    -
    -
    - -
    -

    - Android NDK, Revision 5b (January 2011) -

    - -
    -

    This release of the NDK does not include any new features compared to r5. The r5b release -addresses the - following problems in the r5 release: -

    -
      -
    • The r5 binaries required glibc 2.11, but the r5b binaries are generated with a special - toolchain that targets glibc 2.7 or higher instead. The Linux toolchain binaries now run on -Ubuntu 8.04 or higher.
    • -
    • Fixes a compiler bug in the arm-linux-androideabi-4.4.3 toolchain. - The previous binary generated invalid thumb instruction sequences when - dealing with signed chars.
    • -
    • Adds missing documentation for the - "gnustl_static" value for APP_STL, that allows you to link against - a static library version of GNU libstdc++.
    • the -
    • Fixed the following ndk-build issues: -
        -
      • A bug that created inconsistent dependency files when a - compilation error occured on Windows. This prevented a proper build after - the error was fixed in the source code.
      • -
      • A Cygwin-specific bug where using very short paths for - the Android NDK installation or the project path led to the - generation of invalid dependency files. This made incremental builds - impossible.
      • -
      • A typo that prevented the cpufeatures library from working correctly - with the new NDK toolchain.
      • -
      • Builds in Cygwin are faster by avoiding calls to cygpath -m - from GNU Make for every source or object file, which caused problems - with very large source trees. In case this doesn't work properly, define -NDK_USE_CYGPATH=1 in your - environment to use cygpath -m again.
      • -
      • The Cygwin installation now notifies the user of invalid installation paths that -contain spaces. Previously, an invalid path - would output an error that complained about an incorrect version of GNU Make, even if the -right one was installed. -
      -
    • -
    • Fixed a typo that prevented the NDK_MODULE_PATH environment variable from -working properly when - it contained multiple directories separated with a colon.
    • -
    • The prebuilt-common.sh script contains fixes to check the compiler for 64-bit - generated machine code, instead of relying on the host tag, which - allows the 32-bit toolchain to rebuild properly on Snow Leopard. The toolchain rebuild scripts -now also support - using a 32-bit host toolchain.
    • -
    • A missing declaration for INET_ADDRSTRLEN was added to -<netinet/in.h>.
    • -
    • Missing declarations for IN6_IS_ADDR_MC_NODELOCAL and -IN6_IS_ADDR_MC_GLOBAL were added to <netinet/in6.h>.
    • -
    • 'asm' was replaced with '__asm__' in <asm/byteorder.h> to allow -compilation with -std=c99.
    • -
    -
    -
    - -
    -

    - Android NDK, Revision 5 (December 2010) -

    - -
    -

    This release of the NDK includes many new APIs, most of which are introduced to - support the development of games and similar applications that make extensive use - of native code. Using the APIs, developers have direct native access to events, audio, - graphics and window management, assets, and storage. Developers can also implement the - Android application lifecycle in native code with help from the new - {@link android.app.NativeActivity} class. For detailed information describing the changes -in this - release, read the CHANGES.HTML document included in the downloaded NDK -package. -

    -
    -
    General notes:
    -
    -
      -
    • Adds support for native activities, which allows you to implement the - Android application lifecycle in native code.
    • - -
    • Adds native support for the following: - -
        - -
      • Input subsystem (such as the keyboard and touch screen)
      • - -
      • Access to sensor data (accelerometer, compass, gyroscope, etc).
      • - -
      • Event loop APIs to wait for things such as input and sensor events.
      • - -
      • Window and surface subsystem
      • - -
      • Audio APIs based on the OpenSL ES standard that support playback and recording - as well as control over platform audio effects
      • - -
      • Access to assets packaged in an .apk file.
      • - -
      -
    • - -
    • Includes a new toolchain (based on GCC 4.4.3), which generates better code, and can -also now - be used as a standalone cross-compiler, for people who want to build their stuff with - ./configure && make. See - docs/STANDALONE-TOOLCHAIN.html for the details. The binaries for GCC 4.4.0 are still -provided, - but the 4.2.1 binaries were removed.
    • - -
    • Adds support for prebuilt static and shared libraries (docs/PREBUILTS.html) and -module - exports and imports to make sharing and reuse of third-party modules much easier - (docs/IMPORT-MODULE.html explains why).
    • - -
    • Provides a default C++ STL implementation (based on STLport) as a helper module. It -can be used either - as a static or shared library (details and usage examples are in -sources/android/stlport/README). Prebuilt - binaries for STLport (static or shared) and GNU libstdc++ (static only) are also -provided if you choose to - compile against those libraries instead of the default C++ STL implementation. - C++ Exceptions and RTTI are not supported in the default STL implementation. For more -information, see - docs/CPLUSPLUS-SUPPORT.HTML.
    • - -
    • Includes improvements to the cpufeatures helper library that improves -reporting - of the CPU type (some devices previously reported ARMv7 CPU when the device really was -an ARMv6). We - recommend developers that use this library to rebuild their applications then - upload to Google Play to benefit from the improvements.
    • - -
    • Adds an EGL library that lets you create and manage OpenGL ES textures and - services.
    • - -
    • Adds new sample applications, native-plasma and -native-activity, - to demonstrate how to write a native activity.
    • - -
    • Includes many bugfixes and other small improvements; see docs/CHANGES.html for a -more - detailed list of changes.
    • -
    -
    -
    -
    -
    - -
    -

    - Android NDK, Revision 4b (June 2010) -

    - -
    -
    -
    NDK r4b notes:
    - -
    -

    Includes fixes for several issues in the NDK build and debugging scripts — if - you are using NDK r4, we recommend downloading the NDK r4b build. For detailed - information describing the changes in this release, read the CHANGES.TXT document - included in the downloaded NDK package.

    -
    -
    - -
    -
    General notes:
    - -
    -
      -
    • Provides a simplified build system through the new ndk-build build - command.
    • - -
    • Adds support for easy native debugging of generated machine code on production - devices through the new ndk-gdb command.
    • - -
    • Adds a new Android-specific ABI for ARM-based CPU architectures, - armeabi-v7a. The new ABI extends the existing armeabi ABI to - include these CPU instruction set extensions: - -
        -
      • Thumb-2 instructions
      • - -
      • VFP hardware FPU instructions (VFPv3-D16)
      • - -
      • Optional support for ARM Advanced SIMD (NEON) GCC intrinsics and VFPv3-D32. - Supported by devices such as Verizon Droid by Motorola, Google Nexus One, and - others.
      • -
      -
    • - -
    • Adds a new cpufeatures static library (with sources) that lets your - app detect the host device's CPU features at runtime. Specifically, applications can - check for ARMv7-A support, as well as VFPv3-D32 and NEON support, then provide separate - code paths as needed.
    • - -
    • Adds a sample application, hello-neon, that illustrates how to use the - cpufeatures library to check CPU features and then provide an optimized - code path using NEON instrinsics, if supported by the CPU.
    • - -
    • Lets you generate machine code for either or both of the instruction sets supported - by the NDK. For example, you can build for both ARMv5 and ARMv7-A architectures at the - same time and have everything stored to your application's final - .apk.
    • - -
    • To ensure that your applications are available to users only if their devices are - capable of running them, Google Play now filters applications based on the - instruction set information included in your application — no action is needed on - your part to enable the filtering. Additionally, the Android system itself also checks - your application at install time and allows the installation to continue only if the - application provides a library that is compiled for the device's CPU architecture.
    • - -
    • Adds support for Android 2.2, including a new stable API for accessing the pixel - buffers of {@link android.graphics.Bitmap} objects from native code.
    • -
    -
    -
    -
    -
    - -
    -

    - Android NDK, Revision 3 (March 2010) -

    - -
    -
    -
    General notes:
    - -
    -
      -
    • Adds OpenGL ES 2.0 native library support.
    • - -
    • Adds a sample application,hello-gl2, that illustrates the use of - OpenGL ES 2.0 vertex and fragment shaders.
    • - -
    • The toolchain binaries have been refreshed for this release with GCC 4.4.0, which - should generate slightly more compact and efficient machine code than the previous one - (4.2.1). The NDK also still provides the 4.2.1 binaries, which you can optionally use - to build your machine code.
    • -
    -
    -
    -
    -
    - -
    -

    - Android NDK, Revision 2 (September 2009) -

    - -
    -

    Originally released as "Android 1.6 NDK, Release 1".

    - -
    -
    General notes:
    - -
    -
      -
    • Adds OpenGL ES 1.1 native library support.
    • - -
    • Adds a sample application, san-angeles, that renders 3D graphics - through the native OpenGL ES APIs, while managing activity lifecycle with a {@link - android.opengl.GLSurfaceView} object.
    • -
    -
    -
    -
    -
    - -
    -

    - Android NDK, Revision 1 (June 2009) -

    - -
    -

    Originally released as "Android 1.5 NDK, Release 1".

    - -
    -
    General notes:
    - -
    -
      -
    • Includes compiler support (GCC) for ARMv5TE instructions, including Thumb-1 - instructions.
    • - -
    • Includes system headers for stable native APIs, documentation, and sample - applications.
    • -
    -
    -
    -
    -
    - - - - - - diff --git a/docs/html/ndk/guides/_book.yaml b/docs/html/ndk/guides/_book.yaml deleted file mode 100644 index c015d7a7dcbf6790b943e9eaecdc7cb88844445d..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/_book.yaml +++ /dev/null @@ -1,84 +0,0 @@ -toc: -- title: Getting Started - path: /ndk/guides/index.html - section: - - title: Setup - path: /ndk/guides/setup.html - - title: Concepts - path: /ndk/guides/concepts.html - -- title: Building - path: /ndk/guides/build.html - section: - - title: Android.mk - path: /ndk/guides/android_mk.html - - title: Application.mk - path: /ndk/guides/application_mk.html - - title: ndk-build - path: /ndk/guides/ndk-build.html - - title: Standalone Toolchain - path: /ndk/guides/standalone_toolchain.html - -- title: Architectures and CPUs - path: /ndk/guides/arch.html - section: - - title: ABI Management - path: /ndk/guides/abis.html - - title: NEON - path: /ndk/guides/cpu-arm-neon.html - - title: x86 - path: /ndk/guides/x86.html - - title: x86-64 - path: /ndk/guides/x86-64.html - - title: MIPS - path: /ndk/guides/mips.html - - title: The cpufeatures Library - path: /ndk/guides/cpu-features.html - -- title: Debugging - path: /ndk/guides/debug.html - section: - - title: ndk-gdb - path: /ndk/guides/ndk-gdb.html - - title: ndk-stack - path: /ndk/guides/ndk-stack.html - -- title: Libraries - path: /ndk/guides/libs.html - section: - - title: Prebuilt Libraries - path: /ndk/guides/prebuilts.html - - title: C++ Support - path: /ndk/guides/cpp-support.html - - title: Stable APIs - path: /ndk/guides/stable_apis.html - -- title: Audio - path: /ndk/guides/audio/index.html - section: - - title: Basics - path: /ndk/guides/audio/basics.html - - title: OpenSL ES for Android - path: /ndk/guides/audio/opensl-for-android.html - - title: Audio Input Latency - path: /ndk/guides/audio/input-latency.html - - title: Audio Output Latency - path: /ndk/guides/audio/output-latency.html - - title: Floating-Point Audio - path: /ndk/guides/audio/floating-point.html - - title: Sample Rates - path: /ndk/guides/audio/sample-rates.html - - title: OpenSL ES Programming Notes - path: /ndk/guides/audio/opensl-prog-notes.html - -- title: Vulkan - path: /ndk/guides/graphics/index.html - section: - - title: Getting Started - path: /ndk/guides/graphics/getting-started.html - - title: Design Guidelines - path: /ndk/guides/graphics/design-notes.html - - title: Shader Compilers - path: /ndk/guides/graphics/shader-compilers.html - - title: Validation Layers - path: /ndk/guides/graphics/validation-layer.html diff --git a/docs/html/ndk/guides/abis.jd b/docs/html/ndk/guides/abis.jd deleted file mode 100644 index 306cfdbb17e2fd8ba385027a5de63090f2f4e802..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/abis.jd +++ /dev/null @@ -1,469 +0,0 @@ -page.title=ABI Management -@jd:body - - - -

    Different Android handsets use different CPUs, which in turn support different instruction sets. -Each combination of CPU and instruction sets has its own Application Binary Interface, or -ABI. The ABI defines, with great precision, how an application's machine code is supposed to -interact with the system at runtime. You must specify an ABI for each CPU architecture you want -your app to work with.

    - -

    A typical ABI includes the following information:

    - -
      -
    • The CPU instruction set(s) that the machine code should use.
    • -
    • The endianness of memory stores and loads at runtime.
    • -
    • The format of executable binaries, such as programs and shared libraries, and -the types of content they support.
    • -
    • Various conventions for passing data between your code and the system. -These conventions include alignment constraints, as well as how the system uses the stack and -registers when it calls functions.
    • -
    • The list of function symbols available to your machine code at runtime, -generally from very specific sets of libraries.
    • -
    - -

    This page enumerates the ABIs that the NDK supports, and provides information about how each ABI -works.

    - -

    Supported ABIs

    - -

    Each ABI supports one or more instruction sets. Table 1 provides an at-a-glance overview of -the instruction sets each ABI supports.

    - -

    - Table 1. ABIs and supported instruction sets.

    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ABISupported Instruction Set(s)Notes
    {@code armeabi}
  • ARMV5TE and later
  • -
  • Thumb-1
  • No hard float.
    {@code armeabi-v7a} -
  • armeabi
  • -
  • Thumb-2
  • -
  • VFPv3-D16
  • -
  • Other, optional
  • Incompatible with ARMv5, v6 devices.
    {@code arm64-v8a}
  • AArch-64
  • -{@code x86}
  • x86 (IA-32)
  • -
  • MMX
  • -
  • SSE/2/3
  • -
  • SSSE3
  • No support for MOVBE or SSE4.
    {@code x86_64} -
  • x86-64
  • -
  • MMX
  • -
  • SSE/2/3
  • -
  • SSSE3
  • -
  • SSE4.1, 4.2
  • -
  • POPCNT
  • {@code mips}
  • MIPS32r1 and later
  • Uses hard-float, and assumes a CPU:FPU clock ratio of 2:1 for maximum -compatibility. Provides neither micromips nor MIPS16.
    {@code mips64}
  • MIPS64r6
  • -
    - -

    More detailed information about each ABI appears below.

    - -

    armeabi

    -

    This ABI is for ARM-based CPUs that support at least -the ARMv5TE instruction set. Please refer to the following documentation for -more details:

    - - - -

    The AAPCS standard defines EABI as a family of similar -but distinct ABIs. Also, Android follows the little-endian - -ARM GNU/Linux ABI.

    - -

    This ABI does not support hardware-assisted floating point -computations. Instead, all floating-point operations use software helper -functions from the compiler's {@code libgcc.a} static library.

    - -

    The armeabi ABI supports ARM’s - -Thumb (a.k.a. Thumb-1) instruction set. The NDK generates Thumb -code by default unless you specify different behavior using the -LOCAL_ARM_MODE variable in your -{@code Android.mk} -file.

    - -

    armeabi-v7a

    -

    This ABI extends armeabi to include several - -CPU instruction set extensions. The instruction extensions that this Android-specific -ABI supports are:

    - -
      -
    • The Thumb-2 instruction set extension, which provides performance comparable to 32-bit ARM -instructions with similar compactness to Thumb-1.
    • -
    • The VFP hardware-FPU instructions. More specifically, VFPv3-D16, which -includes 16 dedicated 64-bit floating point registers, in addition to another -16 32-bit registers from the ARM core.
    • -
    - -

    Other extensions that the v7-a ARM spec describes, including - -Advanced SIMD (a.k.a. NEON), VFPv3-D32, and ThumbEE, are optional -to this ABI. Since their presence is not guaranteed, the system should check at runtime -whether the extensions are available. If they are not, you must use alternative code paths. This -check is similar to the one that the system typically performs to check or use -MMX, -SSE2, and other specialized -instruction sets on x86 CPUs.

    - -

    For information about how to perform these runtime checks, refer to -The {@code cpufeatures} Library. -Also, for information about the NDK's support for building -machine code for NEON, see -NEON Support.

    - -

    The {@code armeabi-v7a} ABI uses the {@code -mfloat-abi=softfp} switch to -enforce the rule that the compiler must pass all double values in core register pairs during -function calls, instead of dedicated floating-point ones. The system can perform all internal -computations using the FP registers. Doing so speeds up the computations greatly.

    - -

    arm64-v8a

    -

    This ABI is for ARMv8-based CPUs that support AArch64. It also includes the NEON and -VFPv4 instruction sets.

    - -

    For more information, see the -ARMv8 -Technology Preview, and contact ARM for further details.

    - -

    x86

    -

    This ABI is for CPUs supporting the instruction set commonly -referred to as "x86" or "IA-32". Characteristics of this ABI include:

    - -
      -
    • Instructions normally generated by GCC with compiler flags such as the following: - -
      --march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32
      -
      - -

      These flags target the the Pentium Pro instruction set, along with the -the MMX, -SSE, -SSE2, -SSE3, and -SSSE3 instruction set extensions. -The generated code is an optimization balanced across the top Intel 32-bit -CPUs.

      -

      For more information on compiler flags, particularly related to performance optimization, -refer to GCC -x86 performance hints.

      -
    • -
    • Use of the standard Linux x86 32-bit calling convention, as opposed to the one for SVR. For -more information, see section 6, "Register Usage", of -Calling conventions for different -C++ compilers and operating systems.
    • -
    - -

    The ABI does not include any other optional IA-32 instruction set -extensions, such as:

    -
      -
    • MOVBE
    • -
    • Any variant of SSE4.
    • -
    -

    You can still use these extensions, as long as you use runtime feature-probing to -enable them, and provide fallbacks for devices that do not support them.

    -

    The NDK toolchain assumes 16-byte stack alignment before a function call. The default tools and -options enforce this rule. If you are writing assembly code, you must make sure to maintain stack -alignment, and ensure that other compilers also obey this rule.

    - -

    Refer to the following documents for more details:

    - - -

    x86_64

    -

    This ABI is for CPUs supporting the instruction set commonly referred to as -"x86-64." It supports instructions that GCC typically generates with the following -compiler flags:

    -
    --march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel
    -
    - -

    These flags target the x86-64 instruction set, according to the GCC -documentation. along with the -MMX, -SSE, -SSE2, -SSE3, -SSSE3, -SSE4.1, -SSE4.2, and -POPCNT -instruction-set extensions. The generated code is an optimization balanced -across the top Intel 64-bit CPUs.

    - -

    For more information on compiler flags, particularly related to performance optimization, -refer to GCC -x86 Performance.

    - -

    This ABI does not include any other optional x86-64 instruction set -extensions, such as:

    - -
      -
    • MOVBE
    • -
    • SHA
    • -
    • AVX
    • -
    • AVX2
    • -
    - -

    You can still use these extensions, as long as you use runtime feature probing to -enable them, and provide fallbacks for devices that do not support them.

    -

    Refer to the following documents for more details:

    - - - -

    mips

    -

    This ABI is for MIPS-based CPUs that support at least the MIPS32r1 instruction set. It includes -the following features:

    - -
      -
    • MIPS32 revision 1 ISA
    • -
    • Little-endian
    • -
    • O32
    • -
    • Hard-float
    • -
    • No DSP application-specific extensions
    • -
    - -

    For more information, please refer to the following documentation:

    - - - -

    For more specific details, see -MIPS32 Architecture. -Answers to common questions are in the -MIPS FAQ. -

    - - - -

    mips64

    -

    This ABI is for MIPS64 R6. For more information, see -MIPS64 Architecture.

    - -

    Generating Code for a Specific ABI

    -

    By default, the NDK generates machine code for the armeabi ABI. You can -generate ARMv7-a-compatible machine code, instead, by adding the following line -to your {@code Application.mk} file.

    -
    -APP_ABI := armeabi-v7a
    -
    - -

    To build machine code for two or more distinct ABIs, using spaces as delimiters. For -example:

    - -
    -APP_ABI := armeabi armeabi-v7a
    -
    - -

    This setting tells the NDK to build two versions of your machine code: one -for each ABI listed on this line. For more information on the values you can specify for the -{@code APP_ABI} variable, see Android.mk. -

    - -

    When you build multiple machine-code versions, the build system copies the libraries to your -application project path, and ultimately packages them into your APK, so creating -a fat binary. A fat binary -is larger than one containing only the machine code for a single system; the tradeoff is -gaining wider compatibility, but at the expense of a larger APK.

    - -

    At installation time, the package manager unpacks only the most appropriate -machine code for the target device. For details, see Automatic -extraction of native code at install time.

    - - -

    ABI Management on the Android Platform

    -

    This section provides details about how the Android platform manages native -code in APKs.

    - -

    Native code in app packages

    -

    Both the Play Store and Package Manager expect to find NDK-generated -libraries on filepaths inside the APK matching the following pattern:

    - -
    -/lib/<abi>/lib<name>.so
    -
    - -

    Here, {@code } is one of the ABI names listed under Supported ABIs, -and {@code } is the name of the library as you defined it for the {@code LOCAL_MODULE} -variable in the {@code Android.mk} file. Since -APK files are just zip files, it is trivial to open them and confirm that the shared native -libraries are where they belong.

    - -

    If the system does not find the native shared libraries where it expects them, it cannot use -them. In such a case, the app itself has to copy the libraries over, and then -perform dlopen().

    - -

    In a fat binary, each library resides under a directory whose name matches a corresponding ABI. -For example, a fat binary may contain:

    - -
    -/lib/armeabi/libfoo.so
    -/lib/armeabi-v7a/libfoo.so
    -/lib/arm64-v8a/libfoo.so
    -/lib/x86/libfoo.so
    -/lib/x86_64/libfoo.so
    -/lib/mips/libfoo.so
    -/lib/mips64/libfoo.so
    -
    - -

    Note: ARMv7-based Android devices running 4.0.3 or earlier -install native libraries from the {@code armeabi} directory instead of the {@code armeabi-v7a} -directory if both directories exist. This is because {@code /lib/armeabi/} comes after -{@code /lib/armeabi-v7a/} in the APK. This issue is fixed from 4.0.4.

    - -

    Android Platform ABI support

    -

    The Android system knows at runtime which ABI(s) it supports, because build-specific system -properties indicate:

    - -
      -
    • The primary ABI for the device, corresponding to the machine code used in -the system image itself.
    • -
    • An optional, secondary ABI, corresponding to another ABI that the system image also supports. -
    • -
    - -

    This mechanism ensures that the system extracts the best machine code from -the package at installation time.

    - -

    For best performance, you should compile directly for the primary ABI. For example, a -typical ARMv5TE-based device would only define the primary ABI: {@code armeabi}. By contrast, a -typical, ARMv7-based device would define the primary ABI as {@code armeabi-v7a} and the secondary -one as {@code armeabi}, since it can run application native binaries generated for each of them.

    - -

    Many x86-based devices can also run {@code armeabi-v7a} and {@code armeabi} NDK binaries. For -such devices, the primary ABI would be {@code x86}, and the second one, {@code armeabi-v7a}.

    - -

    A typical MIPS-based device only defines a primary abi: {@code mips}.

    - -

    Automatic extraction of native code at install time

    - -

    When installing an application, the package manager service scans the APK, and looks for any -shared libraries of the form:

    - -
    -lib/<primary-abi>/lib<name>.so
    -
    - -

    If none is found, and you have defined a secondary ABI, the service scans for shared libraries of -the form:

    - -
    -lib/<secondary-abi>/lib<name>.so
    -
    - -

    When it finds the libraries that it's looking for, the package manager -copies them to /lib/lib<name>.so, under the application's -{@code data} directory ({@code data/data//lib/}).

    - -

    If there is no shared-object file at all, the application builds and installs, but crashes at -runtime.

    diff --git a/docs/html/ndk/guides/android_mk.jd b/docs/html/ndk/guides/android_mk.jd deleted file mode 100644 index 1416d13c76640d9fb1237596566453f5dbe093ec..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/android_mk.jd +++ /dev/null @@ -1,875 +0,0 @@ -page.title=Android.mk -@jd:body - - - - -

    This page describes the syntax of the {@code Android.mk} build file, -which glues your C and C++ source files to the Android NDK.

    - -

    Overview

    -

    The {@code Android.mk} file resides in a subdirectory of your project's {@code jni/} directory, -and describes your sources and shared libraries to the build system. It is really a tiny GNU -makefile fragment that the build system parses once or more. The {@code Android.mk} file is useful -for defining project-wide settings that {@code -Application.mk}, the build system, and your -environment variables leave undefined. It can also override project-wide settings for specific -modules.

    - -

    The syntax of the {@code Android.mk} allows you to group your sources into -modules. A module is either a static library, a shared library, or a standalone -executable. You can define one or more modules in each {@code Android.mk} file, and -you can use the same source file in multiple modules. The build system only places shared libraries -into your application package. In addition, static libraries can generate shared libraries.

    - -

    In addition to packaging libraries, the build system handles a variety of other details for you. -For example, you don't need to list header files or explicit dependencies between generated files in -your {@code Android.mk} file. The NDK build system computes these relationships automatically for -you. As a result, you should be able to benefit from new toolchain/platform support in future NDK -releases without having to touch your {@code Android.mk} file.

    - -

    The syntax of this file is very close to that used in the {@code Android.mk} files distributed with -the full Android Open Source Project. While the -build system implementation that uses them is different, their similarity is an -intentional design decision aimed at making it easier for application -developers to reuse source code for external libraries.

    - -

    Basics

    -

    Before exploring the syntax in detail, it is useful to start by understanding the basics -of what a {@code Android.mk} file contains. This section uses the {@code Android.mk} file in the -Hello-JNI sample toward that end, explaining the role that each line in the file plays.

    - - -

    An {@code Android.mk} file must begin by defining the {@code LOCAL_PATH} variable: - -

    -LOCAL_PATH := $(call my-dir)
    -
    - -

    This variable indicates the location of the source files in the development tree. Here, the macro -function {@code my-dir}, provided by the build system, returns the path of the current directory -(the directory containing the {@code Android.mk} file itself).

    - -

    The next line declares the {@code CLEAR_VARS} variable, whose value the build system provides. - -

    -include $(CLEAR_VARS)
    -
    - -

    The {@code CLEAR_VARS} variable points to a special GNU Makefile that clears many -{@code LOCAL_XXX} variables for you, such as {@code LOCAL_MODULE}, {@code LOCAL_SRC_FILES}, and -{@code LOCAL_STATIC_LIBRARIES}. Note that it does not clear {@code LOCAL_PATH}. This variable must -retain its value because the system parses all build control files in a single GNU Make execution -context where all variables are global. You must (re-)declare this variable before describing each -module.

    - -

    Next, the {@code LOCAL_MODULE} variable stores the name of the module that you wish to build. -Use this variable once per module in your application.

    - -
    -LOCAL_MODULE := hello-jni
    -
    - -

    Each module name must be unique and not contain any spaces. The build system, when it -generates the final shared-library file, automatically adds the proper prefix and suffix to -the name that you assign to {@code LOCAL_MODULE}. For example, the example that appears above -results in generation of a library called {@code libhello-jni.so}.

    - -

    Note: If your module's name already starts with {@code lib}, the -build system does not prepend an additional {@code lib} prefix; it takes the module name as-is, and -adds the {@code .so} extension. So a source file originally called, for example, {@code libfoo.c} -still produces a shared-object file called {@code libfoo.so}. This behavior is to support libraries -that the Android platform sources generate from {@code Android.mk} files; the names of all such -libraries start with {@code lib}.

    - -

    The next line enumerates the source files, with spaces delimiting multiple files:

    - -
    -LOCAL_SRC_FILES := hello-jni.c
    -
    - -

    The {@code LOCAL_SRC_FILES} variable must contain a list of C and/or C++ source files to build -into a module.

    - -

    The last line helps the system tie everything together:

    - -
    -include $(BUILD_SHARED_LIBRARY)
    -
    - -

    The {@code BUILD_SHARED_LIBRARY} variable points to a GNU Makefile script that collects all the -information you defined in {@code LOCAL_XXX} variables since the most recent {@code include}. This -script determines what to build, and how to do it.

    - -

    There are more complex examples in the samples directories, with commented -{@code Android.mk} files that you can look at. In addition, -Sample: native-activity provides -a detailed explanation of that sample's {@code Android.mk} file. Finally, -Variables and Macros provides further information on the variables from this section. - - -

    Variables and Macros

    -

    The build system provides many possible variables for use in the the {@code Android.mk} file. -Many of these variables come with preassigned values. Others, you assign.

    - -

    In addition to these variables, you can also define your own arbitrary ones. If you do so, keep -in mind that the NDK build system reserves the following variable names:

    -
      -
    • Names that begin with {@code LOCAL_}, such as {@code LOCAL_MODULE}.
    • -
    • Names that begin with {@code PRIVATE_}, {@code NDK_}, or {@code APP}. The build system uses -these internally.
    • -
    • Lower-case names, such as {@code my-dir}. The build system uses these internally, as well.
    • -
    -

    If you need to define your own convenience variables in an {@code Android.mk} file, we -recommend prepending {@code MY_} to their names. - - -

    NDK-defined variables

    -

    This section discusses the GNU Make variables that the build system defines before parsing your -{@code Android.mk} file. Under certain circumstances, the NDK might parse your {@code Android.mk} -file several times, using a different definition for some of these variables each time.

    - -

    CLEAR_VARS

    -

    This variable points to a build script that undefines nearly all {@code LOCAL_XXX} variables -listed in the "Developer-defined variables" section below. Use this variable to include -this script before describing a new module. The syntax for using it is:

    - -
    -include $(CLEAR_VARS)
    -
    - -

    BUILD_SHARED_LIBRARY

    -

    This variable points to a build script that collects all the information about the module -you provided in your {@code LOCAL_XXX} variables, and determines how to build a target shared -library from the sources you listed. Note that using this script requires that you have already -assigned values to {@code LOCAL_MODULE} and {@code LOCAL_SRC_FILES}, at a minimum (for more -information about these variables, see Module-Description Variables).

    - -

    The syntax for using this variable is:

    - -
    -include $(BUILD_SHARED_LIBRARY)
    -
    - -

    A shared-library variable causes the build system to generate a library file with a {@code .so} -extension.

    - -

    BUILD_STATIC_LIBRARY

    -

    A variant of {@code BUILD_SHARED_LIBRARY} that is used to build a static library. The build -system does not copy static libraries into your project/packages, but it can use them to build -shared libraries (see {@code LOCAL_STATIC_LIBRARIES} and {@code LOCAL_WHOLE_STATIC_LIBRARIES}, -below). The syntax for using this variable is:

    - -
    -include $(BUILD_STATIC_LIBRARY)
    -
    - -

    A static-library variable causes the build system to generate a library with a {@code .a} -extension.

    - -

    PREBUILT_SHARED_LIBRARY

    -

    Points to a build script used to specify a prebuilt shared library. Unlike in the case of -{@code BUILD_SHARED_LIBRARY} and {@code BUILD_STATIC_LIBRARY}, here the value of -{@code LOCAL_SRC_FILES} cannot be a source file. Instead, it must be a single path to a prebuilt -shared library, such as {@code foo/libfoo.so}. The syntax for using this variable is:

    - -
    -include $(PREBUILT_SHARED_LIBRARY)
    -
    - -

    You can also reference a prebuilt library in another module by using the -{@code LOCAL_PREBUILTS} variable. For more information about using prebuilts, see -Using Prebuilt Libraries.

    - - -

    PREBUILT_STATIC_LIBRARY

    -

    The same as {@code PREBUILT_SHARED_LIBRARY}, but for a prebuilt static library. For more -information about using prebuilts, see Using Prebuilt -Libraries.

    - -

    TARGET_ARCH

    -

    The name of the target CPU architecture as the Android Open Source Project specifies it. -For any ARM-compatible build, use {@code arm}, independent of the CPU architecture revision or -ABI (see TARGET_ARCH_ABI, below).

    - -

    The value of this variable is taken from the APP_ABI variable that you define in the -{@code Android.mk} file, which the system reads ahead of parsing the {@code Android.mk} file.

    - -

    TARGET_PLATFORM

    -

    The Android API level number for the build system to target. -For example, the Android 5.1 system images correspond to Android API level 22: {@code android-22}. -For a complete list of platform names and corresponding Android system -images, see Android NDK Native APIs. -The following example shows the syntax for using this variable:

    - -
    -TARGET_PLATFORM := android-22
    -
    - -

    TARGET_ARCH_ABI

    -

    This variable stores the name of the CPU and architecture to target when the build system -parses this {@code Android.mk} file. You can specify one or more of the following values, using -a space as a delimiter between multiple targets. Table 1 shows the ABI setting to use for each -supported CPU and architecture. - -

    - Table 1. ABI settings for different CPUs and architectures.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    CPU and architectureSetting
    ARMv5TE{@code armeabi}
    ARMv7{@code armeabi-v7a}
    ARMv8 AArch64{@code arm64-v8a}
    i686{@code x86}
    x86-64{@code x86_64}
    mips32 (r1){@code mips}
    mips64 (r6){@code mips64}
    All{@code all}
    - -

    The following example shows how to set ARMv8 AArch64 as the target CPU-and-ABI combination:

    - -
    -TARGET_ARCH_ABI := arm64-v8a
    -
    - -

    Note: Up to Android NDK 1.6_r1, this variable is defined as -{@code arm}.

    - -

    For more details about architecture ABIs and associated compatibility -issues, refer to -ABI Management.

    - -

    New target ABIs in the future will have different values.

    - -

    TARGET_ABI

    -

    A concatenation of target Android API level and ABI, it is especially useful when you want to test against -a specific target system image for a real device. For example, to specify a 64-bit ARM device -running on Android API level 22:

    - -
    -TARGET_ABI := android-22-arm64-v8a
    -
    - -

    Note: Up to Android NDK 1.6_r1, the default value was -{@code android-3-arm}.

    - -

    Module-Description Variables

    -

    The variables in this section describe your module to the build system. Each module description -should follow this basic flow: -

      -
        -
      1. Initialize or undefine the variables associated with the module, using the {@code CLEAR_VARS} - variable.
      2. -
      3. Assign values to the variables used to describe the module. -
      4. Set the NDK build system to use the appropriate build script for the module, using the - {@code BUILD_XXX} variable.
      5. -
      -
    - -

    LOCAL_PATH

    -

    This variable is used to give the path of the current file. You must define -it at the start of your {@code Android.mk} file. The following example shows how to do so:

    - -
    -LOCAL_PATH := $(call my-dir)
    -
    - -

    The script to which {@code CLEAR_VARS} points does not clear this variable. Therefore, you only need -to define it a single time, even if your {@code Android.mk} file describes multiple modules.

    - -

    LOCAL_MODULE

    -

    This variable stores the name of your module. It must be unique among all module names, -and must not contain any spaces. You must define it before including any scripts (other than -the one for {@code CLEAR_VARS}). You need not add either the {@code lib} prefix -or the {@code .so} or {@code .a} file extension; the build system makes these modifications -automatically. Throughout your {@code Android.mk} and -{@code Application.mk} files, refer to -your module by its unmodified name. For example, the following line results in the generation of a -shared library module called {@code libfoo.so}:

    - -
    -LOCAL_MODULE := "foo"
    -
    - -

    If you want the generated module to have a name other than {@code lib} + the value of -{@code LOCAL_MODULE}, you can use the {@code LOCAL_MODULE_FILENAME} variable to give the -generated module a name of your own choosing, instead.

    - -

    LOCAL_MODULE_FILENAME

    -

    This optional variable allows you to override the names that the build system -uses by default for files that it generates. For example, if the name of your {@code LOCAL_MODULE} -is {@code foo}, you can force the system to call the file it generates {@code libnewfoo}. The -following example shows how to accomplish this:

    - -
    -LOCAL_MODULE := foo
    -LOCAL_MODULE_FILENAME := libnewfoo
    -
    - -

    For a shared library module, this example would generate a file called {@code libnewfoo.so}.

    - -

    Note: You cannot override filepath or file extension.

    - -

    LOCAL_SRC_FILES

    -

    This variable contains the list of source files that the build system uses to generate the -module. Only list the files that the build system actually passes to the compiler, since the build -system automatically computes any associated depencies.

    -

    Note that you can use both relative (to {@code LOCAL_PATH}) and absolute file paths. - -

    We recommend avoiding absolute file paths; relative paths make your {@code Android.mk} file more -portable.

    - -

    Note: Always use Unix-style forward slashes (/) in build files. -The build system does not handle Windows-style backslashes (\) properly.

    - -

    LOCAL_CPP_EXTENSION

    -

    You can use this optional variable to indicate a file extension other than {@code .cpp} for your -C++ source files. For example, the following line changes the extension to {@code .cxx}. -(The setting must include the dot.) - -

    -LOCAL_CPP_EXTENSION := .cxx
    -
    - -

    From NDK r7, you can use this variable to specify multiple extensions. For instance:

    - -
    -LOCAL_CPP_EXTENSION := .cxx .cpp .cc
    -
    - -

    LOCAL_CPP_FEATURES

    - -

    You can use this optional variable to indicate that your code relies on specific C++ features. -It enables the right compiler and linker flags during the build process. For prebuilt binaries, -this variable also declares which features the binary depends on, thus helping ensure the final -linking works correctly. We recommend that you use this variable instead of enabling -{@code -frtti} and {@code -fexceptions} directly in your {@code LOCAL_CPPFLAGS} definition.

    - -

    Using this variable allows the build system to use the appropriate flags for each module. Using -{@code LOCAL_CPPFLAGS} causes the compiler to use all specified flags for all modules, regardless -of actual need.

    - -For example, to indicate that your code uses RTTI (RunTime Type Information), write:

    - -
    -LOCAL_CPP_FEATURES := rtti
    -
    - -

    To indicate that your code uses C++ exceptions, write:

    - -
    -LOCAL_CPP_FEATURES := exceptions
    -
    - -

    You can also specify multiple values for this variable. For example:

    - -
    -LOCAL_CPP_FEATURES := rtti features
    -
    - -The order in which you describe the values does not matter. - - -

    LOCAL_C_INCLUDES

    -

    You can use this optional variable to specify a list of paths, relative to the -NDK {@code root} directory, to add to the include search path when compiling all sources -(C, C++ and Assembly). For example:

    - -
    -LOCAL_C_INCLUDES := sources/foo
    -
    - -

    Or even:

    - -
    -LOCAL_C_INCLUDES := $(LOCAL_PATH)//foo
    -
    - -

    Define this variable before setting any corresponding inclusion flags via {@code LOCAL_CFLAGS} -or {@code LOCAL_CPPFLAGS}.

    - -

    The build system also uses {@code LOCAL_C_INCLUDES} paths automatically when launching native -debugging with ndk-gdb.

    - - -

    LOCAL_CFLAGS

    - -

    This optional variable sets compiler flags for the build system to pass when building C -and C++ source files. The ability to do so can be useful for specifying additional macro -definitions or compile options.

    - -

    Try not to change the optimization/debugging level in your {@code Android.mk} file. -The build system can handle this setting automatically for you, using the relevant information -in the {@code Application.mk} file. Doing it -this way allows the build system to generate useful data files used during debugging.

    - -

    Note: In android-ndk-1.5_r1, the corresponding flags only applied -to C source files, not C++ ones. They now match the full Android build system behavior. -(You can now use {@code LOCAL_CPPFLAGS} to specify flags for C++ sources only.)

    - -

    It is possible to specify additional include paths by writing: - -

    -LOCAL_CFLAGS += -I<path>,
    -
    - -It is better, however, to use {@code LOCAL_C_INCLUDES} for this purpose, since -doing so also makes it possible to use the paths available for native debugging with ndk-gdb.

    - - -

    LOCAL_CPPFLAGS

    -

    An optional set of compiler flags that will be passed when building C++ -source files only. They will appear after the LOCAL_CFLAGS on the -compiler's command-line.

    - - -

    Note: In android-ndk-1.5_r1, the corresponding flags applied to -both C and C++ sources. This has been corrected to match the full Android build system. -To specify flags for both C and C++ sources, use {@code LOCAL_CFLAGS}.

    - - -

    LOCAL_STATIC_LIBRARIES

    - -

    This variable stores the list of static libraries modules on which the current module depends.

    - -

    If the current module is a shared library or an executable, this variable will force -these libraries to be linked into the resulting binary.

    - -

    If the current module is a static library, this variable simply indicates that other -modules depending on the current one will also depend on the listed -libraries.

    - -

    LOCAL_SHARED_LIBRARIES

    - -

    This variable is the list of shared libraries modules on which this module depends at -runtime. This information is necessary at link time, and to embed the corresponding information -in the generated file.

    - -

    LOCAL_WHOLE_STATIC_LIBRARIES

    -

    This variable is a variant of {@code LOCAL_STATIC_LIBRARIES}, and expresses that the linker -should treat the associated library modules as whole archives. For more information -on whole archives, see the GNU linker's -documentation for the -{@code --whole-archive} flag.

    - -

    This variable is useful when there are circular dependencies among -several static libraries. When you use this variable to build a shared library, it will force -the build system to add all object files from your static libraries to the final binary. The same -is not true, however, when generating executables.

    - - -

    LOCAL_LDLIBS

    - -

    This variable contains the list of additional linker flags for use in building your shared -library or executable. It enables you to use the {@code -l} prefix to pass the name of specific -system libraries. For example, the following example tells the linker to generate a module that -links to {@code /system/lib/libz.so} at load time:

    - -
    -LOCAL_LDLIBS := -lz
    -
    - -

    For the list of exposed system libraries against which you can link in this NDK release, see -Android NDK Native APIs.

    - -

    Note: If you define this variable for a static library, -the build system ignores it, and {@code ndk-build} prints a warning.

    - -

    LOCAL_LDFLAGS

    - -

    The list of other linker flags for the build system to use when building your shared library -or executable. For example, the following example uses the {@code ld.bfd} linker on ARM/X86 GCC -4.6+, on which {@code ld.gold} is the default

    - -
    -LOCAL_LDFLAGS += -fuse-ld=bfd
    -
    - -

    Note: If you define this variable for a static library, the build -system ignores it, and ndk-build prints a warning.

    - -

    LOCAL_ALLOW_UNDEFINED_SYMBOLS

    - -

    By default, when the build system encounters an undefined reference encountered while trying to -build a shared, it will throw an undefined symbol error. This error can help you catch -catch bugs in your source code.

    - -

    To disable this check, set this variable to {@code true}. Note that this setting may cause the -shared library to load at runtime.

    - -

    Note: If you define this variable for a static library, -the build system ignores it, and ndk-build prints a warning.

    - -

    LOCAL_ARM_MODE

    -

    By default, the build system generates ARM target binaries in thumb mode, where each -instruction is 16 bits wide and linked with the STL libraries in the {@code thumb/} directory. -Defining this variable as {@code arm} forces the build system to generate the module's object -files in 32-bit {@code arm} mode. The following example shows how to do this:

    - -
    -LOCAL_ARM_MODE := arm
    -
    - -

    You can also instruct the build system to only build specific sources in {@code arm} mode by -appending {@code .arm} suffix to the the source filenames. For example, the following example -tells the build system to always compile {@code bar.c} in ARM mode, but to build -{@code foo.c} according to the value of {@code LOCAL_ARM_MODE}.

    - -
    -LOCAL_SRC_FILES := foo.c bar.c.arm
    -
    - -

    - -

    Note: You can also force the build system to generate ARM binaries -by setting {@code APP_OPTIM} in your -{@code Application.mk} file to {@code debug}. -Specifying {@code debug} forces an ARM build because the toolchain debugger does not handle Thumb -code properly.

    - - -

    LOCAL_ARM_NEON

    -

    This variable only matters when you are targeting the {@code armeabi-v7a} ABI. It allows the -use of ARM Advanced SIMD (NEON) GCC intrinsics in your C and C++ sources, as well as NEON -instructions in Assembly files.

    - -

    Note that not all ARMv7-based CPUs support the NEON instruction set extensions. For this reason, -you must perform runtime detection to be able to safely use this code at runtime. For more -information, see NEON Support and The {@code cpufeatures} Library.

    - -

    Alternatively, you can use the {@code .neon} suffix to specify that the build system only -compile specific source files with NEON support. In the following example, the build system compiles -{@code foo.c} with thumb and neon support, {@code bar.c} with thumb support, and -{@code zoo.c} with support for ARM and NEON:

    - -
    -LOCAL_SRC_FILES = foo.c.neon bar.c zoo.c.arm.neon
    -
    - - -

    If you use both suffixes, {@code .arm} must precede {@code .neon}.

    - -

    LOCAL_DISABLE_NO_EXECUTE

    - -

    Android NDK r4 added support for the "NX bit" security feature. It is -enabled by default, but you can disable it by setting this variable to {@code true}. We do not -recommend doing so without a compelling reason.

    - -

    This feature does not modify the ABI, and is only enabled on kernels -targeting ARMv6+ CPU devices. Machine code with this feature enabled -will run unmodified on devices running earlier CPU architectures.

    -

    For more information, see Wikipedia: NX bit -and The GNU stack kickstart. - -

    LOCAL_DISABLE_RELRO

    - -

    By default, the NDK compiles code with read-only relocations and GOT -protection. This variable instructs the runtime linker to mark certain regions of memory -as read-only after relocation, making certain security exploits (such as GOT overwrites) -more difficult. Note that these protections are only effective on Android API level 16 and higher. -On lower API levels, the code will still run, but without memory protections.

    - -

    This variable is turned on by default, but you can disable it by setting its value to -{@code true}. We do not recommend doing so without a compelling reason.

    - -

    For more information, see -RELRO: -RELocation Read-Only and Security -enhancements in RedHat Enterprise Linux (section 6).

    - -

    LOCAL_DISABLE_FORMAT_STRING_CHECKS

    - -

    By default, the build system compiles code with format string protection. Doing so forces a -compiler error if a non-constant format string is used in a {@code printf}-style function.

    -

    This protection is on by default, but you can disable it by setting the value of -this variable to {@code true}. We do not recommend doing so without a compelling reason.

    - - -

    LOCAL_EXPORT_CFLAGS

    - -

    This variable records a set of C/C++ compiler flags to add to the {@code LOCAL_CFLAGS} definition -of any other module that uses this one via the {@code LOCAL_STATIC_LIBRARIES} or -{@code LOCAL_SHARED_LIBRARIES} variables.

    - -

    For example, consider the following pair of modules: {@code foo} and {@code bar}, which depends -on {@code foo}:

    - -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := foo
    -LOCAL_SRC_FILES := foo/foo.c
    -LOCAL_EXPORT_CFLAGS := -DFOO=1
    -include $(BUILD_STATIC_LIBRARY)
    -
    -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := bar
    -LOCAL_SRC_FILES := bar.c
    -LOCAL_CFLAGS := -DBAR=2
    -LOCAL_STATIC_LIBRARIES := foo
    -include $(BUILD_SHARED_LIBRARY)
    -
    - -

    Here, the build system passes the flags {@code -DFOO=1} and {@code -DBAR=2} to the compiler when -building {@code bar.c}. It also prepends exported flags to your your module's {@code LOCAL_CFLAGS} -so you can easily override them.

    - -In addition, the relationship among modules is transitive: If {@code zoo} depends on -{@code bar}, which in turn depends on {@code foo}, then {@code zoo} also inherits all flags -exported from {@code foo}.

    - -

    Finally, the build system does not use exported flags when building locally (i.e., building the -module whose flags it is exporting). Thus, in the example above, it does not pass {@code -DFOO=1} -to the compiler when building {@code foo/foo.c}. To build locally, use {@code LOCAL_CFLAGS} -instead.

    - -

    LOCAL_EXPORT_CPPFLAGS

    -

    This variable is the same as {@code LOCAL_EXPORT_CFLAGS}, but for C++ flags only.

    - -

    LOCAL_EXPORT_C_INCLUDES

    -

    This variable is the same as {@code LOCAL_EXPORT_CFLAGS}, but for C include paths. It is useful -in cases where, for example, {@code bar.c} needs to include headers from module {@code foo}.

    - -

    LOCAL_EXPORT_LDFLAGS

    -

    This variable is the same as {@code LOCAL_EXPORT_CFLAGS}, but for linker flags.

    - -

    LOCAL_EXPORT_LDLIBS

    -

    This variable is the same as {@code LOCAL_EXPORT_CFLAGS}, telling the build system to pass names -of specific system libraries to the compiler. Prepend {@code -l} to the name of each library you -specify.

    - -

    Note that the build system appends imported linker flags to the value of your module's -{@code LOCAL_LDLIBS} variable. It does this due to the way Unix linkers work.

    - -

    This variable is typically useful when module {@code foo} is a static library -and has code that depends on a system library. You can then use {@code LOCAL_EXPORT_LDLIBS} to -to export the dependency. For example:

    - -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := foo
    -LOCAL_SRC_FILES := foo/foo.c
    -LOCAL_EXPORT_LDLIBS := -llog
    -include $(BUILD_STATIC_LIBRARY)
    -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := bar
    -LOCAL_SRC_FILES := bar.c
    -LOCAL_STATIC_LIBRARIES := foo
    -include $(BUILD_SHARED_LIBRARY)
    -
    - -

    In this example, the build system puts {@code -llog} at the end of the linker command when it -builds {@code libbar.so}. Doing so tells the linker that, because {@code libbar.so} depends -on {@code foo}, it also depends on the system logging library.

    - -

    LOCAL_SHORT_COMMANDS

    -

    Set this variable to {@code true} when your module has a very high -number of sources and/or dependent static or shared libraries. Doing so forces the -build system to use {@code @} syntax for archives containing intermediate object files -or linking libraries.

    - -

    This feature can be useful on Windows, where the command line accepts a maximum of only -of 8191 characters, which can be too small for complex projects. It also impacts the compilation of -individual source files, placing nearly all compiler flags inside list files, too.

    - -

    Note that any value other than {@code true} will revert to the -default behaviour. You can also define {@code APP_SHORT_COMMANDS} in your -{@code Application.mk} file to force this -behavior for all modules in your project.

    - -

    We do not recommend enabling this feature by default, since it makes the build slower.

    - - -

    LOCAL_THIN_ARCHIVE

    - -

    Set this variable to {@code true} when building static libraries. -Doing so will generate a thin archive, a library file that does not contain -object files, but instead just file paths to the actual objects that it would normally -contain.

    -

    This is useful to reduce the size of your build output. The drawback is that -such libraries cannot be moved to a different location (all paths -inside them are relative).

    -

    Valid values are {@code true}, {@code false} or empty. A -default value can be set in your -{@code Application.mk} file through the {@code APP_THIN_ARCHIVE} - -variable.

    -

    Note: This is ignored for non-static library modules, or prebuilt -static library ones.

    - -

    LOCAL_FILTER_ASM

    -

    Define this variable as a shell command that the build system will use to filter the -assembly files extracted or generated from the files you specified for {@code LOCAL_SRC_FILES}.

    -

    Defining this variable causes the following things to occur:

    - -
      -
        -
      1. The build system generates a temporary assembly file from any C or C++ source file, instead of compiling them into an object file.
      2. -
      3. The build system executes the shell command in {@code LOCAL_FILTER_ASM} -on any temporary assembly file and on any assembly file -listed in {@code LOCAL_SRC_FILES}, thus generating another temporary assembly -file.
      4. -
      5. The build system compiles these filtered assembly files into an object file.
      6. -
      -
    -

    For example:

    - -
    -LOCAL_SRC_FILES  := foo.c bar.S
    -LOCAL_FILTER_ASM :=
    -
    -foo.c --1--> $OBJS_DIR/foo.S.original --2--> $OBJS_DIR/foo.S --3--> $OBJS_DIR/foo.o
    -bar.S                                 --2--> $OBJS_DIR/bar.S --3--> $OBJS_DIR/bar.o
    -
    - -

    "1" corresponds to the compiler, "2" to the filter, and "3" to the assembler. The filter must -be a standalone shell command that takes the name of the input file as its first argument, and the -name of the output file as the second one. For example:

    - -
    -myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
    -myasmfilter bar.S $OBJS_DIR/bar.S
    -
    - -

    NDK-provided function macros

    -

    This section explains GNU Make function macros that the NDK provides. Use -{@code $(call )} to evaluate them; they return textual information.

    - -

    my-dir

    - -

    This macro returns the path of the last included makefile, which typically is the -current {@code Android.mk}'s directory. {@code my-dir} is useful for defining -{@code LOCAL_PATH} at the start of your {@code Android.mk} file. For example:

    - -
    -LOCAL_PATH := $(call my-dir)
    -
    - -

    Due to the way GNU Make works, what this macro really returns is the -path of the last makefile that the build system included when parsing the build scripts. For this -reason, you should not call {@code my-dir} after including another file.

    - -

    For example, consider the following example:

    - -
    -LOCAL_PATH := $(call my-dir)
    -
    -# ... declare one module
    -
    -include $(LOCAL_PATH)/foo/`Android.mk`
    -
    -LOCAL_PATH := $(call my-dir)
    -
    -# ... declare another module
    -
    - -

    The problem here is that the second call to {@code my-dir} defines -{@code LOCAL_PATH} as {@code $PATH/foo} instead of {@code $PATH}, because that was where its -most recent include pointed.

    - -

    You can avoid this problem by putting additional includes after everything -else in the {@code Android.mk} file. For example:

    - -
    -LOCAL_PATH := $(call my-dir)
    -
    -# ... declare one module
    -
    -LOCAL_PATH := $(call my-dir)
    -
    -# ... declare another module
    -
    -# extra includes at the end of the Android.mk file
    -include $(LOCAL_PATH)/foo/Android.mk
    -
    -
    - -

    If it is not feasible to structure the file in this way, save the value of the first -{@code my-dir} call into another variable. For example:

    - -
    -MY_LOCAL_PATH := $(call my-dir)
    -
    -LOCAL_PATH := $(MY_LOCAL_PATH)
    -
    -# ... declare one module
    -
    -include $(LOCAL_PATH)/foo/`Android.mk`
    -
    -LOCAL_PATH := $(MY_LOCAL_PATH)
    -
    -# ... declare another module
    -
    - -

    all-subdir-makefiles

    - -

    Returns the list of {@code Android.mk} files located in all subdirectories of -the current {@code my-dir} path. - -

    You can use this function to provide deep-nested source directory hierarchies to the build -system. By default, the NDK only looks for files in the directory containing the -{@code Android.mk} file.

    - -

    this-makefile

    -

    Returns the path of the current makefile (from which the build system called the function).

    - -

    parent-makefile

    -

    Returns the path of the parent makefile in the inclusion tree (the path of the makefile that -included the current one).

    - -

    grand-parent-makefile

    -

    Returns the path of the grandparent makefile in the inclusion tree (the path of the makefile that -included the current one).

    - -

    import-module

    -

    A function that allows you to find and include a module's {@code Android.mk} file by the name of -the module. A typical example is as follows:

    - -
    -$(call import-module,<name>)
    -
    - -

    In this example, the build system looks for the module tagged {@code } in the list of -directories referenced that your {@code NDK_MODULE_PATH} environment variable references, and -includes its {@code Android.mk} file automatically for you.

    \ No newline at end of file diff --git a/docs/html/ndk/guides/application_mk.jd b/docs/html/ndk/guides/application_mk.jd deleted file mode 100644 index e669f3fcb467a0b5b269ed11f14c2037bd7f34c5..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/application_mk.jd +++ /dev/null @@ -1,219 +0,0 @@ -page.title=Application.mk -@jd:body - -
    -
    -

    On this page

    - -
      -
    1. Overview
    2. -
    3. Variables
    4. -
    -
    -
    - -

    This document explains the {@code Application.mk} build file, which describes the -native modules that your app requires. A module can be a static library, a shared library, -or an executable.

    - -

    We recommend that you read the Concepts and -Android.mk pages before this one. Doing so will -help maximize your understanding of the material on this page.

    - -

    Overview

    -The {@code Application.mk} file is really a tiny GNU Makefile fragment that defines several -variables for compilation. It usually resides under {@code $PROJECT/jni/}, where {@code $PROJECT} -points to your application's project directory. Another alternative is to place it under a -sub-directory of the top-level {@code $NDK/apps/} directory. For example:

    - -
    -$NDK/apps/<myapp>/Application.mk
    -
    - -

    Here, {@code } is a short name used to describe your app to the NDK build system. It -doesn't actually go into your generated shared libraries or your final packages.

    - -

    Variables

    -

    APP_PROJECT_PATH

    -

    This variable stores the absolute path to your app's project-root directory. The build system -uses this information to place stripped-down versions of the generated JNI shared libraries -into a specific location known to the APK-generating tools.

    - -

    If you place your {@code Application.mk} file under {@code $NDK/apps//}, you must -define this variable. If you place it under {@code $PROJECT/jni/}, it is optional. - -

    APP_OPTIM

    -

    Define this optional variable as either {@code release} or {@code debug}. You use it to -alter the optimization level when building your application's modules.

    - -

    Release mode is the default, and generates highly optimized binaries. Debug mode generates -unoptimized binaries that are much easier to debug.

    - -

    Note that you can debug either release or debug binaries. Release binaries, however, provide less -information during debugging. For example, the build system optimizes out some variables, -preventing you from inspecting them. Also, code re-ordering can make it more difficult to step -through the code; stack traces may not be reliable.

    - -

    Declaring {@code android:debuggable} in your application manifest's {@code } -tag will cause this variable to default to {@code debug} instead of {@code release}. Override this -default value by setting {@code APP_OPTIM} to {@code release}.

    - - -

    APP_CFLAGS

    -

    This variable stores a set of C compiler flags that the build system passes to the compiler -when compiling any C or C++ source code for any of the modules. You can use this variable to change -the build of a given module according to the application that needs it, instead of having to modify -the {@code Android.mk} file itself.

    - - -

    All paths in these flags should be relative to the top-level NDK directory. For example, if you -have the following setup:

    - -
    -sources/foo/Android.mk
    -sources/bar/Android.mk
    -
    - -

    To specify in {@code foo/Android.mk} that you want to add the path to the {@code bar} sources -during compilation, you should use: - -

    -APP_CFLAGS += -Isources/bar
    -
    - -

    Or, alternatively:

    - -
    -APP_CFLAGS += -I$(LOCAL_PATH)/../bar
    -
    - -

    {@code -I../bar} will not work since it is equivalent to -{@code -I$NDK_ROOT/../bar}.

    - -

    Note: This variable only works on C, not C++, sources in -android-ndk-1.5_r1. In all versions after that one, {@code APP_CFLAGS} matches the full Android -build system.

    - -

    APP_CPPFLAGS

    -

    This variable contains a set of C++ compiler flags that the build system passes to the compiler -when building only C++ sources.

    - -

    Note: In android-ndk-1.5_r1, this variable works on both C and -C++ sources. In all subsequent versions of the NDK, {@code APP_CPPFLAGS} now matches the full -Android build system. For flags that apply to both C and C++ sources, use {@code APP_CFLAGS}.

    - -

    APP_LDFLAGS

    -

    A set of linker flags that the build system passes when linking the application. This variable -is only relevant when the build system is building shared libraries and executables. When the -build system builds static libraries, it ignores these flags.

    - -

    APP_BUILD_SCRIPT

    -

    By default, the NDK build system looks under {@code jni/} for a file named -{@code Android.mk}.

    - -

    If you want to override this behavior, you can define {@code APP_BUILD_SCRIPT} to point to an -alternate build script. The build system always interprets a non-absolute path as relative to the -NDK's top-level directory.

    - -

    APP_ABI

    -

    By default, the NDK build system generates machine code for the -{@code armeabi} ABI. This machine code -corresponds to an ARMv5TE-based CPU with software floating point operations. You can use -{@code APP_ABI} to select a different ABI. Table 1 shows the {@code APP_ABI} -settings for different instruction sets.

    - -

    - Table 1. {@code APP_ABI} settings for different instruction sets.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Instruction setValue
    Hardware FPU instructions on ARMv7 based devices{@code APP_ABI := armeabi-v7a}
    ARMv8 AArch64{@code APP_ABI := arm64-v8a}
    IA-32{@code APP_ABI := x86}
    Intel64{@code APP_ABI := x86_64}
    MIPS32{@code APP_ABI := mips}
    MIPS64 (r6){@code APP_ABI := mips64}
    All supported instruction sets{@code APP_ABI := all}
    - -

    Note: {@code all} is available starting from NDKr7.

    - -

    You can also specify multiple values by placing them on the same line, delimited by spaces. -For example:

    - -
    -APP_ABI := armeabi armeabi-v7a x86 mips
    -
    - -

    For the list of all supported ABIs and details about their usage and limitations, refer to -ABI Management.

    - -

    APP_PLATFORM

    -

    This variable contains the name of the target Android platform. For example, {@code android-3} -specifies the Android 1.5 system images. For a complete list of platform names and corresponding -Android system images, see Android NDK Native APIs -.

    - -

    APP_STL

    -

    By default, the NDK build system provides C++ headers for the minimal C++ runtime library -({@code system/lib/libstdc++.so}) provided by the Android system. In addition, it comes with -alternative C++ implementations that you can use or link to in your own applications. -Use {@code APP_STL} to select one of them. For information about the supported runtimes, and the -features they offer, see NDK Runtimes and -Features. - -

    APP_SHORT_COMMANDS

    -

    The equivalent of {@code LOCAL_SHORT_COMMANDS} in {@code Application.mk} for your whole project. -For more information, see the documentation for this variable on -{@code Android.mk}.

    - -

    NDK_TOOLCHAIN_VERSION

    -

    Define this variable as either {@code 4.9} or {@code 4.8} to select a version of the GCC -compiler. Version 4.9 is the default for 64-bit ABIs, and 4.8 is the default for 32-bit ABIs. -To select a version of Clang, define this variable as {@code clang3.4}, {@code clang3.5}, or -{@code clang}. Specifying {@code clang} chooses the most recent version of Clang.

    - -

    APP_PIE

    -

    Starting from Android 4.1 (API level 16), Android's dynamic linker supports position-independent -executables (PIE). From Android 5.0 (API level 21), executables require PIE. - -To use PIE to build your executables, set the {@code -fPIE} flag. This flag makes it harder to -exploit memory corruption bugs by randomizing code location. By default, {@code ndk-build} -automatically sets this value to {@code true} if your project targets {@code android-16} or higher. -You may set it manually to either {@code true} or {@code false}.

    - -

    This flag applies only to executables. It has no effect when building shared or static -libraries.

    - -

    Note: PIE executables cannot run on Android releases prior to 4.1. -

    This restriction only applies to executables. It has no effect when building shared or static -libraries.

    - -

    APP_THIN_ARCHIVE

    -

    Sets the default value of {@code LOCAL_THIN_ARCHIVE} in the {@code Android.mk} file for all -static library modules in this project. For more information, see the documentation for -{@code LOCAL_THIN_ARCHIVE} on {@code Android.mk}. -

    diff --git a/docs/html/ndk/guides/arch.jd b/docs/html/ndk/guides/arch.jd deleted file mode 100644 index 3dafe8f3cc0a6fb6ff9d1364cd875094dc029c6c..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/arch.jd +++ /dev/null @@ -1,19 +0,0 @@ -page.title=CPUs and Architectures -@jd:body - -

    When you're working with native code, hardware matters. The NDK lets you ensure you're compiling -for the right architectures and CPUs by giving you a variety of ABIs from which -to choose.

    - -

    This section begins by explaining how to target specific -architectures and CPUs. It then -provides information you need to know when targeting the -ARM -family of CPUs and architectures. Next, it provides information about the other CPUs and -architectures that it supports: NEON, x86 -(32-bit and -64-bit), and -MIPS. Finally, it explains how to use the -{@code cpufeatures} -library, which your app can use to query a given CPU and architecture about the optional -features they support.

    \ No newline at end of file diff --git a/docs/html/ndk/guides/audio/basics.jd b/docs/html/ndk/guides/audio/basics.jd deleted file mode 100644 index bdb85fb673251933ede7265f8eeb89adc87c3eb7..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/basics.jd +++ /dev/null @@ -1,169 +0,0 @@ -page.title=High-Performance Audio Basics -@jd:body - - - - -
    -

    Video

    -

    Google I/O 2013 - High Performance Audio

    -
    -
    - -

    -The Khronos Group's OpenSL ES™ standard exposes audio features -similar to those in the {@link android.media.MediaPlayer} and {@link android.media.MediaRecorder} -APIs in the Android Java framework. OpenSL ES provides a C language interface as well as -C++ bindings, allowing you to call it from code written in either language. -

    - -

    -This page describes the typical use cases for these high-performance audio APIs, how to add them -into your app's source code, and how to incorporate them into the build process. -

    - -

    Building Great Audio Apps

    - -

    -The OpenSL ES APIs are available to help you develop and improve your app's audio performance. - Some typical use cases include the following:

    - -
      -
    • Digital Audio Workstations (DAWs).
    • -
    • Synthesizers.
    • -
    • Drum machines.
    • -
    • Music learning apps.
    • -
    • Karaoke apps.
    • -
    • DJ mixing.
    • -
    • Audio effects.
    • -
    • Video/audio conferencing.
    • -
    - -

    Adding OpenSL ES to your App

    - -

    -You can call OpenSL ES from both C and C++ code. To add the core OpenSL ES -feature set to your app, include the {@code OpenSLES.h} header file: - -

    -
    -#include <SLES/OpenSLES.h>
    -
    - -

    -To add the OpenSL ES -Android extensions as well, include the {@code OpenSLES_Android.h} header file: -

    -
    -#include <SLES/OpenSLES_Android.h>
    -
    - -

    -When you include the {@code OpenSLES_Android.h} header file, the following headers are included -automatically: -

    -
    -#include <SLES/OpenSLES_AndroidConfiguration.h>
    -#include <SLES/OpenSLES_AndroidMetadata.h>
    -
    - -

    Note: -These headers are not required, but are shown as an aid in learning the API. -

    - -

    Building and Debugging

    - -

    -You can incorporate OpenSL ES into your build by specifying it in the -{@code Android.mk} file that serves as one of the -NDK build system's makefiles. Add the following line to -{@code Android.mk}: -

    - -
    -LOCAL_LDLIBS += -lOpenSLES
    -
    - -

    -For robust debugging, we recommend that you examine the {@code SLresult} value that most of -the OpenSL ES APIs return. You can use -asserts -or more advanced error-handling logic for debugging; neither offers -an inherent advantage for working with OpenSL ES, although one or the other might be more suitable -for a given use case. -

    - -

    -We use asserts in our -examples, because they help catch unrealistic conditions that would indicate a coding error. We -have used explicit error handling for other conditions more likely to occur in production. -

    - -

    -Many API errors result in a log entry, in addition to a non-zero result code. Such log entries -can provide additional detail that proves especially useful for relatively complex APIs such as - -{@code Engine::CreateAudioPlayer}. -

    - -

    -You can view the log either from the command line or from Android Studio. To examine the log from -the command line, type the following: -

    - -
    -$ adb logcat
    -
    - -

    -To examine the log from Android Studio, either click the Logcat tab in the -Debug -window, or click the Devices | logcat tab in the -Android DDMS -window. -

    -

    Audio Power Consumption

    -

    Constantly outputting audio incurs significant power consumption. Ensure that you stop the - output in the - onPause() method. - Also consider pausing the silent output after some period of user inactivity. -

    -

    Samples

    - -

    -Supported and tested example code that you can use as a model for your own code resides both locally -and on - -GitHub. The local examples are located in -{@code platforms/android-9/samples/native-audio/}, under your NDK root installation directory. -On GitHub, they are available from the -{@code android-ndk} -repository, in the - -{@code audio-echo} and - -{@code native-audio} directories. -

    -

    The Android NDK implementation of OpenSL ES differs -from the reference specification for OpenSL ES 1.0.1 in a number of respects. -These differences are an important reason as to why sample code that -you copy directly from the OpenSL ES reference specification may not work in your -Android app. -

    -

    -For more information on differences between the reference specification and the -Android implementation, see - -OpenSL ES for Android. diff --git a/docs/html/ndk/guides/audio/floating-point.jd b/docs/html/ndk/guides/audio/floating-point.jd deleted file mode 100644 index 76efce3f60e13cc762b8a98dd062d642831427e8..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/floating-point.jd +++ /dev/null @@ -1,101 +0,0 @@ -page.title=Floating-Point Audio -@jd:body - -

    - - -
    -

    Video

    -

    Will it Float? The Glory and Shame of Floating-Point Audio

    -
    -
    - -

    Using floating-point numbers to represent audio data can significantly enhance audio - quality in high-performance audio applications. Floating point offers the following - advantages:

    - -
      -
    • Wider dynamic range.
    • -
    • Consistent accuracy across the dynamic range.
    • -
    • More headroom to avoid clipping during intermediate calculations and transients.
    • -
    - -

    While floating-point can enhance audio quality, it does present certain disadvantages:

    - -
      -
    • Floating-point numbers use more memory.
    • -
    • Floating-point operations employ unexpected properties, for example, addition is - not associative.
    • -
    • Floating-point calculations can sometimes lose arithmetic precision due to rounding or - numerically unstable algorithms.
    • -
    • Using floating-point effectively requires greater understanding to achieve accurate - and reproducible results.
    • -
    - -

    - Formerly, floating-point was notorious for being unavailable or slow. This is - still true for low-end and embedded processors. But processors on modern - mobile devices now have hardware floating-point with performance that is - similar (or in some cases even faster) than integer. Modern CPUs also support - SIMD - (Single instruction, multiple data), which can improve performance further. -

    - -

    Best Practices for Floating-Point Audio

    -

    The following best practices help you avoid problems with floating-point calculations:

    -
      -
    • Use double precision floating-point for infrequent calculations, -such as computing filter coefficients.
    • -
    • Pay attention to the order of operations.
    • -
    • Declare explicit variables for intermediate values.
    • -
    • Use parentheses liberally.
    • -
    • If you get a NaN or infinity result, use binary search to discover -where it was introduced.
    • -
    - -

    Floating-Point Audio in Android SDK

    - -

    For floating-point audio, the audio format encoding - AudioFormat.ENCODING_PCM_FLOAT is used similarly to - ENCODING_PCM_16_BIT or ENCODING_PCM_8_BIT for specifying - AudioTrack data -formats. The corresponding overloaded method AudioTrack.write() - takes in a float array to deliver data.

    - -
    -   public int write(float[] audioData,
    -        int offsetInFloats,
    -        int sizeInFloats,
    -        int writeMode)
    -
    - -

    For More Information

    - -

    The following Wikipedia pages are helpful in understanding floating-point audio:

    - - - -

    The following article provides information on those aspects of floating-point that have a - direct impact on designers of computer systems:

    - diff --git a/docs/html/ndk/guides/audio/index.jd b/docs/html/ndk/guides/audio/index.jd deleted file mode 100644 index 12d9320c7a43fd6671f113ff67617eb93958537e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/index.jd +++ /dev/null @@ -1,27 +0,0 @@ -page.title=NDK High-Performance Audio -@jd:body - -

    The NDK package includes an Android-specific implementation of the -OpenSL ES™ API -specification from the Khronos Group. -This library allows you to use C or C++ to implement high-performance, low-latency audio, whether -you are writing a synthesizer, digital audio workstation, karaoke, game, - or other real-time app.

    - -

    This section begins by providing some -basic information about the API, including -typical use cases and how to incorporate it into your app. It then explains what you need to know -about the Android-specific -implementation of OpenSL ES, focusing on the differences between this implementation and the -reference specification. Next, you'll learn how to minimze - input latency - when using built-in or external microphones -and some actions that you can take to minimize - output latency. - It describes the reasons that you should use - floating-point - numbers to represent your audio data, and it provides information that will help you choose the -optimal sample rate. This section - concludes with some supplemental - programming notes to ensure proper implementation of OpenSL ES. -

    diff --git a/docs/html/ndk/guides/audio/input-latency.jd b/docs/html/ndk/guides/audio/input-latency.jd deleted file mode 100644 index f1103fcf1936b6638776b035855db463233c6806..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/input-latency.jd +++ /dev/null @@ -1,95 +0,0 @@ -page.title=Audio Input Latency -@jd:body - - - - -

    This page provides guidelines to help you reduce audio input latency when recording with a -built-in microphone or an external headset microphone.

    - -

    Checklist

    - -

    Here are a few important prerequisites:

    - -
      -
    • You must use the Android-specific implementation of the - OpenSL ES™ API. - -
    • If you haven't already done so, download and install the - Android NDK.
    • - -
    • Many of the same requirements for low-latency audio output also apply to low-latency input, - so read the requirements for low-latency output in - Audio Output Latency.
    • -
    - -

    Ways to Reduce Audio Input Latency

    - -

    The following are some methods to help ensure low audio input latency: - -

      -
    • Suggest to your users, if your app relies on low-latency audio, that they use a headset -(for example, by displaying a Best with headphones screen on first run). Note -that just using the headset doesn’t guarantee the lowest possible latency. You may need to -perform other steps to remove any unwanted signal processing from the audio path, such as by -using the -VOICE_RECOGNITION preset when recording.
    • - -
    • It's difficult to test audio input and output latency in isolation. The best solution to -determine the lowest possible audio input latency is to measure round-trip audio and divide -by two.
    • -
    • Be prepared to handle nominal sample rates of 44,100 and 48,000 Hz as reported by - -getProperty(String) for - -PROPERTY_OUTPUT_SAMPLE_RATE. Other sample rates are possible, but rare.
    • - -
    • Be prepared to handle the buffer size reported by - -getProperty(String) for - -PROPERTY_OUTPUT_FRAMES_PER_BUFFER. Typical buffer sizes include 96, 128, 160, 192, 240, 256, -or 512 frames, but other values are possible.
    • -
    - -

    What to Avoid

    - -

    Be sure to take these things into account to help avoid latency issues:

    - -
      -
    • Don’t assume that the speakers and microphones used in mobile devices generally have good -acoustics. Due to their small size, the acoustics are generally poor so signal processing is -added to improve the sound quality. This signal processing introduces latency.
    • - -
    • Don't assume that your input and output callbacks are synchronized. For simultaneous input -and output, separate buffer queue completion handlers are used for each side. There is no -guarantee of the relative order of these callbacks or the synchronization of the audio clocks, -even when both sides use the same sample rate. Your application should buffer the data with -proper buffer synchronization.
    • - -
    • Don't assume that the actual sample rate exactly matches the nominal sample rate. For -example, if the nominal sample rate is 48,000 Hz, it is normal for the audio clock to advance -at a slightly different rate than the operating system {@code CLOCK_MONOTONIC}. This is because -the audio and system clocks may derive from different crystals.
    • - -
    • Don't assume that the actual playback sample rate exactly matches the actual capture sample -rate, especially if the endpoints are on separate paths. For example, if you are capturing from -the on-device microphone at 48,000 Hz nominal sample rate, and playing on USB audio -at 48,000 Hz nominal sample rate, the actual sample rates are likely to be slightly different -from each other.
    • -
    - -

    A consequence of potentially independent audio clocks is the need for asynchronous sample rate -conversion. A simple (though not ideal for audio quality) technique for asynchronous sample rate -conversion is to duplicate or drop samples as needed near a zero-crossing point. More -sophisticated conversions are possible.

    diff --git a/docs/html/ndk/guides/audio/opensl-for-android.jd b/docs/html/ndk/guides/audio/opensl-for-android.jd deleted file mode 100644 index fa5e260f18f31c4d3d56f7387c1002e6c1c825b1..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/opensl-for-android.jd +++ /dev/null @@ -1,1211 +0,0 @@ -page.title=OpenSL ES for Android -@jd:body - - - -

    -This page provides details about how the -NDK implementation of OpenSL -ES™ differs from the reference specification for OpenSL ES 1.0.1. When using sample code from the -specification, you may need to modify it to work on Android. -

    - -

    -Unless otherwise noted, all features are available at Android 2.3 (API level 9) and higher. - Some features are only available for Android 4.0 (API level 14); these are noted. -

    - -

    Note: -The Android Compatibility Definition Document (CDD) enumerates the hardware and software -requirements of a compatible Android device. See -Android Compatibility -for more information on the overall compatibility program, and - -CDD for the actual CDD document. -

    - -

    -OpenSL ES provides a C -language interface that is also accessible using C++. It exposes features similar to the audio -portions of these Android Java APIs: -

    - - - -

    -As with all of the Android Native Development Kit (NDK), the primary purpose of OpenSL ES for -Android is to facilitate the implementation of shared libraries to be called using the Java Native -Interface (JNI -). NDK is not intended for writing pure C/C++ applications. However, OpenSL ES is a -full-featured API, and we expect that you should be able to accomplish most of your audio needs -using only this API, without up-calls to code running in the Android runtime. -

    - -

    Note: -Though based on OpenSL ES, the Android native audio (high-performance audio) API is not a -conforming implementation of any OpenSL ES 1.0.1 profile (game, music, or phone). This is because -Android does not implement all of the features required by any one of the profiles. Any known cases -where Android behaves differently than the specification are described in the -Android extensions section below. -

    - -

    Getting Started

    - -

    -This section provides the information needed to get started using the OpenSL ES APIs. -

    - -

    Example code

    - -

    -We recommend using supported and tested example code that is usable as a model for your own -code, which is located in the NDK folder {@code platforms/android-9/samples/native-audio/}, as well -as in the -audio-echo -and -native-audio -folders of the -android-ndk GitHub -repository. -

    - -

    Caution: -The OpenSL ES 1.0.1 specification contains example code in the appendices (see -Khronos OpenSL ES Registry -for more details). However, the examples in Appendix B: Sample Code and -Appendix C: Use Case Sample Code use features that are not supported by Android. Some -examples also contain typographical errors, or use APIs that are likely to change. Proceed with -caution when referring to these; though the code may be helpful in understanding the full OpenSL ES -standard, it should not be used as-is with Android. -

    - -

    Makefile

    - -

    -Modify your {@code Android.mk} file as follows: -

    -
    -LOCAL_LDLIBS += -lOpenSLES
    -
    - -

    Audio content

    - -

    -The following are some of the many ways to package audio content for your application: -

    - -
      -
    • Resources: By placing your audio files into the {@code res/raw/} folder, - they can be accessed easily by the associated APIs for - Resources. - However, there is no direct native access to resources, so you must write Java - programming language code to copy them out before use.
    • -
    • Assets: By placing your audio files into the {@code assets/} folder, they - are directly accessible by the Android native asset manager APIs. See the header files {@code - android/asset_manager.h} and {@code android/asset_manager_jni.h} for more information on these - APIs. The example code located in the NDK folder {@code platforms/android-9/samples/native-audio/} - uses these native asset manager APIs in conjunction with the Android file descriptor data - locator.
    • -
    • Network: You can use the URI data locator to play audio content directly - from the network. However, be sure to read the Security and permissions - section below.
    • -
    • Local file system: The URI data locator supports the {@code file:} scheme - for local files, provided the files are accessible by the application. Note that the Android - security framework restricts file access via the Linux user ID and group ID mechanisms.
    • -
    • Recorded: Your application can record audio data from the microphone input, - store this content, and then play it back later. The example code uses this method for the - Playback clip.
    • -
    • Compiled and linked inline: You can link your audio content directly into - the shared library, and then play it using an audio player with buffer queue data locator. This - is most suitable for short PCM format clips. The example code uses this technique for the - Hello and Android clips. The PCM data was converted to hex strings using a - {@code bin2c} tool (not supplied).
    • -
    • Real-time synthesis: Your application can synthesize PCM data on the fly and - then play it using an audio player with buffer queue data locator. This is a relatively advanced - technique, and the details of audio synthesis are beyond the scope of this article.
    • -
    - -

    Note: -Finding or creating useful audio content for your application is beyond the scope of this article. -You can use web search terms such as interactive audio, game audio, sound -design, and audio programming to locate more information. -

    -

    Caution: It is your responsibility -to ensure that you are legally permitted to play or record content. There may be privacy -considerations for recording content. -

    - -

    Features Inherited from the Reference Specification

    - -

    -The Android NDK implementation of OpenSL ES inherits much of the feature set from -the reference specification, with certain limitations. -

    - -

    Global entry points

    - -

    -OpenSL ES for Android supports all of the global entry points in the Android specification. -These entry points include: -

    - -
      -
    • {@code slCreateEngine} -
    • -
    • {@code slQueryNumSupportedEngineInterfaces} -
    • -
    • {@code slQuerySupportedEngineInterfaces} -
    • -
    - -

    Objects and interfaces

    - -

    -Table 1 shows the objects and interfaces that the Android NDK implementation of -OpenSL ES supports. If a Yes appears in the cell, then the feature is available in this -implementation. -

    - -

    - Table 1. Android NDK support for objects and interfaces.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FeatureAudio playerAudio recorderEngineOutput mix
    Bass boostYesNoNoYes
    Buffer queueYesNoNoNo
    Dynamic interface managementYesYesYesYes
    Effect sendYesNoNoNo
    EngineNoNoYesNo
    Environmental reverbNoNoNoYes
    EqualizerYesNoNoYes
    Metadata extractionYes: Decode to PCMNoNoNo
    Mute soloYesNoNoNo
    ObjectYesYesYesYes
    PlayYesNoNoNo
    Playback rateYesNoNoNo
    Prefetch statusYesNoNoNo
    Preset reverbNoNoNoYes
    RecordNoYesNoNo
    SeekYesNoNoNo
    VirtualizerYesNoNoYes
    VolumeYesNoNoNo
    Buffer queue data locatorYes: SourceNoNoNo
    I/O device data locatorNoYes: SourceNoNo
    Output mix locatorYes: SinkNoNoNo
    URI data locatorYes: SourceNoNoNo
    - -

    -The next section explains the limitations for some of these features. -

    - -

    Limitations

    - -

    -Certain limitations apply to the features in Table 1. These limitations -represent differences from the reference specification. The rest of this section provides -information about these differences.

    - -

    Dynamic interface management

    - -

    -OpenSL ES for Android does not support {@code RemoveInterface} or -{@code ResumeInterface}. -

    - -

    Effect combinations: environment reverb and preset reverb

    - -

    -You cannot have both environmental reverb and preset reverb on the same output mix. -

    -

    -The platform might ignore effect requests if it estimates that the -CPU load would be too high. -

    - -

    Effect send

    - -

    -SetSendLevel() supports a single send level per audio player. -

    - -

    Environmental reverb

    - -

    -Environmental reverb does not support the reflectionsDelay, -reflectionsLevel, or reverbDelay fields of -the SLEnvironmentalReverbSettings struct. -

    - -

    MIME data format

    - -

    -You can use the MIME data format only with the URI data locator, and only for an audio -player. You cannot use this data format for an audio recorder. -

    -

    -The Android implementation of OpenSL ES requires you to initialize mimeType -to either NULL or a valid UTF-8 string. You must also initialize -containerType to a valid value. -In the absence of other considerations, such as portability to other -implementations or content format that an app cannot identify by header, -we recommend that you -set mimeType to NULL and containerType -to SL_CONTAINERTYPE_UNSPECIFIED. -

    -

    -OpenSL ES for Android supports the following audio formats, so long as the -Android platform supports them as well:

    - -
      -
    • WAV PCM.
    • -
    • WAV alaw.
    • -
    • WAV ulaw.
    • -
    • MP3 Ogg Vorbis.
    • -
    • AAC LC.
    • -
    • HE-AACv1 (AAC+).
    • -
    • HE-AACv2 (enhanced AAC+).
    • -
    • AMR.
    • -
    • FLAC.
    • -
    - -

    Note: -For a list of audio formats that Android supports, see -Supported Media Formats. -

    - -

    -The following limitations apply to the handling of these and other formats in this -implementation of OpenSL ES: -

    - -
      -
    • AAC -formats must reside within an MP4 or ADTS container.
    • -
    • OpenSL ES for Android does not support -MIDI.
    • -
    • WMA is not part of AOSP, and we -have not verified its compatibility with OpenSL ES for Android.
    • -
    • The Android NDK implementation of OpenSL ES does not support direct -playback of DRM or encrypted content. To play back protected audio content, you must -decrypt it in your application before playing, with your app enforcing any DRM -restrictions.
    • -
    - -

    Object-related methods

    - -

    -OpenSL ES for Android does not support the following methods for manipulating objects: -

    - -
      -
    • {@code Resume()}
    • -
    • {@code RegisterCallback()}
    • -
    • {@code AbortAsyncOperation()}
    • -
    • {@code SetPriority()}
    • -
    • {@code GetPriority()}
    • -
    • {@code SetLossOfControlInterfaces()}
    • -
    - -

    PCM data format

    - -

    -PCM is the only data format you can use with buffer queues. Supported PCM -playback configurations have the following characteristics: -

    - -
      -
    • 8-bit unsigned or 16-bit signed.
    • -
    • Mono or stereo.
    • -
    • Little-endian byte ordering.
    • -
    • Sample rates of: -
        -
      • 8,000 Hz.
      • -
      • 11,025 Hz.
      • -
      • 12,000 Hz.
      • -
      • 16,000 Hz.
      • -
      • 22,050 Hz.
      • -
      • 24,000 Hz.
      • -
      • 32,000 Hz.
      • -
      • 44,100 Hz.
      • -
      • 48,000 Hz.
      • -
    • -
    - -

    -The configurations that OpenSL ES for Android supports for recording are -device-dependent; usually, 16,000 Hz mono/16-bit signed is available regardless of the device. -

    -

    -The value of the samplesPerSec field is in units of milliHz, despite the misleading -name. To avoid accidentally using the wrong value, we recommend that you initialize this field using -one of the symbolic constants defined for this purpose, such as {@code SL_SAMPLINGRATE_44_1}. -

    -

    -Android 5.0 (API level 21) and above support floating-point data. -

    - -

    Playback rate

    - -

    -An OpenSL ES playback rate indicates the speed at which an -object presents data, expressed in thousandths of normal speed, or per mille. For example, -a playback rate of 1,000 per mille is 1,000/1,000, or normal speed. -A rate range is a closed interval that expresses possible rate ranges. -

    - -

    -Support for playback-rate ranges and other capabilities may vary depending -on the platform version and implementation. Your app can determine these capabilities at runtime by -using PlaybackRate::GetRateRange() or -PlaybackRate::GetCapabilitiesOfRate() to query the device. -

    - -

    -A device typically supports the same rate range for a data source in PCM format, and a unity rate -range of 1000 per mille to 1000 per mille for other formats: that is, the unity rate range is -effectively a single value. -

    - -

    Record

    - -

    -OpenSL ES for Android does not support the SL_RECORDEVENT_HEADATLIMIT -or SL_RECORDEVENT_HEADMOVING events. -

    - -

    Seek

    - -

    -The SetLoop() method enables whole-file looping. To enable looping, -set the startPos parameter to 0, and the value of the endPos parameter -to SL_TIME_UNKNOWN. -

    - -

    Buffer queue data locator

    - -

    -An audio player or recorder with a data locator for a buffer queue supports PCM data format only. -

    - -

    I/O device data locator

    - -

    -OpenSL ES for Android only supports use of an I/O device data locator when you have -specified the locator as the data source for Engine::CreateAudioRecorder(). -Initialize the device data locator using the values contained in the following code snippet. -

    - -
    -SLDataLocator_IODevice loc_dev =
    -  {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
    -  SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
    -
    - -

    URI data locator

    - -

    -OpenSL ES for Android can only use the URI data locator with MIME data format, -and only for an audio player. You cannot use this data format for an audio recorder. It supports -{@code http:} and {@code file:} schemes. It does not support other schemes, such as {@code https:}, -{@code ftp:}, or -{@code content:}. -

    - -

    -We have not verified support for {@code rtsp:} with audio on the Android platform. -

    - -

    Data structures

    - -

    -Android supports these OpenSL ES 1.0.1 data structures: -

    -
      -
    • {@code SLDataFormat_MIME}
    • -
    • {@code SLDataFormat_PCM}
    • -
    • {@code SLDataLocator_BufferQueue}
    • -
    • {@code SLDataLocator_IODevice}
    • -
    • {@code SLDataLocator_OutputMix}
    • -
    • {@code SLDataLocator_URI}
    • -
    • {@code SLDataSink}
    • -
    • {@code SLDataSource}
    • -
    • {@code SLEngineOption}
    • -
    • {@code SLEnvironmentalReverbSettings}
    • -
    • {@code SLInterfaceID}
    • -
    - -

    Platform configuration

    - -

    -OpenSL ES for Android is designed for multi-threaded applications and is thread-safe. It supports a -single engine per application, and up to 32 objects per engine. Available device memory and CPU may -further restrict the usable number of objects. -

    - -

    -These engine options are recognized, but ignored by {@code slCreateEngine}: -

    - -
      -
    • {@code SL_ENGINEOPTION_THREADSAFE}
    • -
    • {@code SL_ENGINEOPTION_LOSSOFCONTROL}
    • -
    - -

    -OpenMAX AL and OpenSL ES may be used together in the same application. In this case, there is -a single shared engine object internally, and the 32 object limit is shared between OpenMAX AL -and OpenSL ES. The application should first create both engines, use both engines, and finally -destroy both engines. The implementation maintains a reference count on the shared engine so that -it is correctly destroyed during the second destroy operation. -

    - -

    Planning for Future Versions of OpenSL ES

    - -

    -The Android high-performance audio APIs are based on -Khronos Group OpenSL ES -1.0.1. Khronos has released a revised version 1.1 of the standard. The -revised version includes new features, clarifications, corrections of typographical errors, and -some incompatibilities. Most of the expected incompatibilities are relatively minor or are in -areas of OpenSL ES that are not supported by Android. -

    - -

    -An application -developed with this version should work on future versions of the Android platform, provided -that you follow the guidelines that are outlined in the Planning for -binary compatibility section below. -

    - -

    Note: -Future source compatibility is not a goal. That is, if you upgrade to a newer version of the NDK, -you may need to modify your application source code to conform to the new API. We expect that most -such changes will be minor; see details below. -

    - -

    Planning for binary compatibility

    - -

    -We recommend that your application follow these guidelines to improve future binary compatibility: -

    - -
      -
    • Use only the documented subset of Android-supported features from OpenSL ES 1.0.1.
    • -
    • Do not depend on a particular result code for an unsuccessful operation; be prepared to deal - with a different result code.
    • -
    • Application callback handlers generally run in a restricted context. They should be written - to perform their work quickly, and then return as soon as possible. Do not run complex operations - within a callback handler. For example, within a buffer queue completion callback, you can - enqueue another buffer, but do not create an audio player.
    • -
    • Callback handlers should be prepared to be called more or less frequently, to receive - additional event types, and should ignore event types that they do not recognize. Callbacks that - are configured with an event mask made of enabled event types should be prepared to be called - with multiple event type bits set simultaneously. Use "&" to test for each event bit rather than - a switch case.
    • -
    • Use prefetch status and callbacks as a general indication of progress, but do not depend on - specific hard-coded fill levels or callback sequences. The meaning of the prefetch status fill - level, and the behavior for errors that are detected during prefetch, may change.
    • -
    - -

    Note: -See the Buffer queue behavior section below for more details. -

    - -

    Planning for source compatibility

    - -

    -As mentioned, source code incompatibilities are expected in the next version of OpenSL ES from -Khronos Group. The likely areas of change include: -

    - -
      -
    • The buffer queue interface is expected to have significant changes, especially in the areas - of {@code BufferQueue::Enqueue}, the parameter list for {@code slBufferQueueCallback}, and the - name of field {@code SLBufferQueueState.playIndex}. We recommend that your application code use - Android simple buffer queues instead. In the example - code that is supplied with the NDK, we have used Android simple buffer queues for playback for - this reason. (We also use Android simple buffer queue for recording and decoding to PCM, but that - is because standard OpenSL ES 1.0.1 does not support record or decode to a buffer queue data - sink.)
    • -
    • There will be an addition of {@code const} to the input parameters passed by reference, and - to {@code SLchar *} struct fields used as input values. This should not require any changes to - your code.
    • -
    • There will be a substitution of unsigned types for some parameters that are currently signed. - You may need to change a parameter type from {@code SLint32} to {@code SLuint32} or similar, or - add a cast.
    • -
    • {@code Equalizer::GetPresetName} copies the string to application memory instead of returning - a pointer to implementation memory. This will be a significant change, so we recommend that you - either avoid calling this method, or isolate your use of it.
    • -
    • There will be additional fields in the struct types. For output parameters, these new fields - can be ignored, but for input parameters the new fields will need to be initialized. Fortunately, - all of these are expected to be in areas that are not supported by Android.
    • -
    • Interface - GUIDs will change. Refer to interfaces by symbolic name rather than GUID to avoid a - dependency.
    • -
    • {@code SLchar} will change from {@code unsigned char} to {@code char}. This primarily affects - the URI data locator and MIME data format.
    • -
    • {@code SLDataFormat_MIME.mimeType} will be renamed to {@code pMimeType}, and - {@code SLDataLocator_URI.URI} will be renamed to {@code pURI}. We recommend that you initialize - the {@code SLDataFormat_MIME} and {@code SLDataLocator_URI} data structures using a - brace-enclosed, comma-separated list of values, rather than by field name, to isolate your code - from this change. This technique is used in the example code.
    • -
    • {@code SL_DATAFORMAT_PCM} does not permit the application to specify the representation of - the data as signed integer, unsigned integer, or floating-point. The Android implementation - assumes that 8-bit data is unsigned integer and 16-bit is signed integer. In addition, the field - {@code samplesPerSec} is a misnomer, as the actual units are milliHz. These issues are expected - to be addressed in the next OpenSL ES version, which will introduce a new extended PCM data - format that permits the application to explicitly specify the representation and corrects the - field name. As this will be a new data format, and the current PCM data format will still be - available (though deprecated), it should not require any immediate changes to your code.
    • -
    - -

    Android Extensions

    - -

    -OpenSL ES for Android extends the reference OpenSL ES specification to make it compatible with -Android, and to take advantage of the power and flexibility of the Android platform. -

    - -

    -The definition of the API for the Android extensions resides in OpenSLES_Android.h -and the header files that it includes. Consult {@code OpenSLES_Android.h} -for details about these extensions. This file is located under your installation root, in the -{@code platforms/android-<version>/<abi>/include/SLES} directory. Unless otherwise -noted, all interfaces are explicit. -

    - -

    -These extensions limit your application's portability to -other OpenSL ES implementations, because they are Android-specific. You can mitigate this issue by -avoiding use of the extensions or by using {@code #ifdef} to exclude them at compile time. -

    - -

    -Table 2 shows the Android-specific interfaces and data locators that Android OpenSL ES supports -for each object type. The Yes values in the cells indicate the interfaces and data -locators that are available for each object type. -

    - -

    - Table 2. Interfaces and data locators, by object type.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FeatureAudio playerAudio recorderEngineOutput mix
    Android buffer queueYes: Source (decode)NoNoNo
    Android configurationYesYesNoNo
    Android effectYesNoNoYes
    Android effect capabilitiesNoNoYesNo
    Android effect sendYesNoNoNo
    Android simple buffer queueYes: Source (playback) or sink (decode)YesNoNo
    Android buffer queue data locatorYes: Source (decode)NoNoNo
    Android file descriptor data locatorYes: SourceNoNoNo
    Android simple buffer queue data locatorYes: Source (playback) or sink (decode)Yes: SinkNoNo
    - -

    Android configuration interface

    - -

    -The Android configuration interface provides a means to set -platform-specific parameters for objects. This interface is different from other OpenSL ES -1.0.1 interfaces in that your app can use it before instantiating the corresponding object; thus, -you can configure the object before instantiating it. The -{@code OpenSLES_AndroidConfiguration.h} header file, which resides at -{@code platforms/android-<version>/<abi>/include/SLES}, -documents the following available configuration keys and values: -

    - -
      -
    • Stream type for audio players (default SL_ANDROID_STREAM_MEDIA).
    • -
    • Record profile for audio recorders (default SL_ANDROID_RECORDING_PRESET_GENERIC). -
    • -
    - -

    -The following code snippet shows an example of how to set the Android audio stream type on an audio -player: -

    - -
    -// CreateAudioPlayer and specify SL_IID_ANDROIDCONFIGURATION
    -// in the required interface ID array. Do not realize player yet.
    -// ...
    -SLAndroidConfigurationItf playerConfig;
    -result = (*playerObject)->GetInterface(playerObject,
    -    SL_IID_ANDROIDCONFIGURATION, &playerConfig);
    -assert(SL_RESULT_SUCCESS == result);
    -SLint32 streamType = SL_ANDROID_STREAM_ALARM;
    -result = (*playerConfig)->SetConfiguration(playerConfig,
    -    SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
    -assert(SL_RESULT_SUCCESS == result);
    -// ...
    -// Now realize the player here.
    -
    - -

    -You can use similar code to configure the preset for an audio recorder: -

    -
    -// ... obtain the configuration interface as the first four lines above, then:
    -SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
    -result = (*playerConfig)->SetConfiguration(playerConfig,
    -    RECORDING_PRESET, &presetValue, sizeof(SLuint32));
    -
    - -

    Android effects interfaces

    - -

    -Android's effect, effect send, and effect capabilities interfaces provide -a generic mechanism for an application to query and use device-specific -audio effects. Device manufacturers should document any available device-specific audio effects -that they provide. -

    - -

    -Portable applications should use the OpenSL ES 1.0.1 APIs for audio effects instead of the Android -effect extensions. -

    - -

    Android file descriptor data locator

    - -

    -The Android file descriptor data locator permits you to specify the source for an -audio player as an open file descriptor with read access. The data format must be MIME. -

    -

    -This extension is especially useful in conjunction with the native asset manager, because -the app reads assets from the APK via a file descriptor. -

    - -

    Android simple buffer queue data locator and interface

    - -

    -The Android simple buffer queue data locator and interface are -identical to those in the OpenSL ES 1.0.1 reference specification, with two exceptions: You -can also use Android simple buffer queues with both audio players and audio recorders. Also, PCM -is the only data format you can use with these queues. -In the reference specification, buffer queues are for audio players only, but they are -compatible with data formats beyond PCM. -

    -

    -For recording, your app should enqueue empty buffers. When a registered callback sends -notification that the system has finished writing data to the buffer, the app can -read the buffer. -

    -

    -Playback works in the same way. For future source code -compatibility, however, we suggest that applications use Android simple -buffer queues instead of OpenSL ES 1.0.1 buffer queues. -

    - -

    Dynamic interfaces at object creation

    - -

    -For convenience, the Android implementation of OpenSL ES 1.0.1 -permits your app to specify dynamic interfaces when it instantiates an object. -This is an alternative to using DynamicInterfaceManagement::AddInterface() -to add these interfaces after instantiation. -

    - -

    Buffer queue behavior

    - -

    -The Android implementation does not include the -reference specification's requirement that the play cursor return to the beginning -of the currently playing buffer when playback enters the {@code SL_PLAYSTATE_STOPPED} -state. This implementation can conform to that behavior, or it can leave the location of the play -cursor unchanged. -

    - -

    -As a result, your app cannot assume that either behavior occurs. Therefore, -you should explicitly call the BufferQueue::Clear() method after a transition to -SL_PLAYSTATE_STOPPED. Doing so sets the buffer queue to a known state. -

    - -

    -Similarly, there is no specification governing whether the trigger for a buffer queue callback must -be a transition to SL_PLAYSTATE_STOPPED or execution of -BufferQueue::Clear(). Therefore, we recommend that you do not create a dependency on -one or the other; instead, your app should be able to handle both. -

    - -

    Reporting of extensions

    -

    -There are three methods for querying whether the platform supports the Android extensions. These -methods are: -

    - -
      -
    • Engine::QueryNumSupportedExtensions()
    • -
    • Engine::QuerySupportedExtension()
    • -
    • Engine::IsExtensionSupported()
    • -
    - -

    -Any of these methods returns ANDROID_SDK_LEVEL_<API-level>, -where {@code API-level} is the platform API level; for example, {@code ANDROID_SDK_LEVEL_23}. -A platform API level of 9 or higher means that the platform supports the extensions. -

    - - -

    Decode audio to PCM

    - -

    -This section describes a deprecated Android-specific extension to OpenSL ES 1.0.1 -for decoding an encoded stream to PCM without immediate playback. -The table below gives recommendations for use of this extension and alternatives. -

    - - - - - - - - - - - - - - - - - - - - - - -
    API levelAlternatives
    13 and belowAn open-source codec with a suitable license
    14 to 15An open-source codec with a suitable license
    16 to 20 - The {@link android.media.MediaCodec} class or an open-source codec with a suitable license -
    21 and above - NDK MediaCodec in the {@code <media/NdkMedia*.h>} header files, the - {@link android.media.MediaCodec} class, or an open-source codec with a suitable license -
    - -

    Note: -There is currently no documentation for the NDK version of the {@code MediaCodec} API. However, -you can refer to the - -native-codec sample code for an example. -

    - -

    -A standard audio player plays back to an audio device, specifying the output mix as the data sink. -The Android extension differs in that an audio player instead -acts as a decoder if the app has specified the data source either as a URI or as an Android -file descriptor data locator described in MIME data format. In such a case, the data sink is -an Android simple buffer queue data locator with PCM data format. -

    - -

    -This feature is primarily intended for games to pre-load their audio assets when changing to a -new game level, which is similar to the functionality that the {@link android.media.SoundPool} -class provides. -

    - -

    -The application should initially enqueue a set of empty buffers in the Android simple -buffer queue. After that, the app fills the buffers with PCM data. The Android simple -buffer queue callback fires after each buffer is filled. The callback handler processes -the PCM data, re-enqueues the now-empty buffer, and then returns. The application is responsible for -keeping track of decoded buffers; the callback parameter list does not include -sufficient information to indicate the buffer that contains data or the buffer that should be -enqueued next. -

    - -

    -The data source implicitly reports the end of stream (EOS) by delivering a -SL_PLAYEVENT_HEADATEND event at the end of the stream. After the app has decoded -all of the data it received, it makes no further calls to the Android simple buffer queue callback. -

    -

    -The sink's PCM data format typically matches that of the encoded data source -with respect to sample rate, channel count, and bit depth. However, you can decode to a different -sample rate, channel count, or bit depth. -For information about a provision to detect the actual PCM format, see -Determining the format of decoded PCM data via metadata. -

    -

    -OpenSL ES for Android's PCM decoding feature supports pause and initial seek; it does not support -volume control, effects, looping, or playback rate. -

    -

    -Depending on the platform implementation, decoding may require resources -that cannot be left idle. Therefore, we recommend that you make sure to provide -sufficient numbers of empty PCM buffers; otherwise, the decoder starves. This may happen, -for example, if your app returns from the Android simple buffer queue callback without -enqueueing another empty buffer. The result of decoder starvation is -unspecified, but may include: dropping the decoded -PCM data, pausing the decoding process, or terminating the decoder outright. -

    - -

    Note: -To decode an encoded stream to PCM but not play back immediately, for apps running on -Android 4.x (API levels 16–20), we recommend using the {@link android.media.MediaCodec} class. -For new applications running on Android 5.0 (API level 21) or higher, we recommend using the NDK -equivalent, {@code <NdkMedia*.h>}. These header files reside in -the {@code media/} directory under your installation root. -

    - -

    Decode streaming ADTS AAC to PCM

    - -

    -An audio player acts as a streaming decoder if the data source is an -Android buffer queue data locator with MIME data format, and the data -sink is an Android simple buffer queue data locator with PCM data format. -Configure the MIME data format as follows: -

    - -
      -
    • Container: {@code SL_CONTAINERTYPE_RAW}
    • -
    • MIME type string: {@code SL_ANDROID_MIME_AACADTS}
    • -
    - -

    -This feature is primarily intended for streaming media applications that -deal with AAC audio but need to perform custom audio processing -prior to playback. Most applications that need to decode audio to PCM -should use the method that Decode audio to PCM describes, -as that method is simpler and handles more audio formats. The technique described -here is a more specialized approach, to be used only if both of these -conditions apply: -

    - -
      -
    • The compressed audio source is a stream of AAC frames contained in ADTS headers. -
    • -
    • The application manages this stream. The data is not located within -a network resource whose identifier is a URI or within a local file whose identifier is -a file descriptor. -
    • -
    - -

    -The application should initially enqueue a set of filled buffers in the Android buffer queue. -Each buffer contains one or more complete ADTS AAC frames. -The Android buffer queue callback fires after each buffer is emptied. -The callback handler should refill and re-enqueue the buffer, and then return. -The application need not keep track of encoded buffers; the callback parameter -list includes sufficient information to indicate the buffer that should be enqueued next. -The end of stream is explicitly marked by enqueuing an EOS item. -After EOS, no more enqueues are permitted. -

    - -

    -We recommend that you make sure to provide full -ADTS AAC buffers, to avoid starving the decoder. This may happen, for example, if your app -returns from the Android buffer queue callback without enqueueing another full buffer. -The result of decoder starvation is unspecified. -

    - -

    -In all respects except for the data source, the streaming decode method is the same as -the one that Decode audio to PCM describes. -

    - -

    -Despite the similarity in names, an Android buffer queue is not -the same as an Android simple buffer queue. The streaming decoder -uses both kinds of buffer queues: an Android buffer queue for the ADTS -AAC data source, and an Android simple buffer queue for the PCM data -sink. For more information about the Android simple buffer queue API, see Android -simple buffer queue data locator and interface. -For more information about the Android buffer queue API, see the {@code index.html} file in -the {@code docs/Additional_library_docs/openmaxal/} directory under the installation root. -

    - -

    Determining the format of decoded PCM data via metadata

    - -

    -The SLMetadataExtractionItf interface is part of the reference specification. -However, the metadata keys that indicate the actual format of decoded PCM data are specific to -Android. The OpenSLES_AndroidMetadata.h header file defines these metadata keys. -This header file resides under your installation root, in the -{@code platforms/android-<version>/<abi>/include/SLES} directory. -

    - -

    -The metadata key indices are available immediately after -the Object::Realize() method finishes executing. However, the associated values are not -available until after the app decodes the first encoded data. A good -practice is to query for the key indices in the main thread after calling the {@code -Object::Realize} method, and to read the PCM format metadata values in the Android simple -buffer queue callback handler when calling it for the first time. Consult the -example code in the -NDK package for examples of working with this interface. -

    - -

    -Metadata key names are stable, but the key indices are not documented, -and are subject to change. An application should not assume that indices -are persistent across different execution runs, and should not assume that -multiple object instances share indices within the same run. -

    - -

    Floating-point data

    - -

    -An app running on Android 5.0 (API level 21) and higher can supply data to an AudioPlayer in -single-precision, floating-point format. -

    -

    -In following example code, the {@code Engine::CreateAudioPlayer} method creates an audio player -that uses floating-point data: -

    - -
    -#include <SLES/OpenSLES_Android.h>
    -...
    -SLAndroidDataFormat_PCM_EX pcm;
    -pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
    -pcm.numChannels = 2;
    -pcm.sampleRate = SL_SAMPLINGRATE_44_1;
    -pcm.bitsPerSample = 32;
    -pcm.containerSize = 32;
    -pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    -pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
    -pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
    -...
    -SLDataSource audiosrc;
    -audiosrc.pLocator = ...
    -audiosrc.pFormat = &pcm;
    -
    - -

    Programming Notes

    -

    OpenSL ES Programming Notes - provides supplemental information to ensure proper implementation of OpenSL ES.

    -

    Note: -For your convenience, we have included a copy of the OpenSL ES 1.0.1 specification with the NDK in -{@code docs/opensles/OpenSL_ES_Specification_1.0.1.pdf}. -

    - -

    Platform Issues

    - -

    -This section describes known issues in the initial platform release that supports these APIs. -

    - -

    Dynamic interface management

    - -

    -{@code DynamicInterfaceManagement::AddInterface} does not work. Instead, specify the interface in -the array that is passed to Create, as shown in the example code for environmental reverb. -

    - diff --git a/docs/html/ndk/guides/audio/opensl-prog-notes.jd b/docs/html/ndk/guides/audio/opensl-prog-notes.jd deleted file mode 100644 index e70aa080e0efa8ead54aadf3459800978dcb5c5f..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/opensl-prog-notes.jd +++ /dev/null @@ -1,461 +0,0 @@ -page.title=OpenSL ES Programming Notes -@jd:body - - - -

    -The notes in this section supplement the -OpenSL ES 1.0.1 -specification. -

    - -

    Objects and Interface Initialization

    - -

    -Two aspects of the OpenSL ES programming model that may be unfamiliar to new developers are the -distinction between objects and interfaces, and the initialization sequence. -

    - -

    -Briefly, an OpenSL ES object is similar to the object concept in - programming languages such as Java -and C++, except an OpenSL ES object is only visible via its associated interfaces. - This includes -the initial interface for all objects, called {@code SLObjectItf}. - There is no handle for an object -itself, only a handle to the {@code SLObjectItf} interface of the object. -

    - -

    -An OpenSL ES object is first created, which returns an {@code SLObjectItf}, then -realized. This is similar to the common programming pattern of first constructing an -object (which should never fail other than for lack of memory or invalid parameters), and then -completing initialization (which may fail due to lack of resources). The realize step gives the -implementation a logical place to allocate additional resources if needed. -

    - -

    -As part of the API to create an object, an application specifies an array of desired interfaces -that it plans to acquire later. Note that this array does not automatically - acquire the interfaces; -it merely indicates a future intention to acquire them. Interfaces are distinguished as -implicit or explicit. An explicit interface must be listed in the array if it -will be acquired later. An implicit interface need not be listed in the - object create array, but -there is no harm in listing it there. OpenSL ES has one more kind of interface called -dynamic, which does not need to be specified in the object - create array and can be added -later after the object is created. The Android implementation provides - a convenience feature to -avoid this complexity, which is described in - Dynamic interfaces at object creation. -

    - -

    -After the object is created and realized, the application should acquire interfaces for each -feature it needs, using {@code GetInterface} on the initial {@code SLObjectItf}. -

    - -

    -Finally, the object is available for use via its interfaces, though note that - some objects require -further setup. In particular, an audio player with URI data source needs a bit - more preparation in -order to detect connection errors. See the - Audio player prefetch section for details. -

    - -

    -After your application is done with the object, you should explicitly destroy it; see the -Destroy section below. -

    - -

    Audio Player Prefetch

    - -

    -For an audio player with URI data source, {@code Object::Realize} allocates - resources but does not -connect to the data source (prepare) or begin pre-fetching data. These occur once the -player state is set to either {@code SL_PLAYSTATE_PAUSED} or {@code SL_PLAYSTATE_PLAYING}. -

    - -

    -Some information may still be unknown until relatively late in this sequence. In -particular, initially {@code Player::GetDuration} returns {@code SL_TIME_UNKNOWN} and -{@code MuteSolo::GetChannelCount} either returns successfully with channel count zero or the -error result {@code SL_RESULT_PRECONDITIONS_VIOLATED}. These APIs return the proper values -once they are known. -

    - -

    -Other properties that are initially unknown include the sample rate and - actual media content type -based on examining the content's header (as opposed to the - application-specified MIME type and -container type). These are also determined later during - prepare/prefetch, but there are no APIs to -retrieve them. -

    - -

    -The prefetch status interface is useful for detecting when all information - is available, or your -application can poll periodically. Note that some information, such as the - duration of a streaming -MP3, may never be known. -

    - -

    -The prefetch status interface is also useful for detecting errors. Register a callback - and enable -at least the {@code SL_PREFETCHEVENT_FILLLEVELCHANGE} and {@code SL_PREFETCHEVENT_STATUSCHANGE} -events. If both of these events are delivered simultaneously, and -{@code PrefetchStatus::GetFillLevel} reports a zero level, and -{@code PrefetchStatus::GetPrefetchStatus} reports {@code SL_PREFETCHSTATUS_UNDERFLOW}, - then this -indicates a non-recoverable error in the data source. This includes the inability to - connect to the -data source because the local filename does not exist or the network URI is invalid. -

    - -

    -The next version of OpenSL ES is expected to add more explicit support for - handling errors in the -data source. However, for future binary compatibility, we intend to continue - to support the current -method for reporting a non-recoverable error. -

    - -

    -In summary, a recommended code sequence is: -

    - -
      -
    1. {@code Engine::CreateAudioPlayer}
    2. -
    3. {@code Object:Realize}
    4. -
    5. {@code Object::GetInterface} for {@code SL_IID_PREFETCHSTATUS}
    6. -
    7. {@code PrefetchStatus::SetCallbackEventsMask}
    8. -
    9. {@code PrefetchStatus::SetFillUpdatePeriod}
    10. -
    11. {@code PrefetchStatus::RegisterCallback}
    12. -
    13. {@code Object::GetInterface} for {@code SL_IID_PLAY}
    14. -
    15. {@code Play::SetPlayState} to {@code SL_PLAYSTATE_PAUSED}, or - {@code SL_PLAYSTATE_PLAYING}
    16. -
    - -

    Note: -Preparation and prefetching occur here; during this time your callback is called with -periodic status updates. -

    - -

    Destroy

    - -

    -Be sure to destroy all objects when exiting from your application. - Objects should be destroyed in -reverse order of their creation, as it is not safe to destroy an object that has any dependent -objects. For example, destroy in this order: audio players and recorders, output mix, and then -finally the engine. -

    - -

    -OpenSL ES does not support automatic garbage collection or -reference -counting of interfaces. After you call {@code Object::Destroy}, all extant - interfaces that are -derived from the associated object become undefined. -

    - -

    -The Android OpenSL ES implementation does not detect the incorrect use of such interfaces. -Continuing to use such interfaces after the object is destroyed can cause your application to -crash or behave in unpredictable ways. -

    - -

    -We recommend that you explicitly set both the primary object interface and all associated -interfaces to NULL as part of your object destruction sequence, which prevents the accidental -misuse of a stale interface handle. -

    - -

    Stereo Panning

    - -

    -When {@code Volume::EnableStereoPosition} is used to enable stereo panning of a mono source, - there is a 3-dB reduction in total -sound power -level. This is needed to permit the total sound power level to remain constant as - the source is -panned from one channel to the other. Therefore, only enable stereo positioning if you need -it. See the Wikipedia article on -audio panning - for more information. -

    - -

    Callbacks and Threads

    - -

    -Callback handlers are generally called synchronously with respect to the event. That is, at the -moment and location that the event is detected by the implementation. This point is -asynchronous with respect to the application, so you should use a non-blocking synchronization -mechanism to control access to any variables shared between the application and the callback -handler. In the example code, such as for buffer queues, we have either omitted this -synchronization or used blocking synchronization in the interest of simplicity. However, proper -non-blocking synchronization is critical for any production code. -

    - -

    -Callback handlers are called from internal non-application threads that are not attached to the -Android runtime, so they are ineligible to use JNI. Because these internal threads are -critical to -the integrity of the OpenSL ES implementation, a callback handler should also not block - or perform -excessive work. -

    - -

    -If your callback handler needs to use JNI or execute work that is not proportional to the -callback, the handler should instead post an event for another thread to process. Examples of -acceptable callback workload include rendering and enqueuing the next output buffer -(for an AudioPlayer), processing the just-filled input buffer and enqueueing the next - empty buffer -(for an AudioRecorder), or simple APIs such as most of the Get family. See the -Performance section below regarding the workload. -

    - -

    -Note that the converse is safe: an Android application thread that has entered JNI - is allowed to -directly call OpenSL ES APIs, including those that block. However, blocking calls are not -recommended from the main thread, as they may result in - Application Not Responding (ANR). -

    - -

    -The determination regarding the thread that calls a callback handler is largely left up to the -implementation. The reason for this flexibility is to permit future optimizations, - especially on -multi-core devices. -

    - -

    -The thread on which the callback handler runs is not guaranteed to have the same - identity across -different calls. Therefore, do not rely on the {@code pthread_t returned by pthread_self()} - or the -{@code pid_t returned by gettid()} to be consistent across calls. For the same reason, - do not use -the thread local storage (TLS) APIs such as {@code pthread_setspecific()} and -{@code pthread_getspecific()} from a callback. -

    - -

    -The implementation guarantees that concurrent callbacks of the same kind, for the - same object, does -not occur. However, concurrent callbacks of different kinds for the same object are possible on -different threads. -

    - -

    Performance

    - -

    -As OpenSL ES is a native C API, non-runtime application threads that call OpenSL ES have no -runtime-related overhead such as garbage collection pauses. With one exception described below, -there is no additional performance benefit to the use of OpenSL ES other than this. - In particular, -the use of OpenSL ES does not guarantee enhancements such as lower audio latency and higher -scheduling priority over that which the platform generally provides. On the other hand, as the -Android platform and specific device implementations continue to evolve, an OpenSL ES application -can expect to benefit from any future system performance improvements. -

    - -

    -One such evolution is support for reduced -audio output latency. -The underpinnings for reduced -output latency were first included in Android 4.1 (API level 16), and then -continued progress occurred in Android 4.2 (API level 17). These improvements are available via -OpenSL ES for device implementations that - claim feature {@code android.hardware.audio.low_latency}. -If the device doesn't claim this feature but supports Android 2.3 (API level 9) -or later, then you can still use the OpenSL ES APIs but the output latency may be higher. - The lower -output latency path is used only if the application requests a buffer size and sample rate - that are -compatible with the device's native output configuration. These parameters are - device-specific and -should be obtained as described below. -

    - -

    -Beginning with Android 4.2 (API level 17), an application can query for the -platform native or optimal output sample rate and buffer size for the device's primary output -stream. When combined with the feature test just mentioned, an app can now configure itself -appropriately for lower latency output on devices that claim support. -

    - -

    -For Android 4.2 (API level 17) and earlier, a buffer count of two or more is -required for lower latency. Beginning with Android 4.3 (API level 18), a buffer -count of one is sufficient for lower latency. -

    - -

    -All OpenSL ES interfaces for output effects preclude the lower latency path. -

    - -

    -The recommended sequence is as follows: -

    - -
      -
    1. Check for API level 9 or higher to confirm the use of OpenSL ES.
    2. -
    3. Check for the {@code android.hardware.audio.low_latency} feature using code such as this: -
      import android.content.pm.PackageManager;
      -...
      -PackageManager pm = getContext().getPackageManager();
      -boolean claimsFeature = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
      -    
    4. -
    5. Check for API level 17 or higher to confirm the use of - {@code android.media.AudioManager.getProperty()}.
    6. -
    7. Get the native or optimal output sample rate and buffer size for this device's - primary output - stream using code such as this: -
      import android.media.AudioManager;
      -...
      -AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
      -String sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
      -String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER));
      -    
      - Note that {@code sampleRate} and {@code framesPerBuffer} are strings. First check for - null and then convert to int using {@code Integer.parseInt()}.
    8. -
    9. Now use OpenSL ES to create an AudioPlayer with PCM buffer queue data locator.
    10. -
    - -

    Note: -You can use the - - Audio Buffer Size -test app to determine the native buffer size and sample rate for OpenSL ES audio -applications on your audio device. You can also visit GitHub to view -audio-buffer-size samples. - -

    -The number of lower latency audio players is limited. If your application requires more -than a few -audio sources, consider mixing your audio at the application level. Be sure to destroy your audio -players when your activity is paused, as they are a global resource shared with other apps. -

    - -

    -To avoid audible glitches, the buffer queue callback handler must execute within a small and -predictable time window. This typically implies no unbounded blocking on mutexes, conditions, -or I/O operations. Instead consider try locks, locks and waits with timeouts, and - - non-blocking algorithms. -

    - -

    -The computation required to render the next buffer (for AudioPlayer) or consume the previous -buffer (for AudioRecord) should take approximately the same amount of time for each callback. -Avoid algorithms that execute in a non-deterministic amount of time or are bursty in -their computations. A callback computation is bursty if the CPU time spent in any given callback -is significantly larger than the average. In summary, the ideal is for the CPU execution time of -the handler to have variance near zero, and for the handler to not block for unbounded times. -

    - -

    -Lower latency audio is possible for these outputs only: -

    - - - -

    -On some devices, speaker latency is higher than other paths due to digital signal processing for -speaker correction and protection. -

    - -

    -As of API level 21, -lower latency audio input - is supported -on select devices. To take advantage of -this feature, first confirm that lower latency output is available as described above. The -capability for lower latency output is a prerequisite for the lower latency input feature. Then, -create an AudioRecorder with the same sample rate and buffer size as would be used for output. -OpenSL ES interfaces for input effects preclude the lower latency path. The record preset -{@code SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION} must be used for lower latency; this preset -disables device-specific digital signal processing that may add latency to the input path. For -more information on record presets, see the Android -configuration interface section above. -

    - -

    -For simultaneous input and output, separate buffer queue completion handlers are used for each -side. There is no guarantee of the relative order of these callbacks, or the synchronization of -the audio clocks, even when both sides use the same sample rate. Your application - should buffer the -data with proper buffer synchronization. -

    - -

    -One consequence of potentially independent audio clocks is the need for asynchronous sample rate -conversion. A simple (though not ideal for audio quality) technique for asynchronous sample rate -conversion is to duplicate or drop samples as needed near a zero-crossing point. - More sophisticated -conversions are possible. -

    - -

    Security and Permissions

    - -

    -As far as who can do what, security in Android is done at the process level. Java programming -language code cannot do anything more than native code, nor can native code do anything more than -Java programming language code. The only differences between them are the available APIs. -

    - -

    -Applications using OpenSL ES must request the permissions that they would need for similar -non-native APIs. For example, if your application records audio, then it needs the -{@code android.permission.RECORD_AUDIO} permission. Applications that use audio effects need -{@code android.permission.MODIFY_AUDIO_SETTINGS}. Applications that play network URI resources -need {@code android.permission.NETWORK}. See -Working with System -Permissions for more information. -

    - -

    -Depending on the platform version and implementation, media content parsers and - software codecs may -run within the context of the Android application that calls OpenSL ES (hardware codecs are -abstracted but are device-dependent). Malformed content designed to exploit parser and codec -vulnerabilities is a known attack vector. We recommend that you play media only from trustworthy -sources or that you partition your application such that code that handles media from -untrustworthy sources runs in a relatively sandboxed environment. For example, you could -process media from untrustworthy sources in a separate process. Though both processes would still -run under the same UID, this separation does make an attack more difficult. -

    diff --git a/docs/html/ndk/guides/audio/output-latency.jd b/docs/html/ndk/guides/audio/output-latency.jd deleted file mode 100644 index 4aa97a69be7128c4ae9e770e0bb3a81ac9fe593e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/output-latency.jd +++ /dev/null @@ -1,310 +0,0 @@ -page.title=Audio Output Latency -@jd:body - - - - -
    -

    Video

    -

    Audio latency: buffer sizes

    -
    -
    - - -
    -

    Video

    -

    Building great multi-media experiences on Android

    -
    -
    - -

    This page describes how to develop your audio app for low-latency output and how to avoid -warmup latency.

    - -

    Prerequisites

    - -

    Low-latency audio is currently only supported when using Android's implementation of the -OpenSL ES™ API specification, and the Android NDK: -

    - -
      -
    1. Download and install the Android NDK.
    2. -
    3. Read the OpenSL ES - documentation. -
    - -

    Obtain a Low-Latency Track

    - -

    Latency is the time it takes for a signal to travel through a system. These are the common -types of latency related to audio apps: - -

      -
    • Audio output latency is the time between an audio sample being generated by an -app and the sample being played through the headphone jack or built-in speaker.
    • - -
    • Audio input latency is the time between an audio signal being received by a -device’s audio input, such as the microphone, and that same audio data being available to an -app.
    • - -
    • Round-trip latency is the sum of input latency, app processing time, and - output latency.
    • - -
    • Touch latency is the time between a user touching the screen and that -touch event being received by an app.
    • -
    - -

    It is difficult to test audio output latency in isolation since it requires knowing exactly -when the first sample is sent into the audio path (although this can be done using a - -light testing circuit and an oscilloscope). If you know the round-trip audio latency, you can -use the rough rule of thumb: audio output latency is half the round-trip audio latency -over paths without signal processing. -

    - -

    To obtain the lowest latency, you must supply audio data that matches the device's optimal -sample rate and buffer size. For more information, see - -Design For Reduced Latency.

    - -

    Obtain the optimal sample rate

    - -

    In Java, you can obtain the optimal sample rate from AudioManager as shown in the following -code example:

    - -
    -AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    -String frameRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
    -int frameRateInt = Integer.parseInt(frameRate);
    -if (frameRateInt == 0) frameRateInt = 44100; // Use a default value if property not found
    -
    - -

    - Note: The sample rate refers to the rate of each stream. If your source audio - has two channels (stereo), then you will have one stream playing a pair of samples (frame) at - - PROPERTY_OUTPUT_SAMPLE_RATE. -

    - -

    Use the optimal sample rate when creating your audio player

    - -

    Once you have the optimal sample output rate, you can supply it when creating your player -using OpenSL ES:

    - -
    -// create buffer queue audio player
    -void Java_com_example_audio_generatetone_MainActivity_createBufferQueueAudioPlayer
    -        (JNIEnv* env, jclass clazz, jint sampleRate, jint framesPerBuffer)
    -{
    -   ...
    -   // specify the audio source format
    -   SLDataFormat_PCM format_pcm;
    -   format_pcm.numChannels = 2;
    -   format_pcm.samplesPerSec = (SLuint32) sampleRate * 1000;
    -   ...
    -}
    -
    - -

    - Note: {@code samplesPerSec} refers to the sample rate per channel in - millihertz (1 Hz = 1000 mHz). -

    - -

    Avoid adding output interfaces that involve signal processing

    - -

    Only these interfaces are supported by the fast mixer:

    - -
      -
    • SL_IID_ANDROIDSIMPLEBUFFERQUEUE
    • -
    • SL_IID_VOLUME
    • -
    • SL_IID_MUTESOLO
    • -
    - -

    These interfaces are not allowed because they involve signal processing and will cause -your request for a fast-track to be rejected:

    - -
      -
    • SL_IID_BASSBOOST
    • -
    • SL_IID_EFFECTSEND
    • -
    • SL_IID_ENVIRONMENTALREVERB
    • -
    • SL_IID_EQUALIZER
    • -
    • SL_IID_PLAYBACKRATE
    • -
    • SL_IID_PRESETREVERB
    • -
    • SL_IID_VIRTUALIZER
    • -
    • SL_IID_ANDROIDEFFECT
    • -
    • SL_IID_ANDROIDEFFECTSEND
    • -
    - -

    When you create your player, make sure you only add fast interfaces, as shown in -the following example:

    - -
    -const SLInterfaceID interface_ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME };
    -
    - -

    Verify you're using a low-latency track

    - -

    Complete these steps to verify that you have successfully obtained a low-latency track:

    - -
      -
    1. Launch your app and then run the following command:
    2. - -
      -adb shell ps | grep your_app_name
      -
      - -
    3. Make a note of your app's process ID.
    4. - -
    5. Now, play some audio from your app. You have approximately three seconds to run the -following command from the terminal:
    6. - -
      -adb shell dumpsys media.audio_flinger
      -
      - -
    7. Scan for your process ID. If you see an F in the Name column, it's on a -low-latency track (the F stands for fast track).
    8. - -
    - -

    Measure round-trip latency

    - -

    You can measure round-trip audio latency by creating an app that generates an audio signal, -listens for that signal, and measures the time between sending it and receiving it. -Alternatively, you can install this - -latency testing app. This performs a round-trip latency test using the - -Larsen test. You can also - -view the source code for the latency testing app.

    - -

    Since the lowest latency is achieved over audio paths with minimal signal processing, you may -also want to use an - -Audio Loopback Dongle, which allows the test to be run over the headset connector.

    - -

    The lowest possible round-trip audio latency varies greatly depending on device model and -Android build. You can measure it yourself using the latency testing app and loopback -dongle. When creating apps for Nexus devices, you can also use the - -published measurements.

    - -

    You can also get a rough idea of audio performance by testing whether the device reports -support for the - -low_latency and - -pro hardware features.

    - -

    Review the CDD and audio latency

    - -

    The Android Compatibility Definition Document (CDD) enumerates the hardware and software -requirements of a compatible Android device. -See -Android Compatibility for more information on the overall compatibility program, and - -CDD for the actual CDD document.

    - -

    In the CDD, round-trip latency is specified as 20 ms or lower (even though musicians -generally require 10 ms). This is because there are important use cases that are enabled by -20 ms.

    - -

    There is currently no API to determine audio latency over any path on an Android device at -runtime. You can, however, use the following hardware feature flags to find out whether the -device makes any guarantees for latency:

    - - - -

    The criteria for reporting these flags is defined in the CDD in sections 5.6 Audio -Latency and 5.10 Professional Audio.

    - -

    Here’s how to check for these features in Java:

    - -
    -boolean hasLowLatencyFeature =
    -    getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
    -
    -boolean hasProFeature =
    -    getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
    -
    - -

    Regarding the relationship of audio features, the {@code android.hardware.audio.low_latency} -feature is a prerequisite for {@code android.hardware.audio.pro}. A device can implement -{@code android.hardware.audio.low_latency} and not {@code android.hardware.audio.pro}, but not -vice-versa.

    - -

    Use the Optimal Buffer Size When Enqueuing Audio Data

    - -

    You can obtain the optimal buffer size in a similar way to the optimal frame rate, using the -AudioManager API:

    - -
    -AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    -String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
    -int framesPerBufferInt = Integer.parseInt(framesPerBuffer);
    -if (framesPerBufferInt == 0) framesPerBufferInt = 256; // Use default
    -
    - -

    The - -PROPERTY_OUTPUT_FRAMES_PER_BUFFER property indicates the number of audio frames -that the HAL (Hardware Abstraction Layer) buffer can hold. You should construct your audio -buffers so that they contain an exact multiple of this number. If you use the correct number -of audio frames, your callbacks occur at regular intervals, which reduces jitter.

    - -

    It is important to use the API to determine buffer size rather than using a hardcoded value, - because HAL buffer sizes differ across devices and across Android builds.

    - -

    Avoid Warmup Latency

    - -

    When you enqueue audio data for the first time, it takes a small, but still significant, -amount of time for the device audio circuit to warm up. To avoid this warmup latency, you should -enqueue buffers of audio data containing silence, as shown in the following code example:

    - -
    -#define CHANNELS 1
    -static short* silenceBuffer;
    -int numSamples = frames * CHANNELS;
    -silenceBuffer = malloc(sizeof(*silenceBuffer) * numSamples);
    -    for (i = 0; i < numSamples; i++) {
    -        silenceBuffer[i] = 0;
    -    }
    -
    - -

    At the point when audio should be produced, you can switch to enqueuing buffers containing -real audio data.

    - diff --git a/docs/html/ndk/guides/audio/sample-rates.jd b/docs/html/ndk/guides/audio/sample-rates.jd deleted file mode 100644 index da6859762487b68a14c71233ae016f23acac17d4..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/audio/sample-rates.jd +++ /dev/null @@ -1,151 +0,0 @@ -page.title=Sample Rates -@jd:body - - - - -
    -

    Video

    -

    Sample Rates: Why Can't We All Just Agree?

    -
    -
    - -

    As of Android 5.0 (Lollipop), the audio resamplers are now entirely based -on FIR filters derived from a Kaiser windowed-sinc function. The Kaiser windowed-sinc -offers the following properties: -

      -
    • It is straightforward to calculate for its design parameters (stopband - ripple, transition bandwidth, cutoff frequency, filter length).
    • -
    • It is nearly optimal for reduction of stopband energy compared to overall -energy.
    • -
    -See P.P. Vaidyanathan, -Multirate Systems and Filter Banks, p. 50 for discussions of the -Kaiser Window and its optimality and relationship to Prolate Spheroidal -Windows.

    - -

    The design parameters are automatically computed based on internal -quality determination and the sampling ratios desired. Based on the -design parameters, the windowed-sinc filter is generated. For music use, -the resampler for 44.1 to 48 kHz and vice versa is generated at a higher -quality than for arbitrary frequency conversion.

    - -

    The audio resamplers provide increased quality, as well as speed -to achieve that quality. But resamplers can introduce small amounts -of passband ripple and aliasing harmonic noise, and they can cause some high -frequency loss in the transition band, so avoid using them unnecessarily.

    - -

    Best Practices for Sampling and Resampling

    -

    This section describes some best practices to help you avoid problems with sampling rates.

    -

    Choose the sampling rate to fit the device

    - -

    In general, it is best to choose the sampling rate to fit the device, -typically 44.1 kHz or 48 kHz. Use of a sample rate greater than -48 kHz will typically result in decreased quality because a resampler must be -used to play back the file.

    - -

    Use simple resampling ratios (fixed versus interpolated polyphases)

    - -

    The resampler operates in one of the following modes:

    -
      -
    • Fixed polyphase mode. The filter coefficients for each polyphase are precomputed.
    • -
    • Interpolated polyphase mode. The filter coefficients for each polyphase must -be interpolated from the nearest two precomputed polyphases.
    • -
    -

    The resampler is fastest in fixed polyphase mode, when the ratio of input -rate over output rate L/M (taking out the greatest common divisor) -has M less than 256. For example, for 44,100 to 48,000 conversion, L = 147, -M = 160.

    - -

    In fixed polyphase mode, the sampling rate is locked for as -many samples converted and does not change. In interpolated polyphase -mode, the sampling rate is approximate. The drift is generally on the -order of one sample over a few hours of playback on a 48-kHz device. -This is not usually a concern because approximation error is much less than -frequency error of internal quartz oscillators, thermal drift, or jitter - (typically tens of ppm).

    - -

    Choose simple-ratio sampling rates such as 24 kHz (1:2) and 32 kHz (2:3) when playing back - on a 48-kHz device, even though other sampling -rates and ratios may be permitted through AudioTrack.

    - -

    Use upsampling rather than downsampling when changing sample rates

    - -

    Sampling rates can be changed on the fly. The granularity of -such change is based on the internal buffering (typically a few hundred -samples), not on a sample-by-sample basis. This can be used for effects.

    - -

    Do not dynamically change sampling rates when -downsampling. When changing sample rates after an audio track is -created, differences of around 5 to 10 percent from the original rate may -trigger a filter recomputation when downsampling (to properly suppress -aliasing). This can consume computing resources and may cause an audible click -if the filter is replaced in real time.

    - -

    Limit downsampling to no more than 6:1

    - -

    Downsampling is typically triggered by hardware device requirements. When the - Sample Rate converter is used for downsampling, -try to limit the downsampling ratio to no more than 6:1 for good aliasing -suppression (for example, no greater downsample than 48,000 to 8,000). The filter -lengths adjust to match the downsampling ratio, but you sacrifice more -transition bandwidth at higher downsampling ratios to avoid excessively -increasing the filter length. There are no similar aliasing concerns for -upsampling. Note that some parts of the audio pipeline -may prevent downsampling greater than 2:1.

    - -

    If you are concerned about latency, do not resample

    - -

    Resampling prevents the track from being placed in the FastMixer -path, which means that significantly higher latency occurs due to the additional, - larger buffer in the ordinary Mixer path. Furthermore, - there is an implicit delay from the filter length of the resampler, - though this is typically on the order of one millisecond or less, - which is not as large as the additional buffering for the ordinary Mixer path - (typically 20 milliseconds).

    - -

    For More Information

    -

    This section lists some additional resources about sampling and resampling.

    - -

    Sample rates

    - -

    - -Sampling (signal processing) at Wikipedia.

    - -

    Resampling

    - -

    -Sample rate conversion at Wikipedia.

    - -

    -Sample Rate Conversion at source.android.com.

    - -

    The high bit-depth and high kHz controversy

    - -

    -24/192 Music Downloads ... and why they make no sense -by Christopher "Monty" Montgomery of Xiph.Org.

    - -

    -D/A and A/D | Digital Show and Tell -video by Christopher "Monty" Montgomery of Xiph.Org.

    - -

    -The Science of Sample Rates (When Higher Is Better - And When It Isn't).

    - -

    -Audio Myths & DAW Wars

    - -

    -192kHz/24bit vs. 96kHz/24bit "debate"- Interesting revelation

    diff --git a/docs/html/ndk/guides/build.jd b/docs/html/ndk/guides/build.jd deleted file mode 100644 index 62863283c3863f8c4051c0345cbb8bbfc54fb808..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/build.jd +++ /dev/null @@ -1,18 +0,0 @@ -page.title=Building Your Project -@jd:body - -

    One of the NDK's core purposes is allowing you to build C and C++ source code into shared -libraries that you can use in your app.

    - -

    This section explains how to build native binaries for use in your Android app. It begins by -explaining the -{@code Android.mk} file, which -defines properties specific to individual modules, or libraries. Then, it explains the -{@code Application.mk} file, which defines -properties for all the modules that you use in your -app. Next, it tells you how to use the -{@code ndk-build} script, which is what the NDK uses to build your sources. Last, it ventures -into advanced territory, discussing how to incorporate the NDK into your own -toolchain, if you prefer to -build that way instead of using -{@code ndk-build}.

    \ No newline at end of file diff --git a/docs/html/ndk/guides/concepts.jd b/docs/html/ndk/guides/concepts.jd deleted file mode 100755 index 7879219f347b88e333e1812f7534967fd81bddb8..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/concepts.jd +++ /dev/null @@ -1,303 +0,0 @@ -page.title=Concepts -@jd:body - - - -

    Before Beginning

    - -

    This guide assumes that you are already familiar with concepts inherent in native programming and -in Android development.

    - - -

    Introduction

    - -

    This section provides a high-level explanation of how the NDK works. The Android NDK is a set of -tools allowing you to embed C or C++ (“native code”) into your Android apps. The ability to use -native code in Android apps can be particularly useful to developers who wish to do one or more of -the following:

    -
      -
    • Port their apps between platforms.
    • -
    • Reuse existing libraries, or provide their own libraries for reuse. -
    • -
    • Increase performance in certain cases, particularly computationally intensive ones like games. -
    • -
    -

    How it Works

    - -

    This section introduces the main components used in building a native application for Android, -and goes on to describe the process of building and packaging.

    -

    Main components

    - -

    You should have an understanding of the following components as you build your app:

    -
      -
    • ndk-build: The ndk-build script launches the build scripts at the heart of the NDK. These -scripts: -
        -
      • Automatically probe your development system and app project file to determine what to build.
      • -
      • Generate binaries.
      • -
      • Copy the binaries to your app's project path.
      • -
      -

      For more information, see -ndk-build.

      -
    • -
    - -
      -
    • Java: From your Java source, the Android build process generates {@code .dex} -(Dalvik EXecutable) files, which are what the Android OS runs in the Dalvik Virtual Machine -(“DVM”). Even if your app contains no Java source code at all, the build process still generates a -{@code .dex} executable file within which the native component runs. - -

      When developing Java components, use the {@code native} keyword to indicate methods implemented -as native code. For example, the following function declaration tells the compiler that the -implementation is in a native library:

      - - - -
      -public native int add(int  x, int  y);
      -
      -
    • -
    - -
      -
    • Native shared libraries: The NDK builds these libraries, or {@code .so} files, from your native -source code. - -

      Note: If two libraries implement respective methods with the same -signature, a link error occurs. In C, "signature" means method name only. In C++, "signature" means -not only method name, but also its argument names and types.

      -
    • -
    - -
      -
    • Native static libraries: The NDK can also build static libraries, or {@code .a} files, which you -can link against other libraries.
    • -
    - -
      -
    • Java Native Interface (JNI): The JNI is the interface via which the Java and C++ components -talk to one another. This guide assumes knowledge of the JNI; for information about it, consult the - -Java Native Interface Specification.
    • -
    - -
      -
    • Application Binary Interface (ABI): The ABI defines exactly how your app's machine code is -expected to interact with the system at runtime. The NDK builds {@code .so} files against these -definitions. Different ABIs correspond to different architectures: The NDK includes ABI support for -ARMEABI (default), MIPS, and x86. For more information, see -ABI Management.
    • -
    - -
      -
    • Manifest: If you are writing an app with no Java component to it, you must declare the -{@link android.app.NativeActivity} class in the -manifest. -Native Activities and Applications provides more detail on how to do this, under -“Using the {@code native_activity.h} interface.” -
    • -
    - -

    The following two items are only required for building using the -{@code ndk-build} script, -and for debugging using the -{@code ndk-gdb} script. - -

      -
    • {@code Android.mk}: -You must create an -{@code Android.mk} configuration file inside your {@code jni} folder. The {@code ndk-build} -script looks at this file, which defines the module and its name, the source files to be compiled, -build flags and libraries to link.
    • -
    - -
      -
    • {@code Application.mk}: This file -enumerates and describes the modules that your app requires. This information includes: - -
        -
      • ABIs used to compile for specific platforms.
      • -
      • Toolchains.
      • -
      • Standard libraries to include (static and dynamic STLport or default system).
      • -
      -
    • -
    - - -

    Flow

    - -

    The general flow for developing a native app for Android is as follows:

    -
      -
    1. Design your app, deciding which parts to implement in Java, and which parts to implement as -native code. - -

      Note: While it is possible to completely avoid Java, you are likely -to find the Android Java framework useful for tasks including controlling the display and UI.

      -
    2. -
    3. Create an Android app Project as you would for any other Android project.
    4. -
    5. If you are writing a native-only app, declare the {@link android.app.NativeActivity} class in -{@code AndroidManifest.xml}. For more information, see the Native Activities and -Applications. -
    6. -
    7. Create an {@code Android.mk} file describing the native library, including name, flags, linked -libraries, and source files to be compiled in the "JNI" directory.
    8. -
    9. Optionally, you can create an {@code Application.mk} file configuring the target ABIs, -toolchain, release/debug mode, and STL. For any of these that you do not specify, the following -default values are used, respectively: -
        -
      • -ABI: armeabi -
      • -
      • -Toolchain: GCC 4.8 -
      • -
      • -Mode: Release -
      • -
      • -STL: system -
      -
    10. -
    11. Place your native source under the project's {@code jni} directory.
    12. -
    13. Use ndk-build to compile the native ({@code .so}, {@code .a}) libraries.
    14. -
    15. Build the Java component, producing the executable {@code .dex} file.
    16. -
    17. Package everything into an APK file, containing {@code .so}, {@code .dex}, and other files -needed for your app to run. -
    - - -

    Native Activities and Applications

    - -

    The Android SDK provides a helper class, {@link android.app.NativeActivity}, that allows you to -write a completely native activity. {@link android.app.NativeActivity} handles the communication -between the Android framework and your native code, so you do not have to subclass it or call its -methods. All you need to do is declare your application to be native in your -{@code AndroidManifest.xml} file, and begin creating your native application.

    - -

    An Android application using {@link android.app.NativeActivity} still runs in its own virtual -machine, sandboxed from other applications. You can therefore still access Android framework APIs -through the JNI. In certain cases, however–such as for sensors, input events, and -assets–the NDK provides native interfaces that you can use instead of having to call -across the JNI. For more information about such support, see -Android NDK Native APIs.

    - -

    Regardless of whether or not you are developing a native activity, we recommend that you create -your projects with the traditional Android build tools. Doing so helps ensure building and packaging -of Android applications with the correct structure.

    - -

    The Android NDK provides you with two choices to implement your native activity:

    - -
      -
    • The {@code native_activity.h} -header defines the native version of the -{@link android.app.NativeActivity} class. It contains the callback interface and data structures -that you need to create your native activity. Because the main thread of your application handles -the callbacks, your callback implementations must not be blocking. If they block, you might receive -ANR (Application Not Responding) errors because your main thread is unresponsive until the callback -returns.
    • -
    • The {@code android_native_app_glue.h} file defines a static helper library built on top of the -{@code native_activity.h} interface. -It spawns another thread, which handles things such as -callbacks or input events in an event loop. Moving these events to a separate thread prevents any -callbacks from blocking your main thread.
    • -
    - -

    The {@code /sources/android/native_app_glue/android_native_app_glue.c} source is -also available, allowing you to modify the implementation.

    -

    For more information on how to use this static library, examine the native-activity sample -application and its documentation. Further reading is also available in the comments in the {@code /sources/android/native_app_glue/android_native_app_glue.h} file.

    - -

    Using the native_activity.h interface

    - -

    To implement a native activity with the -{@code native_activity.h} -interface:

    - -
      -
    1. Create a {@code jni/} directory in your project's root directory. This directory stores all of -your native code.
    2. -
    3. Declare your native activity in the {@code AndroidManifest.xml} file.
    4. - -

      Because your application has no Java code, set {@code android:hasCode} to {@code false}.

      - -
      -<application android:label="@string/app_name" android:hasCode="false">
      -
      - -

      You must set the {@code android:name} attribute of the activity tag to -{@link android.app.NativeActivity}.

      - -
      -<activity android:name="android.app.NativeActivity"
      -            android:label="@string/app_name">
      -
      -

      Note: You can subclass {@link android.app.NativeActivity}. If you -do, use the name of the subclass instead of {@link android.app.NativeActivity}.

      -

      The {@code android:value} attribute of the {@code meta-data} tag specifies the name of the shared -library containing the entry point to the application (such as C/C++ {@code main}), omitting the -{@code lib} prefix and {@code .so} suffix from the library name.

      - -
      -          <meta-data android:name="android.app.lib_name"
      -            android:value="native-activity" />
      -            <intent-filter>
      -              <action android:name="android.intent.action.MAIN" />
      -              <category android:name="android.intent.category.LAUNCHER" />
      -            </intent-filter>
      -          </activity>
      -        </application>
      -      </manifest>
      -
      - -
    5. Create a file for your native activity, and implement the function named in the - -{@code ANativeActivity_onCreate} variable. -The app calls this function when the native activity starts. This function, analogous -to {@code main} in C/C++, receives a pointer to an -{@code ANativeActivity} -structure, which contains function pointers to the various callback implementations that you need -to write. -Set the applicable callback function pointers in {@code ANativeActivity->callbacks} to the -implementations of your callbacks.
    6. - -
    7. Set the {@code ANativeActivity->instance} field to the address of any instance of specific -data that you want to use.
    8. -
    9. Implement anything else that you want your activity to do upon starting.
    10. -
    11. Implement the rest of the callbacks that you set in {@code ANativeActivity->callbacks}. For -more information on when the callbacks are called, see -Managing the Activity -Lifecycle. -
    12. -
    13. Develop the rest of your application.
    14. -
    15. Create an {@code Android.mk file} in the {@code jni/} directory of your project to describe your -native module to the build system. For more information, see -Android.mk.
    16. -
    17. Once you have an {@code Android.mk} -file, compile your native code using the {@code ndk-build} command.
    18. - -
      -$ cd <path>/<to>/<project>
      -$ <ndk>/ndk-build
      -
      - -
    19. Build and install your Android project as usual. If your native code is in -the {@code jni/} directory, the build script automatically packages the {@code .so} file(s) built -from it into the APK.
    20. -
    - - - diff --git a/docs/html/ndk/guides/cpp-support.jd b/docs/html/ndk/guides/cpp-support.jd deleted file mode 100644 index 6e902f530a1e45d6bb2e1cbd367d6ed99e9db87d..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/cpp-support.jd +++ /dev/null @@ -1,326 +0,0 @@ -page.title=C++ Library Support -@jd:body - - - -

    The Android platform provides a very minimal C++ runtime support library ({@code libstdc++}). -This minimal support does not include, for example:

    - -
      -
    • Standard C++ Library support (except a few trivial headers).
    • -
    • C++ exceptions support
    • -
    • RTTI support
    • -
    - -

    The NDK provides headers for use with this default library. In addition, the NDK provides a -number of helper runtimes that provide additional features. This page provides information about -these helper runtimes, their characteristics, and how to use them. -

    - -

    Helper Runtimes

    - -

    Table 1 provides names, brief explanations, and features of runtimes available inthe NDK.

    - -

    - Table 1. NDK Runtimes and Features.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    NameExplanation> -Features -
    {@code libstdc++} (default) The default minimal system C++ runtime library.N/A
    {@code gabi++_static} The GAbi++ runtime (static).C++ Exceptions and RTTI
    {@code gabi++_shared} The GAbi++ runtime (shared).C++ Exceptions and RTTI
    {@code stlport_static} The STLport runtime (static). C++ Exceptions and RTTI; Standard Library
    {@code stlport_shared} The STLport runtime (shared). C++ Exceptions and RTTI; Standard Library
    {@code gnustl_static} The GNU STL (static). C++ Exceptions and RTTI; Standard Library
    {@code gnustl_shared} The GNU STL (shared). C++ Exceptions and RTTI; Standard Library
    {@code c++_static} The LLVM libc++ runtime (static). C++ Exceptions and RTTI; Standard Library
    {@code c++_shared} The LLVM libc++ runtime (shared). C++ Exceptions and RTTI; Standard Library
    - -

    How to set your runtime

    - -

    Use the {@code APP_STL} variable in your -{@code Application.mk} file to specify the runtime you wish to use. Use the values in -the "Name" column in Table 1 as your setting. For example:

    - -
    -APP_STL := gnustl_static
    -
    - -

    You may only select one runtime for your app, and can only do in -{@code Application.mk}.

    - -

    Even if you do not use the NDK build system, you can still use STLport, libc++ or GNU STL. -For more information on how to use these runtimes with your own toolchain, see Standalone Toolchain.

    - -

    Runtime Characteristics

    -

    libstdc++ (default system runtime)

    - -

    This runtime only provides the following headers, with no support beyond them:

    -
      -
    • {@code cassert}
    • -
    • {@code cctype}
    • -
    • {@code cerrno}
    • -
    • {@code cfloat}
    • -
    • {@code climits}
    • -
    • {@code cmath}
    • -
    • {@code csetjmp}
    • -
    • {@code csignal}
    • -
    • {@code cstddef}
    • -
    • {@code cstdint}
    • -
    • {@code cstdio}
    • -
    • {@code cstdlib}
    • -
    • {@code cstring}
    • -
    • {@code ctime}
    • -
    • {@code cwchar}
    • -
    • {@code new}
    • -
    • {@code stl_pair.h}
    • -
    • {@code typeinfo}
    • -
    • {@code utility}
    • -
    - -

    GAbi++ runtime

    -

    This runtime provides the same headers as the default runtime, but adds support for RTTI -(RunTime Type Information) and exception handling.

    - - -

    STLport runtime

    -

    This runtime is an Android port of STLport -(http://www.stlport.org). It provides a complete set of C++ -standard library headers. It also, by embedding its own instance of GAbi++, provides support for -RTTI and exception handling.

    - -

    While shared and static versions of this runtime are avilable, we recommend using the shared -version. For more information, see Static runtimes.

    - -

    The shared library file is named {@code libstlport_shared.so} instead of {@code libstdc++.so} -as is common on other platforms.

    - -

    In addition to the static- and shared-library options, you can also force the NDK to -build the library from sources by adding the following line to your {@code Application.mk} -file, or setting it in your environment prior to building:

    - -
    -STLPORT_FORCE_REBUILD := true
    -
    - - -

    GNU STL runtime

    -

    This runtime is the GNU Standard C++ Library, ({@code libstdc++-v3}). Its shared library file is -named {@code libgnustl_shared.so}.

    - - -

    libc++ runtime:

    -

    This runtime is an Android port of LLVM libc++. Its -shared library file is named {@code libc++_shared.so}.

    - -

    By default, this runtime compiles with {@code -std=c++11}. As with GNU {@code libstdc++}, you -need to explicitly turn on exceptions or RTTI support. For information on how to do this, see -C++ Exceptions and RTTI.

    - -

    The NDK provides prebuilt static and shared libraries for {@code libc++}, but you can force the -NDK to rebuild {@code libc++} from sources by adding the following line to your -{@code Application.mk} file, or setting it in your environment prior to building:

    - -
    -LIBCXX_FORCE_REBUILD := true
    -
    - -

    Atomic support

    - -

    If you include {@code }, it's likely that you also need {@code libatomic}. -If you are using {@code ndk-build}, add the following line:

    - -
    -LOCAL_LDLIBS += -latomic
    -
    - -

    If you are using your own toolchain, use:

    - -
    --latomic
    -
    - - -

    Compatibility

    - -

    The NDK's libc++ is not stable. Not all the tests pass, and the test suite is not comprehensive. -Some known issues are:

    - -
      -
    • Using {@code c++_shared} on ARM can crash when an exception is thrown.
    • -
    • Support for {@code wchar_t} and the locale APIs is limited.
    • -
    - -

    You should also make sure to check the "Known Issues" section of the changelog for the NDK -release you are using.

    - -

    Warning: Attempting to change to an unsupported locale will -not fail. The operation will succeed, but the locale will not change and the -following message will appear in {@code logcat}.

    - -
    -newlocale() WARNING: Trying to set locale to en_US.UTF-8 other than "", "C" or "POSIX"
    -
    - - -

    Important Considerations

    - -

    C++ Exceptions

    -

    In all versions of the NDK later than NDKr5, the NDK toolchain allows you to use C++ runtimes -that support exception handling. However, to ensure compatibility with earlier releases, it -compiles all C++ sources with {@code -fno-exceptions} support by default. You can enable C++ -exceptions either for your entire app, or for individual modules. - -

    To enable exception-handling support for your entire app, add the following line to -your {@code Application.mk} file. -To enable exception-handling support for individual modules', add the following line to -their respective {@code Android.mk} files.

    - -
    -APP_CPPFLAGS += -fexceptions
    -
    - -

    RTTI

    -

    In all versions of the NDK later than NDKr5, the NDK toolchain allows you to use C++ runtimes -that support RTTI. However, to ensure compatibility with earlier releases, it compiles all C++ -sources with {@code -fno-rtti} by default. - -

    To enable RTTI support for your entire app for your entire application, add the following line to -your {@code Application.mk} file: - -

    -APP_CPPFLAGS += -frtti
    -
    - -To enable RTTI support for individual modules, add the following line to -their respective {@code Android.mk} files: - -
    -LOCAL_CPP_FEATURES += rtti
    -
    - -Alternatively, you can use: - -
    -LOCAL_CPPFLAGS += -frtti
    -
    - -

    Static runtimes

    -

    Linking the static library variant of a C++ runtime to more than one binary may result in -unexpected behavior. For example, you may experience:

    - -
      -
    • Memory allocated in one library, and freed in the other, causing memory leakage or heap -corruption.
    • -
    • Exceptions raised in {@code libfoo.so} going uncaught in {@code libbar.so}, causing your app -to crash.
    • -
    • Buffering of {@code std::cout} not working properly
    • -
    - -

    In addition, if you link two shared libraries–or a shared library and an executable– -against the same static runtime, the final binary image of each shared library includes a copy of -the runtime's code. Having multiple instances of runtime code is problematic because of duplication -of certain global variables that the runtime uses or provides internally.

    - -

    This problem does not apply to a project comprising a single shared library. For example, -you can link against {@code stlport_static}, and expect your app to behave correctly. If your -project requires several shared library modules, we recommend that you use the shared library -variant of your C++ runtime.

    - -

    Shared runtimes

    -

    If your app targets a version of Android earlier than Android 4.3 (Android API level 18), -and you use the shared library variant of a given C++ runtime, you must load the shared library -before any other library that depends on it.

    - -

    For example, an app may have the following modules:

    - -
      -
    • libfoo.so
    • -
    • libbar.so which is used by libfoo.so
    • -
    • libstlport_shared.so, used by both libfoo and libbar
    • -
    - -

    You must load the libraries in reverse dependency order:

    -
    -    static {
    -      System.loadLibrary("stlport_shared");
    -      System.loadLibrary("bar");
    -      System.loadLibrary("foo");
    -    }
    -
    - -

    Note: Do not use the {@code lib} prefix when calling -{@code System.loadLibrary()}.

    - -

    Licensing

    - -

    STLport is licensed under a BSD-style open-source license. See -{@code $NDK/sources/cxx-stl/stlport/README} for more details about STLport.

    - -

    GNU libstdc++ is covered by the GPLv3 license, and not the LGPLv2 or LGPLv3. For -more information, see -License on the GCC website.

    - -

    LLVM {@code libc++} -is dual-licensed under both the University of Illinois "BSD-Like" license and the MIT license.

    diff --git a/docs/html/ndk/guides/cpu-arm-neon.jd b/docs/html/ndk/guides/cpu-arm-neon.jd deleted file mode 100644 index 1d12937c5fb492ad83b9a7fa04b6991184f4c0b7..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/cpu-arm-neon.jd +++ /dev/null @@ -1,109 +0,0 @@ -page.title=NEON Support -@jd:body - - - -

    The NDK supports the ARM Advanced SIMD, an optional instruction-set extension of the ARMv7 spec. -NEON provides a set of scalar/vector instructions and registers (shared with the FPU) comparable to -MMX/SSE/3DNow! in the x86 world. To function, it requires VFPv3-D32 (32 hardware FPU 64-bit -registers, instead of the minimum of 16).

    - -

    The NDK supports the compilation of modules or even specific source files with support for NEON. -As a result, a specific compiler flag enables the use of GCC ARM NEON intrinsics and VFPv3-D32 -at the same time.

    - -

    Not all ARMv7-based Android devices support NEON, but devices that do may benefit significantly -from its support for scalar/vector instructions. For x86 devices, the NDK can also translate NEON -instructions into SSE, although with several restrictions. For more information, see -x86 Support for ARM NEON Intrinsics.

    - -

    Using LOCAL_ARM_NEON

    -

    To have the NDK build all its source files with NEON support, include the following line in -your module definition:

    - -
    -LOCAL_ARM_NEON := true
    -
    - -

    It can be especially useful to build all source files with NEON support if you want to build a -static or shared library that specifically contains NEON code paths.

    - -

    Using the .neon Suffix

    -

    When listing source files for your {@code LOCAL_SRC_FILES} variable, you have the option of -using the {@code .neon} suffix to indicate that you want to build binaries with NEON support. -For example, the following example builds one file with {@code .neon} support, and another -without it:

    - -
    -LOCAL_SRC_FILES := foo.c.neon bar.c
    -
    - -

    You can combine the {@code .neon} suffix with the {@code .arm} suffix, which specifies the 32-bit -ARM instruction set for non-NEON instructions. In such a definition, {@code arm} must come before -{@code neon}. For example: {@code foo.c.arm.neon} works, but {@code foo.c.neon.arm} does not.

    - -

    Build Requirements

    -

    NEON support only works with the {@code armeabi-v7a} and {@code x86} ABIs. If the NDK build -scripts encounter other ABIs while attempting to build with NEON support, the NDK build scripts -exit. x86 provides partial NEON support via translation header. It is -important to use checks like the following in your -{@code Android.mk} file:

    - -
    -# define a static library containing our NEON code
    -ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86))
    -include $(CLEAR_VARS)
    -LOCAL_MODULE    := mylib-neon
    -LOCAL_SRC_FILES := mylib-neon.c
    -LOCAL_ARM_NEON  := true
    -include $(BUILD_STATIC_LIBRARY)
    -endif # TARGET_ARCH_ABI == armeabi-v7a || x86
    -
    - -

    Runtime Detection

    -

    Your app must perform runtime detection to confirm that NEON-capable machine code can be run on -the target device. This is because not all ARMv7-based Android devices support NEON. The app can -perform this check using the -{@code cpufeatures} library that comes with -this NDK.

    - -

    You should explicitly check that {@code android_getCpuFamily()} returns {@code -ANDROID_CPU_FAMILY_ARM}, and that {@code android_getCpuFeatures()} returns a value including the -{@code ANDROID_CPU_ARM_FEATURE_NEON flag} set. For example:

    - -
    -#include <cpu-features.h>
    -...
    -...
    -if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
    -    (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0)
    -{
    -    // use NEON-optimized routines
    -    ...
    -}
    -else
    -{
    -    // use non-NEON fallback routines instead
    -    ...
    -}
    -
    -...
    -
    - -

    Sample Code

    -

    The source code for the NDK's hello-neon sample provides an example of how to use the -{@code cpufeatures} library and NEON intrinsics at the same time. This sample implements a tiny -benchmark for a FIR filter loop using a C version, and a NEON-optimized one for devices that -support it.

    \ No newline at end of file diff --git a/docs/html/ndk/guides/cpu-features.jd b/docs/html/ndk/guides/cpu-features.jd deleted file mode 100644 index 3323efdb719db92eaeeeb25ffc6ce3f3691cfd45..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/cpu-features.jd +++ /dev/null @@ -1,210 +0,0 @@ -page.title=The cpufeatures Library -@jd:body - -
    -
    -

    On this page

    - -
      -
    1. Usage
    2. -
    3. Functions
    4. -
    5. Change History
    6. -
    -
    -
    - -

    The NDK provides a small library named {@code cpufeatures} that your app can use at runtime to -detect the target device's CPU family and the optional features it supports. It is designed to work -as-is on all official Android platform versions.

    - -

    Usage

    -

    The {@code cpufeatures} library is available as an import module. To use it, follow the procedure -below:

    - -
      -
    1. List {@code cpufeatures} in your list of static library dependencies. For example: - -
      -LOCAL_STATIC_LIBRARIES := cpufeatures
      -
      -
    2. - -
    3. In your source code, include the {@code } header file.
    4. - -
    5. At the end of your {@code Android.mk} file, -insert an instruction to import the {@code android/cpufeatures} module. For example: - -
      -$(call import-module,android/cpufeatures)
      -
      - -

      Here is a simple example of an {@code Android.mk} file that imports the {@code cpufeatures} -library:

      - -
      -<project-path>/jni/Android.mk:
      -LOCAL_PATH := $(call my-dir)
      -
      -include $(CLEAR_VARS)
      -LOCAL_MODULE := <your-module-name>
      -LOCAL_SRC_FILES := <your-source-files>
      -LOCAL_STATIC_LIBRARIES := cpufeatures
      -include $(BUILD_SHARED_LIBRARY)
      -
      -$(call import-module,android/cpufeatures)
      -
      -
    6. -
    - -

    Functions

    -

    The {@code cpufeatures} library provides two functions. The first function returns the family to -which the device's CPU belongs. Declare it as follows:

    - -
    -AndroidCpuFamily android_getCpuFamily();
    -
    - -

    The function returns one of the following enums, representing the CPU family/architecture that -the device supports.

    -
      -
    • {@code ANDROID_CPU_FAMILY_ARM}
    • -
    • {@code ANDROID_CPU_FAMILY_X86}
    • -
    • {@code ANDROID_CPU_FAMILY_MIPS}
    • -
    • {@code ANDROID_CPU_FAMILY_ARM64}
    • -
    • {@code ANDROID_CPU_FAMILY_X86_64}
    • -
    • {@code ANDROID_CPU_FAMILY_MIPS64}
    • -
    - -

    For a 32-bit executable on a 64-bit system, this function returns only the 32-bit value.

    - -

    The second function returns the set of optional features that the device's CPU supports. Declare -it as follows: - -

    -uint64_t android_getCpuFeatures();
    -
    - -

    The return value takes the form of a set of bit flags, each flag representing one -CPU-family-specific feature. The rest of this section provides information on features for -the respective families.

    - -

    32-bit ARM CPU family

    - -

    The following flags are available for the 32-bit ARM CPU family:

    -
    -
    {@code ANDROID_CPU_ARM_FEATURE_VFPv2}
    -
    Indicates that the device's CPU supports the VFPv2 instruction set. Most ARMv6 CPUs support -this instruction set.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_ARMv7}
    -
    Indicates that the device's CPU supports the ARMv7-A instruction set as supported by the -armeabi-v7a ABI. This instruction set supports both -Thumb-2 and VFPv3-D16 instructions. This return value also indicates support for the VFPv3 hardware -FPU instruction-set extension.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_VFPv3}
    -
    Indicates that the device's CPU supports the VFPv3 hardware FPU instruction-set extension. -

    This value is equivalent to the {@code VFPv3-D16} instruction set, which provides provides only -16 hardware double-precision FP registers.

    - -
    {@code ANDROID_CPU_ARM_FEATURE_VFP_D32}
    -
    Indicates that the device's CPU supports 32 hardware double-precision FP registers instead of -16. Even when there are 32 hardware double-precision FP registers, there are still only 32 -single-precision registers mapped to the same register banks.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_NEON}
    -
    Indicates that the device's CPU supports the ARM Advanced SIMD (NEON) vector instruction set -extension. Note that ARM mandates that such CPUs also implement VFPv3-D32, which provides 32 -hardware FP registers (shared with the NEON unit).
    - -
    {@code ANDROID_CPU_ARM_FEATURE_VFP_FP16}
    -
    Indicates that the device's CPU supports instructions to perform floating-point operations on -16-bit registers. This feature is part of the VFPv4 specification.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_VFP_FMA}
    -
    Indicates that the device's CPU supports the fused multiply-accumulate extension for the VFP -instruction set. Also part of the VFPv4 specification.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_NEON_FMA}
    -
    Indicates that the device's CPU supports the fused multiply-accumulate extension for the NEON -instruction set. Also part of the VFPv4 specification.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_IDIV_ARM}
    -
    Indicates that the device's CPU supports integer division in ARM mode. Only available on later- -model CPUs, such as Cortex-A15.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2}
    -
    Indicates that the device's CPU supports Integer division in Thumb-2 mode. Only available on -later-model CPUs, such as Cortex-A15.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_iWMMXt}
    -
    Indicates that the device's CPU supports an instruction-set extension that adds MMX registers -and instructions. This feature is only available on a few XScale- based CPUs.
    - -
    {@code ANDROID_CPU_ARM_FEATURE_LDREX_STREX}
    -
    Indicates that the device's CPU supports LDREX and STREX instructions available since ARMv6. -Together, these instructions provide atomic updates on memory with the help of exclusive -monitor.
    -
    - -

    64-bit ARM CPU family

    - -

    The following flags are available for the 64-bit ARM CPU family:

    -
    -
    {@code ANDROID_CPU_ARM64_FEATURE_FP}
    -
    Indicates that the device's CPU has a Floating Point Unit (FPU). All Android ARM64 devices must -support this feature.
    -
    {@code ANDROID_CPU_ARM64_FEATURE_ASIMD}
    -
    Indicates that the device's CPU has an Advanced SIMD (ASIMD) unit. All Android ARM64 devices -must support this feature.
    -
    {@code ANDROID_CPU_ARM64_FEATURE_AES}
    -
    Indicates that the device's CPU supports {@code AES} instructions.
    -
    {@code ANDROID_CPU_ARM64_FEATURE_CRC32}
    -
    Indicates that the device's CPU supports {@code CRC32} instructions.
    -
    {@code ANDROID_CPU_ARM64_FEATURE_SHA1}
    -
    Indicates that the device's CPU supports {@code SHA1} instructions.
    -
    {@code ANDROID_CPU_ARM64_FEATURE_SHA2}
    -
    Indicates that the device's CPU supports {@code SHA2} instructions.
    -
    {@code ANDROID_CPU_ARM64_FEATURE_PMULL}
    -
    Indicates that the device's CPU supports 64-bit {@code PMULL} and {@code PMULL2} -instructions.
    -
    - -

    32-bit x86 CPU family

    - -

    The following flags are available for the 32-bit x86 CPU family.

    -

    -
    {@code ANDROID_CPU_X86_FEATURE_SSSE3}
    -Indicates that the device's CPU supports the SSSE3 instruction extension set.
    - -
    {@code ANDROID_CPU_X86_FEATURE_POPCNT}
    -
    Indicates that the device's CPU supports the {@code POPCNT} instruction.
    - -
    {@code ANDROID_CPU_X86_FEATURE_MOVBE}
    -
    Indicates that the device's CPU supports the {@code MOVBE} instruction. This instruction is -specific to some Intel IA-32 CPUs, such as Atom.
    -
    - -

    {@code android_getCpuFeatures()} returns {@code 0} for CPU families for which there are no -listed extensions.

    - -

    The following function returns the maximum number of CPU cores on the target device:

    - -
    -int  android_getCpuCount(void);
    -
    - -

    MIPS CPU family

    - -
    -
    {@code ANDROID_CPU_MIPS_FEATURE_R6}
    -
    Indicates that the CPU executes MIPS Release 6 instructions natively, and supports obsoleted R1..R5 instructions only via kernel traps.
    - -
    {@code ANDROID_CPU_MIPS_FEATURE_MSA}
    -
    Indicates that the CPU supports MIPS SIMD Architecture instructions.
    -
    - -

    Change History

    -

    For the complete change history of this library, see the comments in -{@code $NDK/sources/android/cpufeatures/cpu-features.c}, where {@code $NDK} is the root of your -NDK installation.

    \ No newline at end of file diff --git a/docs/html/ndk/guides/debug.jd b/docs/html/ndk/guides/debug.jd deleted file mode 100644 index 3c4da3be0af3433a7703700d12e6a5aad0c67a19..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/debug.jd +++ /dev/null @@ -1,11 +0,0 @@ -page.title=Debugging Your Project -@jd:body - -

    After you've built your app, you'll probably need to debug it. This section introduces you to the -NDK's debugging tools.

    - -

    It begins by telling you how to use the -{@code ndk-gdb} tool to debug your code. It closes with an explanation of the -{@code ndk-stack} tool, which helps you use the -ADB logcat tool -as you debug.

    \ No newline at end of file diff --git a/docs/html/ndk/guides/graphics/design-notes.jd b/docs/html/ndk/guides/graphics/design-notes.jd deleted file mode 100644 index 272bd2d14c54b3577209987fd65a3d4bf1e49888..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/graphics/design-notes.jd +++ /dev/null @@ -1,121 +0,0 @@ -page.title=Vulkan Design Guidelines -@jd:body - - - -

    -Vulkan is unlike earlier graphics APIs in that drivers do not perform certain -optimizations, such as pipeline reuse, for apps. Instead, apps using Vulkan must -implement such optimizations themselves. If they do not, they may exhibit worse -performance than apps running OpenGL ES. -

    - -

    -When apps implement these optimizations themselves, they have the potential -to do so more successfully than the driver can, because they have access to -more specific information for a given use case. As a result, skillfully -optimizing an app that uses Vulkan can yield better performance than if the -app were using OpenGL ES. -

    - -

    -This page introduces several optimizations that your Android app can implement -to gain performance boosts from Vulkan. -

    - -

    Apply Display Rotation During Rendering

    - -

    -When the upward-facing direction of an app doesn’t match the orientation of the device’s -display, the compositor rotates the application’s swapchain images so that it -does match. It performs this rotation as it displays the images, which results -in more power consumption—sometimes significantly more—than if it were not -rotating them. -

    - -

    -By contrast, rotating swapchain images while generating them results in -little, if any, additional power consumption. The -{@code VkSurfaceCapabilitiesKHR::currentTransform} field indicates the rotation -that the compositor applies to the window. After an app applies that rotation -during rendering, the app uses the {@code VkSwapchainCreateInfoKHR::preTransform} -field to report that the rotation is complete. -

    - -

    Minimize Render Passes Per Frame

    - -

    -On most mobile GPU architectures, beginning and ending a render pass is an -expensive operation. Your app can improve performance by organizing rendering operations into -as few render passes as possible. -

    - -

    -Different attachment-load and attachment-store ops offer different levels of -performance. For example, if you do not need to preserve the contents of an attachment, you -can use the much faster {@code VK_ATTACHMENT_LOAD_OP_CLEAR} or -{@code VK_ATTACHMENT_LOAD_OP_DONT_CARE} instead of {@code VK_ATTACHMENT_LOAD_OP_LOAD}. Similarly, if -you don't need to write the attachment's final values to memory for later use, you can use -{@code VK_ATTACHMENT_STORE_OP_DONT_CARE} to attain much better performance than -{@code VK_ATTACHMENT_STORE_OP_STORE}. -

    - -

    -Also, in most render passes, your app doesn’t need to load or store the -depth/stencil attachment. In such cases, you can avoid having to allocate physical memory for -the attachment by using the {@code VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT} -flag when creating the attachment image. This bit provides the same benefits as does -{@code glFramebufferDiscard} in OpenGL ES. -

    - -

    Choose Appropriate Memory Types

    - -

    -When allocating device memory, apps must choose a memory type. Memory type -determines how an app can use the memory, and also describes caching and -coherence properties of the memory. Different devices have different memory -types available; different memory types exhibit different performance -characteristics. -

    - -

    -An app can use a simple algorithm to pick the best memory type for a given -use. This algorithm picks the first memory type in the -{@code VkPhysicalDeviceMemoryProperties::memoryTypes} array that meets two criteria: -The memory type must be allowed for the buffer -or image, and must have the minimum properties that the app requires. -

    - -

    -Mobile systems generally don’t have separate physical memory heaps for the -CPU and GPU. On such systems, {@code VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT} is not as -significant as it is on systems that have discrete GPUs with their own, dedicated -memory. An app should not assume this property is required. -

    - -

    Group Descriptor Sets by Frequency

    - -

    -If you have resource bindings that change at different frequencies, use -multiple descriptor sets per pipeline rather than rebinding all resources for -each draw. For example, you can have one set of descriptors for per-scene -bindings, another set for per-material bindings, and a third set for -per-mesh-instance bindings. -

    - -

    -Use immediate constants for the highest-frequency changes, such as changes -executed with each draw call. -

    - diff --git a/docs/html/ndk/guides/graphics/getting-started.jd b/docs/html/ndk/guides/graphics/getting-started.jd deleted file mode 100644 index 0c2d939f1182e64925d9ed710154c358c4fce4ab..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/graphics/getting-started.jd +++ /dev/null @@ -1,201 +0,0 @@ -page.title=Vulkan Setup -@jd:body - - - - -

    -This document explains how to get started with the Vulkan graphics library by downloading, -compiling, and running several sample apps. -

    - -

    -Before beginning, make sure you have the right hardware and platform version prepared. You should -be using one of the following devices, running at least Android N, Developer Preview 2: -

    - -
      -
    • Nexus 6P.
    • -
    • Nexus 5X.
    • -
    • Nexus Player.
    • -
    - -

    -You can confirm your Android version by going to the Settings menu, and -selecting About <device> > Android Version. -Once you’ve confirmed that you have the right hardware and platform version set up, you can -download the necessary software. -

    - -

    Downloading

    - -

    -Before getting started, you must download several tools and other software. -

    - -
      -
    1. If you don’t already have Android Studio, - download it.
    2. - -
    3. Download NDK r12-beta.
    4. - -
    5. Download and install -the Android N-Preview SDK.
    6. - -
    7. (Optional) Build shaderc in NDK r12-beta by navigating to -{@code <ndk-root>/sources/third_party/shaderc/}, -and running the following command: - -
      -../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
      - APP_STL:=c++_shared APP_ABI=all libshaderc_combined
      -
      - -You can specify {@code APP_STL} as {@code gnustl_static}, -{@code gnustl_shared}, {@code c++_static}, -or {@code c++_shared}.
    8. - -
    9. Open a terminal window, and use git to clone the Android Vulkan samples from the -repository in which they reside. - -
      -$ git clone https://github.com/googlesamples/vulkan-basic-samples.git
      -
      -
    10. - -
    11. -Navigate to the {@code LunarGSamples/} directory, which is in the local repository -that you checked out in the previous step. -
    12. - -
    13. Update the gslang source by entering the following command: - -
      -$ ./update_external_sources.sh -s -g
      -
      -
    14. - -
    - - -

    Testing Installation

    - -

    -To confirm that Vulkan is set up properly, you can test it with -the set of Vulkan API samples provided partly for that purpose. Follow these steps to -build and execute these samples: -

    - -
      - - -
    1. (Optional) Build the source by entering the following commands: - -
      -$ cd API-samples
      -$ cmake -DANDROID=ON -DANDROID_ABI=[armeabi-v7a|arm64-v8a| x86|x86_64|all(default)]
      -
      -
    2. - -
    3. -Import the samples into Android Studio. To do so, choose File > -Import -project (Eclipse, ADT, Gradle) and -select the {@code LunarGSamples/API-Samples/android} directory. - -

      You may see an error about missing components or missing SDK version. -Ignore this error message, and follow the installation prompts.

      - -

      After several minutes, the Project pane should -resemble the window shown in Figure 1.

      - - - -

      -Figure 1. Project pane displaying samples after they've been imported. - -

    4. -
    - -

    Compiling Your Project

    - -

    To compile your project, follow these steps:

    - -
      -
    1. Select your project in the Android Studio Project panel.
    2. -
    3. From the Build menu, choose Make Module <module-name> ; or select Build APK to generate APK.
    4. -
    5. Resolve any dependency issues, and then compile. As Figure 2 shows, you can select individual projects to compile by choosing them from the configuration pulldown.
    6. - - - -

      -Figure 2. Selecting an individual project to compile. - -

    - -

    Note: -Additional -tutorial samples illustrate the use of shaders compiled with off-line -compilation integrated into Android Studio. For simplicity, each tutorial -is self-contained, and builds according to standard Android Studio -build procedures. -

    - -

    Running Your Project

    - -

    To run your project, choose an APK to run by choosing Run > Run <project-name>.

    - -

    To debug an APK, choose Run > -Debug <project-name>. For each project, -there’s a Java version and a native (C or C++) version. Run the -native version of the app. For example, for drawcube, -run drawcube-native.

    - -

    Most of the samples have simple functionality, and most stop -automatically after running. The drawcube example is one of -the more visually interesting examples. When you run it, it -should display the image in Figure 3

    . - - - -

    -Figure 3. The successfully compiled program runs and produces a display. -

    - -

    Using the Dynamic Loader

    -

    -The samples use a dynamic loader helper function defined in {@code vulkan_wrapper.h/cpp} to -retrieve Vulkan API pointers using {@code dlopen()} and {@code dlsym()}. It does this rather -than statically linking them with {@code vulkan.so}. -

    - -

    -Using this loader allows the code to link against API level 23 and earlier versions of the platform, which don’t include the {@code vulkan.so} shared library, but can run on devices that support Vulkan API. -

    - -

    -The following snippet shows how to use the dynamic loader. -

    - -
    -#include "vulkan_wrapper.h" // Include Vulkan_wrapper and dynamically load symbols.
    -...
    -// Before any Vulkan API usage,
    -InitVulkan();
    -
    diff --git a/docs/html/ndk/guides/graphics/index.jd b/docs/html/ndk/guides/graphics/index.jd deleted file mode 100644 index cbd4b9ca802cda320f734d7e092d029184132fde..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/graphics/index.jd +++ /dev/null @@ -1,36 +0,0 @@ -page.title=Vulkan Graphics API -@jd:body - - -

    The Android platform includes an Android-specific implementation of the -Vulkan API -specification from the Khronos Group. Vulkan is a -low-overhead, cross-platform API for high-performance, 3D graphics. It provides tools -for creating high-quality, real-time graphics in -applications. Vulkan also provides advantages such as reducing -CPU overhead and providing support for the -SPIR-V Binary -Intermediate language. -

    - -

    -This section begins with information on how to -get started using Vulkan in your -Android app. Next, it provides useful information that you should know about -Vulkan design guidelines -on the Android platform. From there, it explains how -to use Vulkan's shader compilers. -Last, it teaches you how to use -validation layers -to help assure stability in apps using Vulkan. -

    - -

    -For more general information about this cross-platform API specification, see -Khronos's - -Vulkan Overview. -You can also keep up with the latest Vulkan-related developments at the -Vulkan -news page. -

    diff --git a/docs/html/ndk/guides/graphics/shader-compilers.jd b/docs/html/ndk/guides/graphics/shader-compilers.jd deleted file mode 100644 index c51c21c5b7d9971f443d8c6d09368c53925f1dac..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/graphics/shader-compilers.jd +++ /dev/null @@ -1,194 +0,0 @@ -page.title=Vulkan Shader Compilers on Android -@jd:body - - - -

    -A Vulkan app must manage shaders differently from the way an OpenGL ES app does so: -In OpenGL ES, you provide a shader as a set of strings forming the source text of a -GLSL shader program. By contrast, the Vulkan API requires you to provide a shader in -the form of an entry point in a SPIR-V module. -

    - -

    -The NDK includes a runtime library for compiling GLSL into SPIR-V. -The runtime library is the same as the one in the -Shaderc open source project, and use the same -Glslang GLSL reference compiler as a -back end. By default, the Shaderc version of the -compiler assumes you are compiling for Vulkan. After checking whether your code is valid for -Vulkan, the compiler automatically enables the {@code KHR_vulkan_glsl} extension. The Shaderc -version of the compiler also generates Vulkan-compliant SPIR-V code. -

    - -

    -You can choose to compile SPIR-V modules into your Vulkan app during development, a -practice called ahead-of-time, or AOT, compiling. Alternatively, -you can have your app compile them from shipped or procedurally generated shader -source when needed during runtime. This practice is called runtime compiling. -

    - -

    -The rest of this page provides more detail about each practice, and then explains -how to integrate shader compilation into your Vulkan app. -

    - -

    AOT Compilation

    - -

    -For AOT compilation, we recommend the glslc command-line compiler from GLSL to SPIR-V. -This compiler is available from the Shaderc -project.Many of its command-line options are similar to those of GCC and Clang, allowing -you to integrate glslc into build systems easily. -

    - -

    -The glslc tool compiles a single-source file to a SPIR-V module with a single shader -entry point. By default, the output file has the same name as that of the source file, -but with the {@code .spv} extension appended. -

    - -

    -You use filename extensions to tell the glslc tool which graphics shader stage to compile, -or whether a compute shader is being compiled. For information on how to use these filename -extensions, and options you can use with the tool, see - -Shader stage specification in the - -glslc manual. -

    - -

    Runtime Compilation

    - -

    -For JIT compilation of shaders during runtime, the NDK provides the libshaderc library, -which has both C and C++ APIs. -

    - -

    -C++ applications should use the C++ API. We recommend that apps in other languages -use the C API, because the C ABI is lower level, and likely to provide better stability. -

    - -

    -The following example shows how to use the C++ API: -

    - -
    -#include <iostream>
    -#include <string>
    -#include <vector>
    -#include <shaderc/shaderc.hpp>
    -
    -std::vector<uint32_t> compile_file(const std::string& name,
    -                                   shaderc_shader_kind kind,
    -                                   const std::string& data) {
    -  shaderc::Compiler compiler;
    -  shaderc::CompileOptions options;
    -
    -  // Like -DMY_DEFINE=1
    -  options.AddMacroDefinition("MY_DEFINE", "1");
    -
    -  shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(
    -      data.c_str(), data.size(), kind, name.c_str(), options);
    -
    -  if (module.GetCompilationStatus() !=
    -      shaderc_compilation_status_success) {
    -    std::cerr << module.GetErrorMessage();
    -  }
    -
    -  std::vector<uint32_t> result(module.cbegin(), module.cend());
    -  return result;
    -}
    -
    - - - -

    Integrating into Your Projects

    - -

    -You can integrate the Vulkan shader compiler into your app using either the project's -{@code Android.mk} file or Gradle. -

    - -

    Android.mk

    - -

    -Perform the following steps to use your project's {@code Android.mk} -file to integrate the shader compiler. -

    - -
      -
    1. -Include the following lines in your Android.mk file: -
      -include $(CLEAR_VARS)
      -     ...
      -LOCAL_STATIC_LIBRARIES := shaderc
      -     ...
      -include $(BUILD_SHARED_LIBRARY)
      -
      -$(call import-module, third_party/shaderc)
      -
      -
    2. - -
    3. -Set APP_STL to one of {@code c++_static}, {@code c++_shared}, {@code gnustl_static}, -or {@code gnustl_shared}. -
    4. -
    - - - -

    Gradle

    - -
      -
    1. -In a terminal window, navigate to -{@code <ndk_root>/sources/third_party/shaderc/}. -
    2. - -
    3. -Run the following command: - -
      -$ ../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
      -APP_STL:=<stl_version> APP_ABI=all libshaderc_combined
      -
      - -

      -This command places two folders in <ndk_root>/sources/third_party/shaderc/. The directory -structure is as follows: -

      - -
      -include/
      -  shaderc/
      -    shaderc.h
      -    shaderc.hpp
      -libs/
      -  <stl_version>/
      -    {all of the abis}
      -       libshaderc.a
      -
      -
    4. - -
    5. -Add includes and link lines as you normally would for external libraries. -
    6. -

      -The STL that you use to build your program must match the {@code stl} specified in -{@code stl_version}. -Only {@code c++_static}, {@code c++_shared}, {@code gnustl_static}, and -{@code gnustl_shared} are supported. -

      diff --git a/docs/html/ndk/guides/graphics/validation-layer.jd b/docs/html/ndk/guides/graphics/validation-layer.jd deleted file mode 100644 index 1a7d83246d01cfa60ddcae893895d9ba1d65c6f5..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/graphics/validation-layer.jd +++ /dev/null @@ -1,433 +0,0 @@ -page.title=Vulkan Validation Layers on Android -@jd:body - - - -

      -Most explicit graphics APIs do not perform error-checking, because doing so can result in a -performance penalty. Vulkan provides error-checking in a manner that lets you use this feature at -development time, but exclude it from the release build of your app, thus avoiding the penalty when -it matters most. You do this by enabling validation layers. Validation layers intercept -or hook Vulkan entry points for various debug and validation purposes. -

      - -

      -Each validation layer can contain definitions for one or more of these entry points, and -intercepts the entry points for which it contains definitions. When a validation -layer does not define an entry point, the system passes the entry point on to the next -layer. Ultimately, an entry point not defined in any layer reaches the driver, the -base level, unvalidated. -

      - -

      -The Android SDK, NDK, and Vulkan samples include Vulkan validation layers for -use during development. You can hook these validation layers into the graphics stack, allowing -them to report validation issues. This instrumentation allows you to catch and fix misuses -during development. -

      - -

      -This page explains how to: -

        -
      • Integrate NDK's Layer Binaries.
      • -
      • Get source code for validation layers.
      • -
      • Verifying Layer Build.
      • -
      • Enabling Layers in Vulkan Application.
      • - -
      -

      - -

      Add Validation Layers to Project

      - -

      - NDK release 12 and higher includes pre-built validation layer binaries. At - instance and device creation time, when requested by your application, the - Vulkan loader finds them in the APK installed location and loads them. -

      - -

      - To use the pre-built validation layer binaries, either modify the gradle build - configuration of your project or manually add the binaries into the JNI - libraries directory of your project. -

      - - -

      Adding validation layers with Gradle

      - -

      - You can add the validation layer your project using either Andorid Studio's - support for CMake and Ndk-build, or using Studio's experimental plugin for - Gradle. In general, you should use the CMake and Ndk-build configuration. -

      - - -

      - To add the libraries using Android Studio's support for CMake/Ndk-build, - add the following to your project's gradle configuration: -

      - -
      -sourceSets {
      -  main {
      -    jniLibs {
      -      srcDir "${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs"
      -    }
      -  }
      -}
      - -

      - To add the libraries using Android Studio's experimental plugin for Gradle, - add the following to your project's gradle configuration: -

      - -
      -sources {
      -  main {
      -    jniLibs {
      -      source.srcDir "${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs"
      -    }
      -  }
      -}
      - - -

      Adding validation layers to JNI libraries

      - -

      - If configuring your project's gradle build file is not working, you can - manually add the validation layer binaries to your project's JNI libraries - directory by using the following command line options: -

      - -
      -$ cd ${your-app-project-root}
      -$ mkdir -p app/src/main
      -$ cp -fr ${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs app/src/main/
      -
      - - -

      Getting Layer Source

      -

      -If your app needs the latest validation layer, you can pull the latest source from the Khronos Group - -GitHub repository and follow the build instructions there. -

      - -

      Verifying Layer Build

      - -

      -Regardless of whether you build with NDK's prebuilt layers or you build from the latest source code, -the build process produces final file structure like the following: -

      - -
      -src/main/jniLibs/
      -  arm64-v8a/
      -    libVkLayer_core_validation.so
      -    libVkLayer_device_limits.so
      -    libVkLayer_image.so
      -    libVkLayer_object_tracker.so
      -    libVkLayer_parameter_validation.so
      -    libVkLayer_swapchain.so
      -    libVkLayer_threading.so
      -    libVkLayer_unique_objects.so
      -  armeabi-v7a/
      -    libVkLayer_core_validation.so
      -    ...
      -
      - -

      -The following example shows how to verify that your APK contains the validation layers -as expected: -

      - -
      -$ jar -xvf project.apk
      - ...
      - inflated: lib/arm64-v8a/libVkLayer_threading.so
      - inflated: lib/arm64-v8a/libVkLayer_object_tracker.so
      - inflated: lib/arm64-v8a/libVkLayer_swapchain.so
      - inflated: lib/arm64-v8a/libVkLayer_unique_objects.so
      - inflated: lib/arm64-v8a/libVkLayer_parameter_validation.so
      - inflated: lib/arm64-v8a/libVkLayer_image.so
      - inflated: lib/arm64-v8a/libVkLayer_core_validation.so
      - inflated: lib/arm64-v8a/libVkLayer_device_limits.so
      - ...
      -
      - - -

      Enabling Layers

      - -

      The Vulkan API allows an app to enable both instance layers and device layers.

      - -

      Instance layers

      - -

      -A layer that can intercept Vulkan instance-level entry points is called an instance layer. -Instance-level entry points are those with {@code VkInstance} or {@code VkPhysicalDevice} -as the first parameter. -

      - -

      -You can call {@code vkEnumerateInstanceLayerProperties()} to list the available instance layers -and their properties. The system enables instance layers when {@code vkCreateInstace()} executes. -

      - -

      -The following code snippet shows how an app can use the Vulkan API to programmatically enable and -query an instance layer: -

      - -
      -// Get instance layer count using null pointer as last parameter
      -uint32_t instance_layer_present_count = 0;
      -vkEnumerateInstanceLayerProperties(&instance_layer_present_count, nullptr);
      -
      -// Enumerate instance layers with valid pointer in last parameter
      -VkLayerProperties* layer_props =
      -    (VkLayerProperties*)malloc(instance_layer_present_count * sizeof(VkLayerProperties));
      -vkEnumerateInstanceLayerProperties(&instance_layer_present_count, layer_props));
      -
      -// Make sure the desired instance validation layers are available
      -// NOTE:  These are not listed in an arbitrary order.  Threading must be
      -//        first, and unique_objects must be last.  This is the order they
      -//        will be inserted by the loader.
      -const char *instance_layers[] = {
      -    "VK_LAYER_GOOGLE_threading",
      -    "VK_LAYER_LUNARG_parameter_validation",
      -    "VK_LAYER_LUNARG_object_tracker",
      -    "VK_LAYER_LUNARG_core_validation",
      -    "VK_LAYER_LUNARG_device_limits",
      -    "VK_LAYER_LUNARG_image",
      -    "VK_LAYER_LUNARG_swapchain",
      -    "VK_LAYER_GOOGLE_unique_objects"
      -};
      -
      -uint32_t instance_layer_request_count =
      -    sizeof(instance_layers) / sizeof(instance_layers[0]);
      -for (uint32_t i = 0; i < instance_layer_request_count; i++) {
      -    bool found = false;
      -    for (uint32_t j = 0; j < instance_layer_present_count; j++) {
      -        if (strcmp(instance_layers[i], layer_props[j].layerName) == 0) {
      -            found = true;
      -        }
      -    }
      -    if (!found) {
      -        error();
      -    }
      -}
      -
      -// Pass desired instance layers into vkCreateInstance
      -VkInstanceCreateInfo instance_info = {};
      -instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
      -instance_info.enabledLayerCount = instance_layer_request_count;
      -instance_info.ppEnabledLayerNames = instance_layers;
      -...
      -
      - -

      Device layers

      - -

      -A layer that can intercept device-level entry points is called a device layer. Device-level entry -points are those whose first parameter is {@code VkDevice}, {@code VkCommandBuffer}, -or {@code VkQueue}. The list of -device layers to enable is included in the {@code ppEnabledLayerNames} field of the -{@code VkDeviceCreateInfo} -struct that the app passes into {@code vkCreateDevice()}. -

      - -

      -You can call {@code vkEnumerateDeviceLayerProperties} to list the available layers -and their properties. The system enables device layers when it calls {@code vkCreateDevice()}. -

      - -

      -The following code snippet shows how an app can use the Vulkan API to programmatically enable a -device layer. -

      - -
      -
      -// Get device layer count using null as last parameter
      -uint32_t device_layer_present_count = 0;
      -vkEnumerateDeviceLayerProperties(&device_layer_present_count, nullptr);
      -
      -// Enumerate device layers with valid pointer in last parameter
      -VkLayerProperties* layer_props =
      -   (VkLayerProperties *)malloc(device_layer_present_count * sizeof(VkLayerProperties));
      -vkEnumerateDeviceLayerProperties(physical_device, device_layer_present_count, layer_props));
      -
      -// Make sure the desired device validation layers are available
      -// Ensure threading is first and unique_objects is last!
      -const char *device_layers[] = {
      -    "VK_LAYER_GOOGLE_threading",
      -    "VK_LAYER_LUNARG_parameter_validation",
      -    "VK_LAYER_LUNARG_object_tracker",
      -    "VK_LAYER_LUNARG_core_validation",
      -    "VK_LAYER_LUNARG_device_limits",
      -    "VK_LAYER_LUNARG_image",
      -    "VK_LAYER_LUNARG_swapchain",
      -    "VK_LAYER_GOOGLE_unique_objects"
      -};
      -
      -uint32_t device_layer_request_count =
      -   sizeof(device_layers) / sizeof(device_layers[0]);
      -for (uint32_t i = 0; i < device_layer_request_count; i++) {
      -    bool found = false;
      -    for (uint32_t j = 0; j < device_layer_present_count; j++) {
      -        if (strcmp(device_layers[i],
      -           layer_props[j].layerName) == 0) {
      -            found = true;
      -        }
      -    }
      -    if (!found) {
      -        error();
      -    }
      -}
      -
      -// Pass desired device layers into vkCreateDevice
      -VkDeviceCreateInfo device_info = {};
      -device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
      -device_info.enabledLayerCount = device_layer_request_count;
      -device_info.ppEnabledLayerNames = device_layers;
      -...
      -
      - -

      Enabling the Debug Callback

      - -

      -The Debug Report extension {@code VK_EXT_debug_report} allows your application to control -layer behavior when an event occurs.

      - -

      -Before using this extension, you must first make sure that the platform supports it. -The following example shows how to check for debug extension support and -register a callback if the extension is supported. -

      - -
      -// Get the instance extension count
      -uint32_t inst_ext_count = 0;
      -vkEnumerateInstanceExtensionProperties(nullptr, &inst_ext_count, nullptr);
      -
      -// Enumerate the instance extensions
      -VkExtensionProperties* inst_exts =
      -    (VkExtensionProperties *)malloc(inst_ext_count * sizeof(VkExtensionProperties));
      -vkEnumerateInstanceExtensionProperties(nullptr, &inst_ext_count, inst_exts);
      -
      -const char * enabled_inst_exts[16] = {};
      -uint32_t enabled_inst_ext_count = 0;
      -
      -// Make sure the debug report extension is available
      -for (uint32_t i = 0; i < inst_ext_count; i++) {
      -    if (strcmp(inst_exts[i].extensionName,
      -    VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
      -        enabled_inst_exts[enabled_inst_ext_count++] =
      -            VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
      -    }
      -}
      -
      -if (enabled_inst_ext_count == 0)
      -    return;
      -
      -// Pass the instance extensions into vkCreateInstance
      -VkInstanceCreateInfo instance_info = {};
      -instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
      -instance_info.enabledExtensionCount = enabled_inst_ext_count;
      -instance_info.ppEnabledExtensionNames = enabled_inst_exts;
      -
      -PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
      -PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
      -
      -vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)
      -    vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
      -vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)
      -    vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
      -
      -assert(vkCreateDebugReportCallbackEXT);
      -assert(vkDestroyDebugReportCallbackEXT);
      -
      -// Create the debug callback with desired settings
      -VkDebugReportCallbackEXT debugReportCallback;
      -if (vkCreateDebugReportCallbackEXT) {
      -    VkDebugReportCallbackCreateInfoEXT debugReportCallbackCreateInfo;
      -    debugReportCallbackCreateInfo.sType =
      -        VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
      -    debugReportCallbackCreateInfo.pNext = NULL;
      -    debugReportCallbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT |
      -                                          VK_DEBUG_REPORT_WARNING_BIT_EXT |
      -                                          VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
      -    debugReportCallbackCreateInfo.pfnCallback = DebugReportCallback;
      -    debugReportCallbackCreateInfo.pUserData = NULL;
      -
      -    vkCreateDebugReportCallbackEXT(instance, &debugReportCallbackCreateInfo,
      -                                   nullptr, &debugReportCallback);
      -}
      -
      -// Later, when shutting down Vulkan, call the following
      -if (vkDestroyDebugReportCallbackEXT) {
      -   vkDestroyDebugReportCallbackEXT(instance, debugReportCallback, nullptr);
      -}
      -
      -
      - -

      -Once your app has registered and enabled the debug callback, the system routes debugging -messages to a callback that you register. An example of such a callback appears below: -

      - - -
      -#include <android/log.h>
      -
      -static VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
      -                                   VkDebugReportFlagsEXT msgFlags,
      -                                   VkDebugReportObjectTypeEXT objType,
      -                                   uint64_t srcObject, size_t location,
      -                                   int32_t msgCode, const char * pLayerPrefix,
      -                                   const char * pMsg, void * pUserData )
      -{
      -   if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
      -       __android_log_print(ANDROID_LOG_ERROR,
      -                           "AppName",
      -                           "ERROR: [%s] Code %i : %s",
      -                           pLayerPrefix, msgCode, pMsg);
      -   } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
      -       __android_log_print(ANDROID_LOG_WARN,
      -                           "AppName",
      -                           "WARNING: [%s] Code %i : %s",
      -                           pLayerPrefix, msgCode, pMsg);
      -   } else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
      -       __android_log_print(ANDROID_LOG_WARN,
      -                           "AppName",
      -                           "PERFORMANCE WARNING: [%s] Code %i : %s",
      -                           pLayerPrefix, msgCode, pMsg);
      -   } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
      -       __android_log_print(ANDROID_LOG_INFO,
      -                           "AppName", "INFO: [%s] Code %i : %s",
      -                           pLayerPrefix, msgCode, pMsg);
      -   } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
      -       __android_log_print(ANDROID_LOG_VERBOSE,
      -                           "AppName", "DEBUG: [%s] Code %i : %s",
      -                           pLayerPrefix, msgCode, pMsg);
      -   }
      -
      -   // Returning false tells the layer not to stop when the event occurs, so
      -   // they see the same behavior with and without validation layers enabled.
      -   return VK_FALSE;
      -}
      -
      - - - diff --git a/docs/html/ndk/guides/guides_toc.cs b/docs/html/ndk/guides/guides_toc.cs deleted file mode 100644 index 09b2a120fcaa93b5b9ee8b29d907266a1c4c2c00..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/guides_toc.cs +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - diff --git a/docs/html/ndk/guides/images/NDK_build_string.png b/docs/html/ndk/guides/images/NDK_build_string.png deleted file mode 100644 index 338378bca6f0e6feeba5d4e9674701fd6aae1f08..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/guides/images/NDK_build_string.png and /dev/null differ diff --git a/docs/html/ndk/guides/images/NDK_build_string@2x.png b/docs/html/ndk/guides/images/NDK_build_string@2x.png deleted file mode 100644 index 5ba3ce3baf66f707ede87b390e0e1f551825a238..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/guides/images/NDK_build_string@2x.png and /dev/null differ diff --git a/docs/html/ndk/guides/images/config-pulldown.png b/docs/html/ndk/guides/images/config-pulldown.png deleted file mode 100644 index 5af0870a56babbef94bdcfdf7d6b722e89df7426..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/guides/images/config-pulldown.png and /dev/null differ diff --git a/docs/html/ndk/guides/images/drawcube-output.png b/docs/html/ndk/guides/images/drawcube-output.png deleted file mode 100644 index 3b7f775fc10c309474dc116ec6303e953b819d52..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/guides/images/drawcube-output.png and /dev/null differ diff --git a/docs/html/ndk/guides/images/project-pane.png b/docs/html/ndk/guides/images/project-pane.png deleted file mode 100644 index f6d624bacd4c49b2f98c3480276a8d78c490fd83..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/guides/images/project-pane.png and /dev/null differ diff --git a/docs/html/ndk/guides/images/verification_screen.png b/docs/html/ndk/guides/images/verification_screen.png deleted file mode 100644 index 91858baa850cd6386d68f42de3a4876c5e674663..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/guides/images/verification_screen.png and /dev/null differ diff --git a/docs/html/ndk/guides/images/verification_screen@2x.png b/docs/html/ndk/guides/images/verification_screen@2x.png deleted file mode 100644 index 0d666c9d02b3fcd37e04b7b4418f87a40af9ce7b..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/guides/images/verification_screen@2x.png and /dev/null differ diff --git a/docs/html/ndk/guides/index.jd b/docs/html/ndk/guides/index.jd deleted file mode 100644 index 465ce139b6e5bb4ae1972978960775449cefdc2f..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/index.jd +++ /dev/null @@ -1,25 +0,0 @@ -page.title=Getting Started with the NDK -@jd:body - -

      The Native Development Kit (NDK) is a set of tools that allow you to leverage C and -C++ code in your Android apps. You can use it either to build from your own source code, or to take -advantage of existing prebuilt libraries.

      - -

      The NDK is not appropriate for most novice Android programmers, and has little value for many -types of Android apps. It is often not worth the additional complexity it inevitably brings to the -development process. However, it can be useful in cases in which you need to:

      - -
        -
      • Squeeze extra performance out of a device for computationally intensive applications like - games or physics simulations.
      • -
      • Reuse your own or other developers' C or C++ libraries.
      • -
      - -

      This guide gives you the information you need to get up and running with the NDK. It starts by -explaining the concepts underpinning the NDK, and -how to set it up. Next, it continues with information -about targeting different hardware platforms in your -builds. Then, it explains how to use -the NDK to build and -debug your app. Finally, it discusses how to use your -own and other prebuilt libraries.

      diff --git a/docs/html/ndk/guides/libs.jd b/docs/html/ndk/guides/libs.jd deleted file mode 100644 index ea607de8e8647167b0e1aa3b01caf255699b1f4f..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/libs.jd +++ /dev/null @@ -1,13 +0,0 @@ -page.title=Using Existing Libraries -@jd:body - -

      This section discusses the use of existing libraries–both your own, and those that the NDK -provides.

      - -

      It begins by telling you how to use your own -prebuilt libraries. Then, it explains the -C++ helper runtimes available with the NDK, and how to use them. Finally, it provides -information on the other libraries that the NDK provides, such -as OpenGL ES and -OpenSL ES, and the minimum Android API levels -required to support those libraries.

      \ No newline at end of file diff --git a/docs/html/ndk/guides/mips.jd b/docs/html/ndk/guides/mips.jd deleted file mode 100755 index d104ffec7ee6828feed1ad85c15bda06bbfc0152..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/mips.jd +++ /dev/null @@ -1,43 +0,0 @@ -page.title=MIPS Support -@jd:body - -
      -
      -

      On this page

      - -
        -
      1. Overview
      2. -
      3. Compatibility
      4. -
      -
      -
      - -

      The NDK supports the {@code mips} ABI, which allows native code to run on Android-based devices -that have CPUs supporting the MIPS32 instruction set.

      - -

      Overview

      -

      To generate MIPS machine code, include {@code mips} in your -{@code Application.mk} file's -{@code APP_ABI} definition. For example:

      - -
      -APP_ABI := mips
      -
      - -

      For more information about defining the {@code APP_ABI} variable, see -{@code Application.mk}.

      - -

      The build system places generated libraries into {@code $PROJECT/libs/mips/}, where -{@code $PROJECT} represents your project's root directory, and embeds them in your APK under -the {@code /lib/mips/} directory.

      - -

      The Android package manager extracts these libraries when installing your APK on a compatible -MIPS-based device, placing them under your app's private data directory.

      - -

      In the Google Play store, the server filters applications so that a consumer sees only the native -libraries that run on the CPU powering his or her device.

      - -

      Compatibility

      -

      MIPS support requires, at minimum, Android 2.3 (Android API level 9). If your project files -target an older API level, but include MIPS as a targeted platform, the NDK build script -automatically selects the right set of native platform headers/libraries for you.

      diff --git a/docs/html/ndk/guides/ndk-build.jd b/docs/html/ndk/guides/ndk-build.jd deleted file mode 100755 index e653bf50420e1a7a90f6c059d5578038dcb709be..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/ndk-build.jd +++ /dev/null @@ -1,168 +0,0 @@ -page.title=ndk-build -@jd:body - -
    -
    - - -

    The {@code ndk-build} file is a shell script introduced in Android NDK r4. Its purpose -is to invoke the right NDK build script. - -

    Internals

    - -

    Running the {@code ndk-build} script is equivalent to running the following command:

    - -
    -$GNUMAKE -f <ndk>/build/core/build-local.mk
    -<parameters>
    -
    - -

    $GNUMAKE points to GNU Make 3.81 or later, and -<ndk> points to your NDK installation directory. You can use -this information to invoke ndk-build from other shell scripts, or even your own -make files.

    - -

    Invoking from the Command Line

    -

    The {@code ndk-build} file lives in the top level the NDK installation directory. To run it -from the command line, invoke it while in or under your application project directory. -For example:

    - -
    -cd <project>
    -$ <ndk>/ndk-build
    -
    - -

    In this example, <project> points to your -project’s root directory, and <ndk> is the directory where -you installed the NDK.

    - -

    -

    Options

    -

    All parameters to ndk-build are passed directly to the underlying GNU {@code make} -command that runs the NDK build scripts. Combine ndk-build and -options in the form ndk-build <option>. For example:

    - -
    -$ ndk-build clean
    -
    - -

    The following options are available:

    -
    -
    {@code clean}
    -
    Remove any previously generated binaries.
    -
    {@code V=1}
    -
    Launch build, and display build commands.
    -
    {@code -B}
    -
    Force a complete rebuild.
    -
    {@code -B V=1}
    -
    Force a complete rebuild, and display build commands.
    -
    {@code NDK_LOG=1} -
    Display internal NDK log messages (used for debugging the NDK itself).
    -
    {@code NDK_DEBUG=1}
    -
    Force a debuggable build (see Table 1).
    -
    {@code NDK_DEBUG=0}
    -
    Force a release build (see Table 1).
    -
    {@code NDK_HOST_32BIT=1}
    -
    Always use the toolchain in 32-bit mode (see 64-bit and 32-bit - Toolchains).
    -
    {@code NDK_APPLICATION_MK=}
    -
    Build, using a specific Application.mk file pointed to by the - {@code NDK_APPLICATION_MK} variable.
    -
    {@code -C }
    -
    Build the native code for the project path located at {@code }. Useful if you - don't want to {@code cd} to it in your terminal.
    -
    - -

    -

    Debuggable versus Release builds

    -

    Use the NDK_DEBUG option and, in certain cases, -{@code AndroidManifest.xml} to specify debug or release build, -optimization-related behavior, and inclusion of symbols. Table 1 shows the -results of each possible combination of settings.

    -

    Table 1. Results of NDK_DEBUG (command line) and -android:debuggable (manifest) combinations.

    - - - - - - - -
    NDK_DEBUG=0 NDK_DEBUG=1NDK_DEBUG not specified -
    android:debuggble="true" Debug; Symbols; Optimized*1 -Debug; Symbols; Not optimized*2 (same as NDK_DEBUG=1) -
    android:debuggable="false"Release; Symbols; Optimized -Release; Symbols; Not optimizedRelease; No symbols; -Optimized*3
    -*1: Useful for profiling.
    -*2: Default for running {@code ndk-gdb}.
    -*3: Default mode.
    -
    -

    Note: {@code NDK_DEBUG=0} is the equivalent of -{@code APP_OPTIM=release}, and complies with the GCC {@code -O2} option. {@code NDK_DEBUG=1} is the -equivalent of {@code APP_OPTIM=debug} in {@code Application.mk}, and complies with the GCC -{@code -O0} option. For more information about {@code APP_OPTIM}, see -Application.mk.

    -

    The syntax on the command line is, for example:

    - -
    -$ ndk-build NDK_DEBUG=1
    -
    - -

    If you are using build tools from prior to SDK r8, you must also modify your -{@code AndroidManifest.xml} file to specify debug mode. The syntax for doing so resembles the -following:

    - -
    <application android:label="@string/app_name"
    -android:debuggable="true">
    -
    - -From SDK r8 onward, you do not need to touch {@code AndroidManifest.xml}. Building a debug package -(e.g. with ant debug or the corresponding option of the ADT plugin) causes the tool automatically to -pick the native debug files generated with {@code NDK_DEBUG=1}. - - -

    64-Bit and 32-Bit Toolchains

    -

    Some toolchains come with both 64-bit and 32-bit versions. For example, -directories {@code /toolchain//prebuilt/} and -{@code /prebuilt/} may contain both {@code linux-x86} and -{@code linux-x86_64} folders for Linux tools in 32-bit and 64-bit modes, -respectively. The ndk-build script automatically chooses a 64-bit version of -the toolchain if the host OS supports it. You can force the use of a 32-bit -toolchain by using {@code NDK_HOST_32BIT=1} either in your environment or -on the ndk-build command line.

    -

    Note that 64-bit tools utilize host resources better (for instance, they are faster, and handle -larger programs), and they can still generate 32-bit binaries for Android.

    - -

    Requirements

    -

    You need GNU Make 3.81 or later to use ndk-build or the NDK in general. -The build scripts will detect a non-compliant Make tool, and generate an error -message.

    -

    If you have GNU Make 3.81 installed, but the default make -command doesn’t launch it, define {@code GNUMAKE} in your environment to point to it -before launching ndk-build. For example:

    - -
    -$ export GNUMAKE=/usr/local/bin/gmake
    -$ ndk-build
    -
    - -

    You can override other host prebuilt tools in {@code $NDK/prebuilt//bin/} -with the following environment variables:

    - -
    -$ export NDK_HOST_AWK=<path-to-awk>
    -$ export NDK_HOST_ECHO=<path-to-echo>
    -$ export NDK_HOST_CMP=<path-to-cmp>
    -
    diff --git a/docs/html/ndk/guides/ndk-gdb.jd b/docs/html/ndk/guides/ndk-gdb.jd deleted file mode 100755 index 1a990f0b6c8ae4902d0771d9491af75821fc73cc..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/ndk-gdb.jd +++ /dev/null @@ -1,231 +0,0 @@ -page.title=ndk-gdb -@jd:body - -
    -
    -

    On this page

    - -
      -
    1. Requirements
    2. -
    3. Usage
    4. -
    5. Thread Support
    6. -
    -
    -
    - -

    The NDK includes a helper shell script named {@code ndk-gdb} to easily launch a native debugging - session for your NDK-generated machine code.

    - -

    Requirements

    - -

    For native debugging to work, you must follow these requirements:

    - -
      -
    • Build your app using the {@code ndk-build} script. The {@code ndk-gdb} script -does not support using the legacy {@code make APP=} method to build.

    • -
    • Enable app debugging in your {@code AndroidManifest.xml} file by including an -{@code } element that sets the {@code android:debuggable} attribute to {@code -true}.
    • -
    • Build your app to run on Android 2.2 (Android API level 8) or higher.
    • -
    • Debug on a device or emulator running Android 2.2 or higher. - For debugging purposes, the target -API level that you declare in your {@code AndroidManifest.xml} file does not matter.
    • -
    • Develop your app in a Unix shell. On Windows, use Cygwin -or the experimental {@code ndk-gdb-py} Python -implementation.
    • -
    • Use GNU Make 3.81 or higher.
    - -

    Usage

    - To invoke the {@code ndk-gdb} script, change into the application directory or any directory under - it. For example:

    - -
    -cd $PROJECT
    -$NDK/ndk-gdb
    -
    - -

    Here, {@code $PROJECT} points to your project's root directory, and {@code $NDK} points to your -NDK installation path.

    - -

    When you invoke {@code ndk-gdb}, it configures the session to look for your source files -and symbol/debug versions of your generated native libraries. On successfully attaching to your -application process, {@code ndk-gdb} outputs a long series of error messages, noting that it cannot -find various system libraries. This is normal, because your host machine does not contain -symbol/debug versions of these libraries on your target device. You can safely ignore these -messages.

    - -

    Next, {@code ndk-gdb} displays a normal GDB prompt.

    - -

    You interact with {@code ndk-gdb} in the same way as you would with GNU GDB. For example, you can -use {@code b } to set breakpoints, and {@code c} (for "continue") to -resume execution. For a comprehensive list of commands, see the -GDB manual.

    - -

    Note that when you quit the GDB prompt, the application process that you're debugging stops. This -behavior is a gdb limitation.

    - -

    {@code ndk-gdb} handles many error conditions, and displays an informative error message if it -finds a problem. these checks include making sure that the following conditions are satisfied:

    - -
      -
    • Checks that ADB is in your path.
    • -
    • Checks that your application is declared debuggable in its manifest.
    • -
    • Checks that, on the device, the installed application with the same package name is also -debuggable.
    • -
    - -

    By default, {@code ndk-gdb} searches for an already-running application process, and displays an -error if it doesn't find one. You can, however, use the {@code --start} or -{@code --launch=} option to automatically start your activity before the debugging -session. For more information, see Options.

    - - -

    Options

    -

    To see a complete list of options, type {@code ndk-gdb --help} on the command line. Table 1 -shows a number of the more commonly used ones, along with brief descriptions.

    - -

    - Table 1. Common ndk-gdb options and their descriptions.

    - - - - - - - - - - - - - - - - - - - - - -

    Starting {@code ndk-gdb} with this option specified launches the first launchable activity listed -in your application manifest. Use {@code --launch=} to start the next launchable -activity. To dump the list of launchable activities, run {@code --launch-list} from the command -line.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    OptionDescription>
    {@code --verbose}

    This option tells the build system to print verbose information about the native-debugging -session setup. It is necessary only for debugging problems when the debugger can't connect to the -app, and the error messages that {@code ndk-gdb} displays are not enough.

    {@code --force}By default, {@code ndk-gdb} aborts if it finds that another native debugging session is already - running on the same device. This option kills the other session, and replaces it with a new one. - Note that this option does not kill the actual app being debugged, which you must kill - separately.
    {@code --start}

    When you start {@code ndk-gdb}, it tries by default to attach to an existing running instance of -your app on the target device. You can override this default behavior by using {@code --start} to -explicitly launch the application on the target device before the debugging session.

    {@code --launch=}

    This option is similar to {@code --start}, except that it allows you to start a specific - activity from your application. This feature is only useful if your manifest defines multiple - launchable activities.

    {@code --launch-list}

    This convenience option prints the list of all launchable activity names found in your - app manifest. {@code --start} uses the first activity name.

    {@code --project=}This option specifies the app project directory. It is useful if you want to launch the - script without first having to change to the project directory.

    {@code --port=}

    By default, {@code ndk-gdb} uses local TCP port 5039 to communicate with the app it - is debugging on the target device. Using a different port allows you to natively debug programs - running on different devices or emulators connected to the same host machine.

    {@code --adb=}

    This option specifies the adb -tool executable. It is only necessary if you have not set your path to include that executable.

    -
    -
  • {@code -d}
  • -
  • {@code -e}
  • -
  • {@code -s }
  • These flags are similar to the adb commands with the same names. Set these flags if you have -several devices or emulators connected to your host machine. Their meanings are as follows:

    -
    -
    {@code -d}
    -
    Connect to a single physical device.
    -
    {@code -e}
    -
    Connect to a single emulator device.
    -
    {@code -s }
    -
    Connect to a specific device or emulator. Here, {@code } is the device's name - as listed by the {@code adb devices} command.
    -
    - -

    Alternatively, you can define the {@code ADB_SERIAL} environment variable to list a specific -device, without the need for a specific option.

    -
  • {@code --exec=}
  • -
  • {@code -x }
  • -

    This option tells {@code ndk-gdb} to run the GDB initialization commands found in -{@code } after connecting to the process it is debugging. This is a useful feature if -you want to do something repeatedly, such as setting up a list of breakpoints, and then resuming -execution automatically.

    {@code --nowait}

    Disable pausing the Java code until GDB connects. Passing this option may cause the debugger - to miss early breakpoints.

    -
    {@code --tui} -{@code -t}

    Enable Text User Interface if it is available.

    {@code --gnumake-flag=}

    This option is an extra flag (or flags) to pass to the -{@code ndk-build} system when -querying it for project information. You can use multiple instances of this option in the -same command.

    {@code --stdcxx-py-pr={auto|none|gnustdcxx[-GCCVER]|stlport}}

    Use specified Python pretty-printers for displaying types in the Standard C++ Library. - {@code auto} mode works by looking at the {@code .so} files for a {@code libstdc++} library, - and as such only works for a shared library. When linking statically to a {@code libstdc++} library, - you must specify the required printers. The default is {@code none}.

    - -

    Note: The final three options in this table are only for the -Python version of {@code ndk-gdb}.

    - -

    Thread Support

    -

    If your app runs on a platform older than Android 2.3 (API level 9), {@code ndk-gdb} -cannot debug native threads properly. The debugger can only debug the main thread, abd completely -ignores the execution of other threads.

    - -

    If you place a breakpoint on a function executed on a non-main thread, the program exits, and -GDB displays the following message:

    - -
    -Program terminated with signal SIGTRAP, Trace/breakpoint trap.
    -      The program no longer exists.
    -
    diff --git a/docs/html/ndk/guides/ndk-stack.jd b/docs/html/ndk/guides/ndk-stack.jd deleted file mode 100644 index 45d433cbaeb96da5240a3a7e9d2e9bc38b9e510e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/ndk-stack.jd +++ /dev/null @@ -1,86 +0,0 @@ -page.title=ndk-stack -@jd:body - -
    -
    -

    On this page

    - -
      -
    1. Usage
    2. -
    -
    -
    - -

    The {@code ndk-stack} tool allows you to filter stack traces as they appear in the -output of {@code adb logcat}. It also replaces any -address inside a shared library with the corresponding -{@code :} values from your source code, making issues easier -to pinpoint.

    - -

    For example, it translates something like:

    - -
    -I/DEBUG   (   31): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    -I/DEBUG   (   31): Build fingerprint: 'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys'
    -I/DEBUG   (   31): pid: 351, tid: 351  %gt;%gt;%gt; /data/local/ndk-tests/crasher <<<
    -I/DEBUG   (   31): signal 11 (SIGSEGV), fault addr 0d9f00d8
    -I/DEBUG   (   31):  r0 0000af88  r1 0000a008  r2 baadf00d  r3 0d9f00d8
    -I/DEBUG   (   31):  r4 00000004  r5 0000a008  r6 0000af88  r7 00013c44
    -I/DEBUG   (   31):  r8 00000000  r9 00000000  10 00000000  fp 00000000
    -I/DEBUG   (   31):  ip 0000959c  sp be956cc8  lr 00008403  pc 0000841e  cpsr 60000030
    -I/DEBUG   (   31):          #00  pc 0000841e  /data/local/ndk-tests/crasher
    -I/DEBUG   (   31):          #01  pc 000083fe  /data/local/ndk-tests/crasher
    -I/DEBUG   (   31):          #02  pc 000083f6  /data/local/ndk-tests/crasher
    -I/DEBUG   (   31):          #03  pc 000191ac  /system/lib/libc.so
    -I/DEBUG   (   31):          #04  pc 000083ea  /data/local/ndk-tests/crasher
    -I/DEBUG   (   31):          #05  pc 00008458  /data/local/ndk-tests/crasher
    -I/DEBUG   (   31):          #06  pc 0000d362  /system/lib/libc.so
    -I/DEBUG   (   31):
    -
    - -

    into the more readable output:

    - -
    -********** Crash dump: **********
    -Build fingerprint: 'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys'
    -pid: 351, tid: 351  >>> /data/local/ndk-tests/crasher <<<
    -signal 11 (SIGSEGV), fault addr 0d9f00d8
    -Stack frame #00  pc 0000841e  /data/local/ndk-tests/crasher : Routine zoo in /tmp/foo/crasher/jni/zoo.c:13
    -Stack frame #01  pc 000083fe  /data/local/ndk-tests/crasher : Routine bar in /tmp/foo/crasher/jni/bar.c:5
    -Stack frame #02  pc 000083f6  /data/local/ndk-tests/crasher : Routine my_comparison in /tmp/foo/crasher/jni/foo.c:9
    -Stack frame #03  pc 000191ac  /system/lib/libc.so
    -Stack frame #04  pc 000083ea  /data/local/ndk-tests/crasher : Routine foo in /tmp/foo/crasher/jni/foo.c:14
    -Stack frame #05  pc 00008458  /data/local/ndk-tests/crasher : Routine main in /tmp/foo/crasher/jni/main.c:19
    -Stack frame #06  pc 0000d362  /system/lib/libc.so
    -
    - -

    Usage

    -

    To use {@code ndk-stack}, you first need a directory containing symbolic versions of your app's -shared libraries. If you use the NDK build system ({@code ndk-build}), these shared-library -files reside under {@code $PROJECT_PATH/obj/local/}, where {@code } represents -your device's ABI. By default, the system uses the {@code armeabi} ABI.

    - -

    There are two ways to use the tool. You can feed the logcat text as direct input to the program. -For example:

    - -
    -adb logcat | $NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi
    -
    - -

    You can also use the {@code -dump} option to specify the logcat as an input file. For example: -

    - -
    -adb logcat > /tmp/foo.txt
    -$NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi -dump foo.txt
    -
    - -

    When it begins parsing the logcat output, the tool looks for an initial line of asterisks. -For example:

    - -
    -*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    -
    - -

    Note: When copy/pasting traces, don't forget this line, or -{@code ndk-stack} won't work correctly.

    \ No newline at end of file diff --git a/docs/html/ndk/guides/prebuilts.jd b/docs/html/ndk/guides/prebuilts.jd deleted file mode 100644 index 4cb18198aed8262ba1097f06330ed6580766ef08..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/prebuilts.jd +++ /dev/null @@ -1,145 +0,0 @@ -page.title=Using Prebuilt Libraries -@jd:body - - - -

    The NDK supports the use of prebuilt libraries, both static and shared. There are two principal -use cases for this functionality:

    - -
      -
    • Distributing your own libraries to third-party NDK developers without distributing your - sources.
    • -
    • Using a prebuilt version of your own libraries to speed up your build.
    • -
    - -

    This page explains how to use prebuilt libraries.

    - -

    Declaring a Prebuilt Library

    -

    You must declare each prebuilt library you use as a single independent module. To do - so, perform the following steps: - -

      -
    1. Give the module a name. This name does not need to be the same as that of the prebuilt - library, itself.
    2. -
    3. In the module's {@code Android.mk} - file, assign to {@code LOCAL_SRC_FILES} the path to the prebuilt library you are providing. - Specify the path relative to the value of your {@code LOCAL_PATH} variable.

      -

      Note: You must make sure to select the version of your prebuilt - library appropriate to your target ABI. For more information on ensuring library support for - ABIs, see Selecting ABIs for Prebuilt Libraries.

    4. -
    5. Include {@code PREBUILT_SHARED_LIBRARY} or {@code PREBUILT_STATIC_LIBRARY}, depending on - whether you are using a shared ({@code .so}) or static ({@code .a}) library.
    6. -
    - -

    Here is a trivial example that assumes the prebuilt library {@code libfoo.so} resides in - the same directory as the {@code Android.mk} - file that describes it.

    - -
    -LOCAL_PATH := $(call my-dir)
    -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := foo-prebuilt
    -LOCAL_SRC_FILES := libfoo.so
    -include $(PREBUILT_SHARED_LIBRARY)
    -
    - -

    In this example, the name of the module is the same as that of the prebuilt library.

    - -

    The build system places a copy of your prebuilt shared library into {@code $PROJECT/obj/local}, -and another copy, stripped of debug information, into {@code $PROJECT/libs/}. Here, -{@code $PROJECT} is the root directory of your project.

    - -

    Referencing the Prebuilt Library from Other Modules

    -

    To reference a prebuilt library from other modules, specify its name as the value -of the {@code LOCAL_STATIC_LIBRARIES} or {@code LOCAL_SHARED_LIBRARIES} variable in the -{@code Android.mk} files associated with those -other modules.

    - -

    For example, the description of a module using {@code libfoo.so} might be as follows:

    - -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := foo-user
    -LOCAL_SRC_FILES := foo-user.c
    -LOCAL_SHARED_LIBRARIES := foo-prebuilt
    -include $(BUILD_SHARED_LIBRARY)
    -
    - -

    Here, {@code LOCAL_MODULE} is the name of the module referring to the prebuilt; {@code - LOCAL_SHARED_LIBRARIES} is the name of the prebuilt, itself.

    - -

    Exporting Headers for Prebuilt Libraries

    -

    The code in {@code foo-user.c} depends on specific declarations that normally -reside in a header file, such as {@code foo.h}, distributed with the prebuilt library. -For example, {@code foo-user.c} might have a line like the following:

    - -
    -#include <foo.h>
    -
    - -

    In such a case, you need to provide the header and its include path to the compiler when you -build the {@code foo-user} module. A simple way to accomplish this task is to use exports in the -prebuilt module definition. For example, as long as header {@code foo.h} is located under the -{@code include} directory associated with the prebuilt module, you can declare it as follows:

    - -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := foo-prebuilt
    -LOCAL_SRC_FILES := libfoo.so
    -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    -include $(PREBUILT_SHARED_LIBRARY)
    -
    - -

    The {@code LOCAL_EXPORT_C_INCLUDES} definition here ensures that the build system -exports the path to the prebuilt library's {@code include} directory, prepending that path onto the -value of the {@code LOCAL_C_INCLUDES} for the module dependent on it.

    - -

    This operation allows the build system to find the necessary headers.

    - -

    Debugging Prebuilt Libraries

    -

    We recommend that you provide prebuilt shared libraries containing debug symbols. The NDK build -system always strips the symbols from the version of the library that it installs into -{@code $PROJECT/libs//}, but you can use the debug version for debugging with -{@code ndk-gdb}.

    - -

    Selecting ABIs for Prebuilt Libraries

    -

    You must make sure to select the right version of your prebuilt shared library for your targeted -ABI. The -{@code TARGET_ARCH_ABI} variable in the -{@code Android.mk} file can point the build system at the appropriate version of the library. -

    - -

    For example, assume that your project contains two versions of library {@code libfoo.so}:

    - -
    -armeabi/libfoo.so
    -x86/libfoo.so
    -
    - -

    The following snippet shows how to use {@code TARGET_ARCH_ABI} so that the build system selects - the appropriate version of the library:

    - -
    -include $(CLEAR_VARS)
    -LOCAL_MODULE := foo-prebuilt
    -LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfoo.so
    -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    -include $(PREBUILT_SHARED_LIBRARY)
    -
    - -

    If you have specified {@code armeabi} as the value of {@code TARGET_ARCH_ABI}, the build system -uses the version of {@code libfoo.so} located in the {@code armeabi} directory. If you have -specified {@code x86} as the value {@code TARGET_ARCH_ABI}, the build system uses the version in the -{@code x86} directory.

    diff --git a/docs/html/ndk/guides/sample.jd b/docs/html/ndk/guides/sample.jd deleted file mode 100644 index 18ca0b82a0b0573e296677533aff62dcfa3edb78..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/sample.jd +++ /dev/null @@ -1,11 +0,0 @@ -page.title=Sample Walkthroughs -@jd:body - -
    -

    This section explains several of the sample apps provided with the NDK. It assumes that you already have a working knowledge of programming in Java and native code, and focuses on issues particular to working with the NDK.

    -

    It discusses the following samples:

    -
      -
    • hello-jni: A very basic app that illustrates core workings of the NDK.
    • -
    • native-activity: An app that shows the fundamentals of how to construct a purely native app. It places particular emphasis on the android_native_app_glue library.
    • -
    • Teapot: A simple OpenGL demo, showcasing the ndk_helper class.
    • -
    \ No newline at end of file diff --git a/docs/html/ndk/guides/setup.jd b/docs/html/ndk/guides/setup.jd deleted file mode 100644 index d3ace07a1c4b1c7fa21ab3e78c5af52007da3241..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/setup.jd +++ /dev/null @@ -1,93 +0,0 @@ -page.title=Setup -@jd:body - - -
    -
    -

    On this page

    - -
      -
    1. Installation
    2. -
    3. Configuring Eclipse
    4. -
    5. Verification
    6. -
    - - -
    -
    - - -
    -

    This document explains how to:

    -
      -
    • Get and install the NDK.
    • -
    • Configure your system and the Eclipse and the Android Development Tool -(ADT) for use with it.
    • -
    • Verify, using a simple sample, that everything is working as expected. -
    • -
    -

    This document assumes that you are already familiar with Java-based Android development. For more -information on that topic, see the -Android developer site.

    - -

    Installation

    -

    To install and configure the NDK, follow these steps:

    -
      -
    1. Get and install the Android SDK.
    2. -
    3. Download the NDK, -making sure to download the correct version for your development platform. You may place the -unzipped directory anywhere on your local drive.
    4. -
    5. Update your {@code PATH} environment variable with the location of the directory that -contains the NDK.
    6. -
    - - -

    Configuring Eclipse

    -

    Eclipse must know where the NDK is in order to use it when building your app. Follow these steps -to set the location of the NDK.

    -
      -
    1. Launch Eclipse, which is installed as part of the Android SDK.
    2. -
    3. Open Window > Preferences.
    4. -
    5. In the pane on the left side of the Preferences window, select Android. -The Android section expands, revealing a number of subsections.
    6. -
    7. Select NDK. In the pane on the right side of the Preferences window, browse to -the directory that contains the NDK.
    8. -
    9. Click OK to return to the Package Explorer display.
    10. -
    - -

    Verification

    -

    Eclipse

    -

    To confirm that you have installed the NDK, set it up correctly, and properly configured Eclipse, -follow these steps:

    -
      -
    1. Import the hello-jni sample from {@code /samples/}, as you would any other Android -project.
    2. -
    3. In the Project Explorer pane, right-click the project name (HelloJni). A -context menu appears.
    4. -
    5. From the context menu, select Android Tools > Add Native Support. The -Add Android Native Support window appears.
    6. -
    7. Accept the default library name (“hello-jni”), and click Finish.
    8. -
    9. Build and execute the application.
    10. -
    -

    Command line

    -

    Follow these steps to build from the command line:

    -
      -
    1. Change to the root directory of your project.
    2. -
    3. Execute ndk-build to build the native component of your app. do this by -typing {@code ndk-build} at the command prompt.
    4. -
    5. Build and install your project as you would a regular Android app written in Java. For more -information, see -Building and Running and -Building and Running -from the Command Line.
    6. -
    - -

    If you have successfully installed and configured the NDK, the screen on your target device looks -as shown in Figure 1.

    - - - -

    -Figure 1. Target-device screen after successful launch. -

    diff --git a/docs/html/ndk/guides/stable_apis.jd b/docs/html/ndk/guides/stable_apis.jd deleted file mode 100644 index c38e68436a21e036aab9e619b0dc7714d94acb23..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/stable_apis.jd +++ /dev/null @@ -1,501 +0,0 @@ -page.title=Android NDK Native APIs -@jd:body - - - -

    The Android NDK provides a set of native headers and shared library files that has gradually -increased with successive releases of new Android API levels. This page explains these headers and -files, and maps them to specific - Android API levels. -

    - -

    Overview

    -

    There are two basic steps to enable your app to use the libraries that the NDK provides: -

    - -
      -
    1. Include in your code the headers associated with the libraries you wish to use.
    2. - -
    3. Tell the build system that your native module needs to link against the libraries at load time. -For example, to link against {@code /system/lib/libfoo.so}, add the following line to your -Android.mk file:
    4. - -
      -LOCAL_LDLIBS := -lfoo
      -
      - -

      To list multiple libraries, use a space as a delimiter. For more information about using the -{@code LOCAL_LDLIBS} variable, see Android.mk. -

      - -
    - -

    For all API levels, the build system automatically links the standard C libraries, the -standard C++ libraries, real-time extensions, and {@code pthread}; you do not need -to include them when defining your {@code LOCAL_LDLIBS} variable. For more information about -the C and C++ libraries, see Android API level 3.

    - -

    The NDK often provides new headers and libraries for new Android releases. These files reside -under {@code $NDK/platforms/android-//usr/include}. When the NDK does not -have a specific new group of headers and libraries for an Android API level, it means that -an app targeting that level should use the most recently released NDK assets. For example, -there was no new release of NDK headers or libraries for Android API levels 6 and 7. Therefore, -when developing an app targeting Android API level 7, you should use the headers and libraries -located under {@code android-5/}.

    - -

    Table 1 shows the correspondence between NDK-supported API levels and Android releases.

    - -

    - Table 1. NDK-supported API levels and corresponding Android releases.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    NDK-supported API levelAndroid release
    31.5
    41.6
    52.0
    82.2
    92.3 through 3.0.x
    123.1.x
    133.2
    144.0 through 4.0.2
    154.0.3 and 4.0.4
    164.1 and 4.1.1
    174.2 and 4.2.2
    184.3
    194.4
    214.4W and 5.0
    - -

    Each new release of NDK headers and libraries for a given Android API level is cumulative; you -are nearly always safe if you use the most recently released headers when building your app. For -example, you can use the NDK headers for Android API level 21 for an app targeting API level 16. By doing so, however, you increase your APK's footprint.

    - -

    -For more information about Android API levels, see -What is API Level?. -

    - -

    Major Native API Updates

    - -

    Android API level 3

    -

    The NDK provides the following APIs for developing native code that runs on Android 1.5 system -images and above.

    - -

    C library

    -

    The C library headers for Android 1.5 are available through their standard names, such as -{@code stdlib.h} and {@code stdio.h}. If a header is missing at build time, it's because the -header is not available on the 1.5 system image.

    - -

    C++ library

    -

    An extremely minimal C++ support API is available. For more -information on C++ library support, see -C++ Library Support.

    - -

    Android-specific log support

    - -

    {@code } contains various definitions that an app can use to send log -messages to the kernel from native code. For more information about these definitions, see the -comments in {@code $NDK/platforms/android-3/arch-arm/usr/include/android/log.h}, where {@code $NDK} -is the root of your NDK installation.

    - -

    You can write your own wrapper macros to access this functionality. If you wish to perform -logging, your native module should link to {@code /system/lib/liblog.so}. Implement this -linking by including the following line in your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS := -llog
    -
    - -

    ZLib compression library

    -

    You can use the Zlib compression library -by including {@code zlib.h} and {@code zconf.h}. You must also link your native -module against {@code /system/lib/libz.so} by including the following line in your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS := -lz
    -
    - -

    Dynamic linker library

    -

    You can access the Android dynamic linker's {@code dlopen()}, {@code dlsym()}, and -{@code dlclose()} functions by including {@code dlfcn.h}. You must also link against -{@code /system/lib/libdl.so} by including the following line in your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS := -ldl
    -
    - -

    Android API level 4

    -

    The NDK provides the following APIs for developing native code that runs on Android 1.6 system -images and above.

    - -

    OpenGL ES 1.x Library

    -

    The standard OpenGL ES headers {@code gl.h} and {@code glext.h} contain -the declarations necessary for performing OpenGL ES 1.x rendering calls from native code.

    - -

    To use these headers, link your native module to {@code /system/lib/libGLESv1_CM.so} by -including the following line in your -{@code Android.mk} file:

    -

    - -
    -LOCAL_LDLIBS := -lGLESv1_CM
    -
    -

    All Android-based devices support OpenGL ES 1.0, because Android provides an Open GL 1.0-capable -software renderer that can be used on devices without GPUs.

    -

    Only Android devices that have the necessary GPU fully support OpenGL ES 1.1. An app can -query the OpenGL ES version string and extension string to determine whether the current device -supports the features it needs. For information on how to perform this query, see the description of -{@code glGetString()} -in the OpenGL specification.

    - -

    Additionally, you must put a -{@code -} tag in your manifest file to indicate the version of -OpenGL ES -that your application requires.

    - -

    The EGL APIs are only available starting from API level 9. You can, however, -use the VM to perform some of the operations that you would get from those APIS. These operations -include surface creation and flipping. For an example of how to use {@code GLSurfaceView}, see - -Introducing GLSurfaceView.

    - -

    The san-angeles sample application provides an example of how to perform these operations, -rendering each frame in native code. This sample is a small Android port of the excellent -San Angeles Observation demo -program.

    - -

    Android API level 5

    -

    The NDK provides the following APIs for developing native code that runs on Android 2.0 system -images and above.

    - -

    OpenGL ES 2.0 library:

    -

    The standard OpenGL ES 2.0 headers {@code } and {@code } -contain the declarations needed for performing OpenGL ES 2.0 rendering calls from native code. -These rendering calls provide the ability to use the GLSL language to define and use vertex and -fragment shaders.

    - -

    To use OpenGL ES 2.0, link your native module to {@code /system/lib/libGLESv2.so} by -including the following line in your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS := -lGLESv2
    -
    - -

    Not all devices support OpenGL ES 2.0. An app can query the OpenGL -ES version string and extension string to determine whether the current device -supports the features it needs. For information on how to perform this query, see the description of - -{@code glGetString()} in the OpenGL specification.

    - -

    Additionally, you must put a -{@code -} tag in your manifest file to indicate which version of OpenGL ES your -application requires. For more information about the OpenGL ES settings for -{@code }, see -OpenGL ES.

    - -

    The hello-gl2 sample application provies a basic example of how to use OpenGL ES 2.0 with the -NDK.

    - -

    The EGL APIs are only available starting from API level 9. You can, however, -use the VM to perform some of the operations that you would get from those APIs. These operations -include surface creation and flipping. For an example of how to use {@code GLSurfaceView}, see - -Introducing GLSurfaceView.

    - -

    Note: The Android emulator does not support OpenGL ES 2.0 hardware -emulation. Running and testing code that uses this API requires a real device with hardware that can -support OpenGL ES 2.0.

    - -

    Android API level 8

    -

    The NDK provides the following APIs for developing native code that runs on Android 2.2 system -images and above.

    - -

    jnigraphics

    -

    The {@code jnigraphics} library exposes a C-based interface that allows native code to reliably access -the pixel buffers of Java bitmap objects. The workflow for using {@code jnigraphics} is as follows: -

    - -
      -
    1. Use {@code AndroidBitmap_getInfo()} to retrieve information from JNI, such as width and height, -about a given bitmap handle.
    2. - -
    3. Use {@code AndroidBitmap_lockPixels()} to lock the pixel buffer and retrieve a pointer to it. -Doing so ensures that the pixels do not move until the app calls -{@code AndroidBitmap_unlockPixels()}.
    4. - -
    5. In native code, modify the pixel buffer as appropriate for its pixel format, width, and other -characteristics.
    6. - -
    7. Call {@code AndroidBitmap_unlockPixels()} to unlock the buffer.
    8. -
    - -

    To use {@code jnigraphics}, include the {@code } header in your source code, and -link against {@code jnigraphics} by including the following line in your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS += -ljnigraphics
    -
    - -

    Additional details about this feature are in the comments of the {@code bitmap.h} file. - -

    Android API level 9

    -

    The NDK provides the following APIs for developing native code that runs on Android 2.3 system -images and above.

    - -

    EGL

    -

    EGL provides a native platform interface for allocating and managing OpenGLES surfaces. -For more information about its features, see -EGL Native Platform Interface.

    - -

    EGL allows you to perform the following operations from native code:

    - -
      -
    • List supported EGL configurations.
    • -
    • Allocate and release OpenGLES surfaces.
    • -
    • Swap or flip surfaces.
    • -
    - -

    The following headers provide EGL functionality:

    -
      -
    • {@code EGL/egl.h}: the main EGL API definitions.
    • -
    • {@code EGL/eglext.h}: EGL extension-related definitions.
    • -
    - -

    To link against the system's EGL library, add the following line to your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS += -lEGL
    -
    - -

    OpenSL ES

    -

    Android native audio handling is based on the Khronos Group OpenSL ES 1.0.1 API.

    - -

    The standard OpenSL ES headers {@code OpenSLES.h} and {@code OpenSLES_Platform.h} contain -the declarations necessary for performing audio input and output from the native side of Android. -The NDK distribution of the OpenSL ES also provides Android-specific extensions. For information -about these extensions, see the comments in {@code OpenSLES_Android.h} and -{@code OpenSLES_AndroidConfiguration.h}.

    - - -

    The system library {@code libOpenSLES.so} implements the public native audio functions. Link -against it by adding the following line to your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS += -lOpenSLES
    -
    - -

    For more information about the OpenSL ES API, refer to -{@code $NDK/docs/Additional_library_docs/opensles/index.html}, where {@code $NDK} is your NDK -installation root directory.

    - -

    Android native application APIs

    -

    Starting from API level 9, you can write an entire Android app with native code, without using -any Java.

    - -

    Note: Writing your app in native code is not, in itself, enough -for your app to run in the VM. Moreover, your app must still access most features of the Android -platform via JNI.

    - -

    This release provides the following native headers:

    -
      -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    • {@code }
    • -
    - -

    For more information about these headers, see the -NDK API Reference documentation, as well as -the comments in the headers, themselves. Also, for more information about the larger topic of -writing native apps, see -Native Activities and Applications. - -

    When you include one or more of these headers, you must also link against the -{@code libandroid.so} library. To link against {@code libandroid.so}, include the following line in -your {@code Android.mk} file:

    - -
    -LOCAL_LDLIBS += -landroid
    -
    - -

    Android API level 14

    -

    The NDK provides the following APIs for developing native code that runs on Android 4.0 system -images and above.

    - -

    OpenMAX AL

    -

    Android native multimedia handling is based on Khronos Group OpenMAX AL 1.0.1 API.

    -

    The standard OpenMAX AL headers {@code } and -{@code } contain the declarations necessary for performing -multimedia output from the native side of Android.

    - -

    The NDK distribution of OpenMAX AL also provides Android-specific extensions. For information -about these extensions, see the comments in {@code OpenMAXAL_Android.h}.

    - -

    The system library {@code libOpenMAXAL.so} implements the public native multimedia functions. -To link against this library, include the following line in your - {@code Android.mk} file:

    - -
        LOCAL_LDLIBS += -lOpenMAXAL
    -

    For more information about this topic, see {@code $NDK/docs/openmaxal/index.html}, -where {@code $NDK} is the root directory of your NDK installation.

    - -

    OpenSL ES

    -

    OpenSL ES support for this Android API level adds PCM support. For more information about -OpenSL ES support in the NDK, see OpenSL ES.

    - -

    Android API level 18

    -

    The NDK provides the following APIs for developing native code that runs on Android 4.3 system -images and above.

    - -

    OpenGL ES 3.0

    - -

    The standard OpenGL ES 3.0 headers {@code gl3.h} and {@code gl3ext.h} contain the declarations -needed for performing OpenGL ES 3.0 rendering calls from native code. These rendering calls provide -the ability to use the GLSL language to define and use vertex and fragment shaders. - -

    To use OpenGL ES 3.0, link your native module against {@code /system/lib/libGLESv3.so} by -including the following line in your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS := -lGLESv3
    -
    - -

    Not all devices support OpenGL ES 3.0. An app can query the OpenGL -ES version string and extension string to determine whether the current device -supports the features it needs. For information on how to perform this query, see the description of - -{@code glGetString()} in the OpenGL specification.

    - -

    Additionally, you must put a -{@code -} tag in your manifest file to indicate which version of OpenGL ES your -application requires. For more information about the OpenGL ES settings for -{@code }, see -OpenGL ES.

    - -

    The gles3jni sample application provides a basic example of how to use OpenGL ES 3.0 with the -NDK.

    - -

    Note: The Android emulator does not support OpenGL ES 3.0 hardware -emulation. Running and testing code that uses this API requires a real device with hardware that can -support OpenGL ES 3.0.

    - - -

    Android API level 21

    -

    The NDK provides the following APIs for developing native code that runs on Android 4.3 system -images and above.

    - -

    OpenGL ES 3.1

    - -

    The standard OpenGL ES 3.1 headers {@code gl31.h} and {@code gl3ext.h} contain the declarations -needed for performing OpenGL ES 3.1 rendering calls from native code. These rendering calls provide -the ability to use the GLSL language to define and use vertex and fragment shaders. - -

    To use OpenGL ES 3.1, link your native module against {@code /system/lib/libGLESv3.so} by -including the following line in your -{@code Android.mk} file:

    - -
    -LOCAL_LDLIBS := -lGLESv3
    -
    - -

    Not all devices support OpenGL ES 3.1. An app can query the OpenGL -ES version string and extension string to determine whether the current device -supports the features it needs. For information on how to perform this query, see the description of - -{@code glGetString()} in the OpenGL specification.

    - -

    Additionally, you must put a -{@code -} tag in your manifest file to indicate which version of OpenGL ES your -application requires. For more information about the OpenGL ES settings for -{@code }, see -OpenGL ES.

    - -

    The gles3jni sample application provides a basic example of how to use OpenGL ES 3.1 with the -NDK.

    - -

    Note: The Android emulator does not support OpenGL ES 3.1 hardware -emulation. Running and testing code that uses this API requires a real device with hardware that can -support OpenGL ES 3.1.

    - diff --git a/docs/html/ndk/guides/standalone_toolchain.jd b/docs/html/ndk/guides/standalone_toolchain.jd deleted file mode 100755 index 7a6f906cd54d89f6090d8c250bb1e867af46924b..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/standalone_toolchain.jd +++ /dev/null @@ -1,605 +0,0 @@ -page.title=Standalone Toolchain -@jd:body - - - -

    You can use the toolchains provided with the Android NDK independently, or as plug-ins -with an existing IDE. This flexibility -can be useful if you already have your own build system, and only need the ability to invoke the -cross-compiler in order to add support to Android for it.

    - -

    A typical use case is invoking the configure script of an open-source library that expects a -cross-compiler in the {@code CC} environment variable.

    - -

    Note: This page assumes significant understanding of -compiling, linking, and low-level architecture. In addition, the techniques it describes are -unnecessary for most use cases. In most cases, we recommend that you forego using a standalone -toolchain, and instead stick to the NDK build system.

    - -

    Selecting Your Toolchain

    -

    Before anything else, you need to decide which processing architecture your standalone toolchain -is going to target. Each architecture corresponds to a different toolchain name, as Table 1 -shows.

    - -

    - Table 1. {@code APP_ABI} settings for different instruction sets.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ArchitectureToolchain name
    ARM-based{@code arm-linux-androideabi-}
    x86-based{@code x86-}
    MIPS-based{@code mipsel-linux-android-}
    ARM64-based{@code aarch64-linux-android-}
    X86-64-based{@code x86_64-}
    MIPS64-based{@code mips64el-linux-android--}
    - - - -

    Selecting Your Sysroot

    -

    The next thing you need to do is define your sysroot (A sysroot is a directory containing -the system headers and libraries for your target). To define the sysroot, you must must know the -Android API level you want to target for native support; available native APIs vary by Android API -level.

    - -

    Native APIs for the respective -Android API levels reside under {@code $NDK/platforms/}; each API-level -directory, in turn, contains subdirectories for the various CPUs and architectures. The -following example shows how to define a sysroot for a build targeting Android 5.0 -(API level 21), for ARM architecture:

    - -
    -SYSROOT=$NDK/platforms/android-21/arch-arm
    -
    - -For more detail about the Android API levels and the respective native APIs they support, see -Android NDK Native APIs. - -

    Invoking the Compiler

    - -

    There are two ways to invoke the compiler. One method is simple, and leaves most of the lifting -to the build system. The other is more advanced, but provides more flexibility.

    - -

    Simple method

    -

    The simplest way to build is by invoking the appropriate compiler directly from the command -line, using the {@code --sysroot} option to indicate the location of the system files for the -platform you're targeting. For example:

    - -
    -export CC="$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/ \
    -linux-x86/bin/arm-linux-androideabi-gcc-4.8 --sysroot=$SYSROOT"
    -$CC -o foo.o -c foo.c
    -
    - -

    While this method is simple, it lacks in flexibility: It does not allow you to use any C++ STL -(STLport, libc++, or the GNU libstdc++) with it. It also does not support exceptions or RTTI.

    - -

    For Clang, you need to perform an additional two steps:

    -
      -
        -
      1. Add the appropriate {@code -target} for the target architecture, as Table 2 shows.
      2. - -

        - Table 2. Architectures and corresponding values for {@code -target}.

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        ArchitectureValue
        armeabi{@code -target armv5te-none-linux-androideabi}
        armeabi-v7a{@code -target armv7-none-linux-androideabi}
        arm64-v8a{@code -target aarch64-none-linux-android}
        x86{@code -target i686-none-linux-android}
        x86_64{@code -target x86_64-none-linux-android}
        mips{@code -target mipsel-none-linux-android}
        - -
      3. Add assembler and linker support by adding the {@code -gcc-toolchain} option, as in the -following example:
      4. -
        --gcc-toolchain $NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
        -
        -
      - -Ultimately, a command to compile using Clang might look like this: - -
      -export CC="$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/ \
      -linux-x86/bin/arm-linux-androideabi-gcc-4.8 --sysroot=$SYSROOT" -target \
      -armv7-none-linux-androideabi \
      --gcc-toolchain $NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64"
      -$CC -o foo.o -c foo.c
      -
      -
    - -

    Advanced method

    -

    The NDK provides the {@code make-standalone-toolchain.sh} shell script to allow you to perform a -customized toolchain installation from the command line. This approach affords you more flexibility -than the procedure described in Simple method.

    - -

    The script is located in the {@code $NDK/build/tools/} directory, where {@code $NDK} is the -installation root for the NDK. An example of the use of this script appears below:

    - -
    -$NDK/build/tools/make-standalone-toolchain.sh \
    ---arch=arm --platform=android-21 --install-dir=/tmp/my-android-toolchain
    -
    - -

    This command creates a directory named {@code /tmp/my-android-toolchain/}, containing a copy of -the {@code android-21/arch-arm} sysroot, and of the toolchain binaries for a 32-bit ARM -architecture.

    - -

    Note that the toolchain binaries do not depend on or contain host-specific paths, in other words, -you can install them in any location, or even move them if you need to.

    - -

    By default, the build system uses the 32-bit, ARM-based GCC 4.8 toolchain. You can specify a -different value, however, by specifying {@code --arch=} as an option. -Table 3 shows the values to use for other toolchains: - -

    - Table 3. Toolchains and corresponding values, using {@code --arch}.

    - - - - - - - - - - - - - - - - - - - - - - - - - -
    ToolchainValue
    mips64 compiler{@code --arch=mips64}
    mips GCC 4.8 compiler{@code --arch=mips}
    x86 GCC 4.8 compiler{@code --arch=x86}
    x86_64 GCC 4.8 compiler{@code --arch=x86_64}
    mips GCC 4.8 compiler{@code --arch=mips}
    - -

    Alternatively, you can use the {@code --toolchain=} option. Table 4 shows the -values you can specify for {@code }:

    - -

    - Table 4. Toolchains and corresponding values, using {@code --toolchain}.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ToolchainValue
    arm -
  • {@code --toolchain=arm-linux-androideabi-4.8}
  • -
  • {@code --toolchain=arm-linux-androideabi-4.9}
  • -
  • {@code --toolchain=arm-linux-android-clang3.5}
  • -
  • {@code --toolchain=arm-linux-android-clang3.6}
  • -
    x86 -
  • {@code --toolchain=x86-linux-android-4.8}
  • -
  • {@code --toolchain=x86-linux-android-4.9}
  • -
  • {@code --toolchain=x86-linux-android-clang3.5}
  • -
  • {@code --toolchain=x86-linux-android-clang3.6}
  • -
    mips -
  • {@code --toolchain=mips-linux-android-4.8}
  • -
  • {@code --toolchain=mips-linux-android-4.9}
  • -
  • {@code --toolchain=mips-linux-android-clang3.5}
  • -
  • {@code --toolchain=mips-linux-android-clang3.6}
  • -
    arm64 -
  • {@code --toolchain=aarch64-linux-android-4.9}
  • -
  • {@code --toolchain=aarch64-linux-android-clang3.5}
  • -
  • {@code --toolchain=aarch64-linux-android-clang3.6}
  • -
    x86_64 -
  • {@code --toolchain=x86_64-linux-android-4.9}
  • -
  • {@code --toolchain=x86_64-linux-android-clang3.5}
  • -
  • {@code --toolchain=x86_64-linux-android-clang3.6}
  • -
    mips64 -
  • {@code --toolchain=mips64el-linux-android-4.9}
  • -
  • {@code --toolchain=mips64el-linux-android-clang3.5}
  • -
  • {@code --toolchain=mips64el-linux-android-clang3.6}
  • -
    - -

    Note: Table 4 is not an exhaustive list. Other combinations may -also be valid, but are unverified.

    - -

    You can also copy Clang/LLVM 3.6, using one of two methods: You can append {@code -clang3.6} to -the {@code --toolchain} option, so that the {@code --toolchain} option looks like the following -example: - -

    ---toolchain=arm-linux-androideabi-clang3.6
    -
    - -

    You can also add {@code -llvm-version=3.6} as a separate option on the command -line.

    - -

    Note: Instead of specifying a specific version, you can also -use {@code }, which defaults -to the highest available version of Clang.

    - -

    By default, the build system builds for a 32-bit host toolchain. You can specify a 64-bit -host toolchain instead. Table 5 shows the value to use with {@code -system} for different -platforms.

    - -

    - Table 5. Host toolchains and corresponding values, using {@code -system}.

    - - - - - - - - - - - - - - - - - -
    Host toolchainValue
    64-bit Linux{@code -system=linux-x86_64}
    64-bit MacOSX{@code -system=darwin-x86_64}
    64-bit Windows{@code -system=windows-x86_64}
    - -For more information on specifying a 64- or 32-bit instruction host toolchain, see -64-Bit and 32-Bit Toolchains. - -

    You may specify {@code --stl=stlport} to copy {@code libstlport} instead of the default -{@code libgnustl}. If you do so, and you wish to link against the shared library, you must -explicitly use {@code -lstlport_shared}. This requirement is similar to having to use -{@code -lgnustl_shared} for GNU {@code libstdc++}.

    - -

    Similarly, you can specify {@code --stl=libc++} to copy the LLVM libc++ headers and libraries. -To link against the shared library, you must explicitly use -lc++_shared.

    - -

    You can make these settings directly, as in the following example:

    - -
    -export PATH=/tmp/my-android-toolchain/bin:$PATH
    -export CC=arm-linux-androideabi-gcc   # or export CC=clang
    -export CXX=arm-linux-androideabi-g++  # or export CXX=clang++
    -
    - -

    Note that if you omit the {@code -install-dir} option, the {@code make-standalone-toolchain.sh} -shell script creates a tarball in {@code tmp/ndk/.tar.bz2}. This tarball makes -it easy to archive, as well as to redistribute the binaries.

    - -

    This standalone toolchain provides an additional benefit, as well, in that it contains a working -copy of a C++ STL library, with working exceptions and RTTI support.

    - -

    For more options and details, use {@code --help}.

    - -

    Working with Clang

    -

    You can install Clang binaries in the standalone installation by using the -{@code --llvm-version=} option. {@code } is a LLVM/Clang version -number, such as {@code 3.5} or {@code 3.6}. For example: - -

    -build/tools/make-standalone-toolchain.sh \
    ---install-dir=/tmp/mydir \
    ---toolchain=arm-linux-androideabi-4.8 \
    ---llvm-version=3.6
    -
    - -

    Note that Clang binaries are copied along with the GCC ones, because they rely on the same -assembler, linker, headers, libraries, and C++ STL implementation.

    - -

    This operation also installs two scripts, named {@code clang} and {@code clang++}, under -{@code /bin/@}. These scripts invoke the real {@code clang} binary with default -target architecture flags. In other words, they should work without any modification, and you should -be able to use them in your own builds by just setting the {@code CC} and {@code CXX} environment -variables to point to them.

    - -

    Invoking Clang

    -

    In an ARM standalone installation built with {@code llvm-version=3.6}, invoking -Clang on a Unix system takes the form of a single line. For -instance:

    - -
    -`dirname $0`/clang36 -target armv5te-none-linux-androideabi "$@"
    -
    - -

    clang++ invokes clang++31 in the same way.

    - -

    Clang targets with ARM

    - -

    When building for ARM, Clang changes the target based on the presence of the -{@code -march=armv7-a} and/or {@code -mthumb} options:

    - -

    - Table 5. Specifiable {@code -march} values and their resulting targets.

    - - - - - - - - - - - - - - - - - -
    {@code -march} valueResulting target
    {@code -march=armv7-a}{@code armv7-none-linux-androideabi}
    {@code -mthumb}{@code thumb-none-linux-androideabi}
    Both {@code -march=armv7-a} and {@code -mthumb}{@code thumbv7-none-linux-androideabi}
    - -

    You may also override with your own {@code -target} if you wish.

    - -

    The {@code -gcc-toolchain} option is unnecessary because, in a standalone package, -Clang locates {@code as} and {@code ld} in a predefined relative location.

    - -

    {@code clang} and {@code clang++} should be easy drop-in replacements for {@code gcc} and -{@code g++} in a makefile. When in doubt, add the following options to verify that they are -working properly:

    - -
      -
    • {@code -v} to dump commands associated with compiler driver issues
    • -
    • {@code -###} to dump command line options, including implicitly predefined ones.
    • -
    • {@code -x c < /dev/null -dM -E} to dump predefined preprocessor definitions
    • -
    • {@code -save-temps} to compare {@code *.i} or {@code *.ii} preprocessed files.
    • -
    - -

    For more information about Clang, see -http://clang.llvm.org/, especially the GCC compatibility -section.

    - - -

    ABI Compatibility

    -

    The machine code that the ARM toolchain generates should be compatible with the official Android -{@code armeabi} ABI by default.

    - -

    We recommend use of the {@code -mthumb} compiler flag to force the generation of 16-bit Thumb-1 -instructions (the default being 32-bit ARM instructions).

    - -

    If you want to target the armeabi-v7a ABI, you must set the following flags:

    - -
    -CFLAGS= -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
    -
    - -

    The first flag enables Thumb-2 instructions. The second flag enables hardware-FPU instructions -while ensuring that the system passes floating-point parameters in core registers, which is critical -for ABI compatibility.

    - -

    Note: In versions of the NDK prior to r9b, do not use these flags -separately. You must set all or none of them. Otherwise, unpredictable behavior and crashes may -result.

    - -

    To use NEON instructions, you must change the {@code -mfpu} compiler flag:

    - -
    -CFLAGS= -march=armv7-a -mfloat-abi=softfp -mfpu=neon
    -
    - -

    Note that this setting forces the use of {@code VFPv3-D32}, per the ARM specification.

    - -

    Also, make sure to provide the following two flags to the linker:

    - -
    -LDFLAGS= -march=armv7-a -Wl,--fix-cortex-a8
    -
    - -

    The first flag instructs the linker to pick {@code libgcc.a}, {@code libgcov.a}, and -{@code crt*.o}, which are tailored for armv7-a. The 2nd flag is required as a workaround for a CPU -bug in some Cortex-A8 implementations.

    - -

    Since NDK version r9b, all Android native APIs taking or returning double or float values have -{@code attribute((pcs("aapcs")))} for ARM. This makes it possible to compile user code in -{@code -mhard-float} (which implies {@code -mfloat-abi=hard}), and still link with the Android -native APIs that comply with the softfp ABI. For more information on this, see the comments in -{@code $NDK/tests/device/hard-float/jni/Android.mk}.

    - -

    If you want to use NEON intrinsics on x86, the build system can translate them to the native x86 -SSE intrinsics using a special C/C++ language header with the same name, {@code arm_neon.h}, as the -standard ARM NEON intrinsics header.

    - -

    By default, the x86 ABI supports SIMD up to SSSE3, and the header covers ~93% of (1869 of 2009) -NEON functions.

    - -

    You don't have to use any specific compiler flag when targeting the MIPS ABI.

    - -

    To learn more about ABI support, see x86 Support.

    - -

    Warnings and Limitations

    -

    Windows support

    -

    The Windows binaries do not depend on Cygwin. This lack of dependency makes them faster. The -cost, however, is that they do not understand Cygwin path specifications like -{@code cygdrive/c/foo/bar}, as opposed to {@code C:/foo/bar}.

    - -

    The NDK build system ensures that all paths passed to the compiler from Cygwin are automatically -translated, and manages other complexities, as well. If you have a custom build system, -you may need to resolve these complexities yourself.

    - -

    For information on contributing to support for Cygwin/MSys, visit the android-ndk -forum.

    - -

    wchar_t support

    - -

    The Android platform did not really support {@code wchar_t} until Android 2.3 (API level 9). This -fact has several ramifications:

    -
      -
    • If you target platform Android 2.3 or higher, the size of {@code wchar_t} is 4 bytes, and most -{@code wide-char} functions are available in the C library (with the exception of multi-byte -encoding/decoding functions and {@code wsprintf}/{@code wsscanf}).
    • - -
    • If you target any lower API level, the size of {@code wchar_t} is 1 byte, and none of the -wide-char functions works.
    • -
    - -

    We recommend that you get rid of any dependencies on the {@code wchar_t} type, and switch to -better representations. The support provided in Android is only there to help you migrate existing -code.

    - -

    Exceptions, RTTI, and STL

    -

    The toolchain binaries support C++ exceptions and RTTI by default. To disable C++ exceptions -and RTTI when building sources (to generate lighter-weight machine code, for example), use -{@code -fno-exceptions} and {@code -fno-rtti}.

    - -

    To use these features in conjunction with GNU libstdc++, you must explicitly link with libsupc++. -To do so, use {@code -lsupc++} when linking binaries. For example:

    - -
    -arm-linux-androideabi-g++ .... -lsupc++
    -
    - -

    You do not need to do this when using the STLport or libc++ library.

    - -

    C++ STL support

    -

    The standalone toolchain includes a copy of a C++ Standard Template Library implementation. This -implementation is either for GNU libstdc++, STLport, or libc++, depending on what you specify for the -{@code --stl=} option described previously. To use this implementation of STL, you need -to link your project with the proper library:

    - -
      -
    • -Use {@code -lstdc++} to link against the static library version of any implementation. Doing so -ensures that all required C++ STL code is included into your final binary. This method is ideal if -you are only generating a single shared library or executable.

      - -

      This is the method that we recommend.

      -
    • - -
    • Alternatively, use {@code -lgnustl_shared} to link against the shared library version of GNU -{@code libstdc++}. If you use this option, you must also make sure to copy -{@code libgnustl_shared.so} to your device in order for your code to load properly. Table 6 shows -where this file is for each toolchain type. -
    • - -

      Note: GNU libstdc++ is licensed under the GPLv3 license, with a -linking exception. If you cannot comply with its requirements, you cannot redistribute the -shared library in your project.

      - - -
    • Use {@code -lstlport_shared} to link against the shared library version of STLport. When you do -so, you need to make sure that you also copy {@code libstlport_shared.so} to your device in order -for your code to load properly. Table 6 shows where this file is for each toolchain:
    • - -

      - Table 6. Specifiable {@code -march} values and their resulting targets.

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      ToolchainLocation
      arm{@code $TOOLCHAIN/arm-linux-androideabi/lib/}
      arm64{@code $TOOLCHAIN/aarch64-linux-android/lib/}
      x86{@code $TOOLCHAIN/i686-linux-android/lib/}
      x86_64{@code $TOOLCHAIN/x86_64-linux-android/lib/}
      mips{@code $TOOLCHAIN/mipsel-linux-android/lib/}
      mips64{@code $TOOLCHAIN/mips64el-linux-android/lib/}
      - -

      Note: If your project contains multiple shared libraries or -executables, you must link against a shared-library STL implementation. Otherwise, the build -system does not define certain global uniquely, which can result in unpredictable runtime behavior. -This behavior may include crashes and failure to properly catch exceptions.

      - -

      The reason the shared version of the libraries is not simply called {@code libstdc++.so} is that -this name would conflict at runtime with the system's own minimal C++ runtime. For this reason, -the build system enforces a new name for the GNU ELF library. The static library does not have -this problem.

      diff --git a/docs/html/ndk/guides/x86-64.jd b/docs/html/ndk/guides/x86-64.jd deleted file mode 100644 index c2f0d28394d5a6d2d6a315da2407cda747875006..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/x86-64.jd +++ /dev/null @@ -1,52 +0,0 @@ -page.title=Support for 64-bit x86 -@jd:body - -
      -
      -

      On this page

      - -
        -
      1. Overview
      2. -
      3. Standalone Toolchain
      4. -
      5. Compatibilty
      6. -
      - - -
      -
      - -

      The Android NDK supports the {@code x86_64} ABI. This ABI allows native code to run on -Android-based devices using CPUs that support the 64-bit x86 instruction set.

      - -

      Overview

      -

      To generate 64-bit machine code for x86, add {@code x86_64} to the {@code APP_ABI} definition in -your {@code Application.mk} file. For example: - -

      -APP_ABI := x86_64
      -
      - -For more information on how to specify values for {@code APP_ABI}, see -Application.mk.

      - -

      The build system places libraries generated for the {@code x86_64} ABI into -{@code $PROJECT/libs/x86_64/} on your host machine, where {@code $PROJECT} is the root directory -of your project. It also embeds them in your APK, under {@code /lib/x86_64/}.

      - -

      The Android package manager extracts these libraries when installing your APK on a compatible -64-bit, x86-powered device, placing them under your app's private data directory.

      - -

      In the Google Play store, the server filters applications so that a consumer sees only the native -libraries that run on the CPU powering his or her device.

      - -

      Standalone Toolchain

      - -

      You can use the 64-bit x86 toolchain in standalone mode with the NDK. For more -information about doing so, see -Standalone Toolchain, under the "Advanced method" section. - -

      Compatibility

      -

      The NDK provides native versions of Android APIs for 64-bit x86 machine code starting from -Android 5.0 (Android API level 21). If your project files target an older API level, but include -{@code x86_64} as a targeted platform, the NDK build script automatically selects the right set of -native platform headers and libraries for you.

      diff --git a/docs/html/ndk/guides/x86.jd b/docs/html/ndk/guides/x86.jd deleted file mode 100644 index 3a01b05d718f8fa7ed03d0d3c40673111bcbee8f..0000000000000000000000000000000000000000 --- a/docs/html/ndk/guides/x86.jd +++ /dev/null @@ -1,215 +0,0 @@ -page.title=x86 Support -@jd:body - - - -

      The NDK includes support for the {@code x86} ABI, which allows native code to run on -Android-based devices running on CPUs supporting the IA-32 instruction set.

      - -

      Overview

      -

      To generate x86 machine code, add {@code x86} to the {@code APP_ABI} definition in your -{@code Application.mk} file. For example:

      - -
      -APP_ABI := armeabi armeabi-v7a x86
      -
      For more information about defining the {@code APP_ABI} variable, see -{@code Application.mk}.

      - -

      The build system places generated libraries into {@code $PROJECT/libs/x86/}, where -{@code $PROJECT} represents your project's root directory, and embeds them in your APK under -{@code /lib/mips/}.

      - -

      The Android package extracts these libraries when installing your APK on a compatible x86-based -device, placing them under your app's private data directory.

      - -

      In the Google Play store, the server filters applications so that a consumer sees only the native -libraries that run on the CPU powering his or her device.

      - -

      x86 Support for ARM NEON Intrinsics

      -

      Support for ARM NEON intrinsics is provided in the form of C/C++ language headers with the same -name as the standard ARM NEON intrinsics header, {@code arm_neon.h}. These headers are available for -all NDK x86 toolchains. They translate NEON intrinsics to native x86 SSE ones.

      - -

      Characteristics of this solution include the following:

      -
        -
      • Default use of SSE through SSSE3 for porting ARM NEON to Intel SSE, covering ~93% -(1869 of total 2009) of all NEON functions.
      • -
      • Redefinition of ARM NEON 128 bit vectors into the equivalent x86 SIMD data.
      • -
      • Redefinition of some functions from ARM NEON to Intel SSE if a 1:1 correspondence exists.
      • -
      • Implementation of some ARM NEON functions using Intel SIMD if it will yield a performant result. -
      • -
      • Implementation of some of the remaining NEON functions using the serial solution, and issuing -the corresponding "low performance" compiler warning.
      • -
      - - -

      Performance

      -

      In most cases, you should be able to attain performance similar to what you would get from ARM -NEON code. Recommendations for best results include:

      - -
        -
      • Use 16-byte data alignment for faster load and store.
      • -
      • Avoid using constants with NEON functions. Using constants results in a performance penalty due -to having to load constants. If you must use constants, try to initialize them outside of hotspot -loops. If possible, replace them with logical and compare operations.
      • -
      • Try to avoid functions marked as "serially implemented" because they need to store data from -registers to memory. Instead, process them serially and reload them. You may be able to change the -data type or algorithm used to vectorize the whole port instead of leaving it as a serial one.
      • -
      - -

      For more information on this topic, see - -From ARM NEON to Intel SSE– the automatic porting solution, tips and tricks.

      - -

      Known differences from ARM version

      -

      In the great majority of cases, x86 implementations produce the same results as ARM -implementations for NEON. x86 implementations pass -NEON tests nearly 100% of the -time. Still, there are several corner cases in which an x86 implementation produces results -different from its ARM counterpart. Known incompatibilities are as follows:

      - - - -

      Sample code

      -

      In your project make sure to include the {@code arm_neon.h} header, and define include -{@code x86} in your definition of {@code APP_ABI}. The build system then ports your code to x86.

      - -

      For an example of how porting ARM NEON to x86 SSE works, see the hello-neon sample.

      - -

      Standalone Toolchain

      -

      You can incorporate the {@code x86} ABI into your own toolchain. For more information, see -Standalone Toolchain.

      - -

      Compatibility

      -

      x86 support requires, at minimum, Android 2.3 (Android API level 9). If your project files -target an older API level, but include x86 as a targeted platform, the NDK build script -automatically selects the right set of native platform headers/libraries for you.

      \ No newline at end of file diff --git a/docs/html/ndk/index.jd b/docs/html/ndk/index.jd deleted file mode 100644 index fc1c595e748b8648e5a102deda8e2c2e335feaa0..0000000000000000000000000000000000000000 --- a/docs/html/ndk/index.jd +++ /dev/null @@ -1,51 +0,0 @@ -page.title=Android NDK -page.tags="ndk, native, c, c++", -meta.tags="ndk, native, c++" -fullpage=true -section.landing=true -header.hide=1 -footer.hide=1 -@jd:body - -
      -
      -
      -
      -

      Android NDK

      -

      - The Android NDK is a toolset that lets you implement parts of your app using native-code languages such as C and C++. For certain types of apps, this can help you reuse existing code libraries written in those languages. -

      - - - - Get Started -
      -
      -
      - - public class MyActivity extends Activity {
      -   /**
      -   * Native method implemented in C/C++
      -   */

      -   public native void computeFoo();
      - }
      -
      -
      -
      -
      - - -
      -

      Latest

      -
      -
      diff --git a/docs/html/ndk/reference/_book.yaml b/docs/html/ndk/reference/_book.yaml deleted file mode 100644 index ab8b8f93c5ab09912db4f6b9fee7498f8109b79a..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/_book.yaml +++ /dev/null @@ -1,60 +0,0 @@ -toc: -- title: Asset Manager - path: /ndk/reference/group___asset.html - section: - - title: asset_manager.h - path: /ndk/reference/asset__manager_8h.html - - title: asset_manager_jni.h - path: /ndk/reference/asset__manager__jni_8h.html - -- title: Bitmap - path: /ndk/reference/group___bitmap.html - section: - - title: bitmap.h - path: /ndk/reference/bitmap_8h.html - -- title: Configuration - path: /ndk/reference/group___configuration.html - section: - - title: configuration.h - path: /ndk/reference/configuration_8h.html - -- title: Input - path: /ndk/reference/group___input.html - section: - - title: input.h - path: /ndk/reference/input_8h.html - - title: keycodes.h - path: /ndk/reference/keycodes_8h.html - -- title: Looper - path: /ndk/reference/group___looper.html - section: - - title: looper.h - path: /ndk/reference/looper_8h.html - -- title: Native Activity and Window - path: /ndk/reference/group___native_activity.html - section: - - title: native_activity.h - path: /ndk/reference/native__activity_8h.html - - title: native_window.h - path: /ndk/reference/native__window_8h.html - - title: native_window.h - path: /ndk/reference/native__window__jni_8h.html - - title: rect.h - path: /ndk/reference/rect_8h.html - -- title: Sensor - path: /ndk/reference/group___sensor.html - section: - - title: sensor.h - path: /ndk/reference/sensor_8h.html - -- title: Storage Manager - path: /ndk/reference/group___storage.html - section: - - title: storage_manager.h - path: /ndk/reference/storage__manager_8h.html - - title: obb.h - path: /ndk/reference/obb_8h.html diff --git a/docs/html/ndk/reference/annotated.jd b/docs/html/ndk/reference/annotated.jd deleted file mode 100644 index 8045f8dac05dae141143a11e38e30e33d018e77e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/annotated.jd +++ /dev/null @@ -1,25 +0,0 @@ -page.title=Data Structures -page.customHeadTag= -@jd:body - -
    -
    -
    -
    Data Structures
    -
    - diff --git a/docs/html/ndk/reference/asset__manager_8h.jd b/docs/html/ndk/reference/asset__manager_8h.jd deleted file mode 100644 index 88d8deac5fe74c8455085f8ef41f633bda63a714..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/asset__manager_8h.jd +++ /dev/null @@ -1,75 +0,0 @@ -page.title=asset_manager.h File Reference -page.customHeadTag= -@jd:body - - -
    -
    - -
    -
    asset_manager.h File Reference
    -
    -
    - - - - - - - - -

    -Typedefs

    typedef struct AAssetManager AAssetManager
     
    typedef struct AAssetDir AAssetDir
     
    typedef struct AAsset AAsset
     
    - - - -

    -Enumerations

    enum  { AASSET_MODE_UNKNOWN = 0, -AASSET_MODE_RANDOM = 1, -AASSET_MODE_STREAMING = 2, -AASSET_MODE_BUFFER = 3 - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    AAssetDirAAssetManager_openDir (AAssetManager *mgr, const char *dirName)
     
    AAssetAAssetManager_open (AAssetManager *mgr, const char *filename, int mode)
     
    const char * AAssetDir_getNextFileName (AAssetDir *assetDir)
     
    void AAssetDir_rewind (AAssetDir *assetDir)
     
    void AAssetDir_close (AAssetDir *assetDir)
     
    int AAsset_read (AAsset *asset, void *buf, size_t count)
     
    off_t AAsset_seek (AAsset *asset, off_t offset, int whence)
     
    off64_t AAsset_seek64 (AAsset *asset, off64_t offset, int whence)
     
    void AAsset_close (AAsset *asset)
     
    const void * AAsset_getBuffer (AAsset *asset)
     
    off_t AAsset_getLength (AAsset *asset)
     
    off64_t AAsset_getLength64 (AAsset *asset)
     
    off_t AAsset_getRemainingLength (AAsset *asset)
     
    off64_t AAsset_getRemainingLength64 (AAsset *asset)
     
    int AAsset_openFileDescriptor (AAsset *asset, off_t *outStart, off_t *outLength)
     
    int AAsset_openFileDescriptor64 (AAsset *asset, off64_t *outStart, off64_t *outLength)
     
    int AAsset_isAllocated (AAsset *asset)
     
    -
    diff --git a/docs/html/ndk/reference/asset__manager__jni_8h.jd b/docs/html/ndk/reference/asset__manager__jni_8h.jd deleted file mode 100644 index 8aace051d092107b669d82fabe967bb908bfadd7..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/asset__manager__jni_8h.jd +++ /dev/null @@ -1,25 +0,0 @@ -page.title=asset_manager_jni.h File Reference -page.customHeadTag= -@jd:body - - -
    -
    - -
    -
    asset_manager_jni.h File Reference
    -
    -
    -
    #include <android/asset_manager.h>
    -#include <jni.h>
    -
    - - - -

    -Functions

    AAssetManagerAAssetManager_fromJava (JNIEnv *env, jobject assetManager)
     
    -
    diff --git a/docs/html/ndk/reference/bc_s.png b/docs/html/ndk/reference/bc_s.png deleted file mode 100644 index fd162ea76db92647e51fbcd742f46c016f9f633d..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/bc_s.png and /dev/null differ diff --git a/docs/html/ndk/reference/bdwn.png b/docs/html/ndk/reference/bdwn.png deleted file mode 100644 index 7c943f0178f06cc641b5e069ca6ec290369c8023..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/bdwn.png and /dev/null differ diff --git a/docs/html/ndk/reference/bitmap_8h.jd b/docs/html/ndk/reference/bitmap_8h.jd deleted file mode 100644 index 518cab178faf25a9590754a5ce429f1914e6d681..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/bitmap_8h.jd +++ /dev/null @@ -1,61 +0,0 @@ -page.title=bitmap.h File Reference -page.customHeadTag= -@jd:body - - -
    -
    - -
    -
    bitmap.h File Reference
    -
    -
    -
    #include <stdint.h>
    -#include <jni.h>
    -
    - - - -

    -Data Structures

    struct  AndroidBitmapInfo
     
    - - - -

    -Macros

    #define ANDROID_BITMAP_RESUT_SUCCESS   ANDROID_BITMAP_RESULT_SUCCESS
     
    - - - - - -

    -Enumerations

    enum  { ANDROID_BITMAP_RESULT_SUCCESS = 0, -ANDROID_BITMAP_RESULT_BAD_PARAMETER = -1, -ANDROID_BITMAP_RESULT_JNI_EXCEPTION = -2, -ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3 - }
     
    enum  AndroidBitmapFormat {
    -  ANDROID_BITMAP_FORMAT_NONE = 0, -ANDROID_BITMAP_FORMAT_RGBA_8888 = 1, -ANDROID_BITMAP_FORMAT_RGB_565 = 4, -ANDROID_BITMAP_FORMAT_RGBA_4444 = 7, -
    -  ANDROID_BITMAP_FORMAT_A_8 = 8 -
    - }
     
    - - - - - - - -

    -Functions

    int AndroidBitmap_getInfo (JNIEnv *env, jobject jbitmap, AndroidBitmapInfo *info)
     
    int AndroidBitmap_lockPixels (JNIEnv *env, jobject jbitmap, void **addrPtr)
     
    int AndroidBitmap_unlockPixels (JNIEnv *env, jobject jbitmap)
     
    -
    diff --git a/docs/html/ndk/reference/classes.jd b/docs/html/ndk/reference/classes.jd deleted file mode 100644 index e0ec72146f179c47bfa5385b2748256a8cb5d9ab..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/classes.jd +++ /dev/null @@ -1,20 +0,0 @@ -page.title=Data Structure Index -page.customHeadTag= -@jd:body - - -
    -
    -
    Data Structure Index
    -
    - diff --git a/docs/html/ndk/reference/closed.png b/docs/html/ndk/reference/closed.png deleted file mode 100644 index e4e2b25adb14b76c58d22aa1e4122e0c3338d4ac..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/closed.png and /dev/null differ diff --git a/docs/html/ndk/reference/configuration_8h.jd b/docs/html/ndk/reference/configuration_8h.jd deleted file mode 100644 index 3f5f07c631da626804019e552d5c1f31a4d902ef..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/configuration_8h.jd +++ /dev/null @@ -1,222 +0,0 @@ -page.title=configuration.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    configuration.h File Reference
    -
    -
    - - - - -

    -Typedefs

    typedef struct AConfiguration AConfiguration
     
    - - - -

    -Enumerations

    enum  {
    -  ACONFIGURATION_ORIENTATION_ANY = 0x0000, -ACONFIGURATION_ORIENTATION_PORT = 0x0001, -ACONFIGURATION_ORIENTATION_LAND = 0x0002, -ACONFIGURATION_ORIENTATION_SQUARE = 0x0003, -
    -  ACONFIGURATION_TOUCHSCREEN_ANY = 0x0000, -ACONFIGURATION_TOUCHSCREEN_NOTOUCH = 0x0001, -ACONFIGURATION_TOUCHSCREEN_STYLUS = 0x0002, -ACONFIGURATION_TOUCHSCREEN_FINGER = 0x0003, -
    -  ACONFIGURATION_DENSITY_DEFAULT = 0, -ACONFIGURATION_DENSITY_LOW = 120, -ACONFIGURATION_DENSITY_MEDIUM = 160, -ACONFIGURATION_DENSITY_TV = 213, -
    -  ACONFIGURATION_DENSITY_HIGH = 240, -ACONFIGURATION_DENSITY_XHIGH = 320, -ACONFIGURATION_DENSITY_XXHIGH = 480, -ACONFIGURATION_DENSITY_XXXHIGH = 640, -
    -  ACONFIGURATION_DENSITY_ANY = 0xfffe, -ACONFIGURATION_DENSITY_NONE = 0xffff, -ACONFIGURATION_KEYBOARD_ANY = 0x0000, -ACONFIGURATION_KEYBOARD_NOKEYS = 0x0001, -
    -  ACONFIGURATION_KEYBOARD_QWERTY = 0x0002, -ACONFIGURATION_KEYBOARD_12KEY = 0x0003, -ACONFIGURATION_NAVIGATION_ANY = 0x0000, -ACONFIGURATION_NAVIGATION_NONAV = 0x0001, -
    -  ACONFIGURATION_NAVIGATION_DPAD = 0x0002, -ACONFIGURATION_NAVIGATION_TRACKBALL = 0x0003, -ACONFIGURATION_NAVIGATION_WHEEL = 0x0004, -ACONFIGURATION_KEYSHIDDEN_ANY = 0x0000, -
    -  ACONFIGURATION_KEYSHIDDEN_NO = 0x0001, -ACONFIGURATION_KEYSHIDDEN_YES = 0x0002, -ACONFIGURATION_KEYSHIDDEN_SOFT = 0x0003, -ACONFIGURATION_NAVHIDDEN_ANY = 0x0000, -
    -  ACONFIGURATION_NAVHIDDEN_NO = 0x0001, -ACONFIGURATION_NAVHIDDEN_YES = 0x0002, -ACONFIGURATION_SCREENSIZE_ANY = 0x00, -ACONFIGURATION_SCREENSIZE_SMALL = 0x01, -
    -  ACONFIGURATION_SCREENSIZE_NORMAL = 0x02, -ACONFIGURATION_SCREENSIZE_LARGE = 0x03, -ACONFIGURATION_SCREENSIZE_XLARGE = 0x04, -ACONFIGURATION_SCREENLONG_ANY = 0x00, -
    -  ACONFIGURATION_SCREENLONG_NO = 0x1, -ACONFIGURATION_SCREENLONG_YES = 0x2, -ACONFIGURATION_UI_MODE_TYPE_ANY = 0x00, -ACONFIGURATION_UI_MODE_TYPE_NORMAL = 0x01, -
    -  ACONFIGURATION_UI_MODE_TYPE_DESK = 0x02, -ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03, -ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04, -ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05, -
    -  ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06, -ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00, -ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1, -ACONFIGURATION_UI_MODE_NIGHT_YES = 0x2, -
    -  ACONFIGURATION_SCREEN_WIDTH_DP_ANY = 0x0000, -ACONFIGURATION_SCREEN_HEIGHT_DP_ANY = 0x0000, -ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY = 0x0000, -ACONFIGURATION_LAYOUTDIR_ANY = 0x00, -
    -  ACONFIGURATION_LAYOUTDIR_LTR = 0x01, -ACONFIGURATION_LAYOUTDIR_RTL = 0x02, -ACONFIGURATION_MCC = 0x0001, -ACONFIGURATION_MNC = 0x0002, -
    -  ACONFIGURATION_LOCALE = 0x0004, -ACONFIGURATION_TOUCHSCREEN = 0x0008, -ACONFIGURATION_KEYBOARD = 0x0010, -ACONFIGURATION_KEYBOARD_HIDDEN = 0x0020, -
    -  ACONFIGURATION_NAVIGATION = 0x0040, -ACONFIGURATION_ORIENTATION = 0x0080, -ACONFIGURATION_DENSITY = 0x0100, -ACONFIGURATION_SCREEN_SIZE = 0x0200, -
    -  ACONFIGURATION_VERSION = 0x0400, -ACONFIGURATION_SCREEN_LAYOUT = 0x0800, -ACONFIGURATION_UI_MODE = 0x1000, -ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000, -
    -  ACONFIGURATION_LAYOUTDIR = 0x4000, -ACONFIGURATION_MNC_ZERO = 0xffff -
    - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    AConfigurationAConfiguration_new ()
     
    void AConfiguration_delete (AConfiguration *config)
     
    void AConfiguration_fromAssetManager (AConfiguration *out, AAssetManager *am)
     
    void AConfiguration_copy (AConfiguration *dest, AConfiguration *src)
     
    int32_t AConfiguration_getMcc (AConfiguration *config)
     
    void AConfiguration_setMcc (AConfiguration *config, int32_t mcc)
     
    int32_t AConfiguration_getMnc (AConfiguration *config)
     
    void AConfiguration_setMnc (AConfiguration *config, int32_t mnc)
     
    void AConfiguration_getLanguage (AConfiguration *config, char *outLanguage)
     
    void AConfiguration_setLanguage (AConfiguration *config, const char *language)
     
    void AConfiguration_getCountry (AConfiguration *config, char *outCountry)
     
    void AConfiguration_setCountry (AConfiguration *config, const char *country)
     
    int32_t AConfiguration_getOrientation (AConfiguration *config)
     
    void AConfiguration_setOrientation (AConfiguration *config, int32_t orientation)
     
    int32_t AConfiguration_getTouchscreen (AConfiguration *config)
     
    void AConfiguration_setTouchscreen (AConfiguration *config, int32_t touchscreen)
     
    int32_t AConfiguration_getDensity (AConfiguration *config)
     
    void AConfiguration_setDensity (AConfiguration *config, int32_t density)
     
    int32_t AConfiguration_getKeyboard (AConfiguration *config)
     
    void AConfiguration_setKeyboard (AConfiguration *config, int32_t keyboard)
     
    int32_t AConfiguration_getNavigation (AConfiguration *config)
     
    void AConfiguration_setNavigation (AConfiguration *config, int32_t navigation)
     
    int32_t AConfiguration_getKeysHidden (AConfiguration *config)
     
    void AConfiguration_setKeysHidden (AConfiguration *config, int32_t keysHidden)
     
    int32_t AConfiguration_getNavHidden (AConfiguration *config)
     
    void AConfiguration_setNavHidden (AConfiguration *config, int32_t navHidden)
     
    int32_t AConfiguration_getSdkVersion (AConfiguration *config)
     
    void AConfiguration_setSdkVersion (AConfiguration *config, int32_t sdkVersion)
     
    int32_t AConfiguration_getScreenSize (AConfiguration *config)
     
    void AConfiguration_setScreenSize (AConfiguration *config, int32_t screenSize)
     
    int32_t AConfiguration_getScreenLong (AConfiguration *config)
     
    void AConfiguration_setScreenLong (AConfiguration *config, int32_t screenLong)
     
    int32_t AConfiguration_getUiModeType (AConfiguration *config)
     
    void AConfiguration_setUiModeType (AConfiguration *config, int32_t uiModeType)
     
    int32_t AConfiguration_getUiModeNight (AConfiguration *config)
     
    void AConfiguration_setUiModeNight (AConfiguration *config, int32_t uiModeNight)
     
    int32_t AConfiguration_getScreenWidthDp (AConfiguration *config)
     
    void AConfiguration_setScreenWidthDp (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_getScreenHeightDp (AConfiguration *config)
     
    void AConfiguration_setScreenHeightDp (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_getSmallestScreenWidthDp (AConfiguration *config)
     
    void AConfiguration_setSmallestScreenWidthDp (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_getLayoutDirection (AConfiguration *config)
     
    void AConfiguration_setLayoutDirection (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_diff (AConfiguration *config1, AConfiguration *config2)
     
    int32_t AConfiguration_match (AConfiguration *base, AConfiguration *requested)
     
    int32_t AConfiguration_isBetterThan (AConfiguration *base, AConfiguration *test, AConfiguration *requested)
     
    -
    diff --git a/docs/html/ndk/reference/deprecated.jd b/docs/html/ndk/reference/deprecated.jd deleted file mode 100644 index 0e69db69b92c5ccb9f2b23a43e33946c6a116111..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/deprecated.jd +++ /dev/null @@ -1,23 +0,0 @@ -page.title=Deprecated List -page.customHeadTag= -@jd:body - - -
    -
    -
    Deprecated List
    -
    -
    -
    -
    Global ACONFIGURATION_ORIENTATION_SQUARE
    -
    Not currently supported or used.
    -
    Global ACONFIGURATION_TOUCHSCREEN_STYLUS
    -
    Not currently supported or used.
    -
    Global AWINDOW_FLAG_BLUR_BEHIND
    -
    Blurring is no longer supported.
    -
    Global AWINDOW_FLAG_DITHER
    -
    This flag is no longer used.
    -
    Global AWINDOW_FLAG_TOUCHABLE_WHEN_WAKING
    -
    This flag has no effect.
    -
    -
    diff --git a/docs/html/ndk/reference/dir_035c76f7235f5f563d38e3ab90cb9716.jd b/docs/html/ndk/reference/dir_035c76f7235f5f563d38e3ab90cb9716.jd deleted file mode 100644 index 025427afbc407412bdd21a5135d8d4a08cc01fb5..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/dir_035c76f7235f5f563d38e3ab90cb9716.jd +++ /dev/null @@ -1,49 +0,0 @@ -page.title=android Directory Reference -page.customHeadTag= -@jd:body - - - -
    -
    -
    android Directory Reference
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Files

    file  asset_manager.h
     
    file  asset_manager_jni.h
     
    file  bitmap.h
     
    file  configuration.h
     
    file  input.h
     
    file  keycodes.h
     
    file  looper.h
     
    file  native_activity.h
     
    file  native_window.h
     
    file  native_window_jni.h
     
    file  obb.h
     
    file  rect.h
     
    file  sensor.h
     
    file  storage_manager.h
     
    file  window.h
     
    -
    diff --git a/docs/html/ndk/reference/dir_d44c64559bbebec7f509842c48db8b23.jd b/docs/html/ndk/reference/dir_d44c64559bbebec7f509842c48db8b23.jd deleted file mode 100644 index e42811edb7ea9280689048ebb8519e21782951ef..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/dir_d44c64559bbebec7f509842c48db8b23.jd +++ /dev/null @@ -1,21 +0,0 @@ -page.title=include Directory Reference -page.customHeadTag= -@jd:body - - - -
    -
    -
    include Directory Reference
    -
    -
    - - - - -

    -Directories

    directory  android
     
    -
    diff --git a/docs/html/ndk/reference/doxygen-dac.css b/docs/html/ndk/reference/doxygen-dac.css deleted file mode 100644 index 96b6d84378c0f4c84e1b7a26b5330f59384c99dc..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/doxygen-dac.css +++ /dev/null @@ -1,53 +0,0 @@ -#jd-content td { -} - -#jd-content table { - background-color: transparent; - width: 100%; -} - -#jd-content tr.heading td { - background-color: #999; - padding: 0px 12px; -} - -#jd-content tr.heading h2 { - font-size: 14px; - font-weight: bold; - font-family: Roboto, sans-serif; - margin: 0px; - color: #fff; -} - -#jd-content tr.heading hr, #jd-content td.memSeparator, #jd-content div.headertitle { - display: none; -} - - -#jd-content table td.memItemLeft { - text-align: right; - width: 20%; -} - -#jd-content table td.memItemRight { -} - -#jd-content div.memproto { - font-size: 1.15em; - background-color: #e2e2e2; - padding: 3px; -} - -#jd-content div.memproto table { - margin: 0px; - width: auto; -} - -#jd-content table.memname td { - border: none; - padding: 2px; -} - -#jd-content div.memdoc { - margin: 7px 18px; -} diff --git a/docs/html/ndk/reference/doxygen.css b/docs/html/ndk/reference/doxygen.css deleted file mode 100644 index 94f4bf2cc35cebd374fd1b04e614b7918019ffac..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/doxygen.css +++ /dev/null @@ -1,1366 +0,0 @@ -/* The standard CSS for doxygen 1.8.6 */ - -body, table, div, p, dl { - font: 400 14px/22px Roboto,sans-serif; -} - -/* @group Heading Levels */ - -h1.groupheader { - font-size: 150%; -} - -.title { - font: 400 14px/28px Roboto,sans-serif; - font-size: 150%; - font-weight: bold; - margin: 10px 2px; -} - -h2.groupheader { - border-bottom: 1px solid #A9A9A9; - color: #585858; - font-size: 150%; - font-weight: normal; - margin-top: 1.75em; - padding-top: 8px; - padding-bottom: 4px; - width: 100%; -} - -h3.groupheader { - font-size: 100%; -} - -h1, h2, h3, h4, h5, h6 { - -webkit-transition: text-shadow 0.5s linear; - -moz-transition: text-shadow 0.5s linear; - -ms-transition: text-shadow 0.5s linear; - -o-transition: text-shadow 0.5s linear; - transition: text-shadow 0.5s linear; - margin-right: 15px; -} - -h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { - text-shadow: 0 0 15px cyan; -} - -dt { - font-weight: bold; -} - -div.multicol { - -moz-column-gap: 1em; - -webkit-column-gap: 1em; - -moz-column-count: 3; - -webkit-column-count: 3; -} - -p.startli, p.startdd { - margin-top: 2px; -} - -p.starttd { - margin-top: 0px; -} - -p.endli { - margin-bottom: 0px; -} - -p.enddd { - margin-bottom: 4px; -} - -p.endtd { - margin-bottom: 2px; -} - -/* @end */ - -caption { - font-weight: bold; -} - -span.legend { - font-size: 70%; - text-align: center; -} - -h3.version { - font-size: 90%; - text-align: center; -} - -div.qindex, div.navtab{ - background-color: #F1F1F1; - border: 1px solid #BDBDBD; - text-align: center; -} - -div.qindex, div.navpath { - width: 100%; - line-height: 140%; -} - -div.navtab { - margin-right: 15px; -} - -/* @group Link Styling */ - -a { - color: #646464; - font-weight: normal; - text-decoration: none; -} - -.contents a:visited { - color: #747474; -} - -a:hover { - text-decoration: underline; -} - -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: #B8B8B8; - color: #ffffff; - border: 1px double #A8A8A8; -} - -.contents a.qindexHL:visited { - color: #ffffff; -} - -a.el { - font-weight: bold; -} - -a.elRef { -} - -a.code, a.code:visited, a.line, a.line:visited { - color: #4665A2; -} - -a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { - color: #4665A2; -} - -/* @end */ - -dl.el { - margin-left: -1cm; -} - -pre.fragment { - border: 1px solid #C4CFE5; - background-color: #FBFCFD; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; - font-family: monospace, fixed; - font-size: 105%; -} - -div.fragment { - padding: 4px 6px; - margin: 4px 8px 4px 2px; - background-color: #FCFCFC; - border: 1px solid #D5D5D5; -} - -div.line { - font-family: monospace, fixed; - font-size: 13px; - min-height: 13px; - line-height: 1.0; - text-wrap: unrestricted; - white-space: -moz-pre-wrap; /* Moz */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: pre-wrap; /* CSS3 */ - word-wrap: break-word; /* IE 5.5+ */ - text-indent: -53px; - padding-left: 53px; - padding-bottom: 0px; - margin: 0px; - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -div.line.glow { - background-color: cyan; - box-shadow: 0 0 10px cyan; -} - - -span.lineno { - padding-right: 4px; - text-align: right; - border-right: 2px solid #0F0; - background-color: #E8E8E8; - white-space: pre; -} -span.lineno a { - background-color: #D8D8D8; -} - -span.lineno a:hover { - background-color: #C8C8C8; -} - -div.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px; - padding: 0.2em; - border: solid thin #333; - border-radius: 0.5em; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - box-shadow: 2px 2px 3px #999; - -webkit-box-shadow: 2px 2px 3px #999; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); - background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); -} - -div.groupHeader { - margin-left: 16px; - margin-top: 12px; - font-weight: bold; -} - -div.groupText { - margin-left: 16px; - font-style: italic; -} - -body { - background-color: white; - color: black; - margin: 0; -} - -div.contents { - margin-top: 10px; - margin-left: 12px; - margin-right: 8px; -} - -td.indexkey { - background-color: #F1F1F1; - font-weight: bold; - border: 1px solid #D5D5D5; - margin: 2px 0px 2px 0; - padding: 2px 10px; - white-space: nowrap; - vertical-align: top; -} - -td.indexvalue { - background-color: #F1F1F1; - border: 1px solid #D5D5D5; - padding: 2px 10px; - margin: 2px 0px; -} - -tr.memlist { - background-color: #F2F2F2; -} - -p.formulaDsp { - text-align: center; -} - -img.formulaDsp { - -} - -img.formulaInl { - vertical-align: middle; -} - -div.center { - text-align: center; - margin-top: 0px; - margin-bottom: 0px; - padding: 0px; -} - -div.center img { - border: 0px; -} - -address.footer { - text-align: right; - padding-right: 12px; -} - -img.footer { - border: 0px; - vertical-align: middle; -} - -/* @group Code Colorization */ - -span.keyword { - color: #008000 -} - -span.keywordtype { - color: #604020 -} - -span.keywordflow { - color: #e08000 -} - -span.comment { - color: #800000 -} - -span.preprocessor { - color: #806020 -} - -span.stringliteral { - color: #002080 -} - -span.charliteral { - color: #008080 -} - -span.vhdldigit { - color: #ff00ff -} - -span.vhdlchar { - color: #000000 -} - -span.vhdlkeyword { - color: #700070 -} - -span.vhdllogic { - color: #ff0000 -} - -blockquote { - background-color: #F9F9F9; - border-left: 2px solid #B8B8B8; - margin: 0 24px 0 4px; - padding: 0 12px 0 16px; -} - -/* @end */ - -/* -.search { - color: #003399; - font-weight: bold; -} - -form.search { - margin-bottom: 0px; - margin-top: 0px; -} - -input.search { - font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} -*/ - -td.tiny { - font-size: 75%; -} - -.dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #BDBDBD; -} - -th.dirtab { - background: #F1F1F1; - font-weight: bold; -} - -hr { - height: 0px; - border: none; - border-top: 1px solid #7A7A7A; -} - -hr.footer { - height: 1px; -} - -/* @group Member Descriptions */ - -table.memberdecls { - border-spacing: 0px; - padding: 0px; -} - -.memberdecls td, .fieldtable tr { - -webkit-transition-property: background-color, box-shadow; - -webkit-transition-duration: 0.5s; - -moz-transition-property: background-color, box-shadow; - -moz-transition-duration: 0.5s; - -ms-transition-property: background-color, box-shadow; - -ms-transition-duration: 0.5s; - -o-transition-property: background-color, box-shadow; - -o-transition-duration: 0.5s; - transition-property: background-color, box-shadow; - transition-duration: 0.5s; -} - -.memberdecls td.glow, .fieldtable tr.glow { - background-color: cyan; - box-shadow: 0 0 15px cyan; -} - -.mdescLeft, .mdescRight, -.memItemLeft, .memItemRight, -.memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #FAFAFA; - border: none; - margin: 4px; - padding: 1px 0 0 8px; -} - -.mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; -} - -.memSeparator { - border-bottom: 1px solid #DEE4F0; - line-height: 1px; - margin: 0px; - padding: 0px; -} - -.memItemLeft, .memTemplItemLeft { - white-space: nowrap; -} - -.memItemRight { - width: 100%; -} - -.memTemplParams { - color: #747474; - white-space: nowrap; - font-size: 80%; -} - -/* @end */ - -/* @group Member Details */ - -/* Styles for detailed member documentation */ - -.memtemplate { - font-size: 80%; - color: #747474; - font-weight: normal; - margin-left: 9px; -} - -.memnav { - background-color: #F1F1F1; - border: 1px solid #BDBDBD; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} - -.mempage { - width: 100%; -} - -.memitem { - padding: 0; - margin-bottom: 10px; - margin-right: 5px; - -webkit-transition: box-shadow 0.5s linear; - -moz-transition: box-shadow 0.5s linear; - -ms-transition: box-shadow 0.5s linear; - -o-transition: box-shadow 0.5s linear; - transition: box-shadow 0.5s linear; - display: table !important; - width: 100%; -} - -.memitem.glow { - box-shadow: 0 0 15px cyan; -} - -.memname { - font-weight: bold; - margin-left: 6px; -} - -.memname td { - vertical-align: bottom; -} - -.memproto, dl.reflist dt { - border-top: 1px solid #C0C0C0; - border-left: 1px solid #C0C0C0; - border-right: 1px solid #C0C0C0; - padding: 6px 0px 6px 0px; - color: #3D3D3D; - font-weight: bold; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #EAEAEA; - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 4px; - border-top-left-radius: 4px; - /* firefox specific markup */ - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; - /* webkit specific markup */ - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - -} - -.memdoc, dl.reflist dd { - border-bottom: 1px solid #C0C0C0; - border-left: 1px solid #C0C0C0; - border-right: 1px solid #C0C0C0; - padding: 6px 10px 2px 10px; - background-color: #FCFCFC; - border-top-width: 0; - background-image:url('nav_g.png'); - background-repeat:repeat-x; - background-color: #FFFFFF; - /* opera specific markup */ - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - /* firefox specific markup */ - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-bottomright: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - /* webkit specific markup */ - -webkit-border-bottom-left-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -} - -dl.reflist dt { - padding: 5px; -} - -dl.reflist dd { - margin: 0px 0px 10px 0px; - padding: 5px; -} - -.paramkey { - text-align: right; -} - -.paramtype { - white-space: nowrap; -} - -.paramname { - color: #602020; - white-space: nowrap; -} -.paramname em { - font-style: normal; -} -.paramname code { - line-height: 14px; -} - -.params, .retval, .exception, .tparams { - margin-left: 0px; - padding-left: 0px; -} - -.params .paramname, .retval .paramname { - font-weight: bold; - vertical-align: top; -} - -.params .paramtype { - font-style: italic; - vertical-align: top; -} - -.params .paramdir { - font-family: "courier new",courier,monospace; - vertical-align: top; -} - -table.mlabels { - border-spacing: 0px; -} - -td.mlabels-left { - width: 100%; - padding: 0px; -} - -td.mlabels-right { - vertical-align: bottom; - padding: 0px; - white-space: nowrap; -} - -span.mlabels { - margin-left: 8px; -} - -span.mlabel { - background-color: #9A9A9A; - border-top:1px solid #848484; - border-left:1px solid #848484; - border-right:1px solid #D5D5D5; - border-bottom:1px solid #D5D5D5; - text-shadow: none; - color: white; - margin-right: 4px; - padding: 2px 3px; - border-radius: 3px; - font-size: 7pt; - white-space: nowrap; - vertical-align: middle; -} - - - -/* @end */ - -/* these are for tree view when not used as main index */ - -div.directory { - margin: 10px 0px; - border-top: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; - width: 100%; -} - -.directory table { - border-collapse:collapse; -} - -.directory td { - margin: 0px; - padding: 0px; - vertical-align: top; -} - -.directory td.entry { - white-space: nowrap; - padding-right: 6px; - padding-top: 3px; -} - -.directory td.entry a { - outline:none; -} - -.directory td.entry a img { - border: none; -} - -.directory td.desc { - width: 100%; - padding-left: 6px; - padding-right: 6px; - padding-top: 3px; - border-left: 1px solid rgba(0,0,0,0.05); -} - -.directory tr.even { - padding-left: 6px; - background-color: #F9F9F9; -} - -.directory img { - vertical-align: -30%; -} - -.directory .levels { - white-space: nowrap; - width: 100%; - text-align: right; - font-size: 9pt; -} - -.directory .levels span { - cursor: pointer; - padding-left: 2px; - padding-right: 2px; - color: #646464; -} - -div.dynheader { - margin-top: 8px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -address { - font-style: normal; - color: #464646; -} - -table.doxtable { - border-collapse:collapse; - margin-top: 4px; - margin-bottom: 4px; -} - -table.doxtable td, table.doxtable th { - border: 1px solid #4A4A4A; - padding: 3px 7px 2px; -} - -table.doxtable th { - background-color: #5B5B5B; - color: #FFFFFF; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; -} - -table.fieldtable { - /*width: 100%;*/ - margin-bottom: 10px; - border: 1px solid #C0C0C0; - border-spacing: 0px; - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); - box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); -} - -.fieldtable td, .fieldtable th { - padding: 3px 7px 2px; -} - -.fieldtable td.fieldtype, .fieldtable td.fieldname { - white-space: nowrap; - border-right: 1px solid #C0C0C0; - border-bottom: 1px solid #C0C0C0; - vertical-align: top; -} - -.fieldtable td.fieldname { - padding-top: 3px; -} - -.fieldtable td.fielddoc { - border-bottom: 1px solid #C0C0C0; - /*width: 100%;*/ -} - -.fieldtable td.fielddoc p:first-child { - margin-top: 0px; -} - -.fieldtable td.fielddoc p:last-child { - margin-bottom: 2px; -} - -.fieldtable tr:last-child td { - border-bottom: none; -} - -.fieldtable th { - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #EAEAEA; - font-size: 90%; - color: #3D3D3D; - padding-bottom: 4px; - padding-top: 5px; - text-align:left; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom: 1px solid #C0C0C0; -} - - -.tabsearch { - top: 0px; - left: 10px; - height: 36px; - background-image: url('tab_b.png'); - z-index: 101; - overflow: hidden; - font-size: 13px; -} - -.navpath ul -{ - font-size: 11px; - background-image:url('tab_b.png'); - background-repeat:repeat-x; - background-position: 0 -5px; - height:30px; - line-height:30px; - color:#ABABAB; - border:solid 1px #D3D3D3; - overflow:hidden; - margin:0px; - padding:0px; -} - -.navpath li -{ - list-style-type:none; - float:left; - padding-left:10px; - padding-right:15px; - background-image:url('bc_s.png'); - background-repeat:no-repeat; - background-position:right; - color:#595959; -} - -.navpath li.navelem a -{ - height:32px; - display:block; - text-decoration: none; - outline: none; - color: #434343; - font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; -} - -.navpath li.navelem a:hover -{ - color:#929292; -} - -.navpath li.footer -{ - list-style-type:none; - float:right; - padding-left:10px; - padding-right:15px; - background-image:none; - background-repeat:no-repeat; - background-position:right; - color:#595959; - font-size: 8pt; -} - - -div.summary -{ - float: right; - font-size: 8pt; - padding-right: 5px; - width: 50%; - text-align: right; -} - -div.summary a -{ - white-space: nowrap; -} - -div.ingroups -{ - font-size: 8pt; - width: 50%; - text-align: left; -} - -div.ingroups a -{ - white-space: nowrap; -} - -div.header -{ - background-image:url('nav_h.png'); - background-repeat:repeat-x; - background-color: #FAFAFA; - margin: 0px; - border-bottom: 1px solid #D5D5D5; -} - -div.headertitle -{ - padding: 5px 5px 5px 10px; -} - -dl -{ - padding: 0 0 0 10px; -} - -/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ -dl.section -{ - margin-left: 0px; - padding-left: 0px; -} - -dl.note -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #D0C000; -} - -dl.warning, dl.attention -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #FF0000; -} - -dl.pre, dl.post, dl.invariant -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #00D000; -} - -dl.deprecated -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #505050; -} - -dl.todo -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #00C0E0; -} - -dl.test -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #3030E0; -} - -dl.bug -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #C08050; -} - -dl.section dd { - margin-bottom: 6px; -} - - -#projectlogo -{ - text-align: center; - vertical-align: bottom; - border-collapse: separate; -} - -#projectlogo img -{ - border: 0px none; -} - -#projectname -{ - font: 300% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 2px 0px; -} - -#projectbrief -{ - font: 120% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#projectnumber -{ - font: 50% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#titlearea -{ - padding: 0px; - margin: 0px; - width: 100%; - border-bottom: 1px solid #848484; -} - -.image -{ - text-align: center; -} - -.dotgraph -{ - text-align: center; -} - -.mscgraph -{ - text-align: center; -} - -.diagraph -{ - text-align: center; -} - -.caption -{ - font-weight: bold; -} - -div.zoom -{ - border: 1px solid #AFAFAF; -} - -dl.citelist { - margin-bottom:50px; -} - -dl.citelist dt { - color:#545454; - float:left; - font-weight:bold; - margin-right:10px; - padding:5px; -} - -dl.citelist dd { - margin:2px 0; - padding:5px 0; -} - -div.toc { - padding: 14px 25px; - background-color: #F7F7F7; - border: 1px solid #E3E3E3; - border-radius: 7px 7px 7px 7px; - float: right; - height: auto; - margin: 0 20px 10px 10px; - width: 200px; -} - -div.toc li { - background: url("bdwn.png") no-repeat scroll 0 5px transparent; - font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; - margin-top: 5px; - padding-left: 10px; - padding-top: 2px; -} - -div.toc h3 { - font: bold 12px/1.2 Arial,FreeSans,sans-serif; - color: #747474; - border-bottom: 0 none; - margin: 0; -} - -div.toc ul { - list-style: none outside none; - border: medium none; - padding: 0px; -} - -div.toc li.level1 { - margin-left: 0px; -} - -div.toc li.level2 { - margin-left: 15px; -} - -div.toc li.level3 { - margin-left: 30px; -} - -div.toc li.level4 { - margin-left: 45px; -} - -.inherit_header { - font-weight: bold; - color: gray; - cursor: pointer; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.inherit_header td { - padding: 6px 0px 2px 5px; -} - -.inherit { - display: none; -} - -tr.heading h2 { - margin-top: 12px; - margin-bottom: 4px; -} - -/* tooltip related style info */ - -.ttc { - position: absolute; - display: none; -} - -#powerTip { - cursor: default; - white-space: nowrap; - background-color: white; - border: 1px solid gray; - border-radius: 4px 4px 4px 4px; - box-shadow: 1px 1px 7px gray; - display: none; - font-size: smaller; - max-width: 80%; - opacity: 0.9; - padding: 1ex 1em 1em; - position: absolute; - z-index: 2147483647; -} - -#powerTip div.ttdoc { - color: grey; - font-style: italic; -} - -#powerTip div.ttname a { - font-weight: bold; -} - -#powerTip div.ttname { - font-weight: bold; -} - -#powerTip div.ttdeci { - color: #006318; -} - -#powerTip div { - margin: 0px; - padding: 0px; - font: 12px/16px Roboto,sans-serif; -} - -#powerTip:before, #powerTip:after { - content: ""; - position: absolute; - margin: 0px; -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.s:after, #powerTip.s:before, -#powerTip.w:after, #powerTip.w:before, -#powerTip.e:after, #powerTip.e:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.nw:after, #powerTip.nw:before, -#powerTip.sw:after, #powerTip.sw:before { - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; -} - -#powerTip.n:after, #powerTip.s:after, -#powerTip.w:after, #powerTip.e:after, -#powerTip.nw:after, #powerTip.ne:after, -#powerTip.sw:after, #powerTip.se:after { - border-color: rgba(255, 255, 255, 0); -} - -#powerTip.n:before, #powerTip.s:before, -#powerTip.w:before, #powerTip.e:before, -#powerTip.nw:before, #powerTip.ne:before, -#powerTip.sw:before, #powerTip.se:before { - border-color: rgba(128, 128, 128, 0); -} - -#powerTip.n:after, #powerTip.n:before, -#powerTip.ne:after, #powerTip.ne:before, -#powerTip.nw:after, #powerTip.nw:before { - top: 100%; -} - -#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { - border-top-color: #ffffff; - border-width: 10px; - margin: 0px -10px; -} -#powerTip.n:before { - border-top-color: #808080; - border-width: 11px; - margin: 0px -11px; -} -#powerTip.n:after, #powerTip.n:before { - left: 50%; -} - -#powerTip.nw:after, #powerTip.nw:before { - right: 14px; -} - -#powerTip.ne:after, #powerTip.ne:before { - left: 14px; -} - -#powerTip.s:after, #powerTip.s:before, -#powerTip.se:after, #powerTip.se:before, -#powerTip.sw:after, #powerTip.sw:before { - bottom: 100%; -} - -#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { - border-bottom-color: #ffffff; - border-width: 10px; - margin: 0px -10px; -} - -#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { - border-bottom-color: #808080; - border-width: 11px; - margin: 0px -11px; -} - -#powerTip.s:after, #powerTip.s:before { - left: 50%; -} - -#powerTip.sw:after, #powerTip.sw:before { - right: 14px; -} - -#powerTip.se:after, #powerTip.se:before { - left: 14px; -} - -#powerTip.e:after, #powerTip.e:before { - left: 100%; -} -#powerTip.e:after { - border-left-color: #ffffff; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.e:before { - border-left-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -#powerTip.w:after, #powerTip.w:before { - right: 100%; -} -#powerTip.w:after { - border-right-color: #ffffff; - border-width: 10px; - top: 50%; - margin-top: -10px; -} -#powerTip.w:before { - border-right-color: #808080; - border-width: 11px; - top: 50%; - margin-top: -11px; -} - -@media print -{ - #top { display: none; } - #side-nav { display: none; } - #nav-path { display: none; } - body { overflow:visible; } - h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } - .summary { display: none; } - .memitem { page-break-inside: avoid; } - #doc-content - { - margin-left:0 !important; - height:auto !important; - width:auto !important; - overflow:inherit; - display:inline; - } -} - diff --git a/docs/html/ndk/reference/doxygen.png b/docs/html/ndk/reference/doxygen.png deleted file mode 100644 index da7e8aa7670c5559c8c1ee1405452e327c0c848d..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/doxygen.png and /dev/null differ diff --git a/docs/html/ndk/reference/dynsections.js b/docs/html/ndk/reference/dynsections.js deleted file mode 100644 index ed092c7f63048744a471efe72517e5b1af0613aa..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/dynsections.js +++ /dev/null @@ -1,97 +0,0 @@ -function toggleVisibility(linkObj) -{ - var base = $(linkObj).attr('id'); - var summary = $('#'+base+'-summary'); - var content = $('#'+base+'-content'); - var trigger = $('#'+base+'-trigger'); - var src=$(trigger).attr('src'); - if (content.is(':visible')===true) { - content.hide(); - summary.show(); - $(linkObj).addClass('closed').removeClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); - } else { - content.show(); - summary.hide(); - $(linkObj).removeClass('closed').addClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); - } - return false; -} - -function updateStripes() -{ - $('table.directory tr'). - removeClass('even').filter(':visible:even').addClass('even'); -} -function toggleLevel(level) -{ - $('table.directory tr').each(function(){ - var l = this.id.split('_').length-1; - var i = $('#img'+this.id.substring(3)); - var a = $('#arr'+this.id.substring(3)); - if (l -@jd:body - - -
    -
    -
    File List
    -
    - diff --git a/docs/html/ndk/reference/ftv2blank.png b/docs/html/ndk/reference/ftv2blank.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2blank.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2cl.png b/docs/html/ndk/reference/ftv2cl.png deleted file mode 100644 index d660c7bbe88349cdf68f8934adbf7c90409fab0b..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2cl.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2doc.png b/docs/html/ndk/reference/ftv2doc.png deleted file mode 100644 index 7f92e54f9bbca8844816fcd6aa869e13e3bdff4c..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2doc.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2folderclosed.png b/docs/html/ndk/reference/ftv2folderclosed.png deleted file mode 100644 index 359f2073ab18d12249da8c0f63e64dac853836f1..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2folderclosed.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2folderopen.png b/docs/html/ndk/reference/ftv2folderopen.png deleted file mode 100644 index c5103edcf80a08734d0294af7544a792605a3814..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2folderopen.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2lastnode.png b/docs/html/ndk/reference/ftv2lastnode.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2lastnode.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2link.png b/docs/html/ndk/reference/ftv2link.png deleted file mode 100644 index 7f92e54f9bbca8844816fcd6aa869e13e3bdff4c..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2link.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2mlastnode.png b/docs/html/ndk/reference/ftv2mlastnode.png deleted file mode 100644 index 9d1437d2010806e6ce1610d15a7ec44fbce925df..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2mlastnode.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2mnode.png b/docs/html/ndk/reference/ftv2mnode.png deleted file mode 100644 index 9d1437d2010806e6ce1610d15a7ec44fbce925df..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2mnode.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2mo.png b/docs/html/ndk/reference/ftv2mo.png deleted file mode 100644 index e2513ee47eaef5279ea8ff75de8487dd186fe0c4..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2mo.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2node.png b/docs/html/ndk/reference/ftv2node.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2node.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2ns.png b/docs/html/ndk/reference/ftv2ns.png deleted file mode 100644 index c61a541e88e66b1c74582ad0eda4a97907cf033b..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2ns.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2plastnode.png b/docs/html/ndk/reference/ftv2plastnode.png deleted file mode 100644 index a2fffb6fcffd16be189938656c53c9d2c7a52a01..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2plastnode.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2pnode.png b/docs/html/ndk/reference/ftv2pnode.png deleted file mode 100644 index a2fffb6fcffd16be189938656c53c9d2c7a52a01..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2pnode.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2splitbar.png b/docs/html/ndk/reference/ftv2splitbar.png deleted file mode 100644 index 343046b612b0bef5191e66080ff3bff2338a121e..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2splitbar.png and /dev/null differ diff --git a/docs/html/ndk/reference/ftv2vertline.png b/docs/html/ndk/reference/ftv2vertline.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/ftv2vertline.png and /dev/null differ diff --git a/docs/html/ndk/reference/functions.jd b/docs/html/ndk/reference/functions.jd deleted file mode 100644 index fade0d5adba10d2f7366212c28ae3de5ca12f25d..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/functions.jd +++ /dev/null @@ -1,327 +0,0 @@ -page.title=Data Fields -page.customHeadTag= -@jd:body - - -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - a -

    - - -

    - b -

    - - -

    - c -

    - - -

    - d -

    - - -

    - e -

    - - -

    - f -

    - - -

    - h -

    - - -

    - i -

    - - -

    - l -

    - - -

    - m -

    - - -

    - o -

    - - -

    - p -

    - - -

    - r -

    - - -

    - s -

    - - -

    - t -

    - - -

    - u -

    - - -

    - v -

    - - -

    - w -

    - - -

    - x -

    - - -

    - y -

    - - -

    - z -

    -
    diff --git a/docs/html/ndk/reference/functions_vars.jd b/docs/html/ndk/reference/functions_vars.jd deleted file mode 100644 index 129c7ecd19f85ba6e5df3241a83e6b867211a2e1..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/functions_vars.jd +++ /dev/null @@ -1,327 +0,0 @@ -page.title=Data Fields - Variables -page.customHeadTag= -@jd:body - - -
    -  - -

    - a -

    - - -

    - b -

    - - -

    - c -

    - - -

    - d -

    - - -

    - e -

    - - -

    - f -

    - - -

    - h -

    - - -

    - i -

    - - -

    - l -

    - - -

    - m -

    - - -

    - o -

    - - -

    - p -

    - - -

    - r -

    - - -

    - s -

    - - -

    - t -

    - - -

    - u -

    - - -

    - v -

    - - -

    - w -

    - - -

    - x -

    - - -

    - y -

    - - -

    - z -

    -
    diff --git a/docs/html/ndk/reference/globals.jd b/docs/html/ndk/reference/globals.jd deleted file mode 100644 index cb6dc11e2c09ce9e19184309505b73a2dcea7ec5..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals.jd +++ /dev/null @@ -1,2294 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - a -

    -
    diff --git a/docs/html/ndk/reference/globals_defs.jd b/docs/html/ndk/reference/globals_defs.jd deleted file mode 100644 index 8d04efb2663d931c9a5de88935136837d287ea52..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_defs.jd +++ /dev/null @@ -1,24 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
      -
    • AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT -: input.h -
    • -
    • ANDROID_BITMAP_RESUT_SUCCESS -: bitmap.h -
    • -
    • ASENSOR_MAGNETIC_FIELD_EARTH_MAX -: sensor.h -
    • -
    • ASENSOR_MAGNETIC_FIELD_EARTH_MIN -: sensor.h -
    • -
    • ASENSOR_STANDARD_GRAVITY -: sensor.h -
    • -
    -
    diff --git a/docs/html/ndk/reference/globals_enum.jd b/docs/html/ndk/reference/globals_enum.jd deleted file mode 100644 index 7fd396eb5c89907cf9e164a3a4c3a8f87bbaa0e3..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_enum.jd +++ /dev/null @@ -1,12 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -
    diff --git a/docs/html/ndk/reference/globals_eval.jd b/docs/html/ndk/reference/globals_eval.jd deleted file mode 100644 index e1399c7177af5c2c9b8ecd79c6b7b4b291c5a0ab..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_eval.jd +++ /dev/null @@ -1,1652 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -  - -

    - a -

    -
    diff --git a/docs/html/ndk/reference/globals_eval_w.jd b/docs/html/ndk/reference/globals_eval_w.jd deleted file mode 100644 index c996d30350bf5206b16fd491ea956030db26ba2a..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_eval_w.jd +++ /dev/null @@ -1,20 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -  - -

    - w -

    -
    diff --git a/docs/html/ndk/reference/globals_func.jd b/docs/html/ndk/reference/globals_func.jd deleted file mode 100644 index ae48353895da26763ba4447e603726aee5c5b512..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_func.jd +++ /dev/null @@ -1,551 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -  - -

    - a -

    -
    diff --git a/docs/html/ndk/reference/globals_type.jd b/docs/html/ndk/reference/globals_type.jd deleted file mode 100644 index 99fa85951fe7f7cde1be791890823b46aa792188..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_type.jd +++ /dev/null @@ -1,90 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -
    diff --git a/docs/html/ndk/reference/globals_vars.jd b/docs/html/ndk/reference/globals_vars.jd deleted file mode 100644 index e6bd2a4f90bfdf70254e3f9624bfb4498265f765..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_vars.jd +++ /dev/null @@ -1,12 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -
    diff --git a/docs/html/ndk/reference/globals_w.jd b/docs/html/ndk/reference/globals_w.jd deleted file mode 100644 index b72e8c2ff8161568daabdcbe47e640fdc0dabe9f..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/globals_w.jd +++ /dev/null @@ -1,20 +0,0 @@ -page.title=Globals -page.customHeadTag= -@jd:body - - -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - w -

    -
    diff --git a/docs/html/ndk/reference/group___asset.jd b/docs/html/ndk/reference/group___asset.jd deleted file mode 100644 index c2f9067dc7a71e10037d0da2875b3901ba0e3122..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___asset.jd +++ /dev/null @@ -1,591 +0,0 @@ -page.title=Asset -page.customHeadTag= -@jd:body - - -
    - -
    -
    Asset
    -
    -
    - - - - - - -

    -Files

    file  asset_manager.h
     
    file  asset_manager_jni.h
     
    - - - - - - - -

    -Typedefs

    typedef struct AAssetManager AAssetManager
     
    typedef struct AAssetDir AAssetDir
     
    typedef struct AAsset AAsset
     
    - - - -

    -Enumerations

    enum  { AASSET_MODE_UNKNOWN = 0, -AASSET_MODE_RANDOM = 1, -AASSET_MODE_STREAMING = 2, -AASSET_MODE_BUFFER = 3 - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    AAssetDirAAssetManager_openDir (AAssetManager *mgr, const char *dirName)
     
    AAssetAAssetManager_open (AAssetManager *mgr, const char *filename, int mode)
     
    const char * AAssetDir_getNextFileName (AAssetDir *assetDir)
     
    void AAssetDir_rewind (AAssetDir *assetDir)
     
    void AAssetDir_close (AAssetDir *assetDir)
     
    int AAsset_read (AAsset *asset, void *buf, size_t count)
     
    off_t AAsset_seek (AAsset *asset, off_t offset, int whence)
     
    off64_t AAsset_seek64 (AAsset *asset, off64_t offset, int whence)
     
    void AAsset_close (AAsset *asset)
     
    const void * AAsset_getBuffer (AAsset *asset)
     
    off_t AAsset_getLength (AAsset *asset)
     
    off64_t AAsset_getLength64 (AAsset *asset)
     
    off_t AAsset_getRemainingLength (AAsset *asset)
     
    off64_t AAsset_getRemainingLength64 (AAsset *asset)
     
    int AAsset_openFileDescriptor (AAsset *asset, off_t *outStart, off_t *outLength)
     
    int AAsset_openFileDescriptor64 (AAsset *asset, off64_t *outStart, off64_t *outLength)
     
    int AAsset_isAllocated (AAsset *asset)
     
    AAssetManagerAAssetManager_fromJava (JNIEnv *env, jobject assetManager)
     
    -

    Detailed Description

    -

    Typedef Documentation

    - -
    -
    - - - - -
    typedef struct AAsset AAsset
    -
    -

    AAsset provides access to a read-only asset.

    -

    AAsset objects are NOT thread-safe, and should not be shared across threads.

    - -
    -
    - -
    -
    - - - - -
    typedef struct AAssetDir AAssetDir
    -
    -

    AAssetDir provides access to a chunk of the asset hierarchy as if it were a single directory. The contents are populated by the AAssetManager.

    -

    The list of files will be sorted in ascending order by ASCII value.

    - -
    -
    - -
    -
    - - - - -
    typedef struct AAssetManager AAssetManager
    -
    -

    AAssetManager provides access to an application's raw assets by creating AAsset objects.

    -

    AAssetManager is a wrapper to the low-level native implementation of the java AAssetManager, a pointer can be obtained using AAssetManager_fromJava().

    -

    The asset hierarchy may be examined like a filesystem, using AAssetDir objects to peruse a single directory.

    -

    A native AAssetManager pointer may be shared across multiple threads.

    - -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Available access modes for opening assets with AAssetManager_open

    - - - - - -
    Enumerator
    AASSET_MODE_UNKNOWN  -

    No specific information about how data will be accessed.

    -
    AASSET_MODE_RANDOM  -

    Read chunks, and seek forward and backward.

    -
    AASSET_MODE_STREAMING  -

    Read sequentially, with an occasional forward seek.

    -
    AASSET_MODE_BUFFER  -

    Caller plans to ask for a read-only buffer with all data.

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - -
    void AAsset_close (AAssetasset)
    -
    -

    Close the asset, freeing all associated resources.

    - -
    -
    - -
    -
    - - - - - - - - -
    const void* AAsset_getBuffer (AAssetasset)
    -
    -

    Get a pointer to a buffer holding the entire contents of the assset.

    -

    Returns NULL on failure.

    - -
    -
    - -
    -
    - - - - - - - - -
    off_t AAsset_getLength (AAssetasset)
    -
    -

    Report the total size of the asset data.

    - -
    -
    - -
    -
    - - - - - - - - -
    off64_t AAsset_getLength64 (AAssetasset)
    -
    -

    Report the total size of the asset data. Reports the size using a 64-bit number insted of 32-bit as AAsset_getLength.

    - -
    -
    - -
    -
    - - - - - - - - -
    off_t AAsset_getRemainingLength (AAssetasset)
    -
    -

    Report the total amount of asset data that can be read from the current position.

    - -
    -
    - -
    -
    - - - - - - - - -
    off64_t AAsset_getRemainingLength64 (AAssetasset)
    -
    -

    Report the total amount of asset data that can be read from the current position.

    -

    Uses a 64-bit number instead of a 32-bit number as AAsset_getRemainingLength does.

    - -
    -
    - -
    -
    - - - - - - - - -
    int AAsset_isAllocated (AAssetasset)
    -
    -

    Returns whether this asset's internal buffer is allocated in ordinary RAM (i.e. not mmapped).

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int AAsset_openFileDescriptor (AAssetasset,
    off_t * outStart,
    off_t * outLength 
    )
    -
    -

    Open a new file descriptor that can be used to read the asset data. If the start or length cannot be represented by a 32-bit number, it will be truncated. If the file is large, use AAsset_openFileDescriptor64 instead.

    -

    Returns < 0 if direct fd access is not possible (for example, if the asset is compressed).

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int AAsset_openFileDescriptor64 (AAssetasset,
    off64_t * outStart,
    off64_t * outLength 
    )
    -
    -

    Open a new file descriptor that can be used to read the asset data.

    -

    Uses a 64-bit number for the offset and length instead of 32-bit instead of as AAsset_openFileDescriptor does.

    -

    Returns < 0 if direct fd access is not possible (for example, if the asset is compressed).

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int AAsset_read (AAssetasset,
    void * buf,
    size_t count 
    )
    -
    -

    Attempt to read 'count' bytes of data from the current offset.

    -

    Returns the number of bytes read, zero on EOF, or < 0 on error.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    off_t AAsset_seek (AAssetasset,
    off_t offset,
    int whence 
    )
    -
    -

    Seek to the specified offset within the asset data. 'whence' uses the same constants as lseek()/fseek().

    -

    Returns the new position on success, or (off_t) -1 on error.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    off64_t AAsset_seek64 (AAssetasset,
    off64_t offset,
    int whence 
    )
    -
    -

    Seek to the specified offset within the asset data. 'whence' uses the same constants as lseek()/fseek().

    -

    Uses 64-bit data type for large files as opposed to the 32-bit type used by AAsset_seek.

    -

    Returns the new position on success, or (off64_t) -1 on error.

    - -
    -
    - -
    -
    - - - - - - - - -
    void AAssetDir_close (AAssetDirassetDir)
    -
    -

    Close an opened AAssetDir, freeing any related resources.

    - -
    -
    - -
    -
    - - - - - - - - -
    const char* AAssetDir_getNextFileName (AAssetDirassetDir)
    -
    -

    Iterate over the files in an asset directory. A NULL string is returned when all the file names have been returned.

    -

    The returned file name is suitable for passing to AAssetManager_open().

    -

    The string returned here is owned by the AssetDir implementation and is not guaranteed to remain valid if any other calls are made on this AAssetDir instance.

    - -
    -
    - -
    -
    - - - - - - - - -
    void AAssetDir_rewind (AAssetDirassetDir)
    -
    -

    Reset the iteration state of AAssetDir_getNextFileName() to the beginning.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    AAssetManager* AAssetManager_fromJava (JNIEnv * env,
    jobject assetManager 
    )
    -
    -

    Given a Dalvik AssetManager object, obtain the corresponding native AAssetManager object. Note that the caller is responsible for obtaining and holding a VM reference to the jobject to prevent its being garbage collected while the native object is in use.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    AAsset* AAssetManager_open (AAssetManagermgr,
    const char * filename,
    int mode 
    )
    -
    -

    Open an asset.

    -

    The object returned here should be freed by calling AAsset_close().

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    AAssetDir* AAssetManager_openDir (AAssetManagermgr,
    const char * dirName 
    )
    -
    -

    Open the named directory within the asset hierarchy. The directory can then be inspected with the AAssetDir functions. To open the top-level directory, pass in "" as the dirName.

    -

    The object returned here should be freed by calling AAssetDir_close().

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/group___bitmap.jd b/docs/html/ndk/reference/group___bitmap.jd deleted file mode 100644 index 2f2b1999b495d9dbcfc407db3ffde9e13addc1b3..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___bitmap.jd +++ /dev/null @@ -1,230 +0,0 @@ -page.title=Bitmap -page.customHeadTag= -@jd:body - - -
    - -
    -
    Bitmap
    -
    -
    - - - - -

    -Files

    file  bitmap.h
     
    - - - -

    -Data Structures

    struct  AndroidBitmapInfo
     
    - - - -

    -Macros

    #define ANDROID_BITMAP_RESUT_SUCCESS   ANDROID_BITMAP_RESULT_SUCCESS
     
    - - - - - -

    -Enumerations

    enum  { ANDROID_BITMAP_RESULT_SUCCESS = 0, -ANDROID_BITMAP_RESULT_BAD_PARAMETER = -1, -ANDROID_BITMAP_RESULT_JNI_EXCEPTION = -2, -ANDROID_BITMAP_RESULT_ALLOCATION_FAILED = -3 - }
     
    enum  AndroidBitmapFormat {
    -  ANDROID_BITMAP_FORMAT_NONE = 0, -ANDROID_BITMAP_FORMAT_RGBA_8888 = 1, -ANDROID_BITMAP_FORMAT_RGB_565 = 4, -ANDROID_BITMAP_FORMAT_RGBA_4444 = 7, -
    -  ANDROID_BITMAP_FORMAT_A_8 = 8 -
    - }
     
    - - - - - - - -

    -Functions

    int AndroidBitmap_getInfo (JNIEnv *env, jobject jbitmap, AndroidBitmapInfo *info)
     
    int AndroidBitmap_lockPixels (JNIEnv *env, jobject jbitmap, void **addrPtr)
     
    int AndroidBitmap_unlockPixels (JNIEnv *env, jobject jbitmap)
     
    -

    Detailed Description

    -

    Macro Definition Documentation

    - -
    -
    - - - - -
    #define ANDROID_BITMAP_RESUT_SUCCESS   ANDROID_BITMAP_RESULT_SUCCESS
    -
    -

    Backward compatibility: this macro used to be misspelled.

    - -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    AndroidBitmap functions result code.

    - - - - - -
    Enumerator
    ANDROID_BITMAP_RESULT_SUCCESS  -

    Operation was successful.

    -
    ANDROID_BITMAP_RESULT_BAD_PARAMETER  -

    Bad parameter.

    -
    ANDROID_BITMAP_RESULT_JNI_EXCEPTION  -

    JNI exception occured.

    -
    ANDROID_BITMAP_RESULT_ALLOCATION_FAILED  -

    Allocation failed.

    -
    - -
    -
    - -
    -
    - - - - -
    enum AndroidBitmapFormat
    -
    -

    Bitmap pixel format.

    - - - - - - -
    Enumerator
    ANDROID_BITMAP_FORMAT_NONE  -

    No format.

    -
    ANDROID_BITMAP_FORMAT_RGBA_8888  -

    Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits.

    -
    ANDROID_BITMAP_FORMAT_RGB_565  -

    Red: 5 bits, Green: 6 bits, Blue: 5 bits.

    -
    ANDROID_BITMAP_FORMAT_RGBA_4444  -

    Red: 4 bits, Green: 4 bits, Blue: 4 bits, Alpha: 4 bits.

    -
    ANDROID_BITMAP_FORMAT_A_8  -

    Deprecated.

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int AndroidBitmap_getInfo (JNIEnv * env,
    jobject jbitmap,
    AndroidBitmapInfoinfo 
    )
    -
    -

    Given a java bitmap object, fill out the AndroidBitmapInfo struct for it. If the call fails, the info parameter will be ignored.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int AndroidBitmap_lockPixels (JNIEnv * env,
    jobject jbitmap,
    void ** addrPtr 
    )
    -
    -

    Given a java bitmap object, attempt to lock the pixel address. Locking will ensure that the memory for the pixels will not move until the unlockPixels call, and ensure that, if the pixels had been previously purged, they will have been restored.

    -

    If this call succeeds, it must be balanced by a call to AndroidBitmap_unlockPixels, after which time the address of the pixels should no longer be used.

    -

    If this succeeds, *addrPtr will be set to the pixel address. If the call fails, addrPtr will be ignored.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int AndroidBitmap_unlockPixels (JNIEnv * env,
    jobject jbitmap 
    )
    -
    -

    Call this to balance a successful call to AndroidBitmap_lockPixels.

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/group___configuration.jd b/docs/html/ndk/reference/group___configuration.jd deleted file mode 100644 index 708722eb35309b5cf86dee037b89532c6d3c5057..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___configuration.jd +++ /dev/null @@ -1,1557 +0,0 @@ -page.title=Configuration -page.customHeadTag= -@jd:body - - -
    - -
    -
    Configuration
    -
    -
    - - - - -

    -Files

    file  configuration.h
     
    - - - -

    -Typedefs

    typedef struct AConfiguration AConfiguration
     
    - - - -

    -Enumerations

    enum  {
    -  ACONFIGURATION_ORIENTATION_ANY = 0x0000, -ACONFIGURATION_ORIENTATION_PORT = 0x0001, -ACONFIGURATION_ORIENTATION_LAND = 0x0002, -ACONFIGURATION_ORIENTATION_SQUARE = 0x0003, -
    -  ACONFIGURATION_TOUCHSCREEN_ANY = 0x0000, -ACONFIGURATION_TOUCHSCREEN_NOTOUCH = 0x0001, -ACONFIGURATION_TOUCHSCREEN_STYLUS = 0x0002, -ACONFIGURATION_TOUCHSCREEN_FINGER = 0x0003, -
    -  ACONFIGURATION_DENSITY_DEFAULT = 0, -ACONFIGURATION_DENSITY_LOW = 120, -ACONFIGURATION_DENSITY_MEDIUM = 160, -ACONFIGURATION_DENSITY_TV = 213, -
    -  ACONFIGURATION_DENSITY_HIGH = 240, -ACONFIGURATION_DENSITY_XHIGH = 320, -ACONFIGURATION_DENSITY_XXHIGH = 480, -ACONFIGURATION_DENSITY_XXXHIGH = 640, -
    -  ACONFIGURATION_DENSITY_ANY = 0xfffe, -ACONFIGURATION_DENSITY_NONE = 0xffff, -ACONFIGURATION_KEYBOARD_ANY = 0x0000, -ACONFIGURATION_KEYBOARD_NOKEYS = 0x0001, -
    -  ACONFIGURATION_KEYBOARD_QWERTY = 0x0002, -ACONFIGURATION_KEYBOARD_12KEY = 0x0003, -ACONFIGURATION_NAVIGATION_ANY = 0x0000, -ACONFIGURATION_NAVIGATION_NONAV = 0x0001, -
    -  ACONFIGURATION_NAVIGATION_DPAD = 0x0002, -ACONFIGURATION_NAVIGATION_TRACKBALL = 0x0003, -ACONFIGURATION_NAVIGATION_WHEEL = 0x0004, -ACONFIGURATION_KEYSHIDDEN_ANY = 0x0000, -
    -  ACONFIGURATION_KEYSHIDDEN_NO = 0x0001, -ACONFIGURATION_KEYSHIDDEN_YES = 0x0002, -ACONFIGURATION_KEYSHIDDEN_SOFT = 0x0003, -ACONFIGURATION_NAVHIDDEN_ANY = 0x0000, -
    -  ACONFIGURATION_NAVHIDDEN_NO = 0x0001, -ACONFIGURATION_NAVHIDDEN_YES = 0x0002, -ACONFIGURATION_SCREENSIZE_ANY = 0x00, -ACONFIGURATION_SCREENSIZE_SMALL = 0x01, -
    -  ACONFIGURATION_SCREENSIZE_NORMAL = 0x02, -ACONFIGURATION_SCREENSIZE_LARGE = 0x03, -ACONFIGURATION_SCREENSIZE_XLARGE = 0x04, -ACONFIGURATION_SCREENLONG_ANY = 0x00, -
    -  ACONFIGURATION_SCREENLONG_NO = 0x1, -ACONFIGURATION_SCREENLONG_YES = 0x2, -ACONFIGURATION_UI_MODE_TYPE_ANY = 0x00, -ACONFIGURATION_UI_MODE_TYPE_NORMAL = 0x01, -
    -  ACONFIGURATION_UI_MODE_TYPE_DESK = 0x02, -ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03, -ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04, -ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05, -
    -  ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06, -ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00, -ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1, -ACONFIGURATION_UI_MODE_NIGHT_YES = 0x2, -
    -  ACONFIGURATION_SCREEN_WIDTH_DP_ANY = 0x0000, -ACONFIGURATION_SCREEN_HEIGHT_DP_ANY = 0x0000, -ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY = 0x0000, -ACONFIGURATION_LAYOUTDIR_ANY = 0x00, -
    -  ACONFIGURATION_LAYOUTDIR_LTR = 0x01, -ACONFIGURATION_LAYOUTDIR_RTL = 0x02, -ACONFIGURATION_MCC = 0x0001, -ACONFIGURATION_MNC = 0x0002, -
    -  ACONFIGURATION_LOCALE = 0x0004, -ACONFIGURATION_TOUCHSCREEN = 0x0008, -ACONFIGURATION_KEYBOARD = 0x0010, -ACONFIGURATION_KEYBOARD_HIDDEN = 0x0020, -
    -  ACONFIGURATION_NAVIGATION = 0x0040, -ACONFIGURATION_ORIENTATION = 0x0080, -ACONFIGURATION_DENSITY = 0x0100, -ACONFIGURATION_SCREEN_SIZE = 0x0200, -
    -  ACONFIGURATION_VERSION = 0x0400, -ACONFIGURATION_SCREEN_LAYOUT = 0x0800, -ACONFIGURATION_UI_MODE = 0x1000, -ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000, -
    -  ACONFIGURATION_LAYOUTDIR = 0x4000, -ACONFIGURATION_MNC_ZERO = 0xffff -
    - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    AConfigurationAConfiguration_new ()
     
    void AConfiguration_delete (AConfiguration *config)
     
    void AConfiguration_fromAssetManager (AConfiguration *out, AAssetManager *am)
     
    void AConfiguration_copy (AConfiguration *dest, AConfiguration *src)
     
    int32_t AConfiguration_getMcc (AConfiguration *config)
     
    void AConfiguration_setMcc (AConfiguration *config, int32_t mcc)
     
    int32_t AConfiguration_getMnc (AConfiguration *config)
     
    void AConfiguration_setMnc (AConfiguration *config, int32_t mnc)
     
    void AConfiguration_getLanguage (AConfiguration *config, char *outLanguage)
     
    void AConfiguration_setLanguage (AConfiguration *config, const char *language)
     
    void AConfiguration_getCountry (AConfiguration *config, char *outCountry)
     
    void AConfiguration_setCountry (AConfiguration *config, const char *country)
     
    int32_t AConfiguration_getOrientation (AConfiguration *config)
     
    void AConfiguration_setOrientation (AConfiguration *config, int32_t orientation)
     
    int32_t AConfiguration_getTouchscreen (AConfiguration *config)
     
    void AConfiguration_setTouchscreen (AConfiguration *config, int32_t touchscreen)
     
    int32_t AConfiguration_getDensity (AConfiguration *config)
     
    void AConfiguration_setDensity (AConfiguration *config, int32_t density)
     
    int32_t AConfiguration_getKeyboard (AConfiguration *config)
     
    void AConfiguration_setKeyboard (AConfiguration *config, int32_t keyboard)
     
    int32_t AConfiguration_getNavigation (AConfiguration *config)
     
    void AConfiguration_setNavigation (AConfiguration *config, int32_t navigation)
     
    int32_t AConfiguration_getKeysHidden (AConfiguration *config)
     
    void AConfiguration_setKeysHidden (AConfiguration *config, int32_t keysHidden)
     
    int32_t AConfiguration_getNavHidden (AConfiguration *config)
     
    void AConfiguration_setNavHidden (AConfiguration *config, int32_t navHidden)
     
    int32_t AConfiguration_getSdkVersion (AConfiguration *config)
     
    void AConfiguration_setSdkVersion (AConfiguration *config, int32_t sdkVersion)
     
    int32_t AConfiguration_getScreenSize (AConfiguration *config)
     
    void AConfiguration_setScreenSize (AConfiguration *config, int32_t screenSize)
     
    int32_t AConfiguration_getScreenLong (AConfiguration *config)
     
    void AConfiguration_setScreenLong (AConfiguration *config, int32_t screenLong)
     
    int32_t AConfiguration_getUiModeType (AConfiguration *config)
     
    void AConfiguration_setUiModeType (AConfiguration *config, int32_t uiModeType)
     
    int32_t AConfiguration_getUiModeNight (AConfiguration *config)
     
    void AConfiguration_setUiModeNight (AConfiguration *config, int32_t uiModeNight)
     
    int32_t AConfiguration_getScreenWidthDp (AConfiguration *config)
     
    void AConfiguration_setScreenWidthDp (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_getScreenHeightDp (AConfiguration *config)
     
    void AConfiguration_setScreenHeightDp (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_getSmallestScreenWidthDp (AConfiguration *config)
     
    void AConfiguration_setSmallestScreenWidthDp (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_getLayoutDirection (AConfiguration *config)
     
    void AConfiguration_setLayoutDirection (AConfiguration *config, int32_t value)
     
    int32_t AConfiguration_diff (AConfiguration *config1, AConfiguration *config2)
     
    int32_t AConfiguration_match (AConfiguration *base, AConfiguration *requested)
     
    int32_t AConfiguration_isBetterThan (AConfiguration *base, AConfiguration *test, AConfiguration *requested)
     
    -

    Detailed Description

    -

    Typedef Documentation

    - -
    -
    - - - - -
    typedef struct AConfiguration AConfiguration
    -
    -

    AConfiguration is an opaque type used to get and set various subsystem configurations.

    -

    A AConfiguration pointer can be obtained using:

    - - -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Define flags and constants for various subsystem configurations.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Enumerator
    ACONFIGURATION_ORIENTATION_ANY  -

    Orientation: not specified.

    -
    ACONFIGURATION_ORIENTATION_PORT  -

    Orientation: value corresponding to the port resource qualifier.

    -
    ACONFIGURATION_ORIENTATION_LAND  -

    Orientation: value corresponding to the land resource qualifier.

    -
    ACONFIGURATION_ORIENTATION_SQUARE  -
    Deprecated:
    Not currently supported or used.
    -
    ACONFIGURATION_TOUCHSCREEN_ANY  -

    Touchscreen: not specified.

    -
    ACONFIGURATION_TOUCHSCREEN_NOTOUCH  -

    Touchscreen: value corresponding to the notouch resource qualifier.

    -
    ACONFIGURATION_TOUCHSCREEN_STYLUS  -
    Deprecated:
    Not currently supported or used.
    -
    ACONFIGURATION_TOUCHSCREEN_FINGER  -

    Touchscreen: value corresponding to the finger resource qualifier.

    -
    ACONFIGURATION_DENSITY_DEFAULT  -

    Density: default density.

    -
    ACONFIGURATION_DENSITY_LOW  -

    Density: value corresponding to the ldpi resource qualifier.

    -
    ACONFIGURATION_DENSITY_MEDIUM  -

    Density: value corresponding to the mdpi resource qualifier.

    -
    ACONFIGURATION_DENSITY_TV  -

    Density: value corresponding to the tvdpi resource qualifier.

    -
    ACONFIGURATION_DENSITY_HIGH  -

    Density: value corresponding to the hdpi resource qualifier.

    -
    ACONFIGURATION_DENSITY_XHIGH  -

    Density: value corresponding to the xhdpi resource qualifier.

    -
    ACONFIGURATION_DENSITY_XXHIGH  -

    Density: value corresponding to the xxhdpi resource qualifier.

    -
    ACONFIGURATION_DENSITY_XXXHIGH  -

    Density: value corresponding to the xxxhdpi resource qualifier.

    -
    ACONFIGURATION_DENSITY_ANY  -

    Density: any density.

    -
    ACONFIGURATION_DENSITY_NONE  -

    Density: no density specified.

    -
    ACONFIGURATION_KEYBOARD_ANY  -

    Keyboard: not specified.

    -
    ACONFIGURATION_KEYBOARD_NOKEYS  -

    Keyboard: value corresponding to the nokeys resource qualifier.

    -
    ACONFIGURATION_KEYBOARD_QWERTY  -

    Keyboard: value corresponding to the qwerty resource qualifier.

    -
    ACONFIGURATION_KEYBOARD_12KEY  -

    Keyboard: value corresponding to the 12key resource qualifier.

    -
    ACONFIGURATION_NAVIGATION_ANY  -

    Navigation: not specified.

    -
    ACONFIGURATION_NAVIGATION_NONAV  -

    Navigation: value corresponding to the nonav resource qualifier.

    -
    ACONFIGURATION_NAVIGATION_DPAD  -

    Navigation: value corresponding to the dpad resource qualifier.

    -
    ACONFIGURATION_NAVIGATION_TRACKBALL  -

    Navigation: value corresponding to the trackball resource qualifier.

    -
    ACONFIGURATION_NAVIGATION_WHEEL  -

    Navigation: value corresponding to the wheel resource qualifier.

    -
    ACONFIGURATION_KEYSHIDDEN_ANY  -

    Keyboard availability: not specified.

    -
    ACONFIGURATION_KEYSHIDDEN_NO  -

    Keyboard availability: value corresponding to the keysexposed resource qualifier.

    -
    ACONFIGURATION_KEYSHIDDEN_YES  -

    Keyboard availability: value corresponding to the keyshidden resource qualifier.

    -
    ACONFIGURATION_KEYSHIDDEN_SOFT  -

    Keyboard availability: value corresponding to the keyssoft resource qualifier.

    -
    ACONFIGURATION_NAVHIDDEN_ANY  -

    Navigation availability: not specified.

    -
    ACONFIGURATION_NAVHIDDEN_NO  -

    Navigation availability: value corresponding to the navexposed resource qualifier.

    -
    ACONFIGURATION_NAVHIDDEN_YES  -

    Navigation availability: value corresponding to the navhidden resource qualifier.

    -
    ACONFIGURATION_SCREENSIZE_ANY  -

    Screen size: not specified.

    -
    ACONFIGURATION_SCREENSIZE_SMALL  -

    Screen size: value indicating the screen is at least approximately 320x426 dp units, corresponding to the small resource qualifier.

    -
    ACONFIGURATION_SCREENSIZE_NORMAL  -

    Screen size: value indicating the screen is at least approximately 320x470 dp units, corresponding to the normal resource qualifier.

    -
    ACONFIGURATION_SCREENSIZE_LARGE  -

    Screen size: value indicating the screen is at least approximately 480x640 dp units, corresponding to the large resource qualifier.

    -
    ACONFIGURATION_SCREENSIZE_XLARGE  -

    Screen size: value indicating the screen is at least approximately 720x960 dp units, corresponding to the xlarge resource qualifier.

    -
    ACONFIGURATION_SCREENLONG_ANY  -

    Screen layout: not specified.

    -
    ACONFIGURATION_SCREENLONG_NO  -

    Screen layout: value that corresponds to the notlong resource qualifier.

    -
    ACONFIGURATION_SCREENLONG_YES  -

    Screen layout: value that corresponds to the long resource qualifier.

    -
    ACONFIGURATION_UI_MODE_TYPE_ANY  -

    UI mode: not specified.

    -
    ACONFIGURATION_UI_MODE_TYPE_NORMAL  -

    UI mode: value that corresponds to no UI mode type resource qualifier specified.

    -
    ACONFIGURATION_UI_MODE_TYPE_DESK  -

    UI mode: value that corresponds to desk resource qualifier specified.

    -
    ACONFIGURATION_UI_MODE_TYPE_CAR  -

    UI mode: value that corresponds to car resource qualifier specified.

    -
    ACONFIGURATION_UI_MODE_TYPE_TELEVISION  -

    UI mode: value that corresponds to television resource qualifier specified.

    -
    ACONFIGURATION_UI_MODE_TYPE_APPLIANCE  -

    UI mode: value that corresponds to appliance resource qualifier specified.

    -
    ACONFIGURATION_UI_MODE_TYPE_WATCH  -

    UI mode: value that corresponds to watch resource qualifier specified.

    -
    ACONFIGURATION_UI_MODE_NIGHT_ANY  -

    UI night mode: not specified.

    -
    ACONFIGURATION_UI_MODE_NIGHT_NO  -

    UI night mode: value that corresponds to notnight resource qualifier specified.

    -
    ACONFIGURATION_UI_MODE_NIGHT_YES  -

    UI night mode: value that corresponds to night resource qualifier specified.

    -
    ACONFIGURATION_SCREEN_WIDTH_DP_ANY  -

    Screen width DPI: not specified.

    -
    ACONFIGURATION_SCREEN_HEIGHT_DP_ANY  -

    Screen height DPI: not specified.

    -
    ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY  -

    Smallest screen width DPI: not specified.

    -
    ACONFIGURATION_LAYOUTDIR_ANY  -

    Layout direction: not specified.

    -
    ACONFIGURATION_LAYOUTDIR_LTR  -

    Layout direction: value that corresponds to ldltr resource qualifier specified.

    -
    ACONFIGURATION_LAYOUTDIR_RTL  -

    Layout direction: value that corresponds to ldrtl resource qualifier specified.

    -
    ACONFIGURATION_MCC  -

    Bit mask for mcc configuration.

    -
    ACONFIGURATION_MNC  -

    Bit mask for mnc configuration.

    -
    ACONFIGURATION_LOCALE  -

    Bit mask for locale configuration.

    -
    ACONFIGURATION_TOUCHSCREEN  -

    Bit mask for touchscreen configuration.

    -
    ACONFIGURATION_KEYBOARD  -

    Bit mask for keyboard configuration.

    -
    ACONFIGURATION_KEYBOARD_HIDDEN  -

    Bit mask for keyboardHidden configuration.

    -
    ACONFIGURATION_NAVIGATION  -

    Bit mask for navigation configuration.

    -
    ACONFIGURATION_ORIENTATION  -

    Bit mask for orientation configuration.

    -
    ACONFIGURATION_DENSITY  -

    Bit mask for density configuration.

    -
    ACONFIGURATION_SCREEN_SIZE  -

    Bit mask for screen size configuration.

    -
    ACONFIGURATION_VERSION  -

    Bit mask for platform version configuration.

    -
    ACONFIGURATION_SCREEN_LAYOUT  -

    Bit mask for screen layout configuration.

    -
    ACONFIGURATION_UI_MODE  -

    Bit mask for ui mode configuration.

    -
    ACONFIGURATION_SMALLEST_SCREEN_SIZE  -

    Bit mask for smallest screen width configuration.

    -
    ACONFIGURATION_LAYOUTDIR  -

    Bit mask for layout direction configuration.

    -
    ACONFIGURATION_MNC_ZERO  -

    Constant used to to represent MNC (Mobile Network Code) zero. 0 cannot be used, since it is used to represent an undefined MNC.

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_copy (AConfigurationdest,
    AConfigurationsrc 
    )
    -
    -

    Copy the contents of 'src' to 'dest'.

    - -
    -
    - -
    -
    - - - - - - - - -
    void AConfiguration_delete (AConfigurationconfig)
    -
    -

    Free an AConfiguration that was previously created with AConfiguration_new().

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int32_t AConfiguration_diff (AConfigurationconfig1,
    AConfigurationconfig2 
    )
    -
    -

    Perform a diff between two configurations. Returns a bit mask of ACONFIGURATION_* constants, each bit set meaning that configuration element is different between them.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_fromAssetManager (AConfigurationout,
    AAssetManageram 
    )
    -
    -

    Create and return a new AConfiguration based on the current configuration in use in the given AAssetManager.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_getCountry (AConfigurationconfig,
    char * outCountry 
    )
    -
    -

    Return the current country code set in the configuration. The output will be filled with an array of two characters. They are not 0-terminated. If a country is not set, they will be 0.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getDensity (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_DENSITY_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getKeyboard (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_KEYBOARD_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getKeysHidden (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_KEYSHIDDEN_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_getLanguage (AConfigurationconfig,
    char * outLanguage 
    )
    -
    -

    Return the current language code set in the configuration. The output will be filled with an array of two characters. They are not 0-terminated. If a language is not set, they will be 0.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getLayoutDirection (AConfigurationconfig)
    -
    -

    Return the configuration's layout direction, or ACONFIGURATION_LAYOUTDIR_ANY if not set.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getMcc (AConfigurationconfig)
    -
    -

    Return the current MCC set in the configuration. 0 if not set.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getMnc (AConfigurationconfig)
    -
    -

    Return the current MNC set in the configuration. 0 if not set.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getNavHidden (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_NAVHIDDEN_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getNavigation (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_NAVIGATION_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getOrientation (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_ORIENTATION_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getScreenHeightDp (AConfigurationconfig)
    -
    -

    Return the current configuration screen height in dp units, or ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getScreenLong (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_SCREENLONG_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getScreenSize (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_SCREENSIZE_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getScreenWidthDp (AConfigurationconfig)
    -
    -

    Return the current configuration screen width in dp units, or ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getSdkVersion (AConfigurationconfig)
    -
    -

    Return the current SDK (API) version set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getSmallestScreenWidthDp (AConfigurationconfig)
    -
    -

    Return the configuration's smallest screen width in dp units, or ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getTouchscreen (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_TOUCHSCREEN_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getUiModeNight (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_UI_MODE_NIGHT_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AConfiguration_getUiModeType (AConfigurationconfig)
    -
    -

    Return the current ACONFIGURATION_UI_MODE_TYPE_* set in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int32_t AConfiguration_isBetterThan (AConfigurationbase,
    AConfigurationtest,
    AConfigurationrequested 
    )
    -
    -

    Determine whether the configuration in 'test' is better than the existing configuration in 'base'. If 'requested' is non-NULL, this decision is based on the overall configuration given there. If it is NULL, this decision is simply based on which configuration is more specific. Returns non-0 if 'test' is better than 'base'.

    -

    This assumes you have already filtered the configurations with AConfiguration_match().

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int32_t AConfiguration_match (AConfigurationbase,
    AConfigurationrequested 
    )
    -
    -

    Determine whether 'base' is a valid configuration for use within the environment 'requested'. Returns 0 if there are any values in 'base' that conflict with 'requested'. Returns 1 if it does not conflict.

    - -
    -
    - -
    -
    - - - - - - - -
    AConfiguration* AConfiguration_new ()
    -
    -

    Create a new AConfiguration, initialized with no values set.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setCountry (AConfigurationconfig,
    const char * country 
    )
    -
    -

    Set the current country code in the configuration, from the first two characters in the string.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setDensity (AConfigurationconfig,
    int32_t density 
    )
    -
    -

    Set the current density in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setKeyboard (AConfigurationconfig,
    int32_t keyboard 
    )
    -
    -

    Set the current keyboard in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setKeysHidden (AConfigurationconfig,
    int32_t keysHidden 
    )
    -
    -

    Set the current keys hidden in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setLanguage (AConfigurationconfig,
    const char * language 
    )
    -
    -

    Set the current language code in the configuration, from the first two characters in the string.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setLayoutDirection (AConfigurationconfig,
    int32_t value 
    )
    -
    -

    Set the configuration's layout direction.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setMcc (AConfigurationconfig,
    int32_t mcc 
    )
    -
    -

    Set the current MCC in the configuration. 0 to clear.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setMnc (AConfigurationconfig,
    int32_t mnc 
    )
    -
    -

    Set the current MNC in the configuration. 0 to clear.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setNavHidden (AConfigurationconfig,
    int32_t navHidden 
    )
    -
    -

    Set the current nav hidden in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setNavigation (AConfigurationconfig,
    int32_t navigation 
    )
    -
    -

    Set the current navigation in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setOrientation (AConfigurationconfig,
    int32_t orientation 
    )
    -
    -

    Set the current orientation in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setScreenHeightDp (AConfigurationconfig,
    int32_t value 
    )
    -
    -

    Set the configuration's current screen width in dp units.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setScreenLong (AConfigurationconfig,
    int32_t screenLong 
    )
    -
    -

    Set the current screen long in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setScreenSize (AConfigurationconfig,
    int32_t screenSize 
    )
    -
    -

    Set the current screen size in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setScreenWidthDp (AConfigurationconfig,
    int32_t value 
    )
    -
    -

    Set the configuration's current screen width in dp units.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setSdkVersion (AConfigurationconfig,
    int32_t sdkVersion 
    )
    -
    -

    Set the current SDK version in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setSmallestScreenWidthDp (AConfigurationconfig,
    int32_t value 
    )
    -
    -

    Set the configuration's smallest screen width in dp units.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setTouchscreen (AConfigurationconfig,
    int32_t touchscreen 
    )
    -
    -

    Set the current touchscreen in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setUiModeNight (AConfigurationconfig,
    int32_t uiModeNight 
    )
    -
    -

    Set the current UI mode night in the configuration.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void AConfiguration_setUiModeType (AConfigurationconfig,
    int32_t uiModeType 
    )
    -
    -

    Set the current UI mode type in the configuration.

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/group___input.jd b/docs/html/ndk/reference/group___input.jd deleted file mode 100644 index 55db9566e2a7f13c35837b023e5acb39a6a1368d..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___input.jd +++ /dev/null @@ -1,3682 +0,0 @@ -page.title=Input -page.customHeadTag= -@jd:body - - -
    - -
    -
    Input
    -
    -
    - - - - - - -

    -Files

    file  input.h
     
    file  keycodes.h
     
    - - - -

    -Macros

    #define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT   8
     
    - - - - - -

    -Typedefs

    typedef struct AInputEvent AInputEvent
     
    typedef struct AInputQueue AInputQueue
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Enumerations

    enum  { AKEY_STATE_UNKNOWN = -1, -AKEY_STATE_UP = 0, -AKEY_STATE_DOWN = 1, -AKEY_STATE_VIRTUAL = 2 - }
     
    enum  {
    -  AMETA_NONE = 0, -AMETA_ALT_ON = 0x02, -AMETA_ALT_LEFT_ON = 0x10, -AMETA_ALT_RIGHT_ON = 0x20, -
    -  AMETA_SHIFT_ON = 0x01, -AMETA_SHIFT_LEFT_ON = 0x40, -AMETA_SHIFT_RIGHT_ON = 0x80, -AMETA_SYM_ON = 0x04, -
    -  AMETA_FUNCTION_ON = 0x08, -AMETA_CTRL_ON = 0x1000, -AMETA_CTRL_LEFT_ON = 0x2000, -AMETA_CTRL_RIGHT_ON = 0x4000, -
    -  AMETA_META_ON = 0x10000, -AMETA_META_LEFT_ON = 0x20000, -AMETA_META_RIGHT_ON = 0x40000, -AMETA_CAPS_LOCK_ON = 0x100000, -
    -  AMETA_NUM_LOCK_ON = 0x200000, -AMETA_SCROLL_LOCK_ON = 0x400000 -
    - }
     
    enum  { AINPUT_EVENT_TYPE_KEY = 1, -AINPUT_EVENT_TYPE_MOTION = 2 - }
     
    enum  { AKEY_EVENT_ACTION_DOWN = 0, -AKEY_EVENT_ACTION_UP = 1, -AKEY_EVENT_ACTION_MULTIPLE = 2 - }
     
    enum  {
    -  AKEY_EVENT_FLAG_WOKE_HERE = 0x1, -AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2, -AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4, -AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8, -
    -  AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10, -AKEY_EVENT_FLAG_CANCELED = 0x20, -AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40, -AKEY_EVENT_FLAG_LONG_PRESS = 0x80, -
    -  AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, -AKEY_EVENT_FLAG_TRACKING = 0x200, -AKEY_EVENT_FLAG_FALLBACK = 0x400 -
    - }
     
    enum  {
    -  AMOTION_EVENT_ACTION_MASK = 0xff, -AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00, -AMOTION_EVENT_ACTION_DOWN = 0, -AMOTION_EVENT_ACTION_UP = 1, -
    -  AMOTION_EVENT_ACTION_MOVE = 2, -AMOTION_EVENT_ACTION_CANCEL = 3, -AMOTION_EVENT_ACTION_OUTSIDE = 4, -AMOTION_EVENT_ACTION_POINTER_DOWN = 5, -
    -  AMOTION_EVENT_ACTION_POINTER_UP = 6, -AMOTION_EVENT_ACTION_HOVER_MOVE = 7, -AMOTION_EVENT_ACTION_SCROLL = 8, -AMOTION_EVENT_ACTION_HOVER_ENTER = 9, -
    -  AMOTION_EVENT_ACTION_HOVER_EXIT = 10 -
    - }
     
    enum  { AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1 - }
     
    enum  {
    -  AMOTION_EVENT_EDGE_FLAG_NONE = 0, -AMOTION_EVENT_EDGE_FLAG_TOP = 0x01, -AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02, -AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04, -
    -  AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08 -
    - }
     
    enum  {
    -  AMOTION_EVENT_AXIS_X = 0, -AMOTION_EVENT_AXIS_Y = 1, -AMOTION_EVENT_AXIS_PRESSURE = 2, -AMOTION_EVENT_AXIS_SIZE = 3, -
    -  AMOTION_EVENT_AXIS_TOUCH_MAJOR = 4, -AMOTION_EVENT_AXIS_TOUCH_MINOR = 5, -AMOTION_EVENT_AXIS_TOOL_MAJOR = 6, -AMOTION_EVENT_AXIS_TOOL_MINOR = 7, -
    -  AMOTION_EVENT_AXIS_ORIENTATION = 8, -AMOTION_EVENT_AXIS_VSCROLL = 9, -AMOTION_EVENT_AXIS_HSCROLL = 10, -AMOTION_EVENT_AXIS_Z = 11, -
    -  AMOTION_EVENT_AXIS_RX = 12, -AMOTION_EVENT_AXIS_RY = 13, -AMOTION_EVENT_AXIS_RZ = 14, -AMOTION_EVENT_AXIS_HAT_X = 15, -
    -  AMOTION_EVENT_AXIS_HAT_Y = 16, -AMOTION_EVENT_AXIS_LTRIGGER = 17, -AMOTION_EVENT_AXIS_RTRIGGER = 18, -AMOTION_EVENT_AXIS_THROTTLE = 19, -
    -  AMOTION_EVENT_AXIS_RUDDER = 20, -AMOTION_EVENT_AXIS_WHEEL = 21, -AMOTION_EVENT_AXIS_GAS = 22, -AMOTION_EVENT_AXIS_BRAKE = 23, -
    -  AMOTION_EVENT_AXIS_DISTANCE = 24, -AMOTION_EVENT_AXIS_TILT = 25, -AMOTION_EVENT_AXIS_GENERIC_1 = 32, -AMOTION_EVENT_AXIS_GENERIC_2 = 33, -
    -  AMOTION_EVENT_AXIS_GENERIC_3 = 34, -AMOTION_EVENT_AXIS_GENERIC_4 = 35, -AMOTION_EVENT_AXIS_GENERIC_5 = 36, -AMOTION_EVENT_AXIS_GENERIC_6 = 37, -
    -  AMOTION_EVENT_AXIS_GENERIC_7 = 38, -AMOTION_EVENT_AXIS_GENERIC_8 = 39, -AMOTION_EVENT_AXIS_GENERIC_9 = 40, -AMOTION_EVENT_AXIS_GENERIC_10 = 41, -
    -  AMOTION_EVENT_AXIS_GENERIC_11 = 42, -AMOTION_EVENT_AXIS_GENERIC_12 = 43, -AMOTION_EVENT_AXIS_GENERIC_13 = 44, -AMOTION_EVENT_AXIS_GENERIC_14 = 45, -
    -  AMOTION_EVENT_AXIS_GENERIC_15 = 46, -AMOTION_EVENT_AXIS_GENERIC_16 = 47 -
    - }
     
    enum  {
    -  AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0, -AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1, -AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2, -AMOTION_EVENT_BUTTON_BACK = 1 << 3, -
    -  AMOTION_EVENT_BUTTON_FORWARD = 1 << 4 -
    - }
     
    enum  {
    -  AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0, -AMOTION_EVENT_TOOL_TYPE_FINGER = 1, -AMOTION_EVENT_TOOL_TYPE_STYLUS = 2, -AMOTION_EVENT_TOOL_TYPE_MOUSE = 3, -
    -  AMOTION_EVENT_TOOL_TYPE_ERASER = 4 -
    - }
     
    enum  {
    -  AINPUT_SOURCE_CLASS_MASK = 0x000000ff, -AINPUT_SOURCE_CLASS_NONE = 0x00000000, -AINPUT_SOURCE_CLASS_BUTTON = 0x00000001, -AINPUT_SOURCE_CLASS_POINTER = 0x00000002, -
    -  AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004, -AINPUT_SOURCE_CLASS_POSITION = 0x00000008, -AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010 -
    - }
     
    enum  {
    -  AINPUT_SOURCE_UNKNOWN = 0x00000000, -AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON, -AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON, -AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON, -
    -  AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER, -AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER, -AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER, -AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION, -
    -  AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION, -AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE, -AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK, -AINPUT_SOURCE_ANY = 0xffffff00 -
    - }
     
    enum  { AINPUT_KEYBOARD_TYPE_NONE = 0, -AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1, -AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2 - }
     
    enum  {
    -  AINPUT_MOTION_RANGE_X = AMOTION_EVENT_AXIS_X, -AINPUT_MOTION_RANGE_Y = AMOTION_EVENT_AXIS_Y, -AINPUT_MOTION_RANGE_PRESSURE = AMOTION_EVENT_AXIS_PRESSURE, -AINPUT_MOTION_RANGE_SIZE = AMOTION_EVENT_AXIS_SIZE, -
    -  AINPUT_MOTION_RANGE_TOUCH_MAJOR = AMOTION_EVENT_AXIS_TOUCH_MAJOR, -AINPUT_MOTION_RANGE_TOUCH_MINOR = AMOTION_EVENT_AXIS_TOUCH_MINOR, -AINPUT_MOTION_RANGE_TOOL_MAJOR = AMOTION_EVENT_AXIS_TOOL_MAJOR, -AINPUT_MOTION_RANGE_TOOL_MINOR = AMOTION_EVENT_AXIS_TOOL_MINOR, -
    -  AINPUT_MOTION_RANGE_ORIENTATION = AMOTION_EVENT_AXIS_ORIENTATION -
    - }
     
    enum  {
    -  AKEYCODE_UNKNOWN = 0, -AKEYCODE_SOFT_LEFT = 1, -AKEYCODE_SOFT_RIGHT = 2, -AKEYCODE_HOME = 3, -
    -  AKEYCODE_BACK = 4, -AKEYCODE_CALL = 5, -AKEYCODE_ENDCALL = 6, -AKEYCODE_0 = 7, -
    -  AKEYCODE_1 = 8, -AKEYCODE_2 = 9, -AKEYCODE_3 = 10, -AKEYCODE_4 = 11, -
    -  AKEYCODE_5 = 12, -AKEYCODE_6 = 13, -AKEYCODE_7 = 14, -AKEYCODE_8 = 15, -
    -  AKEYCODE_9 = 16, -AKEYCODE_STAR = 17, -AKEYCODE_POUND = 18, -AKEYCODE_DPAD_UP = 19, -
    -  AKEYCODE_DPAD_DOWN = 20, -AKEYCODE_DPAD_LEFT = 21, -AKEYCODE_DPAD_RIGHT = 22, -AKEYCODE_DPAD_CENTER = 23, -
    -  AKEYCODE_VOLUME_UP = 24, -AKEYCODE_VOLUME_DOWN = 25, -AKEYCODE_POWER = 26, -AKEYCODE_CAMERA = 27, -
    -  AKEYCODE_CLEAR = 28, -AKEYCODE_A = 29, -AKEYCODE_B = 30, -AKEYCODE_C = 31, -
    -  AKEYCODE_D = 32, -AKEYCODE_E = 33, -AKEYCODE_F = 34, -AKEYCODE_G = 35, -
    -  AKEYCODE_H = 36, -AKEYCODE_I = 37, -AKEYCODE_J = 38, -AKEYCODE_K = 39, -
    -  AKEYCODE_L = 40, -AKEYCODE_M = 41, -AKEYCODE_N = 42, -AKEYCODE_O = 43, -
    -  AKEYCODE_P = 44, -AKEYCODE_Q = 45, -AKEYCODE_R = 46, -AKEYCODE_S = 47, -
    -  AKEYCODE_T = 48, -AKEYCODE_U = 49, -AKEYCODE_V = 50, -AKEYCODE_W = 51, -
    -  AKEYCODE_X = 52, -AKEYCODE_Y = 53, -AKEYCODE_Z = 54, -AKEYCODE_COMMA = 55, -
    -  AKEYCODE_PERIOD = 56, -AKEYCODE_ALT_LEFT = 57, -AKEYCODE_ALT_RIGHT = 58, -AKEYCODE_SHIFT_LEFT = 59, -
    -  AKEYCODE_SHIFT_RIGHT = 60, -AKEYCODE_TAB = 61, -AKEYCODE_SPACE = 62, -AKEYCODE_SYM = 63, -
    -  AKEYCODE_EXPLORER = 64, -AKEYCODE_ENVELOPE = 65, -AKEYCODE_ENTER = 66, -AKEYCODE_DEL = 67, -
    -  AKEYCODE_GRAVE = 68, -AKEYCODE_MINUS = 69, -AKEYCODE_EQUALS = 70, -AKEYCODE_LEFT_BRACKET = 71, -
    -  AKEYCODE_RIGHT_BRACKET = 72, -AKEYCODE_BACKSLASH = 73, -AKEYCODE_SEMICOLON = 74, -AKEYCODE_APOSTROPHE = 75, -
    -  AKEYCODE_SLASH = 76, -AKEYCODE_AT = 77, -AKEYCODE_NUM = 78, -AKEYCODE_HEADSETHOOK = 79, -
    -  AKEYCODE_FOCUS = 80, -AKEYCODE_PLUS = 81, -AKEYCODE_MENU = 82, -AKEYCODE_NOTIFICATION = 83, -
    -  AKEYCODE_SEARCH = 84, -AKEYCODE_MEDIA_PLAY_PAUSE = 85, -AKEYCODE_MEDIA_STOP = 86, -AKEYCODE_MEDIA_NEXT = 87, -
    -  AKEYCODE_MEDIA_PREVIOUS = 88, -AKEYCODE_MEDIA_REWIND = 89, -AKEYCODE_MEDIA_FAST_FORWARD = 90, -AKEYCODE_MUTE = 91, -
    -  AKEYCODE_PAGE_UP = 92, -AKEYCODE_PAGE_DOWN = 93, -AKEYCODE_PICTSYMBOLS = 94, -AKEYCODE_SWITCH_CHARSET = 95, -
    -  AKEYCODE_BUTTON_A = 96, -AKEYCODE_BUTTON_B = 97, -AKEYCODE_BUTTON_C = 98, -AKEYCODE_BUTTON_X = 99, -
    -  AKEYCODE_BUTTON_Y = 100, -AKEYCODE_BUTTON_Z = 101, -AKEYCODE_BUTTON_L1 = 102, -AKEYCODE_BUTTON_R1 = 103, -
    -  AKEYCODE_BUTTON_L2 = 104, -AKEYCODE_BUTTON_R2 = 105, -AKEYCODE_BUTTON_THUMBL = 106, -AKEYCODE_BUTTON_THUMBR = 107, -
    -  AKEYCODE_BUTTON_START = 108, -AKEYCODE_BUTTON_SELECT = 109, -AKEYCODE_BUTTON_MODE = 110, -AKEYCODE_ESCAPE = 111, -
    -  AKEYCODE_FORWARD_DEL = 112, -AKEYCODE_CTRL_LEFT = 113, -AKEYCODE_CTRL_RIGHT = 114, -AKEYCODE_CAPS_LOCK = 115, -
    -  AKEYCODE_SCROLL_LOCK = 116, -AKEYCODE_META_LEFT = 117, -AKEYCODE_META_RIGHT = 118, -AKEYCODE_FUNCTION = 119, -
    -  AKEYCODE_SYSRQ = 120, -AKEYCODE_BREAK = 121, -AKEYCODE_MOVE_HOME = 122, -AKEYCODE_MOVE_END = 123, -
    -  AKEYCODE_INSERT = 124, -AKEYCODE_FORWARD = 125, -AKEYCODE_MEDIA_PLAY = 126, -AKEYCODE_MEDIA_PAUSE = 127, -
    -  AKEYCODE_MEDIA_CLOSE = 128, -AKEYCODE_MEDIA_EJECT = 129, -AKEYCODE_MEDIA_RECORD = 130, -AKEYCODE_F1 = 131, -
    -  AKEYCODE_F2 = 132, -AKEYCODE_F3 = 133, -AKEYCODE_F4 = 134, -AKEYCODE_F5 = 135, -
    -  AKEYCODE_F6 = 136, -AKEYCODE_F7 = 137, -AKEYCODE_F8 = 138, -AKEYCODE_F9 = 139, -
    -  AKEYCODE_F10 = 140, -AKEYCODE_F11 = 141, -AKEYCODE_F12 = 142, -AKEYCODE_NUM_LOCK = 143, -
    -  AKEYCODE_NUMPAD_0 = 144, -AKEYCODE_NUMPAD_1 = 145, -AKEYCODE_NUMPAD_2 = 146, -AKEYCODE_NUMPAD_3 = 147, -
    -  AKEYCODE_NUMPAD_4 = 148, -AKEYCODE_NUMPAD_5 = 149, -AKEYCODE_NUMPAD_6 = 150, -AKEYCODE_NUMPAD_7 = 151, -
    -  AKEYCODE_NUMPAD_8 = 152, -AKEYCODE_NUMPAD_9 = 153, -AKEYCODE_NUMPAD_DIVIDE = 154, -AKEYCODE_NUMPAD_MULTIPLY = 155, -
    -  AKEYCODE_NUMPAD_SUBTRACT = 156, -AKEYCODE_NUMPAD_ADD = 157, -AKEYCODE_NUMPAD_DOT = 158, -AKEYCODE_NUMPAD_COMMA = 159, -
    -  AKEYCODE_NUMPAD_ENTER = 160, -AKEYCODE_NUMPAD_EQUALS = 161, -AKEYCODE_NUMPAD_LEFT_PAREN = 162, -AKEYCODE_NUMPAD_RIGHT_PAREN = 163, -
    -  AKEYCODE_VOLUME_MUTE = 164, -AKEYCODE_INFO = 165, -AKEYCODE_CHANNEL_UP = 166, -AKEYCODE_CHANNEL_DOWN = 167, -
    -  AKEYCODE_ZOOM_IN = 168, -AKEYCODE_ZOOM_OUT = 169, -AKEYCODE_TV = 170, -AKEYCODE_WINDOW = 171, -
    -  AKEYCODE_GUIDE = 172, -AKEYCODE_DVR = 173, -AKEYCODE_BOOKMARK = 174, -AKEYCODE_CAPTIONS = 175, -
    -  AKEYCODE_SETTINGS = 176, -AKEYCODE_TV_POWER = 177, -AKEYCODE_TV_INPUT = 178, -AKEYCODE_STB_POWER = 179, -
    -  AKEYCODE_STB_INPUT = 180, -AKEYCODE_AVR_POWER = 181, -AKEYCODE_AVR_INPUT = 182, -AKEYCODE_PROG_RED = 183, -
    -  AKEYCODE_PROG_GREEN = 184, -AKEYCODE_PROG_YELLOW = 185, -AKEYCODE_PROG_BLUE = 186, -AKEYCODE_APP_SWITCH = 187, -
    -  AKEYCODE_BUTTON_1 = 188, -AKEYCODE_BUTTON_2 = 189, -AKEYCODE_BUTTON_3 = 190, -AKEYCODE_BUTTON_4 = 191, -
    -  AKEYCODE_BUTTON_5 = 192, -AKEYCODE_BUTTON_6 = 193, -AKEYCODE_BUTTON_7 = 194, -AKEYCODE_BUTTON_8 = 195, -
    -  AKEYCODE_BUTTON_9 = 196, -AKEYCODE_BUTTON_10 = 197, -AKEYCODE_BUTTON_11 = 198, -AKEYCODE_BUTTON_12 = 199, -
    -  AKEYCODE_BUTTON_13 = 200, -AKEYCODE_BUTTON_14 = 201, -AKEYCODE_BUTTON_15 = 202, -AKEYCODE_BUTTON_16 = 203, -
    -  AKEYCODE_LANGUAGE_SWITCH = 204, -AKEYCODE_MANNER_MODE = 205, -AKEYCODE_3D_MODE = 206, -AKEYCODE_CONTACTS = 207, -
    -  AKEYCODE_CALENDAR = 208, -AKEYCODE_MUSIC = 209, -AKEYCODE_CALCULATOR = 210, -AKEYCODE_ZENKAKU_HANKAKU = 211, -
    -  AKEYCODE_EISU = 212, -AKEYCODE_MUHENKAN = 213, -AKEYCODE_HENKAN = 214, -AKEYCODE_KATAKANA_HIRAGANA = 215, -
    -  AKEYCODE_YEN = 216, -AKEYCODE_RO = 217, -AKEYCODE_KANA = 218, -AKEYCODE_ASSIST = 219, -
    -  AKEYCODE_BRIGHTNESS_DOWN = 220, -AKEYCODE_BRIGHTNESS_UP = 221, -AKEYCODE_MEDIA_AUDIO_TRACK = 222, -AKEYCODE_SLEEP = 223, -
    -  AKEYCODE_WAKEUP = 224, -AKEYCODE_PAIRING = 225, -AKEYCODE_MEDIA_TOP_MENU = 226, -AKEYCODE_11 = 227, -
    -  AKEYCODE_12 = 228, -AKEYCODE_LAST_CHANNEL = 229, -AKEYCODE_TV_DATA_SERVICE = 230, -AKEYCODE_VOICE_ASSIST = 231, -
    -  AKEYCODE_TV_RADIO_SERVICE = 232, -AKEYCODE_TV_TELETEXT = 233, -AKEYCODE_TV_NUMBER_ENTRY = 234, -AKEYCODE_TV_TERRESTRIAL_ANALOG = 235, -
    -  AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236, -AKEYCODE_TV_SATELLITE = 237, -AKEYCODE_TV_SATELLITE_BS = 238, -AKEYCODE_TV_SATELLITE_CS = 239, -
    -  AKEYCODE_TV_SATELLITE_SERVICE = 240, -AKEYCODE_TV_NETWORK = 241, -AKEYCODE_TV_ANTENNA_CABLE = 242, -AKEYCODE_TV_INPUT_HDMI_1 = 243, -
    -  AKEYCODE_TV_INPUT_HDMI_2 = 244, -AKEYCODE_TV_INPUT_HDMI_3 = 245, -AKEYCODE_TV_INPUT_HDMI_4 = 246, -AKEYCODE_TV_INPUT_COMPOSITE_1 = 247, -
    -  AKEYCODE_TV_INPUT_COMPOSITE_2 = 248, -AKEYCODE_TV_INPUT_COMPONENT_1 = 249, -AKEYCODE_TV_INPUT_COMPONENT_2 = 250, -AKEYCODE_TV_INPUT_VGA_1 = 251, -
    -  AKEYCODE_TV_AUDIO_DESCRIPTION = 252, -AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253, -AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254, -AKEYCODE_TV_ZOOM_MODE = 255, -
    -  AKEYCODE_TV_CONTENTS_MENU = 256, -AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257, -AKEYCODE_TV_TIMER_PROGRAMMING = 258, -AKEYCODE_HELP = 259 -
    - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    int32_t AInputEvent_getType (const AInputEvent *event)
     
    int32_t AInputEvent_getDeviceId (const AInputEvent *event)
     
    int32_t AInputEvent_getSource (const AInputEvent *event)
     
    int32_t AKeyEvent_getAction (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getFlags (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getKeyCode (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getScanCode (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getMetaState (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getRepeatCount (const AInputEvent *key_event)
     
    int64_t AKeyEvent_getDownTime (const AInputEvent *key_event)
     
    int64_t AKeyEvent_getEventTime (const AInputEvent *key_event)
     
    int32_t AMotionEvent_getAction (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getFlags (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getMetaState (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getButtonState (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getEdgeFlags (const AInputEvent *motion_event)
     
    int64_t AMotionEvent_getDownTime (const AInputEvent *motion_event)
     
    int64_t AMotionEvent_getEventTime (const AInputEvent *motion_event)
     
    float AMotionEvent_getXOffset (const AInputEvent *motion_event)
     
    float AMotionEvent_getYOffset (const AInputEvent *motion_event)
     
    float AMotionEvent_getXPrecision (const AInputEvent *motion_event)
     
    float AMotionEvent_getYPrecision (const AInputEvent *motion_event)
     
    size_t AMotionEvent_getPointerCount (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getPointerId (const AInputEvent *motion_event, size_t pointer_index)
     
    int32_t AMotionEvent_getToolType (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getRawX (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getRawY (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getX (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getY (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getPressure (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getSize (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getTouchMajor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getTouchMinor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getToolMajor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getToolMinor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getOrientation (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getAxisValue (const AInputEvent *motion_event, int32_t axis, size_t pointer_index)
     
    size_t AMotionEvent_getHistorySize (const AInputEvent *motion_event)
     
    int64_t AMotionEvent_getHistoricalEventTime (const AInputEvent *motion_event, size_t history_index)
     
    float AMotionEvent_getHistoricalRawX (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalRawY (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalX (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalY (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalPressure (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalSize (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalTouchMajor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalTouchMinor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalToolMajor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalToolMinor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalOrientation (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalAxisValue (const AInputEvent *motion_event, int32_t axis, size_t pointer_index, size_t history_index)
     
    void AInputQueue_attachLooper (AInputQueue *queue, ALooper *looper, int ident, ALooper_callbackFunc callback, void *data)
     
    void AInputQueue_detachLooper (AInputQueue *queue)
     
    int32_t AInputQueue_hasEvents (AInputQueue *queue)
     
    int32_t AInputQueue_getEvent (AInputQueue *queue, AInputEvent **outEvent)
     
    int32_t AInputQueue_preDispatchEvent (AInputQueue *queue, AInputEvent *event)
     
    void AInputQueue_finishEvent (AInputQueue *queue, AInputEvent *event, int handled)
     
    -

    Detailed Description

    -

    Macro Definition Documentation

    - -
    -
    - - - - -
    #define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT   8
    -
    -

    Bit shift for the action bits holding the pointer index as defined by AMOTION_EVENT_ACTION_POINTER_INDEX_MASK.

    - -
    -
    -

    Typedef Documentation

    - -
    -
    - - - - -
    typedef struct AInputEvent AInputEvent
    -
    -

    Input events.

    -

    Input events are opaque structures. Use the provided accessors functions to read their properties.

    - -
    -
    - -
    -
    - - - - -
    typedef struct AInputQueue AInputQueue
    -
    -

    Input queue

    -

    An input queue is the facility through which you retrieve input events.

    - -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Motion event edge touch flags.

    - - - - - - -
    Enumerator
    AMOTION_EVENT_EDGE_FLAG_NONE  -

    No edges intersected.

    -
    AMOTION_EVENT_EDGE_FLAG_TOP  -

    Flag indicating the motion event intersected the top edge of the screen.

    -
    AMOTION_EVENT_EDGE_FLAG_BOTTOM  -

    Flag indicating the motion event intersected the bottom edge of the screen.

    -
    AMOTION_EVENT_EDGE_FLAG_LEFT  -

    Flag indicating the motion event intersected the left edge of the screen.

    -
    AMOTION_EVENT_EDGE_FLAG_RIGHT  -

    Flag indicating the motion event intersected the right edge of the screen.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Constants that identify each individual axis of a motion event.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Enumerator
    AMOTION_EVENT_AXIS_X  -

    Axis constant: X axis of a motion event.

    -
      -
    • For a touch screen, reports the absolute X screen position of the center of the touch contact area. The units are display pixels.
    • -
    • For a touch pad, reports the absolute X surface position of the center of the touch contact area. The units are device-dependent.
    • -
    • For a mouse, reports the absolute X screen position of the mouse pointer. The units are display pixels.
    • -
    • For a trackball, reports the relative horizontal displacement of the trackball. The value is normalized to a range from -1.0 (left) to 1.0 (right).
    • -
    • For a joystick, reports the absolute X position of the joystick. The value is normalized to a range from -1.0 (left) to 1.0 (right).
    • -
    -
    AMOTION_EVENT_AXIS_Y  -

    Axis constant: Y axis of a motion event.

    -
      -
    • For a touch screen, reports the absolute Y screen position of the center of the touch contact area. The units are display pixels.
    • -
    • For a touch pad, reports the absolute Y surface position of the center of the touch contact area. The units are device-dependent.
    • -
    • For a mouse, reports the absolute Y screen position of the mouse pointer. The units are display pixels.
    • -
    • For a trackball, reports the relative vertical displacement of the trackball. The value is normalized to a range from -1.0 (up) to 1.0 (down).
    • -
    • For a joystick, reports the absolute Y position of the joystick. The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
    • -
    -
    AMOTION_EVENT_AXIS_PRESSURE  -

    Axis constant: Pressure axis of a motion event.

    -
      -
    • For a touch screen or touch pad, reports the approximate pressure applied to the surface by a finger or other tool. The value is normalized to a range from 0 (no pressure at all) to 1 (normal pressure), although values higher than 1 may be generated depending on the calibration of the input device.
    • -
    • For a trackball, the value is set to 1 if the trackball button is pressed or 0 otherwise.
    • -
    • For a mouse, the value is set to 1 if the primary mouse button is pressed or 0 otherwise.
    • -
    -
    AMOTION_EVENT_AXIS_SIZE  -

    Axis constant: Size axis of a motion event.

    -
      -
    • For a touch screen or touch pad, reports the approximate size of the contact area in relation to the maximum detectable size for the device. The value is normalized to a range from 0 (smallest detectable size) to 1 (largest detectable size), although it is not a linear scale. This value is of limited use. To obtain calibrated size information, see AMOTION_EVENT_AXIS_TOUCH_MAJOR or AMOTION_EVENT_AXIS_TOOL_MAJOR.
    • -
    -
    AMOTION_EVENT_AXIS_TOUCH_MAJOR  -

    Axis constant: TouchMajor axis of a motion event.

    -
      -
    • For a touch screen, reports the length of the major axis of an ellipse that represents the touch area at the point of contact. The units are display pixels.
    • -
    • For a touch pad, reports the length of the major axis of an ellipse that represents the touch area at the point of contact. The units are device-dependent.
    • -
    -
    AMOTION_EVENT_AXIS_TOUCH_MINOR  -

    Axis constant: TouchMinor axis of a motion event.

    -
      -
    • For a touch screen, reports the length of the minor axis of an ellipse that represents the touch area at the point of contact. The units are display pixels.
    • -
    • For a touch pad, reports the length of the minor axis of an ellipse that represents the touch area at the point of contact. The units are device-dependent.
    • -
    -

    When the touch is circular, the major and minor axis lengths will be equal to one another.

    -
    AMOTION_EVENT_AXIS_TOOL_MAJOR  -

    Axis constant: ToolMajor axis of a motion event.

    -
      -
    • For a touch screen, reports the length of the major axis of an ellipse that represents the size of the approaching finger or tool used to make contact.
    • -
    • For a touch pad, reports the length of the major axis of an ellipse that represents the size of the approaching finger or tool used to make contact. The units are device-dependent.
    • -
    -

    When the touch is circular, the major and minor axis lengths will be equal to one another.

    -

    The tool size may be larger than the touch size since the tool may not be fully in contact with the touch sensor.

    -
    AMOTION_EVENT_AXIS_TOOL_MINOR  -

    Axis constant: ToolMinor axis of a motion event.

    -
      -
    • For a touch screen, reports the length of the minor axis of an ellipse that represents the size of the approaching finger or tool used to make contact.
    • -
    • For a touch pad, reports the length of the minor axis of an ellipse that represents the size of the approaching finger or tool used to make contact. The units are device-dependent.
    • -
    -

    When the touch is circular, the major and minor axis lengths will be equal to one another.

    -

    The tool size may be larger than the touch size since the tool may not be fully in contact with the touch sensor.

    -
    AMOTION_EVENT_AXIS_ORIENTATION  -

    Axis constant: Orientation axis of a motion event.

    -
      -
    • For a touch screen or touch pad, reports the orientation of the finger or tool in radians relative to the vertical plane of the device. An angle of 0 radians indicates that the major axis of contact is oriented upwards, is perfectly circular or is of unknown orientation. A positive angle indicates that the major axis of contact is oriented to the right. A negative angle indicates that the major axis of contact is oriented to the left. The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians (finger pointing fully right).
    • -
    • For a stylus, the orientation indicates the direction in which the stylus is pointing in relation to the vertical axis of the current orientation of the screen. The range is from -PI radians to PI radians, where 0 is pointing up, -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians is pointing right. See also AMOTION_EVENT_AXIS_TILT.
    • -
    -
    AMOTION_EVENT_AXIS_VSCROLL  -

    Axis constant: Vertical Scroll axis of a motion event.

    -
      -
    • For a mouse, reports the relative movement of the vertical scroll wheel. The value is normalized to a range from -1.0 (down) to 1.0 (up).
    • -
    -

    This axis should be used to scroll views vertically.

    -
    AMOTION_EVENT_AXIS_HSCROLL  -

    Axis constant: Horizontal Scroll axis of a motion event.

    -
      -
    • For a mouse, reports the relative movement of the horizontal scroll wheel. The value is normalized to a range from -1.0 (left) to 1.0 (right).
    • -
    -

    This axis should be used to scroll views horizontally.

    -
    AMOTION_EVENT_AXIS_Z  -

    Axis constant: Z axis of a motion event.

    -
      -
    • For a joystick, reports the absolute Z position of the joystick. The value is normalized to a range from -1.0 (high) to 1.0 (low). On game pads with two analog joysticks, this axis is often reinterpreted to report the absolute X position of the second joystick instead.
    • -
    -
    AMOTION_EVENT_AXIS_RX  -

    Axis constant: X Rotation axis of a motion event.

    -
      -
    • For a joystick, reports the absolute rotation angle about the X axis. The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
    • -
    -
    AMOTION_EVENT_AXIS_RY  -

    Axis constant: Y Rotation axis of a motion event.

    -
      -
    • For a joystick, reports the absolute rotation angle about the Y axis. The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
    • -
    -
    AMOTION_EVENT_AXIS_RZ  -

    Axis constant: Z Rotation axis of a motion event.

    -
      -
    • For a joystick, reports the absolute rotation angle about the Z axis. The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise). On game pads with two analog joysticks, this axis is often reinterpreted to report the absolute Y position of the second joystick instead.
    • -
    -
    AMOTION_EVENT_AXIS_HAT_X  -

    Axis constant: Hat X axis of a motion event.

    -
      -
    • For a joystick, reports the absolute X position of the directional hat control. The value is normalized to a range from -1.0 (left) to 1.0 (right).
    • -
    -
    AMOTION_EVENT_AXIS_HAT_Y  -

    Axis constant: Hat Y axis of a motion event.

    -
      -
    • For a joystick, reports the absolute Y position of the directional hat control. The value is normalized to a range from -1.0 (up) to 1.0 (down).
    • -
    -
    AMOTION_EVENT_AXIS_LTRIGGER  -

    Axis constant: Left Trigger axis of a motion event.

    -
      -
    • For a joystick, reports the absolute position of the left trigger control. The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
    • -
    -
    AMOTION_EVENT_AXIS_RTRIGGER  -

    Axis constant: Right Trigger axis of a motion event.

    -
      -
    • For a joystick, reports the absolute position of the right trigger control. The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
    • -
    -
    AMOTION_EVENT_AXIS_THROTTLE  -

    Axis constant: Throttle axis of a motion event.

    -
      -
    • For a joystick, reports the absolute position of the throttle control. The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
    • -
    -
    AMOTION_EVENT_AXIS_RUDDER  -

    Axis constant: Rudder axis of a motion event.

    -
      -
    • For a joystick, reports the absolute position of the rudder control. The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
    • -
    -
    AMOTION_EVENT_AXIS_WHEEL  -

    Axis constant: Wheel axis of a motion event.

    -
      -
    • For a joystick, reports the absolute position of the steering wheel control. The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
    • -
    -
    AMOTION_EVENT_AXIS_GAS  -

    Axis constant: Gas axis of a motion event.

    -
      -
    • For a joystick, reports the absolute position of the gas (accelerator) control. The value is normalized to a range from 0.0 (no acceleration) to 1.0 (maximum acceleration).
    • -
    -
    AMOTION_EVENT_AXIS_BRAKE  -

    Axis constant: Brake axis of a motion event.

    -
      -
    • For a joystick, reports the absolute position of the brake control. The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
    • -
    -
    AMOTION_EVENT_AXIS_DISTANCE  -

    Axis constant: Distance axis of a motion event.

    -
      -
    • For a stylus, reports the distance of the stylus from the screen. A value of 0.0 indicates direct contact and larger values indicate increasing distance from the surface.
    • -
    -
    AMOTION_EVENT_AXIS_TILT  -

    Axis constant: Tilt axis of a motion event.

    -
      -
    • For a stylus, reports the tilt angle of the stylus in radians where 0 radians indicates that the stylus is being held perpendicular to the surface, and PI/2 radians indicates that the stylus is being held flat against the surface.
    • -
    -
    AMOTION_EVENT_AXIS_GENERIC_1  -

    Axis constant: Generic 1 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_2  -

    Axis constant: Generic 2 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_3  -

    Axis constant: Generic 3 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_4  -

    Axis constant: Generic 4 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_5  -

    Axis constant: Generic 5 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_6  -

    Axis constant: Generic 6 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_7  -

    Axis constant: Generic 7 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_8  -

    Axis constant: Generic 8 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_9  -

    Axis constant: Generic 9 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_10  -

    Axis constant: Generic 10 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_11  -

    Axis constant: Generic 11 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_12  -

    Axis constant: Generic 12 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_13  -

    Axis constant: Generic 13 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_14  -

    Axis constant: Generic 14 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_15  -

    Axis constant: Generic 15 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    AMOTION_EVENT_AXIS_GENERIC_16  -

    Axis constant: Generic 16 axis of a motion event. The interpretation of a generic axis is device-specific.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Constants that identify buttons that are associated with motion events. Refer to the documentation on the MotionEvent class for descriptions of each button.

    - - - - - - -
    Enumerator
    AMOTION_EVENT_BUTTON_PRIMARY  -

    primary

    -
    AMOTION_EVENT_BUTTON_SECONDARY  -

    secondary

    -
    AMOTION_EVENT_BUTTON_TERTIARY  -

    tertiary

    -
    AMOTION_EVENT_BUTTON_BACK  -

    back

    -
    AMOTION_EVENT_BUTTON_FORWARD  -

    forward

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Constants that identify tool types. Refer to the documentation on the MotionEvent class for descriptions of each tool type.

    - - - - - - -
    Enumerator
    AMOTION_EVENT_TOOL_TYPE_UNKNOWN  -

    unknown

    -
    AMOTION_EVENT_TOOL_TYPE_FINGER  -

    finger

    -
    AMOTION_EVENT_TOOL_TYPE_STYLUS  -

    stylus

    -
    AMOTION_EVENT_TOOL_TYPE_MOUSE  -

    mouse

    -
    AMOTION_EVENT_TOOL_TYPE_ERASER  -

    eraser

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Input source masks.

    -

    Refer to the documentation on android.view.InputDevice for more details about input sources and their correct interpretation.

    - - - - - - - - -
    Enumerator
    AINPUT_SOURCE_CLASS_MASK  -

    mask

    -
    AINPUT_SOURCE_CLASS_NONE  -

    none

    -
    AINPUT_SOURCE_CLASS_BUTTON  -

    button

    -
    AINPUT_SOURCE_CLASS_POINTER  -

    pointer

    -
    AINPUT_SOURCE_CLASS_NAVIGATION  -

    navigation

    -
    AINPUT_SOURCE_CLASS_POSITION  -

    position

    -
    AINPUT_SOURCE_CLASS_JOYSTICK  -

    joystick

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Input sources.

    - - - - - - - - - - - - - -
    Enumerator
    AINPUT_SOURCE_UNKNOWN  -

    unknown

    -
    AINPUT_SOURCE_KEYBOARD  -

    keyboard

    -
    AINPUT_SOURCE_DPAD  -

    dpad

    -
    AINPUT_SOURCE_GAMEPAD  -

    gamepad

    -
    AINPUT_SOURCE_TOUCHSCREEN  -

    touchscreen

    -
    AINPUT_SOURCE_MOUSE  -

    mouse

    -
    AINPUT_SOURCE_STYLUS  -

    stylus

    -
    AINPUT_SOURCE_TRACKBALL  -

    trackball

    -
    AINPUT_SOURCE_TOUCHPAD  -

    touchpad

    -
    AINPUT_SOURCE_TOUCH_NAVIGATION  -

    navigation

    -
    AINPUT_SOURCE_JOYSTICK  -

    joystick

    -
    AINPUT_SOURCE_ANY  -

    any

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Keyboard types.

    -

    Refer to the documentation on android.view.InputDevice for more details.

    - - - - -
    Enumerator
    AINPUT_KEYBOARD_TYPE_NONE  -

    none

    -
    AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC  -

    non alphabetic

    -
    AINPUT_KEYBOARD_TYPE_ALPHABETIC  -

    alphabetic

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Constants used to retrieve information about the range of motion for a particular coordinate of a motion event.

    -

    Refer to the documentation on android.view.InputDevice for more details about input sources and their correct interpretation.

    -
    Deprecated:
    These constants are deprecated. Use AMOTION_EVENT_AXIS_* constants instead.
    - - - - - - - - - - -
    Enumerator
    AINPUT_MOTION_RANGE_X  -

    x

    -
    AINPUT_MOTION_RANGE_Y  -

    y

    -
    AINPUT_MOTION_RANGE_PRESSURE  -

    pressure

    -
    AINPUT_MOTION_RANGE_SIZE  -

    size

    -
    AINPUT_MOTION_RANGE_TOUCH_MAJOR  -

    touch major

    -
    AINPUT_MOTION_RANGE_TOUCH_MINOR  -

    touch minor

    -
    AINPUT_MOTION_RANGE_TOOL_MAJOR  -

    tool major

    -
    AINPUT_MOTION_RANGE_TOOL_MINOR  -

    tool minor

    -
    AINPUT_MOTION_RANGE_ORIENTATION  -

    orientation

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Key codes.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Enumerator
    AKEYCODE_UNKNOWN  -

    Unknown key code.

    -
    AKEYCODE_SOFT_LEFT  -

    Soft Left key. Usually situated below the display on phones and used as a multi-function feature key for selecting a software defined function shown on the bottom left of the display.

    -
    AKEYCODE_SOFT_RIGHT  -

    Soft Right key. Usually situated below the display on phones and used as a multi-function feature key for selecting a software defined function shown on the bottom right of the display.

    -
    AKEYCODE_HOME  -

    Home key. This key is handled by the framework and is never delivered to applications.

    -
    AKEYCODE_BACK  -

    Back key.

    -
    AKEYCODE_CALL  -

    Call key.

    -
    AKEYCODE_ENDCALL  -

    End Call key.

    -
    AKEYCODE_0  -

    '0' key.

    -
    AKEYCODE_1  -

    '1' key.

    -
    AKEYCODE_2  -

    '2' key.

    -
    AKEYCODE_3  -

    '3' key.

    -
    AKEYCODE_4  -

    '4' key.

    -
    AKEYCODE_5  -

    '5' key.

    -
    AKEYCODE_6  -

    '6' key.

    -
    AKEYCODE_7  -

    '7' key.

    -
    AKEYCODE_8  -

    '8' key.

    -
    AKEYCODE_9  -

    '9' key.

    -
    AKEYCODE_STAR  -

    '*' key.

    -
    AKEYCODE_POUND  -

    '#' key.

    -
    AKEYCODE_DPAD_UP  -

    Directional Pad Up key. May also be synthesized from trackball motions.

    -
    AKEYCODE_DPAD_DOWN  -

    Directional Pad Down key. May also be synthesized from trackball motions.

    -
    AKEYCODE_DPAD_LEFT  -

    Directional Pad Left key. May also be synthesized from trackball motions.

    -
    AKEYCODE_DPAD_RIGHT  -

    Directional Pad Right key. May also be synthesized from trackball motions.

    -
    AKEYCODE_DPAD_CENTER  -

    Directional Pad Center key. May also be synthesized from trackball motions.

    -
    AKEYCODE_VOLUME_UP  -

    Volume Up key. Adjusts the speaker volume up.

    -
    AKEYCODE_VOLUME_DOWN  -

    Volume Down key. Adjusts the speaker volume down.

    -
    AKEYCODE_POWER  -

    Power key.

    -
    AKEYCODE_CAMERA  -

    Camera key. Used to launch a camera application or take pictures.

    -
    AKEYCODE_CLEAR  -

    Clear key.

    -
    AKEYCODE_A  -

    'A' key.

    -
    AKEYCODE_B  -

    'B' key.

    -
    AKEYCODE_C  -

    'C' key.

    -
    AKEYCODE_D  -

    'D' key.

    -
    AKEYCODE_E  -

    'E' key.

    -
    AKEYCODE_F  -

    'F' key.

    -
    AKEYCODE_G  -

    'G' key.

    -
    AKEYCODE_H  -

    'H' key.

    -
    AKEYCODE_I  -

    'I' key.

    -
    AKEYCODE_J  -

    'J' key.

    -
    AKEYCODE_K  -

    'K' key.

    -
    AKEYCODE_L  -

    'L' key.

    -
    AKEYCODE_M  -

    'M' key.

    -
    AKEYCODE_N  -

    'N' key.

    -
    AKEYCODE_O  -

    'O' key.

    -
    AKEYCODE_P  -

    'P' key.

    -
    AKEYCODE_Q  -

    'Q' key.

    -
    AKEYCODE_R  -

    'R' key.

    -
    AKEYCODE_S  -

    'S' key.

    -
    AKEYCODE_T  -

    'T' key.

    -
    AKEYCODE_U  -

    'U' key.

    -
    AKEYCODE_V  -

    'V' key.

    -
    AKEYCODE_W  -

    'W' key.

    -
    AKEYCODE_X  -

    'X' key.

    -
    AKEYCODE_Y  -

    'Y' key.

    -
    AKEYCODE_Z  -

    'Z' key.

    -
    AKEYCODE_COMMA  -

    ',' key.

    -
    AKEYCODE_PERIOD  -

    '.' key.

    -
    AKEYCODE_ALT_LEFT  -

    Left Alt modifier key.

    -
    AKEYCODE_ALT_RIGHT  -

    Right Alt modifier key.

    -
    AKEYCODE_SHIFT_LEFT  -

    Left Shift modifier key.

    -
    AKEYCODE_SHIFT_RIGHT  -

    Right Shift modifier key.

    -
    AKEYCODE_TAB  -

    Tab key.

    -
    AKEYCODE_SPACE  -

    Space key.

    -
    AKEYCODE_SYM  -

    Symbol modifier key. Used to enter alternate symbols.

    -
    AKEYCODE_EXPLORER  -

    Explorer special function key. Used to launch a browser application.

    -
    AKEYCODE_ENVELOPE  -

    Envelope special function key. Used to launch a mail application.

    -
    AKEYCODE_ENTER  -

    Enter key.

    -
    AKEYCODE_DEL  -

    Backspace key. Deletes characters before the insertion point, unlike AKEYCODE_FORWARD_DEL.

    -
    AKEYCODE_GRAVE  -

    '`' (backtick) key.

    -
    AKEYCODE_MINUS  -

    '-'.

    -
    AKEYCODE_EQUALS  -

    '=' key.

    -
    AKEYCODE_LEFT_BRACKET  -

    '[' key.

    -
    AKEYCODE_RIGHT_BRACKET  -

    ']' key.

    -
    AKEYCODE_BACKSLASH  -

    '\' key.

    -
    AKEYCODE_SEMICOLON  -

    ';' key.

    -
    AKEYCODE_APOSTROPHE  -

    ''' (apostrophe) key.

    -
    AKEYCODE_SLASH  -

    '/' key.

    -
    AKEYCODE_AT  -

    '@' key.

    -
    AKEYCODE_NUM  -

    Number modifier key. Used to enter numeric symbols. This key is not AKEYCODE_NUM_LOCK; it is more like AKEYCODE_ALT_LEFT.

    -
    AKEYCODE_HEADSETHOOK  -

    Headset Hook key. Used to hang up calls and stop media.

    -
    AKEYCODE_FOCUS  -

    Camera Focus key. Used to focus the camera.

    -
    AKEYCODE_PLUS  -

    '+' key.

    -
    AKEYCODE_MENU  -

    Menu key.

    -
    AKEYCODE_NOTIFICATION  -

    Notification key.

    -
    AKEYCODE_SEARCH  -

    Search key.

    -
    AKEYCODE_MEDIA_PLAY_PAUSE  -

    Play/Pause media key.

    -
    AKEYCODE_MEDIA_STOP  -

    Stop media key.

    -
    AKEYCODE_MEDIA_NEXT  -

    Play Next media key.

    -
    AKEYCODE_MEDIA_PREVIOUS  -

    Play Previous media key.

    -
    AKEYCODE_MEDIA_REWIND  -

    Rewind media key.

    -
    AKEYCODE_MEDIA_FAST_FORWARD  -

    Fast Forward media key.

    -
    AKEYCODE_MUTE  -

    Mute key. Mutes the microphone, unlike AKEYCODE_VOLUME_MUTE.

    -
    AKEYCODE_PAGE_UP  -

    Page Up key.

    -
    AKEYCODE_PAGE_DOWN  -

    Page Down key.

    -
    AKEYCODE_PICTSYMBOLS  -

    Picture Symbols modifier key. Used to switch symbol sets (Emoji, Kao-moji).

    -
    AKEYCODE_SWITCH_CHARSET  -

    Switch Charset modifier key. Used to switch character sets (Kanji, Katakana).

    -
    AKEYCODE_BUTTON_A  -

    A Button key. On a game controller, the A button should be either the button labeled A or the first button on the bottom row of controller buttons.

    -
    AKEYCODE_BUTTON_B  -

    B Button key. On a game controller, the B button should be either the button labeled B or the second button on the bottom row of controller buttons.

    -
    AKEYCODE_BUTTON_C  -

    C Button key. On a game controller, the C button should be either the button labeled C or the third button on the bottom row of controller buttons.

    -
    AKEYCODE_BUTTON_X  -

    X Button key. On a game controller, the X button should be either the button labeled X or the first button on the upper row of controller buttons.

    -
    AKEYCODE_BUTTON_Y  -

    Y Button key. On a game controller, the Y button should be either the button labeled Y or the second button on the upper row of controller buttons.

    -
    AKEYCODE_BUTTON_Z  -

    Z Button key. On a game controller, the Z button should be either the button labeled Z or the third button on the upper row of controller buttons.

    -
    AKEYCODE_BUTTON_L1  -

    L1 Button key. On a game controller, the L1 button should be either the button labeled L1 (or L) or the top left trigger button.

    -
    AKEYCODE_BUTTON_R1  -

    R1 Button key. On a game controller, the R1 button should be either the button labeled R1 (or R) or the top right trigger button.

    -
    AKEYCODE_BUTTON_L2  -

    L2 Button key. On a game controller, the L2 button should be either the button labeled L2 or the bottom left trigger button.

    -
    AKEYCODE_BUTTON_R2  -

    R2 Button key. On a game controller, the R2 button should be either the button labeled R2 or the bottom right trigger button.

    -
    AKEYCODE_BUTTON_THUMBL  -

    Left Thumb Button key. On a game controller, the left thumb button indicates that the left (or only) joystick is pressed.

    -
    AKEYCODE_BUTTON_THUMBR  -

    Right Thumb Button key. On a game controller, the right thumb button indicates that the right joystick is pressed.

    -
    AKEYCODE_BUTTON_START  -

    Start Button key. On a game controller, the button labeled Start.

    -
    AKEYCODE_BUTTON_SELECT  -

    Select Button key. On a game controller, the button labeled Select.

    -
    AKEYCODE_BUTTON_MODE  -

    Mode Button key. On a game controller, the button labeled Mode.

    -
    AKEYCODE_ESCAPE  -

    Escape key.

    -
    AKEYCODE_FORWARD_DEL  -

    Forward Delete key. Deletes characters ahead of the insertion point, unlike AKEYCODE_DEL.

    -
    AKEYCODE_CTRL_LEFT  -

    Left Control modifier key.

    -
    AKEYCODE_CTRL_RIGHT  -

    Right Control modifier key.

    -
    AKEYCODE_CAPS_LOCK  -

    Caps Lock key.

    -
    AKEYCODE_SCROLL_LOCK  -

    Scroll Lock key.

    -
    AKEYCODE_META_LEFT  -

    Left Meta modifier key.

    -
    AKEYCODE_META_RIGHT  -

    Right Meta modifier key.

    -
    AKEYCODE_FUNCTION  -

    Function modifier key.

    -
    AKEYCODE_SYSRQ  -

    System Request / Print Screen key.

    -
    AKEYCODE_BREAK  -

    Break / Pause key.

    -
    AKEYCODE_MOVE_HOME  -

    Home Movement key. Used for scrolling or moving the cursor around to the start of a line or to the top of a list.

    -
    AKEYCODE_MOVE_END  -

    End Movement key. Used for scrolling or moving the cursor around to the end of a line or to the bottom of a list.

    -
    AKEYCODE_INSERT  -

    Insert key. Toggles insert / overwrite edit mode.

    -
    AKEYCODE_FORWARD  -

    Forward key. Navigates forward in the history stack. Complement of AKEYCODE_BACK.

    -
    AKEYCODE_MEDIA_PLAY  -

    Play media key.

    -
    AKEYCODE_MEDIA_PAUSE  -

    Pause media key.

    -
    AKEYCODE_MEDIA_CLOSE  -

    Close media key. May be used to close a CD tray, for example.

    -
    AKEYCODE_MEDIA_EJECT  -

    Eject media key. May be used to eject a CD tray, for example.

    -
    AKEYCODE_MEDIA_RECORD  -

    Record media key.

    -
    AKEYCODE_F1  -

    F1 key.

    -
    AKEYCODE_F2  -

    F2 key.

    -
    AKEYCODE_F3  -

    F3 key.

    -
    AKEYCODE_F4  -

    F4 key.

    -
    AKEYCODE_F5  -

    F5 key.

    -
    AKEYCODE_F6  -

    F6 key.

    -
    AKEYCODE_F7  -

    F7 key.

    -
    AKEYCODE_F8  -

    F8 key.

    -
    AKEYCODE_F9  -

    F9 key.

    -
    AKEYCODE_F10  -

    F10 key.

    -
    AKEYCODE_F11  -

    F11 key.

    -
    AKEYCODE_F12  -

    F12 key.

    -
    AKEYCODE_NUM_LOCK  -

    Num Lock key. This is the Num Lock key; it is different from AKEYCODE_NUM. This key alters the behavior of other keys on the numeric keypad.

    -
    AKEYCODE_NUMPAD_0  -

    Numeric keypad '0' key.

    -
    AKEYCODE_NUMPAD_1  -

    Numeric keypad '1' key.

    -
    AKEYCODE_NUMPAD_2  -

    Numeric keypad '2' key.

    -
    AKEYCODE_NUMPAD_3  -

    Numeric keypad '3' key.

    -
    AKEYCODE_NUMPAD_4  -

    Numeric keypad '4' key.

    -
    AKEYCODE_NUMPAD_5  -

    Numeric keypad '5' key.

    -
    AKEYCODE_NUMPAD_6  -

    Numeric keypad '6' key.

    -
    AKEYCODE_NUMPAD_7  -

    Numeric keypad '7' key.

    -
    AKEYCODE_NUMPAD_8  -

    Numeric keypad '8' key.

    -
    AKEYCODE_NUMPAD_9  -

    Numeric keypad '9' key.

    -
    AKEYCODE_NUMPAD_DIVIDE  -

    Numeric keypad '/' key (for division).

    -
    AKEYCODE_NUMPAD_MULTIPLY  -

    Numeric keypad '*' key (for multiplication).

    -
    AKEYCODE_NUMPAD_SUBTRACT  -

    Numeric keypad '-' key (for subtraction).

    -
    AKEYCODE_NUMPAD_ADD  -

    Numeric keypad '+' key (for addition).

    -
    AKEYCODE_NUMPAD_DOT  -

    Numeric keypad '.' key (for decimals or digit grouping).

    -
    AKEYCODE_NUMPAD_COMMA  -

    Numeric keypad ',' key (for decimals or digit grouping).

    -
    AKEYCODE_NUMPAD_ENTER  -

    Numeric keypad Enter key.

    -
    AKEYCODE_NUMPAD_EQUALS  -

    Numeric keypad '=' key.

    -
    AKEYCODE_NUMPAD_LEFT_PAREN  -

    Numeric keypad '(' key.

    -
    AKEYCODE_NUMPAD_RIGHT_PAREN  -

    Numeric keypad ')' key.

    -
    AKEYCODE_VOLUME_MUTE  -

    Volume Mute key. Mutes the speaker, unlike AKEYCODE_MUTE. This key should normally be implemented as a toggle such that the first press mutes the speaker and the second press restores the original volume.

    -
    AKEYCODE_INFO  -

    Info key. Common on TV remotes to show additional information related to what is currently being viewed.

    -
    AKEYCODE_CHANNEL_UP  -

    Channel up key. On TV remotes, increments the television channel.

    -
    AKEYCODE_CHANNEL_DOWN  -

    Channel down key. On TV remotes, decrements the television channel.

    -
    AKEYCODE_ZOOM_IN  -

    Zoom in key.

    -
    AKEYCODE_ZOOM_OUT  -

    Zoom out key.

    -
    AKEYCODE_TV  -

    TV key. On TV remotes, switches to viewing live TV.

    -
    AKEYCODE_WINDOW  -

    Window key. On TV remotes, toggles picture-in-picture mode or other windowing functions.

    -
    AKEYCODE_GUIDE  -

    Guide key. On TV remotes, shows a programming guide.

    -
    AKEYCODE_DVR  -

    DVR key. On some TV remotes, switches to a DVR mode for recorded shows.

    -
    AKEYCODE_BOOKMARK  -

    Bookmark key. On some TV remotes, bookmarks content or web pages.

    -
    AKEYCODE_CAPTIONS  -

    Toggle captions key. Switches the mode for closed-captioning text, for example during television shows.

    -
    AKEYCODE_SETTINGS  -

    Settings key. Starts the system settings activity.

    -
    AKEYCODE_TV_POWER  -

    TV power key. On TV remotes, toggles the power on a television screen.

    -
    AKEYCODE_TV_INPUT  -

    TV input key. On TV remotes, switches the input on a television screen.

    -
    AKEYCODE_STB_POWER  -

    Set-top-box power key. On TV remotes, toggles the power on an external Set-top-box.

    -
    AKEYCODE_STB_INPUT  -

    Set-top-box input key. On TV remotes, switches the input mode on an external Set-top-box.

    -
    AKEYCODE_AVR_POWER  -

    A/V Receiver power key. On TV remotes, toggles the power on an external A/V Receiver.

    -
    AKEYCODE_AVR_INPUT  -

    A/V Receiver input key. On TV remotes, switches the input mode on an external A/V Receiver.

    -
    AKEYCODE_PROG_RED  -

    Red "programmable" key. On TV remotes, acts as a contextual/programmable key.

    -
    AKEYCODE_PROG_GREEN  -

    Green "programmable" key. On TV remotes, actsas a contextual/programmable key.

    -
    AKEYCODE_PROG_YELLOW  -

    Yellow "programmable" key. On TV remotes, acts as a contextual/programmable key.

    -
    AKEYCODE_PROG_BLUE  -

    Blue "programmable" key. On TV remotes, acts as a contextual/programmable key.

    -
    AKEYCODE_APP_SWITCH  -

    App switch key. Should bring up the application switcher dialog.

    -
    AKEYCODE_BUTTON_1  -

    Generic Game Pad Button #1.

    -
    AKEYCODE_BUTTON_2  -

    Generic Game Pad Button #2.

    -
    AKEYCODE_BUTTON_3  -

    Generic Game Pad Button #3.

    -
    AKEYCODE_BUTTON_4  -

    Generic Game Pad Button #4.

    -
    AKEYCODE_BUTTON_5  -

    Generic Game Pad Button #5.

    -
    AKEYCODE_BUTTON_6  -

    Generic Game Pad Button #6.

    -
    AKEYCODE_BUTTON_7  -

    Generic Game Pad Button #7.

    -
    AKEYCODE_BUTTON_8  -

    Generic Game Pad Button #8.

    -
    AKEYCODE_BUTTON_9  -

    Generic Game Pad Button #9.

    -
    AKEYCODE_BUTTON_10  -

    Generic Game Pad Button #10.

    -
    AKEYCODE_BUTTON_11  -

    Generic Game Pad Button #11.

    -
    AKEYCODE_BUTTON_12  -

    Generic Game Pad Button #12.

    -
    AKEYCODE_BUTTON_13  -

    Generic Game Pad Button #13.

    -
    AKEYCODE_BUTTON_14  -

    Generic Game Pad Button #14.

    -
    AKEYCODE_BUTTON_15  -

    Generic Game Pad Button #15.

    -
    AKEYCODE_BUTTON_16  -

    Generic Game Pad Button #16.

    -
    AKEYCODE_LANGUAGE_SWITCH  -

    Language Switch key. Toggles the current input language such as switching between English and Japanese on a QWERTY keyboard. On some devices, the same function may be performed by pressing Shift+Spacebar.

    -
    AKEYCODE_MANNER_MODE  -

    Manner Mode key. Toggles silent or vibrate mode on and off to make the device behave more politely in certain settings such as on a crowded train. On some devices, the key may only operate when long-pressed.

    -
    AKEYCODE_3D_MODE  -

    3D Mode key. Toggles the display between 2D and 3D mode.

    -
    AKEYCODE_CONTACTS  -

    Contacts special function key. Used to launch an address book application.

    -
    AKEYCODE_CALENDAR  -

    Calendar special function key. Used to launch a calendar application.

    -
    AKEYCODE_MUSIC  -

    Music special function key. Used to launch a music player application.

    -
    AKEYCODE_CALCULATOR  -

    Calculator special function key. Used to launch a calculator application.

    -
    AKEYCODE_ZENKAKU_HANKAKU  -

    Japanese full-width / half-width key.

    -
    AKEYCODE_EISU  -

    Japanese alphanumeric key.

    -
    AKEYCODE_MUHENKAN  -

    Japanese non-conversion key.

    -
    AKEYCODE_HENKAN  -

    Japanese conversion key.

    -
    AKEYCODE_KATAKANA_HIRAGANA  -

    Japanese katakana / hiragana key.

    -
    AKEYCODE_YEN  -

    Japanese Yen key.

    -
    AKEYCODE_RO  -

    Japanese Ro key.

    -
    AKEYCODE_KANA  -

    Japanese kana key.

    -
    AKEYCODE_ASSIST  -

    Assist key. Launches the global assist activity. Not delivered to applications.

    -
    AKEYCODE_BRIGHTNESS_DOWN  -

    Brightness Down key. Adjusts the screen brightness down.

    -
    AKEYCODE_BRIGHTNESS_UP  -

    Brightness Up key. Adjusts the screen brightness up.

    -
    AKEYCODE_MEDIA_AUDIO_TRACK  -

    Audio Track key. Switches the audio tracks.

    -
    AKEYCODE_SLEEP  -

    Sleep key. Puts the device to sleep. Behaves somewhat like AKEYCODE_POWER but it has no effect if the device is already asleep.

    -
    AKEYCODE_WAKEUP  -

    Wakeup key. Wakes up the device. Behaves somewhat like AKEYCODE_POWER but it has no effect if the device is already awake.

    -
    AKEYCODE_PAIRING  -

    Pairing key. Initiates peripheral pairing mode. Useful for pairing remote control devices or game controllers, especially if no other input mode is available.

    -
    AKEYCODE_MEDIA_TOP_MENU  -

    Media Top Menu key. Goes to the top of media menu.

    -
    AKEYCODE_11  -

    '11' key.

    -
    AKEYCODE_12  -

    '12' key.

    -
    AKEYCODE_LAST_CHANNEL  -

    Last Channel key. Goes to the last viewed channel.

    -
    AKEYCODE_TV_DATA_SERVICE  -

    TV data service key. Displays data services like weather, sports.

    -
    AKEYCODE_VOICE_ASSIST  -

    Voice Assist key. Launches the global voice assist activity. Not delivered to applications.

    -
    AKEYCODE_TV_RADIO_SERVICE  -

    Radio key. Toggles TV service / Radio service.

    -
    AKEYCODE_TV_TELETEXT  -

    Teletext key. Displays Teletext service.

    -
    AKEYCODE_TV_NUMBER_ENTRY  -

    Number entry key. Initiates to enter multi-digit channel nubmber when each digit key is assigned for selecting separate channel. Corresponds to Number Entry Mode (0x1D) of CEC User Control Code.

    -
    AKEYCODE_TV_TERRESTRIAL_ANALOG  -

    Analog Terrestrial key. Switches to analog terrestrial broadcast service.

    -
    AKEYCODE_TV_TERRESTRIAL_DIGITAL  -

    Digital Terrestrial key. Switches to digital terrestrial broadcast service.

    -
    AKEYCODE_TV_SATELLITE  -

    Satellite key. Switches to digital satellite broadcast service.

    -
    AKEYCODE_TV_SATELLITE_BS  -

    BS key. Switches to BS digital satellite broadcasting service available in Japan.

    -
    AKEYCODE_TV_SATELLITE_CS  -

    CS key. Switches to CS digital satellite broadcasting service available in Japan.

    -
    AKEYCODE_TV_SATELLITE_SERVICE  -

    BS/CS key. Toggles between BS and CS digital satellite services.

    -
    AKEYCODE_TV_NETWORK  -

    Toggle Network key. Toggles selecting broacast services.

    -
    AKEYCODE_TV_ANTENNA_CABLE  -

    Antenna/Cable key. Toggles broadcast input source between antenna and cable.

    -
    AKEYCODE_TV_INPUT_HDMI_1  -

    HDMI #1 key. Switches to HDMI input #1.

    -
    AKEYCODE_TV_INPUT_HDMI_2  -

    HDMI #2 key. Switches to HDMI input #2.

    -
    AKEYCODE_TV_INPUT_HDMI_3  -

    HDMI #3 key. Switches to HDMI input #3.

    -
    AKEYCODE_TV_INPUT_HDMI_4  -

    HDMI #4 key. Switches to HDMI input #4.

    -
    AKEYCODE_TV_INPUT_COMPOSITE_1  -

    Composite #1 key. Switches to composite video input #1.

    -
    AKEYCODE_TV_INPUT_COMPOSITE_2  -

    Composite #2 key. Switches to composite video input #2.

    -
    AKEYCODE_TV_INPUT_COMPONENT_1  -

    Component #1 key. Switches to component video input #1.

    -
    AKEYCODE_TV_INPUT_COMPONENT_2  -

    Component #2 key. Switches to component video input #2.

    -
    AKEYCODE_TV_INPUT_VGA_1  -

    VGA #1 key. Switches to VGA (analog RGB) input #1.

    -
    AKEYCODE_TV_AUDIO_DESCRIPTION  -

    Audio description key. Toggles audio description off / on.

    -
    AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP  -

    Audio description mixing volume up key. Louden audio description volume as compared with normal audio volume.

    -
    AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN  -

    Audio description mixing volume down key. Lessen audio description volume as compared with normal audio volume.

    -
    AKEYCODE_TV_ZOOM_MODE  -

    Zoom mode key. Changes Zoom mode (Normal, Full, Zoom, Wide-zoom, etc.)

    -
    AKEYCODE_TV_CONTENTS_MENU  -

    Contents menu key. Goes to the title list. Corresponds to Contents Menu (0x0B) of CEC User Control Code

    -
    AKEYCODE_TV_MEDIA_CONTEXT_MENU  -

    Media context menu key. Goes to the context menu of media contents. Corresponds to Media Context-sensitive Menu (0x11) of CEC User Control Code.

    -
    AKEYCODE_TV_TIMER_PROGRAMMING  -

    Timer programming key. Goes to the timer recording menu. Corresponds to Timer Programming (0x54) of CEC User Control Code.

    -
    AKEYCODE_HELP  -

    Help key.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Key states (may be returned by queries about the current state of a particular key code, scan code or switch).

    - - - - - -
    Enumerator
    AKEY_STATE_UNKNOWN  -

    The key state is unknown or the requested key itself is not supported.

    -
    AKEY_STATE_UP  -

    The key is up.

    -
    AKEY_STATE_DOWN  -

    The key is down.

    -
    AKEY_STATE_VIRTUAL  -

    The key is down but is a virtual key press that is being emulated by the system.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Meta key / modifer state.

    - - - - - - - - - - - - - - - - - - - -
    Enumerator
    AMETA_NONE  -

    No meta keys are pressed.

    -
    AMETA_ALT_ON  -

    This mask is used to check whether one of the ALT meta keys is pressed.

    -
    AMETA_ALT_LEFT_ON  -

    This mask is used to check whether the left ALT meta key is pressed.

    -
    AMETA_ALT_RIGHT_ON  -

    This mask is used to check whether the right ALT meta key is pressed.

    -
    AMETA_SHIFT_ON  -

    This mask is used to check whether one of the SHIFT meta keys is pressed.

    -
    AMETA_SHIFT_LEFT_ON  -

    This mask is used to check whether the left SHIFT meta key is pressed.

    -
    AMETA_SHIFT_RIGHT_ON  -

    This mask is used to check whether the right SHIFT meta key is pressed.

    -
    AMETA_SYM_ON  -

    This mask is used to check whether the SYM meta key is pressed.

    -
    AMETA_FUNCTION_ON  -

    This mask is used to check whether the FUNCTION meta key is pressed.

    -
    AMETA_CTRL_ON  -

    This mask is used to check whether one of the CTRL meta keys is pressed.

    -
    AMETA_CTRL_LEFT_ON  -

    This mask is used to check whether the left CTRL meta key is pressed.

    -
    AMETA_CTRL_RIGHT_ON  -

    This mask is used to check whether the right CTRL meta key is pressed.

    -
    AMETA_META_ON  -

    This mask is used to check whether one of the META meta keys is pressed.

    -
    AMETA_META_LEFT_ON  -

    This mask is used to check whether the left META meta key is pressed.

    -
    AMETA_META_RIGHT_ON  -

    This mask is used to check whether the right META meta key is pressed.

    -
    AMETA_CAPS_LOCK_ON  -

    This mask is used to check whether the CAPS LOCK meta key is on.

    -
    AMETA_NUM_LOCK_ON  -

    This mask is used to check whether the NUM LOCK meta key is on.

    -
    AMETA_SCROLL_LOCK_ON  -

    This mask is used to check whether the SCROLL LOCK meta key is on.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Input event types.

    - - - -
    Enumerator
    AINPUT_EVENT_TYPE_KEY  -

    Indicates that the input event is a key event.

    -
    AINPUT_EVENT_TYPE_MOTION  -

    Indicates that the input event is a motion event.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Key event actions.

    - - - - -
    Enumerator
    AKEY_EVENT_ACTION_DOWN  -

    The key has been pressed down.

    -
    AKEY_EVENT_ACTION_UP  -

    The key has been released.

    -
    AKEY_EVENT_ACTION_MULTIPLE  -

    Multiple duplicate key events have occurred in a row, or a complex string is being delivered. The repeat_count property of the key event contains the number of times the given key code should be executed.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Key event flags.

    - - - - - - - - - - - - -
    Enumerator
    AKEY_EVENT_FLAG_WOKE_HERE  -

    This mask is set if the device woke because of this key event.

    -
    AKEY_EVENT_FLAG_SOFT_KEYBOARD  -

    This mask is set if the key event was generated by a software keyboard.

    -
    AKEY_EVENT_FLAG_KEEP_TOUCH_MODE  -

    This mask is set if we don't want the key event to cause us to leave touch mode.

    -
    AKEY_EVENT_FLAG_FROM_SYSTEM  -

    This mask is set if an event was known to come from a trusted part of the system. That is, the event is known to come from the user, and could not have been spoofed by a third party component.

    -
    AKEY_EVENT_FLAG_EDITOR_ACTION  -

    This mask is used for compatibility, to identify enter keys that are coming from an IME whose enter key has been auto-labelled "next" or "done". This allows TextView to dispatch these as normal enter keys for old applications, but still do the appropriate action when receiving them.

    -
    AKEY_EVENT_FLAG_CANCELED  -

    When associated with up key events, this indicates that the key press has been canceled. Typically this is used with virtual touch screen keys, where the user can slide from the virtual key area on to the display: in that case, the application will receive a canceled up event and should not perform the action normally associated with the key. Note that for this to work, the application can not perform an action for a key until it receives an up or the long press timeout has expired.

    -
    AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY  -

    This key event was generated by a virtual (on-screen) hard key area. Typically this is an area of the touchscreen, outside of the regular display, dedicated to "hardware" buttons.

    -
    AKEY_EVENT_FLAG_LONG_PRESS  -

    This flag is set for the first key repeat that occurs after the long press timeout.

    -
    AKEY_EVENT_FLAG_CANCELED_LONG_PRESS  -

    Set when a key event has AKEY_EVENT_FLAG_CANCELED set because a long press action was executed while it was down.

    -
    AKEY_EVENT_FLAG_TRACKING  -

    Set for AKEY_EVENT_ACTION_UP when this event's key code is still being tracked from its initial down. That is, somebody requested that tracking started on the key down and a long press has not caused the tracking to be canceled.

    -
    AKEY_EVENT_FLAG_FALLBACK  -

    Set when a key event has been synthesized to implement default behavior for an event that the application did not handle. Fallback key events are generated by unhandled trackball motions (to emulate a directional keypad) and by certain unhandled key presses that are declared in the key map (such as special function numeric keypad keys when numlock is off).

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Motion event actions

    - - - - - - - - - - - - - - -
    Enumerator
    AMOTION_EVENT_ACTION_MASK  -

    Bit mask of the parts of the action code that are the action itself.

    -
    AMOTION_EVENT_ACTION_POINTER_INDEX_MASK  -

    Bits in the action code that represent a pointer index, used with AMOTION_EVENT_ACTION_POINTER_DOWN and AMOTION_EVENT_ACTION_POINTER_UP. Shifting down by AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT provides the actual pointer index where the data for the pointer going up or down can be found.

    -
    AMOTION_EVENT_ACTION_DOWN  -

    A pressed gesture has started, the motion contains the initial starting location.

    -
    AMOTION_EVENT_ACTION_UP  -

    A pressed gesture has finished, the motion contains the final release location as well as any intermediate points since the last down or move event.

    -
    AMOTION_EVENT_ACTION_MOVE  -

    A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and AMOTION_EVENT_ACTION_UP). The motion contains the most recent point, as well as any intermediate points since the last down or move event.

    -
    AMOTION_EVENT_ACTION_CANCEL  -

    The current gesture has been aborted. You will not receive any more points in it. You should treat this as an up event, but not perform any action that you normally would.

    -
    AMOTION_EVENT_ACTION_OUTSIDE  -

    A movement has happened outside of the normal bounds of the UI element. This does not provide a full gesture, but only the initial location of the movement/touch.

    -
    AMOTION_EVENT_ACTION_POINTER_DOWN  -

    A non-primary pointer has gone down. The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.

    -
    AMOTION_EVENT_ACTION_POINTER_UP  -

    A non-primary pointer has gone up. The bits in AMOTION_EVENT_ACTION_POINTER_INDEX_MASK indicate which pointer changed.

    -
    AMOTION_EVENT_ACTION_HOVER_MOVE  -

    A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE). The motion contains the most recent point, as well as any intermediate points since the last hover move event.

    -
    AMOTION_EVENT_ACTION_SCROLL  -

    The motion event contains relative vertical and/or horizontal scroll offsets. Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL and AMOTION_EVENT_AXIS_HSCROLL. The pointer may or may not be down when this event is dispatched. This action is always delivered to the winder under the pointer, which may not be the window currently touched.

    -
    AMOTION_EVENT_ACTION_HOVER_ENTER  -

    The pointer is not down but has entered the boundaries of a window or view.

    -
    AMOTION_EVENT_ACTION_HOVER_EXIT  -

    The pointer is not down but has exited the boundaries of a window or view.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Motion event flags.

    - - -
    Enumerator
    AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED  -

    This flag indicates that the window that received this motion event is partly or wholly obscured by another visible window above it. This flag is set to true even if the event did not directly pass through the obscured area. A security sensitive application can check this flag to identify situations in which a malicious application may have covered up part of its content for the purpose of misleading the user or hijacking touches. An appropriate response might be to drop the suspect touches or to take additional precautions to confirm the user's actual intent.

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - -
    int32_t AInputEvent_getDeviceId (const AInputEventevent)
    -
    -

    Get the id for the device that an input event came from.

    -

    Input events can be generated by multiple different input devices. Use the input device id to obtain information about the input device that was responsible for generating a particular event.

    -

    An input device id of 0 indicates that the event didn't come from a physical device; other numbers are arbitrary and you shouldn't depend on the values. Use the provided input device query API to obtain information about input devices.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AInputEvent_getSource (const AInputEventevent)
    -
    -

    Get the input event source.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AInputEvent_getType (const AInputEventevent)
    -
    -

    Input event accessors.

    -

    Note that most functions can only be used on input events that are of a given type. Calling these functions on input events of other types will yield undefined behavior.Get the input event type.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void AInputQueue_attachLooper (AInputQueuequeue,
    ALooperlooper,
    int ident,
    ALooper_callbackFunc callback,
    void * data 
    )
    -
    -

    Add this input queue to a looper for processing. See ALooper_addFd() for information on the ident, callback, and data params.

    - -
    -
    - -
    -
    - - - - - - - - -
    void AInputQueue_detachLooper (AInputQueuequeue)
    -
    -

    Remove the input queue from the looper it is currently attached to.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void AInputQueue_finishEvent (AInputQueuequeue,
    AInputEventevent,
    int handled 
    )
    -
    -

    Report that dispatching has finished with the given event. This must be called after receiving an event with AInputQueue_get_event().

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int32_t AInputQueue_getEvent (AInputQueuequeue,
    AInputEvent ** outEvent 
    )
    -
    -

    Returns the next available event from the queue. Returns a negative value if no events are available or an error has occurred.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AInputQueue_hasEvents (AInputQueuequeue)
    -
    -

    Returns true if there are one or more events available in the input queue. Returns 1 if the queue has events; 0 if it does not have events; and a negative value if there is an error.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int32_t AInputQueue_preDispatchEvent (AInputQueuequeue,
    AInputEventevent 
    )
    -
    -

    Sends the key for standard pre-dispatching – that is, possibly deliver it to the current IME to be consumed before the app. Returns 0 if it was not pre-dispatched, meaning you can process it right now. If non-zero is returned, you must abandon the current event processing and allow the event to appear again in the event queue (if it does not get consumed during pre-dispatching).

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AKeyEvent_getAction (const AInputEventkey_event)
    -
    -

    Get the key event action.

    - -
    -
    - -
    -
    - - - - - - - - -
    int64_t AKeyEvent_getDownTime (const AInputEventkey_event)
    -
    -

    Get the time of the most recent key down event, in the java.lang.System.nanoTime() time base. If this is a down event, this will be the same as eventTime. Note that when chording keys, this value is the down time of the most recently pressed key, which may not be the same physical key of this event.

    - -
    -
    - -
    -
    - - - - - - - - -
    int64_t AKeyEvent_getEventTime (const AInputEventkey_event)
    -
    -

    Get the time this event occurred, in the java.lang.System.nanoTime() time base.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AKeyEvent_getFlags (const AInputEventkey_event)
    -
    -

    Get the key event flags.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AKeyEvent_getKeyCode (const AInputEventkey_event)
    -
    -

    Get the key code of the key event. This is the physical key that was pressed, not the Unicode character.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AKeyEvent_getMetaState (const AInputEventkey_event)
    -
    -

    Get the meta key state.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AKeyEvent_getRepeatCount (const AInputEventkey_event)
    -
    -

    Get the repeat count of the event. For both key up an key down events, this is the number of times the key has repeated with the first down starting at 0 and counting up from there. For multiple key events, this is the number of down/up pairs that have occurred.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AKeyEvent_getScanCode (const AInputEventkey_event)
    -
    -

    Get the hardware key id of this key event. These values are not reliable and vary from device to device.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AMotionEvent_getAction (const AInputEventmotion_event)
    -
    -

    Get the combined motion event action code and pointer index.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getAxisValue (const AInputEventmotion_event,
    int32_t axis,
    size_t pointer_index 
    )
    -
    -

    Get the value of the request axis for the given pointer index.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AMotionEvent_getButtonState (const AInputEventmotion_event)
    -
    -

    Get the button state of all buttons that are pressed.

    - -
    -
    - -
    -
    - - - - - - - - -
    int64_t AMotionEvent_getDownTime (const AInputEventmotion_event)
    -
    -

    Get the time when the user originally pressed down to start a stream of position events, in the java.lang.System.nanoTime() time base.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AMotionEvent_getEdgeFlags (const AInputEventmotion_event)
    -
    -

    Get a bitfield indicating which edges, if any, were touched by this motion event. For touch events, clients can use this to determine if the user's finger was touching the edge of the display.

    - -
    -
    - -
    -
    - - - - - - - - -
    int64_t AMotionEvent_getEventTime (const AInputEventmotion_event)
    -
    -

    Get the time when this specific event was generated, in the java.lang.System.nanoTime() time base.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AMotionEvent_getFlags (const AInputEventmotion_event)
    -
    -

    Get the motion event flags.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalAxisValue (const AInputEventmotion_event,
    int32_t axis,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical value of the request axis for the given pointer index that occurred between this event and the previous motion event.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int64_t AMotionEvent_getHistoricalEventTime (const AInputEventmotion_event,
    size_t history_index 
    )
    -
    -

    Get the time that a historical movement occurred between this event and the previous event, in the java.lang.System.nanoTime() time base.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalOrientation (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical orientation of the touch area and tool area in radians clockwise from vertical for the given pointer index that occurred between this event and the previous motion event. An angle of 0 degrees indicates that the major axis of contact is oriented upwards, is perfectly circular or is of unknown orientation. A positive angle indicates that the major axis of contact is oriented to the right. A negative angle indicates that the major axis of contact is oriented to the left. The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians (finger pointing fully right).

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalPressure (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical pressure of this event for the given pointer index that occurred between this event and the previous motion event. The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), although values higher than 1 may be generated depending on the calibration of the input device.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalRawX (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical raw X coordinate of this event for the given pointer index that occurred between this event and the previous motion event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views. Whole numbers are pixels; the value may have a fraction for input devices that are sub-pixel precise.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalRawY (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical raw Y coordinate of this event for the given pointer index that occurred between this event and the previous motion event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views. Whole numbers are pixels; the value may have a fraction for input devices that are sub-pixel precise.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalSize (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the current scaled value of the approximate size for the given pointer index that occurred between this event and the previous motion event. This represents some approximation of the area of the screen being pressed; the actual value in pixels corresponding to the touch is normalized with the device specific range of values and scaled to a value between 0 and 1. The value of size can be used to determine fat touch events.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalToolMajor (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical length of the major axis of an ellipse that describes the size of the approaching tool for the given pointer index that occurred between this event and the previous motion event. The tool area represents the estimated size of the finger or pen that is touching the device independent of its actual touch area at the point of contact.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalToolMinor (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical length of the minor axis of an ellipse that describes the size of the approaching tool for the given pointer index that occurred between this event and the previous motion event. The tool area represents the estimated size of the finger or pen that is touching the device independent of its actual touch area at the point of contact.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalTouchMajor (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical length of the major axis of an ellipse that describes the touch area at the point of contact for the given pointer index that occurred between this event and the previous motion event.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalTouchMinor (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical length of the minor axis of an ellipse that describes the touch area at the point of contact for the given pointer index that occurred between this event and the previous motion event.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalX (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical X coordinate of this event for the given pointer index that occurred between this event and the previous motion event. Whole numbers are pixels; the value may have a fraction for input devices that are sub-pixel precise.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getHistoricalY (const AInputEventmotion_event,
    size_t pointer_index,
    size_t history_index 
    )
    -
    -

    Get the historical Y coordinate of this event for the given pointer index that occurred between this event and the previous motion event. Whole numbers are pixels; the value may have a fraction for input devices that are sub-pixel precise.

    - -
    -
    - -
    -
    - - - - - - - - -
    size_t AMotionEvent_getHistorySize (const AInputEventmotion_event)
    -
    -

    Get the number of historical points in this event. These are movements that have occurred between this event and the previous event. This only applies to AMOTION_EVENT_ACTION_MOVE events – all other actions will have a size of 0. Historical samples are indexed from oldest to newest.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AMotionEvent_getMetaState (const AInputEventmotion_event)
    -
    -

    Get the state of any meta / modifier keys that were in effect when the event was generated.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getOrientation (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current orientation of the touch area and tool area in radians clockwise from vertical for the given pointer index. An angle of 0 degrees indicates that the major axis of contact is oriented upwards, is perfectly circular or is of unknown orientation. A positive angle indicates that the major axis of contact is oriented to the right. A negative angle indicates that the major axis of contact is oriented to the left. The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians (finger pointing fully right).

    - -
    -
    - -
    -
    - - - - - - - - -
    size_t AMotionEvent_getPointerCount (const AInputEventmotion_event)
    -
    -

    Get the number of pointers of data contained in this event. Always >= 1.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int32_t AMotionEvent_getPointerId (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the pointer identifier associated with a particular 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.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getPressure (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current pressure of this event for the given pointer index. The pressure generally ranges from 0 (no pressure at all) to 1 (normal pressure), although values higher than 1 may be generated depending on the calibration of the input device.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getRawX (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the original raw X coordinate of this event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getRawY (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the original raw X coordinate of this event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getSize (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current scaled value of the approximate size for the given pointer index. This represents some approximation of the area of the screen being pressed; the actual value in pixels corresponding to the touch is normalized with the device specific range of values and scaled to a value between 0 and 1. The value of size can be used to determine fat touch events.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getToolMajor (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current length of the major axis of an ellipse that describes the size of the approaching tool for the given pointer index. The tool area represents the estimated size of the finger or pen that is touching the device independent of its actual touch area at the point of contact.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getToolMinor (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current length of the minor axis of an ellipse that describes the size of the approaching tool for the given pointer index. The tool area represents the estimated size of the finger or pen that is touching the device independent of its actual touch area at the point of contact.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int32_t AMotionEvent_getToolType (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the tool type of a pointer for the given pointer index. The tool type indicates the type of tool used to make contact such as a finger or stylus, if known.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getTouchMajor (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current length of the major axis of an ellipse that describes the touch area at the point of contact for the given pointer index.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getTouchMinor (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current length of the minor axis of an ellipse that describes the touch area at the point of contact for the given pointer index.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getX (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current X coordinate of this event for the given pointer index. Whole numbers are pixels; the value may have a fraction for input devices that are sub-pixel precise.

    - -
    -
    - -
    -
    - - - - - - - - -
    float AMotionEvent_getXOffset (const AInputEventmotion_event)
    -
    -

    Get the X coordinate offset. For touch events on the screen, this is the delta that was added to the raw screen coordinates to adjust for the absolute position of the containing windows and views.

    - -
    -
    - -
    -
    - - - - - - - - -
    float AMotionEvent_getXPrecision (const AInputEventmotion_event)
    -
    -

    Get the precision of the X coordinates being reported. You can multiply this number with an X coordinate sample to find the actual hardware value of the X coordinate.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    float AMotionEvent_getY (const AInputEventmotion_event,
    size_t pointer_index 
    )
    -
    -

    Get the current Y coordinate of this event for the given pointer index. Whole numbers are pixels; the value may have a fraction for input devices that are sub-pixel precise.

    - -
    -
    - -
    -
    - - - - - - - - -
    float AMotionEvent_getYOffset (const AInputEventmotion_event)
    -
    -

    Get the Y coordinate offset. For touch events on the screen, this is the delta that was added to the raw screen coordinates to adjust for the absolute position of the containing windows and views.

    - -
    -
    - -
    -
    - - - - - - - - -
    float AMotionEvent_getYPrecision (const AInputEventmotion_event)
    -
    -

    Get the precision of the Y coordinates being reported. You can multiply this number with a Y coordinate sample to find the actual hardware value of the Y coordinate.

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/group___looper.jd b/docs/html/ndk/reference/group___looper.jd deleted file mode 100644 index bc845f82a5ab7fdaa9263438c0747393edcfe2aa..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___looper.jd +++ /dev/null @@ -1,442 +0,0 @@ -page.title=Looper -page.customHeadTag= -@jd:body - - -
    - -
    -
    Looper
    -
    -
    - - - - -

    -Files

    file  looper.h
     
    - - - - - -

    -Typedefs

    typedef struct ALooper ALooper
     
    typedef int(* ALooper_callbackFunc )(int fd, int events, void *data)
     
    - - - - - - - -

    -Enumerations

    enum  { ALOOPER_PREPARE_ALLOW_NON_CALLBACKS = 1<<0 - }
     
    enum  { ALOOPER_POLL_WAKE = -1, -ALOOPER_POLL_CALLBACK = -2, -ALOOPER_POLL_TIMEOUT = -3, -ALOOPER_POLL_ERROR = -4 - }
     
    enum  {
    -  ALOOPER_EVENT_INPUT = 1 << 0, -ALOOPER_EVENT_OUTPUT = 1 << 1, -ALOOPER_EVENT_ERROR = 1 << 2, -ALOOPER_EVENT_HANGUP = 1 << 3, -
    -  ALOOPER_EVENT_INVALID = 1 << 4 -
    - }
     
    - - - - - - - - - - - - - - - - - - - -

    -Functions

    ALooperALooper_forThread ()
     
    ALooperALooper_prepare (int opts)
     
    void ALooper_acquire (ALooper *looper)
     
    void ALooper_release (ALooper *looper)
     
    int ALooper_pollOnce (int timeoutMillis, int *outFd, int *outEvents, void **outData)
     
    int ALooper_pollAll (int timeoutMillis, int *outFd, int *outEvents, void **outData)
     
    void ALooper_wake (ALooper *looper)
     
    int ALooper_addFd (ALooper *looper, int fd, int ident, int events, ALooper_callbackFunc callback, void *data)
     
    int ALooper_removeFd (ALooper *looper, int fd)
     
    -

    Detailed Description

    -

    Typedef Documentation

    - -
    -
    - - - - -
    typedef struct ALooper ALooper
    -
    -

    ALooper

    -

    A looper is the state tracking an event loop for a thread. Loopers do not define event structures or other such things; rather they are a lower-level facility to attach one or more discrete objects listening for an event. An "event" here is simply data available on a file descriptor: each attached object has an associated file descriptor, and waiting for "events" means (internally) polling on all of these file descriptors until one or more of them have data available.

    -

    A thread can have only one ALooper associated with it.

    - -
    -
    - -
    -
    - - - - -
    typedef int(* ALooper_callbackFunc)(int fd, int events, void *data)
    -
    -

    For callback-based event loops, this is the prototype of the function that is called when a file descriptor event occurs. It is given the file descriptor it is associated with, a bitmask of the poll events that were triggered (typically ALOOPER_EVENT_INPUT), and the data pointer that was originally supplied.

    -

    Implementations should return 1 to continue receiving callbacks, or 0 to have this file descriptor and callback unregistered from the looper.

    - -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Option for for ALooper_prepare().

    - - -
    Enumerator
    ALOOPER_PREPARE_ALLOW_NON_CALLBACKS  -

    This looper will accept calls to ALooper_addFd() that do not have a callback (that is provide NULL for the callback). In this case the caller of ALooper_pollOnce() or ALooper_pollAll() MUST check the return from these functions to discover when data is available on such fds and process it.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Result from ALooper_pollOnce() and ALooper_pollAll().

    - - - - - -
    Enumerator
    ALOOPER_POLL_WAKE  -

    The poll was awoken using wake() before the timeout expired and no callbacks were executed and no other file descriptors were ready.

    -
    ALOOPER_POLL_CALLBACK  -

    Result from ALooper_pollOnce() and ALooper_pollAll(): One or more callbacks were executed.

    -
    ALOOPER_POLL_TIMEOUT  -

    Result from ALooper_pollOnce() and ALooper_pollAll(): The timeout expired.

    -
    ALOOPER_POLL_ERROR  -

    Result from ALooper_pollOnce() and ALooper_pollAll(): An error occurred.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Flags for file descriptor events that a looper can monitor.

    -

    These flag bits can be combined to monitor multiple events at once.

    - - - - - - -
    Enumerator
    ALOOPER_EVENT_INPUT  -

    The file descriptor is available for read operations.

    -
    ALOOPER_EVENT_OUTPUT  -

    The file descriptor is available for write operations.

    -
    ALOOPER_EVENT_ERROR  -

    The file descriptor has encountered an error condition.

    -

    The looper always sends notifications about errors; it is not necessary to specify this event flag in the requested event set.

    -
    ALOOPER_EVENT_HANGUP  -

    The file descriptor was hung up. For example, indicates that the remote end of a pipe or socket was closed.

    -

    The looper always sends notifications about hangups; it is not necessary to specify this event flag in the requested event set.

    -
    ALOOPER_EVENT_INVALID  -

    The file descriptor is invalid. For example, the file descriptor was closed prematurely.

    -

    The looper always sends notifications about invalid file descriptors; it is not necessary to specify this event flag in the requested event set.

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - -
    void ALooper_acquire (ALooperlooper)
    -
    -

    Acquire a reference on the given ALooper object. This prevents the object from being deleted until the reference is removed. This is only needed to safely hand an ALooper from one thread to another.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    int ALooper_addFd (ALooperlooper,
    int fd,
    int ident,
    int events,
    ALooper_callbackFunc callback,
    void * data 
    )
    -
    -

    Adds a new file descriptor to be polled by the looper. If the same file descriptor was previously added, it is replaced.

    -

    "fd" is the file descriptor to be added. "ident" is an identifier for this event, which is returned from ALooper_pollOnce(). The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback. "events" are the poll events to wake up on. Typically this is ALOOPER_EVENT_INPUT. "callback" is the function to call when there is an event on the file descriptor. "data" is a private data pointer to supply to the callback.

    -

    There are two main uses of this function:

    -

    (1) If "callback" is non-NULL, then this function will be called when there is data on the file descriptor. It should execute any events it has pending, appropriately reading from the file descriptor. The 'ident' is ignored in this case.

    -

    (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce when its file descriptor has data available, requiring the caller to take care of processing it.

    -

    Returns 1 if the file descriptor was added or -1 if an error occurred.

    -

    This method can be called on any thread. This method may block briefly if it needs to wake the poll.

    - -
    -
    - -
    -
    - - - - - - - -
    ALooper* ALooper_forThread ()
    -
    -

    Returns the looper associated with the calling thread, or NULL if there is not one.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    int ALooper_pollAll (int timeoutMillis,
    int * outFd,
    int * outEvents,
    void ** outData 
    )
    -
    -

    Like ALooper_pollOnce(), but performs all pending callbacks until all data has been consumed or a file descriptor is available with no callback. This function will never return ALOOPER_POLL_CALLBACK.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    int ALooper_pollOnce (int timeoutMillis,
    int * outFd,
    int * outEvents,
    void ** outData 
    )
    -
    -

    Waits for events to be available, with optional timeout in milliseconds. Invokes callbacks for all file descriptors on which an event occurred.

    -

    If the timeout is zero, returns immediately without blocking. If the timeout is negative, waits indefinitely until an event appears.

    -

    Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before the timeout expired and no callbacks were invoked and no other file descriptors were ready.

    -

    Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.

    -

    Returns ALOOPER_POLL_TIMEOUT if there was no data before the given timeout expired.

    -

    Returns ALOOPER_POLL_ERROR if an error occurred.

    -

    Returns a value >= 0 containing an identifier (the same identifier ident passed to ALooper_addFd()) if its file descriptor has data and it has no callback function (requiring the caller here to handle it). In this (and only this) case outFd, outEvents and outData will contain the poll events and data associated with the fd, otherwise they will be set to NULL.

    -

    This method does not return until it has finished invoking the appropriate callbacks for all file descriptors that were signalled.

    - -
    -
    - -
    -
    - - - - - - - - -
    ALooper* ALooper_prepare (int opts)
    -
    -

    Prepares a looper associated with the calling thread, and returns it. If the thread already has a looper, it is returned. Otherwise, a new one is created, associated with the thread, and returned.

    -

    The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0.

    - -
    -
    - -
    -
    - - - - - - - - -
    void ALooper_release (ALooperlooper)
    -
    -

    Remove a reference that was previously acquired with ALooper_acquire().

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int ALooper_removeFd (ALooperlooper,
    int fd 
    )
    -
    -

    Removes a previously added file descriptor from the looper.

    -

    When this method returns, it is safe to close the file descriptor since the looper will no longer have a reference to it. However, it is possible for the callback to already be running or for it to run one last time if the file descriptor was already signalled. Calling code is responsible for ensuring that this case is safely handled. For example, if the callback takes care of removing itself during its own execution either by returning 0 or by calling this method, then it can be guaranteed to not be invoked again at any later time unless registered anew.

    -

    Returns 1 if the file descriptor was removed, 0 if none was previously registered or -1 if an error occurred.

    -

    This method can be called on any thread. This method may block briefly if it needs to wake the poll.

    - -
    -
    - -
    -
    - - - - - - - - -
    void ALooper_wake (ALooperlooper)
    -
    -

    Wakes the poll asynchronously.

    -

    This method can be called on any thread. This method returns immediately.

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/group___native_activity.jd b/docs/html/ndk/reference/group___native_activity.jd deleted file mode 100644 index d0b2178e389fee3ce6160e1e11717d672173b62a..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___native_activity.jd +++ /dev/null @@ -1,731 +0,0 @@ -page.title=Native Activity -page.customHeadTag= -@jd:body - - -
    - -
    -
    Native Activity
    -
    -
    - - - - - - - - - - - - -

    -Files

    file  native_activity.h
     
    file  native_window.h
     
    file  native_window_jni.h
     
    file  rect.h
     
    file  window.h
     
    - - - - - - - - - -

    -Data Structures

    struct  ANativeActivity
     
    struct  ANativeActivityCallbacks
     
    struct  ANativeWindow_Buffer
     
    struct  ARect
     
    - - - - - - - - - - - - - -

    -Typedefs

    typedef struct ANativeActivity ANativeActivity
     
    typedef struct
    -ANativeActivityCallbacks 
    ANativeActivityCallbacks
     
    typedef void ANativeActivity_createFunc (ANativeActivity *activity, void *savedState, size_t savedStateSize)
     
    typedef struct ANativeWindow ANativeWindow
     
    typedef struct ANativeWindow_Buffer ANativeWindow_Buffer
     
    typedef struct ARect ARect
     
    - - - - - - - - - -

    -Enumerations

    enum  { ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT = 0x0001, -ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED = 0x0002 - }
     
    enum  { ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY = 0x0001, -ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS = 0x0002 - }
     
    enum  { WINDOW_FORMAT_RGBA_8888 = 1, -WINDOW_FORMAT_RGBX_8888 = 2, -WINDOW_FORMAT_RGB_565 = 4 - }
     
    enum  {
    -  AWINDOW_FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, -AWINDOW_FLAG_DIM_BEHIND = 0x00000002, -AWINDOW_FLAG_BLUR_BEHIND = 0x00000004, -AWINDOW_FLAG_NOT_FOCUSABLE = 0x00000008, -
    -  AWINDOW_FLAG_NOT_TOUCHABLE = 0x00000010, -AWINDOW_FLAG_NOT_TOUCH_MODAL = 0x00000020, -AWINDOW_FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040, -AWINDOW_FLAG_KEEP_SCREEN_ON = 0x00000080, -
    -  AWINDOW_FLAG_LAYOUT_IN_SCREEN = 0x00000100, -AWINDOW_FLAG_LAYOUT_NO_LIMITS = 0x00000200, -AWINDOW_FLAG_FULLSCREEN = 0x00000400, -AWINDOW_FLAG_FORCE_NOT_FULLSCREEN = 0x00000800, -
    -  AWINDOW_FLAG_DITHER = 0x00001000, -AWINDOW_FLAG_SECURE = 0x00002000, -AWINDOW_FLAG_SCALED = 0x00004000, -AWINDOW_FLAG_IGNORE_CHEEK_PRESSES = 0x00008000, -
    -  AWINDOW_FLAG_LAYOUT_INSET_DECOR = 0x00010000, -AWINDOW_FLAG_ALT_FOCUSABLE_IM = 0x00020000, -AWINDOW_FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000, -AWINDOW_FLAG_SHOW_WHEN_LOCKED = 0x00080000, -
    -  AWINDOW_FLAG_SHOW_WALLPAPER = 0x00100000, -AWINDOW_FLAG_TURN_SCREEN_ON = 0x00200000, -AWINDOW_FLAG_DISMISS_KEYGUARD = 0x00400000 -
    - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    void ANativeActivity_finish (ANativeActivity *activity)
     
    void ANativeActivity_setWindowFormat (ANativeActivity *activity, int32_t format)
     
    void ANativeActivity_setWindowFlags (ANativeActivity *activity, uint32_t addFlags, uint32_t removeFlags)
     
    void ANativeActivity_showSoftInput (ANativeActivity *activity, uint32_t flags)
     
    void ANativeActivity_hideSoftInput (ANativeActivity *activity, uint32_t flags)
     
    void ANativeWindow_acquire (ANativeWindow *window)
     
    void ANativeWindow_release (ANativeWindow *window)
     
    int32_t ANativeWindow_getWidth (ANativeWindow *window)
     
    int32_t ANativeWindow_getHeight (ANativeWindow *window)
     
    int32_t ANativeWindow_getFormat (ANativeWindow *window)
     
    int32_t ANativeWindow_setBuffersGeometry (ANativeWindow *window, int32_t width, int32_t height, int32_t format)
     
    int32_t ANativeWindow_lock (ANativeWindow *window, ANativeWindow_Buffer *outBuffer, ARect *inOutDirtyBounds)
     
    int32_t ANativeWindow_unlockAndPost (ANativeWindow *window)
     
    ANativeWindowANativeWindow_fromSurface (JNIEnv *env, jobject surface)
     
    - - - -

    -Variables

    ANativeActivity_createFunc ANativeActivity_onCreate
     
    -

    Detailed Description

    -

    Typedef Documentation

    - -
    -
    - - - - -
    typedef struct ANativeActivity ANativeActivity
    -
    -

    This structure defines the native side of an android.app.NativeActivity. It is created by the framework, and handed to the application's native code as it is being launched.

    - -
    -
    - -
    -
    - - - - -
    typedef void ANativeActivity_createFunc(ANativeActivity *activity, void *savedState, size_t savedStateSize)
    -
    -

    This is the function that must be in the native code to instantiate the application's native activity. It is called with the activity instance (see above); if the code is being instantiated from a previously saved instance, the savedState will be non-NULL and point to the saved data. You must make any copy of this data you need – it will be released after you return from this function.

    - -
    -
    - -
    -
    -

    These are the callbacks the framework makes into a native application. All of these callbacks happen on the main thread of the application. By default, all callbacks are NULL; set to a pointer to your own function to have it called.

    - -
    -
    - -
    -
    - - - - -
    typedef struct ANativeWindow ANativeWindow
    -
    -

    ANativeWindow is opaque type that provides access to a native window.

    -

    A pointer can be obtained using ANativeWindow_fromSurface().

    - -
    -
    - -
    -
    - - - - -
    typedef struct ANativeWindow_Buffer ANativeWindow_Buffer
    -
    -

    ANativeWindow is a struct that represents a windows buffer.

    -

    A pointer can be obtained using ANativeWindow_lock().

    - -
    -
    - -
    -
    - - - - -
    typedef struct ARect ARect
    -
    -

    ARect is a struct that represents a rectangular window area.

    -

    It is used with ANativeActivityCallbacks::onContentRectChanged event callback and ANativeWindow_lock() function.

    - -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Flags for ANativeActivity_showSoftInput; see the Java InputMethodManager API for documentation.

    - - - -
    Enumerator
    ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT  -

    Implicit request to show the input window, not as the result of a direct request by the user.

    -
    ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED  -

    The user has forced the input method open (such as by long-pressing menu) so it should not be closed until they explicitly do so.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Flags for ANativeActivity_hideSoftInput; see the Java InputMethodManager API for documentation.

    - - - -
    Enumerator
    ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY  -

    The soft input window should only be hidden if it was not explicitly shown by the user.

    -
    ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS  -

    The soft input window should normally be hidden, unless it was originally shown with ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Pixel formats that a window can use.

    - - - - -
    Enumerator
    WINDOW_FORMAT_RGBA_8888  -

    Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits.

    -
    WINDOW_FORMAT_RGBX_8888  -

    Red: 8 bits, Green: 8 bits, Blue: 8 bits, Unused: 8 bits.

    -
    WINDOW_FORMAT_RGB_565  -

    Red: 5 bits, Green: 6 bits, Blue: 5 bits.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Window flags, as per the Java API at android.view.WindowManager.LayoutParams.

    - - - - - - - - - - - - - - - - - - - - - - - - -
    Enumerator
    AWINDOW_FLAG_ALLOW_LOCK_WHILE_SCREEN_ON  -

    As long as this window is visible to the user, allow the lock screen to activate while the screen is on. This can be used independently, or in combination with AWINDOW_FLAG_KEEP_SCREEN_ON and/or AWINDOW_FLAG_SHOW_WHEN_LOCKED

    -
    AWINDOW_FLAG_DIM_BEHIND  -

    Everything behind this window will be dimmed.

    -
    AWINDOW_FLAG_BLUR_BEHIND  -

    Blur everything behind this window.

    -
    Deprecated:
    Blurring is no longer supported.
    -
    AWINDOW_FLAG_NOT_FOCUSABLE  -

    This window won't ever get key input focus, so the user can not send key or other button events to it. Those will instead go to whatever focusable window is behind it. This flag will also enable AWINDOW_FLAG_NOT_TOUCH_MODAL whether or not that is explicitly set.

    -

    Setting this flag also implies that the window will not need to interact with a soft input method, so it will be Z-ordered and positioned independently of any active input method (typically this means it gets Z-ordered on top of the input method, so it can use the full screen for its content and cover the input method if needed. You can use AWINDOW_FLAG_ALT_FOCUSABLE_IM to modify this behavior.

    -
    AWINDOW_FLAG_NOT_TOUCHABLE  -

    this window can never receive touch events.

    -
    AWINDOW_FLAG_NOT_TOUCH_MODAL  -

    Even when this window is focusable (its AWINDOW_FLAG_NOT_FOCUSABLE is not set), allow any pointer events outside of the window to be sent to the windows behind it. Otherwise it will consume all pointer events itself, regardless of whether they are inside of the window.

    -
    AWINDOW_FLAG_TOUCHABLE_WHEN_WAKING  -

    When set, if the device is asleep when the touch screen is pressed, you will receive this first touch event. Usually the first touch event is consumed by the system since the user can not see what they are pressing on.

    -
    Deprecated:
    This flag has no effect.
    -
    AWINDOW_FLAG_KEEP_SCREEN_ON  -

    As long as this window is visible to the user, keep the device's screen turned on and bright.

    -
    AWINDOW_FLAG_LAYOUT_IN_SCREEN  -

    Place the window within the entire screen, ignoring decorations around the border (such as the status bar). The window must correctly position its contents to take the screen decoration into account.

    -
    AWINDOW_FLAG_LAYOUT_NO_LIMITS  -

    allow window to extend outside of the screen.

    -
    AWINDOW_FLAG_FULLSCREEN  -

    Hide all screen decorations (such as the status bar) while this window is displayed. This allows the window to use the entire display space for itself – the status bar will be hidden when an app window with this flag set is on the top layer. A fullscreen window will ignore a value of AWINDOW_SOFT_INPUT_ADJUST_RESIZE; the window will stay fullscreen and will not resize.

    -
    AWINDOW_FLAG_FORCE_NOT_FULLSCREEN  -

    Override AWINDOW_FLAG_FULLSCREEN and force the screen decorations (such as the status bar) to be shown.

    -
    AWINDOW_FLAG_DITHER  -

    Turn on dithering when compositing this window to the screen.

    -
    Deprecated:
    This flag is no longer used.
    -
    AWINDOW_FLAG_SECURE  -

    Treat the content of the window as secure, preventing it from appearing in screenshots or from being viewed on non-secure displays.

    -
    AWINDOW_FLAG_SCALED  -

    A special mode where the layout parameters are used to perform scaling of the surface when it is composited to the screen.

    -
    AWINDOW_FLAG_IGNORE_CHEEK_PRESSES  -

    Intended for windows that will often be used when the user is holding the screen against their face, it will aggressively filter the event stream to prevent unintended presses in this situation that may not be desired for a particular window, when such an event stream is detected, the application will receive a AMOTION_EVENT_ACTION_CANCEL to indicate this so applications can handle this accordingly by taking no action on the event until the finger is released.

    -
    AWINDOW_FLAG_LAYOUT_INSET_DECOR  -

    A special option only for use in combination with AWINDOW_FLAG_LAYOUT_IN_SCREEN. When requesting layout in the screen your window may appear on top of or behind screen decorations such as the status bar. By also including this flag, the window manager will report the inset rectangle needed to ensure your content is not covered by screen decorations.

    -
    AWINDOW_FLAG_ALT_FOCUSABLE_IM  -

    Invert the state of AWINDOW_FLAG_NOT_FOCUSABLE with respect to how this window interacts with the current method. That is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the window will behave as if it needs to interact with the input method and thus be placed behind/away from it; if AWINDOW_FLAG_NOT_FOCUSABLE is not set and this flag is set, then the window will behave as if it doesn't need to interact with the input method and can be placed to use more space and cover the input method.

    -
    AWINDOW_FLAG_WATCH_OUTSIDE_TOUCH  -

    If you have set AWINDOW_FLAG_NOT_TOUCH_MODAL, you can set this flag to receive a single special MotionEvent with the action AMOTION_EVENT_ACTION_OUTSIDE for touches that occur outside of your window. Note that you will not receive the full down/move/up gesture, only the location of the first down as an AMOTION_EVENT_ACTION_OUTSIDE.

    -
    AWINDOW_FLAG_SHOW_WHEN_LOCKED  -

    Special flag to let windows be shown when the screen is locked. This will let application windows take precedence over key guard or any other lock screens. Can be used with AWINDOW_FLAG_KEEP_SCREEN_ON to turn screen on and display windows directly before showing the key guard window. Can be used with AWINDOW_FLAG_DISMISS_KEYGUARD to automatically fully dismisss non-secure keyguards. This flag only applies to the top-most full-screen window.

    -
    AWINDOW_FLAG_SHOW_WALLPAPER  -

    Ask that the system wallpaper be shown behind your window. The window surface must be translucent to be able to actually see the wallpaper behind it; this flag just ensures that the wallpaper surface will be there if this window actually has translucent regions.

    -
    AWINDOW_FLAG_TURN_SCREEN_ON  -

    When set as a window is being added or made visible, once the window has been shown then the system will poke the power manager's user activity (as if the user had woken up the device) to turn the screen on.

    -
    AWINDOW_FLAG_DISMISS_KEYGUARD  -

    When set the window will cause the keyguard to be dismissed, only if it is not a secure lock keyguard. Because such a keyguard is not needed for security, it will never re-appear if the user navigates to another window (in contrast to AWINDOW_FLAG_SHOW_WHEN_LOCKED, which will only temporarily hide both secure and non-secure keyguards but ensure they reappear when the user moves to another UI that doesn't hide them). If the keyguard is currently active and is secure (requires an unlock pattern) than the user will still need to confirm it before seeing this window, unless AWINDOW_FLAG_SHOW_WHEN_LOCKED has also been set.

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - -
    void ANativeActivity_finish (ANativeActivityactivity)
    -
    -

    Finish the given activity. Its finish() method will be called, causing it to be stopped and destroyed. Note that this method can be called from any thread; it will send a message to the main thread of the process where the Java finish call will take place.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void ANativeActivity_hideSoftInput (ANativeActivityactivity,
    uint32_t flags 
    )
    -
    -

    Hide the IME while in the given activity. Calls InputMethodManager.hideSoftInput() for the given activity. Note that this method can be called from any thread; it will send a message to the main thread of the process where the Java finish call will take place.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    void ANativeActivity_setWindowFlags (ANativeActivityactivity,
    uint32_t addFlags,
    uint32_t removeFlags 
    )
    -
    -

    Change the window flags of the given activity. Calls getWindow().setFlags() of the given activity. Note that this method can be called from any thread; it will send a message to the main thread of the process where the Java finish call will take place. See window.h for flag constants.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void ANativeActivity_setWindowFormat (ANativeActivityactivity,
    int32_t format 
    )
    -
    -

    Change the window format of the given activity. Calls getWindow().setFormat() of the given activity. Note that this method can be called from any thread; it will send a message to the main thread of the process where the Java finish call will take place.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    void ANativeActivity_showSoftInput (ANativeActivityactivity,
    uint32_t flags 
    )
    -
    -

    Show the IME while in the given activity. Calls InputMethodManager.showSoftInput() for the given activity. Note that this method can be called from any thread; it will send a message to the main thread of the process where the Java finish call will take place.

    - -
    -
    - -
    -
    - - - - - - - - -
    void ANativeWindow_acquire (ANativeWindowwindow)
    -
    -

    Acquire a reference on the given ANativeWindow object. This prevents the object from being deleted until the reference is removed.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    ANativeWindow* ANativeWindow_fromSurface (JNIEnv * env,
    jobject surface 
    )
    -
    -

    Return the ANativeWindow associated with a Java Surface object, for interacting with it through native code. This acquires a reference on the ANativeWindow that is returned; be sure to use ANativeWindow_release() when done with it so that it doesn't leak.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t ANativeWindow_getFormat (ANativeWindowwindow)
    -
    -

    Return the current pixel format of the window surface. Returns a negative value on error.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t ANativeWindow_getHeight (ANativeWindowwindow)
    -
    -

    Return the current height in pixels of the window surface. Returns a negative value on error.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t ANativeWindow_getWidth (ANativeWindowwindow)
    -
    -

    Return the current width in pixels of the window surface. Returns a negative value on error.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int32_t ANativeWindow_lock (ANativeWindowwindow,
    ANativeWindow_BufferoutBuffer,
    ARectinOutDirtyBounds 
    )
    -
    -

    Lock the window's next drawing surface for writing. inOutDirtyBounds is used as an in/out parameter, upon entering the function, it contains the dirty region, that is, the region the caller intends to redraw. When the function returns, inOutDirtyBounds is updated with the actual area the caller needs to redraw – this region is often extended by ANativeWindow_lock.

    - -
    -
    - -
    -
    - - - - - - - - -
    void ANativeWindow_release (ANativeWindowwindow)
    -
    -

    Remove a reference that was previously acquired with ANativeWindow_acquire().

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    int32_t ANativeWindow_setBuffersGeometry (ANativeWindowwindow,
    int32_t width,
    int32_t height,
    int32_t format 
    )
    -
    -

    Change the format and size of the window buffers.

    -

    The width and height control the number of pixels in the buffers, not the dimensions of the window on screen. If these are different than the window's physical size, then it buffer will be scaled to match that size when compositing it to the screen.

    -

    For all of these parameters, if 0 is supplied then the window's base value will come back in force.

    -

    width and height must be either both zero or both non-zero.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t ANativeWindow_unlockAndPost (ANativeWindowwindow)
    -
    -

    Unlock the window's drawing surface after previously locking it, posting the new buffer to the display.

    - -
    -
    -

    Variable Documentation

    - -
    -
    - - - - -
    ANativeActivity_createFunc ANativeActivity_onCreate
    -
    -

    The name of the function that NativeInstance looks for when launching its native code. This is the default function that is used, you can specify "android.app.func_name" string meta-data in your manifest to use a different function.

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/group___sensor.jd b/docs/html/ndk/reference/group___sensor.jd deleted file mode 100644 index 41a0aec4a252c248ef1bec3aa2005bfbd7d178fb..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___sensor.jd +++ /dev/null @@ -1,925 +0,0 @@ -page.title=Sensor -page.customHeadTag= -@jd:body - - - -
    - - - - -

    -Files

    file  sensor.h
     
    - - - - - - - - - - - -

    -Data Structures

    struct  ASensorVector
     
    struct  AMetaDataEvent
     
    struct  AUncalibratedEvent
     
    struct  AHeartRateEvent
     
    struct  ASensorEvent
     
    - - - - - - - -

    -Macros

    #define ASENSOR_STANDARD_GRAVITY   (9.80665f)
     
    #define ASENSOR_MAGNETIC_FIELD_EARTH_MAX   (60.0f)
     
    #define ASENSOR_MAGNETIC_FIELD_EARTH_MIN   (30.0f)
     
    - - - - - - - - - - - - - - - - - - - - - -

    -Typedefs

    typedef struct ASensorVector ASensorVector
     
    typedef struct AMetaDataEvent AMetaDataEvent
     
    typedef struct AUncalibratedEvent AUncalibratedEvent
     
    typedef struct AHeartRateEvent AHeartRateEvent
     
    typedef struct ASensorEvent ASensorEvent
     
    typedef struct ASensorManager ASensorManager
     
    typedef struct ASensorEventQueue ASensorEventQueue
     
    typedef struct ASensor ASensor
     
    typedef ASensor const * ASensorRef
     
    typedef ASensorRef const * ASensorList
     
    - - - - - - - -

    -Enumerations

    enum  {
    -  ASENSOR_TYPE_ACCELEROMETER = 1, -ASENSOR_TYPE_MAGNETIC_FIELD = 2, -ASENSOR_TYPE_GYROSCOPE = 4, -ASENSOR_TYPE_LIGHT = 5, -
    -  ASENSOR_TYPE_PROXIMITY = 8 -
    - }
     
    enum  {
    -  ASENSOR_STATUS_NO_CONTACT = -1, -ASENSOR_STATUS_UNRELIABLE = 0, -ASENSOR_STATUS_ACCURACY_LOW = 1, -ASENSOR_STATUS_ACCURACY_MEDIUM = 2, -
    -  ASENSOR_STATUS_ACCURACY_HIGH = 3 -
    - }
     
    enum  { AREPORTING_MODE_CONTINUOUS = 0, -AREPORTING_MODE_ON_CHANGE = 1, -AREPORTING_MODE_ONE_SHOT = 2, -AREPORTING_MODE_SPECIAL_TRIGGER = 3 - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    ASensorManagerASensorManager_getInstance ()
     
    int ASensorManager_getSensorList (ASensorManager *manager, ASensorList *list)
     
    ASensor const * ASensorManager_getDefaultSensor (ASensorManager *manager, int type)
     
    ASensor const * ASensorManager_getDefaultSensorEx (ASensorManager *manager, int type, bool wakeUp)
     
    ASensorEventQueueASensorManager_createEventQueue (ASensorManager *manager, ALooper *looper, int ident, ALooper_callbackFunc callback, void *data)
     
    int ASensorManager_destroyEventQueue (ASensorManager *manager, ASensorEventQueue *queue)
     
    int ASensorEventQueue_enableSensor (ASensorEventQueue *queue, ASensor const *sensor)
     
    int ASensorEventQueue_disableSensor (ASensorEventQueue *queue, ASensor const *sensor)
     
    int ASensorEventQueue_setEventRate (ASensorEventQueue *queue, ASensor const *sensor, int32_t usec)
     
    int ASensorEventQueue_hasEvents (ASensorEventQueue *queue)
     
    ssize_t ASensorEventQueue_getEvents (ASensorEventQueue *queue, ASensorEvent *events, size_t count)
     
    const char * ASensor_getName (ASensor const *sensor)
     
    const char * ASensor_getVendor (ASensor const *sensor)
     
    int ASensor_getType (ASensor const *sensor)
     
    float ASensor_getResolution (ASensor const *sensor)
     
    int ASensor_getMinDelay (ASensor const *sensor)
     
    int ASensor_getFifoMaxEventCount (ASensor const *sensor)
     
    int ASensor_getFifoReservedEventCount (ASensor const *sensor)
     
    const char * ASensor_getStringType (ASensor const *sensor)
     
    int ASensor_getReportingMode (ASensor const *sensor)
     
    bool ASensor_isWakeUpSensor (ASensor const *sensor)
     
    -

    Detailed Description

    -

    Macro Definition Documentation

    - -
    -
    - - - - -
    #define ASENSOR_MAGNETIC_FIELD_EARTH_MAX   (60.0f)
    -
    -

    Maximum magnetic field on Earth's surface in uT

    - -
    -
    - -
    -
    - - - - -
    #define ASENSOR_MAGNETIC_FIELD_EARTH_MIN   (30.0f)
    -
    -

    Minimum magnetic field on Earth's surface in uT

    - -
    -
    - -
    -
    - - - - -
    #define ASENSOR_STANDARD_GRAVITY   (9.80665f)
    -
    -

    Earth's gravity in m/s^2

    - -
    -
    -

    Typedef Documentation

    - -
    -
    - - - - -
    typedef struct AHeartRateEvent AHeartRateEvent
    -
    - -
    -
    - -
    -
    - - - - -
    typedef struct AMetaDataEvent AMetaDataEvent
    -
    - -
    -
    - -
    -
    - - - - -
    typedef struct ASensor ASensor
    -
    -
    - -
    -
    - - - - -
    typedef struct ASensorEvent ASensorEvent
    -
    - -
    -
    - -
    -
    - - - - -
    typedef struct ASensorEventQueue ASensorEventQueue
    -
    -

    ASensorEventQueue is an opaque type that provides access to ASensorEvent from hardware sensors.

    -

    A new ASensorEventQueue can be obtained using ASensorManager_createEventQueue().

    -

    This file provides a set of functions to enable and disable sensors, check and get events, and set event rates on a ASensorEventQueue.

    - - -
    -
    - -
    -
    - - - - -
    typedef ASensorRef const* ASensorList
    -
    -

    ASensorList is an array of reference to ASensor.

    -

    A ASensorList can be initialized using ASensorManager_getSensorList().

    - -
    -
    - -
    -
    - - - - -
    typedef struct ASensorManager ASensorManager
    -
    -

    ASensorManager is an opaque type to manage sensors and events queues.

    -

    ASensorManager is a singleton that can be obtained using ASensorManager_getInstance().

    -

    This file provides a set of functions that uses ASensorManager to access and list hardware sensors, and create and destroy event queues:

    - - -
    -
    - -
    -
    - - - - -
    typedef ASensor const* ASensorRef
    -
    -

    ASensorRef is a type for constant pointers to ASensor.

    -

    This is used to define entry in ASensorList arrays.

    - -
    -
    - -
    -
    - - - - -
    typedef struct ASensorVector ASensorVector
    -
    -

    A sensor event.

    - -
    -
    - -
    -
    - - - - -
    typedef struct AUncalibratedEvent AUncalibratedEvent
    -
    - -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Structures and functions to receive and process sensor events in native code. Sensor types. (keep in sync with hardware/sensor.h)

    - - - - - - -
    Enumerator
    ASENSOR_TYPE_ACCELEROMETER  -

    ASENSOR_TYPE_ACCELEROMETER reporting-mode: continuous

    -

    All values are in SI units (m/s^2) and measure the acceleration of the device minus the force of gravity.

    -
    ASENSOR_TYPE_MAGNETIC_FIELD  -

    ASENSOR_TYPE_MAGNETIC_FIELD reporting-mode: continuous

    -

    All values are in micro-Tesla (uT) and measure the geomagnetic field in the X, Y and Z axis.

    -
    ASENSOR_TYPE_GYROSCOPE  -

    ASENSOR_TYPE_GYROSCOPE reporting-mode: continuous

    -

    All values are in radians/second and measure the rate of rotation around the X, Y and Z axis.

    -
    ASENSOR_TYPE_LIGHT  -

    ASENSOR_TYPE_LIGHT reporting-mode: on-change

    -

    The light sensor value is returned in SI lux units.

    -
    ASENSOR_TYPE_PROXIMITY  -

    ASENSOR_TYPE_PROXIMITY reporting-mode: on-change

    -

    The proximity sensor which turns the screen off and back on during calls is the wake-up proximity sensor. Implement wake-up proximity sensor before implementing a non wake-up proximity sensor. For the wake-up proximity sensor set the flag SENSOR_FLAG_WAKE_UP. The value corresponds to the distance to the nearest object in centimeters.

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Sensor accuracy measure.

    - - - - - - -
    Enumerator
    ASENSOR_STATUS_NO_CONTACT  -

    no contact

    -
    ASENSOR_STATUS_UNRELIABLE  -

    unreliable

    -
    ASENSOR_STATUS_ACCURACY_LOW  -

    low accuracy

    -
    ASENSOR_STATUS_ACCURACY_MEDIUM  -

    medium accuracy

    -
    ASENSOR_STATUS_ACCURACY_HIGH  -

    high accuracy

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Sensor Reporting Modes.

    - - - - - -
    Enumerator
    AREPORTING_MODE_CONTINUOUS  -

    continuous reporting

    -
    AREPORTING_MODE_ON_CHANGE  -

    reporting on change

    -
    AREPORTING_MODE_ONE_SHOT  -

    on shot reporting

    -
    AREPORTING_MODE_SPECIAL_TRIGGER  -

    special trigger reporting

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - -
    int ASensor_getFifoMaxEventCount (ASensor const * sensor)
    -
    -

    Returns the maximum size of batches for this sensor. Batches will often be smaller, as the hardware fifo might be used for other sensors.

    - -
    -
    - -
    -
    - - - - - - - - -
    int ASensor_getFifoReservedEventCount (ASensor const * sensor)
    -
    -

    Returns the hardware batch fifo size reserved to this sensor.

    - -
    -
    - -
    -
    - - - - - - - - -
    int ASensor_getMinDelay (ASensor const * sensor)
    -
    -

    Returns the minimum delay allowed between events in microseconds. A value of zero means that this sensor doesn't report events at a constant rate, but rather only when a new data is available.

    - -
    -
    - -
    -
    - - - - - - - - -
    const char* ASensor_getName (ASensor const * sensor)
    -
    -

    Returns this sensor's name (non localized)

    - -
    -
    - -
    -
    - - - - - - - - -
    int ASensor_getReportingMode (ASensor const * sensor)
    -
    -

    Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.

    - -
    -
    - -
    -
    - - - - - - - - -
    float ASensor_getResolution (ASensor const * sensor)
    -
    -

    Returns this sensors's resolution

    - -
    -
    - -
    -
    - - - - - - - - -
    const char* ASensor_getStringType (ASensor const * sensor)
    -
    -

    Returns this sensor's string type.

    - -
    -
    - -
    -
    - - - - - - - - -
    int ASensor_getType (ASensor const * sensor)
    -
    -

    Return this sensor's type

    - -
    -
    - -
    -
    - - - - - - - - -
    const char* ASensor_getVendor (ASensor const * sensor)
    -
    -

    Returns this sensor's vendor's name (non localized)

    - -
    -
    - -
    -
    - - - - - - - - -
    bool ASensor_isWakeUpSensor (ASensor const * sensor)
    -
    -

    Returns true if this is a wake up sensor, false otherwise.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int ASensorEventQueue_disableSensor (ASensorEventQueuequeue,
    ASensor const * sensor 
    )
    -
    -

    Disable the selected sensor. Returns a negative error code on failure.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int ASensorEventQueue_enableSensor (ASensorEventQueuequeue,
    ASensor const * sensor 
    )
    -
    -

    Enable the selected sensor. Returns a negative error code on failure.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    ssize_t ASensorEventQueue_getEvents (ASensorEventQueuequeue,
    ASensorEventevents,
    size_t count 
    )
    -
    -

    Returns the next available events from the queue. Returns a negative value if no events are available or an error has occurred, otherwise the number of events returned.

    -

    Examples: ASensorEvent event; ssize_t numEvent = ASensorEventQueue_getEvents(queue, &event, 1);

    -

    ASensorEvent eventBuffer[8]; ssize_t numEvent = ASensorEventQueue_getEvents(queue, eventBuffer, 8);

    - -
    -
    - -
    -
    - - - - - - - - -
    int ASensorEventQueue_hasEvents (ASensorEventQueuequeue)
    -
    -

    Returns true if there are one or more events available in the sensor queue. Returns 1 if the queue has events; 0 if it does not have events; and a negative value if there is an error.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    int ASensorEventQueue_setEventRate (ASensorEventQueuequeue,
    ASensor const * sensor,
    int32_t usec 
    )
    -
    -

    Sets the delivery rate of events in microseconds for the given sensor. Note that this is a hint only, generally event will arrive at a higher rate. It is an error to set a rate inferior to the value returned by ASensor_getMinDelay(). Returns a negative error code on failure.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ASensorEventQueue* ASensorManager_createEventQueue (ASensorManagermanager,
    ALooperlooper,
    int ident,
    ALooper_callbackFunc callback,
    void * data 
    )
    -
    -

    Creates a new sensor event queue and associate it with a looper.

    -

    "ident" is a identifier for the events that will be returned when calling ALooper_pollOnce(). The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int ASensorManager_destroyEventQueue (ASensorManagermanager,
    ASensorEventQueuequeue 
    )
    -
    -

    Destroys the event queue and free all resources associated to it.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    ASensor const* ASensorManager_getDefaultSensor (ASensorManagermanager,
    int type 
    )
    -
    -

    Returns the default sensor for the given type, or NULL if no sensor of that type exists.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    ASensor const* ASensorManager_getDefaultSensorEx (ASensorManagermanager,
    int type,
    bool wakeUp 
    )
    -
    -

    Returns the default sensor with the given type and wakeUp properties or NULL if no sensor of this type and wakeUp properties exists.

    - -
    -
    - -
    -
    - - - - - - - -
    ASensorManager* ASensorManager_getInstance ()
    -
    -

    Get a reference to the sensor manager. ASensorManager is a singleton.

    -

    Example:

    -
    ASensorManager* sensorManager = ASensorManager_getInstance();
    -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int ASensorManager_getSensorList (ASensorManagermanager,
    ASensorListlist 
    )
    -
    -

    Returns the list of available sensors.

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/group___storage.jd b/docs/html/ndk/reference/group___storage.jd deleted file mode 100644 index e29303a1c49a88034a2584dd407dcfebe343b75a..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/group___storage.jd +++ /dev/null @@ -1,450 +0,0 @@ -page.title=Storage -page.customHeadTag= -@jd:body - - -
    - -
    -
    Storage
    -
    -
    - - - - - - -

    -Files

    file  obb.h
     
    file  storage_manager.h
     
    - - - - - - - -

    -Typedefs

    typedef struct AObbInfo AObbInfo
     
    typedef struct AStorageManager AStorageManager
     
    typedef void(* AStorageManager_obbCallbackFunc )(const char *filename, const int32_t state, void *data)
     
    - - - - - -

    -Enumerations

    enum  { AOBBINFO_OVERLAY = 0x0001 - }
     
    enum  {
    -  AOBB_STATE_MOUNTED = 1, -AOBB_STATE_UNMOUNTED = 2, -AOBB_STATE_ERROR_INTERNAL = 20, -AOBB_STATE_ERROR_COULD_NOT_MOUNT = 21, -
    -  AOBB_STATE_ERROR_COULD_NOT_UNMOUNT = 22, -AOBB_STATE_ERROR_NOT_MOUNTED = 23, -AOBB_STATE_ERROR_ALREADY_MOUNTED = 24, -AOBB_STATE_ERROR_PERMISSION_DENIED = 25 -
    - }
     
    - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    AObbInfoAObbScanner_getObbInfo (const char *filename)
     
    void AObbInfo_delete (AObbInfo *obbInfo)
     
    const char * AObbInfo_getPackageName (AObbInfo *obbInfo)
     
    int32_t AObbInfo_getVersion (AObbInfo *obbInfo)
     
    int32_t AObbInfo_getFlags (AObbInfo *obbInfo)
     
    AStorageManagerAStorageManager_new ()
     
    void AStorageManager_delete (AStorageManager *mgr)
     
    void AStorageManager_mountObb (AStorageManager *mgr, const char *filename, const char *key, AStorageManager_obbCallbackFunc cb, void *data)
     
    void AStorageManager_unmountObb (AStorageManager *mgr, const char *filename, const int force, AStorageManager_obbCallbackFunc cb, void *data)
     
    int AStorageManager_isObbMounted (AStorageManager *mgr, const char *filename)
     
    const char * AStorageManager_getMountedObbPath (AStorageManager *mgr, const char *filename)
     
    -

    Detailed Description

    -

    Typedef Documentation

    - -
    -
    - - - - -
    typedef struct AObbInfo AObbInfo
    -
    -

    AObbInfo is an opaque type representing information for obb storage.

    - -
    -
    - -
    -
    - - - - -
    typedef struct AStorageManager AStorageManager
    -
    -

    AStorageManager manages application OBB storage, a pointer can be obtained with AStorageManager_new().

    - -
    -
    - -
    -
    - - - - -
    typedef void(* AStorageManager_obbCallbackFunc)(const char *filename, const int32_t state, void *data)
    -
    -
    -

    Enumeration Type Documentation

    - -
    -
    - - - - -
    anonymous enum
    -
    -

    Flag for an obb file, returned by AObbInfo_getFlags().

    - - -
    Enumerator
    AOBBINFO_OVERLAY  -

    overlay

    -
    - -
    -
    - -
    -
    - - - - -
    anonymous enum
    -
    -

    The different states of a OBB storage passed to AStorageManager_obbCallbackFunc().

    - - - - - - - - - -
    Enumerator
    AOBB_STATE_MOUNTED  -

    The OBB container is now mounted and ready for use. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    AOBB_STATE_UNMOUNTED  -

    The OBB container is now unmounted and not usable. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    AOBB_STATE_ERROR_INTERNAL  -

    There was an internal system error encountered while trying to mount the OBB. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    AOBB_STATE_ERROR_COULD_NOT_MOUNT  -

    The OBB could not be mounted by the system. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    AOBB_STATE_ERROR_COULD_NOT_UNMOUNT  -

    The OBB could not be unmounted. This most likely indicates that a file is in use on the OBB. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    AOBB_STATE_ERROR_NOT_MOUNTED  -

    A call was made to unmount the OBB when it was not mounted. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    AOBB_STATE_ERROR_ALREADY_MOUNTED  -

    The OBB has already been mounted. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    AOBB_STATE_ERROR_PERMISSION_DENIED  -

    The current application does not have permission to use this OBB. This could be because the OBB indicates it's owned by a different package. Can be returned as the status for callbacks made during asynchronous OBB actions.

    -
    - -
    -
    -

    Function Documentation

    - -
    -
    - - - - - - - - -
    void AObbInfo_delete (AObbInfoobbInfo)
    -
    -

    Destroy the AObbInfo object. You must call this when finished with the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AObbInfo_getFlags (AObbInfoobbInfo)
    -
    -

    Get the flags of an OBB file.

    - -
    -
    - -
    -
    - - - - - - - - -
    const char* AObbInfo_getPackageName (AObbInfoobbInfo)
    -
    -

    Get the package name for the OBB.

    - -
    -
    - -
    -
    - - - - - - - - -
    int32_t AObbInfo_getVersion (AObbInfoobbInfo)
    -
    -

    Get the version of an OBB file.

    - -
    -
    - -
    -
    - - - - - - - - -
    AObbInfo* AObbScanner_getObbInfo (const char * filename)
    -
    -

    Scan an OBB and get information about it.

    - -
    -
    - -
    -
    - - - - - - - - -
    void AStorageManager_delete (AStorageManagermgr)
    -
    -

    Release AStorageManager instance.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    const char* AStorageManager_getMountedObbPath (AStorageManagermgr,
    const char * filename 
    )
    -
    -

    Get the mounted path for an OBB.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    int AStorageManager_isObbMounted (AStorageManagermgr,
    const char * filename 
    )
    -
    -

    Check whether an OBB is mounted.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void AStorageManager_mountObb (AStorageManagermgr,
    const char * filename,
    const char * key,
    AStorageManager_obbCallbackFunc cb,
    void * data 
    )
    -
    -

    Attempts to mount an OBB file. This is an asynchronous operation.

    - -
    -
    - -
    -
    - - - - - - - -
    AStorageManager* AStorageManager_new ()
    -
    -

    Obtains a new instance of AStorageManager.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void AStorageManager_unmountObb (AStorageManagermgr,
    const char * filename,
    const int force,
    AStorageManager_obbCallbackFunc cb,
    void * data 
    )
    -
    -

    Attempts to unmount an OBB file. This is an asynchronous operation.

    - -
    -
    -
    diff --git a/docs/html/ndk/reference/index.jd b/docs/html/ndk/reference/index.jd deleted file mode 100644 index 94bcb7a388397ec5869e12e58906ccfb5f547876..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/index.jd +++ /dev/null @@ -1,17 +0,0 @@ -page.title=API Reference -@jd:body - -

    The API reference for the NDK includes documentation for the base set of -native headers that the NDK provides for Android. These headers, and their associated libraries, -expose a variety of features otherwise only accessible via the Android framework. -A few of these features are as follows:

    - -
      -
    • Using hardware sensors.
    • -
    • Accessing storage.
    • -
    • Handling user input.
    • -
    • Setting configuration information, such as screen orientation.
    • -
    - -

    The API reference provides detailed information on these and other functionalities provided -in the NDK.

    diff --git a/docs/html/ndk/reference/input_8h.jd b/docs/html/ndk/reference/input_8h.jd deleted file mode 100644 index 855a346a70280c1f34b089415851942a5447bd7e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/input_8h.jd +++ /dev/null @@ -1,374 +0,0 @@ -page.title=input.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    input.h File Reference
    -
    -
    -
    #include <stdint.h>
    -#include <sys/types.h>
    -#include <android/keycodes.h>
    -#include <android/looper.h>
    -
    - - - -

    -Macros

    #define AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT   8
     
    - - - - - -

    -Typedefs

    typedef struct AInputEvent AInputEvent
     
    typedef struct AInputQueue AInputQueue
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Enumerations

    enum  { AKEY_STATE_UNKNOWN = -1, -AKEY_STATE_UP = 0, -AKEY_STATE_DOWN = 1, -AKEY_STATE_VIRTUAL = 2 - }
     
    enum  {
    -  AMETA_NONE = 0, -AMETA_ALT_ON = 0x02, -AMETA_ALT_LEFT_ON = 0x10, -AMETA_ALT_RIGHT_ON = 0x20, -
    -  AMETA_SHIFT_ON = 0x01, -AMETA_SHIFT_LEFT_ON = 0x40, -AMETA_SHIFT_RIGHT_ON = 0x80, -AMETA_SYM_ON = 0x04, -
    -  AMETA_FUNCTION_ON = 0x08, -AMETA_CTRL_ON = 0x1000, -AMETA_CTRL_LEFT_ON = 0x2000, -AMETA_CTRL_RIGHT_ON = 0x4000, -
    -  AMETA_META_ON = 0x10000, -AMETA_META_LEFT_ON = 0x20000, -AMETA_META_RIGHT_ON = 0x40000, -AMETA_CAPS_LOCK_ON = 0x100000, -
    -  AMETA_NUM_LOCK_ON = 0x200000, -AMETA_SCROLL_LOCK_ON = 0x400000 -
    - }
     
    enum  { AINPUT_EVENT_TYPE_KEY = 1, -AINPUT_EVENT_TYPE_MOTION = 2 - }
     
    enum  { AKEY_EVENT_ACTION_DOWN = 0, -AKEY_EVENT_ACTION_UP = 1, -AKEY_EVENT_ACTION_MULTIPLE = 2 - }
     
    enum  {
    -  AKEY_EVENT_FLAG_WOKE_HERE = 0x1, -AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2, -AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4, -AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8, -
    -  AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10, -AKEY_EVENT_FLAG_CANCELED = 0x20, -AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40, -AKEY_EVENT_FLAG_LONG_PRESS = 0x80, -
    -  AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, -AKEY_EVENT_FLAG_TRACKING = 0x200, -AKEY_EVENT_FLAG_FALLBACK = 0x400 -
    - }
     
    enum  {
    -  AMOTION_EVENT_ACTION_MASK = 0xff, -AMOTION_EVENT_ACTION_POINTER_INDEX_MASK = 0xff00, -AMOTION_EVENT_ACTION_DOWN = 0, -AMOTION_EVENT_ACTION_UP = 1, -
    -  AMOTION_EVENT_ACTION_MOVE = 2, -AMOTION_EVENT_ACTION_CANCEL = 3, -AMOTION_EVENT_ACTION_OUTSIDE = 4, -AMOTION_EVENT_ACTION_POINTER_DOWN = 5, -
    -  AMOTION_EVENT_ACTION_POINTER_UP = 6, -AMOTION_EVENT_ACTION_HOVER_MOVE = 7, -AMOTION_EVENT_ACTION_SCROLL = 8, -AMOTION_EVENT_ACTION_HOVER_ENTER = 9, -
    -  AMOTION_EVENT_ACTION_HOVER_EXIT = 10 -
    - }
     
    enum  { AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1 - }
     
    enum  {
    -  AMOTION_EVENT_EDGE_FLAG_NONE = 0, -AMOTION_EVENT_EDGE_FLAG_TOP = 0x01, -AMOTION_EVENT_EDGE_FLAG_BOTTOM = 0x02, -AMOTION_EVENT_EDGE_FLAG_LEFT = 0x04, -
    -  AMOTION_EVENT_EDGE_FLAG_RIGHT = 0x08 -
    - }
     
    enum  {
    -  AMOTION_EVENT_AXIS_X = 0, -AMOTION_EVENT_AXIS_Y = 1, -AMOTION_EVENT_AXIS_PRESSURE = 2, -AMOTION_EVENT_AXIS_SIZE = 3, -
    -  AMOTION_EVENT_AXIS_TOUCH_MAJOR = 4, -AMOTION_EVENT_AXIS_TOUCH_MINOR = 5, -AMOTION_EVENT_AXIS_TOOL_MAJOR = 6, -AMOTION_EVENT_AXIS_TOOL_MINOR = 7, -
    -  AMOTION_EVENT_AXIS_ORIENTATION = 8, -AMOTION_EVENT_AXIS_VSCROLL = 9, -AMOTION_EVENT_AXIS_HSCROLL = 10, -AMOTION_EVENT_AXIS_Z = 11, -
    -  AMOTION_EVENT_AXIS_RX = 12, -AMOTION_EVENT_AXIS_RY = 13, -AMOTION_EVENT_AXIS_RZ = 14, -AMOTION_EVENT_AXIS_HAT_X = 15, -
    -  AMOTION_EVENT_AXIS_HAT_Y = 16, -AMOTION_EVENT_AXIS_LTRIGGER = 17, -AMOTION_EVENT_AXIS_RTRIGGER = 18, -AMOTION_EVENT_AXIS_THROTTLE = 19, -
    -  AMOTION_EVENT_AXIS_RUDDER = 20, -AMOTION_EVENT_AXIS_WHEEL = 21, -AMOTION_EVENT_AXIS_GAS = 22, -AMOTION_EVENT_AXIS_BRAKE = 23, -
    -  AMOTION_EVENT_AXIS_DISTANCE = 24, -AMOTION_EVENT_AXIS_TILT = 25, -AMOTION_EVENT_AXIS_GENERIC_1 = 32, -AMOTION_EVENT_AXIS_GENERIC_2 = 33, -
    -  AMOTION_EVENT_AXIS_GENERIC_3 = 34, -AMOTION_EVENT_AXIS_GENERIC_4 = 35, -AMOTION_EVENT_AXIS_GENERIC_5 = 36, -AMOTION_EVENT_AXIS_GENERIC_6 = 37, -
    -  AMOTION_EVENT_AXIS_GENERIC_7 = 38, -AMOTION_EVENT_AXIS_GENERIC_8 = 39, -AMOTION_EVENT_AXIS_GENERIC_9 = 40, -AMOTION_EVENT_AXIS_GENERIC_10 = 41, -
    -  AMOTION_EVENT_AXIS_GENERIC_11 = 42, -AMOTION_EVENT_AXIS_GENERIC_12 = 43, -AMOTION_EVENT_AXIS_GENERIC_13 = 44, -AMOTION_EVENT_AXIS_GENERIC_14 = 45, -
    -  AMOTION_EVENT_AXIS_GENERIC_15 = 46, -AMOTION_EVENT_AXIS_GENERIC_16 = 47 -
    - }
     
    enum  {
    -  AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0, -AMOTION_EVENT_BUTTON_SECONDARY = 1 << 1, -AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2, -AMOTION_EVENT_BUTTON_BACK = 1 << 3, -
    -  AMOTION_EVENT_BUTTON_FORWARD = 1 << 4 -
    - }
     
    enum  {
    -  AMOTION_EVENT_TOOL_TYPE_UNKNOWN = 0, -AMOTION_EVENT_TOOL_TYPE_FINGER = 1, -AMOTION_EVENT_TOOL_TYPE_STYLUS = 2, -AMOTION_EVENT_TOOL_TYPE_MOUSE = 3, -
    -  AMOTION_EVENT_TOOL_TYPE_ERASER = 4 -
    - }
     
    enum  {
    -  AINPUT_SOURCE_CLASS_MASK = 0x000000ff, -AINPUT_SOURCE_CLASS_NONE = 0x00000000, -AINPUT_SOURCE_CLASS_BUTTON = 0x00000001, -AINPUT_SOURCE_CLASS_POINTER = 0x00000002, -
    -  AINPUT_SOURCE_CLASS_NAVIGATION = 0x00000004, -AINPUT_SOURCE_CLASS_POSITION = 0x00000008, -AINPUT_SOURCE_CLASS_JOYSTICK = 0x00000010 -
    - }
     
    enum  {
    -  AINPUT_SOURCE_UNKNOWN = 0x00000000, -AINPUT_SOURCE_KEYBOARD = 0x00000100 | AINPUT_SOURCE_CLASS_BUTTON, -AINPUT_SOURCE_DPAD = 0x00000200 | AINPUT_SOURCE_CLASS_BUTTON, -AINPUT_SOURCE_GAMEPAD = 0x00000400 | AINPUT_SOURCE_CLASS_BUTTON, -
    -  AINPUT_SOURCE_TOUCHSCREEN = 0x00001000 | AINPUT_SOURCE_CLASS_POINTER, -AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER, -AINPUT_SOURCE_STYLUS = 0x00004000 | AINPUT_SOURCE_CLASS_POINTER, -AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION, -
    -  AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION, -AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE, -AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK, -AINPUT_SOURCE_ANY = 0xffffff00 -
    - }
     
    enum  { AINPUT_KEYBOARD_TYPE_NONE = 0, -AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC = 1, -AINPUT_KEYBOARD_TYPE_ALPHABETIC = 2 - }
     
    enum  {
    -  AINPUT_MOTION_RANGE_X = AMOTION_EVENT_AXIS_X, -AINPUT_MOTION_RANGE_Y = AMOTION_EVENT_AXIS_Y, -AINPUT_MOTION_RANGE_PRESSURE = AMOTION_EVENT_AXIS_PRESSURE, -AINPUT_MOTION_RANGE_SIZE = AMOTION_EVENT_AXIS_SIZE, -
    -  AINPUT_MOTION_RANGE_TOUCH_MAJOR = AMOTION_EVENT_AXIS_TOUCH_MAJOR, -AINPUT_MOTION_RANGE_TOUCH_MINOR = AMOTION_EVENT_AXIS_TOUCH_MINOR, -AINPUT_MOTION_RANGE_TOOL_MAJOR = AMOTION_EVENT_AXIS_TOOL_MAJOR, -AINPUT_MOTION_RANGE_TOOL_MINOR = AMOTION_EVENT_AXIS_TOOL_MINOR, -
    -  AINPUT_MOTION_RANGE_ORIENTATION = AMOTION_EVENT_AXIS_ORIENTATION -
    - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    int32_t AInputEvent_getType (const AInputEvent *event)
     
    int32_t AInputEvent_getDeviceId (const AInputEvent *event)
     
    int32_t AInputEvent_getSource (const AInputEvent *event)
     
    int32_t AKeyEvent_getAction (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getFlags (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getKeyCode (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getScanCode (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getMetaState (const AInputEvent *key_event)
     
    int32_t AKeyEvent_getRepeatCount (const AInputEvent *key_event)
     
    int64_t AKeyEvent_getDownTime (const AInputEvent *key_event)
     
    int64_t AKeyEvent_getEventTime (const AInputEvent *key_event)
     
    int32_t AMotionEvent_getAction (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getFlags (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getMetaState (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getButtonState (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getEdgeFlags (const AInputEvent *motion_event)
     
    int64_t AMotionEvent_getDownTime (const AInputEvent *motion_event)
     
    int64_t AMotionEvent_getEventTime (const AInputEvent *motion_event)
     
    float AMotionEvent_getXOffset (const AInputEvent *motion_event)
     
    float AMotionEvent_getYOffset (const AInputEvent *motion_event)
     
    float AMotionEvent_getXPrecision (const AInputEvent *motion_event)
     
    float AMotionEvent_getYPrecision (const AInputEvent *motion_event)
     
    size_t AMotionEvent_getPointerCount (const AInputEvent *motion_event)
     
    int32_t AMotionEvent_getPointerId (const AInputEvent *motion_event, size_t pointer_index)
     
    int32_t AMotionEvent_getToolType (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getRawX (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getRawY (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getX (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getY (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getPressure (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getSize (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getTouchMajor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getTouchMinor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getToolMajor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getToolMinor (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getOrientation (const AInputEvent *motion_event, size_t pointer_index)
     
    float AMotionEvent_getAxisValue (const AInputEvent *motion_event, int32_t axis, size_t pointer_index)
     
    size_t AMotionEvent_getHistorySize (const AInputEvent *motion_event)
     
    int64_t AMotionEvent_getHistoricalEventTime (const AInputEvent *motion_event, size_t history_index)
     
    float AMotionEvent_getHistoricalRawX (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalRawY (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalX (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalY (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalPressure (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalSize (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalTouchMajor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalTouchMinor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalToolMajor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalToolMinor (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalOrientation (const AInputEvent *motion_event, size_t pointer_index, size_t history_index)
     
    float AMotionEvent_getHistoricalAxisValue (const AInputEvent *motion_event, int32_t axis, size_t pointer_index, size_t history_index)
     
    void AInputQueue_attachLooper (AInputQueue *queue, ALooper *looper, int ident, ALooper_callbackFunc callback, void *data)
     
    void AInputQueue_detachLooper (AInputQueue *queue)
     
    int32_t AInputQueue_hasEvents (AInputQueue *queue)
     
    int32_t AInputQueue_getEvent (AInputQueue *queue, AInputEvent **outEvent)
     
    int32_t AInputQueue_preDispatchEvent (AInputQueue *queue, AInputEvent *event)
     
    void AInputQueue_finishEvent (AInputQueue *queue, AInputEvent *event, int handled)
     
    -
    diff --git a/docs/html/ndk/reference/keycodes_8h.jd b/docs/html/ndk/reference/keycodes_8h.jd deleted file mode 100644 index 338a361b43a224a70e579e212f10994d0994287a..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/keycodes_8h.jd +++ /dev/null @@ -1,350 +0,0 @@ -page.title=keycodes.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    keycodes.h File Reference
    -
    -
    -
    #include <sys/types.h>
    -
    - - - -

    -Enumerations

    enum  {
    -  AKEYCODE_UNKNOWN = 0, -AKEYCODE_SOFT_LEFT = 1, -AKEYCODE_SOFT_RIGHT = 2, -AKEYCODE_HOME = 3, -
    -  AKEYCODE_BACK = 4, -AKEYCODE_CALL = 5, -AKEYCODE_ENDCALL = 6, -AKEYCODE_0 = 7, -
    -  AKEYCODE_1 = 8, -AKEYCODE_2 = 9, -AKEYCODE_3 = 10, -AKEYCODE_4 = 11, -
    -  AKEYCODE_5 = 12, -AKEYCODE_6 = 13, -AKEYCODE_7 = 14, -AKEYCODE_8 = 15, -
    -  AKEYCODE_9 = 16, -AKEYCODE_STAR = 17, -AKEYCODE_POUND = 18, -AKEYCODE_DPAD_UP = 19, -
    -  AKEYCODE_DPAD_DOWN = 20, -AKEYCODE_DPAD_LEFT = 21, -AKEYCODE_DPAD_RIGHT = 22, -AKEYCODE_DPAD_CENTER = 23, -
    -  AKEYCODE_VOLUME_UP = 24, -AKEYCODE_VOLUME_DOWN = 25, -AKEYCODE_POWER = 26, -AKEYCODE_CAMERA = 27, -
    -  AKEYCODE_CLEAR = 28, -AKEYCODE_A = 29, -AKEYCODE_B = 30, -AKEYCODE_C = 31, -
    -  AKEYCODE_D = 32, -AKEYCODE_E = 33, -AKEYCODE_F = 34, -AKEYCODE_G = 35, -
    -  AKEYCODE_H = 36, -AKEYCODE_I = 37, -AKEYCODE_J = 38, -AKEYCODE_K = 39, -
    -  AKEYCODE_L = 40, -AKEYCODE_M = 41, -AKEYCODE_N = 42, -AKEYCODE_O = 43, -
    -  AKEYCODE_P = 44, -AKEYCODE_Q = 45, -AKEYCODE_R = 46, -AKEYCODE_S = 47, -
    -  AKEYCODE_T = 48, -AKEYCODE_U = 49, -AKEYCODE_V = 50, -AKEYCODE_W = 51, -
    -  AKEYCODE_X = 52, -AKEYCODE_Y = 53, -AKEYCODE_Z = 54, -AKEYCODE_COMMA = 55, -
    -  AKEYCODE_PERIOD = 56, -AKEYCODE_ALT_LEFT = 57, -AKEYCODE_ALT_RIGHT = 58, -AKEYCODE_SHIFT_LEFT = 59, -
    -  AKEYCODE_SHIFT_RIGHT = 60, -AKEYCODE_TAB = 61, -AKEYCODE_SPACE = 62, -AKEYCODE_SYM = 63, -
    -  AKEYCODE_EXPLORER = 64, -AKEYCODE_ENVELOPE = 65, -AKEYCODE_ENTER = 66, -AKEYCODE_DEL = 67, -
    -  AKEYCODE_GRAVE = 68, -AKEYCODE_MINUS = 69, -AKEYCODE_EQUALS = 70, -AKEYCODE_LEFT_BRACKET = 71, -
    -  AKEYCODE_RIGHT_BRACKET = 72, -AKEYCODE_BACKSLASH = 73, -AKEYCODE_SEMICOLON = 74, -AKEYCODE_APOSTROPHE = 75, -
    -  AKEYCODE_SLASH = 76, -AKEYCODE_AT = 77, -AKEYCODE_NUM = 78, -AKEYCODE_HEADSETHOOK = 79, -
    -  AKEYCODE_FOCUS = 80, -AKEYCODE_PLUS = 81, -AKEYCODE_MENU = 82, -AKEYCODE_NOTIFICATION = 83, -
    -  AKEYCODE_SEARCH = 84, -AKEYCODE_MEDIA_PLAY_PAUSE = 85, -AKEYCODE_MEDIA_STOP = 86, -AKEYCODE_MEDIA_NEXT = 87, -
    -  AKEYCODE_MEDIA_PREVIOUS = 88, -AKEYCODE_MEDIA_REWIND = 89, -AKEYCODE_MEDIA_FAST_FORWARD = 90, -AKEYCODE_MUTE = 91, -
    -  AKEYCODE_PAGE_UP = 92, -AKEYCODE_PAGE_DOWN = 93, -AKEYCODE_PICTSYMBOLS = 94, -AKEYCODE_SWITCH_CHARSET = 95, -
    -  AKEYCODE_BUTTON_A = 96, -AKEYCODE_BUTTON_B = 97, -AKEYCODE_BUTTON_C = 98, -AKEYCODE_BUTTON_X = 99, -
    -  AKEYCODE_BUTTON_Y = 100, -AKEYCODE_BUTTON_Z = 101, -AKEYCODE_BUTTON_L1 = 102, -AKEYCODE_BUTTON_R1 = 103, -
    -  AKEYCODE_BUTTON_L2 = 104, -AKEYCODE_BUTTON_R2 = 105, -AKEYCODE_BUTTON_THUMBL = 106, -AKEYCODE_BUTTON_THUMBR = 107, -
    -  AKEYCODE_BUTTON_START = 108, -AKEYCODE_BUTTON_SELECT = 109, -AKEYCODE_BUTTON_MODE = 110, -AKEYCODE_ESCAPE = 111, -
    -  AKEYCODE_FORWARD_DEL = 112, -AKEYCODE_CTRL_LEFT = 113, -AKEYCODE_CTRL_RIGHT = 114, -AKEYCODE_CAPS_LOCK = 115, -
    -  AKEYCODE_SCROLL_LOCK = 116, -AKEYCODE_META_LEFT = 117, -AKEYCODE_META_RIGHT = 118, -AKEYCODE_FUNCTION = 119, -
    -  AKEYCODE_SYSRQ = 120, -AKEYCODE_BREAK = 121, -AKEYCODE_MOVE_HOME = 122, -AKEYCODE_MOVE_END = 123, -
    -  AKEYCODE_INSERT = 124, -AKEYCODE_FORWARD = 125, -AKEYCODE_MEDIA_PLAY = 126, -AKEYCODE_MEDIA_PAUSE = 127, -
    -  AKEYCODE_MEDIA_CLOSE = 128, -AKEYCODE_MEDIA_EJECT = 129, -AKEYCODE_MEDIA_RECORD = 130, -AKEYCODE_F1 = 131, -
    -  AKEYCODE_F2 = 132, -AKEYCODE_F3 = 133, -AKEYCODE_F4 = 134, -AKEYCODE_F5 = 135, -
    -  AKEYCODE_F6 = 136, -AKEYCODE_F7 = 137, -AKEYCODE_F8 = 138, -AKEYCODE_F9 = 139, -
    -  AKEYCODE_F10 = 140, -AKEYCODE_F11 = 141, -AKEYCODE_F12 = 142, -AKEYCODE_NUM_LOCK = 143, -
    -  AKEYCODE_NUMPAD_0 = 144, -AKEYCODE_NUMPAD_1 = 145, -AKEYCODE_NUMPAD_2 = 146, -AKEYCODE_NUMPAD_3 = 147, -
    -  AKEYCODE_NUMPAD_4 = 148, -AKEYCODE_NUMPAD_5 = 149, -AKEYCODE_NUMPAD_6 = 150, -AKEYCODE_NUMPAD_7 = 151, -
    -  AKEYCODE_NUMPAD_8 = 152, -AKEYCODE_NUMPAD_9 = 153, -AKEYCODE_NUMPAD_DIVIDE = 154, -AKEYCODE_NUMPAD_MULTIPLY = 155, -
    -  AKEYCODE_NUMPAD_SUBTRACT = 156, -AKEYCODE_NUMPAD_ADD = 157, -AKEYCODE_NUMPAD_DOT = 158, -AKEYCODE_NUMPAD_COMMA = 159, -
    -  AKEYCODE_NUMPAD_ENTER = 160, -AKEYCODE_NUMPAD_EQUALS = 161, -AKEYCODE_NUMPAD_LEFT_PAREN = 162, -AKEYCODE_NUMPAD_RIGHT_PAREN = 163, -
    -  AKEYCODE_VOLUME_MUTE = 164, -AKEYCODE_INFO = 165, -AKEYCODE_CHANNEL_UP = 166, -AKEYCODE_CHANNEL_DOWN = 167, -
    -  AKEYCODE_ZOOM_IN = 168, -AKEYCODE_ZOOM_OUT = 169, -AKEYCODE_TV = 170, -AKEYCODE_WINDOW = 171, -
    -  AKEYCODE_GUIDE = 172, -AKEYCODE_DVR = 173, -AKEYCODE_BOOKMARK = 174, -AKEYCODE_CAPTIONS = 175, -
    -  AKEYCODE_SETTINGS = 176, -AKEYCODE_TV_POWER = 177, -AKEYCODE_TV_INPUT = 178, -AKEYCODE_STB_POWER = 179, -
    -  AKEYCODE_STB_INPUT = 180, -AKEYCODE_AVR_POWER = 181, -AKEYCODE_AVR_INPUT = 182, -AKEYCODE_PROG_RED = 183, -
    -  AKEYCODE_PROG_GREEN = 184, -AKEYCODE_PROG_YELLOW = 185, -AKEYCODE_PROG_BLUE = 186, -AKEYCODE_APP_SWITCH = 187, -
    -  AKEYCODE_BUTTON_1 = 188, -AKEYCODE_BUTTON_2 = 189, -AKEYCODE_BUTTON_3 = 190, -AKEYCODE_BUTTON_4 = 191, -
    -  AKEYCODE_BUTTON_5 = 192, -AKEYCODE_BUTTON_6 = 193, -AKEYCODE_BUTTON_7 = 194, -AKEYCODE_BUTTON_8 = 195, -
    -  AKEYCODE_BUTTON_9 = 196, -AKEYCODE_BUTTON_10 = 197, -AKEYCODE_BUTTON_11 = 198, -AKEYCODE_BUTTON_12 = 199, -
    -  AKEYCODE_BUTTON_13 = 200, -AKEYCODE_BUTTON_14 = 201, -AKEYCODE_BUTTON_15 = 202, -AKEYCODE_BUTTON_16 = 203, -
    -  AKEYCODE_LANGUAGE_SWITCH = 204, -AKEYCODE_MANNER_MODE = 205, -AKEYCODE_3D_MODE = 206, -AKEYCODE_CONTACTS = 207, -
    -  AKEYCODE_CALENDAR = 208, -AKEYCODE_MUSIC = 209, -AKEYCODE_CALCULATOR = 210, -AKEYCODE_ZENKAKU_HANKAKU = 211, -
    -  AKEYCODE_EISU = 212, -AKEYCODE_MUHENKAN = 213, -AKEYCODE_HENKAN = 214, -AKEYCODE_KATAKANA_HIRAGANA = 215, -
    -  AKEYCODE_YEN = 216, -AKEYCODE_RO = 217, -AKEYCODE_KANA = 218, -AKEYCODE_ASSIST = 219, -
    -  AKEYCODE_BRIGHTNESS_DOWN = 220, -AKEYCODE_BRIGHTNESS_UP = 221, -AKEYCODE_MEDIA_AUDIO_TRACK = 222, -AKEYCODE_SLEEP = 223, -
    -  AKEYCODE_WAKEUP = 224, -AKEYCODE_PAIRING = 225, -AKEYCODE_MEDIA_TOP_MENU = 226, -AKEYCODE_11 = 227, -
    -  AKEYCODE_12 = 228, -AKEYCODE_LAST_CHANNEL = 229, -AKEYCODE_TV_DATA_SERVICE = 230, -AKEYCODE_VOICE_ASSIST = 231, -
    -  AKEYCODE_TV_RADIO_SERVICE = 232, -AKEYCODE_TV_TELETEXT = 233, -AKEYCODE_TV_NUMBER_ENTRY = 234, -AKEYCODE_TV_TERRESTRIAL_ANALOG = 235, -
    -  AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236, -AKEYCODE_TV_SATELLITE = 237, -AKEYCODE_TV_SATELLITE_BS = 238, -AKEYCODE_TV_SATELLITE_CS = 239, -
    -  AKEYCODE_TV_SATELLITE_SERVICE = 240, -AKEYCODE_TV_NETWORK = 241, -AKEYCODE_TV_ANTENNA_CABLE = 242, -AKEYCODE_TV_INPUT_HDMI_1 = 243, -
    -  AKEYCODE_TV_INPUT_HDMI_2 = 244, -AKEYCODE_TV_INPUT_HDMI_3 = 245, -AKEYCODE_TV_INPUT_HDMI_4 = 246, -AKEYCODE_TV_INPUT_COMPOSITE_1 = 247, -
    -  AKEYCODE_TV_INPUT_COMPOSITE_2 = 248, -AKEYCODE_TV_INPUT_COMPONENT_1 = 249, -AKEYCODE_TV_INPUT_COMPONENT_2 = 250, -AKEYCODE_TV_INPUT_VGA_1 = 251, -
    -  AKEYCODE_TV_AUDIO_DESCRIPTION = 252, -AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253, -AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254, -AKEYCODE_TV_ZOOM_MODE = 255, -
    -  AKEYCODE_TV_CONTENTS_MENU = 256, -AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257, -AKEYCODE_TV_TIMER_PROGRAMMING = 258, -AKEYCODE_HELP = 259 -
    - }
     
    -
    diff --git a/docs/html/ndk/reference/looper_8h.jd b/docs/html/ndk/reference/looper_8h.jd deleted file mode 100644 index 91716316581c635852c8100ebcdfa4d68fe7bd43..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/looper_8h.jd +++ /dev/null @@ -1,70 +0,0 @@ -page.title=looper.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    looper.h File Reference
    -
    -
    - - - - - - -

    -Typedefs

    typedef struct ALooper ALooper
     
    typedef int(* ALooper_callbackFunc )(int fd, int events, void *data)
     
    - - - - - - - -

    -Enumerations

    enum  { ALOOPER_PREPARE_ALLOW_NON_CALLBACKS = 1<<0 - }
     
    enum  { ALOOPER_POLL_WAKE = -1, -ALOOPER_POLL_CALLBACK = -2, -ALOOPER_POLL_TIMEOUT = -3, -ALOOPER_POLL_ERROR = -4 - }
     
    enum  {
    -  ALOOPER_EVENT_INPUT = 1 << 0, -ALOOPER_EVENT_OUTPUT = 1 << 1, -ALOOPER_EVENT_ERROR = 1 << 2, -ALOOPER_EVENT_HANGUP = 1 << 3, -
    -  ALOOPER_EVENT_INVALID = 1 << 4 -
    - }
     
    - - - - - - - - - - - - - - - - - - - -

    -Functions

    ALooperALooper_forThread ()
     
    ALooperALooper_prepare (int opts)
     
    void ALooper_acquire (ALooper *looper)
     
    void ALooper_release (ALooper *looper)
     
    int ALooper_pollOnce (int timeoutMillis, int *outFd, int *outEvents, void **outData)
     
    int ALooper_pollAll (int timeoutMillis, int *outFd, int *outEvents, void **outData)
     
    void ALooper_wake (ALooper *looper)
     
    int ALooper_addFd (ALooper *looper, int fd, int ident, int events, ALooper_callbackFunc callback, void *data)
     
    int ALooper_removeFd (ALooper *looper, int fd)
     
    -
    diff --git a/docs/html/ndk/reference/modules.jd b/docs/html/ndk/reference/modules.jd deleted file mode 100644 index 2da73074e75d6aebc6dcae4a69c299486b74f697..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/modules.jd +++ /dev/null @@ -1,23 +0,0 @@ -page.title=Modules -page.customHeadTag= -@jd:body - - -
    -
    -
    Modules
    -
    -
    -
    Here is a list of all modules:
    -
    diff --git a/docs/html/ndk/reference/native__activity_8h.jd b/docs/html/ndk/reference/native__activity_8h.jd deleted file mode 100644 index 147ffdb531f84b81aefaff64676c4222be45e896..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/native__activity_8h.jd +++ /dev/null @@ -1,74 +0,0 @@ -page.title=native_activity.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    native_activity.h File Reference
    -
    -
    -
    #include <stdint.h>
    -#include <sys/types.h>
    -#include <jni.h>
    -#include <android/asset_manager.h>
    -#include <android/input.h>
    -#include <android/native_window.h>
    -
    - - - - - -

    -Data Structures

    struct  ANativeActivity
     
    struct  ANativeActivityCallbacks
     
    - - - - - - - -

    -Typedefs

    typedef struct ANativeActivity ANativeActivity
     
    typedef struct
    -ANativeActivityCallbacks 
    ANativeActivityCallbacks
     
    typedef void ANativeActivity_createFunc (ANativeActivity *activity, void *savedState, size_t savedStateSize)
     
    - - - - - -

    -Enumerations

    enum  { ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT = 0x0001, -ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED = 0x0002 - }
     
    enum  { ANATIVEACTIVITY_HIDE_SOFT_INPUT_IMPLICIT_ONLY = 0x0001, -ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS = 0x0002 - }
     
    - - - - - - - - - - - -

    -Functions

    void ANativeActivity_finish (ANativeActivity *activity)
     
    void ANativeActivity_setWindowFormat (ANativeActivity *activity, int32_t format)
     
    void ANativeActivity_setWindowFlags (ANativeActivity *activity, uint32_t addFlags, uint32_t removeFlags)
     
    void ANativeActivity_showSoftInput (ANativeActivity *activity, uint32_t flags)
     
    void ANativeActivity_hideSoftInput (ANativeActivity *activity, uint32_t flags)
     
    - - - -

    -Variables

    ANativeActivity_createFunc ANativeActivity_onCreate
     
    -
    diff --git a/docs/html/ndk/reference/native__window_8h.jd b/docs/html/ndk/reference/native__window_8h.jd deleted file mode 100644 index 75f9469d6964cba12b66070848f6d1280d115359..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/native__window_8h.jd +++ /dev/null @@ -1,61 +0,0 @@ -page.title=native_window.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    native_window.h File Reference
    -
    -
    -
    #include <android/rect.h>
    -
    - - - -

    -Data Structures

    struct  ANativeWindow_Buffer
     
    - - - - - -

    -Typedefs

    typedef struct ANativeWindow ANativeWindow
     
    typedef struct ANativeWindow_Buffer ANativeWindow_Buffer
     
    - - - -

    -Enumerations

    enum  { WINDOW_FORMAT_RGBA_8888 = 1, -WINDOW_FORMAT_RGBX_8888 = 2, -WINDOW_FORMAT_RGB_565 = 4 - }
     
    - - - - - - - - - - - - - - - - - -

    -Functions

    void ANativeWindow_acquire (ANativeWindow *window)
     
    void ANativeWindow_release (ANativeWindow *window)
     
    int32_t ANativeWindow_getWidth (ANativeWindow *window)
     
    int32_t ANativeWindow_getHeight (ANativeWindow *window)
     
    int32_t ANativeWindow_getFormat (ANativeWindow *window)
     
    int32_t ANativeWindow_setBuffersGeometry (ANativeWindow *window, int32_t width, int32_t height, int32_t format)
     
    int32_t ANativeWindow_lock (ANativeWindow *window, ANativeWindow_Buffer *outBuffer, ARect *inOutDirtyBounds)
     
    int32_t ANativeWindow_unlockAndPost (ANativeWindow *window)
     
    -
    diff --git a/docs/html/ndk/reference/native__window__jni_8h.jd b/docs/html/ndk/reference/native__window__jni_8h.jd deleted file mode 100644 index bffbc034b0f24ef96f7accd3d3481a37bd05158b..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/native__window__jni_8h.jd +++ /dev/null @@ -1,25 +0,0 @@ -page.title=native_window_jni.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    native_window_jni.h File Reference
    -
    -
    -
    #include <android/native_window.h>
    -#include <jni.h>
    -
    - - - -

    -Functions

    ANativeWindowANativeWindow_fromSurface (JNIEnv *env, jobject surface)
     
    -
    diff --git a/docs/html/ndk/reference/nav_f.png b/docs/html/ndk/reference/nav_f.png deleted file mode 100644 index 5ceae878cc8eb5b28d21195e7980e041cd58c003..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/nav_f.png and /dev/null differ diff --git a/docs/html/ndk/reference/nav_g.png b/docs/html/ndk/reference/nav_g.png deleted file mode 100644 index 2093a237a94f6c83e19ec6e5fd42f7ddabdafa81..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/nav_g.png and /dev/null differ diff --git a/docs/html/ndk/reference/nav_h.png b/docs/html/ndk/reference/nav_h.png deleted file mode 100644 index e619809c4c9c9c106a7364569991439f51288d57..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/nav_h.png and /dev/null differ diff --git a/docs/html/ndk/reference/obb_8h.jd b/docs/html/ndk/reference/obb_8h.jd deleted file mode 100644 index a856d4eea5d7eeb794fa41c4a9fbbe86d7ed5a3d..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/obb_8h.jd +++ /dev/null @@ -1,45 +0,0 @@ -page.title=obb.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    obb.h File Reference
    -
    -
    -
    #include <sys/types.h>
    -
    - - - -

    -Typedefs

    typedef struct AObbInfo AObbInfo
     
    - - - -

    -Enumerations

    enum  { AOBBINFO_OVERLAY = 0x0001 - }
     
    - - - - - - - - - - - -

    -Functions

    AObbInfoAObbScanner_getObbInfo (const char *filename)
     
    void AObbInfo_delete (AObbInfo *obbInfo)
     
    const char * AObbInfo_getPackageName (AObbInfo *obbInfo)
     
    int32_t AObbInfo_getVersion (AObbInfo *obbInfo)
     
    int32_t AObbInfo_getFlags (AObbInfo *obbInfo)
     
    -
    diff --git a/docs/html/ndk/reference/open.png b/docs/html/ndk/reference/open.png deleted file mode 100644 index 7e740cc4fde70b626427871d6f7f48ef75107378..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/open.png and /dev/null differ diff --git a/docs/html/ndk/reference/pages.jd b/docs/html/ndk/reference/pages.jd deleted file mode 100644 index 2d7ece8aeb439c39da6dd49d6b0635ad9a36bf5b..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/pages.jd +++ /dev/null @@ -1,16 +0,0 @@ -page.title=Related Pages -page.customHeadTag= -@jd:body - - -
    -
    -
    Related Pages
    -
    -
    -
    Here is a list of all related documentation pages:
    -
    diff --git a/docs/html/ndk/reference/rect_8h.jd b/docs/html/ndk/reference/rect_8h.jd deleted file mode 100644 index 85787b5b5b0c875d58f992980fd19692a8622ab1..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/rect_8h.jd +++ /dev/null @@ -1,30 +0,0 @@ -page.title=rect.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    rect.h File Reference
    -
    -
    -
    #include <stdint.h>
    -
    - - - -

    -Data Structures

    struct  ARect
     
    - - - -

    -Typedefs

    typedef struct ARect ARect
     
    -
    diff --git a/docs/html/ndk/reference/reference_toc.cs b/docs/html/ndk/reference/reference_toc.cs deleted file mode 100644 index d4e2d6daaf24980fc2a7ce81db4e8c92ea399b8b..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/reference_toc.cs +++ /dev/null @@ -1,78 +0,0 @@ - - - - - \ No newline at end of file diff --git a/docs/html/ndk/reference/sensor_8h.jd b/docs/html/ndk/reference/sensor_8h.jd deleted file mode 100644 index a537f4f189a11041ec964336c6c009036fc6c6a9..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/sensor_8h.jd +++ /dev/null @@ -1,143 +0,0 @@ -page.title=sensor.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    sensor.h File Reference
    -
    -
    -
    #include <sys/types.h>
    -#include <android/looper.h>
    -
    - - - - - - - - - - - -

    -Data Structures

    struct  ASensorVector
     
    struct  AMetaDataEvent
     
    struct  AUncalibratedEvent
     
    struct  AHeartRateEvent
     
    struct  ASensorEvent
     
    - - - - - - - -

    -Macros

    #define ASENSOR_STANDARD_GRAVITY   (9.80665f)
     
    #define ASENSOR_MAGNETIC_FIELD_EARTH_MAX   (60.0f)
     
    #define ASENSOR_MAGNETIC_FIELD_EARTH_MIN   (30.0f)
     
    - - - - - - - - - - - - - - - - - - - - - -

    -Typedefs

    typedef struct ASensorVector ASensorVector
     
    typedef struct AMetaDataEvent AMetaDataEvent
     
    typedef struct AUncalibratedEvent AUncalibratedEvent
     
    typedef struct AHeartRateEvent AHeartRateEvent
     
    typedef struct ASensorEvent ASensorEvent
     
    typedef struct ASensorManager ASensorManager
     
    typedef struct ASensorEventQueue ASensorEventQueue
     
    typedef struct ASensor ASensor
     
    typedef ASensor const * ASensorRef
     
    typedef ASensorRef const * ASensorList
     
    - - - - - - - -

    -Enumerations

    enum  {
    -  ASENSOR_TYPE_ACCELEROMETER = 1, -ASENSOR_TYPE_MAGNETIC_FIELD = 2, -ASENSOR_TYPE_GYROSCOPE = 4, -ASENSOR_TYPE_LIGHT = 5, -
    -  ASENSOR_TYPE_PROXIMITY = 8 -
    - }
     
    enum  {
    -  ASENSOR_STATUS_NO_CONTACT = -1, -ASENSOR_STATUS_UNRELIABLE = 0, -ASENSOR_STATUS_ACCURACY_LOW = 1, -ASENSOR_STATUS_ACCURACY_MEDIUM = 2, -
    -  ASENSOR_STATUS_ACCURACY_HIGH = 3 -
    - }
     
    enum  { AREPORTING_MODE_CONTINUOUS = 0, -AREPORTING_MODE_ON_CHANGE = 1, -AREPORTING_MODE_ONE_SHOT = 2, -AREPORTING_MODE_SPECIAL_TRIGGER = 3 - }
     
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Functions

    ASensorManagerASensorManager_getInstance ()
     
    int ASensorManager_getSensorList (ASensorManager *manager, ASensorList *list)
     
    ASensor const * ASensorManager_getDefaultSensor (ASensorManager *manager, int type)
     
    ASensor const * ASensorManager_getDefaultSensorEx (ASensorManager *manager, int type, bool wakeUp)
     
    ASensorEventQueueASensorManager_createEventQueue (ASensorManager *manager, ALooper *looper, int ident, ALooper_callbackFunc callback, void *data)
     
    int ASensorManager_destroyEventQueue (ASensorManager *manager, ASensorEventQueue *queue)
     
    int ASensorEventQueue_enableSensor (ASensorEventQueue *queue, ASensor const *sensor)
     
    int ASensorEventQueue_disableSensor (ASensorEventQueue *queue, ASensor const *sensor)
     
    int ASensorEventQueue_setEventRate (ASensorEventQueue *queue, ASensor const *sensor, int32_t usec)
     
    int ASensorEventQueue_hasEvents (ASensorEventQueue *queue)
     
    ssize_t ASensorEventQueue_getEvents (ASensorEventQueue *queue, ASensorEvent *events, size_t count)
     
    const char * ASensor_getName (ASensor const *sensor)
     
    const char * ASensor_getVendor (ASensor const *sensor)
     
    int ASensor_getType (ASensor const *sensor)
     
    float ASensor_getResolution (ASensor const *sensor)
     
    int ASensor_getMinDelay (ASensor const *sensor)
     
    int ASensor_getFifoMaxEventCount (ASensor const *sensor)
     
    int ASensor_getFifoReservedEventCount (ASensor const *sensor)
     
    const char * ASensor_getStringType (ASensor const *sensor)
     
    int ASensor_getReportingMode (ASensor const *sensor)
     
    bool ASensor_isWakeUpSensor (ASensor const *sensor)
     
    -
    diff --git a/docs/html/ndk/reference/storage__manager_8h.jd b/docs/html/ndk/reference/storage__manager_8h.jd deleted file mode 100644 index 6048d84efdff4c2ba9cc47d384df5cd796fb2c48..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/storage__manager_8h.jd +++ /dev/null @@ -1,59 +0,0 @@ -page.title=storage_manager.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    storage_manager.h File Reference
    -
    -
    -
    #include <stdint.h>
    -
    - - - - - -

    -Typedefs

    typedef struct AStorageManager AStorageManager
     
    typedef void(* AStorageManager_obbCallbackFunc )(const char *filename, const int32_t state, void *data)
     
    - - - -

    -Enumerations

    enum  {
    -  AOBB_STATE_MOUNTED = 1, -AOBB_STATE_UNMOUNTED = 2, -AOBB_STATE_ERROR_INTERNAL = 20, -AOBB_STATE_ERROR_COULD_NOT_MOUNT = 21, -
    -  AOBB_STATE_ERROR_COULD_NOT_UNMOUNT = 22, -AOBB_STATE_ERROR_NOT_MOUNTED = 23, -AOBB_STATE_ERROR_ALREADY_MOUNTED = 24, -AOBB_STATE_ERROR_PERMISSION_DENIED = 25 -
    - }
     
    - - - - - - - - - - - - - -

    -Functions

    AStorageManagerAStorageManager_new ()
     
    void AStorageManager_delete (AStorageManager *mgr)
     
    void AStorageManager_mountObb (AStorageManager *mgr, const char *filename, const char *key, AStorageManager_obbCallbackFunc cb, void *data)
     
    void AStorageManager_unmountObb (AStorageManager *mgr, const char *filename, const int force, AStorageManager_obbCallbackFunc cb, void *data)
     
    int AStorageManager_isObbMounted (AStorageManager *mgr, const char *filename)
     
    const char * AStorageManager_getMountedObbPath (AStorageManager *mgr, const char *filename)
     
    -
    diff --git a/docs/html/ndk/reference/struct_a_heart_rate_event.jd b/docs/html/ndk/reference/struct_a_heart_rate_event.jd deleted file mode 100644 index 1cd2a2d323001b9f6f27787d6d05f4f6a1c40daf..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_heart_rate_event.jd +++ /dev/null @@ -1,51 +0,0 @@ -page.title=AHeartRateEvent Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    AHeartRateEvent Struct Reference
    -
    -
    - -

    #include <sensor.h>

    - - - - - - -

    -Data Fields

    float bpm
     
    int8_t status
     
    -

    Field Documentation

    - -
    -
    - - - - -
    float bpm
    -
    - -
    -
    - -
    -
    - - - - -
    int8_t status
    -
    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_meta_data_event.jd b/docs/html/ndk/reference/struct_a_meta_data_event.jd deleted file mode 100644 index 352b5ba2be40326ad0917a345293c833a708289e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_meta_data_event.jd +++ /dev/null @@ -1,51 +0,0 @@ -page.title=AMetaDataEvent Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    AMetaDataEvent Struct Reference
    -
    -
    - -

    #include <sensor.h>

    - - - - - - -

    -Data Fields

    int32_t what
     
    int32_t sensor
     
    -

    Field Documentation

    - -
    -
    - - - - -
    int32_t sensor
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t what
    -
    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_native_activity.jd b/docs/html/ndk/reference/struct_a_native_activity.jd deleted file mode 100644 index 6d8124beae7c1dea162b10720427b9a89b424f18..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_native_activity.jd +++ /dev/null @@ -1,177 +0,0 @@ -page.title=ANativeActivity Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    ANativeActivity Struct Reference
    -
    -
    - -

    #include <native_activity.h>

    - - - - - - - - - - - - - - - - - - - - - - -

    -Data Fields

    struct ANativeActivityCallbackscallbacks
     
    JavaVM * vm
     
    JNIEnv * env
     
    jobject clazz
     
    const char * internalDataPath
     
    const char * externalDataPath
     
    int32_t sdkVersion
     
    void * instance
     
    AAssetManagerassetManager
     
    const char * obbPath
     
    -

    Detailed Description

    -

    This structure defines the native side of an android.app.NativeActivity. It is created by the framework, and handed to the application's native code as it is being launched.

    -

    Field Documentation

    - -
    -
    - - - - -
    AAssetManager* assetManager
    -
    -

    Pointer to the Asset Manager instance for the application. The application uses this to access binary assets bundled inside its own .apk file.

    - -
    -
    - -
    -
    - - - - -
    struct ANativeActivityCallbacks* callbacks
    -
    -

    Pointer to the callback function table of the native application. You can set the functions here to your own callbacks. The callbacks pointer itself here should not be changed; it is allocated and managed for you by the framework.

    - -
    -
    - -
    -
    - - - - -
    jobject clazz
    -
    -

    The NativeActivity object handle.

    -

    IMPORTANT NOTE: This member is mis-named. It should really be named 'activity' instead of 'clazz', since it's a reference to the NativeActivity instance created by the system for you.

    -

    We unfortunately cannot change this without breaking NDK source-compatibility.

    - -
    -
    - -
    -
    - - - - -
    JNIEnv* env
    -
    -

    JNI context for the main thread of the app. Note that this field can ONLY be used from the main thread of the process; that is, the thread that calls into the ANativeActivityCallbacks.

    - -
    -
    - -
    -
    - - - - -
    const char* externalDataPath
    -
    -

    Path to this application's external (removable/mountable) data directory.

    - -
    -
    - -
    -
    - - - - -
    void* instance
    -
    -

    This is the native instance of the application. It is not used by the framework, but can be set by the application to its own instance state.

    - -
    -
    - -
    -
    - - - - -
    const char* internalDataPath
    -
    -

    Path to this application's internal data directory.

    - -
    -
    - -
    -
    - - - - -
    const char* obbPath
    -
    -

    Available starting with Honeycomb: path to the directory containing the application's OBB files (if any). If the app doesn't have any OBB files, this directory may not exist.

    - -
    -
    - -
    -
    - - - - -
    int32_t sdkVersion
    -
    -

    The platform's SDK version code.

    - -
    -
    - -
    -
    - - - - -
    JavaVM* vm
    -
    -

    The global handle on the process's Java VM.

    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_native_activity_callbacks.jd b/docs/html/ndk/reference/struct_a_native_activity_callbacks.jd deleted file mode 100644 index 45b8e5ef4b732ca4775ac71f49043ef50e0c08e5..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_native_activity_callbacks.jd +++ /dev/null @@ -1,265 +0,0 @@ -page.title=ANativeActivityCallbacks Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    ANativeActivityCallbacks Struct Reference
    -
    -
    - -

    #include <native_activity.h>

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Data Fields

    void(* onStart )(ANativeActivity *activity)
     
    void(* onResume )(ANativeActivity *activity)
     
    void *(* onSaveInstanceState )(ANativeActivity *activity, size_t *outSize)
     
    void(* onPause )(ANativeActivity *activity)
     
    void(* onStop )(ANativeActivity *activity)
     
    void(* onDestroy )(ANativeActivity *activity)
     
    void(* onWindowFocusChanged )(ANativeActivity *activity, int hasFocus)
     
    void(* onNativeWindowCreated )(ANativeActivity *activity, ANativeWindow *window)
     
    void(* onNativeWindowResized )(ANativeActivity *activity, ANativeWindow *window)
     
    void(* onNativeWindowRedrawNeeded )(ANativeActivity *activity, ANativeWindow *window)
     
    void(* onNativeWindowDestroyed )(ANativeActivity *activity, ANativeWindow *window)
     
    void(* onInputQueueCreated )(ANativeActivity *activity, AInputQueue *queue)
     
    void(* onInputQueueDestroyed )(ANativeActivity *activity, AInputQueue *queue)
     
    void(* onContentRectChanged )(ANativeActivity *activity, const ARect *rect)
     
    void(* onConfigurationChanged )(ANativeActivity *activity)
     
    void(* onLowMemory )(ANativeActivity *activity)
     
    -

    Detailed Description

    -

    These are the callbacks the framework makes into a native application. All of these callbacks happen on the main thread of the application. By default, all callbacks are NULL; set to a pointer to your own function to have it called.

    -

    Field Documentation

    - -
    -
    - - - - -
    void(* onConfigurationChanged)(ANativeActivity *activity)
    -
    -

    The current device AConfiguration has changed. The new configuration can be retrieved from assetManager.

    - -
    -
    - -
    -
    - - - - -
    void(* onContentRectChanged)(ANativeActivity *activity, const ARect *rect)
    -
    -

    The rectangle in the window in which content should be placed has changed.

    - -
    -
    - -
    -
    - - - - -
    void(* onDestroy)(ANativeActivity *activity)
    -
    -

    NativeActivity is being destroyed. See Java documentation for Activity.onDestroy() for more information.

    - -
    -
    - -
    -
    - - - - -
    void(* onInputQueueCreated)(ANativeActivity *activity, AInputQueue *queue)
    -
    -

    The input queue for this native activity's window has been created. You can use the given input queue to start retrieving input events.

    - -
    -
    - -
    -
    - - - - -
    void(* onInputQueueDestroyed)(ANativeActivity *activity, AInputQueue *queue)
    -
    -

    The input queue for this native activity's window is being destroyed. You should no longer try to reference this object upon returning from this function.

    - -
    -
    - -
    -
    - - - - -
    void(* onLowMemory)(ANativeActivity *activity)
    -
    -

    The system is running low on memory. Use this callback to release resources you do not need, to help the system avoid killing more important processes.

    - -
    -
    - -
    -
    - - - - -
    void(* onNativeWindowCreated)(ANativeActivity *activity, ANativeWindow *window)
    -
    -

    The drawing window for this native activity has been created. You can use the given native window object to start drawing.

    - -
    -
    - -
    -
    - - - - -
    void(* onNativeWindowDestroyed)(ANativeActivity *activity, ANativeWindow *window)
    -
    -

    The drawing window for this native activity is going to be destroyed. You MUST ensure that you do not touch the window object after returning from this function: in the common case of drawing to the window from another thread, that means the implementation of this callback must properly synchronize with the other thread to stop its drawing before returning from here.

    - -
    -
    - -
    -
    - - - - -
    void(* onNativeWindowRedrawNeeded)(ANativeActivity *activity, ANativeWindow *window)
    -
    -

    The drawing window for this native activity needs to be redrawn. To avoid transient artifacts during screen changes (such resizing after rotation), applications should not return from this function until they have finished drawing their window in its current state.

    - -
    -
    - -
    -
    - - - - -
    void(* onNativeWindowResized)(ANativeActivity *activity, ANativeWindow *window)
    -
    -

    The drawing window for this native activity has been resized. You should retrieve the new size from the window and ensure that your rendering in it now matches.

    - -
    -
    - -
    -
    - - - - -
    void(* onPause)(ANativeActivity *activity)
    -
    -

    NativeActivity has paused. See Java documentation for Activity.onPause() for more information.

    - -
    -
    - -
    -
    - - - - -
    void(* onResume)(ANativeActivity *activity)
    -
    -

    NativeActivity has resumed. See Java documentation for Activity.onResume() for more information.

    - -
    -
    - -
    -
    - - - - -
    void*(* onSaveInstanceState)(ANativeActivity *activity, size_t *outSize)
    -
    -

    Framework is asking NativeActivity to save its current instance state. See Java documentation for Activity.onSaveInstanceState() for more information. The returned pointer needs to be created with malloc(); the framework will call free() on it for you. You also must fill in outSize with the number of bytes in the allocation. Note that the saved state will be persisted, so it can not contain any active entities (pointers to memory, file descriptors, etc).

    - -
    -
    - -
    -
    - - - - -
    void(* onStart)(ANativeActivity *activity)
    -
    -

    NativeActivity has started. See Java documentation for Activity.onStart() for more information.

    - -
    -
    - -
    -
    - - - - -
    void(* onStop)(ANativeActivity *activity)
    -
    -

    NativeActivity has stopped. See Java documentation for Activity.onStop() for more information.

    - -
    -
    - -
    -
    - - - - -
    void(* onWindowFocusChanged)(ANativeActivity *activity, int hasFocus)
    -
    -

    Focus has changed in this NativeActivity's window. This is often used, for example, to pause a game when it loses input focus.

    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_native_window___buffer.jd b/docs/html/ndk/reference/struct_a_native_window___buffer.jd deleted file mode 100644 index a2008fd395f8d18f6e0ed41412cd6f66b40271a7..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_native_window___buffer.jd +++ /dev/null @@ -1,110 +0,0 @@ -page.title=ANativeWindow_Buffer Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    ANativeWindow_Buffer Struct Reference
    -
    -
    - -

    #include <native_window.h>

    - - - - - - - - - - - - - - -

    -Data Fields

    int32_t width
     
    int32_t height
     
    int32_t stride
     
    int32_t format
     
    void * bits
     
    uint32_t reserved [6]
     
    -

    Detailed Description

    -

    ANativeWindow is a struct that represents a windows buffer.

    -

    A pointer can be obtained using ANativeWindow_lock().

    -

    Field Documentation

    - -
    -
    - - - - -
    void* bits
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t format
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t height
    -
    - -
    -
    - -
    -
    - - - - -
    uint32_t reserved[6]
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t stride
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t width
    -
    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_rect.jd b/docs/html/ndk/reference/struct_a_rect.jd deleted file mode 100644 index 4b9bb679429eb272c31399262fcc198f4e341416..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_rect.jd +++ /dev/null @@ -1,86 +0,0 @@ -page.title=ARect Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    ARect Struct Reference
    -
    -
    - -

    #include <rect.h>

    - - - - - - - - - - -

    -Data Fields

    int32_t left
     
    int32_t top
     
    int32_t right
     
    int32_t bottom
     
    -

    Detailed Description

    -

    ARect is a struct that represents a rectangular window area.

    -

    It is used with ANativeActivityCallbacks::onContentRectChanged event callback and ANativeWindow_lock() function.

    -

    Field Documentation

    - -
    -
    - - - - -
    int32_t bottom
    -
    -

    bottom position

    - -
    -
    - -
    -
    - - - - -
    int32_t left
    -
    -

    left position

    - -
    -
    - -
    -
    - - - - -
    int32_t right
    -
    -

    left position

    - -
    -
    - -
    -
    - - - - -
    int32_t top
    -
    -

    top position

    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_sensor_event.jd b/docs/html/ndk/reference/struct_a_sensor_event.jd deleted file mode 100644 index 3c6e49d46fc801fa17ecc719802d51442230ec15..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_sensor_event.jd +++ /dev/null @@ -1,364 +0,0 @@ -page.title=ASensorEvent Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    ASensorEvent Struct Reference
    -
    -
    - -

    #include <sensor.h>

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Data Fields

    int32_t version
     
    int32_t sensor
     
    int32_t type
     
    int32_t reserved0
     
    int64_t timestamp
     
    union {
       union {
          float   data [16]
     
          ASensorVector   vector
     
          ASensorVector   acceleration
     
          ASensorVector   magnetic
     
          float   temperature
     
          float   distance
     
          float   light
     
          float   pressure
     
          float   relative_humidity
     
          AUncalibratedEvent   uncalibrated_gyro
     
          AUncalibratedEvent   uncalibrated_magnetic
     
          AMetaDataEvent   meta_data
     
          AHeartRateEvent   heart_rate
     
       } 
     
       union {
          uint64_t   data [8]
     
          uint64_t   step_counter
     
       }   u64
     
    }; 
     
    uint32_t flags
     
    int32_t reserved1 [3]
     
    -

    Field Documentation

    - -
    -
    - - - - -
    union { ... }
    -
    - -
    -
    - -
    -
    - - - - -
    ASensorVector acceleration
    -
    - -
    -
    - -
    -
    - - - - -
    float data[16]
    -
    - -
    -
    - -
    -
    - - - - -
    uint64_t data[8]
    -
    - -
    -
    - -
    -
    - - - - -
    float distance
    -
    - -
    -
    - -
    -
    - - - - -
    uint32_t flags
    -
    - -
    -
    - -
    -
    - - - - -
    AHeartRateEvent heart_rate
    -
    - -
    -
    - -
    -
    - - - - -
    float light
    -
    - -
    -
    - -
    -
    - - - - -
    ASensorVector magnetic
    -
    - -
    -
    - -
    -
    - - - - -
    AMetaDataEvent meta_data
    -
    - -
    -
    - -
    -
    - - - - -
    float pressure
    -
    - -
    -
    - -
    -
    - - - - -
    float relative_humidity
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t reserved0
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t reserved1[3]
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t sensor
    -
    - -
    -
    - -
    -
    - - - - -
    uint64_t step_counter
    -
    - -
    -
    - -
    -
    - - - - -
    float temperature
    -
    - -
    -
    - -
    -
    - - - - -
    int64_t timestamp
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t type
    -
    - -
    -
    - -
    -
    - - - - -
    union { ... } u64
    -
    - -
    -
    - -
    -
    - - - - -
    AUncalibratedEvent uncalibrated_gyro
    -
    - -
    -
    - -
    -
    - - - - -
    AUncalibratedEvent uncalibrated_magnetic
    -
    - -
    -
    - -
    -
    - - - - -
    ASensorVector vector
    -
    - -
    -
    - -
    -
    - - - - -
    int32_t version
    -
    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_sensor_vector.jd b/docs/html/ndk/reference/struct_a_sensor_vector.jd deleted file mode 100644 index 397ad6d0dd87de19ddcd55f29de59a2a1590cf1a..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_sensor_vector.jd +++ /dev/null @@ -1,172 +0,0 @@ -page.title=ASensorVector Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    ASensorVector Struct Reference
    -
    -
    - -

    #include <sensor.h>

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Data Fields

    union {
       float   v [3]
     
       struct {
          float   x
     
          float   y
     
          float   z
     
       } 
     
       struct {
          float   azimuth
     
          float   pitch
     
          float   roll
     
       } 
     
    }; 
     
    int8_t status
     
    uint8_t reserved [3]
     
    -

    Detailed Description

    -

    A sensor event.

    -

    Field Documentation

    - -
    -
    - - - - -
    union { ... }
    -
    - -
    -
    - -
    -
    - - - - -
    float azimuth
    -
    - -
    -
    - -
    -
    - - - - -
    float pitch
    -
    - -
    -
    - -
    -
    - - - - -
    uint8_t reserved[3]
    -
    - -
    -
    - -
    -
    - - - - -
    float roll
    -
    - -
    -
    - -
    -
    - - - - -
    int8_t status
    -
    - -
    -
    - -
    -
    - - - - -
    float v[3]
    -
    - -
    -
    - -
    -
    - - - - -
    float x
    -
    - -
    -
    - -
    -
    - - - - -
    float y
    -
    - -
    -
    - -
    -
    - - - - -
    float z
    -
    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_a_uncalibrated_event.jd b/docs/html/ndk/reference/struct_a_uncalibrated_event.jd deleted file mode 100644 index 985b0b93e3683528a2c95be5bac7cd6308fb1902..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_a_uncalibrated_event.jd +++ /dev/null @@ -1,171 +0,0 @@ -page.title=AUncalibratedEvent Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    AUncalibratedEvent Struct Reference
    -
    -
    - -

    #include <sensor.h>

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Data Fields

    union {
       float   uncalib [3]
     
       struct {
          float   x_uncalib
     
          float   y_uncalib
     
          float   z_uncalib
     
       } 
     
    }; 
     
    union {
       float   bias [3]
     
       struct {
          float   x_bias
     
          float   y_bias
     
          float   z_bias
     
       } 
     
    }; 
     
    -

    Field Documentation

    - -
    -
    - - - - -
    union { ... }
    -
    - -
    -
    - -
    -
    - - - - -
    union { ... }
    -
    - -
    -
    - -
    -
    - - - - -
    float bias[3]
    -
    - -
    -
    - -
    -
    - - - - -
    float uncalib[3]
    -
    - -
    -
    - -
    -
    - - - - -
    float x_bias
    -
    - -
    -
    - -
    -
    - - - - -
    float x_uncalib
    -
    - -
    -
    - -
    -
    - - - - -
    float y_bias
    -
    - -
    -
    - -
    -
    - - - - -
    float y_uncalib
    -
    - -
    -
    - -
    -
    - - - - -
    float z_bias
    -
    - -
    -
    - -
    -
    - - - - -
    float z_uncalib
    -
    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/struct_android_bitmap_info.jd b/docs/html/ndk/reference/struct_android_bitmap_info.jd deleted file mode 100644 index f995b56e7e074511f78ff7dd99e12f5d2020584d..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/struct_android_bitmap_info.jd +++ /dev/null @@ -1,100 +0,0 @@ -page.title=AndroidBitmapInfo Struct Reference -page.customHeadTag= -@jd:body - - -
    - -
    -
    AndroidBitmapInfo Struct Reference
    -
    -
    - -

    #include <bitmap.h>

    - - - - - - - - - - - - -

    -Data Fields

    uint32_t width
     
    uint32_t height
     
    uint32_t stride
     
    int32_t format
     
    uint32_t flags
     
    -

    Detailed Description

    -

    Bitmap info, see AndroidBitmap_getInfo().

    -

    Field Documentation

    - -
    -
    - - - - -
    uint32_t flags
    -
    -

    Unused.

    - -
    -
    - -
    -
    - - - - -
    int32_t format
    -
    -

    The bitmap pixel format. See AndroidBitmapFormat

    - -
    -
    - -
    -
    - - - - -
    uint32_t height
    -
    -

    The bitmap height in pixels.

    - -
    -
    - -
    -
    - - - - -
    uint32_t stride
    -
    -

    The number of byte per row.

    - -
    -
    - -
    -
    - - - - -
    uint32_t width
    -
    -

    The bitmap width in pixels.

    - -
    -
    -
    The documentation for this struct was generated from the following file: -
    diff --git a/docs/html/ndk/reference/sync_off.png b/docs/html/ndk/reference/sync_off.png deleted file mode 100644 index b85662482b4bed01e9507971963f9c6b71b36e54..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/sync_off.png and /dev/null differ diff --git a/docs/html/ndk/reference/sync_on.png b/docs/html/ndk/reference/sync_on.png deleted file mode 100644 index e5044af075745db2ffb725f2611bcfacac939c95..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/sync_on.png and /dev/null differ diff --git a/docs/html/ndk/reference/tab_a.png b/docs/html/ndk/reference/tab_a.png deleted file mode 100644 index 170a784114dae128e94ed1f2f074bca70d1c92d2..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/tab_a.png and /dev/null differ diff --git a/docs/html/ndk/reference/tab_b.png b/docs/html/ndk/reference/tab_b.png deleted file mode 100644 index 777449930576ef572b0453ac220d416dfff6b4aa..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/tab_b.png and /dev/null differ diff --git a/docs/html/ndk/reference/tab_h.png b/docs/html/ndk/reference/tab_h.png deleted file mode 100644 index e1dddef1ff1ad286ff2c28c6504f3fdd9cab306f..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/tab_h.png and /dev/null differ diff --git a/docs/html/ndk/reference/tab_s.png b/docs/html/ndk/reference/tab_s.png deleted file mode 100644 index 3dc07b0c370fc3009c8f4687a386a98bc665b8e7..0000000000000000000000000000000000000000 Binary files a/docs/html/ndk/reference/tab_s.png and /dev/null differ diff --git a/docs/html/ndk/reference/tabs.css b/docs/html/ndk/reference/tabs.css deleted file mode 100644 index 71145bb1d98b4a134f60e5d807d1d8246925571e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/tabs.css +++ /dev/null @@ -1,60 +0,0 @@ -.tabs, .tabs2, .tabs3 { - background-image: url('tab_b.png'); - width: 100%; - z-index: 101; - font-size: 13px; - font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -} - -.tabs2 { - font-size: 10px; -} -.tabs3 { - font-size: 9px; -} - -.tablist { - margin: 0; - padding: 0; - display: table; -} - -.tablist li { - float: left; - display: table-cell; - background-image: url('tab_b.png'); - line-height: 36px; - list-style: none; -} - -.tablist a { - display: block; - padding: 0 20px; - font-weight: bold; - background-image:url('tab_s.png'); - background-repeat:no-repeat; - background-position:right; - color: #434343; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; - outline: none; -} - -.tabs3 .tablist a { - padding: 0 10px; -} - -.tablist a:hover { - background-image: url('tab_h.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); - text-decoration: none; -} - -.tablist li.current a { - background-image: url('tab_a.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); -} diff --git a/docs/html/ndk/reference/window_8h.jd b/docs/html/ndk/reference/window_8h.jd deleted file mode 100644 index 39e01dca89f5ad86d51edf56cbec81a08d711cec..0000000000000000000000000000000000000000 --- a/docs/html/ndk/reference/window_8h.jd +++ /dev/null @@ -1,53 +0,0 @@ -page.title=window.h File Reference -page.customHeadTag= -@jd:body - - - -
    - -
    -
    window.h File Reference
    -
    -
    - - - - -

    -Enumerations

    enum  {
    -  AWINDOW_FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001, -AWINDOW_FLAG_DIM_BEHIND = 0x00000002, -AWINDOW_FLAG_BLUR_BEHIND = 0x00000004, -AWINDOW_FLAG_NOT_FOCUSABLE = 0x00000008, -
    -  AWINDOW_FLAG_NOT_TOUCHABLE = 0x00000010, -AWINDOW_FLAG_NOT_TOUCH_MODAL = 0x00000020, -AWINDOW_FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040, -AWINDOW_FLAG_KEEP_SCREEN_ON = 0x00000080, -
    -  AWINDOW_FLAG_LAYOUT_IN_SCREEN = 0x00000100, -AWINDOW_FLAG_LAYOUT_NO_LIMITS = 0x00000200, -AWINDOW_FLAG_FULLSCREEN = 0x00000400, -AWINDOW_FLAG_FORCE_NOT_FULLSCREEN = 0x00000800, -
    -  AWINDOW_FLAG_DITHER = 0x00001000, -AWINDOW_FLAG_SECURE = 0x00002000, -AWINDOW_FLAG_SCALED = 0x00004000, -AWINDOW_FLAG_IGNORE_CHEEK_PRESSES = 0x00008000, -
    -  AWINDOW_FLAG_LAYOUT_INSET_DECOR = 0x00010000, -AWINDOW_FLAG_ALT_FOCUSABLE_IM = 0x00020000, -AWINDOW_FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000, -AWINDOW_FLAG_SHOW_WHEN_LOCKED = 0x00080000, -
    -  AWINDOW_FLAG_SHOW_WALLPAPER = 0x00100000, -AWINDOW_FLAG_TURN_SCREEN_ON = 0x00200000, -AWINDOW_FLAG_DISMISS_KEYGUARD = 0x00400000 -
    - }
     
    -
    diff --git a/docs/html/ndk/samples/_book.yaml b/docs/html/ndk/samples/_book.yaml deleted file mode 100644 index 3665f5aeaa4af82ebc85e208212d9be807ffabb1..0000000000000000000000000000000000000000 --- a/docs/html/ndk/samples/_book.yaml +++ /dev/null @@ -1,13 +0,0 @@ -toc: -- title: Overview - path: /ndk/samples/index.html - -- title: Walkthroughs - path: /ndk/samples/walkthroughs.html - section: - - title: hello-jni - path: /ndk/samples/sample_hellojni.html - - title: native-activity - path: /ndk/samples/sample_na.html - - title: Teapot - path: /ndk/samples/sample_teapot.html diff --git a/docs/html/ndk/samples/index.jd b/docs/html/ndk/samples/index.jd deleted file mode 100644 index d2e6dc3feabe8d0566ffa8ae163c2e6c6d8ad122..0000000000000000000000000000000000000000 --- a/docs/html/ndk/samples/index.jd +++ /dev/null @@ -1,33 +0,0 @@ -page.title=Samples: Overview -@jd:body - -

    Welcome to the NDK samples area. Here, you can download a variety of sample -apps to help deepen your understanding the NDK. - - -

    From this page, you can download samples that provide a look at the NDK in action. A few of the -topics covered are:

    - -
      -
    • Managing your native app's activity lifecycle.
    • -
    • Using native OpenGL on an Android device.
    • -
    • Implementing native audio.
    • -
    • Exporting modules.
    • -
    - -

    Note: These samples are also contained in the NDK installation -package; if you have already downloaded the NDK, you have them. They reside in -{@code $NDK/samples/}, where {@code $NDK} is the NDK installation root.

    - - - -

    Vulkan samples are located separately from those for the rest of the NDK. To explore them, -access the link below.

    - - \ No newline at end of file diff --git a/docs/html/ndk/samples/sample_hellojni.jd b/docs/html/ndk/samples/sample_hellojni.jd deleted file mode 100644 index fa61b28152fe8d921bfd45e13f767cc9211097b3..0000000000000000000000000000000000000000 --- a/docs/html/ndk/samples/sample_hellojni.jd +++ /dev/null @@ -1,123 +0,0 @@ -page.title=Sample: hello-jni -@jd:body - - - -

    This sample guides you through HelloJNI, a minimal -application built with the NDK. This sample is in the {@code samples/hello-jni/} directory -under the root directory of your NDK installation.

    - -

    Android.mk

    - -

    The following two lines provide the name of the native source file, along -with the name of the shared library to build. The full name of the built -library is {@code libhello-jni.so}, once the build system adds the -{@code lib} prefix and the {@code .so} extension.

    - -
    -LOCAL_SRC_FILES := hello-jni.c
    -LOCAL_MODULE    := hello-jni
    -
    - -

    For more information about what the {@code Android.mk} file does, and how to use it, see -Android.mk.

    - -

    Application.mk

    -

    This line tells the build system the CPU and architecture against which to build. In this -example, the build system builds for all supported architectures.

    - -
    -APP_ABI := all
    -
    - -

    For more information about the {@code Application.mk} file, and how to use it, see -Application.mk.

    - -

    Java-side Implementation

    -

    The {@code helloJNI.java} file is located in {@code hellojni/src/com/example/hellojni/}. It calls -a function to retrieve a string from the native side, then displays it on the screen.

    - -

    The source code contains three lines of particular interest to the NDK user. -They are presented here in the order in which they are used, rather than by -line order.

    - -

    This function call loads the {@code .so} file upon application startup.

    - -
    -System.loadLibrary("hello-jni");
    -
    - -

    The {@code native} keyword in this method declaration tells the -virtual machine that the function is in the shared library (that is, implemented on the native -side).

    - -
    -public native String stringFromJNI();
    -
    - -

    The Android framework calls the function loaded and declared in the -previous steps, displaying the string on the screen.

    - -
    -tv.setText( stringFromJNI() );
    -
    - -

    C-side Implementation

    -

    The {@code hello-jni.c} file is located in {@code hello-jni/jni/}. It contains a function that -returns a string that the Java side requested). The function declaration is as -follows:

    - -
    -jstring
    -Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
    -                                                  jobject thiz )
    -
    - -

    This declaration corresponds to the native function declared in the -Java source code. The return type, {@code jstring}, is a data type defined -in the -Java Native -Interface Specification. It is not actually a string, but a -pointer to a Java string.

    - -

    After {@code jstring} comes the function name, which is based on the -Java function name and and the path to the file containing it. Construct it -according to the following rules:

    - -
      -
    • Prepend {@code Java_} to it.
    • -
    • Describe the filepath relative to the top-level source directory.
    • -
    • Use underscores in place of forward slashes.
    • -
    • Omit the {@code .java} file extension.
    • -
    • After the last underscore, append the function name.
    • -
    - -

    Following these rules, this example uses the function name -{@code Java_com_example_hellojni_HelloJni_stringFromJNI}. This name refers to a Java -function called {@code stringFromJNI()}, which resides in -{@code hellojni/src/com/example/hellojni/HelloJni.java}.

    - -

    {@code JNIEnv*} is the pointer to the VM, and -{@code jobject} is a pointer to the implicit {@code this} object passed from -the Java side.

    - -

    The following line calls the VM API {@code (*env)}, and passes it a return value: -that is, the string that the function on the Java side had requested.

    - -
    -return (*env)->NewStringUTF(env, "Hello from JNI !
    -Compiled with ABI " ABI ".");
    -
    diff --git a/docs/html/ndk/samples/sample_na.jd b/docs/html/ndk/samples/sample_na.jd deleted file mode 100644 index 0966dd893d487f0402c12a59414a6b4ccb175120..0000000000000000000000000000000000000000 --- a/docs/html/ndk/samples/sample_na.jd +++ /dev/null @@ -1,259 +0,0 @@ -page.title=Sample: native-activity -@jd:body - -
    -
    -

    On this page

    - -
      -
    1. AndroidManifest.xml
    2. -
    3. Android.mk
    4. -
    5. Application.mk
    6. -
    7. main.c
    8. -
    - - -
    -
    - -

    The native-activity sample resides under the NDK installation root, in -{@code samples/native-activity}. It is a very simple example of a purely native -application, with no Java source code. In the absence of any Java source, the -Java compiler still creates an executable stub for the virtual machine to run. -The stub serves as a wrapper for the actual, native program, which is located in the {@code .so} -file.

    - -

    The app itself simply renders a color onto the entire screen, and -then changes the color partly in response to movement that it detects.

    - -

    AndroidManifest.xml

    - -

    An app with only native code must not specify an Android API level lower than 9, which introduced -the {@code NativeActivity} framework class.

    - -
    -<uses-sdk android:minSdkVersion="9" />
    -
    - -

    The following line declares {@code android:hasCode} as {@code false}, as this app has only -native code–no Java. -

    - -
    -<application android:label="@string/app_name"
    -android:hasCode="false">
    -
    - -

    The next line declares the {@code NativeActivity} class.

    - -
    -<activity android:name="android.app.NativeActivity"
    -
    - -

    Finally, the manifest specifies {@code android:value} as the name of the shared library to be -built, minus the initial {@code lib} and the {@code .so} extension. This value must be the same as -the name of {@code LOCAL_MODULE} in {@code Android.mk}.

    - -
    -<meta-data android:name="android.app.lib_name"
    -        android:value="native-activity" />
    -
    - -

    Android.mk

    -

    This file begins by providing the name of the shared library to generate.

    - -
    -LOCAL_MODULE    := native-activity
    -
    - -

    Next, it declares the name of the native source-code file.

    - -
    -LOCAL_SRC_FILES := main.c
    -
    - -

    Next, it lists the external libraries for the build system to use in building the binary. The -{@code -l} (link-against) option precedes each library name.

    - -
      -
    • {@code log} is a logging library.
    • -
    • {@code android} encompasses the standard Android support APIs for NDK. For more information about -the APIs that Android and the NDK support, see Android NDK Native -APIs.
    • -
    • {@code EGL} corresponds to the platform-specific portion of the graphics API.
    • -
    • {@code GLESv1_CM} corresponds to OpenGL ES, the version of OpenGL for Android. This library -depends on EGL.
    • -
    - -

    For each library:

    - -
      -
    • The actual file name starts with {@code lib}, and ends with the -{@code .so} extension. For example, the actual file name for the -{@code log} library is {@code liblog.so}.
    • -
    • The library resides in the following directory, NDK root: -{@code /platforms/android-/arch-/usr/lib/}.
    • -
    - -
    -LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM
    -
    - -

    The next line provides the name of the static library, {@code android_native_app_glue}, which the -application uses to manage {@code NativeActivity} lifecycle events and touch input.

    - -
    -LOCAL_STATIC_LIBRARIES := android_native_app_glue
    -
    - -

    The final line tells the build system to build this static library. -The {@code ndk-build} script places the built library -({@code libandroid_native_app_glue.a}) into the {@code obj} directory -generated during the build process. For more information about the {@code android_native_app_glue} -library, see its {@code android_native_app_glue.h} header and corresponding {@code .c}source file. -

    - - -
    -$(call import-module,android/native_app_glue)
    -
    - -

    For more information about the {@code Android.mk} file, see -Android.mk.

    - - -

    Application.mk

    - -

    This line defines the minimum level of Android API Level support.

    - -
    -APP_PLATFORM := android-10
    -
    - -

    Because there is no ABI definition, the build system defaults to building only for -{@code armeabi}.

    - -

    main.c

    -

    This file essentially contains the entire progam.

    - -

    The following includes correspond to the libraries, both shared and static, -enumerated in {@code Android.mk}.

    - -
    -#include <EGL/egl.h>
    -#include <GLES/gl.h>
    -
    -
    -#include <android/sensor.h>
    -#include <android/log.h>
    -#include <android_native_app_glue>
    -
    - -

    The {@code android_native_app_glue} library calls the following function, -passing it a predefined state structure. It also serves as a wrapper that -simplifies handling of {@code NativeActivity} callbacks.

    - -
    -void android_main(struct android_app* state) {
    -
    - -

    Next, the program handles events queued by the glue library. The event -handler follows the state structure.

    - -
    -struct engine engine;
    -
    -
    -
    -// Suppress link-time optimization that removes unreferenced code
    -// to make sure glue isn't stripped.
    -app_dummy();
    -
    -
    -memset(&engine, 0, sizeof(engine));
    -state->userData = &engine;
    -state->onAppCmd = engine_handle_cmd;
    -state->onInputEvent = engine_handle_input;
    -engine.app = state;
    -
    - -

    The application prepares to start monitoring the sensors, using the -APIs in {@code sensor.h}.

    - -
    -    engine.sensorManager = ASensorManager_getInstance();
    -    engine.accelerometerSensor =
    -                    ASensorManager_getDefaultSensor(engine.sensorManager,
    -                        ASENSOR_TYPE_ACCELEROMETER);
    -    engine.sensorEventQueue =
    -                    ASensorManager_createEventQueue(engine.sensorManager,
    -                        state->looper, LOOPER_ID_USER, NULL, NULL);
    -
    - -

    Next, a loop begins, in which the application polls the system for -messages (sensor events). It sends messages to -{@code android_native_app_glue}, which checks to see whether they match -any {@code onAppCmd} events defined in {@code android_main}. When a -match occurs, the message is sent to the handler for execution.

    - -
    -while (1) {
    -        // Read all pending events.
    -        int ident;
    -        int events;
    -        struct android_poll_source* source;
    -
    -
    -        // If not animating, we will block forever waiting for events.
    -        // If animating, we loop until all events are read, then continue
    -        // to draw the next frame of animation.
    -        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL,
    -                &events,
    -                (void**)&source)) >= 0) {
    -
    -
    -            // Process this event.
    -            if (source != NULL) {
    -                source->process(state, source);
    -            }
    -
    -
    -            // If a sensor has data, process it now.
    -            if (ident == LOOPER_ID_USER) {
    -                if (engine.accelerometerSensor != NULL) {
    -                    ASensorEvent event;
    -                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
    -                            &event, 1) > 0) {
    -                        LOGI("accelerometer: x=%f y=%f z=%f",
    -                                event.acceleration.x, event.acceleration.y,
    -                                event.acceleration.z);
    -                    }
    -                }
    -            }
    -
    -
    -        // Check if we are exiting.
    -        if (state->destroyRequested != 0) {
    -            engine_term_display(&engine);
    -            return;
    -        }
    -    }
    -
    - -

    Once the queue is empty, and the program exits the polling loop, the -program calls OpenGL to draw the screen.

    -
    -    if (engine.animating) {
    -        // Done with events; draw next animation frame.
    -        engine.state.angle += .01f;
    -        if (engine.state.angle > 1) {
    -            engine.state.angle = 0;
    -        }
    -
    -
    -        // Drawing is throttled to the screen update rate, so there
    -        // is no need to do timing here.
    -        engine_draw_frame(&engine);
    -    }
    -}
    -
    diff --git a/docs/html/ndk/samples/sample_teapot.jd b/docs/html/ndk/samples/sample_teapot.jd deleted file mode 100644 index 97708a7cb0bcc46d98b75d4826caa805818d5aa6..0000000000000000000000000000000000000000 --- a/docs/html/ndk/samples/sample_teapot.jd +++ /dev/null @@ -1,360 +0,0 @@ -page.title=Sample: Teapot -@jd:body - - - -

    The Teapot sample is located under in the {@code samples/Teapot/} directory, under the NDK -installation's root directory. This sample uses the OpenGL library to render the iconic -Utah -teapot. In particular, it showcases the {@code ndk_helper} helper class, -a collection of native helper functions required for implementing games and -similar applications as native applications. This class provides:

    - -
      -
    • An abstraction layer, {@code GLContext}, that handles certain NDK-specific behaviors.
    • -
    • Helper functions that are useful but not present in the NDK, such as tap detection.
    • -
    • Wrappers for JNI calls for platform features such as texture loading.
    • -
    - -

    AndroidManifest.xml

    -

    The activity declaration here is not {@link android.app.NativeActivity} itself, but -a subclass of it: {@code TeapotNativeActivity}.

    - -
    -    <activity android:name="com.sample.teapot.TeapotNativeActivity"
    -            android:label="@string/app_name"
    -            android:configChanges="orientation|keyboardHidden">
    -
    - -

    Ultimately, the name of the shared-object file that the build system builds is -{@code libTeapotNativeActivity.so}. The build system adds the {@code lib} prefix and the {@code .so} -extension; neither is part of the value that the manifest originally assigns to -{@code android:value}.

    - -
    -        <meta-data android:name="android.app.lib_name"
    -                android:value="TeapotNativeActivity" />
    -
    - -

    Application.mk

    -

    An app that uses the {@link android.app.NativeActivity} framework class must not specify an -Android API level lower than 9, which introduced that class. For more information about the -{@link android.app.NativeActivity} class, see -Native Activities and Applications. -

    - -
    -APP_PLATFORM := android-9
    -
    - -

    The next line tells the build system to build for all supported architectures.

    -
    -APP_ABI := all
    -
    - -

    Next, the file tells the build system which -C++ runtime support library to use.

    - -
    -APP_STL := stlport_static
    -
    - -

    Java-side Implementation

    -

    The {@code TeapotNativeActivity.java} file is located in -{@code samples/Teapot/src/com/sample/teapot}, under the NDK installation root directory. It handles -activity lifecycle events, and also enables the app to display text on the screen. The following -block of code is most important from the perspective of the native-side implementation: The native -code calls it to display a popup window for displaying text.

    - -
    -
    -void setImmersiveSticky() {
    -    View decorView = getWindow().getDecorView();
    -    decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
    -            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    -            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
    -            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    -            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    -            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    -}
    -
    - -

    Native-side Implementation

    - -

    This section explores the part of the Teapot app implemented in C++.

    - -

    TeapotRenderer.h

    - -

    These function calls perform the actual rendering of the teapot. It uses -{@code ndk_helper} for matrix calculation and to reposition the camera -based on where the user taps.

    - -
    -ndk_helper::Mat4 mat_projection_;
    -ndk_helper::Mat4 mat_view_;
    -ndk_helper::Mat4 mat_model_;
    -
    -
    -ndk_helper::TapCamera* camera_;
    -
    - -

    TeapotNativeActivity.cpp

    - -

    The following lines include {@code ndk_helper} in the native source file, and define the -helper-class name.

    - -
    -
    -#include "NDKHelper.h"
    -
    -//-------------------------------------------------------------------------
    -//Preprocessor
    -//-------------------------------------------------------------------------
    -#define HELPER_CLASS_NAME "com/sample/helper/NDKHelper" //Class name of helper
    -function
    -
    - -

    The first use of the {@code ndk_helper} class is to handle the -EGL-related lifecycle, associating EGL context states (created/lost) with -Android lifecycle events. The {@code ndk_helper} class enables the application to preserve context -information so that the system can restore a destroyed activity. This ability is useful, for -example, when the target machine is rotated (causing an activity to be -destroyed, then immediately restored in the new orientation), or when the lock -screen appears.

    - -
    -ndk_helper::GLContext* gl_context_; // handles EGL-related lifecycle.
    -
    - -

    Next, {@code ndk_helper} provides touch control.

    - -
    -ndk_helper::DoubletapDetector doubletap_detector_;
    -ndk_helper::PinchDetector pinch_detector_;
    -ndk_helper::DragDetector drag_detector_;
    -ndk_helper::PerfMonitor monitor_;
    -
    - -

    It also provides camera control (openGL view frustum).

    - -
    -ndk_helper::TapCamera tap_camera_;
    -
    - -

    The app then prepares to use the device's sensors, using the native APIs provided in the NDK.

    - -
    -ASensorManager* sensor_manager_;
    -const ASensor* accelerometer_sensor_;
    -ASensorEventQueue* sensor_event_queue_;
    -
    - -

    The app calls the following functions in response to various Android -lifecycle events and EGL context state changes, using various functionalities -provided by {@code ndk_helper} via the {@code Engine} class.

    - -
    -
    -void LoadResources();
    -void UnloadResources();
    -void DrawFrame();
    -void TermDisplay();
    -void TrimMemory();
    -bool IsReady();
    -
    - -

    Then, the following function calls back to the Java side to update the UI display.

    - -
    -void Engine::ShowUI()
    -{
    -    JNIEnv *jni;
    -    app_->activity->vm->AttachCurrentThread( &jni, NULL );
    -
    -
    -    //Default class retrieval
    -    jclass clazz = jni->GetObjectClass( app_->activity->clazz );
    -    jmethodID methodID = jni->GetMethodID( clazz, "showUI", "()V" );
    -    jni->CallVoidMethod( app_->activity->clazz, methodID );
    -
    -
    -    app_->activity->vm->DetachCurrentThread();
    -    return;
    -}
    -
    - -

    Next, this function calls back to the Java side to draw a text box -superimposed on the screen rendered on the native side, and showing frame -count.

    - -
    -void Engine::UpdateFPS( float fFPS )
    -{
    -    JNIEnv *jni;
    -    app_->activity->vm->AttachCurrentThread( &jni, NULL );
    -
    -
    -    //Default class retrieval
    -    jclass clazz = jni->GetObjectClass( app_->activity->clazz );
    -    jmethodID methodID = jni->GetMethodID( clazz, "updateFPS", "(F)V" );
    -    jni->CallVoidMethod( app_->activity->clazz, methodID, fFPS );
    -
    -
    -    app_->activity->vm->DetachCurrentThread();
    -    return;
    -}
    -
    - -

    The application gets the system clock and supplies it to the renderer -for time-based animation based on real-time clock. This information is used, for example, in -calculating momentum, where speed declines as a function of time.

    - -
    -renderer_.Update( monitor_.GetCurrentTime() );
    -
    - -

    The application now checks whether the context information that {@code GLcontext} holds is still -valid. If not, {@code ndk-helper} swaps the buffer, reinstantiating the GL context.

    - -
    -if( EGL_SUCCESS != gl_context_->Swap() )  // swaps
    -buffer.
    -
    - -

    The program passes touch-motion events to the gesture detector defined -in the {@code ndk_helper} class. The gesture detector tracks multitouch -gestures, such as pinch-and-drag, and sends a notification when triggered by -any of these events.

    - -
    -    if( AInputEvent_getType( event ) == AINPUT_EVENT_TYPE_MOTION )
    -    {
    -        ndk_helper::GESTURE_STATE doubleTapState =
    -            eng->doubletap_detector_.Detect( event );
    -        ndk_helper::GESTURE_STATE dragState = eng->drag_detector_.Detect( event );
    -        ndk_helper::GESTURE_STATE pinchState = eng->pinch_detector_.Detect( event );
    -
    -        //Double tap detector has a priority over other detectors
    -        if( doubleTapState == ndk_helper::GESTURE_STATE_ACTION )
    -        {
    -            //Detect double tap
    -            eng->tap_camera_.Reset( true );
    -        }
    -        else
    -        {
    -            //Handle drag state
    -            if( dragState & ndk_helper::GESTURE_STATE_START )
    -            {
    -                //Otherwise, start dragging
    -                ndk_helper::Vec2 v;
    -                eng->drag_detector_.GetPointer( v );
    -                eng->TransformPosition( v );
    -                eng->tap_camera_.BeginDrag( v );
    -            }
    -           // ...else other possible drag states...
    -
    -            //Handle pinch state
    -            if( pinchState & ndk_helper::GESTURE_STATE_START )
    -            {
    -                //Start new pinch
    -                ndk_helper::Vec2 v1;
    -                ndk_helper::Vec2 v2;
    -                eng->pinch_detector_.GetPointers( v1, v2 );
    -                eng->TransformPosition( v1 );
    -                eng->TransformPosition( v2 );
    -                eng->tap_camera_.BeginPinch( v1, v2 );
    -            }
    -            // ...else other possible pinch states...
    -        }
    -        return 1;
    -    }
    -
    - -

    The {@code ndk_helper} class also provides access to a vector-math library -({@code vecmath.h}), using it here to transform touch coordinates.

    - -
    -void Engine::TransformPosition( ndk_helper::Vec2& vec )
    -{
    -    vec = ndk_helper::Vec2( 2.0f, 2.0f ) * vec
    -            / ndk_helper::Vec2( gl_context_->GetScreenWidth(),
    -            gl_context_->GetScreenHeight() ) - ndk_helper::Vec2( 1.f, 1.f );
    -}
    -
    - - -

    The {@code HandleCmd()} method handles commands posted from the -android_native_app_glue library. For more information about what the messages -mean, refer to the comments in the {@code android_native_app_glue.h} and -{@code .c} source files.

    - -
    -void Engine::HandleCmd( struct android_app* app,
    -        int32_t cmd )
    -{
    -    Engine* eng = (Engine*) app->userData;
    -    switch( cmd )
    -    {
    -    case APP_CMD_SAVE_STATE:
    -        break;
    -    case APP_CMD_INIT_WINDOW:
    -        // The window is being shown, get it ready.
    -        if( app->window != NULL )
    -        {
    -            eng->InitDisplay();
    -            eng->DrawFrame();
    -        }
    -        break;
    -    case APP_CMD_TERM_WINDOW:
    -        // The window is being hidden or closed, clean it up.
    -        eng->TermDisplay();
    -        eng->has_focus_ = false;
    -        break;
    -    case APP_CMD_STOP:
    -        break;
    -    case APP_CMD_GAINED_FOCUS:
    -        eng->ResumeSensors();
    -        //Start animation
    -        eng->has_focus_ = true;
    -        break;
    -    case APP_CMD_LOST_FOCUS:
    -        eng->SuspendSensors();
    -        // Also stop animating.
    -        eng->has_focus_ = false;
    -        eng->DrawFrame();
    -        break;
    -    case APP_CMD_LOW_MEMORY:
    -        //Free up GL resources
    -        eng->TrimMemory();
    -        break;
    -    }
    -}
    -
    - -

    The {@code ndk_helper} class posts {@code APP_CMD_INIT_WINDOW} when {@code android_app_glue} -receives an {@code onNativeWindowCreated()} callback from the system. -Applications can normally perform window initializations, such as EGL -initialization. They do this outside of the activity lifecycle, since the -activity is not yet ready.

    - -
    -    //Init helper functions
    -    ndk_helper::JNIHelper::Init( state->activity, HELPER_CLASS_NAME );
    -
    -    state->userData = &g_engine;
    -    state->onAppCmd = Engine::HandleCmd;
    -    state->onInputEvent = Engine::HandleInput;
    -
    diff --git a/docs/html/ndk/samples/samples_toc.cs b/docs/html/ndk/samples/samples_toc.cs deleted file mode 100644 index 92266b13b408bebe5fc49720ee217be3254e3a4e..0000000000000000000000000000000000000000 --- a/docs/html/ndk/samples/samples_toc.cs +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - diff --git a/docs/html/ndk/samples/walkthroughs.jd b/docs/html/ndk/samples/walkthroughs.jd deleted file mode 100644 index 88ceb56c4b24c2f64c8d7f8bdad13158d7ca5ba2..0000000000000000000000000000000000000000 --- a/docs/html/ndk/samples/walkthroughs.jd +++ /dev/null @@ -1,13 +0,0 @@ -page.title=Samples: Walkthroughs -@jd:body - -

    This section provides detailed walkthroughs of several key samples. The samples are as -follows:

    - -
  • hello-jni: A very basic app that -illustrates core workings of the NDK.
  • -
  • native-activity: An app that shows the -fundamentals of constructing a purely native app. It places particular emphasis on the -{@code android_native_app_glue library}.
  • -
  • Teapot: A simple OpenGL demo, -showcasing the ndk_helper class.
  • diff --git a/docs/html/preview/_book.yaml b/docs/html/preview/_book.yaml deleted file mode 100644 index ad67249685544db1389526075ceaf49e163c3c58..0000000000000000000000000000000000000000 --- a/docs/html/preview/_book.yaml +++ /dev/null @@ -1,344 +0,0 @@ -toc: -- title: Program Overview - path: /preview/overview.html - path_attributes: - - name: es-lang - value: Información general del programa - - name: in-lang - value: Ikhtisar Program - - name: ja-lang - value: プログラム概要 - - name: ko-lang - value: 프로그램 개요 - - name: pt-br-lang - value: Visão geral do programa - - name: ru-lang - value: Обзор программы - - name: vi-lang - value: Tổng quan về Chương trình - - name: zh-cn-lang - value: 计划概览 - - name: zh-tw-lang - value: 程式總覽 - -- title: Support and Release Notes - path: /preview/support.html - -- title: Set Up the Preview - path: /preview/setup-sdk.html - path_attributes: - - name: es-lang - value: Configurar el SDK de la versión preliminar - - name: in-lang - value: Menyiapkan Preview - - name: ja-lang - value: Preview SDK のセットアップ - - name: ko-lang - value: 미리 보기 SDK 설정하기 - - name: pt-br-lang - value: Configuração do Preview SDK - - name: ru-lang - value: Настройка пакета SDK Preview - - name: vi-lang - value: Kiểm thử trên Thiết bị - - name: zh-cn-lang - value: 设置预览版 SDK - - name: zh-tw-lang - value: 設定預覽版 SDK - -- title: Test on a Device - path: /preview/download.html - path_attributes: - - name: es-lang - value: Pruebe en un dispositivo - - name: in-lang - value: Menguji pada Perangkat - - name: ja-lang - value: デバイス上でテストする - - name: ko-lang - value: 기기에서 테스트 - - name: pt-br-lang - value: Testar em um dispositivo - - name: ru-lang - value: Тестирование на устройстве - - name: vi-lang - value: Kiểm thử trên Thiết bị - - name: zh-cn-lang - value: 在设备上测试 - - name: zh-tw-lang - value: 在裝置上測試 - -- title: Behavior Changes - path: /preview/behavior-changes.html - path_attributes: - - name: es-lang - value: Cambios en los comportamientos - - name: in-lang - value: Perubahan Perilaku - - name: ja-lang - value: 動作の変更点 - - name: ko-lang - value: 동작 변경 - - name: pt-br-lang - value: Mudanças de comportamento - - name: ru-lang - value: Изменения в работе - - name: vi-lang - value: Các thay đổi Hành vi - - name: zh-cn-lang - value: 行为变更 - - name: zh-tw-lang - value: 行為變更 - section: - - title: Background Optimizations - path: /preview/features/background-optimization.html - path_attributes: - - name: es-lang - value: Optimizaciones en segundo plano - - name: in-lang - value: Optimisasi Latar Belakang - - name: ja-lang - value: バックグラウンド処理の最適化 - - name: ko-lang - value: 백그라운드 최적화 - - name: pt-br-lang - value: Otimizações em segundo plano - - name: ru-lang - value: Оптимизация фоновых процессов - - name: vi-lang - value: Tối ưu hóa Chạy ngầm - - name: zh-cn-lang - value: 后台优化 - - name: zh-tw-lang - value: 背景最佳化 - - title: Language and Locale - path: /preview/features/multilingual-support.html - path_attributes: - - name: es-lang - value: Idioma y configuración regional - - name: in-lang - value: Bahasa dan Lokal - - name: ja-lang - value: 言語とロケール - - name: ko-lang - value: 언어 및 로케일 - - name: pt-br-lang - value: Idioma e localidade - - name: ru-lang - value: Язык и языковой стандарт - - name: vi-lang - value: Ngôn ngữ và Bản địa - - name: zh-cn-lang - value: 语言和区域设置 - - name: zh-tw-lang - value: 語言和地區設定 - -- title: Android N for Developers - path: /preview/api-overview.html - path_attributes: - - name: es-lang - value: Información general de la API - - name: in-lang - value: Android N untuk Pengembang - - name: ja-lang - value: API の概要 - - name: ko-lang - value: API 개요 - - name: pt-br-lang - value: Visão geral da API - - name: ru-lang - value: Обзор API-интерфейсов - - name: vi-lang - value: Android N cho Nhà phát triển - - name: zh-cn-lang - value: API 概览 - - name: zh-tw-lang - value: API 總覽 - section: - - title: Multi-Window Support - path: /preview/features/multi-window.html - path_attributes: - - name: es-lang - value: Compatibilidad con ventanas múltiples - - name: in-lang - value: Dukungan Multi-Jendela - - name: ja-lang - value: マルチ ウィンドウのサポート - - name: ko-lang - value: 다중 창 지원 - - name: pt-br-lang - value: Suporte a várias janelas - - name: ru-lang - value: Поддержка многооконного режима - - name: vi-lang - value: Hỗ trợ đa cửa sổ - - name: zh-cn-lang - value: 多窗口支持 - - name: zh-tw-lang - value: 多視窗支援 - - title: Notifications - path: /preview/features/notification-updates.html - path_attributes: - - name: es-lang - value: Notificaciones - - name: in-lang - value: Pemberitahuan - - name: ja-lang - value: 通知 - - name: ko-lang - value: 알림 - - name: pt-br-lang - value: Notificações - - name: ru-lang - value: Уведомления - - name: vi-lang - value: Thông báo - - name: zh-cn-lang - value: 通知 - - name: zh-tw-lang - value: 通知 - - title: Data Saver - path: /preview/features/data-saver.html - - title: TV Recording - path: /preview/features/tv-recording-api.html - path_attributes: - - name: es-lang - value: Grabación de TV - - name: in-lang - value: Perekaman TV - - name: ja-lang - value: TV の録画 - - name: ko-lang - value: TV 녹화 - - name: pt-br-lang - value: Gravação para TV - - name: ru-lang - value: Запись ТВ - - name: vi-lang - value: Ghi lại TV - - name: zh-cn-lang - value: TV 录制 - - name: zh-tw-lang - value: 電視錄製 - - title: Key Attestation - path: /preview/features/key-attestation.html - - title: Network Security Configuration - path: /preview/features/security-config.html - path_attributes: - - name: es-lang - value: Configuración de seguridad de la red - - name: ja-lang - value: ネットワーク セキュリティ構成 - - name: ko-lang - value: 네트워크 보안 구성 - - name: pt-br-lang - value: Configurações de segurança de rede - - name: ru-lang - value: Конфигурация сетевой безопасности - - name: vi-lang - value: Cấu hình Bảo mật mạng - - name: zh-cn-lang - value: 网络安全配置 - - name: zh-tw-lang - value: 網路安全性設定 - - title: ICU4J Support - path: /preview/features/icu4j-framework.html - path_attributes: - - name: es-lang - value: API de ICU4J del framework de Android - - name: in-lang - value: ICU4J Android Framework API - - name: ja-lang - value: ICU4J Android フレームワーク API - - name: ko-lang - value: ICU4J Android 프레임워크 API - - name: pt-br-lang - value: APIs de estrutura do Android para ICU4J - - name: ru-lang - value: API-интерфейсы ICU4J в платформе Android - - name: vi-lang - value: API Khuôn khổ Android ICU4J - - name: zh-cn-lang - value: ICU4J Android 框架 API - - name: zh-tw-lang - value: ICU4J Android 架構 API - - title: Java 8 Language Features - path: /preview/j8-jack.html - path_attributes: - - name: es-lang - value: Funciones del lenguaje Java 8 - - name: in-lang - value: Fitur Bahasa Java 8 - - name: ja-lang - value: Java 8 の機能 - - name: ko-lang - value: Java 8 언어 기능 - - name: pt-br-lang - value: Recursos de linguagem do Java 8 - - name: ru-lang - value: Возможности языка Java 8 - - name: vi-lang - value: Tính năng của Ngôn ngữ Java 8 - - name: zh-cn-lang - value: Java 8 语言功能 - - name: zh-tw-lang - value: Java 8 語言功能 - - title: Android for Work Updates - path: /preview/features/afw.html - - title: Scoped Directory Access - path: /preview/features/scoped-folder-access.html - path_attributes: - - name: es-lang - value: Acceso a directorios determinados - - name: ja-lang - value: 特定のディレクトリへのアクセス - - name: ko-lang - value: 범위가 지정된 디렉터리 액세스 - - name: pt-br-lang - value: Acesso a diretórios com escopo - - name: ru-lang - value: Доступ к выделенным каталогам - - name: vi-lang - value: Truy cập Thư mục theo Phạm vi - - name: zh-cn-lang - value: 作用域目录访问 - - name: zh-tw-lang - value: 限定範圍目錄存取 - -- title: Samples - path: /preview/samples.html - path_attributes: - - name: es-lang - value: Ejemplos - - name: in-lang - value: Contoh - - name: ja-lang - value: サンプル - - name: ko-lang - value: 샘플 - - name: pt-br-lang - value: Exemplos - - name: ru-lang - value: Примеры - - name: zh-cn-lang - value: 示例 - - name: zh-tw-lang - value: 範例 - -- title: License Agreement - path: /preview/license.html - path_attributes: - - name: es-lang - value: Contrato de licencia - - name: ja-lang - value: 使用許諾契約 - - name: ko-lang - value: 라이선스 계약 - - name: pt-br-lang - value: Contrato de licença - - name: ru-lang - value: Лицензионное соглашение - - name: zh-cn-lang - value: 许可协议 - - name: zh-tw-lang - value: 授權協議 diff --git a/docs/html/preview/download-ota.jd b/docs/html/preview/download-ota.jd deleted file mode 100644 index 18f3e8d01f0a9124febab52be8775bc78a96dcba..0000000000000000000000000000000000000000 --- a/docs/html/preview/download-ota.jd +++ /dev/null @@ -1,332 +0,0 @@ -page.title=Applying a Device OTA Image - -@jd:body - -
    - - - - -
    - -

    - This page provides links to over-the-air (OTA) device images and describes - how to manually apply an OTA update to a device. This procedure may be useful - in recovering devices that received OTA updates through the Android Beta - Program and do not start up after the update is installed. -

    - -

    Installing OTA Images

    - -

    - -

    To install an OTA package to a device:

    - -
      -
    1. Download an OTA device image from the table below.
    2. -
    3. Reboot the device into Recovery mode. For more information on putting - Nexus devices in this mode, see - Reset your Nexus - device to factory settings. -
    4. -
    5. On the device, select ADB sideload.
    6. -
    7. Connect the device to a computer with the Android development environment - loaded and the Android Debug Bridge (adb) tool installed.
    8. -
    9. Run the following command: -
      adb sideload <ota-package>
      -
    10. -
    - - - -

    Device OTA Images

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    DeviceDownload / Checksums
    Nexus 5X
    "bullhead"
    bullhead-ota-npd56n-dd5c12ee.zip
    - MD5: af9a82e9a78925ca9c1c7f5f6fb851ec
    - SHA-1: e4aabd5634b7ebdeffa877cd9e49244c0be326e4 -
    Nexus 6
    "shamu"
    shamu-ota-npd56n-2818fd62.zip
    - MD5: d8df396b187a8667889260e5464bd676
    - SHA-1: c03c8ef8be587a574565855d4faa526254794e03 -
    Nexus 6P
    "angler"
    angler-ota-npd56n-d2f2611c.zip
    - MD5: c3c206892d414d4fc7da892ff840eada
    - SHA-1: 2bdc79409ace5e163ef014ae51977d0a71b83df5 -
    Nexus 9
    "volantis"
    volantis-ota-npd56n-42228a60.zip
    - MD5: c80cf483d8b3c014fc7b27f80957a158
    - SHA-1: f437829320f47ea3aa5f8b70ce2f0bb3d30b3f4f -
    Nexus 9G
    "volantisg"
    volantisg-ota-npd56n-9b4dbaac.zip
    - MD5: 9e55ac1650e4f07a662bafa7f082e91c
    - SHA-1: b9982be56c2817d122664869a1fbe9b13e9c72f7 -
    Nexus Player
    "fugu"
    fugu-ota-npd56n-b305968a.zip
    - MD5: dfc980acad6772d8473ccaa9cbbb681a
    - SHA-1: d7bf8192649dea970afda165d181b4eea07abd7d -
    Pixel C
    "ryu"
    ryu-ota-npd56n-5bf2fd66.zip
    - MD5: 1699e4bacfbef16a75ae6cf3f2e3d886
    - SHA-1: e20f3a8e43fcdd6acef21da80894afc8f9474e33 -
    General Mobile 4G (Android One)
    "seed"
    seed_l8150-ota-npd56n-a322696c.zip
    - MD5: afc0e363ad2fd7418423e189a339a8e9
    - SHA-1: fc4d818878df51894eac29932dd0e9f6511329c6 -
    - - -
    - -
    - - - - diff --git a/docs/html/preview/download.jd b/docs/html/preview/download.jd deleted file mode 100644 index ad82211d0e65fd400f58dc114a6609a0986944f2..0000000000000000000000000000000000000000 --- a/docs/html/preview/download.jd +++ /dev/null @@ -1,556 +0,0 @@ -page.title=Test on a Device -meta.tags="preview", "nexus","system image" -page.tags="preview", "androidn" -page.image=images/cards/card-n-downloads_2x.png - -@jd:body - -
    - - - - -
    - - - -

    - To run and test your app on the new platform you need to set up an Android N - runtime environment. You can do that in either of these ways: -

    - -
      -
    • Install Android N on a supported hardware device, or
    • -
    • Set up an Android emulator running Android N
    • -
    - -

    - If you want an environment for basic compatibility testing of your app on the - new platform, all you need is your current APK and a hardware device or - emulator. You don't necessarily need to update your full development - environment to do basic testing. -

    - -

    - If you want to modify your app to target Android N or use new Android N APIs, - you need to set up a development environment that's updated to support - Android N. Set Up to Develop for - Android N has details. -

    - - -

    Set up a hardware device

    - -

    - The N Developer Preview offers system updates for a range of hardware devices - that you can use for testing your app, from phones to tablets and TV. -

    - -

    - If you have access to a supported device, you can update it to a Developer - Preview milestone build in one of these ways: -

    - -
      -
    • Enroll the device in automatic OTA system updates through the - Android Beta Program. Once enrolled, your device will receive regular - over-the-air (OTA) updates of all milestone builds in the N Developer Preview. This - approach is recommended because it lets you seamlessly transition from your current - environment through the various releases of the N Developer Preview.
    • -
    • Download a Developer Preview system image and flash the device. - OTA updates are not provided automatically for devices that you flash manually, but - you can enroll those devices in Android Beta Program to get OTA updates.
    • -
    - -

    Enroll the device in automatic OTA updates

    - -

    - If you have access to a supported device (see the list in the Downloads - table), you can receive over-the-air updates to preview versions of Android - by enrolling that device in the Android Beta Program. These updates are - automatically downloaded and will update your device just like official - system updates. -

    - -

    - You can un-enroll a device at any time. The device will receive an OTA update - to the most recent production version of Android available for that device - (for example, Android 6.0 Marshmallow). The update requires a full device - reset, so user data on the device will be removed. Make sure to back - up important data before un-enrolling a device. -

    - -

    - For more information and to enroll your device, see - the Android Beta Program web site. -

    - -

    Note: - Un-enrolling requires a full device reset. Back up - important data first. -

    - -

    Flashing a device manually

    - -

    - At any time you can download the latest Developer Preview system image and - manually flash it to your device. See the table below to download the system - image for your test device. Manually flashing a device is useful if you need - precise control over the test environment or need to reinstall frequently, - such as for automated testing. -

    - -

    - Installing a system image on a device removes all data from the - device, so you should back up your data first. -

    - -

    - After you back up your device data and download the system image below that - matches your device, follow the instructions at developers.google.com/android - to flash the image onto your device. -

    - -

    - Manually flashed system images do not - automatically receive OTA updates to later Developer Preview - milestone builds. Make sure to keep your environment up-to-date and flash a - new system image at each Developer Preview milestone. -

    - -

    - If you decide you want to get OTA updates after manually flashing a device, - all you need to do is enroll the device in the Android - Beta Program. You can enroll the device at any time to receive the next Preview - update over the air. -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    DeviceDownload / Checksums
    Nexus 5X
    "bullhead"
    bullhead-npd56n-factory-996cac57.tgz
    - MD5: 5aadba91f60de00d58dc6198ef5cc3ba
    - SHA-1: 996cac575d83bde573315290da8f52cecc4127d2 -
    Nexus 6
    "shamu"
    shamu-npd56n-factory-7936bf75.tgz
    - MD5: b7ed0db569f3bc2d6655fe8d8cea0e13
    - SHA-1: 7936bf75e6bfb771bd14485211a319b246311b96 -
    Nexus 6P
    "angler"
    angler-npd56n-factory-1ce5ccad.tgz
    - MD5: f296eccaed4e2526d6435df8cf0e8df1
    - SHA-1: 1ce5ccad8a3eae143e0ecd9c7afbb1be2f1d41cc -
    Nexus 9
    "volantis"
    volantis-npd56n-factory-8b9f997e.tgz
    - MD5: 111c2fe5777dd6aae71fb8ef35dda9d3
    - SHA-1: 8b9f997ea39fdaf505527536bd346948ae1bae30 -
    Nexus 9G
    "volantisg"
    volantisg-npd56n-factory-ef05106a.tgz
    - MD5: 3a6f4d47b385966347bd26b7a922cd6e
    - SHA-1: ef05106a9e3becea5673ea67d6c0cc21a2ec09d4 -
    Nexus Player
    "fugu"
    fugu-npd56n-factory-a51674a1.tgz
    - MD5: b75dc745a64848ea24124db8fa9252ed
    - SHA-1: a51674a1303b17fec0405d513f9c0fe9f225780f -
    Pixel C
    "ryu"
    ryu-npd56n-factory-e36c49b1.tgz
    - MD5: 0a2d660b09e19614a5b3573487b88066
    - SHA-1: e36c49b184843cdfe10278aebc04ce50b6d670b6 -
    General Mobile 4G (Android One)
    "seed"
    seed_l8150-npd56n-factory-dd5d4fd2.tgz
    - MD5: 3420581b969af777753141dacc7f73b9
    - SHA-1: dd5d4fd203f9c5dad658434c0ff370c411b78835 -
    Sony Xperia Z3
    (D6603 and D6653)
    Download: Xperia Companion
    - For more information, see Try Android N Developer Preview for Xperia Z3. -
    - -

    Uninstalling the Preview from a device

    - -

    - If you want to uninstall the preview from a device, you can do so in one of - these ways:

    -
      -
    • Obtain a factory spec system image and then manually - flash it to the device. -
        -
      • For Nexus devices and Pixel C devices, see - the Factory Images - for Nexus Devices page for downloads.
      • -
      • For other devices, please contact the device manufacturer - directly. Alternatively, if the device is supported - in the Android Beta Program, you can enroll the device in the - program and then un-enroll it (see below).
      • -
      -
    • -
    • Un-enroll the device from Android Beta Program. If the - device is enrolled in the Android Beta - Program, regardless of device, you can simply un-enroll it from the program. -

      - The device will receive an OTA update to the most recent production version - of Android available for that device (for example, Android 6.0 Marshmallow). - The update requires a full device reset, so user data on the device will be - removed. Make sure to back up important data before - un-enrolling a device. -

      -
    • -
    - -

    Note: - Uninstalling a Developer Preview system image prior to - the end of the program requires a full device reset and removes all user data - on the device. -

    - - -

    Set up an emulator

    - -

    To use the Android Emulator to run the Android N Preview, you need to -download the Android N Preview SDK and create a virtual device for the -emulator.

    - -

    First, download the Android N Preview SDK as follows (if you -already got it while setting up -to develop for Android N, you can skip this part): - -

      -
    1. In Android Studio, open the Settings dialog - (File > Settings on Windows/Linux, or - Android Studio > Preferences on Mac). In the left - panel, select Appearance & Behavior > - System Settings > Android SDK. - -
    2. Click the SDK Platforms tab, then select the - Android N Preview check box.
    3. - -
    4. Click the SDK Tools tab, then select the - Android SDK Build Tools, Android SDK - Platform-Tools, and Android SDK Tools check - boxes. -
    5. - -
    6. Click OK and accept the license - agreements for any packages to be installed. -
    7. -
    - -

    You should now have Android SDK Built-Tools 24.0 0 rc1, -Platform-Tools 24.0.0 rc1, and SDK Tools -25.0.9. If you do not update the SDK Tools to 25.0.9, then you won't -be able to run the x86_64 system images for Android N.

    - - -

    Now create a virtual device with the Android N system image:

    - -
      -
    1. Open the AVD Manager by selecting Tools > Android > - AVD Manager.
    2. -
    3. Click Create Virtual Device.
    4. -
    5. Select a device such as Nexus 5X, Nexus 6P, Nexus 9, or Android TV, - then click Next.
    6. -
    7. Select the N system image (with the - x86 ABI), then click Next. - (Only x86 system images are currently supported with the Android Emulator -for the Android N Preview.) -
    8. Complete the rest of the AVD configuration and click - Finish.
    9. -
    - -

    You can now launch the Android Emulator with the Android N Preview AVD.

    - -

    -For the best experience in the Android Emulator, make sure you're using -Android Studio 2.1 or higher, which supports Android Emulator 2.0 -with much faster performance compared to the emulator in -Android Studio 1.5.

    - -

    For more information about creating virtual devices, see Managing Virtual Devices. -

    - - - - - - - - - - - - - - -
    - -
    - - - - diff --git a/docs/html/preview/features/afw.jd b/docs/html/preview/features/afw.jd deleted file mode 100644 index 17cd58ea1b8e5d657a3120fd2d25dd3645a034b0..0000000000000000000000000000000000000000 --- a/docs/html/preview/features/afw.jd +++ /dev/null @@ -1,555 +0,0 @@ -page.title=Android for Work Updates -page.metaDescription=New Android for Work APIs and features in Android N. -page.keywords="android for work", "android N", "enterprise", "QR code" - -@jd:body - - - -

    This document describes the new Android for Work features provided in -Android N.

    - -

    QR Code Provisioning

    - -

    - Android for Work now supports using QR codes to provision corporate-liable - devices. The setup wizard now allows you to scan a QR code to provision - the device. -

    - -

    Work Profile Security Challenge

    - -

    - Profile owners can require users to specify a security challenge for apps - running in the work profile. The system shows the security challenge when the - user attempts to open any work apps. If the user successfully completes the - security challenge, the system unlocks the work profile and decrypts it if - necessary. -

    - -

    - If a profile owner sends an {@link - android.app.admin.DevicePolicyManager#ACTION_SET_NEW_PASSWORD} intent, the - system prompts a user to set up a security challenge. The profile owner can - also send an ACTION_SET_NEW_PARENT_PROFILE_PASSWORD intent to - prompt the user to set a device lock. -

    - -

    - Profile owners can choose to set the password policies for the work challenge - differently from the policies for other device passwords. For example, the - minimum length for the device challenge response can be different from the - length required for other passwords. Profile owners set the challenge - policies using the usual {@link android.app.admin.DevicePolicyManager} - methods, such as {@link - android.app.admin.DevicePolicyManager#setPasswordQuality - setPasswordQuality()} and {@link - android.app.admin.DevicePolicyManager#setPasswordMinimumLength - setPasswordMinimumLength()}. The profile owner can also set the device lock, - by using the {@link android.app.admin.DevicePolicyManager} instance returned - by the new DevicePolicyManager.getParentProfileInstance() - method. Additionally, profile owners can customize the credentials screen for - the work challenge by using the {@link android.app.admin.DevicePolicyManager} - class's new setOrganizationColor() and - setOrganizationName() methods. -

    - -

    - For details on the new methods and constants, see the - DevicePolicyManager reference page in the N Preview SDK Reference. -

    - -

    Disable Access to Apps

    - -

    - Device owners and profile owners can temporarily suspend access to packages - by calling the new DevicePolicyManager.setPackagesSuspended() - method. Owners can use the same method to re-enable those packages. -

    - -

    - While a package is suspended, it cannot start activities, notifications to - the package are suppressed, and the app's entry in the overview screen is hidden. - Suspended packages do not show in the overview screen, and they - cannot show dialogs (including toasts and snackbars). They also cannot play - audio or vibrate the device. -

    - -

    - Launchers should apply a distinctive UI to suspended apps to show that the - apps aren't currently available; for example, they might render the app icon - in gray. Launchers can find out if an app is suspended by calling the new - DevicePolicyManager.getPackageSuspended() method. -

    - -

    Toggle Work Mode

    - -

    - On dual-profile devices, users can toggle work mode on and off. While work - mode is turned off, the managed profile is temporarily shut down. Work - profile apps, background sync, and notifications are all disabled, including - the profile owner app. While the work profile is disabled, the system - displays a persistent status icon to remind users that they can't launch work - apps. The system launcher indicates that work apps and widgets are not - accessible. -

    - -

    Always-On VPN

    - -

    - Device owners and profile owners can require that work apps always connect to - the network through a specified VPN. If owners set this requirement, the - device automatically starts that VPN at boot time. -

    - -

    - Owners can require use of a VPN by calling the new - DevicePolicyManager.setAlwaysOnVpnPackage() method. To find out - if the owner has set a VPN requirement, call the new - DevicePolicyManager.GetAlwaysOnVpnPackage() method. -

    - -

    - Because the system can directly bind VPN services without app interaction, - VPN clients need to handle new entry points for always-on VPN. As before, you - can find active services by using an intent filter that matches the action - {@link android.net.VpnService android.net.VpnService}. -

    - -

    - Users can manually set an always-on VPN client that implement {@link - android.net.VpnService} by using the Settings > More > - VPN screen. -

    - -

    Contacts Integration with Work Profile

    - -

    - Profile owners can allow local search and directory lookup of work contacts - from the primary user. For example, a user can access both personal and work - directory contacts from their personal dialer or contacts application (if - permitted by their profile administrator). -

    - -

    - Developers that leverage the Contact Provider can use the Enterprise Contacts - API to access work profile directory entries from the primary user if allowed - by policy: -

    - -
      -
    • ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Phone.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Email.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Callable.ENTERPRISE_CONTENT_FILTER_URI -
    • - -
    • ContactsContract.Directory.ENTERPRISE_CONTENT_URI -
    • - -
    • ContactsContract.Directory.isEntepriseDirectoryId() -
    • -
    - -

    - Profile owners can control the visibility of work contacts in the primary - user using the following new methods: -

    - -
      -
    • - DevicePolicyManager.setCrossProfileContactsSearchDisabled() -
    • - -
    • - DevicePolicyManager.getCrossProfileContactsSearchDisabled() -
    • -
    - -

    Remote Reboot

    - -

    - Device owners can remotely reboot devices. In some cases, devices deployed in - public places inside enclosures can prevent access to the power button. If a - device needs to be rebooted, administrators can do so using the new - DevicePolicyManager.reboot() method. -

    - -

    Disable Data Roaming

    - -

    - Device owners can disable data roaming using the new {@link - android.os.UserManager} user restriction DISALLOW_DATA_ROAMING. -

    - -

    Enterprise Process Logging

    - -

    - Device owners can identify suspicious activity by remotely tracking device - activity, including app launches, adb activity, and screen unlocks. Process - logs don’t require user consent. To retrieve logs, device owners enable - device logging using DevicePolicyManager.setSecurityLoggingEnabled(). -

    - -

    - API changes include: -

    - -
      - -
    • - The new class android.app.admin.SecurityLog and its - methods -
    • - -
    • - void DevicePolicyManager.setSecurityLoggingEnabled() -
    • - -
    • - boolean DevicePolicyManager.isSecurityLoggingEnabled() -
    • - -
    • - List<SecurityEvent> - DevicePolicyManager.retrieveSecurityLogs() -
    • - -
    • - List<SecurityEvent> - DevicePolicyManager.retrievePreRebootSecurityLogs() -
    • - -
    • - void DeviceAdminReceiver.onSecurityLogsAvailable() -
    • -
    - -

    Remote Bug Reports

    - -

    - Device owners can remotely trigger and retrieve a bug report that contains a - device state dump file, which allows forensic investigation of a known - incident or compromised device. Due to the detailed nature of the bug report, - user consent is required. -

    - -

    - Android N includes the following API additions to support this feature. For - details, see the N Preview SDK - Reference. -

    - -
      -
    • - DevicePolicyManager.requestBugreport() -
    • - -
    • - DeviceAdminReceiver.onBugreportFailed() -
    • - -
    • - DeviceAdminReceiver.onBugreportShared() -
    • - -
    • - DeviceAdminReceiver.onBugreportSharingDeclined() -
    • - -
    • - DeviceAdminReceiver.BUGREPORT_FAILURE_FAILED_COMPLETING -
    • - -
    • - DeviceAdminReceiver.BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE -
    • -
    - -

    Remove a Client Certificate

    - -

    - Profile owners and device owners can now remove client certificates that were - installed through {@link android.app.admin.DevicePolicyManager#installKeyPair - installKeyPair()} by calling the new method - DevicePolicyManager.removeKeyPair(). -

    - -

    Grant Access to Client Certificate on - Installation

    - -

    - If a profile owner or device owner grants a third-party app the ability to - manage certificates, the app can grant itself access to certificates it - installs without any intervention by the owner. -

    - -

    - The existing API for managing certificates is extended to include: -

    - -
      -
    • DevicePolicyManager.installKeyPair() -
    • -
    - -

    System UI Policy Transparency

    - -

    - Policies that affect the user experience or restrict user Settings are fully - disclosed to the user, and profile owners and device owners can attribute the - policy to their company’s IT department. In addition to a consistent “Action - not allowed” message in Settings, IT administrators can set an - organization-specific support message in device settings with the following - new {@link android.app.admin.DevicePolicyManager} methods: -

    - -
      -
    • - DevicePolicyManager.setShortSupportMessage() -
    • - -
    • - DevicePolicyManager.setLongSupportMessage() -
    • -
    - -

    Managed Configurations Enhancements

    - -

    - The device or profile owner can enable another application to manage - configurations via the new - DevicePolicyManager.setApplicationRestrictionsManagingPackage() - method. The nominated application can check whether this permission has been - granted by calling - DevicePolicyManager.isCallerApplicationRestrictionsManagingPackage(). -

    - -

    - An application nominated to manage configurations can call {@link - android.app.admin.DevicePolicyManager#setApplicationRestrictions - setApplicationRestrictions()} and {@link - android.app.admin.DevicePolicyManager#getApplicationRestrictions - getApplicationRestrictions()} for any packages within that user or profile. -

    - -

    Location Off Switch

    - -

    - Users can disable location permissions for work apps while continuing to - access location information in their personal apps. A separate location - access switch in Location Settings allows users to deny location updates or - last-location queries for apps running in the work profile. -

    - -

    - The top level location off switch disables location access for both the - primary profile and the managed profile. -

    - -

    Customized Provisioning

    - -

    - An application can customize the profile owner and device owner provisioning - flows with corporate colors and logos. -

    - -
    -
    - DevicePolicyManager.EXTRA_PROVISIONING_MAIN_COLOR -
    - -
    - Customizes flow color. -
    - -
    - DevicePolicyManager.EXTRA_PROVISIONING_LOGO_URI -
    - -
    - Customizes the flow with a corporate logo. -
    -
    - -

    Multiple Wi-Fi CA Certificates

    - -

    - Profile owners and device owners can set multiple CA certificates for a given - Wi-Fi configuration. When corporate Wi-Fi networks have separate CAs for - separate access points with the same SSID, IT administrators can include all - relevant CAs in the Wi-Fi configuration using the new method - setCaCertificates(). -

    - -

    - APIs added are: -

    - -
      -
    • - WifiEnterpriseConfig.setCaCertificates() -
    • - -
    • - WifiEnterpriseConfig.getCaCertificates() -
    • -
    - -

    Customized Lockscreen Message

    - -

    - Device owners can provide owner information to be shownon the lockscreen. - This information takes precedence over the user lock screen message (if one is - set). New {@link android.app.admin.DevicePolicyManager} methods are: -

    - -
      -
    • - setDeviceOwnerLockScreenInfo() -
    • - -
    • - getDeviceOwnerLockScreenInfo() -
    • -
    - -

    Work Profile ConnectionService

    - -

    - Profile owners can specify a work dialer application that uses a - work-specific {@link android.telecom.ConnectionService} for the calling - backend (calling accounts). The work dialer maintains a work-only call log - and relies on work contacts only. Users have a consistent in-call UI - experience regardless of dialing application. Incoming work calls to the work - calling accounts are distinguished from personal incoming calls to the - personal calling accounts. -

    - -

    - The dialer should check for the new flag - android.telecom.Call.PROPERTY_ENTERPRISE_CALL to determine if a call - is a work call. If a call is a work call, the dialer should indicate this, - such as by adding a work badge. -

    - -

    Lock Down Wallpaper

    - -

    - A new user restriction (DISALLOW_SET_WALLPAPER) prevents the - user from changing their wallpaper. The device owner or profile owner can - still change the wallpaper, but they can only change the wallpaper for the - user or profile they control. For example, a profile owner can’t change the - wallpaper of the parent user, but a profile owner in the primary profile or - device owner can. A profile owner or device owner that wants to change the - wallpaper should check whether the the user or profile they manage has a - wallpaper ({@link android.app.WallpaperManager#isWallpaperSupported - isWallpaperSupported()}) and whether they are allowed to change it (with the - new method WallpaperManager.isWallpaperSettingAllowed()) -

    - -

    Lock Down User Icon

    - -

    - A new user restriction (DISALLOW_SET_USER_ICON) prevents the - user from changing their user icon. The user’s device owner or profile owner - can still change the icon. However, a profile owner can only change the user - icon for the profile it controls. -

    - -

    Device Health Monitoring

    - -

    - A device owner or profile owner can use the new - HardwarePropertiesManager interface to retrieve information - about device health, such as CPU or GPU temperatures and CPU usage. The new - monitoring interface is especially useful for monitoring unattended devices - running in a remote location. -

    diff --git a/docs/html/preview/features/notification-updates.jd b/docs/html/preview/features/notification-updates.jd deleted file mode 100644 index af449cbecb5f35c801a258657fad15ed9058b230..0000000000000000000000000000000000000000 --- a/docs/html/preview/features/notification-updates.jd +++ /dev/null @@ -1,399 +0,0 @@ -page.title=Notifications -page.tags=notifications -helpoutsWidget=true -page.image=/preview/images/notifications-card.png - -trainingnavtop=true - -@jd:body - -
    -
    - - -

    This document includes

    -
      -
    1. Direct Reply
    2. -
    3. Bundled Notifications
    4. -
    5. Custom Views
    6. -
    7. Messaging Style
    8. -
    - -
    -
    - -

    Android N introduces several new APIs that allow apps to post -notifications that are highly visible and interactive.

    - -

    Android N extends the existing {@link android.support.v4.app.RemoteInput} -notification API to support inline replies on handsets. This feature allows users - to quickly respond from the notification shade without visiting your app.

    - -

    - Android N also allows you to bundle similar notifications to - appear as a single notification. To make this possible, Android N uses the existing {@link - android.support.v4.app.NotificationCompat.Builder#setGroup - NotificationCompat.Builder.setGroup()} method. Users can expand each of the - notifications, and perform actions such as reply and dismiss on each of the - notifications, individually from the notification shade. -

    - -

    Last, Android N also adds new APIs that allow you to leverage system -decorations in your app’s customized notification views. These APIs help -ensure that the notification views share a consistent presentation with -standard templates.

    - -

    This document highlights some of the key changes that you should take into - account when using the new notification features in your apps.

    - -

    Direct Reply

    - -

    With the Direct Reply feature in Android N, users can quickly -respond to text messages or update task lists directly within the notification -interface. On a handheld, the inline reply action appears as an additional button - attached to the notification. When a user replies via keyboard, the system attaches - the text response to the intent - you had specified for the notification action and sends the intent to your - handheld app. - - - -

    - Figure 1. Android N adds the Reply - action button. -

    - -

    Adding inline reply actions

    - -

    To create a notification action that supports direct reply: -

    - -
      -
    1. Create an instance of {@link android.support.v4.app.RemoteInput.Builder} - that you can add to your notification -action. This class's constructor accepts a string that the system uses as the key - for the text input. Later, your handheld app uses that key to retrieve the text - of the input. - -
      -// Key for the string that's delivered in the action's intent.
      -private static final String KEY_TEXT_REPLY = "key_text_reply";
      -String replyLabel = getResources().getString(R.string.reply_label);
      -RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
      -        .setLabel(replyLabel)
      -        .build();
      -
      -
    2. -
    3. Attach the {@link android.support.v4.app.RemoteInput} - object to an action using addRemoteInput(). - -
      -// Create the reply action and add the remote input.
      -Notification.Action action =
      -        new Notification.Action.Builder(R.drawable.ic_reply_icon,
      -                getString(R.string.label), replyPendingIntent)
      -                .addRemoteInput(remoteInput)
      -                .build();
      -
      -
    4. - -
    5. Apply the action to a notification and issue the notification. - -
      -// Build the notification and add the action.
      -Notification newMessageNotification =
      -        new Notification.Builder(mContext)
      -                .setSmallIcon(R.drawable.ic_message)
      -                .setContentTitle(getString(R.string.title))
      -                .setContentText(getString(R.string.content))
      -                .addAction(action))
      -                .build();
      -
      -// Issue the notification.
      -NotificationManager notificationManager =
      -        NotificationManager.from(mContext);
      -notificationManager.notify(notificationId, newMessageNotification);
      -
      -
      -
    6. - -
    - - -

    The system prompts the user to input a response when they trigger the -notification action.

    - - -

    - Figure 2. The user inputs text from the notification shade. -

    - -

    - Retrieving user input from the inline reply -

    - -

    - To receive user input from the notification interface to the activity you - declared in the reply action's intent: -

    - -
      -
    1. Call {@link android.support.v4.app.RemoteInput#getResultsFromIntent - getResultsFromIntent()} by passing the notification action’s intent as the - input parameter. This method returns a {@link android.os.Bundle} that - contains the text response. - -
      -Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
      -
      -
    2. - -
    3. Query the bundle using the result key (provided to the {@link - android.support.v4.app.RemoteInput.Builder} constructor). You can complete - this process and retrieve the input text by creating a method, as in the - following code snippet: - -
      -// Obtain the intent that started this activity by calling
      -// Activity.getIntent() and pass it into this method to
      -// get the associated string.
      -
      -private CharSequence getMessageText(Intent intent) {
      -    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
      -    if (remoteInput != null) {
      -        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
      -    }
      -    return null;
      - }
      -
      -
    4. - -
    5. Build and issue another notification, using the same notification ID that - you provided for the previous notification. The progress indicator - disappears from the notification interface to inform users of a successful - reply. When working with this new notification, use the context that gets - passed to the receiver's {@code onReceive()} method. - -
      -// Build a new notification, which informs the user that the system
      -// handled their interaction with the previous notification.
      -Notification repliedNotification =
      -        new Notification.Builder(context)
      -                .setSmallIcon(R.drawable.ic_message)
      -                .setContentText(getString(R.string.replied))
      -                .build();
      -
      -// Issue the new notification.
      -NotificationManager notificationManager =
      -        NotificationManager.from(context);
      -notificationManager.notify(notificationId, repliedNotification);
      -
      -
    6. -
    - -

    - For interactive apps, such as chats, it could be useful to include additional - context when handling retrieved text. For example, these apps could show - multiple lines of chat history. When the user responds via {@link - android.support.v4.app.RemoteInput}, you can update the reply history - using the {@code setRemoteInputHistory()} method. -

    - -

    - The notification must be either updated or cancelled after the app has - received remote input. When the user replies to a remote update - using Direct Reply, - do not cancel the notification. Instead, update the notification to display the user's reply. -For notifications using {@code MessagingStyle}, you should add -the reply as the latest message. When using other templates, you can -append the user's reply to the remote-input history. -

    - -

    Bundled Notifications

    - -

    Android N provides developers with a new way to represent - a queue of notifications: bundled notifications. This is similar to the - Notification - Stacks feature in Android Wear. For example, if your app creates notifications - for received messages, when more than one message is received, bundle the - notifications together as a single group. You can - use the existing {@link android.support.v4.app.NotificationCompat.Builder#setGroup -Builder.setGroup()} method to bundle similar notifications.

    - -

    - A notification group imposes a hierarchy on the notifications comprising it. - At the top of that hierarchy is a parent notification that displays summary - information for the group. The user can progressively - expand the notification group, and the system shows more information as the - user drills deeper. When the user expands the bundle, the system reveals more - information for all its child notifications; when the user - expands one of those notifications, the system reveals its entire content. -

    - - -

    - Figure 3. The user can progressively expand the notification - group. -

    - -

    - Note: If the same app sends four or more notifications - and does not specify a grouping, the - system automatically groups them together. -

    - -

    To learn how to add notifications to a group, see -Add -Each Notification to a Group.

    - - -

    Best practices for bundled notifications

    -

    This section provides guidelines about when to use notification groups instead -of the {@link android.app.Notification.InboxStyle InboxStyle} -notifications that have been available in earlier versions of the -Android platform.

    - -

    When to use bundled notifications

    - -

    You should use notification groups only if all of the following conditions are -true for your use case:

    - -
      -
    • The child notifications are complete notifications and can be displayed - individually without the need for a group summary.
    • -
    • There is a benefit to surfacing the child notifications individually. For - example: -
    • -
        -
      • They are actionable, with actions specific to each child.
      • -
      • There is more information to the child that the user wants to read.
      • -
      -
    - -

    Examples of good use cases for notification groups include: a messaging app -displaying a list of incoming messages, or an email app displaying a list of -received emails.

    - -

    -Examples of cases where a single notification is preferable - include individual messages from a single person, or a list representation of - single-line text items. You can use -({@link android.app.Notification.InboxStyle InboxStyle} or -{@link android.app.Notification.BigTextStyle BigTextStyle}) to accomplish -this. -

    - -

    Displaying bundled notifications

    - -

    - The app should always post a group summary, even if the group contains just a - single child. The system will suppress the summary and directly display the - child notification if it only contains a single notification. This ensures - that the system can provide a consistent experience when the user swipes away - children of a group. -

    - -

    - Note: This version of Android N does not yet - suppress the summary for notification groups containing a single child. This - functionality will be added in a later version of Android N. -

    - -

    Peeking notifications

    - -

    While the system usually displays child notifications as a group, you can set - them to temporarily appear as - - heads-up notifications. This feature is especially useful because it allows - immediate access to the most recent child and the actions associated with it. -

    - - -

    Backwards compatibility

    - -

    - Both notification groups and remote input have been a part of the {@link - android.app.Notification} API since Android 5.0 (API level 21) to support - Android Wear devices. If you've already built notifications with these APIs, - the only action you must take is to verify that the app behavior corresponds - to the guidelines described above, and to consider implementing {@code - setRemoteInputHistory()}. -

    - -

    - In order to support backward compatibility, the same APIs are available with - the support library's {@link android.support.v4.app.NotificationCompat} - class, allowing you to build notifications that works on earlier Android - versions. On handhelds and tablets, users only see the summary notification, - so an app should still have an inbox style or an equivalent notification - representative for the whole information content of the group. As Android - Wear devices allow users to see all child notifications even on older - platform levels, you should build child notifications regardless of API - level. -

    - -

    Custom Views

    -

    Starting from Android N, you can customize notification views and -still obtain system decorations like notification headers, actions, and -expandable layouts.

    - -

    To enable this capability, Android N adds the following APIs to style your - custom view:

    - -
    -
    -{@code DecoratedCustomViewStyle()}
    -
    Styles notifications other than media -notifications.
    -
    -{@code DecoratedMediaCustomViewStyle()}
    -
    Styles media notifications.
    -
    - -

    To use this new API, call the {@code setStyle()} method, passing to it -the desired custom view style.

    - -

    This snippet shows how to construct a custom notification object with the -{@code DecoratedCustomViewStyle()} method.

    - -
    -Notification notification = new Notification.Builder()
    -           .setSmallIcon(R.drawable.ic_stat_player)
    -           .setLargeIcon(albumArtBitmap))
    -           .setCustomContentView(contentView);
    -           .setStyle(new Notification.DecoratedCustomViewStyle())
    -           .build();
    -
    -
    - -

    Messaging Style

    -

    - Android N introduces a new API for customizing the style of a notification. - Using the MessagingStyle class, you can change several of the - labels displayed on the notification, including the conversation title, - additional messages, and the content view for the notification. -

    - -

    - The following code snippet demonstrates how to customize a notification's - style using the MessagingStyle class. -

    - -
    -  Notification notification = new Notification.Builder()
    -             .setStyle(new Notification.MessagingStyle("Me")
    -                 .setConversationTitle("Team lunch")
    -                 .addMessage("Hi", timestamp1, null) // Pass in null for user.
    -                 .addMessage("What's up?", timestamp2, "Coworker")
    -                 .addMessage("Not much", timestamp3, null)
    -                 .addMessage("How about lunch?", timestamp4, "Coworker"));
    -
    diff --git a/docs/html/preview/features/tv-recording-api.jd b/docs/html/preview/features/tv-recording-api.jd deleted file mode 100644 index 6619821d7fe9ff40e7f7fc0d840aef4b1f7a125d..0000000000000000000000000000000000000000 --- a/docs/html/preview/features/tv-recording-api.jd +++ /dev/null @@ -1,142 +0,0 @@ -page.title=TV Recording -page.keywords=preview,sdk,tv,recording -page.tags=androidn -page.image=images/cards/card-nyc_2x.jpg - -@jd:body - - - -

    TV input services let the user pause and resume channel playback via -time-shifting APIs. Android N expands on time-shifting -by letting the user save multiple recorded sessions.

    - -

    Users can schedule recordings in advance, or start a recording as they watch -a program. Once the system has saved a recording, the user can browse, manage, -and play back the recording using the system TV app.

    - -

    If you want to provide recording functionality for your TV input service, -you must indicate to the system that your app supports recording, implement -the ability to record programs, handle and communicate any errors that occur -during recording, and manage your recorded sessions.

    - -

    Note: The Live Channels app does not yet -provide a way for users to create or access recordings. Until changes are -made to the Live Channels app, it may be difficult to fully test the recording -experience for your TV input service.

    - -

    Indicating Support for Recording

    - -

    To tell the system that your TV input service supports recording, set -the android:canRecord attribute in your service metadata XML file -to true: -

    - -
    -<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
    -  android:canRecord="true"
    -  android:setupActivity="com.example.sampletvinput.SampleTvInputSetupActivity" />
    -
    - -

    For more information on the service metadata file, see -Declare Your TV Input -Service in the Manifest. -

    - -

    Alternatively, you can indicate recording support in your code using -these steps:

    - -
      -
    1. In your TvInputService.onCreate() method, create a new -TvInputInfo object using the TvInputInfo.Builder -class.
    2. -
    3. When creating the new TvInputInfo object, call -setCanRecord(true) before calling build() to -indicate your service supports recording.
    4. -
    5. Register your TvInputInfo object with the system by calling -TvInputManager.updateTvInputInfo().
    6. -
    - -

    Recording a Session

    - -

    After your TV input service registers that it supports recording -functionality, the system calls your -TvInputService.onCreateRecordingSession() when it needs to access -your app's recording implementation. Implement your own -TvInputService.RecordingSession subclass and return it -when the onCreateRecordingSession() callback -fires. This subclass is responsible for switching to the correct channel data, -recording the requested data, and communicating recording status and errors to -the system.

    - -

    When the system calls RecordingSession.onTune(), passing in a -channel URI, tune to the channel that the URI specifies. Notify the system that -your app has tuned to the desired channel by calling notifyTuned(), -or, if your app could not tune to the proper channel, call -notifyError().

    - -

    The system next invokes the RecordingSession.onStartRecording() -callback. Your app must start recording immediately. When the system invokes -this callback, it may provide a URI that contains information about the program -that is about to be recorded. When the recording is done, you need to copy this -data to the RecordedPrograms data table.

    - -

    Finally, the system calls RecordingSession.onStopRecording(). -At this point, your app must stop recording immediately. You also need to -create an entry in the RecordedPrograms table. This entry should -include the recorded session data URI in the -RecordedPrograms.COLUMN_RECORDING_DATA_URI column, and any program -information that the system provided in the initial call to -onStartRecording().

    - -

    For more details on how to access the RecordedPrograms table -see Managing Recorded Sessions.

    - -

    Handling Recording Errors

    - -

    If an error occurs during recording, rendering the recorded data unusable, -notify the system by calling RecordingSession.notifyError(). -Similarly, you can call notifyError() after a recording session is -created to let the system know that your app can no longer record sessions.

    - -

    If an error occurs during recording, but you'd like to provide a usable -partial recording to users for playback, call -RecordingSession.notifyRecordingStopped() to enable the system to -use the partial session.

    - -

    Managing Recorded Sessions

    - -

    The system maintains information for all recorded sessions from all -recording-capable channel apps in the TvContract.RecordedPrograms -content provider table. This information is accessible via the -RecordedPrograms.Uri content URI. Use content provider APIs to -read, add, and delete entries from this table.

    - -

    For more information on working with content provider data see - -Content Provider Basics .

    - -

    Best Practices

    - -

    TV devices may have limited storage, so use your best judgment when -allocating storage to save recorded sessions. Use -RecordingCallback.onError(RECORDING_ERROR_INSUFFICIENT_SPACE) when -there isn't enough space to save a recorded session.

    - -

    When the user initiates recording, you should start recording data as soon -as possible. To facilitate this, complete any up-front time-consuming tasks, -like accessing and allocating storage space, when the system invokes the -onCreateRecordingSession() callback. Doing so lets you start -recording immediately when the onStartRecording() callback -fires.

    diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.jd deleted file mode 100644 index 9c92fb271e343e574bc805b443fae471026ce65d..0000000000000000000000000000000000000000 --- a/docs/html/preview/index.jd +++ /dev/null @@ -1,133 +0,0 @@ -page.title=Android N Developer Preview -page.tags="preview","developer" -meta.tags="preview", "android" -fullpage=true -forcelocalnav=true -header.hide=1 -footer.hide=1 -@jd:body - - - -
    -
    -
    - -
    -

    Android N Developer Preview

    -

    - Android N final SDK is now available! - Get ready for Android N! - Test your apps on Nexus and other devices. Support new system - behaviors to save power and memory. - Extend your apps with multi-window UI, - direct reply notifications and more. -

    - - - - Get started - -
    -
    - -
    -
    -
    -
    -
    -
    -
    - - - - - -
    -

    Latest

    -
    -
    - -
    -

    Resources

    -
    - Essential information to help you get your apps ready for Android N. -
    - -
    - -
    -
    - diff --git a/docs/html/preview/license.jd b/docs/html/preview/license.jd deleted file mode 100644 index ae02aae58a192fca9a2466d9e2d924305449c080..0000000000000000000000000000000000000000 --- a/docs/html/preview/license.jd +++ /dev/null @@ -1,145 +0,0 @@ -page.title=License Agreement - -@jd:body - -

    -To get started with the Android SDK Preview, you must agree to the following terms and conditions. -As described below, please note that this is a preview version of the Android SDK, subject to change, that you use at your own risk. The Android SDK Preview is not a stable release, and may contain errors and defects that can result in serious damage to your computer systems, devices and data. -

    - -

    -This is the Android SDK Preview License Agreement (the “License Agreement”). -

    -
    -1. Introduction - -1.1 The Android SDK Preview (referred to in the License Agreement as the “Preview” and specifically including the Android system files, packaged APIs, and Preview library files, if and when they are made available) 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 Preview. - -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 “Android-compatible” means any Android implemation 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. - -2. Accepting the License Agreement - -2.1 In order to use the Preview, you must first agree to the License Agreement. You may not use the Preview if you do not accept the License Agreement. - -2.2 By clicking to accept and/or using the Preview, you hereby agree to the terms of the License Agreement. - -2.3 You may not use the Preview and may not accept the License Agreement if you are a person barred from receiving the Preview under the laws of the United States or other countries including the country in which you are resident or from which you use the Preview. - -2.4 If you will use the Preview internally within your company or organization you agree to be bound by the License Agreement on behalf of your employer or other entity, and 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 Preview on behalf of your employer or other entity. - -3. Preview License from Google - -3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable, non-exclusive, and non-sublicensable license to use the Preview solely to develop applications for compatible implementations of Android. - -3.2 You may not use this Preview 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 Preview is not used for that purpose. - -3.3 You agree that Google or third parties owns all legal right, title and interest in and to the Preview, including any Intellectual Property Rights that subsist in the Preview. "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 Preview 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 Preview or any part of the Preview; or (b) load any part of the Preview onto a mobile handset or any other hardware device except a personal computer, combine any part of the Preview with other software, or distribute any software or device incorporating a part of the Preview. - -3.5 Use, reproduction and distribution of components of the Preview licensed under an open source software license are governed solely by the terms of that open source software license and not the License Agreement. You agree to remain a licensee in good standing in regard to such open source software licenses under all the rights granted and to refrain from any actions that may terminate, suspend, or breach such rights. - -3.6 You agree that the form and nature of the Preview that Google provides may change without prior notice to you and that future versions of the Preview may be incompatible with applications developed on previous versions of the Preview. You agree that Google may stop (permanently or temporarily) providing the Preview (or any features within the Preview) 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 Preview. - -4. Use of the Preview by You - -4.1 Google agrees that nothing in the License Agreement gives Google any right, title or interest from you (or your licensors) under the License Agreement in or to any software applications that you develop using the Preview, including any intellectual property rights that subsist in those applications. - -4.2 You agree to use the Preview 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 Preview to develop applications, you will protect the privacy and legal rights of users. If 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 users provide you 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, each user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the Preview, 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 Google or any third party. - -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. - -4.7 The Preview is in development, and your testing and feedback are an important part of the development process. By using the Preview, you acknowledge that implementation of some features are still under development and that you should not rely on the Preview having the full functionality of a stable release. You agree not to publicly distribute or ship any application using this Preview as this Preview will no longer be supported after the official Android SDK is released. - -5. Your Developer Credentials - -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. - -6. Privacy and Information - -6.1 In order to continually innovate and improve the Preview, 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 Preview are being used and how they are being used. Before any of this information is collected, the Preview 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 Preview and is maintained in accordance with Google's Privacy Policy located at http://www.google.com/policies/privacy/. - -7. Third Party Applications - -7.1 If you use the Preview 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. - -8. Using Google APIs - -8.1 Google 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. - -9. Terminating the License Agreement - -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 Preview and any relevant developer credentials. - -9.3 Google may at any time, terminate the License Agreement, with or without cause, upon notice to you. - -9.4 The License Agreement will automatically terminate without notice or other action upon the earlier of: -(A) when Google ceases to provide the Preview or certain parts of the Preview to users in the country in which you are resident or from which you use the service; and -(B) Google issues a final release version of the Android SDK. - -9.5 When the License Agreement is terminated, the license granted to you in the License Agreement will terminate, you will immediately cease all use of the Preview, and the provisions of paragraphs 10, 11, 12 and 14 shall survive indefinitely. - -10. DISCLAIMERS - -10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE PREVIEW IS AT YOUR SOLE RISK AND THAT THE PREVIEW IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE. - -10.2 YOUR USE OF THE PREVIEW AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE PREVIEW 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. WITHOUT LIMITING THE FOREGOING, YOU UNDERSTAND THAT THE PREVIEW IS NOT A STABLE RELEASE AND MAY CONTAIN ERRORS, DEFECTS AND SECURITY VULNERABILITIES THAT CAN RESULT IN SIGNIFICANT DAMAGE, INCLUDING THE COMPLETE, IRRECOVERABLE LOSS OF USE OF YOUR COMPUTER SYSTEM OR OTHER DEVICE. - -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. - -11. LIMITATION OF LIABILITY - -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. - -12. Indemnification - -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 Preview, (b) any application you develop on the Preview that infringes any Intellectual Property Rights of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you of the License Agreement. - -13. Changes to the License Agreement - -13.1 Google may make changes to the License Agreement as it distributes new versions of the Preview. When these changes are made, Google will make a new version of the License Agreement available on the website where the Preview is made available. - -14. General Legal Terms - -14.1 the License Agreement constitutes the whole legal agreement between you and Google and governs your use of the Preview (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 Preview. - -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 PREVIEW 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 PREVIEW. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE. - -14.6 The License Agreement may not be assigned or transferred by you without the prior written approval of Google, and any attempted assignment without such approval will be void. You shall not delegate your responsibilities or obligations under the License Agreement without the prior written approval of Google. - -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. - - -
    \ No newline at end of file diff --git a/docs/html/preview/overview.jd b/docs/html/preview/overview.jd deleted file mode 100644 index faf48b8685fa7f7b0aa751aebdeabfc6045708e7..0000000000000000000000000000000000000000 --- a/docs/html/preview/overview.jd +++ /dev/null @@ -1,448 +0,0 @@ -page.title=Program Overview -page.metaDescription=Get your apps ready for the next version of Android. -page.image=images/cards/card-n-overview_2x.png -meta.tags="preview", "developer", "android" -page.tags="preview", "developer", "android" - -@jd:body - - - -

    - Welcome to the Android N Developer Preview, a program that - gives you everything you need to test and optimize your apps for the next - version of Android. It's free, and you can get started right away just by - downloading the N Developer Preview tools. -

    - - - - - - - -
    -
    -
    -
    -
    - Hardware and emulator images -
    - -

    - Run and test your apps on a range of devices or on an emulator. - -

    -
    - -
    -
    - Latest platform code -
    - -

    - We’ll provide monthly updates during the Preview, so you’ll be testing against the latest platform changes. -

    -
    - -
    -
    - Priority for developer issues -
    - -

    - During the first several weeks we’ll give priority to developer-reported - issues, so test and give feedback as soon as possible. -

    -
    - -
    - -
    - - -
    -
    - New behaviors and capabilities -
    - -

    - Start work early to support new platform behaviors and develop with new features. -

    -
    - -
    -
    - Updates delivered by OTA -
    - -

    - Seamless over-the-air updates for any supported device through the - Android Beta Program. No flashing is needed. -

    -
    - -
    -
    - Feedback and support -
    - -

    - Report issues and give us feedback using our - issue tracker. Connect with other - developers in the - N Developer Community. -

    -
    -
    -
    -
    - - - -

    Timeline and updates

    - -

    - The N Developer Preview runs from 9 March 2016 until the final Android N - public release to AOSP and OEMs, planned for Q3 2016. -

    - - - -

    - At key development milestones, we’ll deliver updates for your development and - testing environment. In general you can expect an update each month (4 to 6 - week interval). The milestones are listed below. -

    - -
      -
    • Preview 1 (initial release, alpha)
    • -
    • Preview 2 (incremental update, alpha)
    • -
    • Preview 3 (incremental update, beta)
    • -
    • Preview 4 (final APIs and official SDK, Play publishing)
    • -
    • Preview 5 (near-final system images for final testing)
    • -
    • Final release to AOSP and ecosystem
    • -
    - -

    - Each update includes SDK tools, preview system images, emulators, reference - documentation, and API diffs. -

    - -

    - The first three preview milestones provide an early - test and development environment that help you identify - compatibility issues in your current apps and plan migration or feature work - needed to target the new platform. This is the priority period in which to - give us your feedback on features and APIs and file compatibility issues - — for all of these, please use the issue - tracker. You can expect some API changes across these updates. -

    - -

    - At previews 4 and 5 you’ll have access to the final - N APIs and SDK to develop with, as well as near-final system images - to test system behaviors and features. Android N will provide a standard API - level at this time. You can begin final compatibility testing of your legacy - apps and refine any new code that is using the N APIs or features. -

    - -

    - Also starting in preview 4, you’ll be able to publish apps to - devices running Android N at the official API level, such as - consumer devices that have opted into the Android Beta program. You can - publish into the Google Play alpha and beta channels first, so you can test - your apps with Android Beta consumers before distributing broadly on the - store. -

    - -

    - As you test and develop on Android N, we strongly recommend keeping - your development environment up-to-date as preview updates are - released. To make the process easier, you can enroll your test devices in the - Android Beta program and get updates over-the-air (OTA) at - each milestone. Alternatively, updated preview images are available that you - download and flash manually. -

    - -

    - We’ll notify you when preview updates are available via the Android Developers Blog, as - well as this site and the Android - N Developer Community. -

    - - -

    What's in the N Developer Preview?

    - -

    - The N Developer Preview includes everything you need to test your existing - apps on a variety of screen sizes, network technologies, CPU/GPU chipsets, - and hardware architectures. -

    - -

    SDK tools

    - -

    You can download these components through the SDK Manager in Android Studio:

    - -
      -
    • N Developer Preview SDK and tools -
    • N Developer Preview emulator system image (32-bit & 64-bit) -
    • N Developer Preview emulator system Image for Android TV (32-bit) -
    • N Developer Preview support libraries (for new app templates) -
    - -

    - We’ll provide updates to these development tools at each milestone as needed. -

    - -

    Hardware system images

    - -

    - The N Developer Preview includes Nexus and other hardware system images that you can use when - testing and developing on physical devices. See the Device Images page for the full list - of hardware images. -

    - -

    - We’ll deliver updated system images for these devices at each milestone. You - can download and flash the updated system images to your test devices - manually, as frequently as you need. This is especially useful for automated - testing environments where you might need to reflash your device multiple - times. -

    - -

    Note: - Devices flashed manually will not get OTA updates like in - last year’s preview. This year, you can get OTAs by enrolling devices in the - Android Beta Program — see details in the next section. -

    - -

    OTA Updates through Android Beta Program

    - -

    - New for Android N is an Over-the-Air (OTA) update program that automatically - delivers the latest preview updates of Android N directly to devices enrolled - in the program. The program is free, and it’s open to anyone who has a - supported device that’s registered to their Google account. -

    - -

    - To enroll in the program visit the Android - Beta Program site. You’ll - see all of the devices registered to your account that are eligible to enroll - in Android Beta. -

    - -
      -
    1. Choose the devices you want to receive the Android N updates -
    2. Click Enroll, read and agree to the terms of service, and then click OK -
    - -

    - Once you’ve enrolled, your device will soon receive an update. In most cases, - you will not need to do a full reset of your data to move to Android N, but - it’s recommended that you back up any data you don’t want to lose before - enrolling the device. -

    - -

    - As updates are delivered to your device, we recommend downloading and - installing them as soon as possible. You’ll want to stay current with the - latest changes in system UI, behavior, APIs, and features. -

    - -

    - At the conclusion of the Developer Preview, your enrolled devices will - receive an update to the official Android N release. -

    - -

    - You can un-enroll your devices from the Android Beta program at any time from - the Android Beta site. Before un-enrolling, make sure to back-up your data on - the device. -

    - -

    Note: - When you un-enroll, your device will be factory reset - to the latest version - of Android 6.0 Marshmallow (not necessarily the version that you had - installed prior to enrolling the device). To ensure a clean installation, - your data will be erased from the device, including contacts, messages, - photos, and so on. -

    - -

    Documentation and sample code

    - -

    - These documentation resources are available on the Developer Preview site to - help you learn about the Android N: -

    - -
      -
    • Set Up to Develop for -Android N has - step-by-step instructions for getting started.
    • -
    • Behavior - Changes points you to key areas to test.
    • -
    • Documentation of new APIs, including an API Overview, downloadable - API - Reference, and detailed developer guides on key features such as - multi-window support, bundled notifications, multi-locale support, and others. -
    • Sample code that - demonstrates how to support permissions and other new features. -
    • Release notes - for the current version of the N Developer Preview, including change notes and - diff reports. -
    - -

    Downloadable API Reference

    - -

    - During the early preview updates, you can download the latest - API Reference - for the Android N platform as a separate zip archive. The reference - download also includes a diff report that helps you identify API changes from - API 23 and the previous update. -

    - -

    - When the Android N APIs are final and an official API level is assigned, - we’ll provide the API reference to you online at https://developer.android.com. -

    - -

    - Support resources -

    - -

    - As you test and develop on the N Developer Preview, please use these channels - to report issues and give feedback. -

    - -
      -
    • N Developer Preview Issue - Tracker is your primary feedback channel. You can report bugs, performance - issues, and general feedback through the issue tracker. You can also check for -known issues and - find workaround steps. We’ll keep you updated on your issue as it’s triaged and sent to - the Android engineering team for review.
    • -
    • The Android N Developer Community is - a Google+ community where you can connect with other developersworking with - Android N. You can share observations or ideas or find answers to - questions about Android N. We’ll moderate the community and provide answers and - guidance as needed.
    • -
    - -

    Targeting, preview APIs, and publishing

    - -

    - The N Developer Preview provides a development-only system and Android - library that does not have a standard API level. If you want - to opt out of compatibility behaviors to test your app (which is strongly - recommended), you can target the preview version of Android N by setting your - app's targetSdkVersion - to “N”. -

    - -

    - The Android N Developer Preview delivers preview APIs - — the APIs will not be official until the final SDK is released, - currently planned for the third quarter of 2016. This means that you can - expect minor API changes over time, especially during - initial weeks of the program. We’ll provide a summary of changes to you with - each update of the Android N Developer Preview. -

    - -

    - Note: Although preview APIs may change, underlying - system behaviors are stable and ready for testing against - right away. -

    - -

    - Google Play prevents publishing of apps targeting the N Developer - Preview. When the Android N final SDK is available, you’ll be able - to target the official Android N API level and publish your app to Google - Play via the alpha and beta release channels. Meanwhile, if you want to - distribute an app targeting Android N to testers, you can do so via email or - by direct download from your site. -

    - -

    - At the full release of Android N to AOSP and OEMs, planned for Q3 2016, - you’ll be able to publish your apps targeting Android N to the public release - channel in Google Play. -

    - - -

    How to get started

    - -

    - To get started testing your app with Android N: -

    - -
      -
    1. Review the API Overview - and Behavior Changes to - get an idea of what's new and how it affects your apps. In particular, - learn about the new notifications features and - multi-window support.
    2. -
    3. Set up your environment by following the instructions for Setting up the Preview SDK - and configuring test devices.
    4. -
    5. Follow the flashing - instructions to flash the latest Android N system image for your device.
    6. -
    7. Review the API Reference - and Android N samples to gain more - insight into new API features and how to use them in your app. -
    8. Join the Android N - Developer Community to get the latest news and connect with other - developers working with the new platform.
    9. -
    - -

    - Thank you for your participation in the Android N Developer Preview program! -

    diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs deleted file mode 100644 index 34d00a400ef146069efbb7a069b2cbf82a3f58a2..0000000000000000000000000000000000000000 --- a/docs/html/preview/preview_toc.cs +++ /dev/null @@ -1,235 +0,0 @@ - diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd deleted file mode 100644 index 3e95f3e864c0d959df55d32e7d137c3b8dca4c82..0000000000000000000000000000000000000000 --- a/docs/html/preview/setup-sdk.jd +++ /dev/null @@ -1,197 +0,0 @@ -page.title=Set Up the Preview -meta.keywords="preview", "android" -page.tags="preview", "developer preview" -page.image=images/cards/card-n-sdk_2x.png - -@jd:body - - - - -

    To develop apps for the Android N Preview, you need to make some updates -to your developer environment, as described on this page.

    - -

    To simply test your app's compatibility on the -Android N system image, follow the guide to Test on an Android N Device.

    - - - - -

    Get Android Studio 2.1

    - -

    The Android N platform adds support for Java 8 language features, -which require a new compiler called Jack. The latest version of Jack -is currently supported only in Android Studio 2.1. So if you want to -use Java 8 language features, you need to use Android Studio 2.1 to -build your app. Otherwise, you don't need to use the Jack compiler, but you -still need to update to JDK 8 to compile against the Android N platform, -as described below.

    - -

    If you already have Android Studio installed, make sure you have Android -Studio 2.1 or higher by clicking Help > Check for Update -(on Mac, Android Studio > Check for Updates).

    - -

    If you don't have it, download Android Studio -2.1 here.

    - - -

    Get the N Preview SDK

    - -

    To start developing with Android N APIs, you need to install the -Android N Preview SDK in Android Studio as follows:

    - -
      -
    1. Open the SDK Manager by clicking Tools > Android > - SDK Manager.
    2. - -
    3. In the SDK Platforms tab, select the - Android N Preview check box.
    4. - -
    5. Click the SDK Tools tab, then select the - Android SDK Build Tools, Android SDK - Platform-Tools, and Android SDK Tools check - boxes. -
    6. - -
    7. Click OK, then accept the licensing - agreements for any packages that need to be installed. -
    8. -
    - -

    Get the N Preview reference documentation

    - -

    Beginning with the Preview 4 release, the API reference for the -N platform (API level 24) is now available online at developer.android.com/reference/. -

    - -

    If you'd like an offline copy of the API reference, you can download it -from the following table. The download also includes an incremental diff report -for API changes between the Preview 3 and Preview 4 release, which is not -available online.

    - - - - - - - - - - -
    DocumentationChecksums
    - n-preview-4-docs.zip - MD5: f853e3ba0707083336dfa780b8fed9a7
    - SHA-1: 36fcbc497cc2e63b1bc1d629c304b0ba43a88946 -
    - - - -

    Get the Java 8 JDK

    - -

    To compile your app against the Android N platform and use some tools with -Android Studio 2.1, you need to install the Java 8 Developer Kit (JDK 8). So, if -you don't already have the latest version, download JDK 8 now.

    - -

    Then set the JDK version in Android Studio as follows:

    - -
      -
    1. Open an Android project in Android Studio, then open the - Project Structure dialog by selecting File > - Project Structure. (Alternatively, you can set the default - for all projects by selecting File > Other Settings > - Default Project Structure.) -
    2. -
    3. In the left panel of the dialog, click SDK Location. -
    4. -
    5. In the JDK Location field, enter the location of the - Java 8 JDK (click the button on the right - to browse your files), then click OK. -
    6. -
    - - - - -

    Update or Create a Project

    - -

    Now that the N platform API level is "24" instead -of "N", you can configure your projects normally with this API level (and even -publish your apps compiled with API 24 on Google Play). Just be sure that you've -updated your project to use Android SDK Build Tools 24.0.0 and -Android SDK Platform-Tools 24.0.0.

    - -

    If you plan to use Java 8 language features, you should also read -Java 8 Language Features -for information about the supported Java 8 features and -how to configure your project with the Jack compiler.

    - - -

    Update an existing project

    - -

    Open the - build.gradle file for your module and update the values as - follows: -

    - -
    -android {
    -  compileSdkVersion 24
    -  buildToolsVersion '24.0.0'
    -  ...
    -
    -  defaultConfig {
    -     targetSdkVersion 24
    -     ...
    -  }
    -  ...
    -}
    - -

    Now that the API level 24 is final, you can compile against it and keep your -minSdkVersion to whatever version is appropriate for your app.

    - - -

    Create a new project

    - - -

    To create a new project for development with the Android N Preview SDK:

    - -
      -
    1. Click File > New Project. and follow the steps until - you reach the Target Android Devices page. -
    2. -
    3. On this page, select the Phone and Tablet check box.
    4. -
    5. Under Phone and Tablet option, in the Minimum - SDK option list, select - API 24: Android 6.X (N Preview).
    6. -
    - - -

    Next Steps

    - - diff --git a/docs/html/preview/support.jd b/docs/html/preview/support.jd deleted file mode 100644 index ef8a65293d477586eb7e7b204edfb783ae21d71a..0000000000000000000000000000000000000000 --- a/docs/html/preview/support.jd +++ /dev/null @@ -1,1513 +0,0 @@ -page.title=Support and Release Notes -meta.keywords="preview", "android" -page.tags="preview", "developer preview" -page.image=images/cards/card-n-support_2x.png - -@jd:body - - - - -

    - Two primary support channels are available to you when developing and testing - with the Android N Developer Preview: Please file bugs at https://developer.android.com/preview/bug for - device-specific, system, and Google App bugs. For issues in other apps, - please contact the developer directly. -

    - -

    - To discuss issues or ideas with other developers working with Android N, join - the Developer Preview Google+ - community. -

    - -

    Developer Preview 4

    - -
    -
    -
    -

    - Date: June 2016
    - Build: NPD56N
    - Emulator support: x86 & ARM (32/64-bit)
    - Google Play services: 8.4
    -

    -
    -
    -
    - -

    General advisories

    - -

    - This Developer Preview release is for app developers and other early - adopters and is available for daily use, development, or - compatibility testing. Please be aware of these general notes about the - release: -

    - -
      -
    • This release may have various stability issues on - supported devices. -
    • - -
    • Some apps may not function as expected on the new - platform version. This includes Google’s apps as well as other apps. -
    • - -
    • Developer Preview 4 is Compatibility Test Suite (CTS) - approved on these devices: Nexus 5X, Nexus 6, Nexus 6P, and - Pixel C. Apps that depend on CTS approved builds should work normally - on these devices (Android Pay for example). -
    • - -
    • Developer Preview 4 is available on all supported - devices: Nexus 5X, Nexus 6, Nexus 6P, Nexus 9, Nexus Player, - Pixel C, General Mobile 4G (Android One), as well as Sony Xperia Z3 - (D6603 and D6653 models). -
    • -
    - - -

    New in DP4

    - -

    Android N final APIs

    - -

    - Developer Preview 4 includes the final APIs for the upcoming - Android N platform. The new API level is 24. -

    - -

    Play publishing

    - -

    - You can now publish apps that use API level 24 to Google - Play, in alpha, beta, and production release channels. -

    - -

    Android Studio and tools updates

    - -

    - Along with Developer Preview 4 we’re providing the final API 24 - SDK to be used with Android Studio 2.1.2 and higher. In addition, - we’re releasing updated Developer Preview 4 system images for the emulator to - help test your apps. -

    - -

    - As new updates roll out for Android Studio, you should see minor improvements in - the new project wizards and AVD manager as we add enhanced support for API 24. - These are primarily cosmetic changes and should not stop you from getting - your app ready for an update in the Play store. -

    - -

    Feature and API changes

    - -
      -
    • In previous versions of Android, an app activates with all of its locale - resources loaded before locale negotiation begins. Starting in Android N DP4, - the system negotiates resource locales individually for each resource object - before the app activates. -
    • - -
    • As announced at Developer Preview 3, we’ve deferred the Launcher - Shortcuts feature to a later release of Android. In Developer Preview 4, - we’ve removed the Launcher Shortcuts APIs. -
    • - -
    • We’ve changed the BLE Scanning behavior starting in DP4. We’ll prevent - applications from starting and stopping scans more than 5 times in 30 - seconds. For long running scans, we’ll convert them into opportunistic scans. -
    • - -
    • The Multi-Window - android:minimalHeight and android:minimalWidth - attributes have been renamed to android:minHeight and - android:minWidth. -
    • -
    - -

    Known Issues

    - -

    Stability

    - -
      -
    • Users may encounter system instability (such as kernel panics and - crashes). -
    • -
    - -

    Launcher

    - -
      -
    • The default launcher’s All Apps tray may become - unresponsive after cycling the screen off and on. Returning to the - homescreen and relaunching the All Apps tray may resolve - this issue. -
    • -
    - -

    Setup Wizard

    - -
      -
    • Crash on selecting "Not now" in "Set up email" screen. -
    • -
    - -

    Media

    - -
      -
    • Media playback may be unreliable on Nexus 9 and Nexus Player, including - issues playing HD video. -
    • - -
    • Occasional freeze when running the YouTube app with other apps in - multi-window mode on Pixel C devices. In some cases hard reboot is required. -
    • - -
    • Apps may have issues playing some Widevine DRM-protected content on Nexus - 9 devices. -
    • - -
    • Issues handling VP8 video on Nexus 9 devices. -
    • -
    - -

    External storage

    - -
      -
    • Apps may become unstable when the user moves them from internal storage - to adoptable external storage (this can include SD card or devices attached - over USB). -
    • -
    - -

    Screen zoom and multiple APKs in Google Play

    - -
      -
    • On devices running Android N, Google Play services 9.0.83 incorrectly - reports the current screen density rather than the stable screen density. - When screen zoom is enabled on these devices, this can cause Google Play to - select a version of a multi-APK app that’s designed for smaller screens. This - issue is fixed in the next version of Google Play services and will be - included in a later Developer Preview release. -
    • -
    - -

    Vulkan support and multiple APKs in Google Play

    - -
      -
    • On devices running Android N, Google Play services 9.0.83 currently - reports Vulkan support but not Vulkan version. This can cause Google Play to - select a version of a multi-APK app that’s designed for lower Vulkan support - on devices with higher version support. Currently, the Google Play Store does - not accept uploads of apps which use Vulkan version targeting. This support - will be added to the Google Play Store in the future and fixed in the next - version of Google Play services (to be included in a later Developer Preview - release). Any N devices using the version of Google Play services 9.0.83 will - continue to receive versions of apps targeting basic Vulkan support. -
    • -
    - -

    Accessibility

    -
      -
    • Switch access doesn't allow user to navigate web pages in Chrome. -
    • - -
    • Accessibility issues for talkback users with notification dismissal, and - wifi selection screen. -
    • -
    - -

    Android for Work

    - -
      -
    • Currently, CA certificates provisioned through {@link - android.app.admin.DevicePolicyManager} are not - available to profiles other than the primary user/profile due to a preload - issue. For example, this could prevent a user from connecting to a trusted - server when in a Work profile. This issue will be resolved in the next - Developer Preview. -
    • - -
    • After reboot with work mode off, solving work challenge does not switch - on work mode. -
    • - -
    • Users receiving a video call in Hangouts have to unlock work challenge - first. -
    • - -
    • Accessing Settings > Security > Device Security crash observed when - separating primary and work challenge. -
    • - -
    • If {@link android.os.UserManager#DISALLOW_CONFIG_VPN} is set before - calling {@link android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage - DevicePolicyManager.setAlwaysOnVpnPackage()}, then setting always on VPN does - not work. That is, after rebooting the device with the {@link - android.os.UserManager#DISALLOW_CONFIG_VPN} restriction set, VPN is not - autostarted. -
    • -
    - -

    Android Auto

    - -

    - The version of Google Maps included in Developer Preview 4 (9.30) crashes - when used with Android Auto. This issue will be fixed in the next update to - Google Maps (9.31), expected in the coming weeks. -

    - - - - - -

    Fixes for issues reported by developers

    - -

    - A number of issues reported by developers have been fixed, including: -

    - -
      -
    • The active network state ({@link android.net.NetworkInfo#getState - NetworkInfo.getState()} and {@link android.net.NetworkInfo#getDetailedState - NetworkInfo.getDetailedState()}) might return incorrect values during some - restricted background scenarios -
    • - -
    • Data Saver restricts the foreground MMS mobile network request - (bug - 208478) -
    • - -
    • Quick settings tiles and notifications sometimes unresponsive -
    • - -
    • Unable to dismiss Clock notifications -
    • - -
    • Duplication of bluetooth icon and other status icons -
    • - -
    • Additional bluetooth connectivity fixes -
    • - -
    - -

    For the full list of fixed issues, see the -issue tracker.

    - -

    Notes on publishing apps that target API 24

    - -

    - Before publishing apps that target API 24 in Google Play, keep these points - in mind: -

    - -
      -
    • If your app’s current targetSdkVersion is 22 or lower and - you want to target API 24, you’ll need to support behaviors - introduced with Android 6.0 (Marshmallow), such as runtime permissions, in - addition to Android N behaviors. -
    • - -
    • Once you publish an app with targetSdkVersion set to 23 or - higher, you can't later publish a version of the app with a higher - versionCode that targets 22 or lower. This restriction applies - in alpha and beta channels as well as production channel. -
    • -
    - - - -

    Developer Preview 3

    - -
    -
    -
    -

    - Date: May 2016
    - Build: NPD35K
    - Emulator support: x86 & ARM (32/64-bit)
    - Google Play services: 8.4
    -

    -
    -
    -
    - -

    General advisories

    - -

    - This Developer Preview release is for app developers and other early - adopters and is available for daily use, development, or - compatibility testing. Please be aware of these general notes about the - release: -

    - -
      -
    • This release may have various stability issues on - supported devices. Users may encounter system instability, such as kernel - panics and crashes. -
    • - -
    • Some apps may not function as expected on the new - platform version. This includes Google’s apps as well as other apps. -
    • - -
    • Developer Preview 3 is Compatibility Test Suite (CTS) - approved on these devices: Nexus 5X, Nexus 6, Nexus 6P, and Pixel - C. Apps that depend on CTS approved builds should - work normally on these devices (Android Pay for example). -
    • - -
    • Developer Preview 3 is available on all supported - devices: Nexus 5X, Nexus 6, Nexus 6P, Nexus 9, Nexus Player, Pixel - C, General Mobile 4G (Android One), as well as Sony Xperia Z3 (D6603 and - D6653 models). - -
    • -
    - - -

    New in DP3

    - -

    VR Mode for Android

    - -

    - Android N adds platform support and optimizations for a new VR Mode to let - developers build high quality mobile VR experiences for users. There are a - number of performance enhancements, including access to an exclusive CPU core - for VR apps. Within your apps, you can take advantage of intelligent - head-tracking, and stereo notifications that work for VR. Most importantly, - Android N provides for very low latency graphics. -

    - -

    - For more information, see the Google VR SDK for Android. -

    - -

    Sustained performance mode

    - -

    - Android N includes optional support for sustained - performance mode, enabling OEMs to provide hints on device performance - capabilities for long running applications. App developers can then use these - hints to tune applications for a predictable, consistent level of device - performance over long periods of time. App developers can try out this new - API in the developer preview on Nexus 6P devices only. -

    - -

    Multiprocess WebView

    - -

    - Starting with version 51 in Android N, WebView will run web content in a - separate sandboxed process when the developer option "Multiprocess WebView" - is enabled. The WebView team is looking for feedback on compatibility and - runtime performance in N before enabling multiprocess WebView in a future - version of Android. In this version, regressions in startup time, total - memory usage and software rendering performance are expected. -

    - -

    - If you find unexpected issues in multiprocess mode we’d like to hear about - them. Please get in touch with the WebView team by - filing a bug. -

    - -

    Keyboard Shortcuts helper

    - -

    - Android N lets users press Meta+/ to trigger a Keyboard - Shortcuts screen that displays all shortcuts available both from the - system and from the app in focus. Developers can add their own shortcuts or - trigger the Shortcuts screen from their apps. See Keyboard - Shortcuts helper for details. -

    - -

    FrameMetrics API

    - -

    - DP3 introduces a new FrameMetrics API - that allows an app to monitor its UI rendering performance by exposing a - streaming pubsub API to transfer frame timing info for the application’s - current window. FrameMetricsListener can be used to measure - interaction-level UI performance in production with higher granularity and - without the need for a USB connection. -

    - -

    Feature and API changes

    - -
    -
    - Launcher Shortcuts and the Launcher Shortcuts API -
    - -
    - We’ve decided to defer this feature to a future release of Android. We plan - to remove the Launcher Shortcuts APIs (ShortcutManager and others) from the - public Android N API starting in the next developer preview. -
    - -
    - WebView Javascript run before page load -
    - -
    - Starting with apps targeting Android N, the Javascript context is reset - when a new page is loaded. Currently, the context is carried over for the - first page loaded in a new {@link android.webkit.WebView} instance. - Developers looking to inject Javascript into the {@link - android.webkit.WebView} should execute the script after the page has - started to load. -
    - -
    - WebView Geolocation on insecure origins -
    - -
    - Starting with apps targeting Android N, the geolocation API will only be - allowed on secure origins (over HTTPS.) This policy is designed to protect - users' private information when they're using an insecure connection. -
    - -
    - Data Saver -
    - -
    - Starting in Developer Preview 3, apps can use use an intent to display a - system dialog that lets the user directly add the app to the Data Saver - exemption whitelist. See the Data Saver - documentation for details. -
    - -
    - Number-blocking -
    - -
    - If an unauthorized user attempts to block or unblock a number, the - operation now fails with {@link java.lang.SecurityException}. (Previously, - the operation threw {@link java.lang.UnsupportedOperationException}.) -
    - -
    - Quick Settings Tile - API -
    - -
    - The system now uses the activity's metadata to decide on the tile mode. - (Previously, tile mode was determined by the return value of - TileService.onTileAdded().) For more information, see - TileService.META_DATA_ACTIVE_TILE in the downloadable API Reference. -
    -
    - -

    Fixes for issues reported by developers

    - -

    - A number of issues reported by developers have been fixed, including: -

    - -
      -
    • Bluetooth Audio playback interrupted after 1 song (bug 206889) -
    • - -
    • Pixel C Consistently Crashes (bug 206962) -
    • - -
    • Clock and Toast notification issues (bug 203094) -
    • - -
    • Pixel C reboots when connected to MacBook Pro via USB C Cable (bug - 205432) -
    • - -
    • Calandar offset by one day (bug 203002) -
    • - -
    • TelephonyManager.getAllCellInfo returning invalid data (bug 203022) -
    • - -
    • Nexus 6p, Bluetooth keeps disconnecting (bug 208062) -
    • -
    - -

    For the full list of fixed issues, see the -issue tracker.

    - -

    Known Issues

    - -

    Accessibility

    - -
      -
    • Unable to listen to TTS output when pitch is set near maximum level. -
    • - -
    • Accessibility features and settings may be disrupted with the user adds a - Work profile, including magnification gesture and setting. Accessibility - state is restored when the user next touches the associated settings. -
    • -
    - -

    Camera

    - -
      -
    • The Camera app has exhibited instability; it may crash in various - circumstances, such as when launched in multi-window mode. -
    • - -
    • Pressing the shutter continuously in panorama mode may cause the Camera - app to crash. -
    • -
    - -

    Audio

    -
      -
    • A platform audio player issue prevents some apps from functioning - normally. For example, Skype and other apps are affected by this issue. -
    • -
    - -

    Connectivity

    - - -
      -
    • When a Bluetooth Low Energy (BLE) peripheral role device advertises a - service and a BLE central role device connects, the peripheral role device - disconnects very quickly. -
    • - -
    • Wi-Fi connection may be dropped when the screen is off. -
    • - -
    • RFCOMM connections are unstable and may result in data corruption and - dangling connections. -
    • - -
    • The active network state ({@link android.net.NetworkInfo#getState - NetworkInfo.getState()} and {@link android.net.NetworkInfo#getDetailedState - NetworkInfo.getDetailedState()}) might return incorrect values during some - restricted background scenarios. -
    • -
    - - -

    - Launcher -

    - -
      -
    • The default launcher’s All Apps tray may become unresponsive after - cycling screen off / screen on. Returning to the homescreen and relaunching - the All Apps tray may resolve this issue. -
    • -
    - -

    - Keyboard -

    - -
      -
    • When updating a device running Android 6.0 or earlier to the N Developer - Preview, Google Keyboard does not preserve preferences data such as recent - emoji and sound settings. -
    • - -
    • Google Indic Managed Keyboard may be unstable. -
    • - -
    • When entering text in a password field, the user can select Russian as - the input language but the keyboard remains in English. This prevents the - user from entering Russian-language passwords. -
    • -
    - -

    - Locale and languages -

    - -
      -
    • When using a right-to-left (RTL) locale, the system may unexpectedly - switch to left-to-right (LTR) presentation after restarting the device. -
    • -
    - -

    Media

    - -
      -
    • Media playback be be unreliable on Nexus 9 and Nexus Player, including - issues playing HD video. -
    • -
    - -

    - Multi-window mode -

    - -
      -
    • Device may freeze when changing orientation in multi-window mode. -
    • - -
    • Several apps currently have issues with multi-window mode: -
        -
      • The system UI may crash when docking Settings > Display > - Screen brightness to multi-window. -
      • - -
      • The Camera app may crash when launched in multi-window mode. -
      • - -
      • YouTube may crash when launched into multi-window mode. To fix the - issue, you can clear the YouTube app’s data at Storage > Apps > - YouTube. -
      • -
      -
    • -
    - -

    - Google Play services -

    - -
      -
    • Apps using Google Cast through Google Play services may be unstable when - the user selects a system locale that uses letters and numbers outside of the - ASCII range. -
    • -
    - -

    - Android for Work and Google Apps Device Policy -

    - -
      -
    • The Device Policy app may crash when the user unlocks the device with the - "device policy status" screen pinned. -
    • - -
    • After setting up a work profile with file-based encryption enabled and - then turning off Work, users must unlock primary profile screen lock to once - again access Work apps. -
    • - -
    • Device reboots when removing the security pattern lock and opening work - app/personal app in the multi-window. -
    • - -
    • Setting DISALLOW_VPN_CONFIG is causing the consent dialog to appear in - always-on-vpn set by Device Policy Client. -
    • - -
    • Traffic is not locked down until VPN is connected in always-on-vpn mode. -
    • -
    - -

    - External storage -

    - -
      -
    • Apps may become unstable when the user moves them from internal storage - to adoptable external storage (this can include SD card or devices attached - over USB). -
    • -
    - -

    - Screen zoom and multiple APKs in Google Play -

    - -
      -
    • On devices running Android N, Google Play services 9.0.83 incorrectly reports - the current screen density rather than the stable screen density. When screen - zoom is enabled on these devices, this can cause Google Play to select a - version of a multi-APK app that’s designed for smaller screens. This issue is - fixed in the next version of Google Play services and will be included in a - later Developer Preview release. -
    • - -
    • On devices running Android N, Google Play services 9.0.83 currently reports - Vulkan support but not Vulkan version. This can cause Google Play to select a - version of a multi-APK app that’s designed for lower Vulkan support on - devices with higher version support. Currently, the Google Play Store does - not accept uploads of Apps which use Vulkan version targeting. This support - will be added to the Google Play Store in the future and fixed in the next - version of Google Play services (to be included in a later Developer Preview - release) any N devices using the version of Google Play services 9.0.83 will - continue to receive versions of Apps targeting basic Vulkan support. -
    • -
    - -

    Notifications

    - -
      -
    • MessagingStyle does not show notifications with "null" (self) sender. -
    • -
    - -

    Developer Tools

    - -
      -
    • - adb may sometimes disconnect while using JDWP debugging. -
    • -
    - - - - -

    Developer Preview 2

    - -
    -
    -
    -

    - Date: April 2016
    - Builds: NPC91K, NPC91O
    - Emulator support: x86 & ARM (32/64-bit)
    - Google Play services: 8.4
    -

    -
    -
    -
    - -

    New in DP2

    - -
      -
    • Platform support for Vulkan, a new 3D rendering API that provides - explicit, low-overhead GPU (Graphics Processor Unit) control and offers - improved performance for draw-call heavy applications. For details, see the - documentation. -
    • - -
    • New people emoji with support for skin tones, and new Unicode 9 glyphs. - Skin tone and new emoji will not show up until keyboards build support for - them in the palette. Apps should not need to take any action to take - advantage of these new emoji, unless the apps use a non-system font. IME - developers need to incorporate support for the new emoji. -
    • - -
    • - Launcher - Shortcuts API: Apps can use ShortcutManager to send - shortcuts to starting points within themselves to the launcher. -
    • - -
    • - Multi-Window: - You can now specify a separate minimum height and minimum width for an - activity. In addition, several API names have been slightly changed. -
    • -
    - -

    Fixes for issues reported by developers

    - -

    - A number of issues reported by developers have been fixed, including: -

    - -
      -
    • Can’t connect to hidden SSID or non-broadcast Wi-Fi. (bug 203116) -
    • - -
    • Microphone mute state persists across activities. (bug 205922) -
    • - -
    • Changing multi-window focus pauses YouTube. (bug 203424) -
    • - -
    • Direct Reply may close open activity. (bug 204411) -
    • - -
    • Various stability fixes. -
    • -
    - -

    General advisories

    - -

    - This Developer Preview release is for app developers only - and is designed for use in compatibility testing and early development only. - Please be aware of these general notes about the release: -

    - -
      - -
    • The development tool components and support libraries have been updated - for the DP2 release. Make sure to update your preview development environment - before developing for DP2. For instructions on setting up your development - environment, see - Set Up the Preview. -
    • - -
    • This release has various stability and performance issues on all devices - that make it not suitable for daily use on phone or tablet, - especially for non-developers. -
    • - -
    • Battery life and performance have not yet been optimized with this - release: - -
        -
      • System and app performance is known to be periodically slow / - janky, and devices may become occasionally unresponsive. These - problems may become more acute with prolonged use. -
      • - -
      • Battery life may be regressed in this release for screen-on and - screen-off use cases. -
      • -
      -
    • - -
    • Some apps may not function normally on Developer Preview - 2. This includes Google’s apps as well as other apps. -
    • - -
    • This early build is not Compatibility Test Suite (CTS) - approved. Apps that depend on CTS approved builds won’t work - (Android Pay for example). -
    • - -
    • This preview release supports the following devices: Nexus 5X, Nexus 6, - Nexus 6P, Nexus 9, and Pixel C, as well as General Mobile 4G - (Android One). Support for Nexus Player is coming soon. -
    • - - -
    • TestDPC has - been updated to handle API changes between DP1 and DP2. -
    • -
    - -

    Known Issues

    - -

    Performance and battery

    - -
      -
    • System and app performance is known to be periodically slow / - janky, and device may become occasionally unresponsive. These - problems may become more acute with prolonged use. -
    • -
    - -

    Google accounts

    - -
      -
    • In some circumstances, there can be issues with - AccountManagerService that prevent logging in to Google accounts -
    • -
    - -

    System update

    - -
      -
    • Device may restart immediately after updating to DP2. -
    • -
    - -

    Accessibility

    - -
      -
    • Problem with listening to text-to-speech (TTS) output when pitch is set - near maximum level. -
    • -
    - -

    Bluetooth

    - -
      -
    • Bluetooth Low Energy (LE) GATT characteristics are using the wrong write - type and will not be sent to a remote device. Thus, for example, some fitness - devices will not work. -
    • -
    - -

    Setup wizard

    - -
      -
    • The option to restore data on a new device (or newly reset device) from - "Your Google Account" is not actionable in the setup wizard. You must restore - data from an existing device by selecting "another Android device" in the - setup wizard, or else set it up as a new device. -
    • -
    - -

    OEM unlock

    - -
      -
    • On some devices, Enable OEM unlock is grayed out in - "Developer Options" while running DP2.
      - Workaround: Opt in to - the Android Beta Program (if you are not already opted in) by visiting - www.google.com/android/beta. Then, opt out and accept the - downgrade OTA. Opting out causes the device to downgrade to Android 6.0. You - should now be able to choose Enable OEM unlock in - "Developer Options". Personal data is erased when you downgrade the - device; however, unlocking the bootloader would have erased this data anyway. -
    • -
    - -

    Android for Work

    - -
      -
    • Work Security Challenge -
        -
      • After migration to N, or after the user creates work profiles, work - profiles can't create keys in the keystore until the user changes their - pattern, PIN, or password, or sets up a Work Challenge. -
      • - -
      • In Direct boot mode, applying the passcode restrictions to the device - causes the work profile to be unlocked, even though the device is locked. - This makes the work profile accessible even though it should be protected - by the device lock screen. -
      • -
      -
    • - -
    • Always On VPN -
        -
      • If Always On VPN mode is turned on, but VPN is not available, apps - connect over the ordinary network. Apps should be offline if they have no - VPN connection available. -
      • - -
      • When Always On mode is on, a VPN connection is not established after - a device reboots into Direct boot mode, even after the user unlocks the - secure lock screen. -
      • -
      -
    • - -
    • Suspend Packages -
        -
      • Device admins can suspend critical system packages, which may lead to - unexpected behavior, such as placing calls despite the "Telephone - disabled" dialog being displayed. -
      • -
      -
    • - -
    • Other -
        -
      • The Settings app crashes on launch if {@link - android.os.UserManager#DISALLOW_MOUNT_PHYSICAL_MEDIA} is set to true when - the user inserts physical media such as an SD card. -
      • - -
      • The first check-in in a Work Profile takes several minutes to - complete. -
      • -
      -
    • -
    - -

    Vulkan

    - -
      -
    • Nexus 5X/6P
    • -
        -
      • Gaps between binding numbers and non-zero - as the first binding number causes {@code vkCreateGraphicsPipeline()} to fail.
      • -
      • Vulkan exhibits incorrect sampling behavior on projected texture coordinates.
      • -
      • in the multithreadCmdBuffer sample, {@code vkCmdClearColorImage()} crashes when - running with the N-DP2 driver.
      • -
      • Return values from {@code vkGetPhysicalDeviceFormatProperties()} do not set a value - for {@code VkFormatProperties::linearTilingFeatures}, which takes a value of 0 as - a result.
      • -
      • Vulkan floating point frame buffer attachments are not handled correctly.
      • -
      -
    • Nexus Player
    • -
        -
      • SPIR-V shaders may trigger driver asserts.
      • -
      • Some pipeline configurations may cause {@code vkCreateGraphicsPipeline()} - to crash.
      • -
      -
    - -

    Device-specific issues

    - -
    -
    - Android One -
    - -
    - Data connection fails when device is switched from slot 1 to slot 2 SIM. -
    - -
    - Pixel C -
    - -
    - Unable to toggle Voice Search "Always On" option. -
    - -
    - Nexus 6 -
    - -
    - Camera pictures in portrait orientation are corrupted, except for HDR+ - photos. -
    - -
    - Nexus Player -
    - -
    - Playback of Netflix HD content may fail on Nexus Player. -
    - -
    - Any application that relies on dynamic video resolution changes may fail on - Nexus Player. -
    - -
    - Any application that use the VP9 video codec may fail on Nexus Player. -
    -
    - - - -

    Developer Preview 1

    - -
    -
    -
    -

    - Date: March 2016
    - Builds: NPC56P, NPC56R, updated: NPC56W, NPC56X
    - Emulator support: x86 & ARM (32/64-bit)
    - Google Play services: 8.4
    -

    -
    -
    -
    - -

    General advisories

    - -

    - This Developer Preview release is for app developers only and is designed for - use in compatibility testing and early development only. Please be aware of - these general notes about the release: -

    -
      -
    • This release has various stability and performance issues on all devices - that make it not suitable for daily use on phone or tablet, - especially for non-developers. -
    • - -
    • System and app performance is known to be periodically slow / - janky, and device may become occasionally unresponsive. These - problems may become more acute with prolonged use. -
    • - -
    • Battery life may be regressed in this release for screen-on and - screen-off use cases. -
    • - -
    • Some apps may not function normally on Developer Preview 1. This includes - Google’s apps as well as other apps. -
    • - -
    • This early build is not Compatibility Test Suite (CTS) approved. Apps - that depend on CTS approved builds (Android Pay for example) won’t work. -
    • - -
    • This preview release supports the following devices: Nexus 5X, Nexus 6, - Nexus 6P, Nexus 9, Nexus Player, and Pixel C, as well as General Mobile 4G - (Android One). -
    • -
    - -

    Platform Issues

    - -

    Performance and battery

    - -
      -
    • System and app performance is known to be periodically slow / - janky, and device may become occasionally unresponsive. These - problems may become more acute with prolonged use. -
    • - -
    • Battery life may be regressed in this release for screen-on and - screen-off use cases. -
    • -
    -

    Dialer

    - -
      -
    • Dialer app does not support Direct boot. This will be addressed later in - N Developer Preview. -
    • - -
    • Voicemail playback does not work. -
    • -
    - -

    Microphone

    - -
      -
    • The system may incorrect persists the microphone mute state across apps and reboots. If you mute the microphone in an app and the state is persisted, open any app that has microphone mute controls and unmute the microphone.
    • -
    - -

    System UI

    - -
      -
    • Some new or modified strings in the system UI are not translated to all - languages. -
    • - -
    • Overview UI is still in development, and subject to change. For example, - we intend to remove the timer that appears when the user switches between - apps. -
    • - -
    • Settings controls and toggles may be slow or appear to be unresponsive. -
    • - -
    • Visual design of notifications is subject to change. -
    • - -
    • In the Gmail app, direct archiving of emails included in a notification - bundle does not work properly. -
    • -
    - -

    Android for Work

    - -
      -
    • Work Security Challenge -
        -
      • After migration to N, or after the user creates work profiles, work - profiles can't create keys in the keystore until the user changes their - pattern, PIN, or password, or sets up a Work Challenge. -
      • - -
      • In Direct boot mode, applying the passcode restrictions to the device - causes the work profile to be unlocked, even though the device is locked. - This makes the work profile accessible even though it should be protected - by the device lock screen. -
      • - -
      • When the user enters a wrong password and pin, the system does not - display any informational message; instead, it only clears the input - field. This issue does not affect pattern or fingerprint input. -
      • - -
      • On a tablet, the background displayed with the work challenge is - disproportionately small. -
      • - -
      • The version of - Google Apps Device Policy that is bundled with N Developer Preview - does not yet support the Work Profile Security Challenge feature. - Developers should instead use TestDPC - to test this feature. -
      • -
      -
    • - -
    • Always On VPN -
        -
      • If Always On VPN mode is turned on, but VPN is not available, apps - not specified as exceptions to the Always On policy connect over the - ordinary network. Unless specified as exceptions to Always On VPN policy, - apps should be offline if they have no VPN connection available. -
          -
        • When Always On mode is on, a VPN connection is not established - after a device reboots into Direct boot mode, even after the user - unlocks the secure lock screen. -
        • -
        -
      • -
      -
    • - -
    • Improved Contacts -
        -
      • Bluetooth PBAP/MAP devices do not display Caller ID for work - contacts. The next release of Preview resolves this issue. -
      • -
      -
    • - -
    • Work Mode -
        -
      • The Google Now Launcher does not display whether Work Mode is on or - off. The Launcher also does not show app suspension state. -
      • - -
      • After the user turns Work Mode off and on, the system no longer shows - Work profile app widgets, such as Calendar. -
      • -
      -
    • - -
    • Suspend Packages -
    • - -
    • Device admins can suspend critical system packages, which may lead to - unexpected behavior, such as placing calls despite the Telephone disabled - dialog’s being displayed. -
    • - -
    • Other -
        -
      • The Settings app crashes on launch if {@link - android.os.UserManager#DISALLOW_MOUNT_PHYSICAL_MEDIA} is set to true when - the user inserts physical media such as an SD card. -
      • - -
      • The {@code DPM.setPackagesSuspended} state does not persist when the - user uninstalls and then reinstalls an app. Either the app should remain - suspended after uninstall/reinstall, or suspended apps should not be - uninstallable -
      • - -
      • The first check-in in a Work Profile takes several minutes to - complete. This may cause the device to take longer than normal to be - visible in the Play EMM API. -
      • - -
      • Notifications from Work Profile apps are not visible to notification - listeners installed in the personal profile. As a result, the system does - not display Notifications as expected. -
      • - -
      -
    • -
    - -

    Keyboard

    - -
      -
    • Bluetooth pairing between keyboards and Android devices may be unstable. -
    • -
    - -

    Video

    - -
      -
    • Video playback may lag and show interruptions.
    • -
    - -

    Wi-Fi

    - -
      -
    • Wi-Fi has undergone some refactoring which may change API corner case - behavior. Specifically, applications which attempt to connect to specific - networks, or attempt to reconnect to networks should retest. -
    • - -
    • The legacy DHCP client has been removed from the platform. The only DHCP - client that the platform supports is the DHCP client introduced in M. -
    • -
    - -

    Direct boot

    - -
      -
    • NFC doesn't function until first unlock. -
        -
      • When a phone with Bluetooth enabled is restarted, Bluetooth does not - turn on automatically. You must manually re-enable Bluetooth. -
      • - -
      • Under some circumstances, the default ringtone may not sound for - phone calls and messages. This behavior is fixed in the next N Preview - release, with one exception (and workaround): -
      • - -
      • On a device that is not freshly wiped--one that has been booted at - least once since being set to direct boot mode--the default notification - ringtone does not sound. The user can work around this issue by manually - selecting a ringtone from Settings. -
      • - -
      • Direct boot is not enabled by default on devices running an N - Developer Preview build. To enable direct boot for testing and - development, go to Developer Options and tap Convert to File Encryption. - In this dev preview, this requires a factory reset to repartition and - reformat your device for File-based Encryption. -
      • -
      -
    • -
    - -

    Picture-in-picture for Android TV

    - -
      -
    • The PIP integration in the Recents UI is not finalized, and is subject to - change. -
        -
      • The animation of the PIP window is not smooth. Future releases of the - Preview will improve this. -
      • -
      -
    • - -
    • Future releases of the Preview will improve upon - the visual design and layout alignment of PIP. -
    • -
    - -

    Bug reports

    - -
      -
    • Bug reports do not always complete successfully (as a workaround, - sometimes they can still be accessed through the bug report document provider - in internal storage). -
    • -
    - -

    Split-screen Multi-window

    - -
      -
    • Apps may experience crashes and unexpected UI behavior when put into - split-screen mode. These are app issues that must be fixed by the app - developer. -
    • - -
    • When an app targets a version of the Android platform earlier than N, the - App may not work with split-screen toast may appear multiple times. -
    • - -
    • Long-pressing the Overview button while using an app with a fixed - orientation may produce unexpected app behavior. -
    • - -
    • Apps may flicker while resizing. -
    • - -
    • Animations are not yet final. -
    • -
    - -

    Input method

    - -
      -
    • Google Keyboard unexpectedly falls back to the generic Google keyboard - when Use system language, but Google Keyboard doesn’t support any of - the languages selected in the system-language preferences. It should fall - back to American English. -

      - You can work around this problem by adding at least one language that - Google Keyboard supports. -

      -
    • -
    - -

    Accessibility

    - -
      -
    • TalkBack exhibits issues with features including Notifications, Quick - Settings Tiles and Multi-window display that may cause system crashing or - lack of spoken feedback from TalkBack. Future releases of the preview will - address these issues. -
    • -
    - -

    Device-Specific Notes and Issues

    - -

    Nexus Player

    -
      -
    • Video playback, app compatibility and stability issues are expected on - Nexus Player in this release of the Preview. -
    • -
    - -

    Pixel C

    -
      -
    • Multi-window resizing may cause crashing.
    • -
    - -

    Nexus 9

    -
      -
    • Nexus 9 devices may not start after receiving an over-the-air (OTA) update - via the Android Beta Program. To recover from this issue, you can try - to manually install the OTA image. For more information, see - Applying a Device OTA Image. -
    • -
    - diff --git a/docs/html/reference/_project.yaml b/docs/html/reference/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e5c26e7fdd8fd35a4ac1946a0d5246cda38fc2f2 --- /dev/null +++ b/docs/html/reference/_project.yaml @@ -0,0 +1,6 @@ +name: "Reference" +home_url: /reference/ +description: "API Reference packages and classes." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /develop/_project.yaml diff --git a/docs/html/samples/_project.yaml b/docs/html/samples/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ede5958cc68324e08929ca1efd4fb29b130dae96 --- /dev/null +++ b/docs/html/samples/_project.yaml @@ -0,0 +1,6 @@ +name: "Samples" +home_url: /samples/ +description: "Welcome to code samples where you can browse sample code and learn how to build different components for your applications." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /develop/_project.yaml diff --git a/docs/html/samples/index.jd b/docs/html/samples/index.jd index 5885086fec5888e27cbb2a21d8362b35468bb0e8..240a54cdadaa7333d6f5c9982615752973007877 100644 --- a/docs/html/samples/index.jd +++ b/docs/html/samples/index.jd @@ -35,7 +35,7 @@ recommended method to retrieve Android code samples.

    from GitHub as a new project.

    -

    To view the Android code samples that you can import, see the +

    To view the Android code samples that you can import, see the Google Samples page on GitHub.

    Download Samples

    @@ -69,6 +69,6 @@ for your applications.

    Note: At this time, the downloadable projects are designed for use with Gradle - and Android Studio. + and Android Studio.

    diff --git a/docs/html/sdk/1.0_r1/installing.jd b/docs/html/sdk/1.0_r1/installing.jd index 38c2a1a32241e6698a57adffeda29ad90cf0d3f5..eb02742bbe827065ee1033fa4ed9848c51bef702 100644 --- a/docs/html/sdk/1.0_r1/installing.jd +++ b/docs/html/sdk/1.0_r1/installing.jd @@ -1,3 +1,4 @@ +excludeFromSuggestions=true @jd:body + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_all.html new file mode 100644 index 0000000000000000000000000000000000000000..fb553f8eebd0c7b27efe011e6004ddc9c769a198 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_all.html @@ -0,0 +1,1327 @@ + + + + + + + + + +All Differences Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Differences +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + + +
    A  +B +C +D +E +F +G +H +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +AbstractMediaItemPresenter
    + +AbstractMediaItemPresenter.ViewHolder
    + +AccessibilityEventCompat
    + +AccessibilityManagerCompat
    + +AccessibilityManagerCompat.AccessibilityStateChangeListener
    + +AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat
    + +AccessibilityManagerCompat.TouchExplorationStateChangeListener
    + +AccessibilityNodeInfoCompat
    + +AccessibilityNodeInfoCompat.AccessibilityActionCompat
    + +AccessibilityNodeInfoCompat.CollectionInfoCompat
    + +AccessibilityNodeInfoCompat.CollectionItemInfoCompat
    + +AccessibilityNodeInfoCompat.RangeInfoCompat
    + +AccessibilityNodeProviderCompat
    + +AccessibilityServiceInfoCompat
    + +AccessibilityWindowInfoCompat
    + +ACTION_ARGUMENT_COLUMN_INT +
    + +ACTION_ARGUMENT_PROGRESS_VALUE +
    + +ACTION_ARGUMENT_ROW_INT +
    + +ACTION_CONTEXT_CLICK +
    + +ACTION_SCROLL_DOWN +
    + +ACTION_SCROLL_LEFT +
    + +ACTION_SCROLL_RIGHT +
    + +ACTION_SCROLL_TO_POSITION +
    + +ACTION_SCROLL_UP +
    + +ACTION_SET_PROGRESS +
    + +ACTION_SHOW_ON_SCREEN +
    + +ActionBarActivity
    + +ActionBarDrawerToggle
    + +ActionMenuView
    + +ActionMenuView.LayoutParams
    + +ActionMenuView.OnMenuItemClickListener
    + +ActivityCompat
    +  android.support.v4.app
    + +  ActivityCompat +() constructor
    + +ActivityOptionsCompat
    + +addAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    + +addTouchExplorationStateChangeListener +(AccessibilityManager, TouchExplorationStateChangeListener)
    + +android.support.customtabs
    + +android.support.design.widget
    + +android.support.transition
    + +android.support.v14.preference
    + +android.support.v17.leanback.widget
    + +android.support.v17.preference
    + +android.support.v4.accessibilityservice
    + +android.support.v4.app
    + +android.support.v4.content
    + +android.support.v4.graphics.drawable
    + +android.support.v4.media
    + +android.support.v4.media.session
    + +android.support.v4.os
    + +android.support.v4.text.util
    + +android.support.v4.util
    + +android.support.v4.view
    + +android.support.v4.view.accessibility
    + +android.support.v4.widget
    + +android.support.v7.app
    + +android.support.v7.appcompat
    + +android.support.v7.content.res
    + +android.support.v7.graphics
    + +android.support.v7.preference
    + +android.support.v7.recyclerview
    + +android.support.v7.util
    + +android.support.v7.widget
    + +android.support.v8.renderscript
    + +AppBarLayout.ScrollingViewBehavior
    + +AppCompatActivity
    + +AppCompatAutoCompleteTextView
    + +AppCompatButton
    + +AppCompatCheckBox
    + +AppCompatCheckedTextView
    + +AppCompatDelegate
    + +AppCompatDialogFragment
    + +AppCompatEditText
    + +AppCompatImageButton
    + +AppCompatImageView
    + +AppCompatMultiAutoCompleteTextView
    + +AppCompatRadioButton
    + +AppCompatRatingBar
    + +AppCompatResources
    + +AppCompatSeekBar
    + +AppCompatSpinner
    + +AppCompatTextView
    + + +
    B  +A +C +D +E +F +G +H +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +BatchingListUpdateCallback
    + +BottomSheetBehavior
    + +BT_FOLDER_TYPE_ALBUMS +
    + +BT_FOLDER_TYPE_ARTISTS +
    + +BT_FOLDER_TYPE_GENRES +
    + +BT_FOLDER_TYPE_MIXED +
    + +BT_FOLDER_TYPE_PLAYLISTS +
    + +BT_FOLDER_TYPE_TITLES +
    + +BT_FOLDER_TYPE_YEARS +
    + +BuildCompat
    + +buildMediaButtonPendingIntent
    +  type  +(Context, ComponentName, long) in android.support.v4.media.session.MediaButtonReceiver +
    + +  type  +(Context, long) in android.support.v4.media.session.MediaButtonReceiver +
    + + +
    C  +A +B +D +E +F +G +H +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +CardView
    + +clearColorFilter +(Drawable)
    + +clearOnTabSelectedListeners +()
    + +CollapsingToolbarLayout
    + +computeScrollVectorForPosition
    +  type  +(int) in android.support.v7.widget.LinearSmoothScroller +
    + +  type  +(int) in android.support.v7.widget.StaggeredGridLayoutManager +
    + +ContextCompat
    +  android.support.v4.content
    + +  ContextCompat +() constructor
    + +CoordinatorLayout
    + +CoordinatorLayout.Behavior
    + +CoordinatorLayout.LayoutParams
    + +CustomTabsIntent
    + +CustomTabsIntent.Builder
    + +CustomTabsSession
    + + +
    D  +A +B +C +E +F +G +H +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +DiffUtil
    + +DiffUtil.Callback
    + +DiffUtil.DiffResult
    + +dispatch +(KeyEvent, Callback, Object, Object)
    + +dodgeInsetEdges +
    + +DrawableCompat
    + + +
    E  +A +B +C +D +F +G +H +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +EXTRA_BT_FOLDER_TYPE +
    + +EXTRA_ENABLE_INSTANT_APPS +
    + +EXTRA_SUGGESTION_KEYWORDS +
    + +EXTRA_USAGE_TIME_REPORT +
    + +EXTRA_USAGE_TIME_REPORT_PACKAGES +
    + + +
    F  +A +B +C +D +E +G +H +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +findFragmentByWho +(String)
    + +findPointerIndex +(MotionEvent, int)
    + +FloatingActionButton.Behavior
    + +FragmentController
    + +fromMediaItem +(Object)
    + +fromMediaItemList +(List<?>)
    + +fromMediaSession +(Context, Object)
    + +fromQueueItem +(Object)
    + +fromQueueItemList +(List<?>)
    + + +
    G  +A +B +C +D +E +F +H +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +getAction +(AccessibilityEvent)
    + +getCompoundDrawablesRelative +(TextView)
    + +getDependents +(View)
    + +getDescription +(AccessibilityServiceInfo)
    + +getDominantColor +(int)
    + +getDominantSwatch +()
    + +getDrawable +(Context, int)
    + +getDrawerArrowDrawable +()
    + +getInsetDodgeRect
    +  type  +(CoordinatorLayout, V, Rect) in android.support.design.widget.CoordinatorLayout.Behavior +
    + +  type  +(CoordinatorLayout, FloatingActionButton, Rect) in android.support.design.widget.FloatingActionButton.Behavior +
    + +getKeyDispatcherState +(View)
    + +getLaunchBounds +()
    + +getMediaItemNumberViewFlipper +()
    + +getMediaItemPausedView +()
    + +getMediaItemPlayingView +()
    + +getMediaPlayState +(Object)
    + +getMovementGranularity +(AccessibilityEvent)
    + +getOnFlingListener +()
    + +getOverScrollMode +(View)
    + +getPasswordVisibilityToggleContentDescription +()
    + +getPasswordVisibilityToggleDrawable +()
    + +getPointerCount +(MotionEvent)
    + +getPointerId +(MotionEvent, int)
    + +getReferrer +(Activity)
    + +getScaledPagingTouchSlop +(ViewConfiguration)
    + +getSelectionMode +()
    + +getSource +(MotionEvent)
    + +getX +(MotionEvent, int)
    + +getY +(MotionEvent, int)
    + +GridLayout
    + +GridLayout.Alignment
    + +GridLayout.LayoutParams
    + +GridLayout.Spec
    + + +
    H  +A +B +C +D +E +F +G +I +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +HOST_VIEW_ID +
    + + +
    I  +A +B +C +D +E +F +G +H +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +insetEdge +
    + +isAtLeastNMR1 +()
    + +isAutoHideEnabled +()
    + +isContextClickable +()
    + +isDirty +(CoordinatorLayout, V)
    + +isImmediateNotifySupported +()
    + +isImportantForAccessibility +(View)
    + +isOpaque +(View)
    + +isPasswordVisibilityToggleEnabled +()
    + +isTracking +(KeyEvent)
    + + +
    K  +A +B +C +D +E +F +G +H +I +L +M +N +O +P +R +S +T +V +W + TOP +

    +KeyEventCompat
    + + +
    L  +A +B +C +D +E +F +G +H +I +K +M +N +O +P +R +S +T +V +W + TOP +

    +layoutDependsOn +(CoordinatorLayout, FloatingActionButton, View)
    + +LeanbackSettingsFragment
    + +LinearLayoutCompat
    + +LinearLayoutCompat.LayoutParams
    + +LinearLayoutManager
    + +LinearSmoothScroller
    + +LinearSnapHelper
    + +ListPopupWindow
    + +ListUpdateCallback
    + +loadDescription +(AccessibilityServiceInfo, PackageManager)
    + + +
    M  +A +B +C +D +E +F +G +H +I +K +L +N +O +P +R +S +T +V +W + TOP +

    +makeBasic +()
    + +makeClipRevealAnimation +(View, int, int, int, int)
    + +makeTaskLaunchBehind +()
    + +MediaBrowserCompat.MediaItem
    + +MediaBrowserServiceCompat.BrowserRoot
    + +MediaButtonReceiver
    + +MediaDescriptionCompat
    + +MediaMetadataCompat
    + +MediaSessionCompat
    + +MediaSessionCompat.QueueItem
    + +METADATA_KEY_BT_FOLDER_TYPE +
    + +METADATA_KEY_MEDIA_URI +
    + +MotionEventCompat
    + +MultiSelectListPreferenceDialogFragmentCompat
    + + +
    N  +A +B +C +D +E +F +G +H +I +K +L +M +O +P +R +S +T +V +W + TOP +

    +NotificationCompat
    + +NotificationCompat.Builder
    + +NotificationCompat.MediaStyle
    + +notifyPlayStateChanged +()
    + + +
    O  +A +B +C +D +E +F +G +H +I +K +L +M +N +P +R +S +T +V +W + TOP +

    +ObjectAdapter
    + +obtain
    +  type  +(Context, Object) in android.support.v4.media.session.MediaSessionCompat +
    + +  type  +(Object) in android.support.v4.media.session.MediaSessionCompat.QueueItem +
    + +  type  +(int, int, boolean) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat +
    + +  type  +(int, int, int, int, boolean) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat +
    + +  type  +(int, float, float, float) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat +
    + +onAccessibilityStateChanged +(boolean)
    + +onAttachedToLayoutParams +(LayoutParams)
    + +onBindMediaPlayState +(ViewHolder)
    + +onChanged +(int, int, Object)
    + +onDependentViewRemoved +(CoordinatorLayout, FloatingActionButton, View)
    + +onDetachedFromLayoutParams +()
    + +onInserted +(int, int)
    + +onMoved +(int, int)
    + +onRemoved +(int, int)
    + +onRequestChildRectangleOnScreen
    +  type  +(CoordinatorLayout, View, Rect, boolean) in android.support.design.widget.AppBarLayout.ScrollingViewBehavior +
    + +  type  +(CoordinatorLayout, V, Rect, boolean) in android.support.design.widget.CoordinatorLayout.Behavior +
    + +onSharedElementsArrived +(List<String>, List<View>, OnSharedElementsReadyListener)
    + +onStart +()
    + +onUnbindMediaPlayState +(ViewHolder)
    + +OVER_SCROLL_ALWAYS +
    + +OVER_SCROLL_IF_CONTENT_SCROLLS +
    + +OVER_SCROLL_NEVER +
    + + +
    P  +A +B +C +D +E +F +G +H +I +K +L +M +N +O +R +S +T +V +W + TOP +

    +Palette
    + +PatternsCompat
    + +PEEK_HEIGHT_AUTO +
    + +PLAY_STATE_INITIAL +
    + +PLAY_STATE_PAUSED +
    + +PLAY_STATE_PLAYING +
    + +PlaybackStateCompat
    + +PopupMenu
    + +PopupMenu.OnDismissListener
    + +PopupMenu.OnMenuItemClickListener
    + +PreferenceFragment
    + +prepareForDrop +(View, View, int, int)
    + + +
    R  +A +B +C +D +E +F +G +H +I +K +L +M +N +O +P +S +T +V +W + TOP +

    +RecyclerView
    + +RecyclerView.OnFlingListener
    + +RecyclerView.SmoothScroller.ScrollVectorProvider
    + +removeAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    + +removeTouchExplorationStateChangeListener +(AccessibilityManager, TouchExplorationStateChangeListener)
    + +requestUsageTimeReport +(PendingIntent)
    + + +
    S  +A +B +C +D +E +F +G +H +I +K +L +M +N +O +P +R +T +V +W + TOP +

    +SearchView
    + +SearchView.OnCloseListener
    + +SearchView.OnQueryTextListener
    + +SearchView.OnSuggestionListener
    + +SearchViewCompat
    + +SearchViewCompat.OnCloseListener
    + +SearchViewCompat.OnCloseListenerCompat
    + +SearchViewCompat.OnQueryTextListener
    + +SearchViewCompat.OnQueryTextListenerCompat
    + +ServiceCompat
    + +setAction +(AccessibilityEvent, int)
    + +setAlwaysUseBrowserUI +(Intent)
    + +setAutoHideEnabled +(boolean)
    + +setCollapsedTitleTextColor +(ColorStateList)
    + +setContextClickable +(boolean)
    + +setDrawerArrowDrawable +(DrawerArrowDrawable)
    + +setExpandedTitleTextColor +(ColorStateList)
    + +setInstantAppsEnabled +(boolean)
    + +setLaunchBounds +(Rect)
    + +setMovementGranularity +(AccessibilityEvent, int)
    + +setOnChildScrollUpCallback +(OnChildScrollUpCallback)
    + +setOnCloseListener +(View, OnCloseListener)
    + +setOnFlingListener +(OnFlingListener)
    + +setOnQueryTextListener +(View, OnQueryTextListener)
    + +setOverScrollMode +(View, int)
    + +setPasswordVisibilityToggleContentDescription
    +  type  +(int) in android.support.design.widget.TextInputLayout +
    + +  type  +(CharSequence) in android.support.design.widget.TextInputLayout +
    + +setPasswordVisibilityToggleDrawable
    +  type  +(Drawable) in android.support.design.widget.TextInputLayout +
    + +  type  +(int) in android.support.design.widget.TextInputLayout +
    + +setPasswordVisibilityToggleEnabled +(boolean)
    + +setPasswordVisibilityToggleTintList +(ColorStateList)
    + +setPasswordVisibilityToggleTintMode +(Mode)
    + +setSecondaryToolbarViews +(RemoteViews, int[], PendingIntent)
    + +setSelectedMediaItemNumberView +(int)
    + +setToolbarItem +(int, Bitmap, String)
    + +ShareActionProvider
    + +ShareActionProvider.OnShareTargetSelectedListener
    + +SharedElementCallback
    + +SharedElementCallback.OnSharedElementsReadyListener
    + +shouldAlwaysUseBrowserUI +(Intent)
    + +SnapHelper
    + +SortedList.Callback
    + +Space
    + +StaggeredGridLayoutManager
    + +startTracking +(KeyEvent)
    + +STOP_FOREGROUND_DETACH +
    + +STOP_FOREGROUND_REMOVE +
    + +stopForeground +(Service, int)
    + +SwipeRefreshLayout
    + +SwipeRefreshLayout.OnChildScrollUpCallback
    + +SwitchCompat
    + + +
    T  +A +B +C +D +E +F +G +H +I +K +L +M +N +O +P +R +S +V +W + TOP +

    +TabLayout
    + +TAG +
    + +TextInputLayout
    + +TextViewCompat
    + +ThemedSpinnerAdapter
    + +ThemedSpinnerAdapter.Helper
    + +toKeyCode +(long)
    + +Toolbar
    + +Toolbar.LayoutParams
    + +Toolbar.OnMenuItemClickListener
    + +Toolbar.SavedState
    + +TYPE_ASSIST_READING_CONTEXT +
    + +TYPE_SPLIT_SCREEN_DIVIDER +
    + +TYPE_VIEW_CONTEXT_CLICKED +
    + +TYPE_WINDOWS_CHANGED +
    + + +
    V  +A +B +C +D +E +F +G +H +I +K +L +M +N +O +P +R +S +T +W + TOP +

    +ViewCompat
    + +ViewConfigurationCompat
    + + +
    W  +A +B +C +D +E +F +G +H +I +K +L +M +N +O +P +R +S +T +V + TOP +

    +WindowInsetsCompat
    +  android.support.v4.view
    + +  WindowInsetsCompat +(WindowInsetsCompat) constructor
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_changes.html new file mode 100644 index 0000000000000000000000000000000000000000..4718b46ab1ce22376047052ed7eb161f3842d5e2 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_changes.html @@ -0,0 +1,666 @@ + + + + + + + + + +All Changes Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Differences +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + + +
    A  +B +C +D +F +G +I +K +L +M +O +P +R +S +T +V +W + TOP +

    +AbstractMediaItemPresenter
    + +AbstractMediaItemPresenter.ViewHolder
    + +AccessibilityEventCompat
    + +AccessibilityManagerCompat
    + +AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat
    + +AccessibilityNodeInfoCompat
    + +AccessibilityNodeInfoCompat.AccessibilityActionCompat
    + +AccessibilityNodeInfoCompat.CollectionInfoCompat
    + +AccessibilityNodeInfoCompat.CollectionItemInfoCompat
    + +AccessibilityNodeInfoCompat.RangeInfoCompat
    + +AccessibilityNodeProviderCompat
    + +AccessibilityServiceInfoCompat
    + +AccessibilityWindowInfoCompat
    + +ActionBarDrawerToggle
    + +ActivityCompat
    +  android.support.v4.app
    + +  ActivityCompat +() constructor
    + +ActivityOptionsCompat
    + +addAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    + +android.support.customtabs
    + +android.support.design.widget
    + +android.support.v14.preference
    + +android.support.v17.leanback.widget
    + +android.support.v17.preference
    + +android.support.v4.accessibilityservice
    + +android.support.v4.app
    + +android.support.v4.content
    + +android.support.v4.graphics.drawable
    + +android.support.v4.media
    + +android.support.v4.media.session
    + +android.support.v4.os
    + +android.support.v4.util
    + +android.support.v4.view
    + +android.support.v4.view.accessibility
    + +android.support.v4.widget
    + +android.support.v7.app
    + +android.support.v7.content.res
    + +android.support.v7.graphics
    + +android.support.v7.preference
    + +android.support.v7.util
    + +android.support.v7.widget
    + +AppBarLayout.ScrollingViewBehavior
    + +AppCompatDelegate
    + +AppCompatResources
    + + +
    B  +A +C +D +F +G +I +K +L +M +O +P +R +S +T +V +W + TOP +

    +BottomSheetBehavior
    + +BuildCompat
    + + +
    C  +A +B +D +F +G +I +K +L +M +O +P +R +S +T +V +W + TOP +

    +CollapsingToolbarLayout
    + +computeScrollVectorForPosition +(int)
    + +ContextCompat
    +  android.support.v4.content
    + +  ContextCompat +() constructor
    + +CoordinatorLayout
    + +CoordinatorLayout.Behavior
    + +CoordinatorLayout.LayoutParams
    + +CustomTabsIntent
    + +CustomTabsIntent.Builder
    + +CustomTabsSession
    + + +
    D  +A +B +C +F +G +I +K +L +M +O +P +R +S +T +V +W + TOP +

    +dispatch +(KeyEvent, Callback, Object, Object)
    + +DrawableCompat
    + + +
    F  +A +B +C +D +G +I +K +L +M +O +P +R +S +T +V +W + TOP +

    +findPointerIndex +(MotionEvent, int)
    + +FloatingActionButton.Behavior
    + +FragmentController
    + + +
    G  +A +B +C +D +F +I +K +L +M +O +P +R +S +T +V +W + TOP +

    +getDescription +(AccessibilityServiceInfo)
    + +getKeyDispatcherState +(View)
    + +getOverScrollMode +(View)
    + +getPointerCount +(MotionEvent)
    + +getPointerId +(MotionEvent, int)
    + +getReferrer +(Activity)
    + +getScaledPagingTouchSlop +(ViewConfiguration)
    + +getSource +(MotionEvent)
    + +getX +(MotionEvent, int)
    + +getY +(MotionEvent, int)
    + + +
    I  +A +B +C +D +F +G +K +L +M +O +P +R +S +T +V +W + TOP +

    +isDirty +(CoordinatorLayout, V)
    + +isOpaque +(View)
    + +isTracking +(KeyEvent)
    + + +
    K  +A +B +C +D +F +G +I +L +M +O +P +R +S +T +V +W + TOP +

    +KeyEventCompat
    + + +
    L  +A +B +C +D +F +G +I +K +M +O +P +R +S +T +V +W + TOP +

    +LeanbackSettingsFragment
    + +LinearLayoutManager
    + +LinearSmoothScroller
    + + +
    M  +A +B +C +D +F +G +I +K +L +O +P +R +S +T +V +W + TOP +

    +MediaBrowserCompat.MediaItem
    + +MediaBrowserServiceCompat.BrowserRoot
    + +MediaButtonReceiver
    + +MediaDescriptionCompat
    + +MediaMetadataCompat
    + +MediaSessionCompat
    + +MediaSessionCompat.QueueItem
    + +MotionEventCompat
    + + +
    O  +A +B +C +D +F +G +I +K +L +M +P +R +S +T +V +W + TOP +

    +ObjectAdapter
    + +obtain
    +  type  +(Context, Object) in android.support.v4.media.session.MediaSessionCompat +
    + +  type  +(Object) in android.support.v4.media.session.MediaSessionCompat.QueueItem +
    + +OVER_SCROLL_ALWAYS +
    + +OVER_SCROLL_IF_CONTENT_SCROLLS +
    + +OVER_SCROLL_NEVER +
    + + +
    P  +A +B +C +D +F +G +I +K +L +M +O +R +S +T +V +W + TOP +

    +Palette
    + +PlaybackStateCompat
    + +PreferenceFragment
    + + +
    R  +A +B +C +D +F +G +I +K +L +M +O +P +S +T +V +W + TOP +

    +RecyclerView
    + +removeAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    + + +
    S  +A +B +C +D +F +G +I +K +L +M +O +P +R +T +V +W + TOP +

    +SearchViewCompat
    + +SearchViewCompat.OnCloseListenerCompat
    + +SearchViewCompat.OnQueryTextListenerCompat
    + +ServiceCompat
    + +setOnCloseListener +(View, OnCloseListener)
    + +setOnQueryTextListener +(View, OnQueryTextListener)
    + +setOverScrollMode +(View, int)
    + +setToolbarItem +(int, Bitmap, String)
    + +SharedElementCallback
    + +SortedList.Callback
    + +StaggeredGridLayoutManager
    + +startTracking +(KeyEvent)
    + +SwipeRefreshLayout
    + + +
    T  +A +B +C +D +F +G +I +K +L +M +O +P +R +S +V +W + TOP +

    +TabLayout
    + +TextInputLayout
    + +TextViewCompat
    + + +
    V  +A +B +C +D +F +G +I +K +L +M +O +P +R +S +T +W + TOP +

    +ViewCompat
    + +ViewConfigurationCompat
    + + +
    W  +A +B +C +D +F +G +I +K +L +M +O +P +R +S +T +V + TOP +

    +WindowInsetsCompat
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_removals.html new file mode 100644 index 0000000000000000000000000000000000000000..179472a322665a00499f8d6ca7928cc1a3cb2262 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/alldiffs_index_removals.html @@ -0,0 +1,124 @@ + + + + + + + + + +All Removals Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Differences +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + + +android.support.v7.appcompat
    + +android.support.v7.recyclerview
    + +android.support.v8.renderscript
    + + +
    L  +A +O +P +T + TOP +

    +layoutDependsOn +(CoordinatorLayout, FloatingActionButton, View)
    + + +
    O  +A +L +P +T + TOP +

    +onAccessibilityStateChanged +(boolean)
    + +onDependentViewRemoved +(CoordinatorLayout, FloatingActionButton, View)
    + +onInserted +(int, int)
    + +onMoved +(int, int)
    + +onRemoved +(int, int)
    + + +
    P  +A +L +O +T + TOP +

    +prepareForDrop +(View, View, int, int)
    + + +
    T  +A +L +O +P + TOP +

    +TAG +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html new file mode 100644 index 0000000000000000000000000000000000000000..41ac3685bdaebbdcae175e960c0e8d398311c384 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.Builder.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.customtabs.CustomTabsIntent.Builder + + + + + + + + + + +
    +
    +
    +

    +Class android.support.customtabs.CustomTabsIntent.Builder +

    + + +

    + + + + + + + + +
    Added Methods +
    + + Builder setInstantAppsEnabled(boolean) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.html new file mode 100644 index 0000000000000000000000000000000000000000..c4f0bfb104678d904349aa371ffd19509ee73338 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsIntent.html @@ -0,0 +1,144 @@ + + + + + + + + + +android.support.customtabs.CustomTabsIntent + + + + + + + + + + +
    +
    +
    +

    +Class android.support.customtabs.CustomTabsIntent +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + Intent setAlwaysUseBrowserUI(Intent) +  
    + + boolean shouldAlwaysUseBrowserUI(Intent) +  
    +  + +

    + + + + + + + + +
    Added Fields +
    + + String EXTRA_ENABLE_INSTANT_APPS +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsSession.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsSession.html new file mode 100644 index 0000000000000000000000000000000000000000..1ccaab30114c51fcaebe43e7c8a5c58afa106952 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.customtabs.CustomTabsSession.html @@ -0,0 +1,140 @@ + + + + + + + + + +android.support.customtabs.CustomTabsSession + + + + + + + + + + +
    +
    +
    +

    +Class android.support.customtabs.CustomTabsSession +

    + + +

    + + + + + + + + +
    Added Methods +
    + + boolean setSecondaryToolbarViews(RemoteViews, int[], PendingIntent) +  
    +  +

    + + + + + + + + + +
    Changed Methods +
    + + boolean setToolbarItem(int, Bitmap, String) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html new file mode 100644 index 0000000000000000000000000000000000000000..ad3dfd83a5b413aa79994a629dfeb957fbd3ace7 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.AppBarLayout.ScrollingViewBehavior.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.design.widget.AppBarLayout.ScrollingViewBehavior + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.AppBarLayout.ScrollingViewBehavior +

    + + +

    + + + + + + + + +
    Added Methods +
    + + boolean onRequestChildRectangleOnScreen(CoordinatorLayout, View, Rect, boolean) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.BottomSheetBehavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.BottomSheetBehavior.html new file mode 100644 index 0000000000000000000000000000000000000000..22984b8b4ccfd2c94c0dceadfb88f49a2112889e --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.BottomSheetBehavior.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.design.widget.BottomSheetBehavior + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.BottomSheetBehavior +

    + + + +

    + + + + + + + + +
    Added Fields +
    + + int PEEK_HEIGHT_AUTO +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html new file mode 100644 index 0000000000000000000000000000000000000000..a20a1edc31c1466e177a8408922201145e9b261d --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CollapsingToolbarLayout.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.design.widget.CollapsingToolbarLayout + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.CollapsingToolbarLayout +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + void setCollapsedTitleTextColor(ColorStateList) +  
    + + void setExpandedTitleTextColor(ColorStateList) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html new file mode 100644 index 0000000000000000000000000000000000000000..edc96ed9c48b15cdba89abe2b2bfbb803b2ff648 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.Behavior.html @@ -0,0 +1,161 @@ + + + + + + + + + +android.support.design.widget.CoordinatorLayout.Behavior + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.CoordinatorLayout.Behavior +

    + + +

    + + + + + + + + + + + + + + + + + + + + +
    Added Methods +
    + + boolean getInsetDodgeRect(CoordinatorLayout, V, Rect) +  
    + + void onAttachedToLayoutParams(LayoutParams) +  
    + + void onDetachedFromLayoutParams() +  
    + + boolean onRequestChildRectangleOnScreen(CoordinatorLayout, V, Rect, boolean) +  
    +  +

    + + + + + + + + + +
    Changed Methods +
    + + boolean isDirty(CoordinatorLayout, V) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.LayoutParams.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.LayoutParams.html new file mode 100644 index 0000000000000000000000000000000000000000..445da889f89614025f143229270226e51c4208d2 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.LayoutParams.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.design.widget.CoordinatorLayout.LayoutParams + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.CoordinatorLayout.LayoutParams +

    + + + +

    + + + + + + + + + + + + +
    Added Fields +
    + + int dodgeInsetEdges +  
    + + int insetEdge +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.html new file mode 100644 index 0000000000000000000000000000000000000000..3ba5c1e3b31e8989f1a3bec4571732e965e871c0 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.CoordinatorLayout.html @@ -0,0 +1,123 @@ + + + + + + + + + +android.support.design.widget.CoordinatorLayout + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.CoordinatorLayout +

    +

    Added interface android.support.v4.view.NestedScrollingParent.
    + + +

    + + + + + + + + +
    Added Methods +
    + + List<View> getDependents(View) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html new file mode 100644 index 0000000000000000000000000000000000000000..07099d61ad160c4900808750311a03db26041fba --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.FloatingActionButton.Behavior.html @@ -0,0 +1,158 @@ + + + + + + + + + +android.support.design.widget.FloatingActionButton.Behavior + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.FloatingActionButton.Behavior +

    + + +

    + + + + + + + + + + + + +
    Removed Methods +
    + + boolean layoutDependsOn(CoordinatorLayout, FloatingActionButton, View) +  
    + + void onDependentViewRemoved(CoordinatorLayout, FloatingActionButton, View) +  
    +  +

    + + + + + + + + + + + + + + + + +
    Added Methods +
    + + boolean getInsetDodgeRect(CoordinatorLayout, FloatingActionButton, Rect) +  
    + + boolean isAutoHideEnabled() +  
    + + void setAutoHideEnabled(boolean) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TabLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TabLayout.html new file mode 100644 index 0000000000000000000000000000000000000000..a09656a8efb65f74cc985bb26c543baddfb51659 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TabLayout.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.design.widget.TabLayout + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.TabLayout +

    + + +

    + + + + + + + + +
    Added Methods +
    + + void clearOnTabSelectedListeners() +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TextInputLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TextInputLayout.html new file mode 100644 index 0000000000000000000000000000000000000000..9ad13eb8cd04fecc8afda6f7f5d14ad8e3a6e02c --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.design.widget.TextInputLayout.html @@ -0,0 +1,185 @@ + + + + + + + + + +android.support.design.widget.TextInputLayout + + + + + + + + + + +
    +
    +
    +

    +Class android.support.design.widget.TextInputLayout +

    + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Methods +
    + + CharSequence getPasswordVisibilityToggleContentDescription() +  
    + + Drawable getPasswordVisibilityToggleDrawable() +  
    + + boolean isPasswordVisibilityToggleEnabled() +  
    + + void setPasswordVisibilityToggleContentDescription(int) +  
    + + void setPasswordVisibilityToggleContentDescription(CharSequence) +  
    + + void setPasswordVisibilityToggleDrawable(Drawable) +  
    + + void setPasswordVisibilityToggleDrawable(int) +  
    + + void setPasswordVisibilityToggleEnabled(boolean) +  
    + + void setPasswordVisibilityToggleTintList(ColorStateList) +  
    + + void setPasswordVisibilityToggleTintMode(Mode) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v14.preference.PreferenceFragment.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v14.preference.PreferenceFragment.html new file mode 100644 index 0000000000000000000000000000000000000000..6b23c1781f610b21f8c339b43e54a8f7b0a3edce --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v14.preference.PreferenceFragment.html @@ -0,0 +1,108 @@ + + + + + + + + + +android.support.v14.preference.PreferenceFragment + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v14.preference.PreferenceFragment +

    +

    Added interface android.support.v7.preference.DialogPreference.TargetFragment.
    + + + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder.html new file mode 100644 index 0000000000000000000000000000000000000000..9f1f00cc9d6c62013be048a3482e43e989dd333c --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder.html @@ -0,0 +1,150 @@ + + + + + + + + + +android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder +

    + + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Methods +
    + + ViewFlipper getMediaItemNumberViewFlipper() +  
    + + View getMediaItemPausedView() +  
    + + View getMediaItemPlayingView() +  
    + + void notifyPlayStateChanged() +  
    + + void setSelectedMediaItemNumberView(int) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.html new file mode 100644 index 0000000000000000000000000000000000000000..a0b0aa984a48e635f375abd5feb5b9bb250d7233 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.AbstractMediaItemPresenter.html @@ -0,0 +1,165 @@ + + + + + + + + + +android.support.v17.leanback.widget.AbstractMediaItemPresenter + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v17.leanback.widget.AbstractMediaItemPresenter +

    + + +

    + + + + + + + + + + + + + + + + +
    Added Methods +
    + + int getMediaPlayState(Object) +  
    + + void onBindMediaPlayState(ViewHolder) +  
    + + void onUnbindMediaPlayState(ViewHolder) +  
    +  + +

    + + + + + + + + + + + + + + + + +
    Added Fields +
    + + int PLAY_STATE_INITIAL +  
    + + int PLAY_STATE_PAUSED +  
    + + int PLAY_STATE_PLAYING +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html new file mode 100644 index 0000000000000000000000000000000000000000..3dad1a2b118dac1352027c4443dc62fcec248f98 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.leanback.widget.ObjectAdapter.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v17.leanback.widget.ObjectAdapter + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v17.leanback.widget.ObjectAdapter +

    + + +

    + + + + + + + + +
    Added Methods +
    + + boolean isImmediateNotifySupported() +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.preference.LeanbackSettingsFragment.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.preference.LeanbackSettingsFragment.html new file mode 100644 index 0000000000000000000000000000000000000000..690328a53b539f6b16b4934f29edc922d388e00b --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v17.preference.LeanbackSettingsFragment.html @@ -0,0 +1,108 @@ + + + + + + + + + +android.support.v17.preference.LeanbackSettingsFragment + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v17.preference.LeanbackSettingsFragment +

    +

    Added interfaces android.support.v14.preference.PreferenceFragment.OnPreferenceDisplayDialogCallback, android.support.v14.preference.PreferenceFragment.OnPreferenceStartFragmentCallback, android.support.v14.preference.PreferenceFragment.OnPreferenceStartScreenCallback.
    + + + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..a353745260f4882ad3df4b0b9678bf74fe342ee2 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat.html @@ -0,0 +1,140 @@ + + + + + + + + + +android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + String loadDescription(AccessibilityServiceInfo, PackageManager) +  
    +  +

    + + + + + + + + + +
    Changed Methods +
    + + String getDescription(AccessibilityServiceInfo) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..95b4fc69d6a00defa45ea03063735b42acfe6152 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityCompat.html @@ -0,0 +1,143 @@ + + + + + + + + + +android.support.v4.app.ActivityCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.app.ActivityCompat +

    + +

    + + + + + + + + + +
    Changed Constructors +
    + + ActivityCompat() + +Now deprecated.
    +
     
    +  + +

    + + + + + + + + + +
    Changed Methods +
    + + Uri getReferrer(Activity) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityOptionsCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityOptionsCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..e675b7fd07492679ba896a2f0a6e21db0fbcb230 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ActivityOptionsCompat.html @@ -0,0 +1,179 @@ + + + + + + + + + +android.support.v4.app.ActivityOptionsCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.app.ActivityOptionsCompat +

    + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Methods +
    + + Rect getLaunchBounds() +  
    + + ActivityOptionsCompat makeBasic() +  
    + + ActivityOptionsCompat makeClipRevealAnimation(View, int, int, int, int) +  
    + + ActivityOptionsCompat makeTaskLaunchBehind() +  
    + + void requestUsageTimeReport(PendingIntent) +  
    + + ActivityOptionsCompat setLaunchBounds(Rect) +  
    +  + +

    + + + + + + + + + + + + +
    Added Fields +
    + + String EXTRA_USAGE_TIME_REPORT +  
    + + String EXTRA_USAGE_TIME_REPORT_PACKAGES +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.FragmentController.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.FragmentController.html new file mode 100644 index 0000000000000000000000000000000000000000..dfc1a60da3733fbb1a015058e038ac4fcb3ee73c --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.FragmentController.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.app.FragmentController + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.app.FragmentController +

    + + +

    + + + + + + + + +
    Added Methods +
    + + Fragment findFragmentByWho(String) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ServiceCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ServiceCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..211a88f03b003c1f1203a19448676ab3e54dbddd --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.ServiceCompat.html @@ -0,0 +1,144 @@ + + + + + + + + + +android.support.v4.app.ServiceCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.app.ServiceCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + void stopForeground(Service, int) +  
    +  + +

    + + + + + + + + + + + + +
    Added Fields +
    + + int STOP_FOREGROUND_DETACH +  
    + + int STOP_FOREGROUND_REMOVE +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.SharedElementCallback.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.SharedElementCallback.html new file mode 100644 index 0000000000000000000000000000000000000000..73940592f2384390d5fe9766544f8968ef84851e --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.app.SharedElementCallback.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.app.SharedElementCallback + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.app.SharedElementCallback +

    + + +

    + + + + + + + + +
    Added Methods +
    + + void onSharedElementsArrived(List<String>, List<View>, OnSharedElementsReadyListener) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.content.ContextCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.content.ContextCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..b6157a2468dcd2d3e1d7974f12d3d6b056bdc096 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.content.ContextCompat.html @@ -0,0 +1,125 @@ + + + + + + + + + +android.support.v4.content.ContextCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.content.ContextCompat +

    + +

    + + + + + + + + + +
    Changed Constructors +
    + + ContextCompat() + +Now deprecated.
    +
     
    +  + + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..92f1ba40d4eef68e5e14572ccd985dd478790964 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.graphics.drawable.DrawableCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.graphics.drawable.DrawableCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.graphics.drawable.DrawableCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + void clearColorFilter(Drawable) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserCompat.MediaItem.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserCompat.MediaItem.html new file mode 100644 index 0000000000000000000000000000000000000000..52da3d4fb553a48fb5234c2b462976e4fd373f5a --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserCompat.MediaItem.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.v4.media.MediaBrowserCompat.MediaItem + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.MediaBrowserCompat.MediaItem +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + MediaItem fromMediaItem(Object) +  
    + + List<MediaItem> fromMediaItemList(List<?>) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot.html new file mode 100644 index 0000000000000000000000000000000000000000..7ea97f3bd552fc1f6176944a3f13fdd65a9b56ed --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot +

    + + + +

    + + + + + + + + +
    Added Fields +
    + + String EXTRA_SUGGESTION_KEYWORDS +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaDescriptionCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaDescriptionCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..fa1d6104143737d70b384480e9c1c1209b0d5bb2 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaDescriptionCompat.html @@ -0,0 +1,171 @@ + + + + + + + + + +android.support.v4.media.MediaDescriptionCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.MediaDescriptionCompat +

    + + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Fields +
    + + long BT_FOLDER_TYPE_ALBUMS +  
    + + long BT_FOLDER_TYPE_ARTISTS +  
    + + long BT_FOLDER_TYPE_GENRES +  
    + + long BT_FOLDER_TYPE_MIXED +  
    + + long BT_FOLDER_TYPE_PLAYLISTS +  
    + + long BT_FOLDER_TYPE_TITLES +  
    + + long BT_FOLDER_TYPE_YEARS +  
    + + String EXTRA_BT_FOLDER_TYPE +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaMetadataCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaMetadataCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..7e0f137c5744369c0132592bd6f3f51c8f0f80d2 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.MediaMetadataCompat.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.v4.media.MediaMetadataCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.MediaMetadataCompat +

    + + + +

    + + + + + + + + + + + + +
    Added Fields +
    + + String METADATA_KEY_BT_FOLDER_TYPE +  
    + + String METADATA_KEY_MEDIA_URI +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaButtonReceiver.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaButtonReceiver.html new file mode 100644 index 0000000000000000000000000000000000000000..65467b8211ea7b5b816a4783c3a1992174650a2c --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaButtonReceiver.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.v4.media.session.MediaButtonReceiver + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.session.MediaButtonReceiver +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + PendingIntent buildMediaButtonPendingIntent(Context, ComponentName, long) +  
    + + PendingIntent buildMediaButtonPendingIntent(Context, long) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.QueueItem.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.QueueItem.html new file mode 100644 index 0000000000000000000000000000000000000000..e3b018488e4ead61dc0ca2e2e5f8b1738b600204 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.QueueItem.html @@ -0,0 +1,147 @@ + + + + + + + + + +android.support.v4.media.session.MediaSessionCompat.QueueItem + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.session.MediaSessionCompat.QueueItem +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + QueueItem fromQueueItem(Object) +  
    + + List<QueueItem> fromQueueItemList(List<?>) +  
    +  +

    + + + + + + + + + +
    Changed Methods +
    + + QueueItem obtain(Object) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..90bd5eb37dba4a936e47eeeaef2061246a1f6240 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.MediaSessionCompat.html @@ -0,0 +1,140 @@ + + + + + + + + + +android.support.v4.media.session.MediaSessionCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.session.MediaSessionCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + MediaSessionCompat fromMediaSession(Context, Object) +  
    +  +

    + + + + + + + + + +
    Changed Methods +
    + + MediaSessionCompat obtain(Context, Object) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..07e2449dd3dd5f9e346c4c53ceb0efdab7bd3d6a --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.media.session.PlaybackStateCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.media.session.PlaybackStateCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.media.session.PlaybackStateCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + int toKeyCode(long) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.os.BuildCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.os.BuildCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..372415af6cee36d4787b66153c823b3719246f2f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.os.BuildCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.os.BuildCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.os.BuildCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + boolean isAtLeastNMR1() +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.KeyEventCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.KeyEventCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..d62437e0fa9f1e08f9b8a89a5176c491735af4d0 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.KeyEventCompat.html @@ -0,0 +1,155 @@ + + + + + + + + + +android.support.v4.view.KeyEventCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.KeyEventCompat +

    + + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Changed Methods +
    + + boolean dispatch(KeyEvent, Callback, Object, Object) + +Now deprecated.
    +
     
    + + Object getKeyDispatcherState(View) + +Now deprecated.
    +
     
    + + boolean isTracking(KeyEvent) + +Now deprecated.
    +
     
    + + void startTracking(KeyEvent) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.MotionEventCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.MotionEventCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..8f58037a524cc44ab793a16aef25f4185af87927 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.MotionEventCompat.html @@ -0,0 +1,175 @@ + + + + + + + + + +android.support.v4.view.MotionEventCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.MotionEventCompat +

    + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Changed Methods +
    + + int findPointerIndex(MotionEvent, int) + +Now deprecated.
    +
     
    + + int getPointerCount(MotionEvent) + +Now deprecated.
    +
     
    + + int getPointerId(MotionEvent, int) + +Now deprecated.
    +
     
    + + int getSource(MotionEvent) + +Now deprecated.
    +
     
    + + float getX(MotionEvent, int) + +Now deprecated.
    +
     
    + + float getY(MotionEvent, int) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..0974230ed4825f048804ad72afe207eee7f861b9 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewCompat.html @@ -0,0 +1,195 @@ + + + + + + + + + +android.support.v4.view.ViewCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.ViewCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + boolean isImportantForAccessibility(View) +  
    +  +

    + + + + + + + + + + + + + + + + + + + +
    Changed Methods +
    + + int getOverScrollMode(View) + +Now deprecated.
    +
     
    + + boolean isOpaque(View) + +Now deprecated.
    +
     
    + + void setOverScrollMode(View, int) + +Now deprecated.
    +
     
    +  + +

    + + + + + + + + + + + + + + + + + + + +
    Changed Fields +
    + + int OVER_SCROLL_ALWAYS +Now deprecated.
    +
     
    + + int OVER_SCROLL_IF_CONTENT_SCROLLS +Now deprecated.
    +
     
    + + int OVER_SCROLL_NEVER +Now deprecated.
    +
     
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..3eec7fa0ae9058da4f0f6a8ebb04416dc215a70c --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.ViewConfigurationCompat.html @@ -0,0 +1,125 @@ + + + + + + + + + +android.support.v4.view.ViewConfigurationCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.ViewConfigurationCompat +

    + + +

    + + + + + + + + + +
    Changed Methods +
    + + int getScaledPagingTouchSlop(ViewConfiguration) + +Now deprecated.
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.WindowInsetsCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.WindowInsetsCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..c5c1d220bff5722aaf1b9e07a0d03d2902132908 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.WindowInsetsCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.view.WindowInsetsCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.WindowInsetsCompat +

    + +

    + + + + + + + + +
    Added Constructors +
    + + WindowInsetsCompat(WindowInsetsCompat) +  
    +  + + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..1f9801f37a3fe37861d709dcd65f6ef4fca30904 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityEventCompat.html @@ -0,0 +1,172 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityEventCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityEventCompat +

    + + +

    + + + + + + + + + + + + + + + + + + + + +
    Added Methods +
    + + int getAction(AccessibilityEvent) +  
    + + int getMovementGranularity(AccessibilityEvent) +  
    + + void setAction(AccessibilityEvent, int) +  
    + + void setMovementGranularity(AccessibilityEvent, int) +  
    +  + +

    + + + + + + + + + + + + + + + + +
    Added Fields +
    + + int TYPE_ASSIST_READING_CONTEXT +  
    + + int TYPE_VIEW_CONTEXT_CLICKED +  
    + + int TYPE_WINDOWS_CHANGED +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..923ec80665cc0f2571bb88fee2116def30f03d94 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat.html @@ -0,0 +1,124 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat +

    +

    Added interface android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener.
    +

    Now deprecated.
    + + +

    + + + + + + + + +
    Removed Methods +
    + + void onAccessibilityStateChanged(boolean) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..defa406ba0e3690b943118c8df0565cfff108ba1 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityManagerCompat.html @@ -0,0 +1,157 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityManagerCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityManagerCompat +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + boolean addTouchExplorationStateChangeListener(AccessibilityManager, TouchExplorationStateChangeListener) +  
    + + boolean removeTouchExplorationStateChangeListener(AccessibilityManager, TouchExplorationStateChangeListener) +  
    +  +

    + + + + + + + + + + + + + + +
    Changed Methods +
    + + boolean addAccessibilityStateChangeListener(AccessibilityManager, AccessibilityStateChangeListener) + +Change in signature from (AccessibilityManager, AccessibilityStateChangeListenerCompat) to (AccessibilityManager, AccessibilityStateChangeListener).
    +
     
    + + boolean removeAccessibilityStateChangeListener(AccessibilityManager, AccessibilityStateChangeListener) + +Change in signature from (AccessibilityManager, AccessibilityStateChangeListenerCompat) to (AccessibilityManager, AccessibilityStateChangeListener).
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..d6f719e2bce89d93d7898091fb091f08407e9853 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat.html @@ -0,0 +1,171 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat +

    + + + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Fields +
    + + AccessibilityActionCompat ACTION_CONTEXT_CLICK +  
    + + AccessibilityActionCompat ACTION_SCROLL_DOWN +  
    + + AccessibilityActionCompat ACTION_SCROLL_LEFT +  
    + + AccessibilityActionCompat ACTION_SCROLL_RIGHT +  
    + + AccessibilityActionCompat ACTION_SCROLL_TO_POSITION +  
    + + AccessibilityActionCompat ACTION_SCROLL_UP +  
    + + AccessibilityActionCompat ACTION_SET_PROGRESS +  
    + + AccessibilityActionCompat ACTION_SHOW_ON_SCREEN +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..d087e4a771735e0b733c842218e6eda766e2972a --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + int getSelectionMode() +  
    + + CollectionInfoCompat obtain(int, int, boolean) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..84fc73b92cb2d969c418fedaaa7b6924edff92c4 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + CollectionItemInfoCompat obtain(int, int, int, int, boolean) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..41abf7ef725ac4d1ff50cb22fe47b114cf1b36ab --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + RangeInfoCompat obtain(int, float, float, float) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..005616afe0a1522806d1ef4be296ea06662ddf14 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.html @@ -0,0 +1,158 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityNodeInfoCompat +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + boolean isContextClickable() +  
    + + void setContextClickable(boolean) +  
    +  + +

    + + + + + + + + + + + + + + + + +
    Added Fields +
    + + String ACTION_ARGUMENT_COLUMN_INT +  
    + + String ACTION_ARGUMENT_PROGRESS_VALUE +  
    + + String ACTION_ARGUMENT_ROW_INT +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeProviderCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeProviderCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..bd6b7f8736c15813086273da63e5b87a73e6e6fd --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityNodeProviderCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityNodeProviderCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityNodeProviderCompat +

    + + + +

    + + + + + + + + +
    Added Fields +
    + + int HOST_VIEW_ID +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityWindowInfoCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityWindowInfoCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..40f3ca2bbd9f833bebb6ae7600772856d92221dc --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.view.accessibility.AccessibilityWindowInfoCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.view.accessibility.AccessibilityWindowInfoCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.view.accessibility.AccessibilityWindowInfoCompat +

    + + + +

    + + + + + + + + +
    Added Fields +
    + + int TYPE_SPLIT_SCREEN_DIVIDER +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..3d9f2eaed0d5a5d5bbe72fce424a52ffc8d69e49 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat.html @@ -0,0 +1,109 @@ + + + + + + + + + +android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat +

    +

    Added interface android.support.v4.widget.SearchViewCompat.OnCloseListener.
    +

    Now deprecated.
    + + + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..df0f3e1d9dce2c5976c5dd108a84d1ff358b6829 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat.html @@ -0,0 +1,109 @@ + + + + + + + + + +android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat +

    +

    Added interface android.support.v4.widget.SearchViewCompat.OnQueryTextListener.
    +

    Now deprecated.
    + + + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..4af1e4641ad695babfa4370593c3165036508f91 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SearchViewCompat.html @@ -0,0 +1,135 @@ + + + + + + + + + +android.support.v4.widget.SearchViewCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.widget.SearchViewCompat +

    + + +

    + + + + + + + + + + + + + + +
    Changed Methods +
    + + void setOnCloseListener(View, OnCloseListener) + +Change in signature from (View, OnCloseListenerCompat) to (View, OnCloseListener).
    +
     
    + + void setOnQueryTextListener(View, OnQueryTextListener) + +Change in signature from (View, OnQueryTextListenerCompat) to (View, OnQueryTextListener).
    +
     
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SwipeRefreshLayout.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SwipeRefreshLayout.html new file mode 100644 index 0000000000000000000000000000000000000000..584878231ad80c91f109d492771701d660c09f7f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.SwipeRefreshLayout.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.widget.SwipeRefreshLayout + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.widget.SwipeRefreshLayout +

    + + +

    + + + + + + + + +
    Added Methods +
    + + void setOnChildScrollUpCallback(OnChildScrollUpCallback) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.TextViewCompat.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.TextViewCompat.html new file mode 100644 index 0000000000000000000000000000000000000000..87b9e6940c8482c1e9e60a2008ef889d3c2bfaea --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v4.widget.TextViewCompat.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v4.widget.TextViewCompat + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v4.widget.TextViewCompat +

    + + +

    + + + + + + + + +
    Added Methods +
    + + Drawable[] getCompoundDrawablesRelative(TextView) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.ActionBarDrawerToggle.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.ActionBarDrawerToggle.html new file mode 100644 index 0000000000000000000000000000000000000000..bc8abd6fd70bdad0b35a5bfcd10e2c5b6bc289d2 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.ActionBarDrawerToggle.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.v7.app.ActionBarDrawerToggle + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.app.ActionBarDrawerToggle +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + DrawerArrowDrawable getDrawerArrowDrawable() +  
    + + void setDrawerArrowDrawable(DrawerArrowDrawable) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.AppCompatDelegate.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.AppCompatDelegate.html new file mode 100644 index 0000000000000000000000000000000000000000..7b131e65792d356827efb3506ba1e0902f8cf749 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.app.AppCompatDelegate.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v7.app.AppCompatDelegate + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.app.AppCompatDelegate +

    + + +

    + + + + + + + + +
    Added Methods +
    + + void onStart() +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.content.res.AppCompatResources.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.content.res.AppCompatResources.html new file mode 100644 index 0000000000000000000000000000000000000000..02f43fd180a8e2fa8593bb442185f23ff69732c7 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.content.res.AppCompatResources.html @@ -0,0 +1,122 @@ + + + + + + + + + +android.support.v7.content.res.AppCompatResources + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.content.res.AppCompatResources +

    + + +

    + + + + + + + + +
    Added Methods +
    + + Drawable getDrawable(Context, int) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.graphics.Palette.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.graphics.Palette.html new file mode 100644 index 0000000000000000000000000000000000000000..1999a489db4e173deda62d33b016693799430fb0 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.graphics.Palette.html @@ -0,0 +1,129 @@ + + + + + + + + + +android.support.v7.graphics.Palette + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.graphics.Palette +

    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + int getDominantColor(int) +  
    + + Swatch getDominantSwatch() +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.util.SortedList.Callback.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.util.SortedList.Callback.html new file mode 100644 index 0000000000000000000000000000000000000000..95be79c8931185be9c68a564344e516ee1828e93 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.util.SortedList.Callback.html @@ -0,0 +1,152 @@ + + + + + + + + + +android.support.v7.util.SortedList.Callback + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.util.SortedList.Callback +

    +

    Added interface android.support.v7.util.ListUpdateCallback.
    + + +

    + + + + + + + + + + + + + + + + +
    Removed Methods +
    + + void onInserted(int, int) +  
    + + void onMoved(int, int) +  
    + + void onRemoved(int, int) +  
    +  +

    + + + + + + + + +
    Added Methods +
    + + void onChanged(int, int, Object) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearLayoutManager.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearLayoutManager.html new file mode 100644 index 0000000000000000000000000000000000000000..2fdfb0e44fbead7ce15b1a0488e5d09876c3585f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearLayoutManager.html @@ -0,0 +1,123 @@ + + + + + + + + + +android.support.v7.widget.LinearLayoutManager + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.widget.LinearLayoutManager +

    +

    Added interface android.support.v7.widget.RecyclerView.SmoothScroller.ScrollVectorProvider.
    + + +

    + + + + + + + + +
    Removed Methods +
    + + void prepareForDrop(View, View, int, int) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearSmoothScroller.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearSmoothScroller.html new file mode 100644 index 0000000000000000000000000000000000000000..5cf79ee33512d87249575a29b041200903f6834a --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.LinearSmoothScroller.html @@ -0,0 +1,126 @@ + + + + + + + + + +android.support.v7.widget.LinearSmoothScroller + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.widget.LinearSmoothScroller +

    +

    Changed from abstract to non-abstract. + + +

    + + + + + + + + + +
    Changed Methods +
    + + PointF computeScrollVectorForPosition(int) + +Changed from abstract to non-abstract. +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.RecyclerView.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.RecyclerView.html new file mode 100644 index 0000000000000000000000000000000000000000..5411a1f7836407f2bf2e25e4564d5f28fe848ef9 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.RecyclerView.html @@ -0,0 +1,130 @@ + + + + + + + + + +android.support.v7.widget.RecyclerView + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.widget.RecyclerView +

    +

    Added interfaces android.support.v4.view.NestedScrollingChild, android.support.v4.view.ScrollingView.
    + + +

    + + + + + + + + + + + + +
    Added Methods +
    + + OnFlingListener getOnFlingListener() +  
    + + void setOnFlingListener(OnFlingListener) +  
    +  + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.StaggeredGridLayoutManager.html b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.StaggeredGridLayoutManager.html new file mode 100644 index 0000000000000000000000000000000000000000..9d0ab875b5142103f78e1223d581ba58edb7fe2d --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/android.support.v7.widget.StaggeredGridLayoutManager.html @@ -0,0 +1,138 @@ + + + + + + + + + +android.support.v7.widget.StaggeredGridLayoutManager + + + + + + + + + + +
    +
    +
    +

    +Class android.support.v7.widget.StaggeredGridLayoutManager +

    +

    Added interface android.support.v7.widget.RecyclerView.SmoothScroller.ScrollVectorProvider.
    + + +

    + + + + + + + + +
    Added Methods +
    + + PointF computeScrollVectorForPosition(int) +  
    +  + +

    + + + + + + + + +
    Removed Fields +
    + + String TAG +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/changes-summary.html b/docs/html/sdk/support_api_diff/24.2.0/changes/changes-summary.html new file mode 100644 index 0000000000000000000000000000000000000000..4456c22e156b12b3202e04e9c7a0107a9ca5fda0 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/changes-summary.html @@ -0,0 +1,329 @@ + + + + + + + + + +Support Library API Differences Report + + + + + + + + + + +
    +
    +
    +
    +

    Support Library API Differences Report

    +

    This report details the changes in the Android Support Library API between two versions. +It shows additions, modifications, and removals for packages, classes, methods, and fields. +The report also includes general statistics that characterize the extent and type of the differences.

    +

    This report is based a comparison of the Support Library API specifications +whose version level identifiers are given in the upper-right corner of this page. It compares a +newer "to" version's API to an older "from" version's API, noting all changes relative to the +older API. So, for example, API elements marked as removed are no longer present in the "to" +API specification.

    +

    To navigate the report, use the "Select a Diffs Index" and "Filter the Index" +controls on the left. The report uses text formatting to indicate interface names, +links to reference documentation, and links to change +description. The statistics are accessible from the "Statistics" link in the upper-right corner.

    +

    For more information about the Android API and SDK, +see the Android Developers site.

    +

    + + + + + + + + + + + + + + + + +
    Removed Packages +
    + + android.support.v7.appcompat  
    + + android.support.v7.recyclerview  
    + + android.support.v8.renderscript  
    +  +

    + + + + + + + + + + + + +
    Added Packages +
    + + android.support.transition +  
    + + android.support.v4.text.util +  
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Changed Packages +
    + + android.support.customtabs +  
    + + android.support.design.widget +  
    + + android.support.v14.preference +  
    + + android.support.v17.leanback.widget +  
    + + android.support.v17.preference +  
    + + android.support.v4.accessibilityservice +  
    + + android.support.v4.app +  
    + + android.support.v4.content +  
    + + android.support.v4.graphics.drawable +  
    + + android.support.v4.media +  
    + + android.support.v4.media.session +  
    + + android.support.v4.os +  
    + + android.support.v4.util +  
    + + android.support.v4.view +  
    + + android.support.v4.view.accessibility +  
    + + android.support.v4.widget +  
    + + android.support.v7.app +  
    + + android.support.v7.content.res +  
    + + android.support.v7.graphics +  
    + + android.support.v7.preference +  
    + + android.support.v7.util +  
    + + android.support.v7.widget +  
    +  + + +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_additions.html new file mode 100644 index 0000000000000000000000000000000000000000..acb81154536d709dd190387dccb655c32ee1f61f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_additions.html @@ -0,0 +1,305 @@ + + + + + + + + + +Class Additions Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Classes +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +B +C +D +G +L +M +N +P +R +S +T + TOP +

    +AccessibilityManagerCompat.AccessibilityStateChangeListener
    +AccessibilityManagerCompat.TouchExplorationStateChangeListener
    +ActionBarActivity
    +ActionMenuView
    +ActionMenuView.LayoutParams
    +ActionMenuView.OnMenuItemClickListener
    +AppCompatActivity
    +AppCompatAutoCompleteTextView
    +AppCompatButton
    +AppCompatCheckBox
    +AppCompatCheckedTextView
    +AppCompatDialogFragment
    +AppCompatEditText
    +AppCompatImageButton
    +AppCompatImageView
    +AppCompatMultiAutoCompleteTextView
    +AppCompatRadioButton
    +AppCompatRatingBar
    +AppCompatSeekBar
    +AppCompatSpinner
    +AppCompatTextView
    + +
    B  +A +C +D +G +L +M +N +P +R +S +T + TOP +

    +BatchingListUpdateCallback
    + +
    C  +A +B +D +G +L +M +N +P +R +S +T + TOP +

    +CardView
    + +
    D  +A +B +C +G +L +M +N +P +R +S +T + TOP +

    +DiffUtil
    +DiffUtil.Callback
    +DiffUtil.DiffResult
    + +
    G  +A +B +C +D +L +M +N +P +R +S +T + TOP +

    +GridLayout
    +GridLayout.Alignment
    +GridLayout.LayoutParams
    +GridLayout.Spec
    + +
    L  +A +B +C +D +G +M +N +P +R +S +T + TOP +

    +LinearLayoutCompat
    +LinearLayoutCompat.LayoutParams
    +LinearSnapHelper
    +ListPopupWindow
    +ListUpdateCallback
    + +
    M  +A +B +C +D +G +L +N +P +R +S +T + TOP +

    +MultiSelectListPreferenceDialogFragmentCompat
    + +
    N  +A +B +C +D +G +L +M +P +R +S +T + TOP +

    +NotificationCompat
    +NotificationCompat.Builder
    +NotificationCompat.MediaStyle
    + +
    P  +A +B +C +D +G +L +M +N +R +S +T + TOP +

    +PatternsCompat
    +PopupMenu
    +PopupMenu.OnDismissListener
    +PopupMenu.OnMenuItemClickListener
    + +
    R  +A +B +C +D +G +L +M +N +P +S +T + TOP +

    +RecyclerView.OnFlingListener
    +RecyclerView.SmoothScroller.ScrollVectorProvider
    + +
    S  +A +B +C +D +G +L +M +N +P +R +T + TOP +

    +SearchView
    +SearchView.OnCloseListener
    +SearchView.OnQueryTextListener
    +SearchView.OnSuggestionListener
    +SearchViewCompat.OnCloseListener
    +SearchViewCompat.OnQueryTextListener
    +ShareActionProvider
    +ShareActionProvider.OnShareTargetSelectedListener
    +SharedElementCallback.OnSharedElementsReadyListener
    +SnapHelper
    +Space
    +SwipeRefreshLayout.OnChildScrollUpCallback
    +SwitchCompat
    + +
    T  +A +B +C +D +G +L +M +N +P +R +S + TOP +

    +ThemedSpinnerAdapter
    +ThemedSpinnerAdapter.Helper
    +Toolbar
    +Toolbar.LayoutParams
    +Toolbar.OnMenuItemClickListener
    +Toolbar.SavedState
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_all.html new file mode 100644 index 0000000000000000000000000000000000000000..3e77bf2de1554839a925a3d791bf40c3d16a8809 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_all.html @@ -0,0 +1,528 @@ + + + + + + + + + +Class Differences Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +Classes +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +B +C +D +F +G +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +AbstractMediaItemPresenter
    +AbstractMediaItemPresenter.ViewHolder
    +AccessibilityEventCompat
    +AccessibilityManagerCompat
    +AccessibilityManagerCompat.AccessibilityStateChangeListener
    +AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat
    +AccessibilityManagerCompat.TouchExplorationStateChangeListener
    +AccessibilityNodeInfoCompat
    +AccessibilityNodeInfoCompat.AccessibilityActionCompat
    +AccessibilityNodeInfoCompat.CollectionInfoCompat
    +AccessibilityNodeInfoCompat.CollectionItemInfoCompat
    +AccessibilityNodeInfoCompat.RangeInfoCompat
    +AccessibilityNodeProviderCompat
    +AccessibilityServiceInfoCompat
    +AccessibilityWindowInfoCompat
    +ActionBarActivity
    +ActionBarDrawerToggle
    +ActionMenuView
    +ActionMenuView.LayoutParams
    +ActionMenuView.OnMenuItemClickListener
    +ActivityCompat
    +ActivityOptionsCompat
    +AppBarLayout.ScrollingViewBehavior
    +AppCompatActivity
    +AppCompatAutoCompleteTextView
    +AppCompatButton
    +AppCompatCheckBox
    +AppCompatCheckedTextView
    +AppCompatDelegate
    +AppCompatDialogFragment
    +AppCompatEditText
    +AppCompatImageButton
    +AppCompatImageView
    +AppCompatMultiAutoCompleteTextView
    +AppCompatRadioButton
    +AppCompatRatingBar
    +AppCompatResources
    +AppCompatSeekBar
    +AppCompatSpinner
    +AppCompatTextView
    + +
    B  +A +C +D +F +G +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +BatchingListUpdateCallback
    +BottomSheetBehavior
    +BuildCompat
    + +
    C  +A +B +D +F +G +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +CardView
    +CollapsingToolbarLayout
    +ContextCompat
    +CoordinatorLayout
    +CoordinatorLayout.Behavior
    +CoordinatorLayout.LayoutParams
    +CustomTabsIntent
    +CustomTabsIntent.Builder
    +CustomTabsSession
    + +
    D  +A +B +C +F +G +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +DiffUtil
    +DiffUtil.Callback
    +DiffUtil.DiffResult
    +DrawableCompat
    + +
    F  +A +B +C +D +G +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +FloatingActionButton.Behavior
    +FragmentController
    + +
    G  +A +B +C +D +F +K +L +M +N +O +P +R +S +T +V +W + TOP +

    +GridLayout
    +GridLayout.Alignment
    +GridLayout.LayoutParams
    +GridLayout.Spec
    + +
    K  +A +B +C +D +F +G +L +M +N +O +P +R +S +T +V +W + TOP +

    +KeyEventCompat
    + +
    L  +A +B +C +D +F +G +K +M +N +O +P +R +S +T +V +W + TOP +

    +LeanbackSettingsFragment
    +LinearLayoutCompat
    +LinearLayoutCompat.LayoutParams
    +LinearLayoutManager
    +LinearSmoothScroller
    +LinearSnapHelper
    +ListPopupWindow
    +ListUpdateCallback
    + +
    M  +A +B +C +D +F +G +K +L +N +O +P +R +S +T +V +W + TOP +

    +MediaBrowserCompat.MediaItem
    +MediaBrowserServiceCompat.BrowserRoot
    +MediaButtonReceiver
    +MediaDescriptionCompat
    +MediaMetadataCompat
    +MediaSessionCompat
    +MediaSessionCompat.QueueItem
    +MotionEventCompat
    +MultiSelectListPreferenceDialogFragmentCompat
    + +
    N  +A +B +C +D +F +G +K +L +M +O +P +R +S +T +V +W + TOP +

    +NotificationCompat
    +NotificationCompat.Builder
    +NotificationCompat.MediaStyle
    + +
    O  +A +B +C +D +F +G +K +L +M +N +P +R +S +T +V +W + TOP +

    +ObjectAdapter
    + +
    P  +A +B +C +D +F +G +K +L +M +N +O +R +S +T +V +W + TOP +

    +Palette
    +PatternsCompat
    +PlaybackStateCompat
    +PopupMenu
    +PopupMenu.OnDismissListener
    +PopupMenu.OnMenuItemClickListener
    +PreferenceFragment
    + +
    R  +A +B +C +D +F +G +K +L +M +N +O +P +S +T +V +W + TOP +

    +RecyclerView
    +RecyclerView.OnFlingListener
    +RecyclerView.SmoothScroller.ScrollVectorProvider
    + +
    S  +A +B +C +D +F +G +K +L +M +N +O +P +R +T +V +W + TOP +

    +SearchView
    +SearchView.OnCloseListener
    +SearchView.OnQueryTextListener
    +SearchView.OnSuggestionListener
    +SearchViewCompat
    +SearchViewCompat.OnCloseListener
    +SearchViewCompat.OnCloseListenerCompat
    +SearchViewCompat.OnQueryTextListener
    +SearchViewCompat.OnQueryTextListenerCompat
    +ServiceCompat
    +ShareActionProvider
    +ShareActionProvider.OnShareTargetSelectedListener
    +SharedElementCallback
    +SharedElementCallback.OnSharedElementsReadyListener
    +SnapHelper
    +SortedList.Callback
    +Space
    +StaggeredGridLayoutManager
    +SwipeRefreshLayout
    +SwipeRefreshLayout.OnChildScrollUpCallback
    +SwitchCompat
    + +
    T  +A +B +C +D +F +G +K +L +M +N +O +P +R +S +V +W + TOP +

    +TabLayout
    +TextInputLayout
    +TextViewCompat
    +ThemedSpinnerAdapter
    +ThemedSpinnerAdapter.Helper
    +Toolbar
    +Toolbar.LayoutParams
    +Toolbar.OnMenuItemClickListener
    +Toolbar.SavedState
    + +
    V  +A +B +C +D +F +G +K +L +M +N +O +P +R +S +T +W + TOP +

    +ViewCompat
    +ViewConfigurationCompat
    + +
    W  +A +B +C +D +F +G +K +L +M +N +O +P +R +S +T +V + TOP +

    +WindowInsetsCompat
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_changes.html new file mode 100644 index 0000000000000000000000000000000000000000..58fe615bd673f7357e29b536edf8c7b93b8c34ad --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_changes.html @@ -0,0 +1,394 @@ + + + + + + + + + +Class Changes Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Classes +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +B +C +D +F +K +L +M +O +P +R +S +T +V +W + TOP +

    +AbstractMediaItemPresenter
    +AbstractMediaItemPresenter.ViewHolder
    +AccessibilityEventCompat
    +AccessibilityManagerCompat
    +AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat
    +AccessibilityNodeInfoCompat
    +AccessibilityNodeInfoCompat.AccessibilityActionCompat
    +AccessibilityNodeInfoCompat.CollectionInfoCompat
    +AccessibilityNodeInfoCompat.CollectionItemInfoCompat
    +AccessibilityNodeInfoCompat.RangeInfoCompat
    +AccessibilityNodeProviderCompat
    +AccessibilityServiceInfoCompat
    +AccessibilityWindowInfoCompat
    +ActionBarDrawerToggle
    +ActivityCompat
    +ActivityOptionsCompat
    +AppBarLayout.ScrollingViewBehavior
    +AppCompatDelegate
    +AppCompatResources
    + +
    B  +A +C +D +F +K +L +M +O +P +R +S +T +V +W + TOP +

    +BottomSheetBehavior
    +BuildCompat
    + +
    C  +A +B +D +F +K +L +M +O +P +R +S +T +V +W + TOP +

    +CollapsingToolbarLayout
    +ContextCompat
    +CoordinatorLayout
    +CoordinatorLayout.Behavior
    +CoordinatorLayout.LayoutParams
    +CustomTabsIntent
    +CustomTabsIntent.Builder
    +CustomTabsSession
    + +
    D  +A +B +C +F +K +L +M +O +P +R +S +T +V +W + TOP +

    +DrawableCompat
    + +
    F  +A +B +C +D +K +L +M +O +P +R +S +T +V +W + TOP +

    +FloatingActionButton.Behavior
    +FragmentController
    + +
    K  +A +B +C +D +F +L +M +O +P +R +S +T +V +W + TOP +

    +KeyEventCompat
    + +
    L  +A +B +C +D +F +K +M +O +P +R +S +T +V +W + TOP +

    +LeanbackSettingsFragment
    +LinearLayoutManager
    +LinearSmoothScroller
    + +
    M  +A +B +C +D +F +K +L +O +P +R +S +T +V +W + TOP +

    +MediaBrowserCompat.MediaItem
    +MediaBrowserServiceCompat.BrowserRoot
    +MediaButtonReceiver
    +MediaDescriptionCompat
    +MediaMetadataCompat
    +MediaSessionCompat
    +MediaSessionCompat.QueueItem
    +MotionEventCompat
    + +
    O  +A +B +C +D +F +K +L +M +P +R +S +T +V +W + TOP +

    +ObjectAdapter
    + +
    P  +A +B +C +D +F +K +L +M +O +R +S +T +V +W + TOP +

    +Palette
    +PlaybackStateCompat
    +PreferenceFragment
    + +
    R  +A +B +C +D +F +K +L +M +O +P +S +T +V +W + TOP +

    +RecyclerView
    + +
    S  +A +B +C +D +F +K +L +M +O +P +R +T +V +W + TOP +

    +SearchViewCompat
    +SearchViewCompat.OnCloseListenerCompat
    +SearchViewCompat.OnQueryTextListenerCompat
    +ServiceCompat
    +SharedElementCallback
    +SortedList.Callback
    +StaggeredGridLayoutManager
    +SwipeRefreshLayout
    + +
    T  +A +B +C +D +F +K +L +M +O +P +R +S +V +W + TOP +

    +TabLayout
    +TextInputLayout
    +TextViewCompat
    + +
    V  +A +B +C +D +F +K +L +M +O +P +R +S +T +W + TOP +

    +ViewCompat
    +ViewConfigurationCompat
    + +
    W  +A +B +C +D +F +K +L +M +O +P +R +S +T +V + TOP +

    +WindowInsetsCompat
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_removals.html new file mode 100644 index 0000000000000000000000000000000000000000..c4662980dd5072a333f43a43da051574c917886c --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/classes_index_removals.html @@ -0,0 +1,61 @@ + + + + + + + + + +Class Removals Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Classes +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_additions.html new file mode 100644 index 0000000000000000000000000000000000000000..312effc0f2c07ffe7af615714fef905d801197bf --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_additions.html @@ -0,0 +1,67 @@ + + + + + + + + + +Constructor Additions Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Constructors +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    W  + TOP +

    +WindowInsetsCompat +(WindowInsetsCompat) constructor
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_all.html new file mode 100644 index 0000000000000000000000000000000000000000..24310b7728cc030f967dfcb3e0a7a9ec0c6a2be7 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_all.html @@ -0,0 +1,85 @@ + + + + + + + + + +Constructor Differences Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +Constructors +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +C +W + TOP +

    +ActivityCompat +() constructor
    + +
    C  +A +W + TOP +

    +ContextCompat +() constructor
    + +
    W  +A +C + TOP +

    +WindowInsetsCompat +(WindowInsetsCompat) constructor
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_changes.html new file mode 100644 index 0000000000000000000000000000000000000000..62a75f8ccb38d4058b825735b546a03f562939b3 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_changes.html @@ -0,0 +1,75 @@ + + + + + + + + + +Constructor Changes Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Constructors +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +C + TOP +

    +ActivityCompat +() constructor
    + +
    C  +A + TOP +

    +ContextCompat +() constructor
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_removals.html new file mode 100644 index 0000000000000000000000000000000000000000..2fbd2e12dd5766a4f1a379d5da499b25c39101ba --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/constructors_index_removals.html @@ -0,0 +1,61 @@ + + + + + + + + + +Constructor Removals Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Constructors +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_additions.html new file mode 100644 index 0000000000000000000000000000000000000000..cdb8ee8f91f4ed0f57a327eebdd1a4564089b096 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_additions.html @@ -0,0 +1,267 @@ + + + + + + + + + +Field Additions Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Fields +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +B +D +E +H +I +M +P +S +T + TOP +

    +ACTION_ARGUMENT_COLUMN_INT +
    +ACTION_ARGUMENT_PROGRESS_VALUE +
    +ACTION_ARGUMENT_ROW_INT +
    +ACTION_CONTEXT_CLICK +
    +ACTION_SCROLL_DOWN +
    +ACTION_SCROLL_LEFT +
    +ACTION_SCROLL_RIGHT +
    +ACTION_SCROLL_TO_POSITION +
    +ACTION_SCROLL_UP +
    +ACTION_SET_PROGRESS +
    +ACTION_SHOW_ON_SCREEN +
    + +
    B  +A +D +E +H +I +M +P +S +T + TOP +

    +BT_FOLDER_TYPE_ALBUMS +
    +BT_FOLDER_TYPE_ARTISTS +
    +BT_FOLDER_TYPE_GENRES +
    +BT_FOLDER_TYPE_MIXED +
    +BT_FOLDER_TYPE_PLAYLISTS +
    +BT_FOLDER_TYPE_TITLES +
    +BT_FOLDER_TYPE_YEARS +
    + +
    D  +A +B +E +H +I +M +P +S +T + TOP +

    +dodgeInsetEdges +
    + +
    E  +A +B +D +H +I +M +P +S +T + TOP +

    +EXTRA_BT_FOLDER_TYPE +
    +EXTRA_ENABLE_INSTANT_APPS +
    +EXTRA_SUGGESTION_KEYWORDS +
    +EXTRA_USAGE_TIME_REPORT +
    +EXTRA_USAGE_TIME_REPORT_PACKAGES +
    + +
    H  +A +B +D +E +I +M +P +S +T + TOP +

    +HOST_VIEW_ID +
    + +
    I  +A +B +D +E +H +M +P +S +T + TOP +

    +insetEdge +
    + +
    M  +A +B +D +E +H +I +P +S +T + TOP +

    +METADATA_KEY_BT_FOLDER_TYPE +
    +METADATA_KEY_MEDIA_URI +
    + +
    P  +A +B +D +E +H +I +M +S +T + TOP +

    +PEEK_HEIGHT_AUTO +
    +PLAY_STATE_INITIAL +
    +PLAY_STATE_PAUSED +
    +PLAY_STATE_PLAYING +
    + +
    S  +A +B +D +E +H +I +M +P +T + TOP +

    +STOP_FOREGROUND_DETACH +
    +STOP_FOREGROUND_REMOVE +
    + +
    T  +A +B +D +E +H +I +M +P +S + TOP +

    +TYPE_ASSIST_READING_CONTEXT +
    +TYPE_SPLIT_SCREEN_DIVIDER +
    +TYPE_VIEW_CONTEXT_CLICKED +
    +TYPE_WINDOWS_CHANGED +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_all.html new file mode 100644 index 0000000000000000000000000000000000000000..14b3e97afc1bca018f1c916eb811e0d4847105da --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_all.html @@ -0,0 +1,299 @@ + + + + + + + + + +Field Differences Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +Fields +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +B +D +E +H +I +M +O +P +S +T + TOP +

    +ACTION_ARGUMENT_COLUMN_INT +
    +ACTION_ARGUMENT_PROGRESS_VALUE +
    +ACTION_ARGUMENT_ROW_INT +
    +ACTION_CONTEXT_CLICK +
    +ACTION_SCROLL_DOWN +
    +ACTION_SCROLL_LEFT +
    +ACTION_SCROLL_RIGHT +
    +ACTION_SCROLL_TO_POSITION +
    +ACTION_SCROLL_UP +
    +ACTION_SET_PROGRESS +
    +ACTION_SHOW_ON_SCREEN +
    + +
    B  +A +D +E +H +I +M +O +P +S +T + TOP +

    +BT_FOLDER_TYPE_ALBUMS +
    +BT_FOLDER_TYPE_ARTISTS +
    +BT_FOLDER_TYPE_GENRES +
    +BT_FOLDER_TYPE_MIXED +
    +BT_FOLDER_TYPE_PLAYLISTS +
    +BT_FOLDER_TYPE_TITLES +
    +BT_FOLDER_TYPE_YEARS +
    + +
    D  +A +B +E +H +I +M +O +P +S +T + TOP +

    +dodgeInsetEdges +
    + +
    E  +A +B +D +H +I +M +O +P +S +T + TOP +

    +EXTRA_BT_FOLDER_TYPE +
    +EXTRA_ENABLE_INSTANT_APPS +
    +EXTRA_SUGGESTION_KEYWORDS +
    +EXTRA_USAGE_TIME_REPORT +
    +EXTRA_USAGE_TIME_REPORT_PACKAGES +
    + +
    H  +A +B +D +E +I +M +O +P +S +T + TOP +

    +HOST_VIEW_ID +
    + +
    I  +A +B +D +E +H +M +O +P +S +T + TOP +

    +insetEdge +
    + +
    M  +A +B +D +E +H +I +O +P +S +T + TOP +

    +METADATA_KEY_BT_FOLDER_TYPE +
    +METADATA_KEY_MEDIA_URI +
    + +
    O  +A +B +D +E +H +I +M +P +S +T + TOP +

    +OVER_SCROLL_ALWAYS +
    +OVER_SCROLL_IF_CONTENT_SCROLLS +
    +OVER_SCROLL_NEVER +
    + +
    P  +A +B +D +E +H +I +M +O +S +T + TOP +

    +PEEK_HEIGHT_AUTO +
    +PLAY_STATE_INITIAL +
    +PLAY_STATE_PAUSED +
    +PLAY_STATE_PLAYING +
    + +
    S  +A +B +D +E +H +I +M +O +P +T + TOP +

    +STOP_FOREGROUND_DETACH +
    +STOP_FOREGROUND_REMOVE +
    + +
    T  +A +B +D +E +H +I +M +O +P +S + TOP +

    +TAG +
    +TYPE_ASSIST_READING_CONTEXT +
    +TYPE_SPLIT_SCREEN_DIVIDER +
    +TYPE_VIEW_CONTEXT_CLICKED +
    +TYPE_WINDOWS_CHANGED +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_changes.html new file mode 100644 index 0000000000000000000000000000000000000000..c72b2deece722ae082c937385a96e46fda279d15 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_changes.html @@ -0,0 +1,71 @@ + + + + + + + + + +Field Changes Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Fields +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    O  + TOP +

    +OVER_SCROLL_ALWAYS +
    +OVER_SCROLL_IF_CONTENT_SCROLLS +
    +OVER_SCROLL_NEVER +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_removals.html new file mode 100644 index 0000000000000000000000000000000000000000..61820d1f1ccba7656b7d595bc0be155f9a8f944a --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/fields_index_removals.html @@ -0,0 +1,67 @@ + + + + + + + + + +Field Removals Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Fields +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    T  + TOP +

    +TAG +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_help.html b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_help.html new file mode 100644 index 0000000000000000000000000000000000000000..966dda8764bbf9171d4162382dcf52e619e0692f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_help.html @@ -0,0 +1,134 @@ + + + + + + + + + +JDiff Help + + + + + + + + + + + + + + + + + +
    Generated by
    JDiff
    +
    + +
    +

    JDiff Documentation

    +
    +
    +JDiff is a Javadoc doclet which generates a report of the API differences between two versions of a product. It does not report changes in Javadoc comments, or changes in what a class or method does. +This help page describes the different parts of the output from JDiff. +
    +
    + See the reference page in the source for JDiff for information about how to generate a report like this one. +
    +
    +The indexes shown in the top-left frame help show each type of change in more detail. The index "All Differences" contains all the differences between the APIs, in alphabetical order. +These indexes all use the same format: +
      +
    • Removed packages, classes, constructors, methods and fields are struck through.
    • +
    • Added packages, classes, constructors, methods and fields appear in bold.
    • +
    • Changed packages, classes, constructors, methods and fields appear in normal text.
    • +
    +
    +
    +You can always tell when you are reading a JDiff page, rather than a Javadoc page, by the color of the index bar and the color of the background. +Links which take you to a Javadoc page are always in a typewriter font. +Just like Javadoc, all interface names are in italic, and class names are not italicized. Where there are multiple entries in an index with the same name, the heading for them is also in italics, but is not a link. +
    +
    +

    Javadoc

    +This is a link to the top-level Javadoc page for the new version of the product. +
    +
    +

    Overview

    +The overview is the top-level summary of what was removed, added and changed between versions. +
    +
    +

    Package

    +This is a link to the package containing the current changed class or interface. +
    +
    +

    Class

    +This is highlighted when you are looking at the changed class or interface. +
    +
    +

    Text Changes

    +This is a link to the top-level index of all documentation changes for the current package or class. +If it is not present, then there are no documentation changes for the current package or class. +This link can be removed entirely by not using the -docchanges option. +
    +
    +

    Statistics

    +This is a link to a page which shows statistics about the changes between the two APIs. +This link can be removed entirely by not using the -stats option. +
    +
    +

    Help

    +A link to this Help page for JDiff. +
    +
    +

    Prev/Next

    +These links take you to the previous and next changed package or class. +
    +
    +

    Frames/No Frames

    +These links show and hide the HTML frames. All pages are available with or without frames. +
    +
    +

    Complex Changes

    +There are some complex changes which can occur between versions, for example, when two or more methods with the same name change simultaneously, or when a method or field is moved into or from a superclass. +In these cases, the change will be seen as a removal and an addition, rather than as a change. Unexpected removals or additions are often part of one of these type of changes. +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_statistics.html b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_statistics.html new file mode 100644 index 0000000000000000000000000000000000000000..7010da6a7e05f56498b7834a49443f13d11f612d --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_statistics.html @@ -0,0 +1,596 @@ + + + + + + + + + +API Change Statistics + + + + + + + + + + +
    +
    +
    +

    API Change Statistics

    +

    The overall difference between API Levels 24.1.0 and 24.2.0 is approximately 8.39%. +

    +
    + +

    Total of Differences, by Number and Type

    +

    +The table below lists the numbers of program elements (packages, classes, constructors, methods, and fields) that were added, changed, or removed. The table includes only the highest-level program elements — that is, if a class with two methods was added, the number of methods added does not include those two methods, but the number of classes added does include that class. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    TypeAdditionsChangesRemovalsTotal
    Packages222327
    Classes and Interfaces64630127
    Constructors1203
    Methods80257112
    Fields383142
    Total18511511311
    +
    + +

    Changed Packages, Sorted by Percentage Difference

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Percentage Difference*Package
    37android.support.v7.widget
    33android.support.v7.content.res
    32android.support.v7.util
    19android.support.v4.view.accessibility
    12android.support.v7.app
    5android.support.v4.widget
    4android.support.v4.accessibilityservice
    4android.support.customtabs
    3android.support.v4.util
    3android.support.v4.os
    2android.support.v4.media.session
    2android.support.v4.app
    2android.support.design.widget
    2android.support.v4.media
    1android.support.v7.preference
    1android.support.v4.view
    1android.support.v17.preference
    <1android.support.v4.graphics.drawable
    <1android.support.v7.graphics
    <1android.support.v17.leanback.widget
    <1android.support.v14.preference
    <1android.support.v4.content
    +

    * See Calculation of Change Percentages, below.

    +
    + +

    Changed Classes and Interfaces, Sorted by Percentage Difference

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Percentage
    Difference*
    Class or Interface
    60 +android.support.v4.app.ServiceCompat
    38 +android.support.design.widget.FloatingActionButton.Behavior
    33 +android.support.v4.app.ActivityOptionsCompat
    33 +android.support.v4.os.BuildCompat
    33 +android.support.v4.view.accessibility.AccessibilityManagerCompat
    33 +android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListenerCompat
    33 +android.support.v7.content.res.AppCompatResources
    28 +android.support.customtabs.CustomTabsSession
    28 +android.support.v7.util.SortedList.Callback
    25 +android.support.v4.media.session.MediaButtonReceiver
    25 +android.support.v4.view.ViewConfigurationCompat
    25 +android.support.v4.widget.SearchViewCompat.OnCloseListenerCompat
    23 +android.support.v4.media.MediaDescriptionCompat
    20 +android.support.v4.view.KeyEventCompat
    18 +android.support.v17.leanback.widget.AbstractMediaItemPresenter
    18 +android.support.design.widget.TextInputLayout
    17 +android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder
    16 +android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat
    15 +android.support.v4.media.session.MediaSessionCompat.QueueItem
    13 +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
    12 +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat
    11 +android.support.v4.view.accessibility.AccessibilityEventCompat
    11 +android.support.design.widget.AppBarLayout.ScrollingViewBehavior
    10 +android.support.v17.preference.LeanbackSettingsFragment
    9 +android.support.design.widget.CoordinatorLayout.Behavior
    8 +android.support.design.widget.CoordinatorLayout.LayoutParams
    8 +android.support.v4.media.MediaBrowserCompat.MediaItem
    7 +android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot
    7 +android.support.v4.widget.TextViewCompat
    7 +android.support.v4.app.ActivityCompat
    6 +android.support.v4.app.SharedElementCallback
    6 +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat
    6 +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat
    6 +android.support.v4.view.accessibility.AccessibilityNodeProviderCompat
    6 +android.support.v4.widget.SearchViewCompat
    6 +android.support.v7.app.ActionBarDrawerToggle
    5 +android.support.customtabs.CustomTabsIntent
    4 +android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat
    4 +android.support.v4.view.MotionEventCompat
    4 +android.support.v7.graphics.Palette
    4 +android.support.v7.widget.StaggeredGridLayoutManager
    3 +android.support.v4.media.session.MediaSessionCompat
    3 +android.support.v4.content.ContextCompat
    3 +android.support.customtabs.CustomTabsIntent.Builder
    2 +android.support.design.widget.BottomSheetBehavior
    2 +android.support.design.widget.CoordinatorLayout
    2 +android.support.v4.graphics.drawable.DrawableCompat
    2 +android.support.v4.view.WindowInsetsCompat
    2 +android.support.v14.preference.PreferenceFragment
    2 +android.support.v4.view.accessibility.AccessibilityWindowInfoCompat
    2 +android.support.v4.view.ViewCompat
    2 +android.support.design.widget.CollapsingToolbarLayout
    2 +android.support.v17.leanback.widget.ObjectAdapter
    2 +android.support.v4.media.MediaMetadataCompat
    2 +android.support.v7.widget.LinearSmoothScroller
    2 +android.support.v4.widget.SwipeRefreshLayout
    1 +android.support.v7.widget.LinearLayoutManager
    1 +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat
    1 +android.support.design.widget.TabLayout
    1 +android.support.v4.app.FragmentController
    1 +android.support.v7.app.AppCompatDelegate
    1 +android.support.v7.widget.RecyclerView
    1 +android.support.v4.media.session.PlaybackStateCompat
    +

    * See Calculation of Change Percentages, below.

    +
    +

    Calculation of Change Percentages

    +

    +The percent change statistic reported for all elements in the "to" API Level specification is defined recursively as follows:

    +
    +Percentage difference = 100 * (added + removed + 2*changed)
    +                        -----------------------------------
    +                        sum of public elements in BOTH APIs
    +
    +

    where added is the number of packages added, removed is the number of packages removed, and changed is the number of packages changed. +This definition is applied recursively for the classes and their program elements, so the value for a changed package will be less than 1, unless every class in that package has changed. +The definition ensures that if all packages are removed and all new packages are +added, the change will be 100%.

    +
    + +
    +
    + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_topleftframe.html b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_topleftframe.html new file mode 100644 index 0000000000000000000000000000000000000000..6a2e76e10fc235b752374f304558a3123ecd7f79 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/jdiff_topleftframe.html @@ -0,0 +1,63 @@ + + + + + + + + + +Android API Version Differences + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Select a Diffs Index:
    All Differences
    By Package
    By Class
    By Constructor
    By Method
    By Field
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_additions.html new file mode 100644 index 0000000000000000000000000000000000000000..419a6073f3b1bb4f06be8d3ba86f62c057cff125 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_additions.html @@ -0,0 +1,448 @@ + + + + + + + + + +Method Additions Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Methods +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +B +C +F +G +I +L +M +N +O +R +S +T + TOP +

    +addTouchExplorationStateChangeListener +(AccessibilityManager, TouchExplorationStateChangeListener)
    + +
    B  +A +C +F +G +I +L +M +N +O +R +S +T + TOP +

    +buildMediaButtonPendingIntent
    +  type  +(Context, ComponentName, long) in android.support.v4.media.session.MediaButtonReceiver +
    +  type  +(Context, long) in android.support.v4.media.session.MediaButtonReceiver +
    + +
    C  +A +B +F +G +I +L +M +N +O +R +S +T + TOP +

    +clearColorFilter +(Drawable)
    +clearOnTabSelectedListeners +()
    +computeScrollVectorForPosition +(int)
    + +
    F  +A +B +C +G +I +L +M +N +O +R +S +T + TOP +

    +findFragmentByWho +(String)
    +fromMediaItem +(Object)
    +fromMediaItemList +(List<?>)
    +fromMediaSession +(Context, Object)
    +fromQueueItem +(Object)
    +fromQueueItemList +(List<?>)
    + +
    G  +A +B +C +F +I +L +M +N +O +R +S +T + TOP +

    +getAction +(AccessibilityEvent)
    +getCompoundDrawablesRelative +(TextView)
    +getDependents +(View)
    +getDominantColor +(int)
    +getDominantSwatch +()
    +getDrawable +(Context, int)
    +getDrawerArrowDrawable +()
    +getInsetDodgeRect
    +  type  +(CoordinatorLayout, V, Rect) in android.support.design.widget.CoordinatorLayout.Behavior +
    +  type  +(CoordinatorLayout, FloatingActionButton, Rect) in android.support.design.widget.FloatingActionButton.Behavior +
    +getLaunchBounds +()
    +getMediaItemNumberViewFlipper +()
    +getMediaItemPausedView +()
    +getMediaItemPlayingView +()
    +getMediaPlayState +(Object)
    +getMovementGranularity +(AccessibilityEvent)
    +getOnFlingListener +()
    +getPasswordVisibilityToggleContentDescription +()
    +getPasswordVisibilityToggleDrawable +()
    +getSelectionMode +()
    + +
    I  +A +B +C +F +G +L +M +N +O +R +S +T + TOP +

    +isAtLeastNMR1 +()
    +isAutoHideEnabled +()
    +isContextClickable +()
    +isImmediateNotifySupported +()
    +isImportantForAccessibility +(View)
    +isPasswordVisibilityToggleEnabled +()
    + +
    L  +A +B +C +F +G +I +M +N +O +R +S +T + TOP +

    +loadDescription +(AccessibilityServiceInfo, PackageManager)
    + +
    M  +A +B +C +F +G +I +L +N +O +R +S +T + TOP +

    +makeBasic +()
    +makeClipRevealAnimation +(View, int, int, int, int)
    +makeTaskLaunchBehind +()
    + +
    N  +A +B +C +F +G +I +L +M +O +R +S +T + TOP +

    +notifyPlayStateChanged +()
    + +
    O  +A +B +C +F +G +I +L +M +N +R +S +T + TOP +

    +obtain
    +  type  +(int, int, boolean) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat +
    +  type  +(int, int, int, int, boolean) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat +
    +  type  +(int, float, float, float) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat +
    +onAttachedToLayoutParams +(LayoutParams)
    +onBindMediaPlayState +(ViewHolder)
    +onChanged +(int, int, Object)
    +onDetachedFromLayoutParams +()
    +onRequestChildRectangleOnScreen
    +  type  +(CoordinatorLayout, View, Rect, boolean) in android.support.design.widget.AppBarLayout.ScrollingViewBehavior +
    +  type  +(CoordinatorLayout, V, Rect, boolean) in android.support.design.widget.CoordinatorLayout.Behavior +
    +onSharedElementsArrived +(List<String>, List<View>, OnSharedElementsReadyListener)
    +onStart +()
    +onUnbindMediaPlayState +(ViewHolder)
    + +
    R  +A +B +C +F +G +I +L +M +N +O +S +T + TOP +

    +removeTouchExplorationStateChangeListener +(AccessibilityManager, TouchExplorationStateChangeListener)
    +requestUsageTimeReport +(PendingIntent)
    + +
    S  +A +B +C +F +G +I +L +M +N +O +R +T + TOP +

    +setAction +(AccessibilityEvent, int)
    +setAlwaysUseBrowserUI +(Intent)
    +setAutoHideEnabled +(boolean)
    +setCollapsedTitleTextColor +(ColorStateList)
    +setContextClickable +(boolean)
    +setDrawerArrowDrawable +(DrawerArrowDrawable)
    +setExpandedTitleTextColor +(ColorStateList)
    +setInstantAppsEnabled +(boolean)
    +setLaunchBounds +(Rect)
    +setMovementGranularity +(AccessibilityEvent, int)
    +setOnChildScrollUpCallback +(OnChildScrollUpCallback)
    +setOnFlingListener +(OnFlingListener)
    +setPasswordVisibilityToggleContentDescription
    +  type  +(int) in android.support.design.widget.TextInputLayout +
    +  type  +(CharSequence) in android.support.design.widget.TextInputLayout +
    +setPasswordVisibilityToggleDrawable
    +  type  +(Drawable) in android.support.design.widget.TextInputLayout +
    +  type  +(int) in android.support.design.widget.TextInputLayout +
    +setPasswordVisibilityToggleEnabled +(boolean)
    +setPasswordVisibilityToggleTintList +(ColorStateList)
    +setPasswordVisibilityToggleTintMode +(Mode)
    +setSecondaryToolbarViews +(RemoteViews, int[], PendingIntent)
    +setSelectedMediaItemNumberView +(int)
    +shouldAlwaysUseBrowserUI +(Intent)
    +stopForeground +(Service, int)
    + +
    T  +A +B +C +F +G +I +L +M +N +O +R +S + TOP +

    +toKeyCode +(long)
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_all.html new file mode 100644 index 0000000000000000000000000000000000000000..d33bfc0d13387e5101f3d7b24e8c47840f5a876f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_all.html @@ -0,0 +1,579 @@ + + + + + + + + + +Method Differences Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +Methods +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +B +C +D +F +G +I +L +M +N +O +P +R +S +T + TOP +

    +addAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    +addTouchExplorationStateChangeListener +(AccessibilityManager, TouchExplorationStateChangeListener)
    + +
    B  +A +C +D +F +G +I +L +M +N +O +P +R +S +T + TOP +

    +buildMediaButtonPendingIntent
    +  type  +(Context, ComponentName, long) in android.support.v4.media.session.MediaButtonReceiver +
    +  type  +(Context, long) in android.support.v4.media.session.MediaButtonReceiver +
    + +
    C  +A +B +D +F +G +I +L +M +N +O +P +R +S +T + TOP +

    +clearColorFilter +(Drawable)
    +clearOnTabSelectedListeners +()
    +computeScrollVectorForPosition
    +  type  +(int) in android.support.v7.widget.LinearSmoothScroller +
    +  type  +(int) in android.support.v7.widget.StaggeredGridLayoutManager +
    + +
    D  +A +B +C +F +G +I +L +M +N +O +P +R +S +T + TOP +

    +dispatch +(KeyEvent, Callback, Object, Object)
    + +
    F  +A +B +C +D +G +I +L +M +N +O +P +R +S +T + TOP +

    +findFragmentByWho +(String)
    +findPointerIndex +(MotionEvent, int)
    +fromMediaItem +(Object)
    +fromMediaItemList +(List<?>)
    +fromMediaSession +(Context, Object)
    +fromQueueItem +(Object)
    +fromQueueItemList +(List<?>)
    + +
    G  +A +B +C +D +F +I +L +M +N +O +P +R +S +T + TOP +

    +getAction +(AccessibilityEvent)
    +getCompoundDrawablesRelative +(TextView)
    +getDependents +(View)
    +getDescription +(AccessibilityServiceInfo)
    +getDominantColor +(int)
    +getDominantSwatch +()
    +getDrawable +(Context, int)
    +getDrawerArrowDrawable +()
    +getInsetDodgeRect
    +  type  +(CoordinatorLayout, V, Rect) in android.support.design.widget.CoordinatorLayout.Behavior +
    +  type  +(CoordinatorLayout, FloatingActionButton, Rect) in android.support.design.widget.FloatingActionButton.Behavior +
    +getKeyDispatcherState +(View)
    +getLaunchBounds +()
    +getMediaItemNumberViewFlipper +()
    +getMediaItemPausedView +()
    +getMediaItemPlayingView +()
    +getMediaPlayState +(Object)
    +getMovementGranularity +(AccessibilityEvent)
    +getOnFlingListener +()
    +getOverScrollMode +(View)
    +getPasswordVisibilityToggleContentDescription +()
    +getPasswordVisibilityToggleDrawable +()
    +getPointerCount +(MotionEvent)
    +getPointerId +(MotionEvent, int)
    +getReferrer +(Activity)
    +getScaledPagingTouchSlop +(ViewConfiguration)
    +getSelectionMode +()
    +getSource +(MotionEvent)
    +getX +(MotionEvent, int)
    +getY +(MotionEvent, int)
    + +
    I  +A +B +C +D +F +G +L +M +N +O +P +R +S +T + TOP +

    +isAtLeastNMR1 +()
    +isAutoHideEnabled +()
    +isContextClickable +()
    +isDirty +(CoordinatorLayout, V)
    +isImmediateNotifySupported +()
    +isImportantForAccessibility +(View)
    +isOpaque +(View)
    +isPasswordVisibilityToggleEnabled +()
    +isTracking +(KeyEvent)
    + +
    L  +A +B +C +D +F +G +I +M +N +O +P +R +S +T + TOP +

    +layoutDependsOn +(CoordinatorLayout, FloatingActionButton, View)
    +loadDescription +(AccessibilityServiceInfo, PackageManager)
    + +
    M  +A +B +C +D +F +G +I +L +N +O +P +R +S +T + TOP +

    +makeBasic +()
    +makeClipRevealAnimation +(View, int, int, int, int)
    +makeTaskLaunchBehind +()
    + +
    N  +A +B +C +D +F +G +I +L +M +O +P +R +S +T + TOP +

    +notifyPlayStateChanged +()
    + +
    O  +A +B +C +D +F +G +I +L +M +N +P +R +S +T + TOP +

    +obtain
    +  type  +(Context, Object) in android.support.v4.media.session.MediaSessionCompat +
    +  type  +(Object) in android.support.v4.media.session.MediaSessionCompat.QueueItem +
    +  type  +(int, int, boolean) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat +
    +  type  +(int, int, int, int, boolean) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat +
    +  type  +(int, float, float, float) in android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat +
    +onAccessibilityStateChanged +(boolean)
    +onAttachedToLayoutParams +(LayoutParams)
    +onBindMediaPlayState +(ViewHolder)
    +onChanged +(int, int, Object)
    +onDependentViewRemoved +(CoordinatorLayout, FloatingActionButton, View)
    +onDetachedFromLayoutParams +()
    +onInserted +(int, int)
    +onMoved +(int, int)
    +onRemoved +(int, int)
    +onRequestChildRectangleOnScreen
    +  type  +(CoordinatorLayout, View, Rect, boolean) in android.support.design.widget.AppBarLayout.ScrollingViewBehavior +
    +  type  +(CoordinatorLayout, V, Rect, boolean) in android.support.design.widget.CoordinatorLayout.Behavior +
    +onSharedElementsArrived +(List<String>, List<View>, OnSharedElementsReadyListener)
    +onStart +()
    +onUnbindMediaPlayState +(ViewHolder)
    + +
    P  +A +B +C +D +F +G +I +L +M +N +O +R +S +T + TOP +

    +prepareForDrop +(View, View, int, int)
    + +
    R  +A +B +C +D +F +G +I +L +M +N +O +P +S +T + TOP +

    +removeAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    +removeTouchExplorationStateChangeListener +(AccessibilityManager, TouchExplorationStateChangeListener)
    +requestUsageTimeReport +(PendingIntent)
    + +
    S  +A +B +C +D +F +G +I +L +M +N +O +P +R +T + TOP +

    +setAction +(AccessibilityEvent, int)
    +setAlwaysUseBrowserUI +(Intent)
    +setAutoHideEnabled +(boolean)
    +setCollapsedTitleTextColor +(ColorStateList)
    +setContextClickable +(boolean)
    +setDrawerArrowDrawable +(DrawerArrowDrawable)
    +setExpandedTitleTextColor +(ColorStateList)
    +setInstantAppsEnabled +(boolean)
    +setLaunchBounds +(Rect)
    +setMovementGranularity +(AccessibilityEvent, int)
    +setOnChildScrollUpCallback +(OnChildScrollUpCallback)
    +setOnCloseListener +(View, OnCloseListener)
    +setOnFlingListener +(OnFlingListener)
    +setOnQueryTextListener +(View, OnQueryTextListener)
    +setOverScrollMode +(View, int)
    +setPasswordVisibilityToggleContentDescription
    +  type  +(int) in android.support.design.widget.TextInputLayout +
    +  type  +(CharSequence) in android.support.design.widget.TextInputLayout +
    +setPasswordVisibilityToggleDrawable
    +  type  +(Drawable) in android.support.design.widget.TextInputLayout +
    +  type  +(int) in android.support.design.widget.TextInputLayout +
    +setPasswordVisibilityToggleEnabled +(boolean)
    +setPasswordVisibilityToggleTintList +(ColorStateList)
    +setPasswordVisibilityToggleTintMode +(Mode)
    +setSecondaryToolbarViews +(RemoteViews, int[], PendingIntent)
    +setSelectedMediaItemNumberView +(int)
    +setToolbarItem +(int, Bitmap, String)
    +shouldAlwaysUseBrowserUI +(Intent)
    +startTracking +(KeyEvent)
    +stopForeground +(Service, int)
    + +
    T  +A +B +C +D +F +G +I +L +M +N +O +P +R +S + TOP +

    +toKeyCode +(long)
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_changes.html new file mode 100644 index 0000000000000000000000000000000000000000..ef008cbad1834a4c12193e93f2e6b65b163d402d --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_changes.html @@ -0,0 +1,222 @@ + + + + + + + + + +Method Changes Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Methods +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    A  +C +D +F +G +I +O +R +S + TOP +

    +addAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    + +
    C  +A +D +F +G +I +O +R +S + TOP +

    +computeScrollVectorForPosition +(int)
    + +
    D  +A +C +F +G +I +O +R +S + TOP +

    +dispatch +(KeyEvent, Callback, Object, Object)
    + +
    F  +A +C +D +G +I +O +R +S + TOP +

    +findPointerIndex +(MotionEvent, int)
    + +
    G  +A +C +D +F +I +O +R +S + TOP +

    +getDescription +(AccessibilityServiceInfo)
    +getKeyDispatcherState +(View)
    +getOverScrollMode +(View)
    +getPointerCount +(MotionEvent)
    +getPointerId +(MotionEvent, int)
    +getReferrer +(Activity)
    +getScaledPagingTouchSlop +(ViewConfiguration)
    +getSource +(MotionEvent)
    +getX +(MotionEvent, int)
    +getY +(MotionEvent, int)
    + +
    I  +A +C +D +F +G +O +R +S + TOP +

    +isDirty +(CoordinatorLayout, V)
    +isOpaque +(View)
    +isTracking +(KeyEvent)
    + +
    O  +A +C +D +F +G +I +R +S + TOP +

    +obtain
    +  type  +(Context, Object) in android.support.v4.media.session.MediaSessionCompat +
    +  type  +(Object) in android.support.v4.media.session.MediaSessionCompat.QueueItem +
    + +
    R  +A +C +D +F +G +I +O +S + TOP +

    +removeAccessibilityStateChangeListener +(AccessibilityManager, AccessibilityStateChangeListener)
    + +
    S  +A +C +D +F +G +I +O +R + TOP +

    +setOnCloseListener +(View, OnCloseListener)
    +setOnQueryTextListener +(View, OnQueryTextListener)
    +setOverScrollMode +(View, int)
    +setToolbarItem +(int, Bitmap, String)
    +startTracking +(KeyEvent)
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_removals.html new file mode 100644 index 0000000000000000000000000000000000000000..1c0c6be7f8635bed6b0455c743e61fcf67e6bed3 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/methods_index_removals.html @@ -0,0 +1,93 @@ + + + + + + + + + +Method Removals Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Methods +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    + +
    L  +O +P + TOP +

    +layoutDependsOn +(CoordinatorLayout, FloatingActionButton, View)
    + +
    O  +L +P + TOP +

    +onAccessibilityStateChanged +(boolean)
    +onDependentViewRemoved +(CoordinatorLayout, FloatingActionButton, View)
    +onInserted +(int, int)
    +onMoved +(int, int)
    +onRemoved +(int, int)
    + +
    P  +L +O + TOP +

    +prepareForDrop +(View, View, int, int)
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_additions.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_additions.html new file mode 100644 index 0000000000000000000000000000000000000000..bb88d9fe5593e5dc3ea9df7b084f75ffb48f9475 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_additions.html @@ -0,0 +1,66 @@ + + + + + + + + + +Package Additions Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Packages +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    +
    +
    + +android.support.transition
    +android.support.v4.text.util
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_all.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_all.html new file mode 100644 index 0000000000000000000000000000000000000000..78805db862fc12105b444a30ff4635d11b4d93db --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_all.html @@ -0,0 +1,91 @@ + + + + + + + + + +Package Differences Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +Packages +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    +
    +
    + +android.support.customtabs
    +android.support.design.widget
    +android.support.transition
    +android.support.v14.preference
    +android.support.v17.leanback.widget
    +android.support.v17.preference
    +android.support.v4.accessibilityservice
    +android.support.v4.app
    +android.support.v4.content
    +android.support.v4.graphics.drawable
    +android.support.v4.media
    +android.support.v4.media.session
    +android.support.v4.os
    +android.support.v4.text.util
    +android.support.v4.util
    +android.support.v4.view
    +android.support.v4.view.accessibility
    +android.support.v4.widget
    +android.support.v7.app
    +android.support.v7.appcompat
    +android.support.v7.content.res
    +android.support.v7.graphics
    +android.support.v7.preference
    +android.support.v7.recyclerview
    +android.support.v7.util
    +android.support.v7.widget
    +android.support.v8.renderscript
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_changes.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_changes.html new file mode 100644 index 0000000000000000000000000000000000000000..f5f6425161518acadfe888debd33fa7b28e5d239 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_changes.html @@ -0,0 +1,86 @@ + + + + + + + + + +Package Changes Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Packages +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    +
    +
    + +android.support.customtabs
    +android.support.design.widget
    +android.support.v14.preference
    +android.support.v17.leanback.widget
    +android.support.v17.preference
    +android.support.v4.accessibilityservice
    +android.support.v4.app
    +android.support.v4.content
    +android.support.v4.graphics.drawable
    +android.support.v4.media
    +android.support.v4.media.session
    +android.support.v4.os
    +android.support.v4.util
    +android.support.v4.view
    +android.support.v4.view.accessibility
    +android.support.v4.widget
    +android.support.v7.app
    +android.support.v7.content.res
    +android.support.v7.graphics
    +android.support.v7.preference
    +android.support.v7.util
    +android.support.v7.widget
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_removals.html b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_removals.html new file mode 100644 index 0000000000000000000000000000000000000000..ce5ca58605034dc131dc6117b41918a7cb16ebc5 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/packages_index_removals.html @@ -0,0 +1,67 @@ + + + + + + + + + +Package Removals Index + + + + + + + + + + + + + + + +
    + Filter the Index: +
    +All Packages +
    +Removals +
    +Additions +
    +Changes +
    +
    +Listed as: Added, Removed, Changed +
    +
    +
    + +android.support.v7.appcompat
    +android.support.v7.recyclerview
    +android.support.v8.renderscript
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.customtabs.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.customtabs.html new file mode 100644 index 0000000000000000000000000000000000000000..45a31ffa007a0aefa6101576bc88336dccb7f539 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.customtabs.html @@ -0,0 +1,133 @@ + + + + + + + + + +android.support.customtabs + + + + + + + + + + +
    +
    +
    +

    +Package android.support.customtabs +

    +

    + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + CustomTabsIntent +  
    + + CustomTabsIntent.Builder +  
    + + CustomTabsSession +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.design.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.design.widget.html new file mode 100644 index 0000000000000000000000000000000000000000..a311b48ee54bc06181aaf2b6ccea6abdea48db5d --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.design.widget.html @@ -0,0 +1,175 @@ + + + + + + + + + +android.support.design.widget + + + + + + + + + + +
    +
    +
    +

    +Package android.support.design.widget +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + AppBarLayout.ScrollingViewBehavior +  
    + + BottomSheetBehavior +  
    + + CollapsingToolbarLayout +  
    + + CoordinatorLayout +  
    + + CoordinatorLayout.Behavior +  
    + + CoordinatorLayout.LayoutParams +  
    + + FloatingActionButton.Behavior +  
    + + TabLayout +  
    + + TextInputLayout +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v14.preference.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v14.preference.html new file mode 100644 index 0000000000000000000000000000000000000000..f24be00d1680008a924a43dbe7c5e2729cad3619 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v14.preference.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v14.preference + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v14.preference +

    +

    + + + + + + + + +
    Changed Classes +
    + + PreferenceFragment +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.leanback.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.leanback.widget.html new file mode 100644 index 0000000000000000000000000000000000000000..c07a4873251f18e22ce58cb0186ee89af99e9464 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.leanback.widget.html @@ -0,0 +1,133 @@ + + + + + + + + + +android.support.v17.leanback.widget + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v17.leanback.widget +

    +

    + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + AbstractMediaItemPresenter +  
    + + AbstractMediaItemPresenter.
    ViewHolder
    +
     
    + + ObjectAdapter +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.preference.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.preference.html new file mode 100644 index 0000000000000000000000000000000000000000..c61d79dcea1054d355d92266f65f2666033584a4 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v17.preference.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v17.preference + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v17.preference +

    +

    + + + + + + + + +
    Changed Classes +
    + + LeanbackSettingsFragment +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.accessibilityservice.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.accessibilityservice.html new file mode 100644 index 0000000000000000000000000000000000000000..2c0f684969a58ee5a876b2d7297aa120788d3bf7 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.accessibilityservice.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v4.accessibilityservice + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.accessibilityservice +

    +

    + + + + + + + + +
    Changed Classes +
    + + AccessibilityServiceInfoCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.app.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.app.html new file mode 100644 index 0000000000000000000000000000000000000000..58ed06f92887cc2859d031d3099ee25799df1fba --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.app.html @@ -0,0 +1,162 @@ + + + + + + + + + +android.support.v4.app + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.app +

    +

    + + + + + + + + +
    Added Interfaces +
    + + SharedElementCallback.
    OnSharedElementsReadyListener
    +
     
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + ActivityCompat +  
    + + ActivityOptionsCompat +  
    + + FragmentController +  
    + + ServiceCompat +  
    + + SharedElementCallback +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.content.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.content.html new file mode 100644 index 0000000000000000000000000000000000000000..65dd61658bc7f0a95f295a8ac67c7c46ea190723 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.content.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v4.content + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.content +

    +

    + + + + + + + + +
    Changed Classes +
    + + ContextCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.graphics.drawable.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.graphics.drawable.html new file mode 100644 index 0000000000000000000000000000000000000000..f8b31a57551a725f024ac8bf781b8f5e366c5808 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.graphics.drawable.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v4.graphics.drawable + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.graphics.drawable +

    +

    + + + + + + + + +
    Changed Classes +
    + + DrawableCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.html new file mode 100644 index 0000000000000000000000000000000000000000..5300c86b70b2266fd2f7d93ed50c5d43eefd7538 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.html @@ -0,0 +1,140 @@ + + + + + + + + + +android.support.v4.media + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.media +

    +

    + + + + + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + MediaBrowserCompat.MediaItem +  
    + + MediaBrowserServiceCompat.
    BrowserRoot
    +
     
    + + MediaDescriptionCompat +  
    + + MediaMetadataCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.session.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.session.html new file mode 100644 index 0000000000000000000000000000000000000000..459d0c3f4a7e6141960dc3fdcfa2b9d6552ca702 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.media.session.html @@ -0,0 +1,140 @@ + + + + + + + + + +android.support.v4.media.session + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.media.session +

    +

    + + + + + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + MediaButtonReceiver +  
    + + MediaSessionCompat +  
    + + MediaSessionCompat.QueueItem +  
    + + PlaybackStateCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.os.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.os.html new file mode 100644 index 0000000000000000000000000000000000000000..6d7f3993fe4e881a792ddc3a2d8ac636ae6e1fe4 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.os.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v4.os + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.os +

    +

    + + + + + + + + +
    Changed Classes +
    + + BuildCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.util.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.util.html new file mode 100644 index 0000000000000000000000000000000000000000..6f0e7778fdb4ec6b9d0c04c3181bbbd37fb2167d --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.util.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v4.util + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.util +

    +

    + + + + + + + + +
    Added Classes +
    + + PatternsCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.accessibility.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.accessibility.html new file mode 100644 index 0000000000000000000000000000000000000000..d5d126cbc7b769b09bb31ee6a25dfe4bcf6d6e1f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.accessibility.html @@ -0,0 +1,204 @@ + + + + + + + + + +android.support.v4.view.accessibility + + + + + + + + + + + + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.html new file mode 100644 index 0000000000000000000000000000000000000000..d720d413d37ce004dcc50256b2f80438aecec305 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.view.html @@ -0,0 +1,147 @@ + + + + + + + + + +android.support.v4.view + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.view +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + KeyEventCompat +  
    + + MotionEventCompat +  
    + + ViewCompat +  
    + + ViewConfigurationCompat +  
    + + WindowInsetsCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.widget.html new file mode 100644 index 0000000000000000000000000000000000000000..2efef459645686ded72c15476be2cea7c7b5bb7f --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v4.widget.html @@ -0,0 +1,176 @@ + + + + + + + + + +android.support.v4.widget + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v4.widget +

    +

    + + + + + + + + + + + + + + + + +
    Added Interfaces +
    + + SearchViewCompat.OnCloseListener +  
    + + SearchViewCompat.OnQueryTextListener +  
    + + SwipeRefreshLayout.OnChildScrollUpCallback +  
    +  +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + SearchViewCompat +  
    + + SearchViewCompat.OnCloseListenerCompat +  
    + + SearchViewCompat.OnQueryTextListenerCompat +  
    + + SwipeRefreshLayout +  
    + + TextViewCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.app.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.app.html new file mode 100644 index 0000000000000000000000000000000000000000..f36cba52ec3c9919784a4d1aadc8e071c2c07db7 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.app.html @@ -0,0 +1,176 @@ + + + + + + + + + +android.support.v7.app + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v7.app +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Classes +
    + + ActionBarActivity +  
    + + AppCompatActivity +  
    + + AppCompatDialogFragment +  
    + + NotificationCompat +  
    + + NotificationCompat.Builder +  
    + + NotificationCompat.MediaStyle +  
    +  +

    + + + + + + + + + + + + +
    Changed Classes +
    + + ActionBarDrawerToggle +  
    + + AppCompatDelegate +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.content.res.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.content.res.html new file mode 100644 index 0000000000000000000000000000000000000000..2e4b703d349c6ae3196c455549df52407683bd66 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.content.res.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v7.content.res + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v7.content.res +

    +

    + + + + + + + + +
    Changed Classes +
    + + AppCompatResources +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.graphics.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.graphics.html new file mode 100644 index 0000000000000000000000000000000000000000..439c8d3b7c82db426371295eca48cc8e9daa710d --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.graphics.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v7.graphics + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v7.graphics +

    +

    + + + + + + + + +
    Changed Classes +
    + + Palette +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.preference.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.preference.html new file mode 100644 index 0000000000000000000000000000000000000000..b2b781b82892f7f3d6cdc01a0a465f082fbda3f3 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.preference.html @@ -0,0 +1,119 @@ + + + + + + + + + +android.support.v7.preference + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v7.preference +

    +

    + + + + + + + + +
    Added Classes +
    + + MultiSelectListPreferenceDialogFragmentCompat +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.util.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.util.html new file mode 100644 index 0000000000000000000000000000000000000000..c35fb8c89385cfbc5bb27f0017b50ac6ba2eb7f3 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.util.html @@ -0,0 +1,162 @@ + + + + + + + + + +android.support.v7.util + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v7.util +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Classes and Interfaces +
    + + BatchingListUpdateCallback +  
    + + DiffUtil +  
    + + DiffUtil.Callback +  
    + + DiffUtil.DiffResult +  
    + + ListUpdateCallback +  
    +  +

    + + + + + + + + +
    Changed Classes +
    + + SortedList.Callback +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.widget.html b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.widget.html new file mode 100644 index 0000000000000000000000000000000000000000..72e5497cb0dd8b1e1622ad5a26d164c56d8d8b89 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/changes/pkg_android.support.v7.widget.html @@ -0,0 +1,463 @@ + + + + + + + + + +android.support.v7.widget + + + + + + + + + + +
    +
    +
    +

    +Package android.support.v7.widget +

    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Added Classes and Interfaces +
    + + ActionMenuView +  
    + + ActionMenuView.LayoutParams +  
    + + ActionMenuView.OnMenuItemClickListener +  
    + + AppCompatAutoCompleteTextView +  
    + + AppCompatButton +  
    + + AppCompatCheckBox +  
    + + AppCompatCheckedTextView +  
    + + AppCompatEditText +  
    + + AppCompatImageButton +  
    + + AppCompatImageView +  
    + + AppCompatMultiAutoCompleteTextView +  
    + + AppCompatRadioButton +  
    + + AppCompatRatingBar +  
    + + AppCompatSeekBar +  
    + + AppCompatSpinner +  
    + + AppCompatTextView +  
    + + CardView +  
    + + GridLayout +  
    + + GridLayout.Alignment +  
    + + GridLayout.LayoutParams +  
    + + GridLayout.Spec +  
    + + LinearLayoutCompat +  
    + + LinearLayoutCompat.LayoutParams +  
    + + LinearSnapHelper +  
    + + ListPopupWindow +  
    + + PopupMenu +  
    + + PopupMenu.OnDismissListener +  
    + + PopupMenu.OnMenuItemClickListener +  
    + + RecyclerView.OnFlingListener +  
    + + RecyclerView.SmoothScroller.
    ScrollVectorProvider
    +
     
    + + SearchView +  
    + + SearchView.OnCloseListener +  
    + + SearchView.OnQueryTextListener +  
    + + SearchView.OnSuggestionListener +  
    + + ShareActionProvider +  
    + + ShareActionProvider.OnShareTargetSelectedListener +  
    + + SnapHelper +  
    + + Space +  
    + + SwitchCompat +  
    + + ThemedSpinnerAdapter +  
    + + ThemedSpinnerAdapter.Helper +  
    + + Toolbar +  
    + + Toolbar.LayoutParams +  
    + + Toolbar.OnMenuItemClickListener +  
    + + Toolbar.SavedState +  
    +  +

    + + + + + + + + + + + + + + + + + + + + +
    Changed Classes +
    + + LinearLayoutManager +  
    + + LinearSmoothScroller +  
    + + RecyclerView +  
    + + StaggeredGridLayoutManager +  
    +  +

    + +
    +
    + + + + diff --git a/docs/html/sdk/support_api_diff/24.2.0/missingSinces.txt b/docs/html/sdk/support_api_diff/24.2.0/missingSinces.txt new file mode 100644 index 0000000000000000000000000000000000000000..95149859daf208bdc409f642ca34cfa6464a63f9 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/missingSinces.txt @@ -0,0 +1,183 @@ +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityManagerCompat.AccessibilityStateChangeListener Interface +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener Interface +NO DOC BLOCK: android.support.v7.app.ActionBarActivity Class +NO DOC BLOCK: android.support.v7.widget.ActionMenuView Class +NO DOC BLOCK: android.support.v7.widget.ActionMenuView.LayoutParams Class +NO DOC BLOCK: android.support.v7.widget.ActionMenuView.OnMenuItemClickListener Interface +NO DOC BLOCK: android.support.v7.app.AppCompatActivity Class +NO DOC BLOCK: android.support.v7.widget.AppCompatAutoCompleteTextView Class +NO DOC BLOCK: android.support.v7.widget.AppCompatButton Class +NO DOC BLOCK: android.support.v7.widget.AppCompatCheckBox Class +NO DOC BLOCK: android.support.v7.widget.AppCompatCheckedTextView Class +NO DOC BLOCK: android.support.v7.app.AppCompatDialogFragment Class +NO DOC BLOCK: android.support.v7.widget.AppCompatEditText Class +NO DOC BLOCK: android.support.v7.widget.AppCompatImageButton Class +NO DOC BLOCK: android.support.v7.widget.AppCompatImageView Class +NO DOC BLOCK: android.support.v7.widget.AppCompatMultiAutoCompleteTextView Class +NO DOC BLOCK: android.support.v7.widget.AppCompatRadioButton Class +NO DOC BLOCK: android.support.v7.widget.AppCompatRatingBar Class +NO DOC BLOCK: android.support.v7.widget.AppCompatSeekBar Class +NO DOC BLOCK: android.support.v7.widget.AppCompatSpinner Class +NO DOC BLOCK: android.support.v7.widget.AppCompatTextView Class +NO DOC BLOCK: android.support.v7.util.BatchingListUpdateCallback Class +NO DOC BLOCK: android.support.v7.widget.CardView Class +NO DOC BLOCK: android.support.v7.util.DiffUtil Class +NO DOC BLOCK: android.support.v7.util.DiffUtil.Callback Class +NO DOC BLOCK: android.support.v7.util.DiffUtil.DiffResult Class +NO DOC BLOCK: android.support.v7.widget.GridLayout Class +NO DOC BLOCK: android.support.v7.widget.GridLayout.Alignment Class +NO DOC BLOCK: android.support.v7.widget.GridLayout.LayoutParams Class +NO DOC BLOCK: android.support.v7.widget.GridLayout.Spec Class +NO DOC BLOCK: android.support.v7.widget.LinearLayoutCompat Class +NO DOC BLOCK: android.support.v7.widget.LinearLayoutCompat.LayoutParams Class +NO DOC BLOCK: android.support.v7.widget.LinearSnapHelper Class +NO DOC BLOCK: android.support.v7.widget.ListPopupWindow Class +NO DOC BLOCK: android.support.v7.util.ListUpdateCallback Interface +NO DOC BLOCK: android.support.v7.preference.MultiSelectListPreferenceDialogFragmentCompat Class +NO DOC BLOCK: android.support.v7.app.NotificationCompat Class +NO DOC BLOCK: android.support.v7.app.NotificationCompat.Builder Class +NO DOC BLOCK: android.support.v7.app.NotificationCompat.MediaStyle Class +NO DOC BLOCK: android.support.v4.util.PatternsCompat Class +NO DOC BLOCK: android.support.v7.widget.PopupMenu Class +NO DOC BLOCK: android.support.v7.widget.PopupMenu.OnDismissListener Interface +NO DOC BLOCK: android.support.v7.widget.PopupMenu.OnMenuItemClickListener Interface +NO DOC BLOCK: android.support.v7.widget.RecyclerView.OnFlingListener Class +NO DOC BLOCK: android.support.v7.widget.RecyclerView.SmoothScroller.ScrollVectorProvider Interface +NO DOC BLOCK: android.support.v7.widget.SearchView Class +NO DOC BLOCK: android.support.v7.widget.SearchView.OnCloseListener Interface +NO DOC BLOCK: android.support.v7.widget.SearchView.OnQueryTextListener Interface +NO DOC BLOCK: android.support.v7.widget.SearchView.OnSuggestionListener Interface +NO DOC BLOCK: android.support.v4.widget.SearchViewCompat.OnCloseListener Interface +NO DOC BLOCK: android.support.v4.widget.SearchViewCompat.OnQueryTextListener Interface +NO DOC BLOCK: android.support.v7.widget.ShareActionProvider Class +NO DOC BLOCK: android.support.v7.widget.ShareActionProvider.OnShareTargetSelectedListener Interface +NO DOC BLOCK: android.support.v4.app.SharedElementCallback.OnSharedElementsReadyListener Interface +NO DOC BLOCK: android.support.v7.widget.SnapHelper Class +NO DOC BLOCK: android.support.v7.widget.Space Class +NO DOC BLOCK: android.support.v4.widget.SwipeRefreshLayout.OnChildScrollUpCallback Interface +NO DOC BLOCK: android.support.v7.widget.SwitchCompat Class +NO DOC BLOCK: android.support.v7.widget.ThemedSpinnerAdapter Interface +NO DOC BLOCK: android.support.v7.widget.ThemedSpinnerAdapter.Helper Class +NO DOC BLOCK: android.support.v7.widget.Toolbar Class +NO DOC BLOCK: android.support.v7.widget.Toolbar.LayoutParams Class +NO DOC BLOCK: android.support.v7.widget.Toolbar.OnMenuItemClickListener Interface +NO DOC BLOCK: android.support.v7.widget.Toolbar.SavedState Class +NO DOC BLOCK: android.support.v4.view.WindowInsetsCompat Constructor (android.support.v4.view.WindowInsetsCompat) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityManagerCompat Method addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, android.support.v4.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener) +NO DOC BLOCK: android.support.v4.media.session.MediaButtonReceiver Method buildMediaButtonPendingIntent(android.content.Context, android.content.ComponentName, long) +NO DOC BLOCK: android.support.v4.media.session.MediaButtonReceiver Method buildMediaButtonPendingIntent(android.content.Context, long) +NO DOC BLOCK: android.support.v4.graphics.drawable.DrawableCompat Method clearColorFilter(android.graphics.drawable.Drawable) +NO DOC BLOCK: android.support.design.widget.TabLayout Method clearOnTabSelectedListeners() +NO DOC BLOCK: android.support.v7.widget.StaggeredGridLayoutManager Method computeScrollVectorForPosition(int) +NO DOC BLOCK: android.support.v4.app.FragmentController Method findFragmentByWho(java.lang.String) +NO DOC BLOCK: android.support.v4.media.MediaBrowserCompat.MediaItem Method fromMediaItem(java.lang.Object) +NO DOC BLOCK: android.support.v4.media.MediaBrowserCompat.MediaItem Method fromMediaItemList(java.util.List) +NO DOC BLOCK: android.support.v4.media.session.MediaSessionCompat Method fromMediaSession(android.content.Context, java.lang.Object) +NO DOC BLOCK: android.support.v4.media.session.MediaSessionCompat.QueueItem Method fromQueueItem(java.lang.Object) +NO DOC BLOCK: android.support.v4.media.session.MediaSessionCompat.QueueItem Method fromQueueItemList(java.util.List) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityEventCompat Method getAction(android.view.accessibility.AccessibilityEvent) +NO DOC BLOCK: android.support.v4.widget.TextViewCompat Method getCompoundDrawablesRelative(android.widget.TextView) +NO DOC BLOCK: android.support.design.widget.CoordinatorLayout Method getDependents(android.view.View) +NO DOC BLOCK: android.support.v7.graphics.Palette Method getDominantColor(int) +NO DOC BLOCK: android.support.v7.graphics.Palette Method getDominantSwatch() +NO DOC BLOCK: android.support.v7.content.res.AppCompatResources Method getDrawable(android.content.Context, int) +NO DOC BLOCK: android.support.v7.app.ActionBarDrawerToggle Method getDrawerArrowDrawable() +NO DOC BLOCK: android.support.design.widget.CoordinatorLayout.Behavior Method getInsetDodgeRect(android.support.design.widget.CoordinatorLayout, V, android.graphics.Rect) +NO DOC BLOCK: android.support.design.widget.FloatingActionButton.Behavior Method getInsetDodgeRect(android.support.design.widget.CoordinatorLayout, android.support.design.widget.FloatingActionButton, android.graphics.Rect) +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Method getLaunchBounds() +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder Method getMediaItemNumberViewFlipper() +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder Method getMediaItemPausedView() +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder Method getMediaItemPlayingView() +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter Method getMediaPlayState(java.lang.Object) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityEventCompat Method getMovementGranularity(android.view.accessibility.AccessibilityEvent) +NO DOC BLOCK: android.support.v7.widget.RecyclerView Method getOnFlingListener() +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method getPasswordVisibilityToggleContentDescription() +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method getPasswordVisibilityToggleDrawable() +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat Method getSelectionMode() +NO DOC BLOCK: android.support.v4.os.BuildCompat Method isAtLeastNMR1() +NO DOC BLOCK: android.support.design.widget.FloatingActionButton.Behavior Method isAutoHideEnabled() +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat Method isContextClickable() +NO DOC BLOCK: android.support.v17.leanback.widget.ObjectAdapter Method isImmediateNotifySupported() +NO DOC BLOCK: android.support.v4.view.ViewCompat Method isImportantForAccessibility(android.view.View) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method isPasswordVisibilityToggleEnabled() +NO DOC BLOCK: android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat Method loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager) +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Method makeBasic() +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Method makeClipRevealAnimation(android.view.View, int, int, int, int) +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Method makeTaskLaunchBehind() +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder Method notifyPlayStateChanged() +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat Method obtain(int, int, boolean) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat Method obtain(int, int, int, int, boolean) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat Method obtain(int, float, float, float) +NO DOC BLOCK: android.support.design.widget.CoordinatorLayout.Behavior Method onAttachedToLayoutParams(android.support.design.widget.CoordinatorLayout.LayoutParams) +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter Method onBindMediaPlayState(android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder) +NO DOC BLOCK: android.support.v7.util.SortedList.Callback Method onChanged(int, int, java.lang.Object) +NO DOC BLOCK: android.support.design.widget.CoordinatorLayout.Behavior Method onDetachedFromLayoutParams() +NO DOC BLOCK: android.support.design.widget.AppBarLayout.ScrollingViewBehavior Method onRequestChildRectangleOnScreen(android.support.design.widget.CoordinatorLayout, android.view.View, android.graphics.Rect, boolean) +NO DOC BLOCK: android.support.design.widget.CoordinatorLayout.Behavior Method onRequestChildRectangleOnScreen(android.support.design.widget.CoordinatorLayout, V, android.graphics.Rect, boolean) +NO DOC BLOCK: android.support.v4.app.SharedElementCallback Method onSharedElementsArrived(java.util.List, java.util.List, android.support.v4.app.SharedElementCallback.OnSharedElementsReadyListener) +NO DOC BLOCK: android.support.v7.app.AppCompatDelegate Method onStart() +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter Method onUnbindMediaPlayState(android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityManagerCompat Method removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager, android.support.v4.view.accessibility.AccessibilityManagerCompat.TouchExplorationStateChangeListener) +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Method requestUsageTimeReport(android.app.PendingIntent) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityEventCompat Method setAction(android.view.accessibility.AccessibilityEvent, int) +NO DOC BLOCK: android.support.customtabs.CustomTabsIntent Method setAlwaysUseBrowserUI(android.content.Intent) +NO DOC BLOCK: android.support.design.widget.FloatingActionButton.Behavior Method setAutoHideEnabled(boolean) +NO DOC BLOCK: android.support.design.widget.CollapsingToolbarLayout Method setCollapsedTitleTextColor(android.content.res.ColorStateList) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat Method setContextClickable(boolean) +NO DOC BLOCK: android.support.v7.app.ActionBarDrawerToggle Method setDrawerArrowDrawable(android.support.v7.graphics.drawable.DrawerArrowDrawable) +NO DOC BLOCK: android.support.design.widget.CollapsingToolbarLayout Method setExpandedTitleTextColor(android.content.res.ColorStateList) +NO DOC BLOCK: android.support.customtabs.CustomTabsIntent.Builder Method setInstantAppsEnabled(boolean) +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Method setLaunchBounds(android.graphics.Rect) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityEventCompat Method setMovementGranularity(android.view.accessibility.AccessibilityEvent, int) +NO DOC BLOCK: android.support.v4.widget.SwipeRefreshLayout Method setOnChildScrollUpCallback(android.support.v4.widget.SwipeRefreshLayout.OnChildScrollUpCallback) +NO DOC BLOCK: android.support.v7.widget.RecyclerView Method setOnFlingListener(android.support.v7.widget.RecyclerView.OnFlingListener) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setPasswordVisibilityToggleContentDescription(int) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setPasswordVisibilityToggleContentDescription(java.lang.CharSequence) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setPasswordVisibilityToggleDrawable(android.graphics.drawable.Drawable) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setPasswordVisibilityToggleDrawable(int) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setPasswordVisibilityToggleEnabled(boolean) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setPasswordVisibilityToggleTintList(android.content.res.ColorStateList) +NO DOC BLOCK: android.support.design.widget.TextInputLayout Method setPasswordVisibilityToggleTintMode(android.graphics.PorterDuff.Mode) +NO DOC BLOCK: android.support.customtabs.CustomTabsSession Method setSecondaryToolbarViews(android.widget.RemoteViews, int[], android.app.PendingIntent) +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter.ViewHolder Method setSelectedMediaItemNumberView(int) +NO DOC BLOCK: android.support.customtabs.CustomTabsIntent Method shouldAlwaysUseBrowserUI(android.content.Intent) +NO DOC BLOCK: android.support.v4.app.ServiceCompat Method stopForeground(android.app.Service, int) +NO DOC BLOCK: android.support.v4.media.session.PlaybackStateCompat Method toKeyCode(long) +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat Field ACTION_ARGUMENT_COLUMN_INT +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat Field ACTION_ARGUMENT_PROGRESS_VALUE +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat Field ACTION_ARGUMENT_ROW_INT +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_CONTEXT_CLICK +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_SCROLL_DOWN +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_SCROLL_LEFT +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_SCROLL_RIGHT +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_SCROLL_TO_POSITION +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_SCROLL_UP +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_SET_PROGRESS +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat Field ACTION_SHOW_ON_SCREEN +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field BT_FOLDER_TYPE_ALBUMS +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field BT_FOLDER_TYPE_ARTISTS +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field BT_FOLDER_TYPE_GENRES +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field BT_FOLDER_TYPE_MIXED +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field BT_FOLDER_TYPE_PLAYLISTS +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field BT_FOLDER_TYPE_TITLES +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field BT_FOLDER_TYPE_YEARS +NO DOC BLOCK: android.support.design.widget.CoordinatorLayout.LayoutParams Field dodgeInsetEdges +NO DOC BLOCK: android.support.v4.media.MediaDescriptionCompat Field EXTRA_BT_FOLDER_TYPE +NO DOC BLOCK: android.support.customtabs.CustomTabsIntent Field EXTRA_ENABLE_INSTANT_APPS +NO DOC BLOCK: android.support.v4.media.MediaBrowserServiceCompat.BrowserRoot Field EXTRA_SUGGESTION_KEYWORDS +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Field EXTRA_USAGE_TIME_REPORT +NO DOC BLOCK: android.support.v4.app.ActivityOptionsCompat Field EXTRA_USAGE_TIME_REPORT_PACKAGES +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityNodeProviderCompat Field HOST_VIEW_ID +NO DOC BLOCK: android.support.design.widget.CoordinatorLayout.LayoutParams Field insetEdge +NO DOC BLOCK: android.support.v4.media.MediaMetadataCompat Field METADATA_KEY_BT_FOLDER_TYPE +NO DOC BLOCK: android.support.v4.media.MediaMetadataCompat Field METADATA_KEY_MEDIA_URI +NO DOC BLOCK: android.support.design.widget.BottomSheetBehavior Field PEEK_HEIGHT_AUTO +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter Field PLAY_STATE_INITIAL +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter Field PLAY_STATE_PAUSED +NO DOC BLOCK: android.support.v17.leanback.widget.AbstractMediaItemPresenter Field PLAY_STATE_PLAYING +NO DOC BLOCK: android.support.v4.app.ServiceCompat Field STOP_FOREGROUND_DETACH +NO DOC BLOCK: android.support.v4.app.ServiceCompat Field STOP_FOREGROUND_REMOVE +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityEventCompat Field TYPE_ASSIST_READING_CONTEXT +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityWindowInfoCompat Field TYPE_SPLIT_SCREEN_DIVIDER +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityEventCompat Field TYPE_VIEW_CONTEXT_CLICKED +NO DOC BLOCK: android.support.v4.view.accessibility.AccessibilityEventCompat Field TYPE_WINDOWS_CHANGED diff --git a/docs/html/sdk/support_api_diff/24.2.0/stylesheet-jdiff.css b/docs/html/sdk/support_api_diff/24.2.0/stylesheet-jdiff.css new file mode 100644 index 0000000000000000000000000000000000000000..edafaa3da3e52425614c22df3412f98f057fbf1e --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/stylesheet-jdiff.css @@ -0,0 +1,44 @@ + +/* (http://www.jdiff.org) */ + +div.and-diff-id {border: 1px solid #eee;position:relative;float:right;clear:both;padding:0px;} +table.diffspectable {border:1px;padding:0px;margin:0px;} +.diffspechead {background-color:#eee;} +.diffspectable tr {border:0px;padding:0px;} +.diffspectable td {background-color:eee;border:0px;font-size:90%;font-weight:normal;padding:0px;padding-left:1px;padding-right:1px;text-align:center;color:777;} +td.diffvalueold {color:orange;background-color:white;border:0px;font-size:80%;font-style:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;} +td.diffvaluenew {color:green;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;} +td.diffvalue {color:444;background-color:white;border:0px;font-size:80%;font-weight:normal;text-align:left;padding:0px;padding-left:1px;padding-right:1px;line-height:.95em;} +td.diffspec {background-color:white;border:0px;font-size:80%;font-weight:normal;padding:1px;color:444;text-align:right;padding-right:.5em;line-height:.95em;} +tt {font-size:11pt;font-family:monospace;} +.indexHeader { + font-size:96%; + line-height:.8em;} +.jdiffIndex td { + font-size:96%; + xline-height:.8em; + padding:2px; + padding-left:1em;} +.indexText { + font-size:100%; + padding-left:1em;} +#indexTableCaption { + font-size:96%; + margin-top:.25em; + margin-bottom:0; + } +.hiddenlink { + font-size:96%; + line-height:.8em; + text-decoration:none;} +a { + text-decoration:none;} +a:hover { + text-decoration:underline;} +.indexBox { + border: 1px solid red; + margin:1em 0 0 0;} +.letterIndexHead { + font-size: 1.5em;font-weight:9; + margin:0 0 0em 0; + border: 1px solid red;} diff --git a/docs/html/sdk/support_api_diff/24.2.0/user_comments_for_24.1.0_to_24.2.0.xml b/docs/html/sdk/support_api_diff/24.2.0/user_comments_for_24.1.0_to_24.2.0.xml new file mode 100644 index 0000000000000000000000000000000000000000..5a1bfc6171a3ccc242763beb4e840172647d7493 --- /dev/null +++ b/docs/html/sdk/support_api_diff/24.2.0/user_comments_for_24.1.0_to_24.2.0.xml @@ -0,0 +1,1897 @@ + + + + + + + + + + + + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + + + InsertCommentsHere + + + + diff --git a/docs/html/topic/arc/_book.yaml b/docs/html/topic/arc/_book.yaml new file mode 100644 index 0000000000000000000000000000000000000000..42287a7c858759e8e2c7ecea96a2f45678b67bfe --- /dev/null +++ b/docs/html/topic/arc/_book.yaml @@ -0,0 +1,9 @@ +toc: +- title: Optimizing Apps for Chromebooks + path: /topic/arc/index.html +- title: App Manifest Compatibility for Chromebooks + path: /topic/arc/manifest.html +- title: Loading Apps on Chromebooks + path: /topic/arc/sideload.html +- title: Chrome OS Device Support for Apps + path: /topic/arc/device-support.html diff --git a/docs/html/topic/arc/device-support.jd b/docs/html/topic/arc/device-support.jd new file mode 100644 index 0000000000000000000000000000000000000000..fc471acb05a5ec319cf579496c579b3931560d5c --- /dev/null +++ b/docs/html/topic/arc/device-support.jd @@ -0,0 +1,153 @@ +page.title=Chrome OS Device Support for Apps +@jd:body + +
    +
    +

    On this page

    + +
      +
    1. Overview
    2. +
    3. Supported Platforms
    4. +
    +
    +
    + +

    +You can use the Google Play Store to install Android apps on several Google +Chromebooks. This document describes the Chromebooks, Chromeboxes, and +Chromebases that can install Android apps, both currently and in upcoming +releases of Chrome OS. +

    + +

    Overview

    + +

    +The same Android apps that run on phones and tablets can run on Chromebooks +without compromising their speed, simplicity, or security. To develop the best +experience for Android apps across Chromebooks, you should test your app on a +suite of devices that consists of the following categories: +

    + +
      +
    • + ARM architecture. +
    • +
    • + Intel x86 architecture. +
    • +
    • + Touch. +
    • +
    • + Non-touch (uses fake-touch). +
    • +
    • + Convertible. +
    • +
    + +

    To learn more about Google Play Store support on Chromebooks, see the +following +Google Chrome blog post. +

    + +

    Note: You may elect to exclude your app from +being available to certain Android devices, such as Chromebooks. For more +information, visit +View & restrict your app's compatible devices. +

    + +

    +The following section lists the Chromebooks that work with Android apps and the +categories that each device satisfies. +

    + +

    Supported Platforms

    + +

    +Android apps are not available on every Chromebook, but Google continues to +evaluate more devices based on a range of factors, such as processor type, GPU, +and drivers. The following table shows the platforms that currently support +Android apps: +

    + +

    + Table 1. Chromebooks that currently support Android apps.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ManufacturerModelArchitectureTouchscreen supportConvertible
    AcerChromebook R11 / C738TIntel x86YesYes
    AsusChromebook FlipARMYesYes
    GoogleChromebook Pixel (2015)Intel x86YesNo
    + +

    +The following list shows the platforms that will support Android apps in an +upcoming release of Chrome OS: +

    + +
      +
    • Acer: Chromebook 11 C740, Chromebook 11 CB3-111 / C730 / + C730E / CB3-131, Chromebook 14 CB3-431, Chromebook 14 for Work, Chromebook + 15 CB5-571 / C910, Chromebook 15 CB3-531, Chromebox CXI2, Chromebase 24 +
    • +
    • Asus: Chromebook C200, Chromebook C201, + Chromebook C202SA, Chromebook C300SA, Chromebook C300, Chromebox CN62, + Chromebit CS10
    • +
    • AOpen: Chromebox Commercial, + Chromebase Commercial 22"
    • +
    • Bobicus: Chromebook 11
    • +
    • CDI: eduGear Chromebook K Series, + eduGear Chromebook M Series, eduGear Chromebook R Series
    • +
    • CTL: Chromebook J2 / J4, N6 Education Chromebook, + J5 Convertible Chromebook
    • +
    • Dell: Chromebook 11 3120, Chromebook 13 7310
    • +
    • Edxis: Chromebook, Education Chromebook
    • +
    • Haier: Chromebook 11, Chromebook 11e, Chromebook 11 G2 +
    • +
    • Hexa: Chromebook Pi
    • +
    • HiSense: Chromebook 11
    • +
    • Lava: Xolo Chromebook
    • +
    • HP: Chromebook 11 G3 / G4 / G4 EE, Chromebook 14 G4, + Chromebook 13
    • +
    • Lenovo: 100S Chromebook, N20 / N20P Chromebook, + N21 Chromebook, ThinkCentre Chromebox, ThinkPad 11e Chromebook, + N22 Chromebook, Thinkpad 13 Chromebook, Thinkpad 11e Chromebook Gen 3
    • +
    • Medion: Akoya S2013, Chromebook S2015
    • +
    • M&A: Chromebook
    • +
    • NComputing: Chromebook CX100
    • +
    • Nexian: Chromebook 11.6"
    • +
    • PCMerge: Chromebook PCM-116E
    • +
    • Poin2: Chromebook 11
    • +
    • Samsung: Chromebook 2 11" - XE500C12, Chromebook 3
    • +
    • Sector 5: E1 Rugged Chromebook
    • +
    • Senkatel: C1101 Chromebook
    • +
    • Toshiba: Chromebook 2, Chromebook 2 (2015)
    • +
    • True IDC: Chromebook 11
    • +
    • Viglen: Chromebook 11
    • +
    diff --git a/docs/html/topic/arc/index.jd b/docs/html/topic/arc/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..a025459226aa5805f0089f6652d58ed212c98464 --- /dev/null +++ b/docs/html/topic/arc/index.jd @@ -0,0 +1,398 @@ +page.title=Optimizing Apps for Chromebooks +@jd:body + + + +

    +Google Chromebooks now support the Google Play Store and Android apps. This +document describes some ways that you can optimize your Android apps for +Chromebooks. +

    + +

    Update Your App's Manifest File

    + +

    +To begin optimizing your Android app for Chromebooks, update your manifest file +(AndroidManifest.xml) to account for some key hardware and software +differences between Chromebooks and other devices running Android. +

    + +

    +As of Chrome OS version M53, all Android apps that don't explicitly require the +android.hardware.touchscreen +feature will also work on Chrome OS devices that support the +android.hardware.faketouch feature. However, if you want your app +to work on all Chromebooks in the best possible way, go to your manifest file +and adjust the settings so that the android.hardware.touchscreen +feature is not required, as shown in the following example. You should also +review your mouse and keyboard interactions. +

    + +
    +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    +          ... >
    +    <!-- Some Chromebooks don't support touch. Although not essential,
    +         it's a good idea to explicitly include this declaration. -->
    +    <uses-feature android:name="android.hardware.touchscreen"
    +                  android:required="false" />
    +</manifest>
    +
    + +

    +Different devices often have different sensors available in them. See the Sensors +Overview document for an overview of all sensors that the Android platform +supports. Although Android handheld devices may have GPS and accelerometers, +sensors are not guaranteed to be available in every Chromebook. However, there +are cases where the functionality of a sensor is provided in another way. For +example, Chromebooks may not have GPS sensors, but they still provide location +data based on Wi-Fi connections. If you want your app to run on Chromebooks, +regardless of sensor support, you should update your manifest file so that none +of the sensors are required. +

    + +

    Note: If you don't require a particular sensor +for your app but still use measurements from the sensor when it's available, +make sure you dynamically check for the sensor's availability before trying to +gather information from it in your app. +

    + +

    +Some software features are unsupported on Chromebooks. For example, apps that +provide custom IMEs, app widgets, live wallpapers, and app launchers aren't +supported and won't be available for installation on Chromebooks. For a complete +list of software features that aren't currently supported on Chromebooks, see incompatible +software features. +

    + +

    Leverage Support for Multi-Window Mode

    + +

    +The implementation of Android apps on Chrome OS includes basic multi-window +support. Instead of automatically drawing over the full screen, Android renders +apps on Chrome OS into layouts that are appropriate for this form factor. Google +provides support for the most common window layouts: + +

      +
    • + Portrait – Similar to Nexus 5. +
    • +
    • + Landscape – Similar to Nexus 7. +
    • +
    • + Maximized – Uses all available screen pixels. +
    • +
    + +

    +In addition, end users are presented with window controls to toggle among all +available layouts. By choosing the correct orientation option, you can ensure +that the user has the correct layout upon launching the app. If an app is +available in portrait and landscape, it defaults to landscape if possible. After +this option is set, it is remembered on a per-app basis. Google recommends that +you test your app to ensure that it handles changes in window size +appropriately. +

    + +

    Support the Keyboard, Trackpad, and Mouse

    + +

    +All Chromebooks have a physical keyboard and a trackpad, and some Chromebooks +have a touchscreen as well. Some devices can even convert from a laptop to a +tablet. +

    + +

    +Many existing apps already support mouse and trackpad interactions with no extra +work required. However, it's always best to adjust your app's behavior +appropriately when users interact with it using a trackpad instead of a +touchscreen, and you should support and distinguish between both interfaces +properly. Given the support for physical keyboards, you can now provide hotkeys +to enable your app's users to be more productive. For example, if your app +supports printing, you can use Ctrl+P to open a print dialog. +

    + +

    Use Backup and Restore Effectively

    + +

    +One of the strongest features of Chromebooks is that users can easily migrate +from one device to another. That is, if someone stops using one Chromebook and +starts using another, they simply have to sign in, and all of their apps appear. +

    + +

    Tip: Although it's not mandatory, backing up +your app's data to the cloud is a good idea. +

    + +

    +Chromebooks can also be shared among a large number of people, such as in +schools. Since local storage is not infinite, entire accounts—together +with their storage—can be removed from the device at any point. For +educational settings, it's a good idea to keep this scenario in mind. +

    + +

    Update the NDK Libraries

    + +

    +If your app uses the Android NDK libraries, and its target SDK version is 23 or +higher, ensure that text relocations are removed from both the ARM and x86 +versions of your NDK libraries, as they're not compatible in Android 6.0 (API +level 23) and higher. By leaving text relocations in your NDK libraries, you may +also cause incompatibility errors with Chromebooks, especially when running on +a device that uses an x86 architecture. +

    + +

    Note: To view more details on updating NDK +libraries properly, see the +Runtime section of the Android 6.0 Changes document. +

    + +

    Plan Support for New Android Features

    + +

    +Android apps on Chromebooks initially ship with APIs for Android 6.0 (API level +23). By following the best practices outlined above, your app is likely to be +compatible with the multi-window improvements introduced in Android 7.0 (API +level 24). It's good to plan support for the APIs and behaviors available as of +Android 7.0, which feature several improvements. For example, multi-window +support is better integrated, and you're able to resize activities arbitrarily, +making them feel more natural. You can also access APIs for drag-and-drop +operations across apps and mouse cursor control. +

    + +

    Test Your App

    + +

    +To load your app onto your +Chromebook for testing, you must enter Developer mode on your Chrome OS +device and enable unknown sources. See the +Putting your Chrome OS Device into Developer Mode document for detailed +instructions about moving your device into Developer mode. After your device is +in Developer mode, you can go to your Chrome settings and select Enable +Unknown Sources under the security in app settings. +

    + +

    +After enabling Developer mode, you can load an Android app onto your Chrome OS +device using one of several methods. For more details, see the Load Your App section of +the Loading Apps on Chromebooks page. +

    + +

    Note: To ensure that your Android app works +well on a variety of Chromebook devices and available form factors, Google +recommends that you test your app on an ARM-based Chromebook, an x86-based +Chromebook, a device with a touchscreen and one without one, and on a +convertible device (one that can change between a laptop and a tablet). To view +the full list of supported devices, see the Chrome OS Device Support for +Apps page.

    + +

    Set Up ADB

    + +

    +Before attempting to set up an ADB connection, you must start your Chrome OS in + +Developer Mode so that you have the ability to install Android apps on the +Chromebook. +

    + +

    Caution: After switching your Chrome OS +device to Developer mode, it restarts and clears all existing data on the +device. +

    + +

    +To set up ADB, complete the following steps: +

    + +
      +
    1. + Press Ctrl+D to start your device. +
    2. +
    3. + Finish the setup process. +
    4. +
    5. + Log into your test account. +
    6. +
    7. + Accept the Google Play Store terms and service conditions. +
    8. +
    + +

    Configure the firewall

    + +

    +To configure the Chrome OS firewall to allow incoming ADB connections, complete +the following steps: +

    + +
      +
    1. + Press Ctrl+Alt+T to start the Chrome OS terminal. +
    2. +
    3. + Type shell to get to the bash command shell: +
      +crosh> shell
      +chronos@localhost / $
      +
      +
    4. +
    5. + Type the following commands to set up developer features and enable + disk-write access for the firewall settings changes: +
      +chronos@localhost / $ sudo /usr/libexec/debugd/helpers/dev_features_rootfs_verification
      +chronos@localhost / $ sudo reboot
      +
      + The sudo reboot command restarts your Chromebook. +

      Note: You can press the Tab +key to enable autocompletion of file names.

      +
    6. +
    7. + After your device restarts, log in to your test account and type the + following command to enable the secure shell and configure the + firewall properly: +
      +chronos@localhost / $ sudo /usr/libexec/debugd/helpers/dev_features_ssh
      +
      + You can now exit out of the shell. +
    8. +
    + +

    Note: You must complete this procedure only +once on your Chromebook.

    + +

    Check the IP address of your Chromebook

    + +

    +To verify the IP address of your Chromebook, complete the following steps: +

    + +
      +
    1. + Click the clock icon in the bottom-right area of the screen. +
    2. +
    3. + Click Settings. +
    4. +
    5. + The Internet Connection section in the Settings area lists all of + the available networks. Select the one that you want to use for ADB. +
    6. +
    7. + Take note of the IP address that appears. +
    8. +
    + +

    Enable ADB debugging

    + +

    +To enable ADB debugging, complete the following steps: +

    + +
      +
    1. + Click the clock icon in the bottom-right area of the screen. +
    2. +
    3. + Click Settings. +
    4. +
    5. + In the Android Apps section, click the Settings + link in the line that reads Manage your Android apps in Settings. + This brings up the Android apps settings. +
    6. +
    7. + Click About device. +
    8. +
    9. + Click Build number seven times to move into Developer mode. +
    10. +
    11. + Click the arrow in the top-left area of the window to go back to the main + Settings screen. +
    12. +
    13. + Click the new Developer options item, activate ADB + debugging, and then click OK to allow ADB + debugging. +
    14. +
    15. + Return to your development machine and use ADB to connect to your + Chromebook's using its IP address and port 22. +
    16. +
    17. + On your Chromebook, click Allow when prompted whether you + want to allow the debugger. Your ADB session is established. +
    18. +
    + +

    Troubleshooting ADB debugging

    + +

    +Sometimes the ADB device shows that it's offline when everything is connected +properly. In this case, complete the following steps to troubleshoot the issue: +

    + +
      +
    1. + Deactivate ADB debugging in Developer options. +
    2. +
    3. + In a terminal window, run adb kill-server. +
    4. +
    5. + Re-activate the ADB debugging option. +
    6. +
    7. + In a terminal window, attempt to run adb connect. +
    8. +
    9. + Click Allow when prompted whether you want to allow + debugging. Your ADB session is established. +
    10. +
    + +

    Additional Learning Materials

    + +

    +To learn more about optimizing your Android apps for Chromebooks, consult the +following resources: +

    + + diff --git a/docs/html/topic/arc/manifest.jd b/docs/html/topic/arc/manifest.jd new file mode 100644 index 0000000000000000000000000000000000000000..7d1866591ab3f55c067460abb2f00b17459955f6 --- /dev/null +++ b/docs/html/topic/arc/manifest.jd @@ -0,0 +1,341 @@ +page.title=App Manifest Compatibility for Chromebooks +@jd:body + + + +

    +As you prepare your Android app to run on Chromebooks, you should consider the +device features that your app uses. Chromebooks don't support all of the +hardware and software features that are available on other devices running +Android. If your app requires specific features that aren't supported on +Chromebooks, it won't be available for installation on Chromebooks. +

    + +

    +You declare your app's requirements for hardware features and certain software +features in the manifest file. +This document describes the app manifest feature declarations that aren't +compatible with Chromebooks. +

    + +

    Incompatible Manifest Entries

    + +

    +The manifest entries listed in this section aren't currently compatible with +Chromebooks. If your app uses any of these entries, consider removing them or +including the required="false" attribute value with them so that +your app can be installed on Chromebooks. For more information about declaring +feature use without requiring that the feature be available on the device, see +the guide for the +<uses-feature> manifest element. +

    + +

    Note: See the +Features Reference for a complete list of app manifest features and +descriptions. +

    + +

    Hardware features

    + +

    +Support for hardware features varies on Chromebooks. Some features aren't +supported on any Chromebooks while others are supported on some Chromebooks. +

    + +

    Unsupported hardware features

    + +

    +The following list includes the hardware features that aren't currently +supported on Chromebooks: +

    + +
      +
    • + android.hardware.camera – Back-facing camera +
    • +
    • + android.hardware.camera.autofocus – Camera that uses + autofocus +
    • +
    • + android.hardware.camera.capability.manual_post_processing  + – Camera that uses the MANUAL_POST_PROCESSING feature, + including functionality for overriding auto white balance +
    • +
    • + android.hardware.camera.capability.manual_sensor – Camera + that uses the MANUAL_SENSOR feature, including auto-exposure + locking support +
    • +
    • + android.hardware.camera.capability.raw – Camera that uses + the RAW feature, including the ability to save DNG (raw) files + and provide DNG-related metadata +
    • +
    • + android.hardware.camera.flash – Camera that uses flash +
    • +
    • + android.hardware.camera.level.full – Camera that uses + FULL-level image-capturing support +
    • +
    • + android.hardware.consumerir – Infrared (IR) +
    • +
    • + android.hardware.location.gps – GPS +
    • +
    • + android.hardware.nfc – Near-Field Communication (NFC) +
    • +
    • + android.hardware.nfc.hce – NFC card emulation + (deprecated) +
    • +
    • + android.hardware.sensor.barometer – Barometer (air + pressure) +
    • +
    • + android.hardware.telephony – Telephony, including radio + with data communication services +
    • +
    • + android.hardware.telephony.cdma – Telephony Code Division + Multiple Access (CDMA) network support +
    • +
    • + android.hardware.telephony.gsm – Telephony Global System + for Mobile Communications (GSM) network support +
    • +
    • + android.hardware.type.automotive – Android Auto user + interface +
    • +
    • + android.hardware.type.television – Television + (deprecated) +
    • + android.hardware.usb.accessory – USB accessory mode +
    • +
    • + android.hardware.usb.host – USB host mode +
    • +
    + +

    Partially-supported hardware features

    + +

    +The following list includes the hardware features that may be available on some +Chromebooks: +

    + +
      +
    • + android.hardware.sensor.accelerometer – Accelerometer + (device orientation) +
    • +
    • + android.hardware.sensor.compass – Compass +
    • +
    • + android.hardware.sensor.gyroscope – Gyroscope (device + rotation and twist) +
    • +
    • + android.hardware.sensor.light – Light +
    • +
    • + android.hardware.sensor.proximity – Proximity (to user) +
    • +
    • + android.hardware.sensor.stepcounter – Step counter +
    • +
    • + android.hardware.sensor.stepdetector – Step detector +
    • +
    + +

    Touchscreen hardware support

    + +

    +As of Chrome OS version M53, all Android apps that don't explicitly require the + +android.hardware.touchscreen feature will also work on Chrome +OS devices that support the +android.hardware.faketouch feature. Devices that have fake +touch interfaces provide a user input system that emulates basic touch events. +For example, the user could interact with a mouse or remote control to move an +on-screen cursor, scroll through a list, and drag elements from one part of the +screen to another. +

    + +

    +If you don't want your app to be installed on devices that have fake touch +interfaces but not touchscreens, you can complete one of the following actions: +

    + + + +

    Software features

    + +

    +The following list includes the software features that aren't currently +supported on Chromebooks: +

    + +
      +
    • + android.software.app_widgets – App Widgets on the Home + screen +
    • +
    • + android.software.device_admin – Device policy + administration +
    • +
    • + android.software.home_screen – Replaces device's Home + screen +
    • +
    • + android.software.input_methods – Custom input methods + (instances of + InputMethodService) +
    • +
    • + android.software.leanback – UI designed for large-screen + viewing +
    • +
    • + android.software.live_wallpaper – Animated wallpapers +
    • +
    • + android.software.live_tv – Streaming live TV programs +
    • +
    • + android.software.managed_users – Secondary users and + managed profiles +
    • +
    • + android.software.midi – Musical Instrument Digital + Interface (MIDI) protocol, which supports connecting to musical instruments + and providing sound +
    • +
    • + android.software.sip – Session Initiation Protocol (SIP) + service, which supports video conferencing and instant messaging +
    • +
    • + android.software.sip.voip – Voice Over Internet Protocol + (VoIP) service based on SIP, which supports two-way video conferencing +
    • +
    + +

    Permissions That Imply Feature Requirements

    + +

    +Some permissions that you request in your manifest files can create implied +requests for hardware and software features. By requesting these permissions, +you'll prevent your app from being installed on Chromebooks. +

    + +

    +For details about how to prevent permission requests from making your app +unavailable on Chromebooks, see the Incompatible +Manifest Entries section of this page. +

    + +

    +The following table shows the permissions that imply certain feature +requirements which make an app incompatible with Chromebooks: +

    + +

    +Table 1. Device permissions that imply hardware features which +are incompatible with Chromebooks. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CategoryThis Permission......Implies This Feature Requirement
    CameraCAMERA + android.hardware.camera and
    + android.hardware.camera.autofocus +
    TelephonyCALL_PHONEandroid.hardware.telephony
    CALL_PRIVILEGEDandroid.hardware.telephony
    MODIFY_PHONE_STATEandroid.hardware.telephony
    PROCESS_OUTGOING_CALLSandroid.hardware.telephony
    READ_SMSREAD_SMSandroid.hardware.telephony
    RECEIVE_SMSandroid.hardware.telephony
    RECEIVE_MMSandroid.hardware.telephony
    RECEIVE_WAP_PUSHandroid.hardware.telephony
    SEND_SMSandroid.hardware.telephony
    WRITE_APN_SETTINGSandroid.hardware.telephony
    WRITE_SMSandroid.hardware.telephony
    diff --git a/docs/html/topic/arc/sideload.jd b/docs/html/topic/arc/sideload.jd new file mode 100644 index 0000000000000000000000000000000000000000..dca84ffc65ca4f72b2480724fd44fe7ebefa1eba --- /dev/null +++ b/docs/html/topic/arc/sideload.jd @@ -0,0 +1,125 @@ +page.title=Loading Apps on Chromebooks +@jd:body + +
    + +
    + +

    +This document describes how to enter Developer mode and enable +unknown resources so that you can load Android apps on your Google +Chromebook. +

    + +

    Enter Developer Mode

    + +

    +To load Android apps, you must enable unknown sources. Enabling unknown sources +is available only when your device is in Developer mode. +

    + +

    Caution: Modifications that you make to the +system are not supported by Google and may void your warranty. Additionally, +modifications may cause hardware, software, or security issues. +

    + +

    Note: On most devices, both the +recovery button and the dev-switch button are virtualized. If +these instructions don't work for you, see the +specific instructions for your device. +

    + +

    +To enter Developer mode, complete these steps: +

    + +
      +
    1. + Invoke Recovery mode by pressing and holding the + Esc and Refresh (F3) keys, then pressing + the Power button. +
    2. +
    3. + When the Recovery screen appears, press Ctrl+D. + There's no prompt for this action, so you must simply complete it. + Afterwards, you are prompted to confirm and reboot into Developer mode. +
    4. +
    + +

    +If you see one of the following screens when you turn on your device, you've +successfully entered Developer mode: +

    + + + +

    Figure 1. Developer mode confirmation +screens.

    + +

    Note: To skip the OS loading screen, either +wait 30 seconds or press Ctrl+D, and your Chromebook continues +starting. +

    + +

    Enable Unknown Sources

    + +

    +To enable unknown sources, navigate to Chrome Settings > App Settings > +Security, then enable Unknown sources by moving the +slider to the right. +

    + +

    Note:You can enable unknown sources only when +your device is in Developer mode. +

    + +

    Load Your App

    + +

    +After enabling unknown sources, you can load apps by copying an app's APK file +to the Downloads folder and opening it with Android's File Manager app. + +

    + +

    +You can copy the APK file to your Chromebook using one of the following methods: +

    + +
      +
    • + Using a cloud app – Upload your APK file to Google + Drive or send it to yourself via email. Open it with the Android app + equivalent (Drive and Gmail, respectively). +
    • +
    • + Using an external storage device – Transfer the APK + file to the Downloads folder of your Chromebook using a thumb drive, SD + card, or an external hard drive. Afterwards, open the Android File Manager + app by navigating to Chrome Settings > App Settings > Device & + USB > Explore. +
    • +
    • + Using ADB – After setting up ADB on your + Chromebook, enter the following command into a terminal window on your + development workstation: +
      +adb install app-name.apk
      +
      +

      This command pushes the app to your connected Chromebook and installs the + app. For more information about copying and installing apps from a + development computer, see Installing an + Application.

      +
    • +
    diff --git a/docs/html/topic/instant-apps/_project.yaml b/docs/html/topic/instant-apps/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e6b8cd95fd69ac5ea9e4f6a6015091f4b7f8434e --- /dev/null +++ b/docs/html/topic/instant-apps/_project.yaml @@ -0,0 +1,6 @@ +name: "Android Instant Apps" +home_url: /topic/instant-apps/ +description: "An evolution in app sharing and discovery, Android Instant Apps enables Android apps to run instantly, without requiring installation." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /develop/_project.yaml diff --git a/docs/html/topic/instant-apps/faqs.jd b/docs/html/topic/instant-apps/faqs.jd index bf37241c8cd2d451cba294f6024a8af2e38340ed..f69a4da610c643a741495f303c524c9886643f8a 100644 --- a/docs/html/topic/instant-apps/faqs.jd +++ b/docs/html/topic/instant-apps/faqs.jd @@ -46,10 +46,7 @@ forcelocalnav=true How do permissions work in Android Instant Apps?
    Android Instant Apps uses the runtime permissions model introduced in - Android 6.0. - If an app supports the permission model introduced in Android 6.0 - (API level 23), it does not require any additional work to become an Instant - App that runs on older devices. + Android 6.0 (API level 23).

    diff --git a/docs/html/topic/instant-apps/index.jd b/docs/html/topic/instant-apps/index.jd index e2da9c519892a8f1684e932f696071ba363dc422..89809820981d39fa20e59ae7ff001b279ea207a7 100644 --- a/docs/html/topic/instant-apps/index.jd +++ b/docs/html/topic/instant-apps/index.jd @@ -81,7 +81,7 @@ excludeFromSuggestions=true Get people to your flagship Android experience from links that would otherwise open your mobile web page — like search, social media, messaging, and other deep links — without them - needing to stop and install your app first. + needing to install your app first.

    diff --git a/docs/html/topic/libraries/_project.yaml b/docs/html/topic/libraries/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cdf59e5120ce33f8aa110c6d75b91830c0b3e46a --- /dev/null +++ b/docs/html/topic/libraries/_project.yaml @@ -0,0 +1,6 @@ +name: "Android Libraries" +home_url: /topic/libraries/ +description: "This section describes several useful Android libraries that are not included with the Android Framework." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /develop/_project.yaml diff --git a/docs/html/topic/libraries/data-binding/index.jd b/docs/html/topic/libraries/data-binding/index.jd index 293de51ea0001670ae52dafa857c6090c9ef92f7..0faa1db1bf602b4937ead0a8d8eb4ef1a8ddac21 100644 --- a/docs/html/topic/libraries/data-binding/index.jd +++ b/docs/html/topic/libraries/data-binding/index.jd @@ -162,7 +162,9 @@ page.tags="databinding", "layouts"

    To use data binding, Android Plugin for Gradle 1.5.0-alpha1 - or higher is required. + or higher is required. See how to update the Android +Plugin for Gradle.

    @@ -246,21 +248,21 @@ android {

    Expressions within the layout are written in the attribute properties using - the “&commat;{}” syntax. Here, the TextView’s text is set to + the "@{}" syntax. Here, the TextView's text is set to the firstName property of user:

     <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
    -          android:text="&commat;{user.firstName}"/>
    +          android:text="@{user.firstName}"/>
     

    Data Object

    - Let’s assume for now that you have a plain-old Java object (POJO) for User: + Let's assume for now that you have a plain-old Java object (POJO) for User:

    @@ -296,8 +298,8 @@ public class User {
     

    From the perspective of data binding, these two classes are equivalent. The - expression &commat;{user.firstName} used - for the TextView’s android:text attribute will + expression @{user.firstName} used + for the TextView's android:text attribute will access the firstName field in the former class and the getFirstName() method in the latter class. Alternatively, it will also be resolved to firstName() if that @@ -310,10 +312,10 @@ public class User {

    By default, a Binding class will be generated based on the name of the layout - file, converting it to Pascal case and suffixing “Binding” to it. The above + file, converting it to Pascal case and suffixing "Binding" to it. The above layout file was main_activity.xml so the generate class was MainActivityBinding. This class holds all the bindings from the - layout properties (e.g. the user variable) to the layout’s Views + layout properties (e.g. the user variable) to the layout's Views and knows how to assign values for the binding expressions.The easiest means for creating the bindings is to do it while inflating:

    @@ -328,7 +330,7 @@ protected void onCreate(Bundle savedInstanceState) { }

    - You’re done! Run the application and you’ll see Test User in the UI. + You're done! Run the application and you'll see Test User in the UI. Alternatively, you can get the view via:

    @@ -434,15 +436,15 @@ public class Presenter { Then you can bind the click event to your class as follows:
    -  <?xml version="1.0" encoding="utf-8"?>
    -  <layout xmlns:android="http://schemas.android.com/apk/res/android">
    +  <?xml version="1.0" encoding="utf-8"?>
    +  <layout xmlns:android="http://schemas.android.com/apk/res/android">
           <data>
    -          <variable name="task" type="com.android.example.Task" />
    -          <variable name="presenter" type="com.android.example.Presenter" />
    +          <variable name="task" type="com.android.example.Task" />
    +          <variable name="presenter" type="com.android.example.Presenter" />
           </data>
    -      <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
    -          <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
    -          android:onClick="@{() -> presenter.onSaveClick(task)}" />
    +      <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
    +          <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
    +          android:onClick="@{() -> presenter.onSaveClick(task)}" />
           </LinearLayout>
       </layout>
     
    @@ -465,7 +467,7 @@ public class Presenter { above could be written as:

    -  android:onClick="@{(view) -> presenter.onSaveClick(task)}"
    +  android:onClick="@{(view) -> presenter.onSaveClick(task)}"
     
    Or if you wanted to use the parameter in the expression, it could work as follows:
    @@ -474,7 +476,7 @@ public class Presenter {
     }
     
    -  android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
    +  android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
     
    You can use a lambda expression with more than one parameter:
    @@ -483,8 +485,8 @@ public class Presenter {
     }
     
    -  <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
    -        android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
    +  <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
    +        android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
     

    If the event you are listening to returns a value whose type is not {@code @@ -498,7 +500,7 @@ public class Presenter { }

    -  android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
    +  android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
     

    If the expression cannot be evaluated due to {@code null} objects, Data Binding returns @@ -510,13 +512,13 @@ If you need to use an expression with a predicate (e.g. ternary), you can use {@code void} as a symbol.

    -  android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
    +  android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"
     
    Avoid Complex Listeners
    Listener expressions are very powerful and can make your code very easy to read. -On the other hand, listeners containing complex expressions make your layouts hard to read and unmaintainable. -These expressions should be as simple as passing available data from your UI to your callback method. You should implement +On the other hand, listeners containing complex expressions make your layouts hard to read and unmaintainable. +These expressions should be as simple as passing available data from your UI to your callback method. You should implement any business logic inside the callback method that you invoked from the listener expression.

    @@ -580,7 +582,7 @@ any business logic inside the callback method that you invoked from the listener

    When there are class name conflicts, one of the classes may be renamed to an - “alias:” + "alias:"

    @@ -601,7 +603,7 @@ any business logic inside the callback method that you invoked from the listener
         <import type="com.example.User"/>
         <import type="java.util.List"/>
         <variable name="user" type="User"/>
    -    <variable name="userList" type="List&lt;User>"/>
    +    <variable name="userList" type="List&lt;User&gt;"/>
     </data>
     

    @@ -695,7 +697,7 @@ any business logic inside the callback method that you invoked from the listener

    By default, a Binding class is generated based on the name of the layout file, starting it with upper-case, removing underscores ( _ ) and - capitalizing the following letter and then suffixing “Binding”. This class + capitalizing the following letter and then suffixing "Binding". This class will be placed in a databinding package under the module package. For example, the layout file contact_item.xml will generate ContactItemBinding. If the module package is @@ -718,7 +720,7 @@ any business logic inside the callback method that you invoked from the listener This generates the binding class as ContactItem in the databinding package in the module package. If the class should be generated in a different package within the module package, it may be prefixed with - “.”: + ".":

    @@ -741,7 +743,7 @@ any business logic inside the callback method that you invoked from the listener
     
     
     

    - Variables may be passed into an included layout's binding from the + Variables may be passed into an included layout's binding from the containing layout by using the application namespace and the variable name in an attribute:

    @@ -855,8 +857,8 @@ any business logic inside the callback method that you invoked from the listener
     android:text="@{String.valueOf(index + 1)}"
    -android:visibility="@{age &lt; 13 ? View.GONE : View.VISIBLE}"
    -android:transitionName='@{"image_" + id}'
    +android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"
    +android:transitionName='@{"image_" + id}'
     

    Missing Operations @@ -945,9 +947,9 @@ android:transitionName='@{"image_" + id}' <import type="android.util.SparseArray"/> <import type="java.util.Map"/> <import type="java.util.List"/> - <variable name="list" type="List&lt;String>"/> - <variable name="sparse" type="SparseArray&lt;String>"/> - <variable name="map" type="Map&lt;String, String>"/> + <variable name="list" type="List&lt;String&gt;"/> + <variable name="sparse" type="SparseArray&lt;String&gt;"/> + <variable name="map" type="Map&lt;String, String&gt;"/> <variable name="index" type="int"/> <variable name="key" type="String"/> </data> @@ -969,17 +971,17 @@ android:text="@{map[key]}"

    -android:text='@{map["firstName"]}'
    +android:text='@{map["firstName"]}'
     

    It is also possible to use double quotes to surround the attribute value. - When doing so, String literals should either use the &quot; or back quote + When doing so, String literals should either use the ' or back quote (`).

     android:text="@{map[`firstName`}"
    -android:text="@{map[&quot;firstName&quot;]}"
    +android:text="@{map['firstName']}"
     

    Resources @@ -1216,7 +1218,7 @@ private static class User { }

    - That's it! To access the value, use the set and get accessor methods: + That's it! To access the value, use the set and get accessor methods:

    @@ -1247,15 +1249,15 @@ user.put("age", 17);
     
     <data>
         <import type="android.databinding.ObservableMap"/>
    -    <variable name="user" type="ObservableMap&lt;String, Object>"/>
    +    <variable name="user" type="ObservableMap&lt;String, Object&gt;"/>
     </data>
     …
     <TextView
    -   android:text='@{user["lastName"]}'
    +   android:text='@{user["lastName"]}'
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
     <TextView
    -   android:text='@{String.valueOf(1 + (Integer)user["age"])}'
    +   android:text='@{String.valueOf(1 + (Integer)user["age"])}'
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
     
    @@ -1277,15 +1279,15 @@ user.add(17); <data> <import type="android.databinding.ObservableList"/> <import type="com.example.my.app.Fields"/> - <variable name="user" type="ObservableList&lt;Object>"/> + <variable name="user" type="ObservableList&lt;Object&gt;"/> </data> … <TextView - android:text='@{user[Fields.LAST_NAME]}' + android:text='@{user[Fields.LAST_NAME]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView - android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}' + android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}' android:layout_width="wrap_content" android:layout_height="wrap_content"/>
    @@ -1428,7 +1430,7 @@ public abstract void setNote(String note);

    When inflating another layout, a binding must be established for the new - layout. Therefore, the ViewStubProxy must listen to the ViewStub's + layout. Therefore, the ViewStubProxy must listen to the ViewStub's {@link android.view.ViewStub.OnInflateListener} and establish the binding at that time. Since only one can exist, the ViewStubProxy allows the developer to set an OnInflateListener on it that it will call after establishing the binding. @@ -1443,9 +1445,9 @@ public abstract void setNote(String note);

    - At times, the specific binding class won't be known. For example, a + At times, the specific binding class won't be known. For example, a {@link android.support.v7.widget.RecyclerView.Adapter} operating against arbitrary layouts - won't know the specific binding class. It still must assign the binding value during the + won't know the specific binding class. It still must assign the binding value during the {@link android.support.v7.widget.RecyclerView.Adapter#onBindViewHolder}.

    @@ -1499,13 +1501,13 @@ public void onBindViewHolder(BindingHolder holder, int position) { For an attribute, data binding tries to find the method setAttribute. The namespace for the attribute does not matter, only the attribute name itself.

    - For example, an expression associated with TextView's attribute + For example, an expression associated with TextView's attribute android:text will look for a setText(String). If the expression returns an int, data binding will search for a setText(int) method. Be careful to have the expression return the correct type, casting if necessary. Note that data binding will work even if no attribute exists with the given name. You can then easily "create" attributes for any setter by - using data binding. For example, support DrawerLayout doesn't have any + using data binding. For example, support DrawerLayout doesn't have any attributes, but plenty of setters. You can use the automatic setters to use one of these.

    @@ -1522,7 +1524,7 @@ namespace for the attribute does not matter, only the attribute name itself.

    - Some attributes have setters that don't match by name. For these + Some attributes have setters that don't match by name. For these methods, an attribute may be associated with the setter through {@link android.databinding.BindingMethods} annotation. This must be associated with a class and contains {@link android.databinding.BindingMethod} annotations, one for @@ -1591,8 +1593,8 @@ public static void loadImage(ImageView view, String url, Drawable error) { }

    -<ImageView app:imageUrl=“@{venue.imageUrl}”
    -app:error=“@{@drawable/venueError}”/>
    +<ImageView app:imageUrl="@{venue.imageUrl}"
    +app:error="@{@drawable/venueError}"/>
     

    @@ -1747,7 +1749,7 @@ public static void setListener(View view, final OnViewDetachedFromWindow detach,

     <TextView
    -   android:text='@{userMap["lastName"]}'
    +   android:text='@{userMap["lastName"]}'
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
     
    diff --git a/docs/html/topic/libraries/support-library/features.jd b/docs/html/topic/libraries/support-library/features.jd index 584bef8a79818fab67b0303e636670d12263c4cc..b5f189a0886e4aa919dfd4961370e47f93cd8bc1 100755 --- a/docs/html/topic/libraries/support-library/features.jd +++ b/docs/html/topic/libraries/support-library/features.jd @@ -7,7 +7,15 @@ page.title=Support Library Features

    In this document

      -
    1. v4 Support Library
    2. +
    3. v4 Support Libraries +
        +
      1. v4 compat library
      2. +
      3. v4 core-utils library
      4. +
      5. v4 core-ui library
      6. +
      7. v4 media-compat library
      8. +
      9. v4 fragment library
      10. +
      +
    4. Multidex Support Library
    5. v7 Support Libraries
        @@ -63,100 +71,115 @@ page.title=Support Library Features include the library in your application.

        -

        v4 Support Library

        +

        v4 Support Libraries

        -

        This library is designed to be used with Android 1.6 (API level 4) and higher. It includes the - largest set of APIs compared to the other libraries, including support for application components, - user interface features, accessibility, data handling, network connectivity, and programming - utilities. Here are a few of the key classes included in the v4 library:

        - -
          -
        • App Components -
            -
          • {@link android.support.v4.app.Fragment} - - Adds support for encapsulation of user interface and functionality - with Fragments, enabling - applications to provide layouts that adjust between small and - large-screen devices. -
          • - -
          • {@link android.support.v4.app.NotificationCompat} - Adds support for rich notification - features.
          • -
          • {@link android.support.v4.content.LocalBroadcastManager} - Allows applications to easily - register for and receive intents within a single application without broadcasting them - globally.
          • -
          -
        • -
        • User Interface -
            -
          • {@link android.support.v4.view.ViewPager} - Adds a - {@link android.view.ViewGroup} that manages the layout for the - child views, which the user can swipe between.
          • -
          • {@link android.support.v4.view.PagerTitleStrip} - - Adds a non-interactive title strip, that can be added as a child of - {@link android.support.v4.view.ViewPager}.
          • -
          • {@link android.support.v4.view.PagerTabStrip} - Adds a - navigation widget for switching between paged views, that can also be used with - {@link android.support.v4.view.ViewPager}.
          • -
          • {@link android.support.v4.widget.DrawerLayout} - Adds - support for creating a Navigation Drawer that can be pulled in from the edge of a window.
          • -
          • {@link android.support.v4.widget.SlidingPaneLayout} - - Adds widget for creating linked summary and detail views that - appropriately adapt to various screen sizes.
          • -
          -
        • -
        • Accessibility -
            -
          • {@link android.support.v4.widget.ExploreByTouchHelper} - - Adds a helper class for implementing accessibility support for custom views.
          • -
          • {@link android.support.v4.view.accessibility.AccessibilityEventCompat} - Adds support for - {@link android.view.accessibility.AccessibilityEvent}. For more information about implementing - accessibility, see Accessibility.
          • - -
          • {@link android.support.v4.view.accessibility.AccessibilityNodeInfoCompat} - Adds support - for {@link android.view.accessibility.AccessibilityNodeInfo}.
          • -
          • {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat} - Adds - support for {@link android.view.accessibility.AccessibilityNodeProvider}.
          • -
          • {@link android.support.v4.view.AccessibilityDelegateCompat} - Adds support for - {@link android.view.View.AccessibilityDelegate}.
          • -
          -
        • -
        • Content -
            -
          • {@link android.support.v4.content.Loader} - Adds support for asynchronous loading of data. - The library also provides concrete implementations of this class, including - {@link android.support.v4.content.CursorLoader} and - {@link android.support.v4.content.AsyncTaskLoader}.
          • -
          • {@link android.support.v4.content.FileProvider} - Adds support for sharing of private - files between applications.
          • -
          -
        • -
        +

        + These libraries are designed to be used with Android 2.3 (API level 9) and + higher. They include the largest set of APIs compared to the other libraries, + including support for application components, user interface features, + accessibility, data handling, network connectivity, and programming + utilities. +

        - There are many other APIs included in this library. For complete, detailed information about the - v4 Support Library APIs, see the {@link android.support.v4.app android.support.v4} package in the - API reference. + For complete, detailed information about the classes and methods provided by + the v4 support libraries, see the {@link android.support.v4.app + android.support.v4} package in the API reference.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v4/} directory. The library does not contain user -interface resources. To include it in your application project, follow the instructions for -Adding libraries without -resources.

        -

        Caution: Using dynamic dependencies, especially for higher version -numbers, can cause unexpected version updates and regression incompatibilities.

        +

        + Note: Prior to Support Library revision 24.2.0, there was a + single v4 support library. That library was divided into multiple modules to + improve efficiency. For backwards compatibility, if you list + support-v4 in your Gradle script, your APK will include all of + the v4 modules. However, to reduce APK size, we recommend that you just list + the specific modules your app needs. +

        + +

        v4 compat library

        + +

        + Provides compatibility wrappers for a number of framework APIs, such as + Context.obtainDrawable() and + View.performAccessibilityAction(). +

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:support-v4:23.3.0
        +com.android.support:support-compat:24.2.1
        +
        + +

        v4 core-utils library

        + +

        + Provides a number of utility classes, such as {@link + android.support.v4.content.AsyncTaskLoader} and {@link + android.support.v4.content.PermissionChecker}. +

        + +

        + The Gradle build script dependency identifier for this library is as follows: +

        + +
        +com.android.support:support-core-utils:24.2.1
         
        +

        v4 core-ui library

        +

        + Implements a variety of UI-related components, such as {@link + android.support.v4.view.ViewPager}, {@link + android.support.v4.widget.NestedScrollView}, and {@link + android.support.v4.widget.ExploreByTouchHelper}. +

        + +

        + The Gradle build script dependency identifier for this library is as follows: +

        + +
        +com.android.support:support-core-ui:24.2.1
        +
        + +

        v4 media-compat library

        + +

        + Backports portions of the media framework, + including {@link android.media.browse.MediaBrowser} and {@link + android.media.session.MediaSession}. +

        + +

        + The Gradle build script dependency identifier for this library is as follows: +

        + +
        +com.android.support:support-media-compat:24.2.1
        +
        + +

        v4 fragment library

        + +

        + Adds support for encapsulation of user interface and functionality with + fragments, + enabling applications to provide layouts that adjust between small and + large-screen devices. This module has dependencies on compat, core-utils, core-ui, and media-compat. +

        + +

        + The Gradle build script dependency identifier for this library is as follows: +

        + +
        +com.android.support:support-fragment:24.2.1
        +

        Multidex Support Library

        @@ -167,15 +190,6 @@ com.android.support:support-v4:23.3.0 Building Apps with Over 64K Methods.

        -

        - After you download the Android Support Libraries, this library is located in the - {@code <sdk>/extras/android/support/multidex/} directory. The library does not contain - user interface resources. To include it in your application project, follow the instructions - for - Adding libraries without - resources. -

        -

        The Gradle build script dependency identifier for this library is as follows:

        @@ -188,7 +202,7 @@ com.android.support:multidex:1.0.0

        v7 Support Libraries

        -

        There are several libraries designed to be used with Android 2.1 (API level 7) and higher. +

        There are several libraries designed to be used with Android 2.3 (API level 9) and higher. These libraries provide specific feature sets and can be included in your application independently from each other.

        @@ -228,16 +242,10 @@ com.android.support:multidex:1.0.0 -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v7/appcompat/} directory. The library contains user -interface resources. To include it in your application project, follow the instructions for -Adding libraries with -resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:appcompat-v7:23.3.0
        +com.android.support:appcompat-v7:24.2.1
         
        @@ -249,16 +257,10 @@ widget, which lets you show information inside cards that have a consistent look on any app. These cards are useful for material design implementations, and are used extensively in layouts for TV apps.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v7/cardview/} directory. The library contains user interface -resources. To include it in your application project, follow the instructions -for Adding -libraries with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:cardview-v7:23.3.0
        +com.android.support:cardview-v7:24.2.1
         
        @@ -271,16 +273,10 @@ allows you to arrange user interface elements using a grid of rectangular cells. For detailed information about the v7 gridlayout library APIs, see the {@link android.support.v7.widget android.support.v7.widget} package in the API reference.

        -

        This library is located in the {@code <sdk>/extras/android/support/v7/gridlayout/} - directory . The library contains user - interface resources. To include it in your application project, follow the instructions for - Adding libraries with - resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:gridlayout-v7:23.3.0
        +com.android.support:gridlayout-v7:24.2.1
         
        @@ -300,21 +296,10 @@ information about the v7 mediarouter library APIs, see the {@link android.support.v7.media android.support.v7.media} package in the API reference.

        -

        The v7 mediarouter library is located in the -<sdk>/extras/android/support/v7/mediarouter/ directory after -you download the Android Support Library. It's provided as a library project -with a dependency on the v7 appcompat library, so you'll need to include both -libraries in your build path when setting up your project. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        - -

        The Gradle builder script dependency identifier is as follows: -com.android.support:support-v7-mediarouter:<revision>, -where "<revision>" is the minimum revision at which the library is available. For example:

        +

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:mediarouter-v7:23.3.0
        +com.android.support:mediarouter-v7:24.2.1
         

        The v7 mediarouter library APIs introduced in Support Library @@ -331,16 +316,10 @@ prominent colors from an image. For example, a music app could use a from an album cover, and use those colors to build a color-coordinated song title card.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v7/palette/} directory. The library does not contain -user interface resources. To include it in your application project, follow the instructions for -Adding libraries without -resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:palette-v7:23.3.0
        +com.android.support:palette-v7:24.2.1
         
        @@ -353,16 +332,10 @@ class. This class provides support for the widget, a view for efficiently displaying large data sets by providing a limited window of data items.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v7/recyclerview/} directory. The library contains -user interface resources. To include it in your application project, follow the instructions -for Adding -libraries with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:recyclerview-v7:23.3.0
        +com.android.support:recyclerview-v7:24.2.1
         
        @@ -382,34 +355,21 @@ such as {@link android.support.v7.preference.CheckBoxPreference} and {@link android.support.v7.preference.ListPreference}.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v7/preference} directory. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:preference-v7:23.3.0
        +com.android.support:preference-v7:24.2.1
         
        - - - - - - -

        v8 Support Library

        -

        This library is designed to be used with Android 2.2 (API level 8) and higher. +

        This library is designed to be used with Android 2.3 (API level 9) and higher. This library provides specific feature sets and can be included in your application independently from other libraries.

        v8 renderscript library

        -

        This library is designed to be used with Android (API level 8) and higher. It adds support for +

        This library is designed to be used with Android 2.3 (API level 9) and higher. It adds support for the RenderScript computation framework. These APIs are included in the {@link android.support.v8.renderscript} package. You should be aware that the steps for including these APIs in your application is very @@ -446,16 +406,10 @@ defaultConfig { android.support.v13} package in the API reference.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v13/} directory. The library does not contain user -interface resources. To include it in your application project, follow the instructions for -Adding libraries without -resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:support-v13:23.3.0
        +com.android.support:support-v13:24.2.1
         
        @@ -478,16 +432,10 @@ for preference interfaces such as package in the API reference.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v14/} directory. The library does not contain user -interface resources. To include it in your application project, follow the instructions for -Adding libraries without -resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:preference-v14:23.3.0
        +com.android.support:preference-v14:24.2.1
         
        @@ -507,16 +455,10 @@ interface and classes, such as package in the API reference.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v17/} directory. The library does not contain user -interface resources. To include it in your application project, follow the instructions for -Adding libraries without -resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:preference-leanback-v17:23.3.0
        +com.android.support:preference-leanback-v17:24.2.1
         
        @@ -549,16 +491,10 @@ com.android.support:preference-leanback-v17:23.3.0 into a {@link android.support.v17.leanback.app.RowsFragment}. -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/v17/leanback} directory. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:leanback-v17:23.3.0
        +com.android.support:leanback-v17:24.2.1
         
        @@ -570,16 +506,10 @@ package provides APIs to support adding annotation metadata to your apps.

        -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/annotations} directory. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:support-annotations:23.3.0
        +com.android.support:support-annotations:24.2.1
         
        @@ -594,17 +524,10 @@ provides APIs to support adding material design components and patterns to your app developers to build upon, such as navigation drawers, floating action buttons (FAB), snackbars, and tabs.

        - -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/design} directory. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:design:23.3.0
        +com.android.support:design:24.2.1
         
        @@ -622,17 +545,10 @@ and Custom Tabs Callback.

        - -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/customtabs} directory. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:customtabs:23.3.0
        +com.android.support:customtabs:24.2.1
         
        @@ -653,17 +569,10 @@ and PercentRelativeLayout.

        - -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/percent} directory. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:percent:23.3.0
        +com.android.support:percent:24.2.1
         
        @@ -683,15 +592,8 @@ and RecommendationExtender.

        - -

        After you download the Android Support Libraries, this library is located in the -{@code <sdk>/extras/android/support/recommendation} directory. For more information -on how to set up your project, follow the instructions in Adding libraries -with resources.

        -

        The Gradle build script dependency identifier for this library is as follows:

        -com.android.support:recommendation:23.3.0
        +com.android.support:recommendation:24.2.1
         
        diff --git a/docs/html/topic/libraries/support-library/revisions.jd b/docs/html/topic/libraries/support-library/revisions.jd index 47d2ac18df01fe17d556120e8528d9ee42fb078f..9a24d1540e9b85088e6f26f430e83e9d9eaf8e94 100644 --- a/docs/html/topic/libraries/support-library/revisions.jd +++ b/docs/html/topic/libraries/support-library/revisions.jd @@ -6,9 +6,548 @@ page.metaDescription=This page provides details about the Support Library packag

        This page provides details about the Support Library package releases.

        -

        +

        Android Support Library, revision 24.2.1 + (September 2016) +

        + +
        + +

        Fixed issues:

        + +
          +
        • {@link android.support.design.widget.FloatingActionButton} can no longer + be anchored to indirect children of {@link + android.support.design.widget.CoordinatorLayout}. (AOSP issue 220250) +
        • + +
        • Image inside {@link + android.support.design.widget.CollapsingToolbarLayout} doesn’t scale properly + with fitsSystemWindows=true. (AOSP issue 220389) +
        • + +
        • {@link android.support.design.widget.CoordinatorLayout} throws {@link + java.lang.IndexOutOfBoundsException} when {@link + android.support.design.widget.Snackbar} is shown and dismissed. (AOSP issue + 220762) +
        • + +
        • {@link android.support.design.widget.TextInputLayout} fails to resolve + error text color. (AOSP issue 220305) +
        • + +
        • {@link android.support.v7.util.SortedList.BatchedCallback#onMoved + BatchedCallback.onMoved()} calls {@link + android.support.v7.util.SortedList.BatchedCallback#onInserted + BatchedCallback.onInserted()}. (AOSP issue 220309) +
        • + +
        • {@link android.support.design.widget.TextInputLayout} overrides right + compound drawable. (AOSP issue 220728) +
        • +
        + +

        + A complete list of public bug fixes is available on the + AOSP Issue Tracker. +

        + + +
        +
        + + + +
        +

        + Android Support Library, revision 24.2.0 + (August 2016) +

        + +
        + +

        Release 24.2.0 contains the following changes:

        + + + +

        Note: Release 24.2.0 removes support for + Android 2.2 (API level 8) and lower. Classes and methods that exist only to + serve those system versions are now marked as deprecated and should no longer + be used. These deprecated classes and methods may be removed in a future + release. +

        + +

        v4 Support Library split

        + +

        With this release, the v4 Support Library has + been split into several smaller modules:

        + +
        +
        + support-compat +
        + +
        + Provides compatibility wrappers for new framework APIs, such as + Context.getDrawable() and + View.performAccessibilityAction(). +
        + +
        + support-core-utils +
        + +
        + Provides a number of utility classes, such as {@link + android.support.v4.content.AsyncTaskLoader} and {@link + android.support.v4.content.PermissionChecker}. +
        + +
        + support-core-ui +
        + +
        + Implements a variety of UI-related components, such as {@link + android.support.v4.view.ViewPager}, {@link + android.support.v4.widget.NestedScrollView}, and {@link + android.support.v4.widget.ExploreByTouchHelper}. +
        + +
        + support-media-compat +
        + +
        + Backports portions of the media framework, + including {@link android.media.browse.MediaBrowser} and {@link + android.media.session.MediaSession}. +
        + +
        + support-fragment +
        + +
        + Backports the fragment + framework. This module has dependencies on support-compat, + support-core-utils, support-core-ui, and + support-media-compat. +
        +
        + +

        For backwards compatibility, if you list support-v4 in your +Gradle script, your APK will include all of these modules. However, to reduce +APK size, we recommend that you just list the specific modules your app needs. +

        + +

        API updates

        + +
          +
        • Clients using Custom Tabs can + control whether Instant Apps should open. (Note that Instant Apps are not yet + generally available.) To enable or disable Instant Apps, call + CustomTabsIntent.Builder.setInstantAppsEnabled() or + specify + EXTRA_ENABLE_INSTANT_APPS. By default, Custom Tabs will + default to enabling Instant Apps, when that feature becomes available. +
        • + +
        • {@link android.support.design.widget.TextInputLayout} adds support for + the + password visibility toggle from the material design specification. +
        • + +
        • The new android.support.transition + package backports the Transitions framework to API levels 14 + and higher. For more information, see the android.support.transition reference. +
        • + +
        • The Custom Tabs support library + adds support for using {@link android.widget.RemoteViews} in the secondary + toolbar. The existing {@link + android.support.customtabs.CustomTabsSession#setToolbarItem setToolbarItem()} + method is now deprecated. +
        • + +
        • {@link android.support.v7.content.res.AppCompatResources} adds the + ability to load a <vector> (on API level 9 and higher) or + <animated-vector> (on API level 11 and higher) from a + resource ID, by using the new getDrawable() method. +
        • + +
        • {@link android.support.design.widget.CoordinatorLayout} now supports + defining inset views, and specifying that other views should dodge the inset + views. This allows apps to replicate behavior patterns similar to the way + {@link android.support.design.widget.FloatingActionButton} moves out of the + way of a {@link android.support.design.widget.Snackbar}, but for any + arbitrary view children. For more information, see the + LayoutParams.insetEdge and + LayoutParams.dodgeInsetEdges reference documentation. +
        • + +
        • The new + DiffUtil class can calculate the difference between two + collections, and can dispatch a list of update operations that are suitable + to be consumed by a {@link android.support.v7.widget.RecyclerView.Adapter}. +
        • + +
        • + + RecyclerView.OnFlingListener has been added to support custom + behavior in response to flings. The SnapHelper + class provides an implementation specifically for snapping child views, and + the LinearSnapHelper + class extends this implementation to provide center-aligned snapping + behavior similar to {@link android.support.v4.view.ViewPager}. +
        • + +
        • The Custom Tabs library now allows clients to request the standard + browser UI, rather than custom tabs UI, by calling + CustomTabsIntent.setAlwaysUseBrowserUI(). This behavior is + useful in cases where the browser defaults to custom tabs UI but the user + has expressed a preference for the standard browser UI. +
        • + +
        + +

        Behavior changes

        + +
          +
        • If you use the appcompat library's day/night functionality, the system + now automatically recreates your activity whenever the day/night mode changes + (either because of the time of day, or because of a call to {@link + android.support.v7.app.AppCompatDelegate#setLocalNightMode + AppCompatDelegate.setLocalNightMode()}). +
        • + +
        • {@link android.support.design.widget.Snackbar} now draws behind the + navigation bar if the status bar is translucent. +
        • + +
        + +

        MediaRouter library

        + +

        + Bluetooth devices are no longer listed as media routes. Routing audio to + Bluetooth devices is now solely controlled at the Android system level. +

        + + +

        Deprecations

        + +

        Deprecated classes and methods are subject to removal in a future release. You should migrate away from these APIs as soon as possible.

        + +
          +
        • Several methods on the following classes were only required for API 8 and + lower, and should no longer be used. Instead, use the framework + implementations. +
            +
          • {@link android.support.v4.view.KeyEventCompat}: Replace with {@link + android.view.KeyEvent} +
          • + +
          • {@link android.support.v4.view.MotionEventCompat}: Use {@link + android.view.MotionEvent} +
          • + +
          • {@link android.support.v4.view.ViewCompat}: Use {@link + android.view.View} +
          • + +
          • {@link android.support.v4.view.ViewConfigurationCompat}: Use {@link + android.view.ViewConfiguration} +
          • +
          +
        • + +
        • + {@link android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat#getDescription + AccessibilityServiceInfoCompat.getDescription()} + has been deprecated in favor of + loadDescription() + which returns a correctly localized description. +
        • + +
        • You should not instantiate the ActivityCompat class + directly. The non-static getReferrer(Activity) method will be + made static in an upcoming release. +
        • + +
        • {@link android.support.design.widget.CoordinatorLayout.Behavior#isDirty + CoordinatorLayout.Behavior.isDirty()} has been deprecated and is no longer + called by {@link android.support.design.widget.CoordinatorLayout}. Any + implementations, as well as any calls to this method, should be removed. +
        • + +
        • {@link android.support.v4.media.session.MediaSessionCompat#obtain + MediaSessionCompat.obtain()} has been deprecated and replaced with the more + appropriately-named method + fromMediaSession(). +
        • + +
        • {@link + android.support.v4.media.session.MediaSessionCompat.QueueItem#obtain + MediaSessionCompat.QueueItem.obtain()} has been deprecated and replaced with + the more appropriately-named method + fromQueueItem(). +
        • + +
        • Several abstract classes have been deprecated and replaced with + interfaces that more closely reflect their framework equivalents. + +
        • + +
        • {@link android.support.customtabs.CustomTabsSession#setToolbarItem + CustomTabsSession.setToolbarItem()} has been deprecated and replaced by the + RemoteViews-based + setSecondaryToolbarViews(). +
        • +
        + +

        Bug fixes

        + +

        The following known issues have been fixed with release 24.2.0:

        + +
          +
        • Ensure SwipeRefreshLayout indicator is shown when + setRefreshing(true) is called before the first measurement pass + (AOSP + issue 77712) +
        • + +
        • Prevent TabLayout from flickering when changing pages + (AOSP + issue 180454) +
        • + +
        • Avoid ClassNotFoundException when unmarshalling + SavedState on API level 11 and lower (AOSP issue + 196430) +
        • +
        + +

        + A complete list of public bug fixes is available on the + AOSP Issue Tracker. +

        + +
        +
        + + + +
        +

        + Android Support Library, revision 24.1.1 + (July 2016) +

        + +
        + +

        Fixed issues:

        + +
          +
        • Fixes an issue in the 24.1.0 release which affected resource IDs + shared between support libraries. This issue caused apps that depended on + support libraries with resources (such as design and appcompat) to + encounter issues caused by resource ID mismatches. +
        • +
        + +
        +
        + + + +
        +

        + Android Support Library, revision 24.1.0 + (July 2016) +

        + +
        +
        +
        + Changes for v4 Support + Library: +
        + +
        +
          +
        • {@link android.support.v4.app.NotificationCompat.Action.WearableExtender} + has new getHintDisplayActionInline() and + setHintDisplayActionInline() methods for compatibility with + Android Wear 2.0 Preview. + These methods allow an application to specify that an action should be + displayed inline with the notification. +
        • + +
        • Calling {@link android.support.v4.app.Fragment#setUserVisibleHint + Fragment.setUserVisbileHint()} will no longer cause a fragment to become + started if the hint has been added to a {@link + android.support.v4.app.FragmentTransaction} that is not yet committed. This + affects users of {@link android.support.v4.app.FragmentPagerAdapter} that + override {@link android.support.v4.app.Fragment#setUserVisibleHint + setUserVisbileHint()} and assume a specific lifecycle state of the fragment + after calling super.setUserVisibleHint(). For more information, + see the reference page for docs for {@link + android.support.v4.app.Fragment#setUserVisibleHint + Fragment.setUserVisbileHint()}. +
        • +
        + +
        +

        Fixed issues:

        + +
          +
        • TabLayout.setCustomView(null) results in NullPointerException + (AOSP + issue 214753) +
        • + +
        • TabLayout incorrectly highlights custom tabs (AOSP issue 214316) +
        • + +
        • AppCompatTextHelper uses incorrectly sorted attribute array (AOSP issue 214366) +
        • + +
        • Unable to reference VectorDrawable from drawable container XML when using + custom ContextWrapper (AOSP issue 214055) +
        • + +
        • ViewDragHelper.saveLastMotion() throws ArrayIndexOutOfBoundsException + (AOSP + issue 212945) +
        • + +
        • BottomSheetBehavior expands to old content height when using + setState(STATE_EXPANDED) (AOSP issue + 213660) +
        • + +
        • CollapsingToolbarLayout doesn’t handle pinnable children with top or + bottom margins (AOSP issue + 213001) +
        • + +
        • Leanback browse title does not support RTL alignment (AOSP issue + 213461) +
        • + +
        • PagerTabStrip disappears due to missing inherited annotation (AOSP issue + 213359) +
        • + +
        • Data binding throws NullPointerException when using Boolean to set + conditional flags (AOSP issue + 191841) +
        • + +
        • CoordinatorLayout does not respond to setFitsSystemWindows() (AOSP issue + 212720) +
        • + +
        • BottomSheetBehavior crashes when setting initial state (AOSP issue + 203114) +
        • + +
        • ViewPager skips pages if the page index is a large value (AOSP issue + 211734) +
        • + +
        • BottomSheetBehavior does not work with dynamic layouts (AOSP issue + 205226) +
        • +
        +
        +
        + + + +
        +

        + Android Support Library, revision 24.0.0 (June 2016)

        @@ -120,7 +659,7 @@ page.metaDescription=This page provides details about the Support Library packag

        Android Support Library, revision 23.4.0 (May 2016)

        @@ -815,7 +1354,7 @@ page.metaDescription=This page provides details about the Support Library packag
        • Day and night themes can be found here: {@code - <sdk>/extras/android/support/v7/appcompat/res/values/themes_daynight.xml} + /extras/android/support/v7/appcompat/res/values/themes_daynight.xml}
        • {@code AppCompatDelegate.setDefaultNightMode()}: sets the @@ -2435,8 +2974,6 @@ if (animator instanceof SimpleItemAnimator) {
          • Added {@link android.support.v7.widget.GridLayout} to provide support for the {@link android.widget.GridLayout} layout object.
          • -
          • Added {@link android.support.v7.widget.Space} which can be used to create blank areas - within a {@link android.support.v7.widget.GridLayout} layout object.
      1. @@ -2661,7 +3198,7 @@ android.support.v4.app.TaskStackBuilder} to provide support for implementing the Android Design guidelines for navigation. These additions include a way to implement the action bar's Up button across versions. For an example implementation of this pattern, see the AppNavigation sample in -({@code <sdk>/samples/<platform>/AppNavigation}). +({@code /samples//AppNavigation}).
      2. Added {@link android.support.v4.app.NotificationCompat.Builder} to provide a compatibility implementation of Android 3.0's {@link android.app.Notification.Builder} helper class for creating standardized system notifications.
      3. diff --git a/docs/html/topic/libraries/support-library/setup.jd b/docs/html/topic/libraries/support-library/setup.jd index 62f7148acc7cb1b5ebfa355e44f8042ab0c47e1f..adb263cbcd9a1bf8f9af453407f059e2e0a6b44c 100755 --- a/docs/html/topic/libraries/support-library/setup.jd +++ b/docs/html/topic/libraries/support-library/setup.jd @@ -10,18 +10,12 @@ page.title=Support Library Setup
        1. Downloading the Support Library
        2. Choosing Support Libraries
        3. -
        4. Adding Support Libraries -
            -
          1. Adding libraries without resources
          2. -
          3. Adding libraries with resources
          4. -
          -
        5. +
        6. Adding Support Libraries
        7. Using Support Library APIs
          1. Manifest Declaration Changes
        8. -
        9. Code Samples

        See also

        @@ -45,8 +39,8 @@ page.title=Support Library Setup

        Downloading the Support Libraries

        -

        The Android Support Library package is provided as a supplemental download to the Android SDK - and is available through the Android +

        The Android Support Repository package is provided as a supplemental download + to the Android SDK and is available through the Android SDK Manager. Follow the instructions below to obtain the Support Library files.

        @@ -57,22 +51,18 @@ page.title=Support Library Setup
      4. Start the Android SDK Manager.
      5. In the SDK Manager window, scroll to the end of the Packages list, find the Extras folder and, if necessary, expand to show its contents.
      6. -
      7. Select the Android Support Library item. -

        - Note: If you're developing with Android Studio, select and install the - Android Support Repository item instead. -

        -
      8. +
      9. Select the Android Support Repository item.
      10. Click the Install packages... button.
      -

      Figure 1. The Android SDK Manager with the -Android Support Library selected.

      +

      Figure 1. The Android SDK Manager with +Android Support Repository selected.

      After downloading, the tool installs the Support Library files to your existing Android SDK directory. The library files are located in the following subdirectory of your SDK: - {@code <sdk>/extras/android/support/} directory.

      + <sdk>/extras/android/m2repository/com/android/support/ + directory.

      Choosing Support Libraries

      @@ -89,60 +79,29 @@ Android Support Library selected.

      classpath dependencies within your development environment. You must perform this procedure for each Support Library you want to use.

      -

      Some Support Libraries contain resources beyond compiled code classes, such as images or XML - files. For example, the v7 - appcompat and v7 - gridlayout libraries include resources.

      - -

      If you are not sure if a library contains resources, check the - Support Library Features page. - The following sections describe how to add a Support Library with or without resources to your - application project.

      - - -

      Adding libraries without resources

      - -

      To add a Support Library without resources to your application project:

      - -
        -
      1. Make sure you have downloaded the Android Support Repository - using the SDK Manager.
      2. -
      3. Open the {@code build.gradle} file for your application.
      4. -
      5. Add the support library to the {@code dependencies} section. For example, to add the v4 - support library, add the following lines: -
        -dependencies {
        -    ...
        -    compile "com.android.support:support-v4:18.0.+"
        -}
        -
        -
      6. -
      - - -

      Adding libraries with resources

      - -

      To add a Support Library with resources (such as - v7 - appcompat for action bar) to your application project:

      +

      To add a Support Library to your application project:

      1. Make sure you have downloaded the Android Support Repository using the SDK Manager.
      2. Open the {@code build.gradle} file for your application.
      3. -
      4. Add the support library feature project identifier to the {@code dependencies} section. - For example, to include the {@code appcompat} project add - {@code compile "com.android.support:appcompat-v7:18.0.+"} to the dependencies section, as - shown in the following example: +
      5. Add the support library to the {@code dependencies} section. For + example, to add the v4 core-utils library, add the following lines:
         dependencies {
             ...
        -    compile "com.android.support:appcompat-v7:18.0.+"
        +    compile "com.android.support:support-core-utils:24.2.0"
         }
         
      +

      + Caution: Using dynamic dependencies (for example, + palette-v7:23.0.+) can cause unexpected version updates and + regression incompatibilities. We recommend that you explicitly specify a + library version (for example, palette-v7:24.2.0). +

      Using Support Library APIs

      @@ -189,12 +148,12 @@ dependencies {
         <uses-sdk
      -      android:minSdkVersion="7"
      -      android:targetSdkVersion="17" />
      +      android:minSdkVersion="14"
      +      android:targetSdkVersion="23" />
       

      The manifest setting tells Google Play that your application can be installed on devices with Android - 2.1 (API level 7) and higher.

      + 4.0 (API level 14) and higher.

      If you are using Gradle build files, the minSdkVersion setting in the build file overrides the manifest settings.

      @@ -206,7 +165,7 @@ android { ... defaultConfig { - minSdkVersion 8 + minSdkVersion 16 ... } ... @@ -214,28 +173,15 @@ android {

      In this case, the build file setting tells Google Play that the default build variant of your - application can be installed on devices with Android 2.2 (API level 8) and higher. For more + application can be installed on devices with Android 4.1 (API level 16) and higher. For more information about build variants, see Build System Overview.

      - Note: If you are including the v4 support and v7 appcompat libraries in your - application, you should specify a minimum SDK version of "7" (and not - "4"). The highest support library level you include in your application determines - the lowest API version in which it can operate. + Note: If you are including several support libraries, the + minimum SDK version must be the highest version required by any of + the specified libraries. For example, if your app includes both the v14 Preference Support library and the + v17 Leanback library, your minimum + SDK version must be 17 or higher.

      - - -

      Code Samples

      - -

      Each Support Library includes code samples to help you get started using the support -APIs. The code is included in the download from the SDK Manager and is placed inside the Android -SDK installation directory, as listed below:

      - -
        -
      • 4v Samples: {@code <sdk>/extras/android/support/samples/Support4Demos/}
      • -
      • 7v Samples: {@code <sdk>/extras/android/support/samples/Support7Demos/}
      • -
      • 13v Samples: {@code <sdk>/extras/android/support/samples/Support13Demos/}
      • -
      • App Navigation: {@code <sdk>/extras/android/support/samples/SupportAppNavigation/}
      • -
      - diff --git a/docs/html/topic/performance/_book.yaml b/docs/html/topic/performance/_book.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4021e85c14aaacab85da84c67b7555b87c1f8eb4 --- /dev/null +++ b/docs/html/topic/performance/_book.yaml @@ -0,0 +1,61 @@ +toc: +- title: Optimizing for Battery Life + path: /topic/performance/power/index.html + path_attributes: + - name: description + value: Learn to make your app more battery-friendly. + section: + - title: Network Use and Battery Consumption + path: /topic/performance/power/network/index.html + section: + - title: Collecting Network Traffic Data + path: /topic/performance/power/network/gather-data.html + - title: Analyzing Data Traffic + path: /topic/performance/power/network/analyze-data.html + - title: Optimizing User-Initiated Network Use + path: /topic/performance/power/network/action-user-traffic.html + - title: Optimizing App-Initiated Network Use + path: topic/performance/power/network/action-app-traffic.html + - title: Optimizing Server-Initiated Network Use + path: /topic/performance/power/network/action-server-traffic.html + - title: Optimizing General Network Use + path: /topic/performance/power/network/action-any-traffic.html + - title: Doze and App Standby + path: /training/monitoring-device-state/doze-standby.html + path_attributes: + - name: description + value: Help ensure the device isn't depleting the battery when not in use. + - title: Battery Historian + path: /topic/performance/power/battery-historian.html +- title: Rendering + path: /topic/performance/rendering/index.html + path_attributes: + - name: description + value: Speed up your app's rendering + section: + - title: Reducing Overdraw + path: /topic/performance/rendering/overdraw.html + - title: Performance and View Hierarchies + path: /topic/performance/rendering/optimizing-view-hierarchies.html + - title: Analyzing with Profile GPU Rendering + path: /topic/performance/rendering/profile-gpu.html +- title: Intelligent Job-Scheduling + path: /topic/performance/scheduling.html +- title: Background Optimization + path: /topic/performance/background-optimization.html +- title: Reducing APK Size + path: /topic/performance/reduce-apk-size.html +- title: Reducing Image Download Sizes + path: /topic/performance/network-xfer.html +- title: Launch-Time Performance + path: /topic/performance/launch-time.html +- title: Better Performance through Threading + path: /topic/performance/threads.html +- title: Manage Your App's Memory + path: /topic/performance/memory.html +- title: Overview of Memory Managemement + path: /topic/performance/memory-overview.html + path_attributes: + - name: description + value: How to keep your app's memory footprint small in order to improve performance on a variety of mobile devices. + diff --git a/docs/html/topic/performance/_project.yaml b/docs/html/topic/performance/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d4202a992b6b2a48d6bbdff81d16c5afe93873d3 --- /dev/null +++ b/docs/html/topic/performance/_project.yaml @@ -0,0 +1,6 @@ +name: "Performance" +home_url: /topic/performance/ +description: "Improve your app's performance by learning how to optimize power consumption, launch times, and other important areas of performance." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /develop/_project.yaml diff --git a/docs/html/preview/features/background-optimization.jd b/docs/html/topic/performance/background-optimization.jd similarity index 87% rename from docs/html/preview/features/background-optimization.jd rename to docs/html/topic/performance/background-optimization.jd index 3e4c041367a09365e03559cc63e28ce1fdbceb10..0a1a6f5336be57f9c172ec974cffef6643819065 100644 --- a/docs/html/preview/features/background-optimization.jd +++ b/docs/html/topic/performance/background-optimization.jd @@ -14,29 +14,31 @@ page.image=images/cards/card-nyc_2x.jpg
      1. Restrictions on CONNECTIVITY_ACTION -
      2. - -
      3. - Scheduling Network Jobs on Unmetered - Connections -
      4. - -
      5. - Monitoring Network Connectivity While the App - is Running +
      6. Restrictions on NEW_PICTURE and NEW_VIDEO -
      7. - -
      8. - New JobInfo methods -
      9. - -
      10. - New JobParameter Methods +
      11. @@ -54,12 +56,12 @@ page.image=images/cards/card-nyc_2x.jpg

        - To alleviate this issue, Android N applies the following + To alleviate this issue, Android 7.0 (API level 24) applies the following restrictions:

          -
        • Apps targeting the Preview do not receive {@link +
        • Apps targeting Android 7.0 (API level 24) do not receive {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} broadcasts if they register to receive them in their manifest. Apps that are running can still listen for {@code CONNECTIVITY_CHANGE} on their main thread by registering a @@ -70,16 +72,16 @@ page.image=images/cards/card-nyc_2x.jpg
        • Apps cannot send or receive {@link android.hardware.Camera#ACTION_NEW_PICTURE} or {@link android.hardware.Camera#ACTION_NEW_VIDEO} broadcasts. This optimization - affects all apps, not only those targeting the Preview. + affects all apps, not only those targeting Android 7.0 (API level 24).

        - If your app uses any of these intents, you should remove dependencies on - them as soon as possible so that you can target Android N devices properly. - The Android framework provides several solutions to mitigate the need for - these implicit broadcasts. For example, {@link android.app.job.JobScheduler} - and {@code GcmNetworkManager} provide robust mechanisms to schedule network operations when specified conditions, such as a connection to an unmetered @@ -101,7 +103,7 @@ page.image=images/cards/card-nyc_2x.jpg

        - Apps targeting the Android N do not receive {@link + Apps targeting Android 7.0 (API level 24) do not receive {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} broadcasts if they register to receive them in their manifest, and processes that depend on this broadcast will not start. This could pose a problem for apps that want @@ -198,11 +200,11 @@ public static void scheduleJob(Context context) {

        - In the Android N, apps are not able to send or receive {@link + In Android 7.0 (API level 24), apps are not able to send or receive {@link android.hardware.Camera#ACTION_NEW_PICTURE} or {@link android.hardware.Camera#ACTION_NEW_VIDEO} broadcasts. This restriction helps alleviate the performance and user experience impacts when several apps must - wake up in order to process a new image or video. Android N + wake up in order to process a new image or video. Android 7.0 (API level 24) extends {@link android.app.job.JobInfo} and {@link android.app.job.JobParameters} to provide an alternative solution.

        @@ -212,7 +214,7 @@ public static void scheduleJob(Context context) {

        - To trigger jobs on content URI changes, Android N extends + To trigger jobs on content URI changes, Android 7.0 (API level 24) extends the {@link android.app.job.JobInfo} API with the following methods:

        @@ -287,7 +289,7 @@ public static void scheduleJob(Context context) {

        - Android N also extends {@link android.app.job.JobParameters} to + Android 7.0 (API level 24) also extends {@link android.app.job.JobParameters} to allow your app to receive useful information about what content authorities and URIs triggered the job:

        @@ -361,13 +363,13 @@ public boolean onStartJob(JobParameters params) { conditions, can improve performance and user experience. Removing dependencies on background services and statically-registered implicit broadcast receivers can help your app run better on such devices. Although - Android N takes steps to reduce some of these issues, it is + Android 7.0 (API level 24) takes steps to reduce some of these issues, it is recommended that you optimize your app to run without the use of these background processes entirely.

        - Android N introduces some additional Android Debug Bridge (ADB) commands that you can use to test app behavior with those background processes disabled:

        @@ -379,7 +381,7 @@ public boolean onStartJob(JobParameters params) {
      12. -{@code $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore}
        +{@code $ adb shell cmd appops set  RUN_IN_BACKGROUND ignore}
         
      13. @@ -389,7 +391,7 @@ public boolean onStartJob(JobParameters params) {
      14. -{@code $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow}
        +{@code $ adb shell cmd appops set  RUN_IN_BACKGROUND allow}
         
      15. diff --git a/docs/html/topic/performance/images/app-rankings.png b/docs/html/topic/performance/images/app-rankings.png new file mode 100644 index 0000000000000000000000000000000000000000..9dd60e54735f8c7bafa4a358e4f06bcb84898760 Binary files /dev/null and b/docs/html/topic/performance/images/app-rankings.png differ diff --git a/docs/html/topic/performance/images/bars.png b/docs/html/topic/performance/images/bars.png new file mode 100644 index 0000000000000000000000000000000000000000..3afea465c975a766b39ecfe33e7dd3e25761e5ce Binary files /dev/null and b/docs/html/topic/performance/images/bars.png differ diff --git a/docs/html/topic/performance/images/beforeafterindexed.png b/docs/html/topic/performance/images/beforeafterindexed.png new file mode 100644 index 0000000000000000000000000000000000000000..dc7762ed42a4341a850f9fdfcd2a86d66846370b Binary files /dev/null and b/docs/html/topic/performance/images/beforeafterindexed.png differ diff --git a/docs/html/topic/performance/images/cold-launch.png b/docs/html/topic/performance/images/cold-launch.png new file mode 100644 index 0000000000000000000000000000000000000000..2935ece7866513ef1c7a472f7ff994b3e724ef90 Binary files /dev/null and b/docs/html/topic/performance/images/cold-launch.png differ diff --git a/docs/html/topic/performance/images/comparison.png b/docs/html/topic/performance/images/comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..18f204c31d1bde0d683ea8267c444db58749272c Binary files /dev/null and b/docs/html/topic/performance/images/comparison.png differ diff --git a/docs/html/topic/performance/images/decisions.png b/docs/html/topic/performance/images/decisions.png new file mode 100644 index 0000000000000000000000000000000000000000..d4f21f8f770b00ab0f775aa31d10930c9393187a Binary files /dev/null and b/docs/html/topic/performance/images/decisions.png differ diff --git a/docs/html/topic/performance/images/displayed-logcat.png b/docs/html/topic/performance/images/displayed-logcat.png new file mode 100644 index 0000000000000000000000000000000000000000..7dee884d5a0c7f99cebea1ea46ae0fc8146f1fc5 Binary files /dev/null and b/docs/html/topic/performance/images/displayed-logcat.png differ diff --git a/docs/html/topic/performance/images/dropdown.png b/docs/html/topic/performance/images/dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..59ec6110e5ef514641c46adf85b365eeb0e12623 Binary files /dev/null and b/docs/html/topic/performance/images/dropdown.png differ diff --git a/docs/html/topic/performance/images/generic-timeline.png b/docs/html/topic/performance/images/generic-timeline.png new file mode 100644 index 0000000000000000000000000000000000000000..04388b6f4abbf658ed9d7d07c50997c4ea70bf90 Binary files /dev/null and b/docs/html/topic/performance/images/generic-timeline.png differ diff --git a/docs/html/topic/performance/images/lint-display.png b/docs/html/topic/performance/images/lint-display.png new file mode 100644 index 0000000000000000000000000000000000000000..e3609381a4c45798df203b8b926cf15920105ebf Binary files /dev/null and b/docs/html/topic/performance/images/lint-display.png differ diff --git a/docs/html/topic/performance/images/lint-inspect-code.png b/docs/html/topic/performance/images/lint-inspect-code.png new file mode 100644 index 0000000000000000000000000000000000000000..41604a18252138ee68d387bb2bbafe011c2fd06c Binary files /dev/null and b/docs/html/topic/performance/images/lint-inspect-code.png differ diff --git a/docs/html/topic/performance/images/moarparrots.png b/docs/html/topic/performance/images/moarparrots.png new file mode 100644 index 0000000000000000000000000000000000000000..ee10ec158936e9c47d1ca1f5a389c137003f7a2d Binary files /dev/null and b/docs/html/topic/performance/images/moarparrots.png differ diff --git a/docs/html/topic/performance/images/palette.png b/docs/html/topic/performance/images/palette.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6be6b4246c81ca572e9493dc5df64f7b98af6d Binary files /dev/null and b/docs/html/topic/performance/images/palette.png differ diff --git a/docs/html/topic/performance/images/parrot.png b/docs/html/topic/performance/images/parrot.png new file mode 100644 index 0000000000000000000000000000000000000000..7a8b86a97b1e2e08bd487d7c4622b59611897a4a Binary files /dev/null and b/docs/html/topic/performance/images/parrot.png differ diff --git a/docs/html/topic/performance/images/pug-visualization.png b/docs/html/topic/performance/images/pug-visualization.png new file mode 100644 index 0000000000000000000000000000000000000000..8270d0e37d1d12c63c9284e8062a94edd3373c8f Binary files /dev/null and b/docs/html/topic/performance/images/pug-visualization.png differ diff --git a/docs/html/topic/performance/images/pugspecificdata.png b/docs/html/topic/performance/images/pugspecificdata.png new file mode 100644 index 0000000000000000000000000000000000000000..1c2be837ba2619c24b492adbbe5173bd64af3e99 Binary files /dev/null and b/docs/html/topic/performance/images/pugspecificdata.png differ diff --git a/docs/html/topic/performance/images/s-generic-closeup.png b/docs/html/topic/performance/images/s-generic-closeup.png new file mode 100644 index 0000000000000000000000000000000000000000..6685d51a32a18328c84f34c8df13d7623111adc3 Binary files /dev/null and b/docs/html/topic/performance/images/s-generic-closeup.png differ diff --git a/docs/html/topic/performance/images/s-profiler-legend.png b/docs/html/topic/performance/images/s-profiler-legend.png new file mode 100644 index 0000000000000000000000000000000000000000..968fd381156a363bce0ad6d763b23804f1a33f2f Binary files /dev/null and b/docs/html/topic/performance/images/s-profiler-legend.png differ diff --git a/docs/html/topic/performance/images/vq.gif b/docs/html/topic/performance/images/vq.gif new file mode 100644 index 0000000000000000000000000000000000000000..cbf6a35040596b5d86f8ce77113f6c7511a68c6e Binary files /dev/null and b/docs/html/topic/performance/images/vq.gif differ diff --git a/docs/html/topic/performance/index.jd b/docs/html/topic/performance/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..2b6b1972a03bacef18ca97cf0796ebfd948eaae7 --- /dev/null +++ b/docs/html/topic/performance/index.jd @@ -0,0 +1,39 @@ +page.title=Performance and Power +page.article=true +page.metaDescription=Improve your app's performance by learning how to optimize power consumption, launch times, and other important areas of performance. + +meta.tags="performance" +page.tags="performance" + +@jd:body + + + +

        Implementing a cool idea is a great start toward an app that delights users, +but it's just the beginning. The next step is maximizing your app's performance. +For example, users want apps that:

        + +
          +
        • Use power sparingly.
        • +
        • Start up quickly.
        • +
        • Respond quickly to user interaction.
        • +
        + +

        This section provides you with the know-how you need in order to make +your apps not only cool, but also performant. Read on to discover how to +develop apps that are power-thrifty, responsive, efficient, and well-behaved.

        + + + + +
        +

        More resources

        +
        +
        +
        diff --git a/docs/html/topic/performance/launch-time.jd b/docs/html/topic/performance/launch-time.jd new file mode 100644 index 0000000000000000000000000000000000000000..84d5fab12a6bcaa21be2c1863b0e9a475ad45137 --- /dev/null +++ b/docs/html/topic/performance/launch-time.jd @@ -0,0 +1,565 @@ +page.title=Launch-Time Performance +@jd:body + + + +

        +Users expect apps to be responsive and fast to load. An app with a slow startup +time doesn’t meet this expectation, and can be disappointing to users. This +sort of poor experience may cause a user to rate your app poorly on the Play +store, or even abandon your app altogether. +

        + +

        +This document provides information to help you optimize your app’s launch time. +It begins by explaining the internals of the launch process. Next, it discusses +how to profile startup performance. Last, it describes some common startup-time +issues, and gives some hints on how to address them. +

        + +

        Launch Internals

        + +

        +App launch can take place in one of three states, each affecting how +long it takes for your app to become visible to the user: cold start, +warm start, and lukewarm start. In a cold start, your app starts from scratch. +In the other states, the system needs to bring the app from the background to +the foreground. We recommend that you always optimize based on an assumption of +a cold start. Doing so can improve the performance of warm and lukewarm starts, +as well. +

        + +

        +To optimize your app for fast startup, it’s useful to understand what’s +happening at the system and app levels, and how they interact, in each of +these states. +

        + +

        Cold start

        + +

        +A cold start refers to an app’s starting from scratch: the system’s process +has not, until this start, created the app’s process. Cold starts happen in +cases such as your app’s being launched for the first time since the device +booted, or since the system killed the app. This type of start presents the +greatest challenge in terms of minimizing startup time, because the system +and app have more work to do than in the other launch states. +

        + +

        +At the beginning of a cold start, the system has three tasks. These tasks are: +

        + +
          +
        1. Loading and launching the app.
        2. +
        3. Displaying a blank starting window for the app immediately after launch. +
        4. +
        5. Creating the app + + process.
        6. +
        +
        +

        +As soon as the system creates the app process, the app process is responsible +for the next stages. These stages are: +

        + +
          +
        1. Creating the app object.
        2. +
        3. Launching the main thread.
        4. +
        5. Creating the main activity.
        6. +
        7. Inflating views.
        8. +
        9. Laying out the screen.
        10. +
        11. Performing the initial draw.
        12. +
        + +

        +Once the app process has completed the first draw, the system process swaps +out the currently displayed background window, replacing it with the main +activity. At this point, the user can start using the app. +

        + +

        +Figure 1 shows how the system and app processes hand off work between each +other. +

        +
        + + +

        + Figure 1. A visual representation of the important parts of + a cold application launch. +

        + +

        +Performance issues can arise during creation of the app and +creation of the activity. +

        + +

        Application creation

        + +

        +When your application launches, the blank starting window remains on the screen +until the system finishes drawing the app for the first time. At that point, +the system process swaps out the starting window for your app, allowing the +user to start interacting with the app. +

        + +

        +If you’ve overloaded {@link android.app.Application#onCreate() Application.oncreate()} +in your own app, the app starts by calling this +method on your app object. Afterwards, the app spawns the main thread, also +known as the UI thread, and tasks it with creating your main activity. +

        + +

        +From this point, system- and app-level processes proceed in accordance with +the +app lifecycle stages. +

        + +

        Activity creation

        + +

        +After the app process creates your activity, the activity performs the +following operations: +

        + +
          +
        1. Initializes values.
        2. +
        3. Calls constructors.
        4. +
        5. Calls the callback method, such as + {@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()}, + appropriate to the current lifecycle state of the activity.
        6. +
        + +

        +Typically, the +{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} +method has the greatest impact on load time, because it performs the work with +the highest overhead: loading and inflating views, and initializing the objects +needed for the activity to run. +

        + +

        Warm start

        + +

        +A warm start of your application is much simpler and lower-overhead than a +cold start. In a warm start, all the system does is bring your activity to +the foreground. If all of your application’s activities are still resident in +memory, then the app can avoid having to repeat object initialization, layout +inflation, and rendering. +

        + +

        +However, if some memory has been purged in response to memory trimming +events, such as +{@link android.content.ComponentCallbacks2#onTrimMemory(int) onTrimMemory()}, +then those objects will need to be recreated in +response to the warm start event. +

        + +

        +A warm start displays the same on-screen behavior as a cold start scenario: +The system process displays a blank screen until the app has finished rendering +the activity. +

        + +

        Lukewarm start

        + +

        +A lukewarm start encompasses some subset of the operations that +take place during a cold start; at the same time, it represents less overhead +than a warm start. There are many potential states that could be considered +lukewarm starts. For instance: +

        + +
          +
        • The user backs out of your app, but then re-launches it. The process may + have continued to run, but the app must recreate the activity from scratch + via a call to + {@link android.app.Activity#onCreate(android.os.Bundle) onCreate()}.
        • + +
        • The system evicts your app from memory, and then the user re-launches it. + The process and the Activity need to be restarted, but the task can + benefit somewhat from the saved instance state bundle passed into + {@link android.app.Activity#onCreate(android.os.Bundle) onCreate()}.
        • +
        + +

        Profiling Launch Performance

        + +

        +In order to properly diagnose start time performance, you can track metrics +that show how long it takes your application to start. +

        + +

        Time to initial display

        + +

        +From Android 4.4 (API level 19), logcat includes an output line containing +a value called {@code Displayed}. This value represents +the amount of time elapsed between launching the process and finishing drawing +the corresponding activity on the screen. The elapsed time encompasses the +following sequence of events: +

        + +
          +
        1. Launch the process.
        2. +
        3. Initialize the objects.
        4. +
        5. Create and initialize the activity.
        6. +
        7. Inflate the layout.
        8. +
        9. Draw your application for the first time.
        10. +
        + +

        +The reported log line looks similar to the following example: +

        + +
        +ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
        +
        + +

        +If you’re tracking logcat output from the command line, or in a terminal, +finding the elapsed time is straightforward. To find elapsed time in +Android Studio, you must disable filters in your logcat view. Disabling the +filters is necessary because the system server, not the app itself, serves +this log. +

        + +

        +Once you’ve made the appropriate settings, you can easily search for the +correct term to see the time. Figure 2 shows how to disable filters, and, +in the second line of output from the bottom, an example of logcat output of +the {@code Displayed} time. +

        +
        + + +

        + Figure 2. Disabling filters, and + finding the {@code Displayed} value in logcat. +

        + +

        +The {@code Displayed} metric in the logcat output does not necessarily capture +the amount of time until all resources are loaded and displayed: it leaves out +resources that are not referenced in the layout file or that the app creates +as part of object initialization. It excludes these resources because loading +them is an inline process, and does not block the app’s initial display. +

        + +

        Time to full display

        + +

        +You can use the {@link android.app.Activity#reportFullyDrawn()} method to +measure the elapsed time +between application launch and complete display of all resources and view +hierarchies. This can be valuable in cases where an app performs lazy loading. +In lazy loading, an app does not block the initial drawing of the window, but +instead asynchronously loads resources and updates the view hierarchy. +

        + +

        +If, due to lazy loading, an app’s initial display does not include all +resources, you might consider the completed loading and display of all +resources and views as a separate metric: For example, your UI might be +fully loaded, with some text drawn, but not yet display images that the +app must fetch from the network. +

        + +

        +To address this concern, you can manually call +{@link android.app.Activity#reportFullyDrawn()} +to let the system know that your activity is +finished with its lazy loading. When you use this method, the value +that logcat displays is the time elapsed +since the creation of the application object, and the moment +{@link android.app.Activity#reportFullyDrawn()} is called. +

        + +

        +If you learn that your display times are slower than you’d like, you can +go on to try to identify the bottlenecks in the startup process. +

        + +

        Identifying bottlenecks

        + +

        +Two good ways to look for bottlenecks are Android Studio’s Method Tracer tool +and inline tracing. To learn about Method Tracer, see that tool’s +documentation. +

        + +

        +If you do not have access to the Method Tracer tool, or cannot start the tool +at the correct time to gain log information, you can gain similar insight +through inline tracing inside of your apps’ and activities’ {@code onCreate()} +methods. To learn about inline tracing, see the reference documentation for +the {@link android.os.Trace} functions, and for the +Systrace tool. +

        + +

        Common Issues

        + +

        +This section discusses several issues that often affect apps’ startup +performance. These issues chiefly concern initializing app and activity +objects, as well as the loading of screens. +

        + +

        Heavy app initialization

        + +

        +Launch performance can suffer when your code overrides the {@code Application} +object, and executes heavy work or complex logic when initializing that object. +Your app may waste time during startup if your Application subclasses perform +initializations that don’t need to be done yet. Some initializations may be +completely unnecessary: for example, initializing state information for the +main activity, when the app has actually started up in response to an intent. +With an intent, the app uses only a subset of the previously initialized state +data. +

        + +

        +Other challenges during app initialization include garbage-collection events +that are impactful or numerous, or disk I/O happening concurrently with +initialization, further blocking the initialization process. Garbage collection +is especially a consideration with the Dalvik runtime; the Art runtime performs +garbage collection concurrently, minimizing that operation's impact. +

        + +

        Diagnosing the problem

        + +

        +You can use method tracing or inline tracing to try to diagnose the problem. +

        + +
        Method tracing
        + +

        +Running the Method Tracer tool reveals that the +{@link android.app.Instrumentation#callApplicationOnCreate(android.app.Application) callApplicationOnCreate()} +method eventually calls your {@code com.example.customApplication.onCreate} +method. If the tool shows that these +methods are taking a long time to finish executing, you should explore further +to see what work is occurring there. +

        + +
        Inline tracing
        + +

        +Use inline tracing to investigate likely culprits including: +

        + +
          +
        • Your app’s initial {@link android.app.Application#onCreate()} + function.
        • +
        • Any global singleton objects your app initializes.
        • +
        • Any disk I/O, deserialization, or tight loops that might be occurring + during the bottleneck. +
        + + +

        Solutions to the problem

        + +

        +Whether the problem lies with unnecessary initializations or disk I/O, +the solution calls for lazy-initializing objects: initializing only those +objects that are immediately needed. For example, rather than creating global +static objects, instead, move to a singleton pattern, where the app initalizes +objects only the first time it accesses them. +

        + +

        Heavy activity initialization

        + +

        +Activity creation often entails a lot of high-overhead work. Often, there are +opportunities to optimize this work to achieve performance improvements. Such +common issues include: +

        + +
          +
        • Inflating large or complex layouts.
        • +
        • Blocking screen drawing on disk, or network I/O.
        • +
        • Loading and decoding bitmaps.
        • +
        • Rasterizing {@link android.graphics.drawable.VectorDrawable VectorDrawable} objects.
        • +
        • Initialization of other subsystems of the activity.
        • +
        + +

        Diagnosing the problem

        + +

        +In this case, as well, both method tracing and inline tracing can prove useful. +

        + +
        Method tracing
        + +

        +When running the Method Tracer tool, the particular areas to +focus on your your app’s {@link android.app.Application} subclass constructors and +{@code com.example.customApplication.onCreate()} methods. +

        + +

        +If the tool shows that these methods are taking a long time to finish +executing, you should explore further to see what work is occurring there. +

        + +
        Inline tracing
        + +

        +Use inline tracing to investigate likely culprits including: +

        + +
          +
        • Your app’s initial {@link android.app.Application#onCreate()} + function.
        • +
        • Any global singleton objects it initializes.
        • +
        • Any disk I/O, deserialization, or tight loops that might be occurring + during the bottleneck.
        • +
        + +

        Solutions to the problem

        + +

        +There are many potential bottlenecks, but two common problems and remedies +are as follows: +

        + +
          +
        • The larger your view hierarchy, the more time the app takes to inflate + it. Two steps you can take to address this issue are: + +
            +
          • Flattening your view hierarchy by reducing redundant or nested + layouts.
          • + +
          • Not inflating parts of the UI that do not need to be visible during + launch. Instead, use use a {@link android.view.ViewStub} object as a + placeholder for sub-hierarchies that the app can inflate at a more + appropriate time.
          • +
          +
        • + +
        • Having all of your resource initialization on the main + thread can also slow down startup. You can address this issue as follows: + +
            +
          • Move all resource initialization so that the app can perform it + lazily on a different thread.
          • +
          • Allow the app to load and display your views, and then later + update visual properties that are dependent on bitmaps and other + resources.
          • +
          +
        • + +

          Themed launch screens

          + + +

          +You may wish to theme your app’s loading experience, so that the app’s +launch screen is thematically consistent with the rest of the app, instead of +with the system theming. Doing so can hide a slow activity launch. +

          + +

          +A common way to implement a themed launch screen is to use the the +{@link android.R.attr#windowDisablePreview} theme attribute to turn off +the initial blank screen +that the system process draws when launching the app. However, this approach +can result in a longer startup time than apps that don’t suppress the preview +window. Also, it forces the user to wait with no feedback while the activity +launches, making them wonder if the app is functioning properly. +

          + +

          Diagnosing the problem

          + +

          +You can often diagnose this problem by observing a slow response when a user +launches your app. In such a case, the screen may seem to be frozen, or to +have stopped responding to input. +

          + +

          Solutions to the problem

          + +

          +We recommend that, rather than disabling the preview window, you +follow the common + +Material Design patterns. You can use the activity's +{@code windowBackground} theme attribute to provide a simple custom drawable +for the starting activity. +

          + +

          +For example, you might create a new drawable file and reference it from the +layout XML and app manifest file as follows: +

          + +

          Layout XML file:

          + +
          +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
          +  <!-- The background color, preferably the same as your normal theme -->
          +  <item android:drawable="@android:color/white"/>
          +  <!-- Your product logo - 144dp color version of your app icon -->
          +  <item>
          +    <bitmap
          +      android:src="@drawable/product_logo_144dp"
          +      android:gravity="center"/>
          +  </item>
          +</layer-list>
          +
          + +

          Manifest file:

          + +
          +<activity ...
          +android:theme="@style/AppTheme.Launcher" />
          +
          + +

          +The easiest way to transition back to your normal theme is to call +{@link android.view.ContextThemeWrapper#setTheme(int) setTheme(R.style.AppTheme)} +before calling {@code super.onCreate()} and {@code setContentView()}: +

          + +
          +public class MyMainActivity extends AppCompatActivity {
          +  @Override
          +  protected void onCreate(Bundle savedInstanceState) {
          +    // Make sure this is before calling super.onCreate
          +    setTheme(R.style.Theme_MyApp);
          +    super.onCreate(savedInstanceState);
          +    // ...
          +  }
          +}
          +
          diff --git a/docs/html/topic/performance/memory-overview.jd b/docs/html/topic/performance/memory-overview.jd new file mode 100644 index 0000000000000000000000000000000000000000..58067d2be4b834e1c40dbfed0ad0496b00a9ed28 --- /dev/null +++ b/docs/html/topic/performance/memory-overview.jd @@ -0,0 +1,288 @@ +page.title=Overview of Android Memory Management +page.tags=ram,memory,paging,mmap + +@jd:body + + + +

          + The Android Runtime (ART) and Dalvik virtual machine use + paging + and memory-mapping + (mmapping) to manage memory. This means that any memory an app + modifies—whether by allocating + new objects or touching mmapped pages—remains resident in RAM and + cannot be paged out. The only way to release memory from an app is to release + object references that the app holds, making the memory available to the + garbage collector. + That is with one exception: any files + mmapped in without modification, such as code, + can be paged out of RAM if the system wants to use that memory elsewhere. +

          + +

          + This page explains how Android manages app processes and memory + allocation. For more information about how to manage memory more efficiently + in your app, see + Manage Your App's Memory. +

          + + + +

          Garbage collection

          + +

          + A managed memory environment, like the ART or Dalvik virtual machine, + keeps track of each memory allocation. Once it determines + that a piece of memory is no longer being used by the program, + it frees it back to the heap, without any intervention from the programmer. + The mechanism for reclaiming unused memory + within a managed memory environment + is known as garbage collection. Garbage collection has two goals: + find data objects in a program that cannot be accessed in the future; and + reclaim the resources used by those objects. +

          + +

          + Android’s memory heap is a generational one, meaning that there are + different buckets of allocations that it tracks, + based on the expected life and size of an object being allocated. + For example, recently allocated objects belong in the Young generation. + When an object stays active long enough, it can be promoted + to an older generation, followed by a permanent generation. +

          + +

          + Each heap generation has its own dedicated upper limit on the amount + of memory that objects there can occupy. Any time a generation starts + to fill up, the system executes a garbage collection + event in an attempt to free up memory. The duration of the garbage collection + depends on which generation of objects it's collecting + and how many active objects are in each generation. +

          + +

          + Even though garbage collection can be quite fast, it can still + affect your app's performance. You don’t generally control + when a garbage collection event occurs from within your code. + The system has a running set of criteria for determining when to perform + garbage collection. When the criteria are satisfied, + the system stops executing the process and begins garbage collection. If + garbage collection occurs in the middle of an intensive processing loop + like an animation or during music playback, it can increase processing time. + This increase can potentially push code execution in your app past the + recommended 16ms threshold for efficient and smooth frame rendering. +

          + +

          + Additionally, your code flow may perform kinds of work that + force garbage collection events to occur + more often or make them last longer-than-normal. + For example, if you allocate multiple objects in the + innermost part of a for-loop during each frame of an alpha + blending animation, you might pollute your memory heap with a + lot of objects. + In that circumstance, the garbage collector executes multiple garbage + collection events and can degrade the performance of your app. +

          + +

          + For more general information about garbage collection, see + Garbage collection. +

          + + + +

          Sharing Memory

          + +

          + In order to fit everything it needs in RAM, + Android tries to share RAM pages across processes. It + can do so in the following ways: +

          + +
            +
          • + Each app process is forked from an existing process called Zygote. + The Zygote process starts when the system boots and loads common + framework code and resources + (such as activity themes). To start a new app process, + the system forks the Zygote process then + loads and runs the app's code in the new process. + This approach allows most of the RAM pages allocated for + framework code and resources to be shared across all app processes. +
          • + +
          • + Most static data is mmapped into a process. + This technique allows data to be shared + between processes, and also allows it to be paged + out when needed. Example static data include: + Dalvik code (by placing it in a pre-linked .odex + file for direct mmapping), app resources + (by designing the resource table to be a structure + that can be mmapped and by aligning the zip + entries of the APK), and traditional project + elements like native code in .so files. +
          • + +
          • + In many places, Android shares the same dynamic + RAM across processes using explicitly allocated + shared memory regions (either with ashmem or gralloc). + For example, window surfaces use shared + memory between the app and screen compositor, and + cursor buffers use shared memory between the + content provider and client. +
          • +
          + +

          + Due to the extensive use of shared memory, determining + how much memory your app is using requires + care. Techniques to properly determine your app's + memory use are discussed in + Investigating Your RAM Usage. +

          + + + +

          Allocating and Reclaiming App Memory

          + +

          + The Dalvik heap is constrained to a + single virtual memory range for each app process. This defines + the logical heap size, which can grow as it needs to + but only up to a limit that the system defines + for each app. +

          + +

          + The logical size of the heap is not the same as + the amount of physical memory used by the heap. + When inspecting your app's heap, Android computes + a value called the Proportional Set Size (PSS), + which accounts for both dirty and clean pages + that are shared with other processes—but only in an + amount that's proportional to how many apps share + that RAM. This (PSS) total is what the system + considers to be your physical memory footprint. + For more information about PSS, see the + Investigating Your RAM Usage + guide. +

          + +

          + The Dalvik heap does not compact the logical + size of the heap, meaning that Android does not + defragment the heap to close up space. Android + can only shrink the logical heap size when there + is unused space at the end of the heap. However, + the system can still reduce physical memory used by the heap. + After garbage collection, Dalvik + walks the heap and finds unused pages, then returns + those pages to the kernel using madvise. So, paired + allocations and deallocations of large + chunks should result in reclaiming all (or nearly all) + the physical memory used. However, + reclaiming memory from small allocations can be much + less efficient because the page used + for a small allocation may still be shared with + something else that has not yet been freed. + +

          + + + +

          Restricting App Memory

          + +

          + To maintain a functional multi-tasking environment, + Android sets a hard limit on the heap size + for each app. The exact heap size limit varies + between devices based on how much RAM the device + has available overall. If your app has reached the + heap capacity and tries to allocate more + memory, it can receive an {@link java.lang.OutOfMemoryError}. +

          + +

          + In some cases, you might want to query the + system to determine exactly how much heap space you + have available on the current device—for example, to + determine how much data is safe to keep in a + cache. You can query the system for this figure by calling + {@link android.app.ActivityManager#getMemoryClass() }. + This method returns an integer indicating the number of + megabytes available for your app's heap. +

          + + + +

          Switching apps

          + +

          + When users switch between apps, + Android keeps apps that + are not foreground—that is, not visible to the user or running a + foreground service like music playback— + in a least-recently used (LRU) cache. + For example, when a user first launches an app, + a process is created for it; but when the user + leaves the app, that process does not quit. + The system keeps the process cached. If + the user later returns to the app, the system reuses the process, thereby + making the app switching faster. +

          + +

          + If your app has a cached process and it retains memory + that it currently does not need, + then your app—even while the user is not using it— + affects the system's + overall performance. As the system runs low on memory, + it kills processes in the LRU cache + beginning with the process least recently used. The system also + accounts for processes that hold onto the most memory + and can terminate them to free up RAM. +

          + +

          + Note: When the system begins killing processes in the + LRU cache, it primarily works bottom-up. The system also considers which + processes consume more memory and thus provide the system + more memory gain if killed. + The less memory you consume while in the LRU list overall, + the better your chances are + to remain in the list and be able to quickly resume. +

          + +

          + For more information about how processes are cached while + not running in the foreground and how + Android decides which ones + can be killed, see the + Processes and Threads + guide. +

          diff --git a/docs/html/topic/performance/memory.jd b/docs/html/topic/performance/memory.jd new file mode 100644 index 0000000000000000000000000000000000000000..ef1c4ae0aeeac95fded7165f4d4990e24db0475c --- /dev/null +++ b/docs/html/topic/performance/memory.jd @@ -0,0 +1,593 @@ +page.title=Manage Your App's Memory +page.tags=ram,low memory,OutOfMemoryError,onTrimMemory + +@jd:body + + + + + +

          + Random-access memory (RAM) is a valuable + resource in any software development environment, but + it's even more valuable on a mobile operating system + where physical memory is often constrained. + Although both the Android Runtime (ART) and Dalvik virtual machine perform + routine garbage collection, this does not mean you can ignore + when and where your app allocates and releases memory. + You still need to avoid + introducing memory leaks, usually caused by holding onto + object references in static member variables, and + release any {@link java.lang.ref.Reference} objects at the appropriate + time as defined by + lifecycle callbacks. +

          + +

          + This page explains how you can + proactively reduce memory usage within your app. + For more information about general + practices to clean up your resources when programming in Java, + refer to other books or online + documentation about managing resource references. + If you’re looking for information about how to + analyze memory in a running app, read + Tools for analyzing RAM usage. + For more detailed information about how the Android Runtime and Dalvik + virtual machine manage memory, see the + Overview of Android Memory Management. +

          + + + +

          Monitor Available Memory and Memory Usage

          + +

          + The Android framework, Android Studio, and Android SDK + can help you analyze and adjust your app's memory usage. + The Android framework + exposes several APIs that allow your app to reduce its memory usage + dynamically during runtime. Android Studio and the Android SDK + contain several tools that allow you to investigate how your + app uses memory. +

          + + + +

          Tools for analyzing RAM usage

          + +

          + Before you can fix the memory usage problems in your app, you first need + to find them. Android Studio and the Android SDK include several tools + for analyzing memory usage in your app: +

          + +
            +
          1. + The Device Monitor has a Dalvik Debug Monitor Server (DDMS) tool that allows + you to inspect memory allocation within your app process. + You can use this information to understand how your + app uses memory overall. For example, you can force a garbage collection + event and then view the types of objects that remain in memory. You can + use this information to identify operations or actions within your app + that allocate or leave excessive amounts of objects in memory. + +

            For more information about how to use the DDMS tool, see + Using DDMS. +

            +
          2. + +
          3. + The Memory Monitor in Android Studio shows you how your app allocates + memory over the course of a single session. + The tool shows a graph of available + and allocated Java memory over time, including garbage collection events. + You can also initiate garbage collection events and take a snapshot of + the Java heap while your app runs. The output from the Memory Monitor tool + can help you identify points when your app experiences excessive garbage + collection events, leading to app slowness. +

            + For more information about how to use Memory Monitor tool, see + Viewing Heap Updates. +

            +
          4. + +
          5. + Garbage collection events also show up in the Traceview viewer. Traceview + allows you to view trace log files as both a timeline and as a profile + of what happened within a method. You can use this tool to determine + what code was executing when a garbage collection event occurred. +

            + For more information about how to use the Traceview viewer, see + Profiling with Traceview and dmtracedump. +

            +
          6. + +
          7. + The Allocation Tracker tool in Android Studio gives you a detailed look + at how your app allocates memory. + The Allocation Tracker records an app's memory allocations and lists + all allocated objects within the profiling snapshot. You can use this + tool to track down parts of your code that allocate too many objects. + +

            + For more information about how to use the Allocation Tracker tool, see + Allocation Tracker Walkthrough. +

            +
          8. + +
          + + + +

          Release memory in response to events

          + +

          + An Android device can run with varying amounts of free memory + depending on the physical amount of RAM on the device and how the user + operates it. The system broadcasts signals to indicate when it is under + memory pressure, and apps should listen for these signals and adjust + their memory usage as appropriate. +

          + +

          + You can use the {@link android.content.ComponentCallbacks2} API + to listen for these signals and then adjust your memory + usage in response to app lifecycle + or device events. The + {@link android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()} + method allows your app to listen for memory related events when the app runs + in the foreground (is visible) and when it runs in the background. +

          + +

          + To listen for these events, implement the {@link + android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()} + callback in your {@link android.app.Activity} + classes, as shown in the following code snippet. +

          + +
          +import android.content.ComponentCallbacks2;
          +// Other import statements ...
          +
          +public class MainActivity extends AppCompatActivity
          +    implements ComponentCallbacks2 {
          +
          +    // Other activity code ...
          +
          +    /**
          +     * Release memory when the UI becomes hidden or when system resources become low.
          +     * @param level the memory-related event that was raised.
          +     */
          +    public void onTrimMemory(int level) {
          +
          +        // Determine which lifecycle or system event was raised.
          +        switch (level) {
          +
          +            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
          +
          +                /*
          +                   Release any UI objects that currently hold memory.
          +
          +                   The user interface has moved to the background.
          +                */
          +
          +                break;
          +
          +            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
          +            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
          +            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
          +
          +                /*
          +                   Release any memory that your app doesn't need to run.
          +
          +                   The device is running low on memory while the app is running.
          +                   The event raised indicates the severity of the memory-related event.
          +                   If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
          +                   begin killing background processes.
          +                */
          +
          +                break;
          +
          +            case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
          +            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
          +            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
          +
          +                /*
          +                   Release as much memory as the process can.
          +
          +                   The app is on the LRU list and the system is running low on memory.
          +                   The event raised indicates where the app sits within the LRU list.
          +                   If the event is TRIM_MEMORY_COMPLETE, the process will be one of
          +                   the first to be terminated.
          +                */
          +
          +                break;
          +
          +            default:
          +                /*
          +                  Release any non-critical data structures.
          +
          +                  The app received an unrecognized memory level value
          +                  from the system. Treat this as a generic low-memory message.
          +                */
          +                break;
          +        }
          +    }
          +}
          +
          + +

          + The + {@link android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()} + callback was added in Android 4.0 (API level 14). For earlier versions, + you can use the + {@link android.content.ComponentCallbacks#onLowMemory()} + callback as a fallback for older versions, which is roughly equivalent to the + {@link android.content.ComponentCallbacks2#TRIM_MEMORY_COMPLETE} event. +

          + + + +

          Check how much memory you should use

          + +

          + To allow multiple running processes, Android sets a hard limit + on the heap size alloted for each app. The exact heap size limit varies + between devices based on how much RAM the device + has available overall. If your app has reached the heap capacity and + tries to allocate more + memory, the system throws an {@link java.lang.OutOfMemoryError}. +

          + +

          + To avoid running out of memory, you can to query the system to determine + how much heap space you have available on the current device. + You can query the system for this figure by calling + {@link android.app.ActivityManager#getMemoryInfo(android.app.ActivityManager.MemoryInfo) getMemoryInfo()}. + This returns an + {@link android.app.ActivityManager.MemoryInfo } object that provides + information about the device's + current memory status, including available memory, total memory, and + the memory threshold—the memory level below which the system begins + to kill processes. The + {@link android.app.ActivityManager.MemoryInfo } class also exposes a simple + boolean field, + {@link android.app.ActivityManager.MemoryInfo#lowMemory } + that tells you whether the device is running low on memory. +

          + +

          + The following code snippet shows an example of how you can use the + {@link android.app.ActivityManager#getMemoryInfo(android.app.ActivityManager.MemoryInfo) getMemoryInfo()}. + method in your application. +

          + +
          +public void doSomethingMemoryIntensive() {
          +
          +    // Before doing something that requires a lot of memory,
          +    // check to see whether the device is in a low memory state.
          +    ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();
          +
          +    if (!memoryInfo.lowMemory) {
          +        // Do memory intensive work ...
          +    }
          +}
          +
          +// Get a MemoryInfo object for the device's current memory status.
          +private ActivityManager.MemoryInfo getAvailableMemory() {
          +    ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
          +    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
          +    activityManager.getMemoryInfo(memoryInfo);
          +    return memoryInfo;
          +}
          +
          + + + +

          Use More Memory-Efficient Code Constructs

          + +

          + Some Android features, Java classes, and code constructs tend to + use more memory than others. You can minimize how + much memory your app uses by choosing more efficient alternatives in + your code. +

          + + + +

          Use services sparingly

          + +

          + Leaving a service running when it’s not needed is + one of the worst memory-management + mistakes an Android app can make. If your app needs a + service + to perform work in the background, do not keep it running unless + it needs to run a job. Remember to stop your service when it has completed + its task. Otherwise, you can inadvertently cause a memory leak. +

          + +

          + When you start a service, the system prefers to always keep the process + for that service running. This behavior + makes services processes very expensive + because the RAM used by a service remains unavailable to other processes. + This reduces the number of cached processes that the system can keep in + the LRU cache, making app switching less efficient. It can even lead to + thrashing in the system when memory is tight and the system can’t + maintain enough processes to host all the services currently running. +

          + +

          + You should generally avoid use of persistent services because of + the on-going demands they place on available memory. Instead, we + recommend that you use an alternative implementation + such as {@link android.app.job.JobScheduler}. For more information about + how to use {@link android.app.job.JobScheduler} to schedule background + processes, see + Background Optimizations. +

          + If you must use a service, the + best way to limit the lifespan of your service is to use an {@link + android.app.IntentService}, which finishes + itself as soon as it's done handling the intent that started it. + For more information, read + Running in a Background Service. +

          + + + +

          Use optimized data containers

          + +

          + Some of the classes provided by the programming language are not optimized for + use on mobile devices. For example, the generic + {@link java.util.HashMap} implementation can be quite memory + inefficient because it needs a separate entry object for every mapping. +

          + +

          + The Android framework includes several optimized data containers, including + {@link android.util.SparseArray}, {@link android.util.SparseBooleanArray}, + and {@link android.support.v4.util.LongSparseArray}. + For example, the {@link android.util.SparseArray} classes are more + efficient because they avoid the system's need to + autobox + the key and sometimes value (which creates yet another object or + two per entry). +

          + +

          + If necessary, you can always switch to raw arrays for a really lean data + structure. +

          + + + +

          Be careful with code abstractions

          + +

          + Developers often use abstractions simply as a good programming practice, + because abstractions can improve code flexibility and maintenance. + However, abstractions come at a significant cost: + generally they require a fair amount more code that + needs to be executed, requiring more time and + more RAM for that code to be mapped into memory. + So if your abstractions aren't supplying a + significant benefit, you should avoid them. +

          + +

          + For example, enums often require more than twice as much memory as static + constants. You should strictly avoid using enums on Android. +

          + + + +

          Use nano protobufs for serialized data

          + +

          + Protocol buffers + are a language-neutral, platform-neutral, extensible mechanism + designed by Google for serializing structured data—similar to XML, but + smaller, faster, and simpler. If you decide to use + protobufs for your data, you should always use nano protobufs in your + client-side code. Regular protobufs generate extremely verbose code, which + can cause many kinds of problems in your app such as + increased RAM use, significant APK size increase, and slower execution. +

          + +

          + For more information, see the "Nano version" section in the + protobuf readme. +

          + + + +

          Avoid memory churn

          + +

          + As mentioned previously, garbage collections events don't normally affect + your app's performance. However, many garbage collection events that occur + over a short period of time can quickly eat up your frame time. The more time + that the system spends on garbage collection, the less time it has to do + other stuff like rendering or streaming audio. +

          + +

          + Often, memory churn can cause a large number of + garbage collection events to occur. In practice, memory churn describes the + number of allocated temporary objects that occur in a given amount of time. +

          + +

          + For example, you might allocate multiple temporary objects within a + for loop. Or you might create new + {@link android.graphics.Paint} or {@link android.graphics.Bitmap} + objects inside the + {@link android.view.View#onDraw(android.graphics.Canvas) onDraw()} + function of a view. + In both cases, the app creates a lot of objects quickly at high volume. + These can quickly consume all the available memory in the young generation, + forcing a garbage collection event to occur. +

          + +

          + Of course, you need to find the places in your code where + the memory churn is high before you can fix them. Use the tools discussed in + Analyze your RAM usage +

          + +

          + Once you identify the problem areas in your code, try to reduce the number of + allocations within performance critical areas. Consider moving things out of + inner loops or perhaps moving them into a + Factory + based allocation structure. +

          + + + +

          Remove Memory-Intensive Resources and Libraries

          + +

          + Some resources and libraries within your code can gobble up memory without + you knowing it. Overall size of your APK, including third-party libraries + or embedded resources, can affect how much memory your app consumes. You can + improve your app's memory consumption by removing any redundant, unnecessary, + or bloated components, resources, or libraries from your code. +

          + + + +

          Reduce overall APK size

          + +

          + You can significantly reduce your app's memory usage by reducing the overall + size of your app. Bitmap size, resources, animation frames, and third-party + libraries can all contribute to the size of your APK. + Android Studio and the Android SDK provide multiple tools + to help you reduce the size of your resources and external dependencies. +

          + +

          + For more information about how to reduce your overall APK size, see + Reduce APK Size. +

          + + + +

          Use caution with dependency injection frameworks

          + +

          + Dependency injection framework such as + Guice + or + RoboGuice + can simplify the code you write and provide an adaptive environment + that's useful for testing and other configuration changes. However, dependency + frameworks aren't always optimized for mobile devices. +

          + +

          + For example, these frameworks tend to initialize processes by + scanning your code for annotations. This which can require significant + amounts of your code to be mapped into RAM unnecessarily. The system + allocates these mapped pages into clean memory so Android can drop them; yet + that can't happen until the pages have remained in memory for a long period + of time. +

          + +

          + If you need to use a dependency injection framework in your app, consider + using + Dagger + instead. For example, Dagger does not use reflection to scan your app's code. + Dagger's strict implementation means that it can be used in Android apps + without needlessly increasing memory usage. +

          + + + +

          Be careful about using external libraries

          + +

          + External library code is often not written for mobile environments and + can be inefficient when used + for work on a mobile client. When you decide to use an + external library, you may need to optimize that library for mobile devices. + Plan for that work up-front and analyze the library in terms of code size and + RAM footprint before deciding to use it at all. +

          + +

          + Even some mobile-optimized libraries can cause problems due to differing + implementations. For example, one library may use nano protobufs + while another uses micro protobufs, resulting in two different protobuf + implementations in your app. This can happen with different + implementations of logging, analytics, image loading frameworks, + caching, and many other things you don't expect. +

          + +

          + Although ProGuard can + help to remove APIs and resources with the right flags, it can't remove a + library's large internal dependencies. The features that you want in these + libraries may require lower-level dependencies. This becomes especially + problematic when you use an {@link android.app.Activity } subclass from a + library (which will tend to have wide swaths of dependencies), + when libraries use reflection (which is common and means you need to spend a + lot of time manually tweaking ProGuard to get it to work), and so on. +

          + +

          + Also avoid using a shared library for just one or two features out of dozens. + You don't want to pull in a large amount of code and overhead that + you don't even use. When you consider whether to use a library, look for + an implementation that strongly matches what you need. Otherwise, you might + decide to create your own implementation. +

          + diff --git a/docs/html/topic/performance/network-xfer.jd b/docs/html/topic/performance/network-xfer.jd new file mode 100644 index 0000000000000000000000000000000000000000..7fe5594ca89968ccf77f66e0004fae699cb7855f --- /dev/null +++ b/docs/html/topic/performance/network-xfer.jd @@ -0,0 +1,374 @@ +page.title=Reducing Image Download Sizes +page.metaDescription=Improve network performance by optimizing image size. + +meta.tags="performance" +page.tags="performance" + +@jd:body + + + +

          +Most download traffic consists of images. As a result, the smaller you can make +your downloadable images, the better a network experience your app can provide +for users. This page provides guidance on making image files smaller and more +network-friendly. +

          + +

          Understanding Image Formats

          + +

          Android apps typically use images that are in one or more of the following file +formats: PNG, JPG, and WebP. For each of these formats, there are steps you can +take to reduce image sizes. +

          + +

          PNG

          + +

          +A key to making your PNG files smaller is reducing the number of unique +colors used in each row of pixels that comprises the image. By using fewer +colors, you improve the compression potential at all of the other stages of +the pipeline. +

          + +

          +Reducing the number of unique colors makes a significant difference because PNG +compression effectiveness is partly a function of the degree to which +horizontally adjacent pixel colors vary. Thus, reducing the number of unique +colors in each row of your PNG images can help in reducing their file sizes. +

          + +

          +When deciding whether to pursue this strategy, you should keep in mind that +reducing the number of unique colors effectively amounts to applying a lossy +encoding stage to the image. However, an encoding tool may not be a good +judge of how bad a seemingly small error looks to the human eye. Therefore, +you should perform this work manually in order to help ensure +the right balance between efficient compression and acceptable image quality. +

          + +

          +There are two particularly useful approaches you can take: striving for indexed +formats, and applying vector quantization. +

          + + +

          Strive for indexed formats

          + +

          +Any attempt at color reduction should start with trying to optimize your colors +so that you can use the INDEXED format when exporting the image as a PNG. The +INDEXED color mode works by choosing the best 256 colors to use, and replacing +all pixel values with indices into that color palette. The result is a +reduction from 16 million (potential) colors to only 256 colors: from 3 (without +transparency) or 4 (with transparency) bytes per pixel to 1 byte per pixel. +This change is a significant first-step file size reduction. +

          + +

          +Figure 1 shows shows an image and its indexed variant. +

          + + +

          +Figure 1. An image before and after conversion to the INDEXED format. +

          + + +

          +Figure 2 shows the color palette for the image in Figure 1: +

          + + +

          +Figure 2. The color palette for the image in Figure 1. +

          + +

          +Representing your image as a paletted image goes a long way toward +significantly improving the file size, so it's worth investigating if the +majority of your images can be converted. +

          + +

          +Of course, not every image can be accurately represented with only 256 colors. +Some images, for example, might need 257, 310, 512, or 912 colors to +look correct. In such cases, vector quantization can also be helpful. +

          + +

          Vector quantization

          + +

          +The process of creating an indexed image may be better described as vector +quantization (VQ). VQ serves as a rounding process for multidimensional +numbers. In this process, all the colors in your image get grouped based upon +their similarity. For a given group, all colors in that group are replaced by a +single center point value, which minimizes error for colors in that +cell (or "site" if you're using the Voronoi terminology). In Figure 3, +the green dots represent input colors, and the red dots are the center points +that replace the input colors. Each cell is bounded by blue lines. +

          + + +

          +Figure 3. Applying vector quantization to the colors in an image. +

          + +

          +The result of applying VQ to an image reduces the number of unique colors, +replacing each group of colors with a single color that's "pretty close" +in visual quality. +

          + +

          +This technique also allows you to define the maximum number of unique colors in +your image. For example, Figure 4 shows the a parrot head in 16.7 million colors +(24 bits per pixel, or bpp) alongside a version that only allows only +16 (3 bpp) unique colors to be used. +

          + + +

          +Figure 4. Image before and after application of vector quantification. +

          + +

          +Immediately, you can see that there's a loss of quality; most of the gradient +colors have been replaced, imparting a banding effect to the image. This image +needs more than 16 unique colors. +

          + +

          +Setting up a VQ step in your pipeline can help you get a better sense of the +true number of unique colors that your image uses, and can help you reduce them +significantly. There are a number of readily available tools that you can use +to help you implement this technique. +

          + +

          JPG

          + +

          +If you are using JPG images, there are several small changes you can make that +potentially provide significant file-size savings. These include: +

          + +
            +
          • +Producing a smaller file size through different encoding methods (without +impacting quality). +
          • + +
          • +Adjusting quality slightly in order to yield better compression. +
          • +
          + +

          Pursuing these strategies can often net you file-size reductions of up to +25%. +

          + +

          +When choosing tools, remember that photo exporting tools can +insert unnecessary metadata, such as GPS information, into your images. At +a minimum, try to leverage existing tools to help strip out this information +from your files. +

          + +

          WebP

          + +

          +WebP is a newer image format supported from Android 4.2.1 (API level 17). This +format provides superior lossless and lossy compression for images on the web. +Using WebP, developers can create smaller, richer images. WebP lossless image +files are, on average, + +26% smaller than PNGs. These image files also support +transparency (also known as alpha channel) at a cost of just + +22% more bytes. +

          + +

          +WebP lossy images are + +25-34% smaller than comparable JPG images at equivalent +SSIM +quality indices. For cases when lossy RGB compression is acceptable, lossy +WebP also supports transparency, typically producing file sizes 3 times smaller +than PNG. +

          + +

          +For more information about WebP, visit the +WebP site. +

          + +

          Selecting a Format

          + +

          +Different image formats are suitable for different types of images. JPG and PNG +have very different compression processes, and they produce quite different +results. +

          + +

          +The decision between PNG and JPG often comes down to the complexity of the +image itself. Figure 5 shows two images that come out quite differently +depending on which compression scheme the developer applies. The image on the +left has many small details, and thus compresses more efficiently with JPG. The +image on the right, with runs of the same color, compresses more efficiently +with PNG. +

          + + +

          +Figure 5. Suitable cases for JPG vs. PNG +

          + + +

          +WebP as a format can support both lossy and lossless modes, making it an ideal +replacement for both PNG and JPG. The only thing to keep in mind is that it +only has native support on devices running Android 4.2.1 (API level 17) and +higher. Fortunately, the large + +majority of devices satisfy that requirement. +

          + +

          +Figure 6 provides a simple visualization to help you decide which compression +scheme to use. +

          + + +

          +Figure 6. Deciding on a compression scheme +

          + +

          Determining Optimal Quality Values

          + +

          +There are several techniques you can use to achieve the right balance between +compression and image quality. One technique uses scalar values and therefore +only works for JPG and WebP. The other technique takes advantage of the +Butteraugli library, and is usable for all image formats. +

          + +

          Scalar values (JPG and WebP only)

          + +

          +The power of JPG and WebP comes from the fact that you can use a scalar value +to balance quality against file size. The trick is finding out what the correct +quality value is for your image. Too low a quality level produces a small file +at the cost of image quality. Too high a quality level increases file size +without providing a noticeable benefit to the user. +

          + +

          +The most straightforward solution is to pick some non-maximum value, and use +that value. However, be aware that the quality value affects every image +differently. While a quality of 75%, for example, may look fine on most images, +there may be some cases do not fare as well. You should make sure to test your +chosen maximum value against a representative sample of images. Also, make +sure to perform all of your tests against the original images, and not on +compressed versions. +

          + +

          +For large media applications that upload and re-send millions of JPGs a day, +hand-tuning for each asset is impractical. You might address this challenge by +specifying several different quality levels, according to image category. For +example, you might set 35% as the quality setting for thumbnails, since a +smaller image hides more compression artifacts. +

          + +

          Butteraugli

          + +

          +The Butteraugli project is a library to test an image's Psychovisual Error +Threshold: the point at which a viewer starts to notice image degradation. In +other words, this project attempts to quantify how distorted your compressed +image is. +

          + +

          +Butteraugli allows you to define a goal for visual quality, and then run PNG, +JPG, WebP lossy, and WebP lossless compressions. You can then choose the image +that is the best balance of file size and Butteraugli level. Figure 7 shows an +example of how Butteraugli was used to find the minimal JPG quality level +before the visual distortion was high enough for a user could perceive a +problem; the result is a roughly 65% reduction in file size. +

          + + +

          +Figure 7. An image before and after application of Butteraugli technology. +

          + +

          +Butteraugli allows you to proceed based on either output or input. That is, you +can look for the lowest quality setting before a user perceives noticeable +distortion in the resulting image, or you can iteratively set image-distortion +levels to learn their associated quality levels. +

          + +

          Serving Sizes

          + +

          +It is tempting to keep only a single resolution of an image on a server. When a +device accesses the image, the server serves it at that one resolution and +leaves downscaling to the device. +

          + +

          +This solution is convenient for the developer, but potentially painful for the +user, because the solution forces the user to download much more data than they +need. + +You should instead store multiple sizes of images, and serve the size that is +most appropriate for a particular use case. For example, for a thumbnail, +serving an actual thumbnail image instead of serving and downscaling a +full-size version consumes much less network bandwidth +

          + +

          +This approach is good for download speed, and is less costly for users who may +be using limited or metered data plans. Proceeding like this also results in +the image's taking less space on the device and in main memory. In the +case of large images, such as 4K ones, this approach also saves the device +from having to resize images before loading them. +

          + +

          +Implementing this approach requires that you have a backend image service to +provide images at various resolutions with proper caching. There are existing +services that can provide help with this task. For example, +App Engine comes +with image resizing functionality already installed. +

          diff --git a/docs/html/topic/performance/performance_toc.cs b/docs/html/topic/performance/performance_toc.cs new file mode 100644 index 0000000000000000000000000000000000000000..8c395239872a88264779822630d8c5ee4a4139a0 --- /dev/null +++ b/docs/html/topic/performance/performance_toc.cs @@ -0,0 +1,2289 @@ + + diff --git a/docs/html/topic/performance/power/battery-historian.jd b/docs/html/topic/performance/power/battery-historian.jd new file mode 100644 index 0000000000000000000000000000000000000000..79ea59d214190228fc9ec6fa6599ea86b4c041e3 --- /dev/null +++ b/docs/html/topic/performance/power/battery-historian.jd @@ -0,0 +1,247 @@ +page.title=Analyzing Power Use with Battery Historian +page.metaDescription=Improve network performance by optimizing image size. + +meta.tags="power" +page.tags="power" + +@jd:body + + + +

          +The Battery Historian tool provides insight into a device’s battery consumption +over time. At a system-wide level, the tool visualizes power-related events from +the system logs in an HTML representation. At an app-specific level, the tool +provides a variety of data that can help you identify battery-draining app +behavior. +

          + +

          +This document describes some of the ways you can use Battery Historian +to learn about battery-consumption patterns. The document begins by explaining +how to read the system-wide data that Battery Historian reports. Then, +it presents ways in which you can use Battery Historian to diagnose +and troubleshoot your own app's behavior related to battery consumption. +Last, it offers several tips on scenarios in which Battery Historian may be +particularly useful. +

          + +

          System-wide View

          + +

          +The Battery Historian tool provides a system-wide visualization of various +app and system behaviors, along with their correlation against battery +consumption over time. This view, shown in Figure 1, can help you +diagnose and identify power use issues with your app. +

          + + +

          +Figure 1. +Battery Historian’s display of system-wide events affecting power +consumption. +

          + +

          +Of particular interest in this figure is the black, horizontal, downward trend +line representing Battery Level, measured on the y-axis. For example, at the +very beginning of the Battery Level line, at approximately 6:50 AM, the +visualization shows a relatively steep drop in battery level. +

          + +

          +Figure 2 provides a close-up of that part of the display. +

          + + +

          +Figure 2. +A close-up of the Battery Historian timeline from roughly 6:50 AM to 7:20 AM. +

          + +

          +At the very beginning of the Battery Level line, as battery decline steeply, +the display shows three things happening: The CPU is running, an app has +acquired a wakelock, and the screen is on. In this way, Battery Historian helps +you understand what events are happening when battery consumption is high. You +can then target these behaviors in your app and investigate whether there are +related optimizations you can make. +

          + +

          +The system-wide visualization can provide other clues, as well. For instance, if +it shows that the mobile radio is frequently being turned off and on, there may +be an opportunity to optimize this behavior through intelligent scheduling APIs such as JobScheduler or +Firebase Job Dispatcher. +

          + +

          +The next section explains how to investigate behavior and events specific to +your own app. +

          + +

          +

          App-Specific Data

          +

          + +

          +In addition to the macro-level data provided by the system-wide view, Battery +Historian also provides tables and some visualization of data specific to each +app running on your device. The tabular data includes: +

          + +
            +
          • The app’s estimated power use on the device.
          • +
          • Network information.
          • +
          • Wakelocks.
          • +
          • Services.
          • +
          • Process info.
          • +
          + +

          +The tables provide two dimensions of data about your app. First, you can look +up where your app’s power usage ranks compared to other apps. To do so, click +Device Power Estimates table under Tables. This example +examines a fictional app called Pug Power. +

          + + +

          +Figure 3. Investigating which apps consume the most power. +

          + +

          +The table in Figure 3 reveals that Pug Power is the ninth biggest consumer of +battery power on this device, and the third biggest app that is not part of the +OS. This data suggests that this app bears deeper investigation. +

          + +

          +To look up the data for a specific app, enter its package name into the lower +of the two dropdown menus under App Selection, located under the left +side of the visualization. +

          + + +

          +Figure 4. Entering a specific app whose data to view. +

          + +

          +When you select a specific app, the following data visualization categories +change to display app-specific data instead of system-wide data: +

          + +
            +
          • SyncManager.
          • +
          • Foreground process.
          • +
          • Userspace Wakelock.
          • +
          • Top app.
          • +
          • JobScheduler.
          • +
          • Activity Manager Proc.
          • +
          + +The SyncManager and JobScheduler visualizations immediately make it obvious if +your app performs syncs and executes jobs more frequently than necessary. In +doing so, they can quickly reveal an opportunity to optimize your app’s +behavior for improved battery performance. + +

          +You can also obtain one more piece of app-specific visualization data, +Userspace Wakelock. To include this information in the bug report, +enter the following command in your terminal window: +

          + +
          +$ adb shell dumpsys batterystats --enable full-wake-history
          +
          + +

          +Note: From Android 6.0 (API level 23), the platform includes +Doze functionality, which imposes certain optimizations on apps. For example, +Doze batches jobs to take place during brief maintenance windows, regardless of +how JobScheduler has scheduled them. +

          + +

          +Figures 5 and 6 show data for Pug Power: Figure 5 +shows the visualization of +the app-specific data, and Figure 6 shows the corresponding tabular data. +

          + + +

          +Figure 5. Visualization of data for fictional app Pug Power. +

          + + +

          +Figure 6. Tabular data for the fictional Pug Power app. +

          + +

          +A look at the visualization does not show anything immediately obvious. +The JobScheduler line shows that the app has no jobs scheduled. The SyncManager +line shows that the app has not performed any syncs. +

          + +

          +However, examination of the Wakelocks segment of the tabular data +reveals that Pug Power acquires wakelocks totaling over an hour. This unusual +and costly behavior can account for the app’s high level of power consumption. +This piece of information helps the developer target an area where optimization +is likely to greatly help. In this case, why does the app acquire so much +wakelock time, and how can the developer ameliorate this behavior? +

          + +

          Other Cases Where Battery Historian Can Help

          + +

          +There are many other cases in which Battery Historian can help you diagnose +opportunities for improving battery behavior. For example, Battery Historian +can tell you if your app is: +

          + +
            +
          • Firing wakeup alarms overly frequently (every 10 seconds or less).
          • +
          • Continuously holding a GPS lock.
          • +
          • Scheduling jobs every 30 seconds or less.
          • +
          • Scheduling syncs every 30 seconds or less.
          • +
          • Using the cellular radio more frequently than you expect.
          • +
          + diff --git a/docs/html/topic/performance/power/index.jd b/docs/html/topic/performance/power/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..88addcea1f71262d649a74866c38fd9860fa7617 --- /dev/null +++ b/docs/html/topic/performance/power/index.jd @@ -0,0 +1,125 @@ +page.title=Optimizing for Battery Life +page.metaDescription=Learn how to help your app go easier on the battery. + +meta.tags="performance" +page.tags="performance" + +@jd:body + +
          +
          +

          + In this document +

          +
            +
          1. + Lazy First +
          2. +
          3. + Platform Features +
          4. +
          5. + Tooling +
          6. +
          +
          +
          + +

          Battery life is the single most important aspect of the mobile user +experience. A device without power offers no functionality at all. +For this reason, it is critically important that apps be as respectful of +battery life as possible.

          + +

          There are three important things to keep in mind in keeping your app +power-thrifty:

          +
            +
          • Make your apps Lazy First.
          • +
          • Take advantage of platform features that can help manage your app's battery +consumption.
          • +
          • Use tools that can help you identify battery-draining culprits.
          • +
          + +

          Lazy First

          + +

          Making your app Lazy First means looking for ways to reduce and optimize +operations that are particularly battery-intensive. The core questions +underpinning Lazy First design are: + +

            + +
          • Reduce: Are there redundant operations your app can cut +out? For example, can it cache downloaded data instead of repeatedly waking + up the radio to re-download the data?
          • + +
          • Defer: Does an app need to perform an action right + away? For example, + can it wait until the device is charging before it backs data up to the + cloud?
          • + +
          • Coalesce: Can work be batched, instead of putting the + device + into an active state many times? For example, is it really necessary for + several dozen apps to each turn on the radio at separate times to send + their messages? Can the messages instead be transmitted during a + single awakening of the radio?
          • +
          + +

          +You should ask these questions when it comes to using the CPU, +the radio, and the screen. Lazy First design is often a good way +to tame these battery killers. +

          + +

          +To help you achieve these and other efficiencies, the Android platform +provides a number of features to help maximize battery life. +

          + +

          Platform Features

          + +

          +Broadly speaking, the Android platform provides two categories of help +for you to optimize your app's battery use. First, it provides several +APIs that you can implement in your app. You can learn more about these APIs in +Intelligent Job Scheduling +and +Network Use and Battery Consumption. +

          + +

          +There are also internal mechanisms in the platform to help conserve +battery life. While they are not APIs that you implement programmatically, +you should still be aware of them so that your app can leverage them +successfully. For more information, see +Doze and +App Standby.

          + +

          +You can get even more benefit out of these features by using the tools +available for the platform to discover the parts of your app that consume +the most power. Finding what to target is a big step toward +successful optimization. +

          + +

          Tooling

          + +

          There are tools for Android, including +Profile GPU Rendering +and Battery Historian +to help you identify areas that you can optimize for better battery life. +Take advantage of these tools to target areas where you can apply the +principles of Lazy First. +

          + +
          +

          More resources

          +
          +
          +
          diff --git a/docs/html/training/performance/battery/network/action-any-traffic.jd b/docs/html/topic/performance/power/network/action-any-traffic.jd similarity index 100% rename from docs/html/training/performance/battery/network/action-any-traffic.jd rename to docs/html/topic/performance/power/network/action-any-traffic.jd diff --git a/docs/html/training/performance/battery/network/action-app-traffic.jd b/docs/html/topic/performance/power/network/action-app-traffic.jd similarity index 100% rename from docs/html/training/performance/battery/network/action-app-traffic.jd rename to docs/html/topic/performance/power/network/action-app-traffic.jd diff --git a/docs/html/training/performance/battery/network/action-server-traffic.jd b/docs/html/topic/performance/power/network/action-server-traffic.jd similarity index 100% rename from docs/html/training/performance/battery/network/action-server-traffic.jd rename to docs/html/topic/performance/power/network/action-server-traffic.jd diff --git a/docs/html/training/performance/battery/network/action-user-traffic.jd b/docs/html/topic/performance/power/network/action-user-traffic.jd similarity index 100% rename from docs/html/training/performance/battery/network/action-user-traffic.jd rename to docs/html/topic/performance/power/network/action-user-traffic.jd diff --git a/docs/html/training/performance/battery/network/analyze-data.jd b/docs/html/topic/performance/power/network/analyze-data.jd similarity index 100% rename from docs/html/training/performance/battery/network/analyze-data.jd rename to docs/html/topic/performance/power/network/analyze-data.jd diff --git a/docs/html/training/performance/battery/network/gather-data.jd b/docs/html/topic/performance/power/network/gather-data.jd similarity index 100% rename from docs/html/training/performance/battery/network/gather-data.jd rename to docs/html/topic/performance/power/network/gather-data.jd diff --git a/docs/html/training/performance/battery/network/index.jd b/docs/html/topic/performance/power/network/index.jd similarity index 100% rename from docs/html/training/performance/battery/network/index.jd rename to docs/html/topic/performance/power/network/index.jd diff --git a/docs/html/topic/performance/reduce-apk-size.jd b/docs/html/topic/performance/reduce-apk-size.jd new file mode 100644 index 0000000000000000000000000000000000000000..1e73bf017c1ec7193782666df020f77dfc5f8f1d --- /dev/null +++ b/docs/html/topic/performance/reduce-apk-size.jd @@ -0,0 +1,538 @@ +page.title=Reduce APK Size +trainingnavtop=true + +@jd:body + +
          + +
          + +

          + Users often avoid downloading apps that seem too large, particularly in + emerging markets where devices connect to often-spotty 2G and + 3G networks or work on pay-by-the-byte plans. This article describes how to + reduce your app's APK size, which enables more users to download your app. +

          + +

          + Understand the APK Structure +

          + +

          + Before discussing how to reduce the size of your app, it's helpful to + understand the structure of an app's APK. An APK file consists of a ZIP + archive that contains all the files that comprise your app. These files + include Java class files, resource files, and a file containing compiled + resources. +

          + +

          +An APK contains the following directories: +

          + +
            +
          • {@code META-INF/}: Contains the CERT.SF and + CERT.RSA signature files, as well as the {@code MANIFEST.MF} + manifest file. +
          • + +
          • {@code assets/}: Contains the app's assets, which the app can retrieve + using an {@link android.content.res.AssetManager} object. +
          • + +
          • + {@code res/}: Contains resources that aren't compiled into + resources.arsc. +
          • + +
          • {@code lib/}: Contains the compiled code that is specific to the software + layer of a processor. This directory contains a subdirectory for each + platform type, like armeabi, armeabi-v7a, + arm64-v8a, x86, x86_64, and + mips. +
          • +
          + +

          +An APK also contains the following files. Among them, +only AndroidManifest.xml is mandatory. +

          + +
            +
          • {@code resources.arsc}: Contains compiled resources. This file contains + the XML content from all configurations of the res/values/ + folder. The packaging tool extracts this XML content, compiles it to binary + form, and archives the content. This content includes language strings and + styles, as well as paths to content that is not included directly in the + resources.arsc file, such as layout files and images. +
          • + +
          • {@code classes.dex}: Contains the classes compiled in the DEX file format + understood by the Dalvik/ART virtual machine. +
          • + +
          • {@code AndroidManifest.xml}: Contains the core Android manifest file. + This file lists the name, version, access rights, and referenced library + files of the app. The file uses Android's binary XML format. +
          • +
          + +

          + Reduce Resource Count and Size +

          + +

          + The size of your APK has an impact on how fast your app loads, how much + memory it uses, and how much power it consumes. One of the simple ways to + make your APK smaller is to reduce the number and size of the + resources it contains. In particular, you can remove resources + that your app no longer uses, and you can use scalable {@link + android.graphics.drawable.Drawable} objects in place of image files. This + section discusses these methods as well as several other ways that you can + reduce the resources in your app to decrease the overall size of your APK. +

          + +

          + Remove Unused Resources +

          + +

          + The {@code lint} tool, a + static code analyzer included in Android Studio, detects resources in your + res/ folder that your code doesn't reference. When the + lint tool discovers a potentially unused resource in your + project, it prints a message like the following example. +

          + +
          +res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
          +    to be unused [UnusedResources]
          +
          +

          + Note: The lint tool doesn't scan the {@code + assets/} folder, assets that are referenced via reflection, or library files + that you've linked to your app. Also, it doesn't remove resources; it only + alerts you to their presence. +

          + +

          + Libraries that you add to your code may include unused resources. Gradle can + automatically remove resources on your behalf if you enable {@code shrinkResources} in + your app's build.gradle file. +

          + +
          +android {
          +    // Other settings
          +
          +    buildTypes {
          +        release {
          +            minifyEnabled true
          +            shrinkResources true
          +            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
          +        }
          +    }
          +}
          +
          +

          + To use {@code shrinkResources}, you must enable code shrinking. During the + build process, first ProGuard removes unused code + but leaves unused resources. Then Gradle removes the unused resources. +

          + +

          + For more information about ProGuard and other ways + Android Studio helps you reduce APK size, see Shrink Your Code and Resources. +

          + +

          + In Android Gradle Plugin 0.7 and higher, you can declare the configurations + that your app supports. Gradle passes this information to the build system + using the {@code resConfig} and {@code resConfigs} flavors and the + defaultConfig option. The build system then prevents resources + from other, unsupported configurations from appearing in the APK, reducing + the APK's size. For more information about this feature, see Remove unused + alternative resources. +

          + +

          + Minimize Resource Use from Libraries +

          + +

          + When developing an Android app, you usually use external libraries to improve + your app's usability and versatility. For example, you might reference the + Android + Support Library to improve the user experience on older devices, or you + could use Google Play + Services to retrieve automatic translations for text within your app. +

          + +

          + If a library was designed for a server or desktop, it can include many + objects and methods that your app doesn’t need. To include only the parts of + the library that your app needs, you can edit the library's files if the + license allows you to modify the library. You can also use an alternative, + mobile-friendly library to add specific functionality to your app. +

          + +

          + Note: ProGuard can clean up some + unnecessary code imported with a library, but it can't remove a library's + large internal dependencies. +

          + +

          + Support Only Specific Densities +

          + +

          + Android supports a very large set of devices, encompassing a variety of + screen densities. In Android 4.4 (API level 19) and higher, the framework + supports various densities: ldpi, mdpi, + tvdpi, hdpi, xhdpi, + xxhdpi and xxxhdpi. Although Android supports all + these densities, you don't need to export your rasterized assets to each + density. +

          + +

          + If you know that only a small percentage of your users have devices with + specific densities, consider whether you need to bundle those densities into + your app. If you don't include resources for a specific screen density, + Android automatically scales existing resources originally designed for other + screen densities. +

          + +

          + If your app needs only scaled images, you can save even more space by having + a single variant of an image in drawable-nodpi/. We recommend + that every app include at least an xxhdpi image variant. +

          + +

          + For more information screen densities, see Screen Sizes and + Densities. +

          + +

          + Reduce Animation Frames +

          + +

          + Frame-by-frame animations can drastically increase the size of your APK. + Figure 1 shows an example of a frame-by-frame animation separated into + multiple PNG files within a directory. Each image is one frame in the + animation. +

          + +

          + For each frame that you add to the animation, you increase the number of + images stored in the APK. In Figure 1, the image animates at 30 FPS within + the app. If the image animated at only 15 FPS instead, the animation would + require only half the number of needed frames. +

          + +
          + +
          + Figure 1. Frame by frame animations stored as resources. +
          +
          + +

          + Use Drawable Objects +

          + +

          + Some images don't require a static image resource; the framework can + dynamically draw the image at runtime instead. {@link + android.graphics.drawable.Drawable} objects (<shape> in + XML) can take up a tiny amount of space in your APK. In addition, XML {@link + android.graphics.drawable.Drawable} objects produce monochromatic images + compliant with material design guidelines. +

          + +

          + Reuse Resources +

          + +

          + You can include a separate resource for variations of an image, such as + tinted, shaded, or rotated versions of the same image. We recommend, however, + that you reuse the same set of resources, customizing them as needed at + runtime. +

          + +

          + Android provides several utilities to change the color of an asset, either + using the {@code android:tint} and {@code tintMode} attributes on Android 5.0 + (API level 21) and higher. For lower versions of the platform, use the {@link + android.graphics.ColorFilter} class. +

          +

          + You can also omit resources that are only a rotated equivalent of another + resource. The following code snippet provides an example of turning an + "expand" arrow into a "collapse" arrow icon by simply rotating the original + image 180 degrees: +

          + +
          +<?xml version="1.0" encoding="utf-8"?>
          +<rotate xmlns:android="http://schemas.android.com/apk/res/android"
          +    android:drawable="@drawable/ic_arrow_expand"
          +    android:fromDegrees="180"
          +    android:pivotX="50%"
          +    android:pivotY="50%"
          +    android:toDegrees="180" />
          +
          +

          + Render From Code +

          + +

          + You can also reduce your APK size by procedurally rendering your images. + Procedural rendering frees up space because you no longer store an image file + in your APK. +

          + +

          + Crunch PNG Files +

          + +

          + The aapt tool can optimize the image resources placed in + res/drawable/ with lossless compression during the build + process. For example, the aapt tool can convert a true-color PNG + that does not require more than 256 colors to an 8-bit PNG with a color + palette. Doing so results in an image of equal quality but a smaller memory + footprint. +

          + +

          + Keep in mind that the aapt has the following limitations: +

          + +
            +
          • The aapt tool does not shrink PNG files contained in the + asset/ folder. +
          • + +
          • Image files need to use 256 or fewer colors for the aapt + tool to optimize them. +
          • + +
          • The aapt tool may inflate PNG files that have already been + compressed. To prevent this, you can use the cruncherEnabled + flag in Gradle to disable this process for PNG files: +
          • +
          + +
          +aaptOptions {
          +    cruncherEnabled = false
          +}
          +
          +

          + Compress PNG and JPEG Files +

          + +

          + You can reduce PNG file sizes without losing image quality using tools like + pngcrush, pngquant, or zopflipng. All of these tools can + reduce PNG file size while preserving image quality. +

          + +

          + The {@code pngcrush} tool is particularly effective: This tool iterates over + PNG filters and zlib (Deflate) parameters, using each combination of filters + and parameters to compress the image. It then chooses the configuration that + yields the smallest compressed output. +

          + +

          + For JPEG files, you can use tools like packJPG that compress JPEG + files into a more compact form. +

          + +

          + Use WebP File Format +

          + +

          + Instead of using PNG or JPEG files, you can also use the WebP + file format for your images. The WebP format provides lossy compression (like + JPEG) as well as transparency (like PNG) but can provide better compression + than either JPEG or PNG. +

          + +

          + Using the WebP file format has a few notable drawbacks, however. First, + support for WebP is not available in versions of the platform lower than + Android 3.2 (API level 13). Second, it takes a longer amount of time for the + system to decode WebP than PNG files. +

          + +

          + Note: Google Play accepts APKs only if the included icons + use the PNG format. You can't use other file formats like JPEG or WebP for + app icons if you intend to publish your app through Google Play. +

          + +

          + Use Vector Graphics +

          + +

          + You can use vector graphics to create resolution-independent icons and other + scalable media. Using these graphics can greatly reduce your APK footprint. + Vector images are represented in Android as {@link + android.graphics.drawable.VectorDrawable} objects. With a {@link + android.graphics.drawable.VectorDrawable } object, a 100-byte file can + generate a sharp image the size of the screen. +

          + +

          + However, it takes a significant amount of time for the system to render each + {@link android.graphics.drawable.VectorDrawable} object, and larger images + take even longer to appear on the screen. Therefore, consider using these + vector graphics only when displaying small images. +

          + +

          + For more information on working with {@link + android.graphics.drawable.VectorDrawable } objects, see Working + with Drawables. +

          + +

          + Reduce Native and Java Code +

          + +

          + There are several methods you can use to reduce the size of the Java and + native codebase in your app. +

          + +

          + Remove Unnecessary Generated Code +

          + +

          + Make sure to understand the footprint of any code which is automatically + generated. For example, many protocol buffer tools generate an excessive + number of methods and classes, which can double or triple the size of your + app. +

          + +

          + Remove Enumerations +

          + +

          + A single enum can add about 1.0 to 1.4 KB of size to your app's + classes.dex file. These additions can quickly accumulate for + complex systems or shared libraries. If possible, consider using the + @IntDef annotation and ProGuard to strip enumerations + out and convert them to integers. This type conversion preserves all of the + type safety benefits of enums. +

          + +

          + Reduce the Size of Native Binaries +

          + +

          + If your app uses native code and the Android NDK, you can also reduce the + size of your app by optimizing your code. Two useful techniques are + removing debug symbols and not extracting native libraries. +

          + +

          + Remove Debug Symbols +

          + +

          + Using debug symbols makes sense if your application is in development and + still requires debugging. Use the arm-eabi-strip tool, provided + in the Android NDK, to remove unnecessary debug symbols from native + libraries. After that, you can compile your release build. +

          + +

          + Avoid Extracting Native Libraries +

          + +

          + Store {@code .so} files uncompressed in the APK, and set the {@code + android:extractNativeLibs} flag to false in the {@code + } element of your app manifest. This will prevent + {@link android.content.pm.PackageManager} from copying out {@code .so} files + from the APK to the filesystem during installation and will have the added + benefit of making delta updates of your app smaller. +

          + +

          + Maintain Multiple Lean APKs +

          + +

          + Your APK can contain content that users download but never use, like regional + or language information. To create a minimal download for your users, you can + segment your app into several APKs, differentiated by factors such as screen + size or GPU texture support. +

          + +

          + When a user downloads your app, their device receives the correct APK based + on the device's features and settings. This way, devices don't receive assets + for features that the devices don't have. For example, if a user has a + hdpi device, they don’t need xxxhdpi resources that + you might include for devices with higher density displays. +

          + +

          + For more information, see Configure APK Splits + and Maintaining Multiple APKs. +

          diff --git a/docs/html/topic/performance/rendering/index.jd b/docs/html/topic/performance/rendering/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..1b16df035376bdc0f2af138f70ed5ddb10ca06be --- /dev/null +++ b/docs/html/topic/performance/rendering/index.jd @@ -0,0 +1,60 @@ +page.title=Rendering +page.article=true + +page.tags=battery +page.metaDescription=Learn how to optimize your app's rendering performance. + +@jd:body + + + + +

          + A key aspect of your app that influences your users' perception of quality is + the smoothness with which it renders images and text to the screen. It is + important to avoid jank and sluggish responsiveness when your app is drawing + to the screen. +

          + +

          + This section helps you learn several ways to optimize your app's rendering + performance: reducing overdraw, optimizing view hierarchies, and taking + advantage of the Profile GPU tool. +

          + +

          Rendering Actions

          + +
          +
          + + Reducing Overdraw +
          +
          + Minimize the number of times you app redraws the same pixel in a single + frame. +
          + +
          + + Performance and View Hierarchies +
          +
          + Make sure your layout and measurement are executing efficiently, and + avoid double taxation. +
          + + +
          + + Analyzing with Profile GPU Rendering +
          +
          + Take advantage of this on-device tool to identify bottlenecks that + may be slowing your app's rendering down. +
          + + +
          diff --git a/docs/html/topic/performance/rendering/optimizing-view-hierarchies.jd b/docs/html/topic/performance/rendering/optimizing-view-hierarchies.jd new file mode 100644 index 0000000000000000000000000000000000000000..27d3d163f853cc338c34dd9b9ae30ca67dfc8bbe --- /dev/null +++ b/docs/html/topic/performance/rendering/optimizing-view-hierarchies.jd @@ -0,0 +1,388 @@ +page.title=Performance and View Hierarchies +@jd:body + + + + +

          +The way you manage the hierarchy of your {@link android.view.View} objects can +have a substantial impact on your app’s performance. This page describes how to +assess whether your view hierarchy is slowing your app down, and offers some +strategies for addressing issues that may arise. +

          + +

          Layout and Measure Performance

          +

          +The rendering pipeline includes a layout-and-measure +stage, during which the system appropriately positions the relevant items in +your view hierarchy. The measure part of this stage determines the sizes and +boundaries of {@link android.view.View} objects. The layout part determines where on the screen to +position the {@link android.view.View} objects. +

          + +

          +Both of these pipeline stages incur some small cost per view or layout that they +process. Most of the time, this cost is minimal and doesn’t noticeably affect +performance. However, it can be greater when an app adds or removes View +objects, such as when a {@link android.support.v7.widget.RecyclerView} +object recycles them or reuses them. The +cost can also be higher if a {@link android.view.View} object needs to consider +resizing to main its constraints: For example, if your app calls +{@link android.widget.TextView#setText(char[], int, int) SetText()} on a +{@link android.view.View} object that wraps text, the +{@link android.view.View} may need to resize. +

          + +

          +If cases like these take too long, they can prevent a frame from rendering +within the allowed 16ms, so that frames are dropped, and animation becomes +janky. +

          + +

          +Because you cannot move these operations to a worker thread—your app must +process them on the main thread—your best bet is to optimize them so that +they can take as little time as possible. +

          + +

          Managing complexity: layouts matter

          + +

          +Android Layouts +allow you to nest UI objects in the view hierarchy. This nesting can also impose +a layout cost. When your app processes an object for layout, the app performs +the same process on all children of the layout as well. For a complicated +layout, sometimes a cost only arises the first time the system computes the +layout. For instance, when your app recycles a complex list item in a +{@link android.support.v7.widget.RecyclerView} object, the +system needs to lay out all of the objects. In another example, trivial changes +can propagate up the chain toward the parent +until they reach an object that doesn’t affect the size of the parent. +

          + +

          +The most common case in which layout takes an especially long time is when +hierarchies of {@link android.view.View} objects are nested within one another. Each nested layout +object adds cost to the layout stage. The flatter your hierarchy, the less +time that it takes for the layout stage to complete. +

          + +

          +If you are using the {@link android.widget.RelativeLayout} class, you may be able to achieve the same +effect, at lower cost, by using nested, unweighted +{@link android.widget.LinearLayout} views instead. Additionally, if your app +targets Android N (API level 24), it is likely that +you can use a special layout editor to create a {@code ConstraintLayout} +object instead of {@link android.widget.RelativeLayout}. Doing so allows you +to avoid many of the issues this section +describes. The {@code ConstraintLayout} +class offers similar layout control, but +with much-improved performance. This class uses its own constraint-solving +system to resolve relationships between views in a very different way from +standard layouts. +

          + +

          Double Taxation

          + +

          +Typically, the framework executes the layout +or measure stage in a single pass and quite quickly. However, with some more +complicated layout cases, the framework may have to iterate multiple times on +the layout or measure stage before ultimately positioning the elements. Having +to perform more than one layout-and-measure iteration is referred to as +double taxation. +

          + +

          +For example, when you use the {@link android.widget.RelativeLayout} container, which allows you to +position {@link android.view.View} objects with respect to the positions of other {@link android.view.View} objects, the +framework performs the following actions: +

          + +
            +
          1. Executes a layout-and-measure pass, during which the framework calculates +each child object’s position and size, based on each child’s request. +
          2. Uses this data, also taking object weights into account, to figure out the +proper position of correlated views. +
          3. Performs a second layout pass to finalize the objects’ positions. +
          4. Goes on to the next stage of the rendering process.
          + +

          +The more levels your view hierarchy has, the greater the potential performance +penalty. +

          + +

          +Containers other than {@link android.widget.RelativeLayout} may also give rise to double taxation. For +example: +

          + +
            +
          • A {@link android.widget.LinearLayout} view +could result in a double layout-and-measure pass if you make it horizontal. +A double layout-and-measure pass may also occur in a vertical orientation if you +add measureWithLargestChild, +in which case the framework may need to do a second pass to resolve the proper +sizes of objects. +
          • The {@link android.widget.GridLayout} +has a similar issue. While this container also allows relative positioning, it +normally avoids double taxation by pre-processing the positional relationships +among child views. However, if the layout uses weights or fill with the +{@link android.view.Gravity} class, the +benefit of that preprocessing is lost, and the framework may have to perform +multiple passes if it the container were a {@link android.widget.RelativeLayout}.
          • +
          +

          +Multiple layout-and-measure passes are not, in themselves, a performance burden. +But they can become so if they’re in the wrong spot. You should be wary of +situations where one of the following conditions applies to your container: +

          + +
            +
          • It is a root element in your view hierarchy. +
          • It has a deep view hierarchy beneath it. +
          • It is nested. +
          • There are many instances of it populating the screen, similar to children + in a {@link android.widget.ListView} object.
          • +
          + +

          Diagnosing View Hierarchy Issues

          + +

          +Layout performance is a complex problem with many facets. There are a couple of +tools that can give you solid indications about where performance bottlenecks +are occurring. A few other tools provide less definitive information, but can +also provide helpful hints. +

          + +

          +

          Systrace

          +

          + +

          +One tool that provides excellent data about performance is Systrace, +which is built into Android Studio. The Systrace tool allows you to collect and +inspect timing information across an entire Android device, allowing you to see +specifically where performance bottlenecks arise. For more information about +Systrace, see +Analyze UI Performance with Systrace. +

          + +

          Profile GPU rendering

          + +

          +The other tool most likely to provide you with concrete information about +performance bottlenecks is the on-device +Profile GPU rendering tool, available on devices powered by Android 6.0 (API +level 23) and later. This tool allows you to see how long the layout-and-measurestage is + taking for each frame +of rendering. This data can help you diagnose runtime performance issues, +and help you determine what, if any layout-and-measure issues you need to +address. +

          + +

          +In its graphical representation of the data it captures, Profile +GPU rendering uses the color blue to represent layout time. For more +information about how to use this tool, see Profile +GPU Rendering Walkthrough. +

          + +

          Lint

          + +

          +Android Studio’s Lint tool can +help you gain a sense of inefficiencies in the view hierarchy. To use this tool, +select Analyze > Inspect Code, as shown in Figure 1. +

          + + +

          + Figure 1. Locating Inspect Code in the +Android Studio. +

          + +

          +Information about various layout items appears under +Android > Lint > Performance. To see more detail, +you can click on each item to expand it, and see more +information in the pane on the right side of the screen. +Figure 2 shows an example of such a display. +

          + + +

          + Figure 2. Viewing information about specific +issues that the lint tool has identified. +

          + + +

          +Clicking on one of these items reveals, in the pane to the right, the problem +associated with that item. +

          + +

          +To understand more about specific topics and issues in this area, see the Lint +documentation. +

          + +

          Hierarchy Viewer

          + +

          +Android Studio’s Hierarchy +Viewer tool provides a visual representation of your app’s view hierarchy. +It is a good way to navigate the hierarchy of your app, providing a clear visual +representation of a particular view’s parent chain, and allowing you to inspect +the layouts that your app constructs. +

          + +

          +The views that Hierarchy Viewer presents can also help identify performance +problems arising from double taxation. It can also provide an easy way for you +to identify deep chains of nested layouts, or layout areas with a large amount +of nested children, another potential source of performance costs. In these +scenarios, the layout-and-measure stages can be particularly costly, +resulting in performance issues. +

          + +

          +You can also can get a sense of relative time taken by layout-and-measure +operations by clicking the “profile node” button. +

          + +

          +For more information about Hierarchy Viewer, see Optimizing +Your UI. +

          + +

          Solving View Hierarchy Issues

          + +

          +The fundamental concept behind solving performance problems that arise from view +hierarchies is simple in concept, but more difficult in practice. Preventing +view hierarchies from imposing performance penalties encompasses the dual goals +of flattening your view hierarchy and reducing double taxation. This section +discusses some strategies for pursuing these goals. +

          + +

          Removing redundant nested layouts

          + +

          +Developers often use more nested layouts than necessary. For example, a +{@link android.widget.RelativeLayout} container might contain a single child that is also a +{@link android.widget.RelativeLayout} container. This nesting amounts to redundancy, and adds +unnecessary cost to the view hierarchy. +

          + +

          +Lint can often flag this problem for you, reducing debugging time. +

          + +

          Adopting Merge/Include

          +

          +One frequent cause of redundant nested layouts is the +<include> +tag. For example, you may define a re-usable layout as follows: +

          + +
          +<LinearLayout>
          +    <!-- some stuff here -->
          +</LinearLayout>
          +</pre>
          +
          + +

          +And then an include tag to add this item to the parent container: +

          + +
          +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          +    android:orientation="vertical"
          +    android:layout_width="match_parent"
          +    android:layout_height="match_parent"
          +    android:background="@color/app_bg"
          +    android:gravity="center_horizontal">
          +
          +    <include layout="@layout/titlebar"/>
          +
          +    <TextView android:layout_width="match_parent"
          +              android:layout_height="wrap_content"
          +              android:text="@string/hello"
          +              android:padding="10dp" />
          +
          +    ...
          +
          +</LinearLayout>
          +
          + +

          +The include unnecessarily nests the first layout within the second layout. +

          + +

          +The merge +tag can help prevent this issue. For information about this tag, see Re-using +Layouts with <include>. +

          + +

          Adopting a cheaper layout

          + +

          +You may not be able to adjust your existing layout scheme so that it doesn’t +contain redundant layouts. In certain cases, the only solution may be to flatten +your hierarchy by switching over to an entirely different layout type. +

          + +

          +For example, you may find that a {@link android.widget.TableLayout} +provides the same functionality as a more complex layout with many +positional dependencies. In the N release of Android, the +{@code ConstraintLayout} class provides similar functionality to +{@link android.widget.RelativeLayout}, but at a significantly lower cost. +

          diff --git a/docs/html/topic/performance/rendering/overdraw.jd b/docs/html/topic/performance/rendering/overdraw.jd new file mode 100644 index 0000000000000000000000000000000000000000..c1feff57a26b1045e084fe2aa8b3dc1699ccf98a --- /dev/null +++ b/docs/html/topic/performance/rendering/overdraw.jd @@ -0,0 +1,197 @@ +page.title=Reducing Overdraw +page.metaDescription=Improve performance by reducing unnecessary rendering. + +meta.tags="performance" +page.tags="performance" + +@jd:body + +
          +
          + +

          In this document

          +
            + +
          1. + Understanding Overdraw +
          2. +
          3. + Finding Overdraw Problems +
          4. +
          5. + Fixing Overdraw +
          6. +
          +
          +
          + +

          +An app may draw the same pixel more than once within a single frame, an event +called overdraw. Overdraw is usually unnecessary, and best +eliminated. It manifests itself as a performance problem by wasting GPU time to +render pixels that don't contribute to what the user sees on the screen. +

          + +

          +This document explains overdraw: what it is, how to diagnose it, and actions you +can take to eliminate or mitigate it. +

          + +

          Understanding Overdraw

          + +

          +Overdraw refers to the system's drawing a pixel on the screen multiple times +in a single frame of rendering. For example, if we have a bunch of stacked UI +cards, each card hides a portion of the one below it. +

          + +

          +However, the system still needs to draw even the hidden portions of the cards +in the stack. This is because stacked cards are rendered according to the +painter's +algorithm: that is, in back-to-front order. +This sequence of rendering allows the system to apply proper alpha blending to +translucent objects such as shadows. +

          + +

          Finding Overdraw Problems

          + +

          +The platform offers several tools to help you determine if overdraw is +affecting your app's performance. These tools are available right on the device, +and accessible by turning on Developer Settings under +Settings. For more information about device developer settings, see +Run Apps on a +Hardware Device. +

          + +

          Debug GPU overdraw tool

          + +

          +The Debug GPU Overdraw tool uses color-coding to show the number of times your +app draws each pixel on the screen. The higher this count, the +more likely it is that overdraw affects your app's performance. +

          + +

          +For more information on how to use the tool, refer to the related +walkthrough +and + +codelab. +

          + +

          Profile GPU rendering tool

          + +

          +The Profile GPU Rendering tool displays, as a scrolling histogram, the time +each stage of the rendering pipeline takes to display a single frame. The +Process part of each bar, indicated in orange, shows when the system +is swapping buffers; this metric provides important clues about overdraw. +

          + +

          +On less performant GPUs, available fill-rate (the speed at which the GPU can +fill the frame buffer) can be quite low. As the number of +pixels required to draw a frame increases, the GPU may take longer to process +new commands, and ask the rest of the system to wait until it can catch up. +The Process bar shows that this spike happens as the GPU gets +overwhelmed trying to draw pixels as fast as possible. Issues other than +raw numbers of pixels may also cause this metric to spike. For example, +if the Debug GPU Overdraw tool shows heavy overdraw and Process spikes, +there's likely an issue with overdraw. +

          + +

          Note: The + +Profile GPU Rendering tool does not +work with apps that use the NDK. This is because the system pushes framework +messages to the background whenever OpenGL takes a full-screen context. In +such cases, you may find a profiling tool provided by the GPU manufacturer +helpful.

          + +

          Fixing Overdraw

          + +

          +There are several strategies you can pursue to reduce or eliminate overdraw: +

          + +
            +
          • Removing unneeded backgrounds in layouts.
          • +
          • Flattening the view hierarchy.
          • +
          • Reducing transparency.
          • +
          + +

          +This section provides information about each of these approaches. +

          + +

          Removing unneeded backgrounds in layouts

          + +

          +By default, a layout does not have a background, which means it does not render +anything directly by itself. When layouts do have backgrounds, however, they may +contribute to overdraw. +

          + +

          +Removing unnecessary backgrounds is a quick way of improving rendering +performance. An unnecessary background may never be visible because it's +completely covered by everything else the app is drawing on top of that +view. For example, the system may entirely cover up a parent's +background when it draws child views on top of it. +

          + +

          +To find out why you're overdrawing, walk through the hierarchy in +the Hierarchy Viewer tool. +As you do so, look out for any backgrounds you can eliminate because +they are not visible to the user. Cases where many containers share a +common background color offer another opportunity to eliminate unneeded +backgrounds: You can set the window background to the main background color +of your app, and leave all of the containers above it with no background values +defined. +

          + +

          Flattening view hierarchy

          + +

          +Modern layouts make it easy to stack and layer views to produce beautiful +design. However, doing so can degrade performance by resulting in overdraw, +especially in scenarios where each stacked view object is opaque, requiring the +drawing of both seen and unseen pixels to the screen. +

          + +

          +If you encounter this sort of issue, you may be able to improve performance by +optimizing your view hierarchy to reduce the number of overlapping UI objects. +For more information about how to accomplish this, see +Optimizing View +Hierarchies. +

          + +

          Reducing transparency

          + +

          +Rendering of transparent pixels on screen, known as alpha rendering, is a key +contributor to overdraw. Unlike standard overdraw, +in which the system completely hides existing drawn pixels by drawing +opaque pixels on top of them, transparent +objects require existing pixels to be drawn first, so that the right blending +equation can occur. Visual effects like transparent animations, fade-outs, and +drop shadows all involve some sort of transparency, and can therefore contribute +significantly to overdraw. You can improve overdraw in these situations by +reducing the number of transparent objects you render. For example, you can get +gray text by drawing black text in a {@link android.widget.TextView} with a +translucent alpha value set on it. But you can get the same effect with far +better performance by simply drawing the text in gray. +

          + +

          +To learn more about performance costs that transparency imposes throughout the +entire drawing pipeline, watch the video + +Hidden Costs of Transparency. +

          + diff --git a/docs/html/topic/performance/rendering/profile-gpu.jd b/docs/html/topic/performance/rendering/profile-gpu.jd new file mode 100644 index 0000000000000000000000000000000000000000..fc9877772610680532092be23bb61abbd644fade --- /dev/null +++ b/docs/html/topic/performance/rendering/profile-gpu.jd @@ -0,0 +1,406 @@ +page.title=Analyzing with Profile GPU Rendering +page.metaDescription=Use the Profile GPU tool to help you optimize your app's rendering performance. + +meta.tags="power" +page.tags="power" + +@jd:body + +
          +
          + +

          In this document

          +
            +
          1. + Visual Representation
          2. + + +
          3. + Stages and Their Meanings + + +
          4. +
          +
          +
          + +

          +The +Profile GPU Rendering tool indicates the relative time that each stage of +the rendering pipeline takes to render the previous frame. This knowledge +can help you identify bottlenecks in the pipeline, so that you +can know what to optimize to improve your app's rendering performance. +

          + +

          +This page briefly explains what happens during each pipeline stage, and +discusses issues that can cause bottlenecks there. Before reading +this page, you should be familiar with the information presented in the +Profile GPU +Rendering Walkthrough. In addition, to understand how all of the +stages fit together, it may be helpful to review + +how the rendering pipeline works. +

          + +

          Visual Representation

          + +

          +The Profile GPU Rendering tool displays stages and their relative times in the +form of a graph: a color-coded histogram. Figure 1 shows an example of +such a display. +

          + + +

          +Figure 1. Profile GPU Rendering Graph +

          + +

          + +

          +Each segment of each vertical bar displayed in the Profile GPU Rendering +graph represents a stage of the pipeline and is highlighted using a specific +color in +the bar graph. Figure 2 shows a key to the meaning of each displayed color. +

          + + +

          +Figure 2. Profile GPU Rendering Graph Legend +

          + +

          +Once you understand what each color signfiies, +you can target specific aspects of your +app to try to optimize its rendering performance. +

          + +

          Stages and Their Meanings

          + +

          +This section explains what happens during each stage corresponding +to a color in Figure 2, as well as bottleneck causes to look out for. +

          + + +

          Input Handling

          + +

          +The input handling stage of the pipeline measures how long the app +spent handling input events. This metric indicates how long the app +spent executing code called as a result of input event callbacks. +

          + +

          When this segment is large

          + +

          +High values in this area are typically a result of too much work, or +too-complex work, occurring inside the input-handler event callbacks. +Since these callbacks always occur on the main thread, solutions to this +problem focus on optimizing the work directly, or offloading the work to a +different thread. +

          + +

          +It’s also worth noting that {@link android.support.v7.widget.RecyclerView} +scrolling can appear in this phase. +{@link android.support.v7.widget.RecyclerView} scrolls immediately when it +consumes the touch event. As a result, +it can inflate or populate new item views. For this reason, it’s important to +make this operation as fast as possible. Profiling tools like Traceview or +Systrace can help you investigate further. +

          + +

          Animation

          + +

          +The Animations phase shows you just how long it took to evaluate all the +animators that were running in that frame. The most common animators are +{@link android.animation.ObjectAnimator}, +{@link android.view.ViewPropertyAnimator}, and +Transitions. +

          + +

          When this segment is large

          + +

          +High values in this area are typically a result of work that’s executing due +to some property change of the animation. For example, a fling animation, +which scrolls your {@link android.widget.ListView} or +{@link android.support.v7.widget.RecyclerView}, causes large amounts of view +inflation and population. +

          + +

          Measurement/Layout

          + +

          +In order for Android to draw your view items on the screen, it executes +two specific operations across layouts and views in your view hierarchy. +

          + +

          +First, the system measures the view items. Every view and layout has +specific data that describes the size of the object on the screen. Some views +can have a specific size; others have a size that adapts to the size +of the parent layout container +

          + +

          +Second, the system lays out the view items. Once the system calculates +the sizes of children views, the system can proceed with layout, sizing +and positioning the views on the screen. +

          + +

          +The system performs measurement and layout not only for the views to be drawn, +but also for the parent hierarchies of those views, all the way up to the root +view. +

          + +

          When this segment is large

          + +

          +If your app spends a lot of time per frame in this area, it is +usually either because of the sheer volume of views that need to be +laid out, or problems such as + +double taxation at the wrong spot in your +hierarchy. In either of these cases, addressing performance involves +improving +the performance of your view hierarchies. +

          + +

          +Code that you’ve added to +{@link android.view.View#onLayout(boolean, int, int, int, int)} or +{@link android.view.View#onMeasure(int, int)} +can also cause performance +issues. Traceview and +Systrace can help you examine +the callstacks to identify problems your code may have. +

          + +

          Drawing

          + +

          +The draw stage translates a view’s rendering operations, such as drawing +a background or drawing text, into a sequence of native drawing commands. +The system captures these commands into a display list. +

          + +

          +The Draw bar records how much time it takes to complete capturing the commands +into the display list, for all the views that needed to be updated on the screen +this frame. The measured time applies to any code that you have added to the UI +objects in your app. Examples of such code may be the +{@link android.view.View#onDraw(android.graphics.Canvas) onDraw()}, +{@link android.view.View#dispatchDraw(android.graphics.Canvas) dispatchDraw()}, +and the various draw ()methods belonging to the subclasses of the +{@link android.graphics.drawable.Drawable} class. +

          + +

          When this segment is large

          + +

          +In simplified terms, you can understand this metric as showing how long it took +to run all of the calls to +{@link android.view.View#onDraw(android.graphics.Canvas) onDraw()} +for each invalidated view. This +measurement includes any time spent dispatching draw commands to children and +drawables that may be present. For this reason, when you see this bar spike, the +cause could be that a bunch of views suddenly became invalidated. Invalidation +makes it necessary to regenerate views' display lists. Alternatively, a +lengthy time may be the result of a few custom views that have some extremely +complex logic in their +{@link android.view.View#onDraw(android.graphics.Canvas) onDraw()} methods. +

          + +

          Sync/Upload

          + +

          +The Sync & Upload metric represents the time it takes to transfer +bitmap objects from CPU memory to GPU memory during the current frame. +

          + +

          +As different processors, the CPU and the GPU have different RAM areas +dedicated to processing. When you draw a bitmap on Android, the system +transfers the bitmap to GPU memory before the GPU can render it to the +screen. Then, the GPU caches the bitmap so that the system doesn’t need to +transfer the data again unless the texture gets evicted from the GPU texture +cache. +

          + +

          Note: On Lollipop devices, this stage is +purple. +

          + +

          When this segment is large

          + +

          +All resources for a frame need to reside in GPU memory before they can be +used to draw a frame. This means that a high value for this metric could mean +either a large number of small resource loads or a small number of very large +resources. A common case is when an app displays a single bitmap that’s +close to the size of the screen. Another case is when an app displays a +large number of thumbnails. +

          + +

          +To shrink this bar, you can employ techniques such as: +

          + +
            +
          • +Ensuring your bitmap resolutions are not much larger than the size at which they +will be displayed. For example, your app should avoid displaying a 1024x1024 +image as a 48x48 image. +
          • + +
          • +Taking advantage of {@link android.graphics.Bitmap#prepareToDraw()} +to asynchronously pre-upload a bitmap before the next sync phase. +
          • +
          + +

          Issuing Commands

          + +

          +The Issue Commands segment represents the time it takes to issue all +of the commands necessary for drawing display lists to the screen. +

          + +

          +For the system to draw display lists to the screen, it sends the +necessary commands to the GPU. Typically, it performs this action through the +OpenGL ES API. +

          + +

          +This process takes some time, as the system performs final transformation +and clipping for each command before sending the command to the GPU. Additional +overhead then arises on the GPU side, which computes the final commands. These +commands include final transformations, and additional clipping. +

          + +

          When this segment is large

          + +

          +The time spent in this stage is a direct measure of the complexity and +quantity of display lists that the system renders in a given +frame. For example, having many draw operations, especially in cases where +there's a small inherent cost to each draw primitive, could inflate this time. +For example: +

          + +
          +for (int i = 0; i < 1000; i++)
          +canvas.drawPoint()
          +
          + +

          +is a lot more expensive to issue than: +

          + +
          +canvas.drawPoints(mThousandPointArray);
          +
          + +

          +There isn’t always a 1:1 correlation between issuing commands and +actually drawing display lists. Unlike Issue Commands, +which captures the time it takes to send drawing commands to the GPU, +the Draw metric represents the time that it took to capture the issued +commands into the display list. +

          + +

          +This difference arises because the display lists are cached by +the system wherever possible. As a result, there are situations where a +scroll, transform, or animation requires the system to re-send a display +list, but not have to actually rebuild it—recapture the drawing +commands—from scratch. As a result, you can see a high “Issue +commands” bar without seeing a high Draw commands bar. +

          + +

          Processing/Swapping Buffers

          + +

          +Once Android finishes submitting all its display list to the GPU, +the system issues one final command to tell the graphics driver that it's +done with the current frame. At this point, the driver can finally present +the updated image to the screen. +

          + +

          When this segment is large

          + +

          +It’s important to understand that the GPU executes work in parallel with the +CPU. The Android system issues draw commands to the GPU, and then moves on to +the next task. The GPU reads those draw commands from a queue and processes +them. +

          + +

          +In situations where the CPU issues commands faster than the GPU +consumes them, the communications queue between the processors can become +full. When this occurs, the CPU blocks, and waits until there is space in the +queue to place the next command. This full-queue state arises often during the +Swap Buffers stage, because at that point, a whole frame’s worth of +commands have been submitted. +

          + +

          +The key to mitigating this problem is to reduce the complexity of work occurring +on the GPU, in similar fashion to what you would do for the “Issue Commands” +phase. +

          + + +

          Miscellaneous

          + +

          +In addition to the time it takes the rendering system to perform its work, +there’s an additional set of work that occurs on the main thread and has +nothing to do with rendering. Time that this work consumes is reported as +misc time. Misc time generally represents work that might be occurring +on the UI thread between two consecutive frames of rendering. +

          + +

          When this segment is large

          + +

          +If this value is high, it is likely that your app has callbacks, intents, or +other work that should be happening on another thread. Tools such as +Method +Tracing or Systrace can provide +visibility into the tasks that are running on +the main thread. This information can help you target performance improvements. +

          diff --git a/docs/html/topic/performance/scheduling.jd b/docs/html/topic/performance/scheduling.jd new file mode 100644 index 0000000000000000000000000000000000000000..c11cf9b4a227b86674291e1bf6fada4d2372e049 --- /dev/null +++ b/docs/html/topic/performance/scheduling.jd @@ -0,0 +1,285 @@ +page.title=Intelligent Job-Scheduling +@jd:body + + + +

          +Modern apps can perform many of their tasks asynchronously, outside the +direct flow of user interaction. Some examples of these asynchronous tasks are: +

          + +
            +
          • Updating network resources.
          • +
          • Downloading information.
          • +
          • Updating background tasks.
          • +
          • Scheduling system service calls.
          • +
          + +

          +Scheduling this work intelligently can improve your app’s performance, +along with aspects of system health such as battery life. {@link android.app.job.JobScheduler} +does this scheduling work for you. +

          + +

          +There are several APIs that your app can use to schedule background work. Chief +among these options is {@link android.app.job.JobScheduler}. +The {@link android.app.job.JobScheduler} API allows you to specify robust +conditions for executing tasks, +along with centralized task scheduling across the device for optimal +system health. {@link android.app.job.JobScheduler} also offers highly +scalable functionality: it is suitable for small tasks like clearing a cache, +and for large ones such as syncing a database to the cloud. +

          + +

          +In addition to {@link android.app.job.JobScheduler}, there are several other +facilities available to help your app schedule work. These include: +

          + + + +

          +This page provides brief introductions to {@link android.app.job.JobScheduler} +and other APIs that can help your app schedule work to maximize app performance +and system health. +

          + +

          Android Framework JobScheduler

          + +

          +{@link android.app.job.JobScheduler} is the Android framework’s native platform +for scheduling tasks or work. It first became available in Android 5.0 (API +level 21), and remains under active development. Notably, Android N (API +level 24) added the ability to trigger jobs based on +{@link android.content.ContentProvider} changes. +

          + +

          +{@link android.app.job.JobScheduler} is implemented in the platform, which +allows it to collect information about jobs that need to run across all apps. +This information is used to schedule jobs to run at, or around, the same time. +Batching job execution in this fashion allows the device to enter and stay in +sleep states longer, preserving battery life. +

          + +

          +You use {@link android.app.job.JobScheduler} by registering jobs, specifying +their requirements for network and timing. The system then gracefully schedules +the jobs to execute at the appropriate times. At the same time, it also defers +job execution as necessary to comply with + +Doze and App Standby restrictions. +{@link android.app.job.JobScheduler} provides many methods to define +job-execution conditions. +

          + +

          +If your app targets Android 5.0 (API level 21), we recommend that you use the +{@link android.app.job.JobScheduler} to execute background tasks. For more +information about {@link android.app.job.JobScheduler}, see its +API-reference +documentation. +

          + +

          AlarmManager

          + +

          +The {@link android.app.AlarmManager} API is another option that the framework +provides for scheduling tasks. This API is useful in cases in which an app +needs to post a notification or set off an alarm at a very specific time. +

          + +

          +You should only use this API for tasks that must execute at a specific time, +but do not require the other, more robust, execution conditions that +{@link android.app.job.JobScheduler} allows you to specify, such as device +idle and charging detect. +

          + +

          +{@link android.app.AlarmManager} does not honor + +Doze and App Standby restrictions; it runs tasks even during + +Doze or App Standby mode. Additionally, +an app running during + +Doze or App Standby mode cannot use the network. +

          + +

          Firebase JobDispatcher

          + +

          + +Firebase JobDispatcher is an open-source library that provides an API similar to +{@link android.app.job.JobScheduler} in the Android platform. + +Firebase JobDispatcher serves as a +{@link android.app.job.JobScheduler}-compatibility layer for apps targeting +versions of Android lower than 5.0 (API level 21). +

          + +

          + +Firebase JobDispatcher supports the use of Google Play services as an +implementation for dispatching (running) jobs, but the library also allows you +to define and use other implementations: For example, you might decide to use +{@link android.app.job.JobScheduler} or write your own, custom code. +Because of this versatility, we recommend that you use this + +Firebase JobDispatcher if your app targets a version of Android lower +than 5.0 (API level 21). +

          + +

          +For more information about + +Firebase JobDispatcher, refer to its + +documentation and source code. +

          + +

          GCM Network Manager

          + +

          +GCM +Network Manager is a compatibility port of the Android +{@link android.app.job.JobScheduler} for apps that support versions of Android +prior to 5.0 (API level 21). This API has all of the same advantages as +{@link android.app.job.JobScheduler}. However, it depends on Google Play +services, which acts like {@link android.app.job.JobScheduler} by taking care +of cross-app job scheduling to improve battery life. This client library is +part of the Google Play services GCM client library, but does not require +that an app use +Google Cloud +Messaging. +

          + +

          +This library is an earlier version of + +Firebase JobDispatcher. Forward development on GCM Network Manager has +stopped; we recommend that you use + +Firebase JobDispatcher going forward. +

          + +

          Additional Facilities

          + +

          +In addition to the APIs and libraries described above, there are also sync +adapters and services that can enable your app, under specific conditions, +to perform better and more robustly. +

          + +

          SyncAdapter

          + +

          +The framework continues to provide the +{@link android.content.AbstractThreadedSyncAdapter SyncAdapter} class for +managing tasks that sync data between the device and a server. Sync adapters are +designed specifically for syncing data between a device and the cloud; you +should only use them for this type of task. Sync adapters are more complex to +implement than the libraries and APIs mentioned above, because they require at +least a fake + +authenticatorand + +content provider implementation. For these reasons, you typically should +not create a sync adapter just to sync data to the cloud in the +background. Wherever possible, you should instead use +{@link android.app.job.JobScheduler}, + +Firebase JobDispatcher, or +GCM +Network Manager . +

          + +

          +In Android N (API level 24), the {@code SyncManager} sits on top of +the {@link android.app.job.JobScheduler}. You should only use the +{@link android.content.AbstractThreadedSyncAdapter SyncAdapter} +class if you require the additional functionality that it provides. +

          + +

          Services

          + +

          +The Services +framework allows you to perform long-running operations in the background. +We recommend foreground services for tasks, such as playing +music, which need to stay resident for the user. Bound services also continue +to be useful for various use cases: for example, when a service needs to +run only when a user is viewing a fragment or activity. +

          + +

          +You should avoid using started services that run perpetually or +perform periodic work, since they continue to use device resources +even when they are not performing useful tasks. Instead, you +should use other solutions that this page describes, +and that provide native lifecycle management. Use started services +only as a last resort. The Android platform may not support +started services in the future. +

          + +

          Additional Points

          + +

          +Regardless of the solution you adopt, keep the following points in mind: +

          + +
            +
          • Captive Internet Portals, VPNs, and proxies can pose + Internet-connectivity detection problems. A library or API may think the + Internet is available, but your service may not be accessible. Fail + gracefully and reschedule as few of your tasks as possible.
          • +
          • Depending on the conditions you assign for running a task, + such as network availability, after the task is triggered, a + change may occur so that those conditions are no longer met. + In such a case, your operation may fail unexpectedly and repeatedly. + For this reason, you + should code your background task logic to notice when tasks are failing + persistently, and perform exponential back-off to avoid + inadvertently over-using resources.
          • + + + +
          • Remember to use exponential backoff when rescheduling any work, + especially when using {@link android.app.AlarmManager}. If your app uses + {@link android.app.job.JobScheduler}, + GCM + Network Manager, + + Firebase JobDispatcher, or sync adapters, exponential backoff is automatically used.
          • +
          diff --git a/docs/html/topic/performance/threads.jd b/docs/html/topic/performance/threads.jd new file mode 100644 index 0000000000000000000000000000000000000000..b2a2d9f44b725314417194645a9195667cd9a8e8 --- /dev/null +++ b/docs/html/topic/performance/threads.jd @@ -0,0 +1,453 @@ +page.title=Threading Performance +@jd:body + + + +

          +Making adept use of threads on Android can help you boost your app’s +performance. This page discusses several aspects of working with threads: +working with the UI, or main, thread; the relationship between app lifecycle and +thread priority; and, methods that the platform provides to help manage thread +complexity. In each of these areas, this page describes potential pitfalls and +strategies for avoiding them. +

          +

          Main Thread

          +

          +When the user launches your app, Android creates a new Linux +process along with an execution thread. This main thread, +also known as the UI thread, is responsible for everything that happens +onscreen. Understanding how it works can help you design your app to use the +main thread for the best possible performance. +

          +

          Internals

          +

          +The main thread has a very simple design: Its only job is to take and execute +blocks of work from a thread-safe work queue until its app is terminated. The +framework generates some of these blocks of work from a variety of places. These +places include callbacks associated with lifecycle information, user events such +as input, or events coming from other apps and processes. In addition, app can +explicitly enqueue blocks on their own, without using the framework. +

          +

          +Nearly any +block of code your app executes is tied to an event callback, such as input, +layout inflation, or draw. When something triggers an event, the thread where the event +happened pushes the event out of itself, and into the main thread’s message +queue. The main thread can then service the event. +

          + +

          +While an animation or screen update is occurring, the system tries to execute a +block of work (which is responsible for drawing the screen) every 16ms or so, in +order to render smoothly at 60 +frames per second. For the system to reach this goal, some operations must +happen on the main thread. However, when the main thread’s messaging queue +contains tasks that are either too numerous or too long for the main thread to +complete work within the 16ms window, the app should move this work to a worker +thread. If the main thread cannot finish executing blocks of work within 16ms, +the user may observe hitching, lagging, or a lack of UI responsiveness to input. +If the main thread blocks for approximately five seconds, the system displays +the Application +Not Responding (ANR) dialog, allowing the user to close the app directly. +

          +

          +Moving numerous or long tasks from the main thread, so that they don’t interfere +with smooth rendering and fast responsiveness to user input, is the biggest +reason for you to adopt threading in your app. +

          +

          Threading and UI Object References

          +

          +By design, Android +UI objects are not thread-safe. An app is expected to create, use, and +destroy UI objects, all on the main thread. If you try to modify +or even reference a UI object in a thread other than the main thread, the result +can be exceptions, silent failures, crashes, and other undefined misbehavior. +

          +

          +Issues with references fall into two distinct categories: explicit references +and implicit references. +

          +

          Explicit references

          +

          +Many tasks on non-main threads have the end goal of updating UI objects. +However, if one of these threads accesses an object in the view hierarchy, +application instability can result: If a worker thread changes the properties of +that object at the same time that any other thread is referencing the object, +the results are undefined. +

          +

          +For example, consider an app that holds a direct reference to a UI object on a +worker thread. The object on the worker thread may contain a reference to a +{@link android.view.View}; but before the work completes, the {@link android.view.View} is +removed from the view hierarchy. When these two actions happen simultaneously, +the reference keeps the {@link android.view.View} object in memory and sets properties on it. +However, the user never sees +this object, and the app deletes the object once the reference to it is gone. +

          + +

          +In another example, {@link android.view.View} objects contain references to the activity +that owns them. If +that activity is destroyed, but there remains a threaded block of work that +references it—directly or indirectly—the garbage collector will not collect +the activity until that block of work finishes executing. +

          +

          +This scenario can cause a problem in situations where threaded work may be in +flight while some activity lifecycle event, such as a screen rotation, occurs. +The system wouldn’t be able to perform garbage collection until the in-flight +work completes. As a result, there may be two {@link android.app.Activity} objects in +memory until garbage collection can take place. +

          + +

          +With scenarios like these, we suggest that your app not include explicit +references to UI objects in threaded work tasks. Avoiding such references helps you avoid +these types of memory leaks, while also steering clear of threading contention. +

          +

          +In all cases, your app should only update UI objects on the main thread. This +means that you should craft a negotiation policy that allows multiple threads to +communicate work back to the main thread, which tasks the topmost activity or +fragment with the work of updating the actual UI object. +

          +

          Implicit references

          +

          +A common code-design flaw with threaded objects can be seen in the snippet of +code below: +

          +
          +public class MainActivity extends Activity {
          +  // …...
          +  public class MyAsyncTask extends AsyncTask   {
          +    @Override protected String doInBackground(Void... params) {...}
          +    @Override protected void onPostExecute(String result) {...}
          +  }
          +}
          +
          +

          +The flaw in this snippet is that the code declares the threading object +{@code MyAsyncTask} as an inner class of some activity. This declaration creates an +implicit reference to the enclosing {@link android.app.Activity} object. +As a result, the object contains a reference to the activity until the +threaded work completes, causing a delay in the destruction of the referenced activity. +This delay, in turn, puts more pressure on memory. +

          +

          +A direct solution to this problem would be to define your overloaded class +instances in their own files, thus removing the implicit reference. +

          +

          +Another solution is to declare the {@link android.os.AsyncTask} object +as a static nested class. Doing so eliminates the implicit reference problem +because of the way a static nested +class differs from an inner class: An instance of an inner class requires an +instance of the outer class to be instantiated, and has direct access to the +methods and fields of its enclosing instance. By contrast, a static nested class +does not require a reference to an instance of enclosing class, so it contains +no references to the outer class members. +

          +
          +public class MainActivity extends Activity {
          +  // …...
          +  Static public class MyAsyncTask extends AsyncTask   {
          +    @Override protected String doInBackground(Void... params) {...}
          +    @Override protected void onPostExecute(String result) {...}
          +  }
          +}
          +
          +

          Threading and App and Activity Lifecycles

          +

          +The app lifecycle can affect how threading works in your application. +You may need to decide that a thread should, or should not, persist after an +activity is destroyed. You should also be aware of the relationship between +thread prioritization and whether an activity is running in the foreground or +background. +

          +

          Persisting threads

          +

          +Threads persist past the lifetime of the activities that spawn them. Threads +continue to execute, uninterrupted, regardless of the creation or destruction of +activities. In some cases, this persistence is undesirable. +

          +

          +Consider a case in which an activity spawns a set of threaded work blocks, and +is then destroyed before a worker thread can execute the blocks. What should the +app do with the blocks that are in flight? +

          + +

          +If the blocks were going to update a UI that no longer exists, there’s no reason +for the work to continue. For example, if the work is to load user information +from a database, and then update views, the thread is no longer necessary. +

          + +

          +By contrast, the work packets may have some benefit not entirely related to the +UI. In this case, you should persist the thread. For example, the packets may be +waiting to download an image, cache it to disk, and update the associated +{@link android.view.View} object. Although the object no longer exists, the acts of downloading and +caching the image may still be helpful, in case the user returns to the +destroyed activity. +

          + +

          +Managing lifecycle responses manually for all threading objects can become +extremely complex. If you don’t manage them correctly, your app can suffer from +memory contention and performance issues. Loaders +are one solution to this problem. A loader facilitates asynchronous loading of +data, while also persisting information through configuration changes. +

          +

          Thread priority

          +

          +As described in Processes +and the Application Lifecycle, the priority that your app’s threads receive +depends partly on where the app is in the app lifecycle. As you create and +manage threads in your application, it’s important to set their priority so that +the right threads get the right priorities at the right times. If set too high, +your thread may interrupt the UI thread and RenderThread, causing your app to +drop frames. If set too low, you can make your async tasks (such as image +loading) slower than they need to be. +

          +

          +Every time you create a thread, you should call +{@link android.os.Process#setThreadPriority(int, int) setThreadPriority()}. +The system’s thread +scheduler gives preference to threads with high priorities, balancing those +priorities with the need to eventually get all the work done. Generally, threads +in the foreground +group get about 95% of the total execution time from the device, while the +background group gets roughly 5%. +

          +

          +The system also assigns each thread its own priority value, using the +{@link android.os.Process} class. +

          +

          +By default, the system sets a thread’s priority to the same priority and group +memberships as the spawning thread. However, your application can explicitly +adjust thread priority by using +{@link android.os.Process#setThreadPriority(int, int) setThreadPriority()}. +

          +

          +The {@link android.os.Process} +class helps reduce complexity in assigning priority values by providing a +set of constants that your app can use to set thread priorities. For example, THREAD_PRIORITY_DEFAULT +represents the default value for a thread. Your app should set the thread's priority to THREAD_PRIORITY_BACKGROUND +for threads that are executing less-urgent work. +

          +

          +Your app can use the THREAD_PRIORITY_LESS_FAVORABLE +and THREAD_PRIORITY_MORE_FAVORABLE +constants as incrementers to set relative priorities. A list of all of these +enumerated states and modifiers appears in the reference documentation for +the {@link android.os.Process#THREAD_PRIORITY_AUDIO} class. + +For more information on +managing threads, see the reference documentation about the +{@link java.lang.Thread} and {@link android.os.Process} classes. +

          +

          +https://developer.android.com/reference/android/os/Process.html#THREAD_PRIORITY_AUDIO +

          +

          Helper Classes for Threading

          +

          +The framework provides the same Java classes & primitives to facilitate +threading, such as the {@link java.lang.Thread} and +{@link java.lang.Runnable} classes. +In order to help reduce the cognitive load associated with +of developing threaded applications for +Android, the framework provides a set of helpers which can aide in development. +Each helper class has a specific set of performance nuances that make them +unique for a specific subset of threading problems. Using the wrong class for +the wrong situation can lead to performance issues. +

          +

          The AsyncTask class

          +

          + +The {@link android.os.AsyncTask} class +is a simple, useful primitive for apps that need to quickly move work from the +main thread onto worker threads. For example, an input event might trigger the +need to update the UI with a loaded bitmap. An {@link android.os.AsyncTask} +object can offload the +bitmap loading and decoding to an alternate thread; once that processing is +complete, the {@link android.os.AsyncTask} object can manage receiving the work +back on the main thread to update the UI. +

          +

          +When using {@link android.os.AsyncTask}, there are a few important performance +aspects to keep in +mind. First, by default, an app pushes all of the {@link android.os.AsyncTask} +objects it creates into a +single thread. Therefore, they execute in serial fashion, and—as with the +main +thread—an especially long work packet can block the queue. For this reason, +we suggest that you only use {@link android.os.AsyncTask} to handle work items +shorter than 5ms in duration. +

          +

          +{@link android.os.AsyncTask} objects are also the most common offenders +for implicit-reference issues. +{@link android.os.AsyncTask} objects present risks related to explicit +references, as well, but these are +sometimes easier to work around. For example, an {@link android.os.AsyncTask} +may require a reference to a UI object in order to update the UI object +properly once {@link android.os.AsyncTask} executes its callbacks on the +main thread. In such a situation, you +can use a {@link java.lang.ref.WeakReference} +to store a reference to the required UI object, and access the object once the +{@link android.os.AsyncTask} is operating on the main thread. To be clear, +holding a {@link java.lang.ref.WeakReference} +to an object does not make the object thread-safe; the +{@link java.lang.ref.WeakReference} merely +provides a method to handle issues with explicit references and garbage +collection. +

          +

          The HandlerThread class

          +

          +While an {@link android.os.AsyncTask} +is useful, +it may not always be the right solution to your threading problem. Instead, +you may need a more traditional approach to executing a block of work on a +longer running thread, and some ability to manage that workflow manually. +

          + +

          +Consider a common challenge with getting preview frames from your +{@link android.hardware.Camera} object. + When you register for Camera preview frames, you receive them in the + {@link android.hardware.Camera.PreviewCallback#onPreviewFrame(byte[], android.hardware.Camera) onPreviewFrame()} +callback, which is invoked on the event thread it was called from. If this +callback were invoked on the UI thread, the task of dealing with the huge pixel +arrays would be interfering with rendering and event processing work. The same +problem applies to {@link android.os.AsyncTask}, which also executes jobs serially and is +susceptible to blocking. +

          +

          +This is a situation where a handler thread would be appropriate: A handler thread +is effectively a long-running thread that grabs work from a queue, and operates +on it. In this example, when your app delegates the +{@link android.hardware.Camera#open Camera.open()} command to a +block of work on the handler thread, the associated + {@link android.hardware.Camera.PreviewCallback#onPreviewFrame(byte[], android.hardware.Camera) onPreviewFrame()} +callback +lands on the handler thread, rather than the UI or {@link android.os.AsyncTask} +threads. So, if you’re going to be doing long-running work on the pixels, this +may be a better solution for you. +

          +

          +When your app creates a thread using {@link android.os.HandlerThread}, don’t +forget to set the thread’s + +priority based on the type of work it’s doing. Remember, CPUs can only +handle a small number of threads in parallel. Setting the priority helps +the system know the right ways to schedule this work when all other threads +are fighting for attention. +

          +

          The ThreadPoolExecutor class

          +

          +There are certain types of work that can be reduced to highly parallel, +distributed tasks. One such task, for example, is calculating a filter for each +8x8 block of an 8 megapixel image. With the sheer volume of work packets this +creates, +{@code AsyncTask} and {@code HandlerThread} aren’t appropriate +classes. The single-threaded nature of {@link android.os.AsyncTask} would +turn all the threadpooled work into a linear system. +Using the {@link android.os.HandlerThread} class, on the other hand, would +require the programmer to manually manage load balancing between a group of +threads. +

          + +

          +{@link java.util.concurrent.ThreadPoolExecutor} is a helper class to make +this process easier. This class manages the creation of a group of threads, sets +their priorities, and manages how work is distributed among those threads. +As workload increases or decreases, the class spins up or destroys more threads +to adjust to the workload. +

          +

          +This class also helps your app spawn an optimum number of threads. When it +constructs a {@link java.util.concurrent.ThreadPoolExecutor} +object, the app sets a minimum and maximum +number of threads. As the workload given to the +{@link java.util.concurrent.ThreadPoolExecutor} increases, +the class will take the initialized minimum and maximum thread counts into +account, and consider the amount of pending work there is to do. Based on these +factors, {@link java.util.concurrent.ThreadPoolExecutor} decides on how many +threads should be alive at any given time. +

          +

          How many threads should you create?

          +

          +Although from a software level, your code has the ability to create hundreds of +threads, doing so can create performance issues. CPUs really only have the +ability to handle a small number of threads in parallel; everything above that +runs +into priority and scheduling issues. As such, it’s important to only create +as many threads as your workload needs. +

          +

          +Practically speaking, there’s a number of variables responsible for this, but +picking a value (like 4, for starters), and testing it with Systrace is as +solid a strategy as any other. You can use trial-and-error to discover the +minimum number of threads you can use without running into problems. +

          +

          +Another consideration in deciding on how many threads to have is that threads +aren’t free: they take up memory. Each thread costs a minimum of 64k of memory. +This adds up quickly across the many apps installed on a device, especially in +situations where the call stacks grow significantly. +

          +

          +Many system processes and third-party libraries often spin up their own +threadpools. If your app can reuse an existing threadpool, this reuse may help +performance by reducing contention for memory and processing resources. +

          + + diff --git a/docs/html/training/_book.yaml b/docs/html/training/_book.yaml index 00f9295b05f73372cbac175ffd4a2b2b7df2c2d3..47862e2402542fe21595e4ae9c2376f21fc5ecbe 100644 --- a/docs/html/training/_book.yaml +++ b/docs/html/training/_book.yaml @@ -420,6 +420,8 @@ toc: path: /training/basics/network-ops/connecting.html - title: Managing Network Usage path: /training/basics/network-ops/managing.html + - title: Optimizing Network Data Usage + path: /training/basics/network-ops/data-saver.html - title: Parsing XML Data path: /training/basics/network-ops/xml.html - title: Transferring Data Without Draining the Battery @@ -436,16 +438,6 @@ toc: path: /training/efficient-downloads/redundant_redundant.html - title: Modifying Patterns Based on the Connectivity Type path: /training/efficient-downloads/connectivity_patterns.html - - title: Syncing to the Cloud - path: /training/backup/index.html - path_attributes: - - name: description - value: How to sync and back up app and user data to remote web services in the cloud and how to restore the data back to multiple devices. - section: - - title: Configuring Auto Backup - path: /training/backup/autosyncapi.html - - title: Using the Backup API - path: /training/backup/backupapi.html - title: Resolving Cloud Save Conflicts path: /training/cloudsave/conflict-res.html path_attributes: @@ -693,8 +685,12 @@ toc: value: 再生中カードを表示する - title: Adding a Guided Step path: /training/tv/playback/guided-step.html + - title: Introducing First-time Users to Your App + path: /training/tv/playback/onboarding.html - title: Enabling Background Playback path: /training/tv/playback/options.html + - title: Adding Picture-in-picture + path: /training/tv/playback/picture-in-picture.html - title: Helping Users Find Content on TV path: /training/tv/discovery/index.html path_attributes: @@ -724,6 +720,8 @@ toc: path: /training/tv/tif/channel.html - title: Managing User Interaction path: /training/tv/tif/ui.html + - title: Supporting Content Recording + path: /training/tv/tif/content-recording.html - title: TV Apps Checklist path: /training/tv/publishing/checklist.html path_attributes: @@ -892,6 +890,11 @@ toc: value: 順応性のある UI フローの実装 - name: zh-cn-lang value: 实施自适应用户界面流程 + - title: Build a Responsive UI with ConstraintLayout + path: /training/constraint-layout/index.html + path_attributes: + - name: description + value: How to build a layout using ConstraintLayout and the Android Studio Layout Editor. - title: Adding the App Bar path: /training/appbar/index.html path_attributes: @@ -1143,6 +1146,8 @@ toc: value: 维护兼容性 - name: zh-tw-lang value: 維持相容性 + - title: Selecting Colors with the Palette API + path: /training/material/palette-colors.html - title: Best Practices for User Input path: /training/best-user-input.html @@ -1227,15 +1232,9 @@ toc: path: /training/scheduling/wakelock.html - title: Scheduling Repeating Alarms path: /training/scheduling/alarms.html - - title: Best Practices for Performance path: /training/best-performance.html section: - - title: Managing Your App's Memory - path: /training/articles/memory.html - path_attributes: - - name: description - value: How to keep your app's memory footprint small in order to improve performance on a variety of mobile devices. - title: Performance Tips path: /training/articles/perf-tips.html path_attributes: @@ -1267,23 +1266,6 @@ toc: - name: description value: How to minimize the amount of power your app requires by adapting to current power conditions and performing power-hungry tasks at proper intervals. section: - - title: Reducing Network Battery Drain - path: /training/performance/battery/network/index.html - section: - - title: Collecting Network Traffic Data - path: /training/performance/battery/network/gather-data.html - - title: Analyzing Network Traffic Data - path: /training/performance/battery/network/analyze-data.html - - title: Optimizing User-Initiated Network Use - path: /training/performance/battery/network/action-user-traffic.html - - title: Optimizing App-Initiated Network Use - path: /training/performance/battery/network/action-app-traffic.html - - title: Optimizing Server-Initiated Network Use - path: /training/performance/battery/network/action-server-traffic.html - - title: Optimizing General Network Use - path: /training/performance/battery/network/action-any-traffic.html - - title: Optimizing for Doze and App Standby - path: /training/monitoring-device-state/doze-standby.html - title: Monitoring the Battery Level and Charging State path: /training/monitoring-device-state/battery-monitoring.html path_attributes: @@ -1363,6 +1345,11 @@ toc: path_attributes: - name: description value: How to ensure that your app is secure when performing network transactions. + - title: Network Security Configuration + path: /training/articles/security-config.html + path_attributes: + - name: description + value: Customize the behavior of your app's secure network connections safely. - title: Updating Your Security Provider to Protect Against SSL Exploits path: /training/articles/security-gms-provider.html path_attributes: @@ -1373,11 +1360,31 @@ toc: path_attributes: - name: description value: How to use the SafetyNet service to analyze a device where your app is running and get information about its compatibility with your app. + - title: Checking URLs with the Safe Browsing API + path: /training/safebrowsing/index.html + path_attributes: + - name: description + value: How to use the SafetyNet service to determine if a URL is designated as a known threat. + - title: Verifying Hardware-backed Key Pairs with Key Attestation + path: /training/articles/security-key-attestation.html + path_attributes: + - name: description + value: How to retrieve and verify the properties of a device's hardware-backed key pair. - title: Enhancing Security with Device Management Policies path: /work/device-management-policy.html path_attributes: - name: description value: How to create an application that enforces security policies on devices. + - title: Supporting Direct Boot + path: /training/articles/direct-boot.html + path_attributes: + - name: description + value: How use device encrypted storage during Direct Boot mode. + - title: Using Scoped Directory Access + path: /training/articles/scoped-directory-access.html + path_attributes: + - name: description + value: How to use scoped directory access to request access to external storage directories. - title: Best Practices for Permissions & Identifiers path: /training/best-permissions-ids.html diff --git a/docs/html/training/_project.yaml b/docs/html/training/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6aa8760644dc8b831066fc722200dd203d14e80a --- /dev/null +++ b/docs/html/training/_project.yaml @@ -0,0 +1,6 @@ +name: "Training" +home_url: /training/ +description: "Android Training provides a collection of classes that aim to help you build great apps for Android." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /develop/_project.yaml diff --git a/docs/html/training/accessibility/accessible-app.jd b/docs/html/training/accessibility/accessible-app.jd index dd26febf094922078438c430a35a72cef6a6c865..54c185c5052967bcf749e4ec5c5926f22f1f17b5 100644 --- a/docs/html/training/accessibility/accessible-app.jd +++ b/docs/html/training/accessibility/accessible-app.jd @@ -55,7 +55,7 @@ href="https://play.google.com/store/apps/details?id=com.google.android.marvin.ta If you have a label that's likely not to change during the lifecycle of the application (such as "Pause" or "Purchase"), you can add it via the XML layout, by setting a UI element's {@code android:contentDescription} attribute, like in this example:

          @@ -163,7 +163,7 @@ supported can be found in the {@link android.view.accessibility.AccessibilityEvent} reference documentation.

          As an example, if you want to extend an image view such that you can write -captions by typing on the keyboard when it has focus, it makes sense to fire an +captions by typing on the keyboard when it has focus, it makes sense to fire an {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} event, even though that's not normally built into image views. The code to generate that event would look like this:

          diff --git a/docs/html/training/accessibility/service.jd b/docs/html/training/accessibility/service.jd index 5b99c46be67e8de9aacaa904e2cfa6e71efe67f6..c034145161050b5286a23567ea218dd97be0fe00 100755 --- a/docs/html/training/accessibility/service.jd +++ b/docs/html/training/accessibility/service.jd @@ -17,7 +17,7 @@ previous.link=accessible-app.html
        • Create Your Accessibility Service
        • Configure Your Accessibility Service
        • Respond to AccessibilityEvents
        • -
        • Query the View Heirarchy for More Context
        • +
        • Query the View Hierarchy for More Context

      You should also read

      @@ -67,7 +67,7 @@ public class MyAccessibilityService extends AccessibilityService {

      Like any other service, you also declare it in the manifest file. Remember to specify that it handles the {@code android.accessibilityservice} intent, -so that the service is called when applications fire an +so that the service is called when applications fire an {@link android.view.accessibility.AccessibilityEvent}.

      @@ -200,7 +200,7 @@ public void onAccessibilityEvent(AccessibilityEvent event) {
       }
       
      -

      Query the View Heirarchy for More Context

      +

      Query the View Hierarchy for More Context

      This step is optional, but highly useful. The Android platform provides the ability for an {@link android.accessibilityservice.AccessibilityService} to query the view hierarchy, collecting information about the UI component that generated an event, and diff --git a/docs/html/training/animation/screen-slide.jd b/docs/html/training/animation/screen-slide.jd index a68d475f18ee40740dc7f6425b3616004eaaeb16..d953c0793f9756ec266dde59faa54069420f3e12 100644 --- a/docs/html/training/animation/screen-slide.jd +++ b/docs/html/training/animation/screen-slide.jd @@ -218,7 +218,7 @@ public class ScreenSlidePagerActivity extends FragmentActivity { position of the page on the screen, which is obtained from the position parameter of the {@link android.support.v4.view.ViewPager.PageTransformer#transformPage transformPage()} method.

      -

      The position parameter indicates where a given page is located relative to the center of the screen. +

      The position parameter indicates where a given page is located relative to the center of the screen. It is a dynamic property that changes as the user scrolls through the pages. When a page fills the screen, its position value is 0. When a page is drawn just off the right side of the screen, its position value is 1. If the user scrolls halfway between pages one and two, page one has a position of -0.5 and page two has a position of 0.5. Based on the position of the pages on the screen, you can create custom slide animations by setting page properties with methods such as {@link android.view.View#setAlpha setAlpha()}, {@link android.view.View#setTranslationX setTranslationX()}, or {@link android.view.View#setScaleY setScaleY()}.

      diff --git a/docs/html/training/animation/zoom.jd b/docs/html/training/animation/zoom.jd index 6a38e7d8c71d4e2249f6bc22712ea207bcf99d19..60de70e8c02ce3e2f9bbf3370791f6b3d3aa80d1 100644 --- a/docs/html/training/animation/zoom.jd +++ b/docs/html/training/animation/zoom.jd @@ -297,13 +297,13 @@ private void zoomImageFromThumb(final View thumbView, int imageResId) { set.play(ObjectAnimator .ofFloat(expandedImageView, View.X, startBounds.left)) .with(ObjectAnimator - .ofFloat(expandedImageView, + .ofFloat(expandedImageView, View.Y,startBounds.top)) .with(ObjectAnimator - .ofFloat(expandedImageView, + .ofFloat(expandedImageView, View.SCALE_X, startScaleFinal)) .with(ObjectAnimator - .ofFloat(expandedImageView, + .ofFloat(expandedImageView, View.SCALE_Y, startScaleFinal)); set.setDuration(mShortAnimationDuration); set.setInterpolator(new DecelerateInterpolator()); diff --git a/docs/html/training/app-indexing/deep-linking.jd b/docs/html/training/app-indexing/deep-linking.jd index 2c4a1310fbf1ea8e31a8007770cbde670e2c1059..a68e5a3cc4c125e1e9a73b2c9a440ffed736b813 100644 --- a/docs/html/training/app-indexing/deep-linking.jd +++ b/docs/html/training/app-indexing/deep-linking.jd @@ -69,7 +69,7 @@ in your manifest for deep linking. The URIs {@code “example://gizmos”} and <!-- Accepts URIs that begin with "example://gizmos” --> <data android:scheme="example" android:host="gizmos" /> - + </intent-filter> </activity> diff --git a/docs/html/training/articles/assistant.jd b/docs/html/training/articles/assistant.jd index a1fbd6ba1634be3cf05697113bb3284aeb896bcf..703b3778a27536738701bfd11352e757e31dd8f1 100644 --- a/docs/html/training/articles/assistant.jd +++ b/docs/html/training/articles/assistant.jd @@ -11,110 +11,92 @@ page.article=true

    Android 6.0 Marshmallow introduces a new way for users to engage with apps - through the assistant. -

    + through the assistant. The assistant is a top-level window that users can view to obtain + contextually relevant actions for the current activity. These actions might include deep links + to other apps on the device.

    - Users summon the assistant with a long-press on the Home button or by saying - the {@link android.service.voice.AlwaysOnHotwordDetector keyphrase}. In - response to the long-press, the system opens a top-level window that displays - contextually relevant actions for the current activity. These potential - actions might include deep links to other apps on the device. + Users activate the assistant with a long press on the Home button or by saying a + keyphrase. + In response, the system opens a top-level window that displays contextually + relevant actions.

    - This guide explains how Android apps use Android's Assist API to improve the - assistant user experience. + Google App implements the assistant overlay window through a feature called + Now on Tap, which works with the Android platform-level functionality. The system allows + the user to select an assistant app, which obtains contextual information from your app + using Android’s Assist API.

    - - -

    Using the Assist API

    -

    - The example below shows how Google Now integrates with the Android assistant - using a feature called Now on Tap. + This guide explains how Android apps use Android's Assist API to improve the assistant + user experience. +

    + +

    Using the Assistant

    +

    - The assistant overlay window in our example (2, 3) is implemented by Google - Now through a feature called Now on Tap, which works in concert with the - Android platform-level functionality. The system allows the user to select - the assistant app (Figure 2) that obtains contextual information from the - source app using the Assist API which is a part of the platform. + Figure 1 illustrates a typical user interaction with the assistant. When the user long-presses + the Home button, the Assist API callbacks are invoked + in the source app (step 1). The assistant renders the overlay window (steps 2 and 3), + and then the user selects the action to perform. The assistant executes the selected action, + such as firing an intent with a deep link to the (destination) restaurant app (step 4).

    -

    Figure 1. Assistant interaction example with the Now on Tap feature of - Google Now + the Google App

    - An Android user first configures the assistant and can change system options - such as using text and view hierarchy as well as the screenshot of the - current screen (Figure 2). -

    - -

    - From there, the assistant receives the information only when the user - activates assistance, such as when they tap and hold the Home button ( shown - in Figure 1, step 1). + Users can configure the assistant by selecting Settings > Apps > Default Apps > + Assist & voice input. Users can change system options such as accessing + the screen contents as text and accessing a screenshot, as shown in Figure 2.

    -
    +

    - Figure 2. Assist & voice input settings (Settings/Apps/Default - Apps/Assist & voice input) + Figure 2. Assist & voice input settings

    -

    Assist API Lifecycle

    - -

    - Going back to our example from Figure 1, the Assist API callbacks are invoked - in the source app after step 1 (user long-presses the Home button) - and before step 2 (the assistant renders the overlay window). Once the user - selects the action to perform (step 3), the assistant executes it, for - example by firing an intent with a deep link to the (destination) - restaurant app (step 4). -

    - -

    Source App

    +

    Source app

    - In most cases, your app does not need to do anything extra to integrate with - the assistant if you already follow accessibility best practices. This section describes how to provide additional information - to help improve the assistant user experience, as well as scenarios, such as - custom Views, that need special handling. + to help improve the assistant user experience as well as scenarios + that need special handling, such as custom Views.

    - -

    Share Additional Information with the Assistant

    +

    Share additional information + with the assistant

    In addition to the text and the screenshot, your app can share - additional information with the assistant. For example, your music - app can choose to pass current album information, so that the assistant can + other information with the assistant. For example, your music + app can choose to pass current album information so that the assistant can suggest smarter actions tailored to the current activity.

    @@ -122,13 +104,13 @@ page.article=true To provide additional information to the assistant, your app provides global application context by registering an app listener and supplies activity-specific information with activity callbacks as shown in - Figure 3. + Figure 3:

    - Figure 3. Assist API lifecycle sequence diagram. + Figure 3. Assist API lifecycle sequence diagram

    @@ -136,43 +118,42 @@ page.article=true To provide global application context, the app creates an implementation of {@link android.app.Application.OnProvideAssistDataListener} and registers it using {@link - android.app.Application#registerOnProvideAssistDataListener(android.app.Application.OnProvideAssistDataListener)}. - In order to provide activity-specific contextual information, activity - overrides {@link android.app.Activity#onProvideAssistData(android.os.Bundle)} + android.app.Application#registerOnProvideAssistDataListener(android.app.Application.OnProvideAssistDataListener) registerOnProvideAssistDataListener()}. + To provide activity-specific contextual information, the activity + overrides {@link android.app.Activity#onProvideAssistData(android.os.Bundle) onProvideAssistData()} and {@link - android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent)}. + android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent) onProvideAssistContent()}. The two activity methods are called after the optional global - callback (registered with {@link - android.app.Application#registerOnProvideAssistDataListener(android.app.Application.OnProvideAssistDataListener)}) - is invoked. Since the callbacks execute on the main thread, they should + callback is invoked. Because the callbacks execute on the main thread, they should complete promptly. The callbacks are invoked only when the activity is running.

    -
    Providing Context
    +
    Providing context

    - {@link android.app.Activity#onProvideAssistData(android.os.Bundle)} is called - when the user is requesting the assistant to build a full {@link + When the user activates the assistant, + {@link android.app.Activity#onProvideAssistData(android.os.Bundle) onProvideAssistData()} is called to build a full + {@link android.content.Intent#ACTION_ASSIST} Intent with all of the context of the current application represented as an instance of the {@link android.app.assist.AssistStructure}. You can override this method to place - into the bundle anything you would like to appear in the - EXTRA_ASSIST_CONTEXT part of the assist Intent. + anything you like into the bundle to appear in the + {@link android.content.Intent#EXTRA_ASSIST_CONTEXT} part of the assist intent.

    -
    Describing Content
    +
    Describing content

    Your app can implement {@link - android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent)} - to improve assistant user experience by providing references to content + android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent) onProvideAssistContent()} + to improve the assistant user experience by providing content-related references related to the current activity. You can describe the app content using the - common vocabulary defined by Schema.org + common vocabulary defined by Schema.org through a JSON-LD object. In the example below, a music app provides - structured data to describe the music album the user is currently - looking at. + structured data to describe the music album that the user is currently + viewing:

    @@ -191,127 +172,158 @@ public void onProvideAssistContent(AssistContent assistContent)
     

    - Custom implementations of {@link - android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent)} - may also adjust the provided {@link - android.app.assist.AssistContent#setIntent(android.content.Intent) content - intent} to better reflect the top-level context of the activity, supply - {@link android.app.assist.AssistContent#setWebUri(android.net.Uri) the URI} - of the displayed content, and fill in its {@link - android.app.assist.AssistContent#setClipData(android.content.ClipData)} with - additional content of interest that the user is currently viewing. + You can also improve the user experience with custom implementations of + {@link + android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent) onProvideAssistContent()}, + which can provide the following benefits: +

    +
      +
    • + Adjusts the provided content + intent to + better reflect the top-level context of the activity.
    • +
    • + Supplies the URI + of the displayed content.
    • +
    • Fills in {@link + android.app.assist.AssistContent#setClipData(android.content.ClipData) setClipData()} with additional + content of interest that the user is currently viewing.
    • +
    +

    + Note: Apps that use a custom text selection implementation likely need + to implement {@link + android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent) onProvideAssistContent()} + and call {@link android.app.assist.AssistContent#setClipData(android.content.ClipData) setClipData()}.

    -

    Default Implementation

    +

    Default implementation

    - If neither {@link - android.app.Activity#onProvideAssistData(android.os.Bundle)} nor {@link - android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent)} - callbacks are implemented, the system will still proceed and pass the - information collected automatically to the assistant unless the current + If neither the {@link + android.app.Activity#onProvideAssistData(android.os.Bundle) onProvideAssistData()} nor the {@link + android.app.Activity#onProvideAssistContent(android.app.assist.AssistContent) onProvideAssistContent()} + callback is implemented, the system still proceeds and passes the + automatically collected information to the assistant unless the current window is flagged as secure. As shown in Figure 3, the system uses the default implementations of {@link - android.view.View#onProvideStructure(android.view.ViewStructure)} and {@link - android.view.View#onProvideVirtualStructure(android.view.ViewStructure)} to + android.view.View#onProvideStructure(android.view.ViewStructure) onProvideStructure()} and {@link + android.view.View#onProvideVirtualStructure(android.view.ViewStructure) onProvideVirtualStructure()} to collect text and view hierarchy information. If your view implements custom - text drawing, you should override {@link - android.view.View#onProvideStructure(android.view.ViewStructure)} to provide + text drawing, override {@link + android.view.View#onProvideStructure(android.view.ViewStructure) onProvideStructure()} to provide the assistant with the text shown to the user by calling {@link - android.view.ViewStructure#setText(java.lang.CharSequence)}. + android.view.ViewStructure#setText(java.lang.CharSequence) setText(CharSequence)}.

    - In most cases, implementing accessibility support will enable the - assistant to obtain the information it needs. This includes - providing {@link android.R.attr#contentDescription - android:contentDescription} attributes, populating {@link - android.view.accessibility.AccessibilityNodeInfo} for custom views, making - sure custom {@link android.view.ViewGroup ViewGroups} correctly {@link - android.view.ViewGroup#getChildAt(int) expose} their children, and following - the best practices described in “Making Applications - Accessible”. -

    + In most cases, implementing accessibility support enables the + assistant to obtain the information it needs. To implement accessibility support, + observe the best practices described in Making Applications + Accessible, including the following:

    + +
      +
    • Provide {@link android.R.attr#contentDescription + android:contentDescription} attributes.
    • +
    • Populate {@link + android.view.accessibility.AccessibilityNodeInfo} for custom views.
    • +
    • Make + sure that custom {@link android.view.ViewGroup ViewGroup} objects correctly + expose + their children.
    • +

    Excluding views from the assistant

    - An activity can exclude the current view from the assistant. This is accomplished + To handle sensitive information, your app can exclude the current view from the assistant by setting the {@link android.view.WindowManager.LayoutParams#FLAG_SECURE - FLAG_SECURE} layout parameter of the WindowManager and must be done - explicitly for every window created by the activity, including Dialogs. Your - app can also use {@link android.view.SurfaceView#setSecure(boolean) - SurfaceView.setSecure} to exclude a surface from the assistant. There is no + FLAG_SECURE} layout parameter of the {@link android.view.WindowManager}. You must set {@link + android.view.WindowManager.LayoutParams#FLAG_SECURE + FLAG_SECURE} explicitly for + every window created by the activity, including dialogs. Your app can also use + {@link android.view.SurfaceView#setSecure(boolean) setSecure()} to exclude + a surface from the assistant. There is no global (app-level) mechanism to exclude all views from the assistant. Note - that FLAG_SECURE does not cause the Assist API callbacks to stop - firing. The activity which uses FLAG_SECURE can still explicitly + that {@link android.view.WindowManager.LayoutParams#FLAG_SECURE + FLAG_SECURE} does not cause the Assist API callbacks to stop + firing. The activity that uses {@link android.view.WindowManager.LayoutParams#FLAG_SECURE + FLAG_SECURE} can still explicitly provide information to the assistant using the callbacks described earlier this guide.

    -

    Voice Interactions

    +

    Note: For enterprise accounts (Android for Work), + the administrator can disable + the collection of assistant data for the work profile by using the {@link + android.app.admin.DevicePolicyManager#setScreenCaptureDisabled(android.content.ComponentName, boolean) + setScreenCaptureDisabled()} method of the {@link android.app.admin.DevicePolicyManager} API.

    + +

    Voice interactions

    - Assist API callbacks are also invoked upon {@link - android.service.voice.AlwaysOnHotwordDetector keyphrase detection}. For more - information see the voice - actions documentation. + Assist API callbacks are also invoked upon + keyphrase + detection. For more information, see the + Voice + Actions documentation.

    Z-order considerations

    The assistant uses a lightweight overlay window displayed on top of the - current activity. The assistant can be summoned by the user at any time. - Therefore, apps should not create permanent {@link - android.Manifest.permission#SYSTEM_ALERT_WINDOW system alert} - windows interfering with the overlay window shown in Figure 4. + current activity. Because the user can activate the assistant at any time, + don't create permanent + system alert windows that interfere with the overlay window, as shown in + Figure 4.

    - Figure 4. Assist layer Z-order. + Figure 4. Assist layer Z-order

    - If your app uses {@link - android.Manifest.permission#SYSTEM_ALERT_WINDOW system alert} windows, it - must promptly remove them as leaving them on the screen will degrade user - experience and annoy the users. + If your app uses + system alert windows, remove them promptly because leaving them on the + screen degrades the user experience.

    -

    Destination App

    +

    Destination app

    - The matching between the current user context and potential actions displayed - in the overlay window (shown in step 3 in Figure 1) is specific to the - assistant’s implementation. However, consider adding deep linking support - to your app. The assistant will typically take advantage of deep linking. For - example, Google Now uses deep linking and App Indexing in order to + The assistant typically takes advantage of deep linking to find destination apps. To make your + app a potential destination app, consider adding deep linking support. The matching + between the current user context and deep links or other potential actions displayed in the + overlay window (shown in step 3 in Figure 1) is specific to the assistant’s implementation. + For + example, the Google App uses deep linking and Firebase App Indexing in order to drive traffic to destination apps.

    -

    Implementing your own assistant

    +

    Implementing Your Own Assistant

    - Some developers may wish to implement their own assistant. As shown in Figure - 2, the active assistant app can be selected by the Android user. The + You may wish to implement your own assistant. As shown in Figure + 2, the user can select the active assistant app. The assistant app must provide an implementation of {@link android.service.voice.VoiceInteractionSessionService} and {@link android.service.voice.VoiceInteractionSession} as shown in - this example and it requires the {@link - android.Manifest.permission#BIND_VOICE_INTERACTION} permission. It can then + "https://android.googlesource.com/platform/frameworks/base/+/marshmallow-release/tests/VoiceInteraction/" class="external-link"> + this VoiceInteraction example. It also requires the {@link + android.Manifest.permission#BIND_VOICE_INTERACTION} permission. The assistant can then receive the text and view hierarchy represented as an instance of the {@link android.app.assist.AssistStructure} in {@link android.service.voice.VoiceInteractionSession#onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure,android.app.assist.AssistContent) onHandleAssist()}. - The assistant receives the screenshot through {@link + It receives the screenshot through {@link android.service.voice.VoiceInteractionSession#onHandleScreenshot(android.graphics.Bitmap) onHandleScreenshot()}.

    diff --git a/docs/html/preview/features/direct-boot.jd b/docs/html/training/articles/direct-boot.jd similarity index 71% rename from docs/html/preview/features/direct-boot.jd rename to docs/html/training/articles/direct-boot.jd index 8351f4b4b10fe233ec3f6a573270d79b9af1000f..ea2686e0a055bce6454277db1013acddeebc3071 100644 --- a/docs/html/preview/features/direct-boot.jd +++ b/docs/html/training/articles/direct-boot.jd @@ -1,12 +1,10 @@ -page.title=Direct Boot -page.keywords=preview,sdk,direct boot -page.tags=androidn -page.image=images/cards/card-nyc_2x.jpg +page.title=Supporting Direct Boot +page.keywords=direct boot @jd:body -
    -
    + -

    Android N runs in a secure, Direct Boot mode +

    Android 7.0 runs in a secure, Direct Boot mode when the device has been powered on but the user has not unlocked the device. To support this, the system provides two storage locations for data:

    @@ -62,21 +61,23 @@ storage. Apps register with the system by marking components as android:directBootAware attribute to true in your manifest.

    Encryption aware components can register to receive a -LOCKED_BOOT_COMPLETED broadcast message from the +{@link android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED +ACTION_LOCKED_BOOT_COMPLETED} broadcast message from the system when the device has been restarted. At this point device encrypted storage is available, and your component can execute tasks that need to be run during Direct Boot mode, such as triggering a scheduled alarm.

    The following code snippet is an example of how to register a {@link android.content.BroadcastReceiver} as encryption aware, and add an -intent filter for LOCKED_BOOT_COMPLETED, in the app manifest:

    +intent filter for {@link android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED +ACTION_LOCKED_BOOT_COMPLETED}, in the app manifest:

     <receiver
       android:directBootAware="true" >
       ...
       <intent-filter>
    -    <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
    +    <action android:name="android.intent.action.ACTION_LOCKED_BOOT_COMPLETED" />
       </intent-filter>
     </receiver>
     
    @@ -88,7 +89,8 @@ device encrypted storage as well as credential encrypted storage.

    To access device encrypted storage, create a second {@link android.content.Context} instance by calling -Context.createDeviceProtectedStorageContext(). All storage API +{@link android.content.Context#createDeviceProtectedStorageContext +Context.createDeviceProtectedStorageContext()}. All storage API calls made using this context access the device encrypted storage. The following example accesses the device encrypted storage and opens an existing app data file:

    @@ -119,7 +121,8 @@ after boot:

    • If your app has foreground processes that need immediate notification, -listen for the {@code ACTION_USER_UNLOCKED} message.
    • +listen for the {@link android.content.Intent#ACTION_USER_UNLOCKED +ACTION_USER_UNLOCKED} message.
    • If your app only uses background processes that can act on a delayed notification, listen for the {@link android.content.Intent#ACTION_BOOT_COMPLETED ACTION_BOOT_COMPLETED} @@ -127,14 +130,17 @@ message.

    If the user has unlocked the device, you can find out by calling -UserManager.isUserUnlocked().

    +{@link android.os.UserManager#isUserUnlocked UserManager.isUserUnlocked()}. +

    Migrating Existing Data

    If a user updates their device to use Direct Boot mode, you might have existing data that needs to get migrated to device encrypted storage. Use -Context.moveSharedPreferencesFrom() and -Context.moveDatabaseFrom() to migrate preference and database +{@link android.content.Context#moveSharedPreferencesFrom +Context.moveSharedPreferencesFrom()} and +{@link android.content.Context#moveDatabaseFrom +Context.moveDatabaseFrom()} to migrate preference and database data between credential encrypted storage and device encrypted storage.

    Use your best judgment when deciding what data to migrate from credential @@ -145,13 +151,13 @@ separate sets of data in the two encrypted stores.

    Testing Your Encryption Aware App

    -

    Test your encryption aware app using the new Direct Boot mode. There are +

    Test your encryption aware app with Direct Boot mode enabled. There are two ways to enable Direct Boot.

    Caution: Enabling Direct Boot wipes all user data on the device.

    -

    On supported devices with Android N installed, enable +

    On supported devices with Android 7.0 installed, enable Direct Boot by doing one of the following:

      @@ -186,3 +192,34 @@ $ adb shell sm set-emulate-fbe false

      Using these commands causes the device to reboot.

      + +

      Checking Device Policy Encryption Status

      + +

      Device administration apps can use +{@link android.app.admin.DevicePolicyManager#getStorageEncryptionStatus +DevicePolicyManager.getStorageEncryptionStatus()} to check the current +encryption status of the device. If your app is targeting an API level +lower than 24.0 (Android 7.0), +{@link android.app.admin.DevicePolicyManager#getStorageEncryptionStatus +getStorageEncryptionStatus()} will return +{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE +ENCRYPTION_STATUS_ACTIVE} if the device is either using full-disk encryption, +or file-based encryption with Direct Boot. In both of these cases, data is +always stored encrypted at rest. If your app is targeting an API level of +24.0 or higher, +{@link android.app.admin.DevicePolicyManager#getStorageEncryptionStatus +getStorageEncryptionStatus()} will return +{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE +ENCRYPTION_STATUS_ACTIVE} if the device is using full-disk encryption. It will +return +{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER +ENCRYPTION_STATUS_ACTIVE_PER_USER} if the device is using file-based encryption +with Direct Boot.

      + +

      If you build a device administration app +that targets Android 7.0, make sure to check for both +{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE +ENCRYPTION_STATUS_ACTIVE} and +{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER +ENCRYPTION_STATUS_ACTIVE_PER_USER} to determine if the device is +encrypted.

      diff --git a/docs/html/training/articles/memory.jd b/docs/html/training/articles/memory.jd deleted file mode 100644 index de7af589aefd07921afa0661f8418bd2e63a07ab..0000000000000000000000000000000000000000 --- a/docs/html/training/articles/memory.jd +++ /dev/null @@ -1,740 +0,0 @@ -page.title=Managing Your App's Memory -page.tags=ram,low memory,OutOfMemoryError,onTrimMemory -page.article=true -@jd:body - - - - - -

      Random-access memory (RAM) is a valuable resource in any software development environment, but -it's even more valuable on a mobile operating system where physical memory is often constrained. -Although Android's Dalvik virtual machine performs routine garbage collection, this doesn't allow -you to ignore when and where your app allocates and releases memory.

      - -

      In order for the garbage collector to reclaim memory from your app, you need to avoid -introducing memory leaks (usually caused by holding onto object references in global members) and -release any {@link java.lang.ref.Reference} objects at the appropriate time (as defined by -lifecycle callbacks discussed further below). For most apps, the Dalvik garbage collector takes -care of the rest: the system reclaims your memory allocations when the corresponding objects leave -the scope of your app's active threads.

      - -

      This document explains how Android manages app processes and memory allocation, and how you can -proactively reduce memory usage while developing for Android. For more information about general -practices to clean up your resources when programming in Java, refer to other books or online -documentation about managing resource references. If you’re looking for information about how to -analyze your app’s memory once you’ve already built it, read Investigating Your RAM Usage.

      - - - - -

      How Android Manages Memory

      - -

      Android does not offer swap space for memory, but it does use paging and memory-mapping -(mmapping) to manage memory. This means that any memory you modify—whether by allocating -new objects or touching mmapped pages—remains resident in RAM and cannot be paged out. -So the only way to completely release memory from your app is to release object references you may -be holding, making the memory available to the garbage collector. That is with one exception: -any files mmapped in without modification, such as code, can be paged out of RAM if the system -wants to use that memory elsewhere.

      - - -

      Sharing Memory

      - -

      In order to fit everything it needs in RAM, Android tries to share RAM pages across processes. It -can do so in the following ways:

      -
        -
      • Each app process is forked from an existing process called Zygote. -The Zygote process starts when the system boots and loads common framework code and resources -(such as activity themes). To start a new app process, the system forks the Zygote process then -loads and runs the app's code in the new process. This allows most of the RAM pages allocated for -framework code and resources to be shared across all app processes.
      • - -
      • Most static data is mmapped into a process. This not only allows that same data to be shared -between processes but also allows it to be paged out when needed. Example static data include: -Dalvik code (by placing it in a pre-linked {@code .odex} file for direct mmapping), app resources -(by designing the resource table to be a structure that can be mmapped and by aligning the zip -entries of the APK), and traditional project elements like native code in {@code .so} files.
      • - -
      • In many places, Android shares the same dynamic RAM across processes using explicitly allocated -shared memory regions (either with ashmem or gralloc). For example, window surfaces use shared -memory between the app and screen compositor, and cursor buffers use shared memory between the -content provider and client.
      • -
      - -

      Due to the extensive use of shared memory, determining how much memory your app is using requires -care. Techniques to properly determine your app's memory use are discussed in Investigating Your RAM Usage.

      - - -

      Allocating and Reclaiming App Memory

      - -

      Here are some facts about how Android allocates then reclaims memory from your app:

      - -
        -
      • The Dalvik heap for each process is constrained to a single virtual memory range. This defines -the logical heap size, which can grow as it needs to (but only up to a limit that the system defines -for each app).
      • - -
      • The logical size of the heap is not the same as the amount of physical memory used by the heap. -When inspecting your app's heap, Android computes a value called the Proportional Set Size (PSS), -which accounts for both dirty and clean pages that are shared with other processes—but only in an -amount that's proportional to how many apps share that RAM. This (PSS) total is what the system -considers to be your physical memory footprint. For more information about PSS, see the Investigating Your -RAM Usage guide.
      • - -
      • The Dalvik heap does not compact the logical size of the heap, meaning that Android does not -defragment the heap to close up space. Android can only shrink the logical heap size when there -is unused space at the end of the heap. But this doesn't mean the physical memory used by the heap -can't shrink. After garbage collection, Dalvik walks the heap and finds unused pages, then returns -those pages to the kernel using madvise. So, paired allocations and deallocations of large -chunks should result in reclaiming all (or nearly all) the physical memory used. However, -reclaiming memory from small allocations can be much less efficient because the page used -for a small allocation may still be shared with something else that has not yet been freed.
      • -
      - - -

      Restricting App Memory

      - -

      To maintain a functional multi-tasking environment, Android sets a hard limit on the heap size -for each app. The exact heap size limit varies between devices based on how much RAM the device -has available overall. If your app has reached the heap capacity and tries to allocate more -memory, it will receive an {@link java.lang.OutOfMemoryError}.

      - -

      In some cases, you might want to query the system to determine exactly how much heap space you -have available on the current device—for example, to determine how much data is safe to keep in a -cache. You can query the system for this figure by calling {@link -android.app.ActivityManager#getMemoryClass()}. This returns an integer indicating the number of -megabytes available for your app's heap. This is discussed further below, under -Check how much memory you should use.

      - - -

      Switching Apps

      - -

      Instead of using swap space when the user switches between apps, Android keeps processes that -are not hosting a foreground ("user visible") app component in a least-recently used (LRU) cache. -For example, when the user first launches an app, a process is created for it, but when the user -leaves the app, that process does not quit. The system keeps the process cached, so if -the user later returns to the app, the process is reused for faster app switching.

      - -

      If your app has a cached process and it retains memory that it currently does not need, -then your app—even while the user is not using it—is constraining the system's -overall performance. So, as the system runs low on memory, it may kill processes in the LRU cache -beginning with the process least recently used, but also giving some consideration toward -which processes are most memory intensive. To keep your process cached as long as possible, follow -the advice in the following sections about when to release your references.

      - -

      More information about how processes are cached while not running in the foreground and how -Android decides which ones -can be killed is available in the Processes and Threads guide.

      - - - - -

      How Your App Should Manage Memory

      - -

      You should consider RAM constraints throughout all phases of development, including during app -design (before you begin development). There are many -ways you can design and write code that lead to more efficient results, through aggregation of the -same techniques applied over and over.

      - -

      You should apply the following techniques while designing and implementing your app to make it -more memory efficient.

      - - -

      Use services sparingly

      - -

      If your app needs a service -to perform work in the background, do not keep it running unless -it's actively performing a job. Also be careful to never leak your service by failing to stop it -when its work is done.

      - -

      When you start a service, the system prefers to always keep the process for that service -running. This makes the process very expensive because the RAM used by the service can’t be used by -anything else or paged out. This reduces the number of cached processes that the system can keep in -the LRU cache, making app switching less efficient. It can even lead to thrashing in the system -when memory is tight and the system can’t maintain enough processes to host all the services -currently running.

      - -

      The best way to limit the lifespan of your service is to use an {@link -android.app.IntentService}, which finishes -itself as soon as it's done handling the intent that started it. For more information, read -Running in a Background Service -.

      - -

      Leaving a service running when it’s not needed is one of the worst memory-management -mistakes an Android app can make. So don’t be greedy by keeping a service for your app -running. Not only will it increase the risk of your app performing poorly due to RAM constraints, -but users will discover such misbehaving apps and uninstall them.

      - - -

      Release memory when your user interface becomes hidden

      - -

      When the user navigates to a different app and your UI is no longer visible, you should -release any resources that are used by only your UI. Releasing UI resources at this time can -significantly increase the system's capacity for cached processes, which has a direct impact on the -quality of the user experience.

      - -

      To be notified when the user exits your UI, implement the {@link -android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()} callback in your {@link -android.app.Activity} classes. You should use this -method to listen for the {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN} level, -which indicates your UI is now hidden from view and you should free resources that only your UI -uses.

      - - -

      Notice that your app receives the {@link android.content.ComponentCallbacks2#onTrimMemory -onTrimMemory()} callback with {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN} -only when all the UI components of your app process become hidden from the user. -This is distinct -from the {@link android.app.Activity#onStop onStop()} callback, which is called when an {@link -android.app.Activity} instance becomes hidden, which occurs even when the user moves to -another activity in your app. So although you should implement {@link android.app.Activity#onStop -onStop()} to release activity resources such as a network connection or to unregister broadcast -receivers, you usually should not release your UI resources until you receive {@link -android.content.ComponentCallbacks2#onTrimMemory onTrimMemory(TRIM_MEMORY_UI_HIDDEN)}. This ensures -that if the user navigates back from another activity in your app, your UI resources are -still available to resume the activity quickly.

      - - - -

      Release memory as memory becomes tight

      - -

      During any stage of your app's lifecycle, the {@link -android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()} callback also tells you when -the overall device memory is getting low. You should respond by further releasing resources based -on the following memory levels delivered by {@link android.content.ComponentCallbacks2#onTrimMemory -onTrimMemory()}:

      - -
        -
      • {@link android.content.ComponentCallbacks2#TRIM_MEMORY_RUNNING_MODERATE} -

        Your app is running and not considered killable, but the device is running low on memory and the -system is actively killing processes in the LRU cache.

        -
      • - -
      • {@link android.content.ComponentCallbacks2#TRIM_MEMORY_RUNNING_LOW} -

        Your app is running and not considered killable, but the device is running much lower on -memory so you should release unused resources to improve system performance (which directly -impacts your app's performance).

        -
      • - -
      • {@link android.content.ComponentCallbacks2#TRIM_MEMORY_RUNNING_CRITICAL} -

        Your app is still running, but the system has already killed most of the processes in the -LRU cache, so you should release all non-critical resources now. If the system cannot reclaim -sufficient amounts of RAM, it will clear all of the LRU cache and begin killing processes that -the system prefers to keep alive, such as those hosting a running service.

        -
      • -
      - -

      Also, when your app process is currently cached, you may receive one of the following -levels from {@link android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()}:

      -
        -
      • {@link android.content.ComponentCallbacks2#TRIM_MEMORY_BACKGROUND} -

        The system is running low on memory and your process is near the beginning of the LRU list. -Although your app process is not at a high risk of being killed, the system may already be killing -processes in the LRU cache. You should release resources that are easy to recover so your process -will remain in the list and resume quickly when the user returns to your app.

        -
      • - -
      • {@link android.content.ComponentCallbacks2#TRIM_MEMORY_MODERATE} -

        The system is running low on memory and your process is near the middle of the LRU list. If the -system becomes further constrained for memory, there's a chance your process will be killed.

        -
      • - -
      • {@link android.content.ComponentCallbacks2#TRIM_MEMORY_COMPLETE} -

        The system is running low on memory and your process is one of the first to be killed if the -system does not recover memory now. You should release everything that's not critical to -resuming your app state.

        - -
      • -
      - -

      Because the {@link android.content.ComponentCallbacks2#onTrimMemory onTrimMemory()} callback was -added in API level 14, you can use the {@link android.content.ComponentCallbacks#onLowMemory()} -callback as a fallback for older versions, which is roughly equivalent to the {@link -android.content.ComponentCallbacks2#TRIM_MEMORY_COMPLETE} event.

      - -

      Note: When the system begins killing processes in the LRU cache, -although it primarily works bottom-up, it does give some consideration to which processes are -consuming more memory and will thus provide the system more memory gain if killed. -So the less memory you consume while in the LRU list overall, the better your chances are -to remain in the list and be able to quickly resume.

      - - - -

      Check how much memory you should use

      - -

      As mentioned earlier, each Android-powered device has a different amount of RAM available to the -system and thus provides a different heap limit for each app. You can call {@link -android.app.ActivityManager#getMemoryClass()} to get an estimate of your app's available heap in -megabytes. If your app tries to allocate more memory than is available here, it will receive an -{@link java.lang.OutOfMemoryError}.

      - -

      In very special situations, you can request a larger heap size by setting the {@code largeHeap} -attribute to "true" in the manifest {@code } -tag. If you do so, you can call {@link -android.app.ActivityManager#getLargeMemoryClass()} to get an estimate of the large heap size.

      - -

      However, the ability to request a large heap is intended only for a small set of apps that can -justify the need to consume more RAM (such as a large photo editing app). Never request a -large heap simply because you've run out of memory and you need a quick fix—you -should use it only when you know exactly where all your memory is being allocated and why it must -be retained. Yet, even when you're confident your app can justify the large heap, you should avoid -requesting it to whatever extent possible. Using the extra memory will increasingly be to the -detriment of the overall user experience because garbage collection will take longer and system -performance may be slower when task switching or performing other common operations.

      - -

      Additionally, the large heap size is not the same on all devices and, when running on -devices that have limited RAM, the large heap size may be exactly the same as the regular heap -size. So even if you do request the large heap size, you should call {@link -android.app.ActivityManager#getMemoryClass()} to check the regular heap size and strive to always -stay below that limit.

      - - -

      Avoid wasting memory with bitmaps

      - -

      When you load a bitmap, keep it in RAM only at the resolution you need for the current device's -screen, scaling it down if the original bitmap is a higher resolution. Keep in mind that an -increase in bitmap resolution results in a corresponding (increase2) in memory needed, -because both the X and Y dimensions increase.

      - -

      Note: On Android 2.3.x (API level 10) and below, bitmap objects -always appear as the same size in your app heap regardless of the image resolution (the actual -pixel data is stored separately in native memory). This makes it more difficult to debug the bitmap -memory allocation because most heap analysis tools do not see the native allocation. However, -beginning in Android 3.0 (API level 11), the bitmap pixel data is allocated in your app's Dalvik -heap, improving garbage collection and debuggability. So if your app uses bitmaps and you're having -trouble discovering why your app is using some memory on an older device, switch to a device -running Android 3.0 or higher to debug it.

      - -

      For more tips about working with bitmaps, read Managing Bitmap Memory.

      - - -

      Use optimized data containers

      - -

      Take advantage of optimized containers in the Android framework, such as {@link -android.util.SparseArray}, {@link android.util.SparseBooleanArray}, and {@link -android.support.v4.util.LongSparseArray}. The generic {@link java.util.HashMap} -implementation can be quite memory -inefficient because it needs a separate entry object for every mapping. Additionally, the {@link -android.util.SparseArray} classes are more efficient because they avoid the system's need -to autobox -the key and sometimes value (which creates yet another object or two per entry). And don't be -afraid of dropping down to raw arrays when that makes sense.

      - - - -

      Be aware of memory overhead

      - -

      Be knowledgeable about the cost and overhead of the language and libraries you are using, and -keep this information in mind when you design your app, from start to finish. Often, things on the -surface that look innocuous may in fact have a large amount of overhead. Examples include:

      -
        -
      • Enums often require more than twice as much memory as static constants. You should strictly -avoid using enums on Android.
      • - -
      • Every class in Java (including anonymous inner classes) uses about 500 bytes of code.
      • - -
      • Every class instance has 12-16 bytes of RAM overhead.
      • - -
      • Putting a single entry into a {@link java.util.HashMap} requires the allocation of an -additional entry object that takes 32 bytes (see the previous section about optimized data containers).
      • -
      - -

      A few bytes here and there quickly add up—app designs that are class- or object-heavy will suffer -from this overhead. That can leave you in the difficult position of looking at a heap analysis and -realizing your problem is a lot of small objects using up your RAM.

      - - -

      Be careful with code abstractions

      - -

      Often, developers use abstractions simply as a "good programming practice," because abstractions -can improve code flexibility and maintenance. However, abstractions come at a significant cost: -generally they require a fair amount more code that needs to be executed, requiring more time and -more RAM for that code to be mapped into memory. So if your abstractions aren't supplying a -significant benefit, you should avoid them.

      - - -

      Use nano protobufs for serialized data

      - -

      Protocol -buffers are a language-neutral, platform-neutral, extensible mechanism designed by Google for -serializing structured data—think XML, but smaller, faster, and simpler. If you decide to use -protobufs for your data, you should always use nano protobufs in your client-side code. Regular -protobufs generate extremely verbose code, which will cause many kinds of problems in your app: -increased RAM use, significant APK size increase, slower execution, and quickly hitting the DEX -symbol limit.

      - -

      For more information, see the "Nano version" section in the protobuf readme.

      - - - -

      Avoid dependency injection frameworks

      - -

      Using a dependency injection framework such as Guice or -RoboGuice may be -attractive because they can simplify the code you write and provide an adaptive environment -that's useful for testing and other configuration changes. However, these frameworks tend to perform -a lot of process initialization by scanning your code for annotations, which can require significant -amounts of your code to be mapped into RAM even though you don't need it. These mapped pages are -allocated into clean memory so Android can drop them, but that won't happen until the pages have -been left in memory for a long period of time.

      - - -

      Be careful about using external libraries

      - -

      External library code is often not written for mobile environments and can be inefficient when used -for work on a mobile client. At the very least, when you decide to use an external library, you -should assume you are taking on a significant porting and maintenance burden to optimize the -library for mobile. Plan for that work up-front and analyze the library in terms of code size and -RAM footprint before deciding to use it at all.

      - -

      Even libraries supposedly designed for use on Android are potentially dangerous because each -library may do things differently. For example, one library may use nano protobufs while another -uses micro protobufs. Now you have two different protobuf implementations in your app. This can and -will also happen with different implementations of logging, analytics, image loading frameworks, -caching, and all kinds of other things you don't expect. ProGuard won't save you here because these -will all be lower-level dependencies that are required by the features for which you want the -library. This becomes especially problematic when you use an {@link android.app.Activity} -subclass from a library (which -will tend to have wide swaths of dependencies), when libraries use reflection (which is common and -means you need to spend a lot of time manually tweaking ProGuard to get it to work), and so on.

      - -

      Also be careful not to fall into the trap of using a shared library for one or two features out of -dozens of other things it does; you don't want to pull in a large amount of code and overhead that -you don't even use. At the end of the day, if there isn't an existing implementation that is a -strong match for what you need to do, it may be best if you create your own implementation.

      - - -

      Optimize overall performance

      - -

      A variety of information about optimizing your app's overall performance is available -in other documents listed in Best Practices -for Performance. Many of these documents include optimizations tips for CPU performance, but -many of these tips also help optimize your app's memory use, such as by reducing the number of -layout objects required by your UI.

      - -

      You should also read about optimizing -your UI with the layout debugging tools and take advantage of -the optimization suggestions provided by the lint tool.

      - - -

      Use ProGuard to strip out any unneeded code

      - -

      The ProGuard tool shrinks, -optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and -methods with semantically obscure names. Using ProGuard can make your code more compact, requiring -fewer RAM pages to be mapped.

      - - -

      Use zipalign on your final APK

      - -

      If you do any post-processing of an APK generated by a build system (including signing it -with your final production certificate), then you must run zipalign on it to have it re-aligned. -Failing to do so can cause your app to require significantly more RAM, because things like -resources can no longer be mmapped from the APK.

      - -

      Note: Google Play Store does not accept APK files that -are not zipaligned.

      - - -

      Analyze your RAM usage

      - -

      Once you achieve a relatively stable build, begin analyzing how much RAM your app is using -throughout all stages of its lifecycle. For information about how to analyze your app, read Investigating Your RAM Usage.

      - - - - -

      Use multiple processes

      - -

      If it's appropriate for your app, an advanced technique that may help you manage your app's -memory is dividing components of your app into multiple processes. This technique must always be -used carefully and most apps should not run multiple processes, as it can easily -increase—rather than decrease—your RAM footprint if done incorrectly. It is primarily -useful to apps that may run significant work in the background as well as the foreground and can -manage those operations separately.

      - - -

      An example of when multiple processes may be appropriate is when building a music player that -plays music from a service for long period of time. If -the entire app runs in one process, then many of the allocations performed for its activity UI must -be kept around as long as it is playing music, even if the user is currently in another app and the -service is controlling the playback. An app like this may be split into two process: one for its -UI, and the other for the work that continues running in the background service.

      - -

      You can specify a separate process for each app component by declaring the {@code android:process} attribute -for each component in the manifest file. For example, you can specify that your service should run -in a process separate from your app's main process by declaring a new process named "background" -(but you can name the process anything you like):

      - -
      -<service android:name=".PlaybackService"
      -         android:process=":background" />
      -
      - -

      Your process name should begin with a colon (':') to ensure that the process remains private to -your app.

      - -

      Before you decide to create a new process, you need to understand the memory implications. -To illustrate the consequences of each process, consider that an empty process doing basically -nothing has an extra memory footprint of about 1.4MB, as shown by the memory information -dump below.

      - -
      -adb shell dumpsys meminfo com.example.android.apis:empty
      -
      -** MEMINFO in pid 10172 [com.example.android.apis:empty] **
      -                Pss     Pss  Shared Private  Shared Private    Heap    Heap    Heap
      -              Total   Clean   Dirty   Dirty   Clean   Clean    Size   Alloc    Free
      -             ------  ------  ------  ------  ------  ------  ------  ------  ------
      -  Native Heap     0       0       0       0       0       0    1864    1800      63
      -  Dalvik Heap   764       0    5228     316       0       0    5584    5499      85
      - Dalvik Other   619       0    3784     448       0       0
      -        Stack    28       0       8      28       0       0
      -    Other dev     4       0      12       0       0       4
      -     .so mmap   287       0    2840     212     972       0
      -    .apk mmap    54       0       0       0     136       0
      -    .dex mmap   250     148       0       0    3704     148
      -   Other mmap     8       0       8       8      20       0
      -      Unknown   403       0     600     380       0       0
      -        TOTAL  2417     148   12480    1392    4832     152    7448    7299     148
      -
      - -

      Note: More information about how to read this output is provided -in Investigating -Your RAM Usage. The key data here is the Private Dirty and Private -Clean memory, which shows that this process is using almost 1.4MB of non-pageable RAM -(distributed across the Dalvik heap, native allocations, book-keeping, and library-loading), -and another 150K of RAM for code that has been mapped in to execute.

      - -

      This memory footprint for an empty process is fairly significant and it can quickly -grow as you start doing work in that process. For -example, here is the memory use of a process that is created only to show an activity with some -text in it:

      - -
      -** MEMINFO in pid 10226 [com.example.android.helloactivity] **
      -                Pss     Pss  Shared Private  Shared Private    Heap    Heap    Heap
      -              Total   Clean   Dirty   Dirty   Clean   Clean    Size   Alloc    Free
      -             ------  ------  ------  ------  ------  ------  ------  ------  ------
      -  Native Heap     0       0       0       0       0       0    3000    2951      48
      -  Dalvik Heap  1074       0    4928     776       0       0    5744    5658      86
      - Dalvik Other   802       0    3612     664       0       0
      -        Stack    28       0       8      28       0       0
      -       Ashmem     6       0      16       0       0       0
      -    Other dev   108       0      24     104       0       4
      -     .so mmap  2166       0    2824    1828    3756       0
      -    .apk mmap    48       0       0       0     632       0
      -    .ttf mmap     3       0       0       0      24       0
      -    .dex mmap   292       4       0       0    5672       4
      -   Other mmap    10       0       8       8      68       0
      -      Unknown   632       0     412     624       0       0
      -        TOTAL  5169       4   11832    4032   10152       8    8744    8609     134
      -
      - -

      The process has now almost tripled in size, to 4MB, simply by showing some text in the UI. This -leads to an important conclusion: If you are going to split your app into multiple processes, only -one process should be responsible for UI. Other processes should avoid any UI, as this will quickly -increase the RAM required by the process (especially once you start loading bitmap assets and other -resources). It may then be hard or impossible to reduce the memory usage once the UI is drawn.

      - -

      Additionally, when running more than one process, it's more important than ever that you keep your -code as lean as possible, because any unnecessary RAM overhead for common implementations are now -replicated in each process. For example, if you are using enums (though you should not use enums), all of -the RAM needed to create and initialize those constants is duplicated in each process, and any -abstractions you have with adapters and temporaries or other overhead will likewise be replicated.

      - -

      Another concern with multiple processes is the dependencies that exist between them. For example, -if your app has a content provider that you have running in the default process which also hosts -your UI, then code in a background process that uses that content provider will also require that -your UI process remain in RAM. If your goal is to have a background process that can run -independently of a heavy-weight UI process, it can't have dependencies on content providers or -services that execute in the UI process.

      - - - - - - - - - - - diff --git a/docs/html/training/articles/perf-anr.jd b/docs/html/training/articles/perf-anr.jd index bbebec5a83e10d7868658c2c37a0a16972b2b763..58db3e2f711c88b62ad05d59c0cc8c5bca292290 100644 --- a/docs/html/training/articles/perf-anr.jd +++ b/docs/html/training/articles/perf-anr.jd @@ -14,6 +14,14 @@ page.article=true
    • Reinforcing Responsiveness
    • +

      You should also read

      + +
    @@ -64,10 +72,10 @@ concern.)

    and Window Manager system services. Android will display the ANR dialog for a particular application when it detects one of the following conditions:

    -
      -
    • No response to an input event (such as key press or screen touch events) +
        +
      • No response to an input event (such as key press or screen touch events) within 5 seconds.
      • -
      • A {@link android.content.BroadcastReceiver BroadcastReceiver} +
      • A {@link android.content.BroadcastReceiver BroadcastReceiver} hasn't finished executing within 10 seconds.
      @@ -100,7 +108,7 @@ To post progress changes to the user, you can call {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} callback method. From your implementation of {@link android.os.AsyncTask#onProgressUpdate onProgressUpdate()} (which runs on the UI thread), you can notify the user. For example:

      - +
       private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
           // Do the long-running work in here
      @@ -127,14 +135,14 @@ private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
           }
       }
       
      - +

      To execute this worker thread, simply create an instance and call {@link android.os.AsyncTask#execute execute()}:

      - +
       new DownloadFilesTask().execute(url1, url2, url3);
       
      - +

      Although it's more complicated than {@link android.os.AsyncTask}, you might want to instead create your own {@link java.lang.Thread} or {@link android.os.HandlerThread} class. If you do, @@ -143,7 +151,7 @@ android.os.Process#setThreadPriority Process.setThreadPriority()} and passing {@ android.os.Process#THREAD_PRIORITY_BACKGROUND}. If you don't set the thread to a lower priority this way, then the thread could still slow down your app because it operates at the same priority as the UI thread by default.

      - +

      If you implement {@link java.lang.Thread} or {@link android.os.HandlerThread}, be sure that your UI thread does not block while waiting for the worker thread to complete—do not call {@link java.lang.Thread#wait Thread.wait()} or @@ -165,6 +173,16 @@ application should start an {@link android.app.IntentService} if a potentially long running action needs to be taken in response to an intent broadcast.

      +

      + Another common issue with {@link android.content.BroadcastReceiver} objects + occurs when they execute too frequently. Frequent background execution can + reduce the amount of memory available to other apps. + For more information about how to enable and disable + {@link android.content.BroadcastReceiver} objects efficiently, see + Manipulating + Broadcast Receivers on Demand. +

      +

      Tip: You can use {@link android.os.StrictMode} to help find potentially long running operations such as network or database operations that @@ -183,16 +201,16 @@ make your application seem responsive to users:

    • If your application is doing work in the background in response to user input, show that progress is being made (such as with a {@link android.widget.ProgressBar} in your UI).
    • - +
    • For games specifically, do calculations for moves in a worker thread.
    • - +
    • If your application has a time-consuming initial setup phase, consider showing a splash screen or rendering the main view as quickly as possible, indicate that loading is in progress and fill the information asynchronously. In either case, you should indicate somehow that progress is being made, lest the user perceive that the application is frozen.
    • - +
    • Use performance tools such as Systrace and Traceview to determine bottlenecks in your app's responsiveness.
    • diff --git a/docs/html/training/articles/perf-jni.jd b/docs/html/training/articles/perf-jni.jd index 5a9fa1e04b46317e92fd1e7ac99801a0a1b01a28..8d2fd9b2ebb67f94b250bd940faaa2f6d3086766 100644 --- a/docs/html/training/articles/perf-jni.jd +++ b/docs/html/training/articles/perf-jni.jd @@ -564,9 +564,9 @@ be aware of:

      that looked through the weak globals table, the arguments, the locals table, and the globals table in that order. The first time it found your direct pointer, it would report that your reference was of the type it - happened to be examining. This meant, for example, that if + happened to be examining. This meant, for example, that if you called GetObjectRefType on a global jclass that happened - to be the same as the jclass passed as an implicit argument to your static + to be the same as the jclass passed as an implicit argument to your static native method, you'd get JNILocalRefType rather than JNIGlobalRefType.
    diff --git a/docs/html/training/articles/perf-tips.jd b/docs/html/training/articles/perf-tips.jd index 4a3184c76fe82239853d51c0edc5a5b5f9efafd1..30cab14d5da671605cf172864c1a7c5c6c0a22a8 100644 --- a/docs/html/training/articles/perf-tips.jd +++ b/docs/html/training/articles/perf-tips.jd @@ -28,7 +28,8 @@ when combined, but it's unlikely that these changes will result in dramatic performance effects. Choosing the right algorithms and data structures should always be your priority, but is outside the scope of this document. You should use the tips in this document as general coding practices that you can incorporate into your habits for general code -efficiency.

    +efficiency. +

    There are two basic rules for writing efficient code:

      @@ -43,14 +44,13 @@ processors running at different speeds. It's not even generally the case that you can simply say "device X is a factor F faster/slower than device Y", and scale your results from one device to others. In particular, measurement on the emulator tells you very little about performance on any device. There -are also huge differences between devices with and without a +are also huge differences between devices with and without a JIT: the best code for a device with a JIT is not always the best code for a device without.

      To ensure your app performs well across a wide variety of devices, ensure -your code is efficient at all levels and agressively optimize your performance.

      - +your code is efficient at all levels and aggressively optimize your performance.

      Avoid Creating Unnecessary Objects

      @@ -88,7 +88,7 @@ parallel single one-dimension arrays:

      but this also generalizes to the fact that two parallel arrays of ints are also a lot more efficient than an array of {@code (int,int)} objects. The same goes for any combination of primitive types. - +
    • If you need to implement a container that stores tuples of {@code (Foo,Bar)} objects, try to remember that two parallel {@code Foo[]} and {@code Bar[]} arrays are generally much better than a single array of custom {@code (Foo,Bar)} objects. @@ -401,19 +401,6 @@ final fields too.) need to solve. Make sure you can accurately measure your existing performance, or you won't be able to measure the benefit of the alternatives you try.

      -

      Every claim made in this document is backed up by a benchmark. The source -to these benchmarks can be found in the code.google.com -"dalvik" project.

      - -

      The benchmarks are built with the -Caliper microbenchmarking -framework for Java. Microbenchmarks are hard to get right, so Caliper goes out -of its way to do the hard work for you, and even detect some cases where you're -not measuring what you think you're measuring (because, say, the VM has -managed to optimize all your code away). We highly recommend you use Caliper -to run your own microbenchmarks.

      -

      You may also find Traceview useful for profiling, but it's important to realize that it currently disables the JIT, diff --git a/docs/html/preview/features/scoped-folder-access.jd b/docs/html/training/articles/scoped-directory-access.jd similarity index 61% rename from docs/html/preview/features/scoped-folder-access.jd rename to docs/html/training/articles/scoped-directory-access.jd index 06dd6652677dedada073f08bfd242629ff9cdfa4..1e0bf39fc594061c4632d0eec29bc75f1543d5af 100644 --- a/docs/html/preview/features/scoped-folder-access.jd +++ b/docs/html/training/articles/scoped-directory-access.jd @@ -1,11 +1,10 @@ -page.title=Scoped Directory Access -page.keywords=preview,sdk,scoped directory access -page.tags=androidn +page.title=Using Scoped Directory Access +page.keywords=scoped directory access @jd:body -

      -
      +
      +

      In this document

      1. Accessing an External Storage Directory
      2. @@ -32,29 +31,37 @@ via a system UI, which is unnecessary if your app always accesses the same external directory.
    -

    Android N provides a new simplified API to access -common external storage directories.

    +

    Android 7.0 provides a simplified API to access common external storage +directories.

    Accessing an External Storage Directory

    -

    Use the StorageManager class to get the appropriate -StorageVolume instance. Then, create an intent by calling the -StorageVolume.createAccessIntent() method of that instance. +

    Use the {@link android.os.storage.StorageManager} class to get the +appropriate {@link android.os.storage.StorageVolume} instance. Then, create +an intent by calling the +{@link android.os.storage.StorageVolume#createAccessIntent +StorageVolume.createAccessIntent()} method of that instance. Use this intent to access external storage directories. To get a list of -all available volumes, including removable media volumes, use -StorageManager.getVolumesList().

    +all available volumes, including removable media +volumes, use {@link android.os.storage.StorageManager#getStorageVolumes +StorageManager.getStorageVolumes()}.

    If you have information about a specific file, use -StorageManager.getStorageVolume(File) to get the -StorageVolume that contains the file. Call -createAccessIntent() on this StorageVolume to access +{@link android.os.storage.StorageManager#getStorageVolume +StorageManager.getStorageVolume(File)} to get the +{@link android.os.storage.StorageVolume} that contains the file. Call +{@link android.os.storage.StorageVolume#createAccessIntent +createAccessIntent()} on this +{@link android.os.storage.StorageVolume} to access the external storage directory for the file.

    On secondary volumes, such as external SD cards, pass in null when calling -StorageVolume.createAccessIntent() to request access to the entire +{@link android.os.storage.StorageVolume#createAccessIntent +createAccessIntent()} to request access to the entire volume, instead of a specific directory. -StorageVolume.createAccessIntent() returns null if you pass in +{@link android.os.storage.StorageVolume#createAccessIntent +createAccessIntent()} returns null if you pass in null to the primary volume, or if you pass in an invalid directory name.

    @@ -63,7 +70,7 @@ null to the primary volume, or if you pass in an invalid directory name.
     StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
    -StorageVolume volume = sm.getPrimaryVolume();
    +StorageVolume volume = sm.getPrimaryStorageVolume();
     Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
     startActivityForResult(intent, request_code);
     
    @@ -71,25 +78,27 @@ startActivityForResult(intent, request_code);

    The system attempts to grant access to the external directory, and if necessary confirms access with the user using a simplified UI:

    - +

    Figure 1. An application requesting access to the Pictures directory.

    If the user grants access, the system calls your -onActivityResult() override with a result code of -Activity.RESULT_OK, and intent data that contains the URI. Use +{@link android.app.Activity#onActivityResult onActivityResult()} override +with a result code of {@link android.app.Activity#RESULT_OK +RESULT_OK}, and intent data that contains the URI. Use the provided URI to access directory information, similar to using URIs returned by the Storage Access Framework.

    If the user doesn't grant access, the system calls your -onActivityResult() override with a result code of -Activity.RESULT_CANCELED, and null intent data.

    +{@link android.app.Activity#onActivityResult onActivityResult()} override +with a result code of {@link android.app.Activity#RESULT_CANCELED +RESULT_CANCELED}, and null intent data.

    -

    Note: Getting access to a specific external directory +

    Getting access to a specific external directory also gains access to subdirectories within that directory.

    Accessing a Directory on Removable Media

    @@ -112,9 +121,9 @@ first add a {@link android.content.BroadcastReceiver} that listens for the

    When the user mounts removable media, like an SD card, the system sends a {@link android.os.Environment#MEDIA_MOUNTED} notification. This notification -provides a StorageVolume object in the intent data that you can -use to access directories on the removable media. The following example -accesses the Pictures directory on removable media:

    +provides a {@link android.os.storage.StorageVolume} object in the intent data +that you can use to access directories on the removable media. The following +example accesses the Pictures directory on removable media:

     // BroadcastReceiver has already cached the MEDIA_MOUNTED
    @@ -129,19 +138,22 @@ startActivityForResult(intent, request_code);
     
     

    Where possible, persist the external directory access URI so you don't have to repeatedly ask the user for access. Once the user has granted access, call -getContentResolver().takePersistableUriPermssion() with the -directory access URI. The system will persist the URI and subsequent access -requests will return RESULT_OK and not show confirmation UI to the -user.

    +{@link android.content.Context#getContentResolver getContentResolver()} and +with the returned {@link android.content.ContentResolver} call +{@link android.content.ContentResolver#takePersistableUriPermission +takePersistableUriPermission()} with the directory access URI. The system will +persist the URI and subsequent access requests will return +{@link android.app.Activity#RESULT_OK RESULT_OK} and not show confirmation +UI to the user.

    If the user denies access to an external directory, do not immediately request access again. Repeatedly insisting on access results in a poor user experience. If a request is denied by the user, and the app requests access again, the UI displays a Don't ask again checkbox:

    - +

    Figure 1. An application making a second request for access to removable media.

    diff --git a/docs/html/preview/features/security-config.jd b/docs/html/training/articles/security-config.jd similarity index 78% rename from docs/html/preview/features/security-config.jd rename to docs/html/training/articles/security-config.jd index 2706ced8579b183de4b9273770569002ae2a27eb..90a93fa00078512bb543871f36f4206e641433af 100644 --- a/docs/html/preview/features/security-config.jd +++ b/docs/html/training/articles/security-config.jd @@ -1,11 +1,12 @@ page.title=Network Security Configuration -page.keywords=androidn,security,network +page.keywords=security,network,config +page.metaDescription=Feature that allows app developers to customize network security settings in a safe configuration file. page.image=images/cards/card-nyc_2x.jpg @jd:body -
    -
    +
    +

    In this document

      @@ -28,11 +29,10 @@ page.image=images/cards/card-nyc_2x.jpg

      - Android N includes a Network Security Configuration - feature that lets apps customize their network security settings in a safe, - declarative configuration file without modifying app code. These settings can - be configured for specific domains and for a specific app. The key - capabilities of this feature are as follows: + The Network Security Configuration feature lets apps customize their network + security settings in a safe, declarative configuration file without modifying + app code. These settings can be configured for specific domains and for a + specific app. The key capabilities of this feature are as follows:

        @@ -49,7 +49,7 @@ page.image=images/cards/card-nyc_2x.jpg
      • - Cleartext traffic opt-out: Protect apps from from + Cleartext traffic opt-out: Protect apps from accidental usage of cleartext traffic.
      • @@ -72,10 +72,10 @@ page.image=images/cards/card-nyc_2x.jpg
         <?xml version="1.0" encoding="utf-8"?>
         <manifest ... >
        -  <application android:networkSecurityConfig="@xml/network_security_config"
        -               ... >
        -    ...
        -  </application>
        +    <application android:networkSecurityConfig="@xml/network_security_config"
        +                    ... >
        +        ...
        +    </application>
         </manifest>
         
        @@ -87,12 +87,12 @@ page.image=images/cards/card-nyc_2x.jpg

          -
        • Connecting to a host with a custom certificate authority(self-signed, - issued by an internal corporate CA, etc). +
        • Connecting to a host with a custom certificate authority, such as a + CA that is self-signed or is issued internally within a company.
        • Limiting the set of CAs to only the CAs you trust instead of every - preinstalled CA. + pre-installed CA.
        • Trusting additional CAs not included in the system. @@ -100,12 +100,11 @@ page.image=images/cards/card-nyc_2x.jpg

        - By default secure (e.g. TLS, HTTPS) connections from all apps trust - the pre-installed system CAs, and apps targeting API level 23 - (Android M) and below also trust the user-added CA store by default. An - app can customize its own connections using {@code base-config} (for - app-wide customization) or {@code domain-config} (for per-domain - customization). + By default, secure connections (using protocols like TLS and HTTPS) from all + apps trust the pre-installed system CAs, and apps targeting Android 6.0 (API + level 23) and lower also trust the user-added CA store by default. An app can + customize its own connections using {@code base-config} (for app-wide + customization) or {@code domain-config} (for per-domain customization).

        @@ -147,8 +146,8 @@ page.image=images/cards/card-nyc_2x.jpg

        - The config to limit the set of trusted CAs is similar to trusting a custom CA for a specific domain except + The configuration to limit the set of trusted CAs is similar to trusting a custom CA for a specific domain except that multiple CAs are provided in the resource.

        @@ -207,14 +206,14 @@ elements instead of one.

        Configuring CAs for Debugging

        - When debugging an app that connects over HTTPS you may want to + When debugging an app that connects over HTTPS, you may want to connect to a local development server, which does not have the SSL certificate for your production server. In order to support this without any - modification to your app's code you can specify debug-only CAs that - are only trusted when only when android:debuggable - is {@code true} by using {@code debug-overrides}. Normally IDEs and build + is {@code true}, by using {@code debug-overrides}. Normally, IDEs and build tools set this flag automatically for non-release builds.

        @@ -243,7 +242,7 @@ android:debuggable

        Applications intending to connect to destinations using only secure - connections can opt-out of supporting cleartext (using unencrypted HTTP + connections can opt-out of supporting cleartext (using the unencrypted HTTP protocol instead of HTTPS) to those destinations. This option helps prevent accidental regressions in apps due to changes in URLs provided by external sources such as backend servers. @@ -273,29 +272,30 @@ android:debuggable

        Pinning Certificates

        - Normally an app trusts all preinstalled CAs. If any of these CAs were - to issue a fradulent certificate the app would be at risk from a MiTM - attack. Some apps choose to limit the set of certificates they accept - by either limiting the set of CAs they trust or by certificate pinning. + Normally, an app trusts all pre-installed CAs. If any of these CAs were to + issue a fradulent certificate, the app would be at risk from a + man-in-the-middle attack. Some apps choose to limit the set of certificates + they accept by either limiting the set of CAs they trust or by certificate + pinning.

        Certificate pinning is done by providing a set of certificates by hash of the - public key (SubjectPublicKeyInfo of the X.509 certificate). A certificate - chain is then only valid if the certificate chain contains at least one of - the pinned public keys. + public key (SubjectPublicKeyInfo of the X.509 certificate). A + certificate chain is then valid only if the certificate chain contains at + least one of the pinned public keys.

        - Note that when using certificate pinning you should always include a backup - key so that if you are forced to switch to new keys, or change CAs (when + Note that, when using certificate pinning, you should always include a backup + key so that if you are forced to switch to new keys or change CAs (when pinning to a CA certificate or an intermediate of that CA), your - app's connectivity is unaffected. Otherwise you must to push out + app's connectivity is unaffected. Otherwise, you must push out an update to the app to restore connectivity.

        - Additionally it is possible to set an expiration time for pins after which + Additionally, it is possible to set an expiration time for pins after which pinning is not performed. This helps prevent connectivity issues in apps which have not been updated. However, setting an expiration time on pins may enable pinning bypass. @@ -322,24 +322,24 @@ android:debuggable

        Configuration Inheritance Behavior

        - Values not set in a specific config are inherited. This behavior allows more - complex configurations while keeping the configuration file readable. + Values not set in a specific configuration are inherited. This behavior allows + more complex configurations while keeping the configuration file readable.

        - If a value is not set in a specific entry then value from the next more - general entry is used. Values not set in a {@code domain-config} is - taken from the parent {@code domain-config}, if nested, or from the {@code - base-config} if not. Values not set in the {@code base-config} uses the + If a value is not set in a specific entry, then the value from the more + general entry is used. For example, values not set in a {@code domain-config} + are taken from the parent {@code domain-config}, if nested, or from the {@code + base-config} if not. Values not set in the {@code base-config} use the platform default values.

        - For example consider, where all connections to subdomains of {@code - example.com} must use a custom set of CAs. Additonally cleartext traffic to + For example, consider where all connections to subdomains of {@code + example.com} must use a custom set of CAs. Additonally, cleartext traffic to these domains is permitted except when connecting to {@code secure.example.com}. By nesting the configuration for {@code - secure.example.com} inside the configuration for {@code example.com} the + secure.example.com} inside the configuration for {@code example.com}, the {@code trust-anchors} does not need to be duplicated.

        @@ -458,7 +458,8 @@ android:debuggable

        Any values that are not set use the platform default values. The default - configuration for apps targeting above API level 24 and above: + configuration for apps targeting Android 7.0 (API level 24) and higher is as + follows:

        @@ -468,7 +469,8 @@ android:debuggable
             </trust-anchors>
         </base-config>
         
        -The default configuration for apps targeting API level 23 and below is: +The default configuration for apps targeting Android 6.0 (API level 23) and +lower is as follows:
         <base-config cleartextTrafficPermitted="true">
             <trust-anchors>
        @@ -499,13 +501,14 @@ The default configuration for apps targeting API level 23 and below is:
         
        Any number of nested <domain-config>
        Description
        -
        Configuration used for connections to specific destinations as the defined by {@code domain} elements. +
        Configuration used for connections to specific destinations, as defined by +the {@code domain} elements. -

        Note that if multiple {@code domain-config} elements cover a destination the config with the most specific (longest) -matching domain rule is used.

        +

        Note that if multiple {@code domain-config} elements cover a destination, the +configuration with the most specific (longest) matching domain rule is +used.

        -

        <domain>

        @@ -530,8 +533,8 @@ matching domain rule is used.

        - If {@code "true"} then this domain rule matches the domain and all - subdomains, including subdomains of subdomains, otherwise the rule only + If {@code "true"}, then this domain rule matches the domain and all + subdomains, including subdomains of subdomains. Otherwise, the rule only applies to exact matches.
        @@ -572,13 +575,13 @@ matching domain rule is used.

        Overrides to be applied when android:debuggable - is {@code "true"} which is normally the case for non-release builds + is {@code "true"}, which is normally the case for non-release builds generated by IDEs and build tools. Trust anchors specified in {@code - debug-overrides} are added to all other configurations and certificate + debug-overrides} are added to all other configurations, and certificate pinning is not performed when the server's certificate chain uses one of these debug-only trust anchors. If android:debuggable - is {@code "false"} then this section is completely ignored. + is {@code "false"}, then this section is completely ignored.
        @@ -627,11 +630,11 @@ matching domain rule is used.

        {@code src}
        -The source of CA certificates, can be one of +The source of CA certificates. Each certificate can be one of the following:
          -
        • a raw resource id pointing to a file containing X.509 certificates. +
        • a raw resource ID pointing to a file containing X.509 certificates. Certificates must be encoded in DER or PEM format. In the case of PEM - certificates the file must not contain extra non-PEM data such as + certificates, the file must not contain extra non-PEM data such as comments.
        • @@ -647,9 +650,9 @@ The source of CA certificates, can be one of

          Specifies if the CAs from this source bypass certificate pinning. If {@code - "true"} then certificate chains which chain through one of the CAs from this - source then pinning is not be performed. This can be useful for debug CAs - or to support letting the user MiTM your app's secure traffic. + "true"}, then pinning is not performed on certificate chains which are + signed by one of the CAs from this source. This can be useful for debugging + CAs or for testing man-in-the-middle attacks on your app's secure traffic.

          @@ -705,13 +708,12 @@ The source of CA certificates, can be one of

          - The date, in {@code yyyy-MM-dd} format, at and after which the pins - expire, thus disabling pinning. If the attribute is not set then the - pins do not expire. + The date, in {@code yyyy-MM-dd} format, on which the pins expire, thus + disabling pinning. If the attribute is not set, then the pins do not + expire.

          - Expiration helps prevent connectivity issues in apps which do - not get updates to their pin set, for example because the user - disabled app updates. + Expiration helps prevent connectivity issues in apps which do not get + updates to their pin set, such as when the user disables app updates.

        @@ -742,7 +744,7 @@ The source of CA certificates, can be one of
        - The digest algorithm used to generate the pin. Currently only + The digest algorithm used to generate the pin. Currently, only {@code "SHA-256"} is supported.
        diff --git a/docs/html/preview/features/key-attestation.jd b/docs/html/training/articles/security-key-attestation.jd similarity index 91% rename from docs/html/preview/features/key-attestation.jd rename to docs/html/training/articles/security-key-attestation.jd index 98b8340496d24bab222fff25f2682db46dbc0572..9145d308f1405cf81395ac7fceb431370fb6ea5e 100644 --- a/docs/html/preview/features/key-attestation.jd +++ b/docs/html/training/articles/security-key-attestation.jd @@ -1,11 +1,11 @@ page.title=Key Attestation -page.metaDescription=New support in Android N for verifying security properties of hardware-backed keys. -page.keywords="android N", "security", "TEE", "hardware-backed", "keystore", "certificate", "key attestation" +page.metaDescription=A tool for verifying security properties of hardware-backed key pairs. +page.keywords="security", "TEE", "hardware-backed", "keystore", "certificate", "key attestation" @jd:body -
        -
        +
        +

        In this document

        1. Retrieving and Verifying a Hardware-backed Key Pair
        2. @@ -21,6 +21,19 @@ page.keywords="android N", "security", "TEE", "hardware-backed", "keystore", "ce interpret the schema of the attestation certificate's extension data.

          +

          + Note: Only a small number of devices running Android 7.0 (API + level 24) support hardware-level key attestation; all other devices running + Android 7.0 use software-level key attestation instead. Before you verify the + properties of a device's hardware-backed keys in a production-level + environment, you should make sure that the device supports hardware-level key + attestation. To do so, you should check that the attestation certificate chain + contains a root certificate that is signed by the Google attestation root key + and that the attestationSecurityLevel element within the key description data structure + is set to the TrustedEnvironment security level. +

          +

          Retrieving and Verifying a Hardware-backed Key Pair

          @@ -32,15 +45,17 @@ page.keywords="android N", "security", "TEE", "hardware-backed", "keystore", "ce

          - The root certificate within this chain is signed using an attestation key, - which the device manufacturer injects into the device’s hardware-backed - keystore at the factory. + If the device supports hardware-level key attestation, the root certificate + within this chain is signed using an attestation root key, which the device + manufacturer injects into the device’s hardware-backed keystore at the + factory.

          - Note: On devices that ship with Android N and Google Play - services, the root certificate is issued by Google. You should verify that - this root certificate appears within Google’s list of root certificates. + Note: On devices that ship with hardware-level key + attestation, Android 7.0 (API level 24), and Google Play services, the root + certificate is signed by the Google attestation root key. You should verify + that this root certificate appears within Google’s list of root certificates.

          @@ -218,7 +233,7 @@ VerifiedBootState ::= ENUMERATED {

          - attestationSecurity + attestationSecurityLevel
          @@ -227,10 +242,10 @@ VerifiedBootState ::= ENUMERATED { level of the attestation.

          -

          - Note: Although it is possible to attest keys that are - stored in the Android system—that is, if the - attestationSecurity value is set to Software—you +

          + Warning: Although it is possible to attest keys that are + stored in the Android system—that is, if the value of + attestationSecurityLevel is set to Software—you cannot trust these attestations if the Android system becomes compromised.

          @@ -246,7 +261,7 @@ VerifiedBootState ::= ENUMERATED {
          - keymasterSecurity + keymasterSecurityLevel
          @@ -344,7 +359,8 @@ VerifiedBootState ::= ENUMERATED {

          Each field name corresponds to a similarly-named Keymaster tag. For example, the keySize field in an authorization list corresponds to the - KM_TAG_KEY_SIZE Keymaster tag. + + KM_TAG_KEY_SIZE Keymaster tag.

          @@ -767,7 +783,7 @@ VerifiedBootState ::= ENUMERATED {

          The month and year associated with the security patch that is currently installed on the device, specified as a six-digit integer. For example, the - June 2016 patch is represented as 201606. + August 2016 patch is represented as 201608.
          diff --git a/docs/html/training/articles/user-data-overview.jd b/docs/html/training/articles/user-data-overview.jd index 8715d36cb76c643f156160f48981dd280a266961..dc0df20fc06c3e05c3f357f11b982f70c92ebcdb 100644 --- a/docs/html/training/articles/user-data-overview.jd +++ b/docs/html/training/articles/user-data-overview.jd @@ -266,4 +266,4 @@ href="#references" style="color:#777;padding-left:.1em;">1 href="http://stackoverflow.com/questions/24374701/alternative-to-read-phone-state-permission-for-getting-notified-of-call">source)

          [2] Using Personal Examples to Improve Risk Communication for Security and Privacy Decisions, by M. Harbach, M. Hettig, S. Weber, and M. Smith. In Proceedings of ACM CHI 2014.

          [3] Modeling Users’ Mobile App Privacy Preferences: Restoring Usability in a Sea of Permission Settings, by J. Lin B. Liu, N. Sadeh and J. Hong. In Proceedings of SOUPS 2014.

          -

          [4] Teens and Mobile Apps Privacy. (source)

          +

          [4] Teens and Mobile Apps Privacy. (source)

          diff --git a/docs/html/training/articles/user-data-permissions.jd b/docs/html/training/articles/user-data-permissions.jd index edc755884e53f22fb88ccab574c97ff78629c809..ace5f7ff0d3543763f951bd7f0baef24048fccc9 100644 --- a/docs/html/training/articles/user-data-permissions.jd +++ b/docs/html/training/articles/user-data-permissions.jd @@ -56,7 +56,7 @@ Working With see Working with System Permissions. For best practices for working with unique identifiers, please see Best Practices for - Unique Identifiers. + Unique Identifiers.

          Tenets of Working diff --git a/docs/html/training/auto/audio/index.jd b/docs/html/training/auto/audio/index.jd index 3a1b1e883494161db56cb30b54a2cf7aa629787c..65883671f956ea49b0d0622d86ff816ff2c093f2 100644 --- a/docs/html/training/auto/audio/index.jd +++ b/docs/html/training/auto/audio/index.jd @@ -596,7 +596,7 @@ href="https://www.youtube.com/watch?v=xc2HZSwPcwM">

          Support Voice Actions

          -

          To reduce driver distractions, you can add voice actions in your audio playback app. With voice +

          To reduce driver distractions, you must add voice actions in your audio playback app. With voice action support, users can launch your app and play audio by providing voice input on Auto screens. If your audio playback app is already active and the user says “Play a song”, the system starts playing music without requiring the user to look at or touch diff --git a/docs/html/training/auto/index.jd b/docs/html/training/auto/index.jd index 0a7ceb34298d5ac1b11a207cb04ef84616c7c94f..a0d0bb87457bdc3536af06ba20c8d5fc73ce0afb 100644 --- a/docs/html/training/auto/index.jd +++ b/docs/html/training/auto/index.jd @@ -8,7 +8,9 @@ page.metaDescription=Starting point for building apps for Auto, with guidelines, @jd:body - + +

          Start the video course

          The Android platform enables you to extend your app to work with in-vehicle console systems @@ -27,7 +29,7 @@ page.metaDescription=Starting point for building apps for Auto, with guidelines, For more information, follow the links below to learn how to extend your Android app to support use in vehicles.

          - +

          Get Started

          diff --git a/docs/html/training/auto/testing/index.jd b/docs/html/training/auto/testing/index.jd index c93012fab3518d8b74aaa577ed16e1f65b405b8b..e3e2d862be88453356be8b55b024bb0a2c10eef3 100644 --- a/docs/html/training/auto/testing/index.jd +++ b/docs/html/training/auto/testing/index.jd @@ -523,7 +523,7 @@ to Settings > About phone (or About tablet)

          1. Install the Android Media Browser simulator -({@code <sdk>/extras/google/simulators/media-browser-simulator.apk}) on +({@code /extras/google/simulators/media-browser-simulator.apk}) on the test device. You can do this using the adb command line tool.
          2. Enable @@ -540,7 +540,7 @@ appears in Auto. If your app does not appear, stop the simulator from
            1. Install the Android Messaging simulator - ({@code <sdk>/extras/google/simulators/messaging-simulator.apk}) + ({@code /extras/google/simulators/messaging-simulator.apk}) on the test device. You can do this using the adb command line tool.
            2. Enable the simulator to read notifications posted on the system: diff --git a/docs/html/training/backup/autosyncapi.jd b/docs/html/training/backup/autosyncapi.jd deleted file mode 100644 index 0e2a9a9b992e772e465c8011bbd42639e37af14f..0000000000000000000000000000000000000000 --- a/docs/html/training/backup/autosyncapi.jd +++ /dev/null @@ -1,370 +0,0 @@ -page.title=Configuring Auto Backup for Apps -page.tags=backup, marshmallow, androidm -page.keywords=backup, autobackup -page.image=images/cards/card-auto-backup_2x.png - -@jd:body - - - -

              - Users frequently invest time and effort to configure apps just the way they like them. Switching - to a new device can cancel out all that careful configuration. For apps whose target SDK version - is Android 6.0 (API level 23) and higher, devices running Android 6.0 and higher automatically - back up app data to the cloud. The system performs this automatic backup - for nearly all app data by default, and does so without your having to write any additional app - code. -

              - -

              -Note: To protect user privacy, the device user must have opted in to Google -services for Auto Backup to work. The Google services opt-in dialog appears when the user goes -through the Setup Wizard or configures the first Google account on the device. -

              - -

              - When a user installs your app on - a new device, or reinstalls your app on one (for example, after a factory reset), the system - automatically restores the app data from the cloud. This lesson provides information about how to - configure the Auto Backup for Apps feature, explaining its default behavior and how to - exclude data that you don't want the system to back up. -

              - -

              - The automatic backup feature preserves the data your app creates on a user device by uploading it - to the user’s Google Drive account and encrypting it. There is no charge to you or the user for - data storage, and the saved data does not count towards the user's personal Google Drive quota. - Each app can store up to 25MB. Once its backed-up data reaches 25MB, the app no longer sends - data to the cloud. If the system performs a data restore, it uses the last data snapshot that - the app had sent to the cloud. -

              - -

              Automatic backups occur when the following conditions are met:

              -
                -
              • The device is idle.
              • -
              • The device is charging.
              • -
              • The device is connected to a Wi-Fi network.
              • -
              • At least 24 hours have elapsed since the last backup.
              • -
              -

              - -

              Configure Data Backup

              - -

              - On devices running Android 6.0 (API level 23) or higher, the default system behavior is to back up - almost all data that an app creates. The exception is - automatically excluded data files. This section explains how you can use settings in - your app manifest to further - limit and configure what data the system backs up. -

              - -

              Including or excluding data

              - -

              - Depending on what data your app needs and how you save it, you may need to set specific - rules for including or excluding certain files or directories. Auto Backup for Apps - lets you set these backup rules through the app manifest, in which you specify a backup scheme - configuration XML file. For example: -

              - -
              -<?xml version="1.0" encoding="utf-8"?>
              -<manifest xmlns:android="http://schemas.android.com/apk/res/android"
              -        xmlns:tools="http://schemas.android.com/tools"
              -        package="com.my.appexample">
              -    <uses-sdk android:minSdkVersion="23"/>
              -    <uses-sdk android:targetSdkVersion="23"/>
              -    <application ...
              -        android:fullBackupContent="@xml/mybackupscheme">
              -    </app>
              -    ...
              -</manifest>
              -
              - -

              - In this example, the android:fullBackupContent attribute specifies an XML file - called {@code mybackupscheme.xml}, which resides in the res/xml/ directory of your - app development project. This configuration file contains rules controlling which files are backed - up. The following example code shows a configuration file that excludes a specific file, - {@code device_info.db}: -

              - -
              -<?xml version="1.0" encoding="utf-8"?>
              -<full-backup-content>
              -    <exclude domain="database" path="device_info.db"/>
              -</full-backup-content>
              -
              - -

              Automatically excluded data files

              - -

              - Most apps do not need to, and in fact should not, back up all data. For example, the system - should not back up temporary files and caches. For this reason, the automatic backup - service excludes certain data files by default: -

              - -
                -
              • Files in the directories to which the - {@link android.content.Context#getCacheDir getCacheDir()} and - {@link android.content.Context#getCodeCacheDir getCodeCacheDir()} methods refer. -
              • - -
              • Files located on external storage, unless they reside in the directory to which the - {@link android.content.Context#getExternalFilesDir getExternalFilesDir()} method refers. -
              • - -
              • Files located in the directory to which the - {@link android.content.Context#getNoBackupFilesDir getNoBackupFilesDir()} method refers. -
              • -
              -

              Backup Configuration Syntax

              - -

              - The backup service configuration allows you to specify what files to include or exclude from - backup. The syntax for the data backup configuration XML file is as follows: -

              - -
              -<full-backup-content>
              -    <include domain=["file" | "database" | "sharedpref" | "external" | "root"]
              -    path="string" />
              -    <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"]
              -    path="string" />
              -</full-backup-content>
              -
              - -

              - The following elements and attributes allow you to specify the files to include in, and exclude - from, backup: -

              - -
                -
              • - <include>: Specifies a set of resources to - back up, instead of having the system back up all data in your app by default. If you specify - an <include> element, the system backs up only the resources specified - with this element. You can specify multiple sets of resources to back up by using multiple - <include> elements -
              • - -
              • - <exclude>: Specifies any data you want the system to exclude - when it does a full backup. If you target the same set of resources with both the - <include> and <exclude> elements, - <exclude> takes precedence. -
              • - -
              • - domain: Specifies the type of resource you want to include in, - or exclude from, backup. Valid values for this attribute include: - - - -
                  -
                • - root: Specifies that the resource is in the app’s root directory. -
                • - -
                • - file: Specifies a resource in the directory returned by the - {@link android.content.Context#getFilesDir getFilesDir()} method. -
                • - -
                • - database: Specifies a database that the - {@link android.content.Context#getDatabasePath getDatabasePath()} method returns, or that - the app interacts with via the {@link android.database.sqlite.SQLiteOpenHelper} class. -
                • - -
                • - sharedpref: Specifies a {@link android.content.SharedPreferences} object - that the {@link android.content.Context#getSharedPreferences getSharedPreferences()} - method returns. -
                • - -
                • - external: Specifies that the resource is in external storage, and corresponds - to a file in the directory that the - {@link android.content.Context#getExternalFilesDir getExternalFilesDir()} method returns. -
                • -
                -
              • -
              • - path: Specifies the file path to a resource that you want to include in, or - exclude from, backup. -
              • - - -
              - - -

              Disabling data backups

              - -

              - You can choose to prevent automatic backups of any of your app data by setting the - android:allowBackup attribute to false in the {@code app} element of - your manifest. This setting is illustrated in the following example: -

              - -
              -<?xml version="1.0" encoding="utf-8"?>
              -<manifest xmlns:android="http://schemas.android.com/apk/res/android"
              -        xmlns:tools="http://schemas.android.com/tools"
              -        package="com.my.appexample">
              -    <uses-sdk android:minSdkVersion="23"/>
              -    <uses-sdk android:targetSdkVersion="23"/>
              -    <application ...
              -        android:allowBackup="false">
              -    </application>
              -    ...
              -</manifest>
              -
              - -

              Support Lower Versions of Android

              - -

              There are two scenarios in which you may also need to support versions of Android lower -than 6.0 (API level 23): You may be updating your existing app to take advantage of the -new auto backup functionality in Android 6.0, while wanting -to continue supporting earlier versions of Android. Or you may be releasing a new app, but -want to make sure devices running on versions of Android predating 6.0 also have backup -functionality.

              - -

              Updating an existing app to support auto backup

              - -

              Earlier versions of Android supported a key/value-pair-based backup mechanism, in which the app -defines a subclass of {@link android.app.backup.BackupAgent} and sets - -{@code android:backupAgent} in its -app manifest. If your app -used this legacy approach, you can transition to full-data backups by adding the -{@code android:fullBackupOnly="true"} attribute to the -{@code <application/>} -element in the manifest. When running on a device with Android 5.1 -(API level 22) or lower, your app ignores this value in the manifest, and continues performing -backups in the previous manner.

              - -

              Even if you’re not using key/value backups, you can still use the approach described above to do -any custom processing in {@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} -or {@link android.app.backup.BackupAgent#onFullBackup onFullBackup()}. You can also use that -approach to receive a notification when a restore operation happens in -{@link android.app.backup.BackupAgent#onRestoreFinished onRestoreFinished()}. If you want to retain -the system's default implementation of -XML include/exclude rules handling, call -{@link android.app.backup.BackupAgent#onFullBackup super.onFullBackup()}.

              - -

              Giving your new app support for lower versions of Android

              - -

              If you are creating a new app that targets Android 6.0, but you also want to enable cloud backup -for devices running on Android 5.1 (API level 22) and lower, you must also -implement the Backup API.

              - -

              Test Backup Configuration

              - -

              - Once you have created a backup configuration, you should test it to make sure your app saves data - and can restore it properly. -

              - - -

              Enabling Backup Logging

              - -

              - To help determine how the backup feature is parsing your XML file, enable logging before - performing a test backup: -

              - -
              -$ adb shell setprop log.tag.BackupXmlParserLogging VERBOSE
              -
              - -

              Testing Backup

              - -

              To manually run a backup, first initialize the Backup Manager by executing the following - command: -

              - -
              -$ adb shell bmgr run
              -
              - -

              - Next, manually back up your application using the following command. Use the - <PACKAGE> parameter to specify the package name for your app: -

              - -
              -$ adb shell bmgr fullbackup <PACKAGE>
              - - -

              Testing restore

              - -

              - To manually initiate a restore after the system has backed up your app data, execute the following - command, using the <PACKAGE> parameter to specify the package name for your - app: -

              - -
              -$ adb shell bmgr restore <PACKAGE>
              -
              - -

              - Warning: This action stops your app and wipes its data before performing the restore - operation. -

              - -

              - You can test automatic restore for your app by uninstalling and reinstalling your app. The app - data is automatically restored from the cloud once the app installation is complete. -

              - - -

              Troubleshooting backups

              - -

              - If backup fails, you can clear the backup data and associated metadata either by turning backup - off and on in Settings > Backup, factory-resetting the device, or - executing this command: -

              - -
              $ adb shell bmgr wipe <TRANSPORT> <PACKAGE>
              - -

              - You must prepend com.google.android.gms to the {@code <TRANSPORT>} value. - To get the list of transports, execute the - following command: -

              - -
              $ adb shell bmgr list transports
              - -

              Handle Google Cloud Messaging

              - -

              - For apps that use Google Cloud - Messaging (GCM) for push notifications, backing up the registration - token that Google Cloud Messaging registration returned can cause unexpected behavior in - notifications for the restored app. This is because when a user installs your app on a new device, - the app must - query the GCM API for a new registration token. If the old registration is present, because the - system had backed it up and restored it, the app doesn't seek the new token. To prevent this issue - from arising, exclude the registration token from the set of backed-up files. -

              diff --git a/docs/html/training/backup/backupapi.jd b/docs/html/training/backup/backupapi.jd deleted file mode 100644 index b115b8b214551969dc22829edd8bf44c8e5476be..0000000000000000000000000000000000000000 --- a/docs/html/training/backup/backupapi.jd +++ /dev/null @@ -1,200 +0,0 @@ -page.title=Using the Backup API -parent.title=Syncing to the Cloud -parent.link=index.html - -trainingnavtop=true - -next.title=Making the Most of Google Cloud Messaging -next.link=gcm.html - -@jd:body - -
              -
              -

              This lesson teaches you to

              -
                -
              1. Register for the Android Backup Service
              2. -
              3. Configure Your Manifest
              4. -
              5. Write Your Backup Agent
              6. -
              7. Request a Backup
              8. -
              9. Restore from a Backup
              10. -
              -

              You should also read

              - -
              -
              - -

              When a user purchases a new device or resets their existing one, they might -expect that when Google Play restores your app back to their device during the -initial setup, the previous data associated with the app restores as well. On versions of Android -prior to 6.0 (API level 23), app data is not restored by default, and all the user's accomplishments -or settings in your app are lost.

              -

              For situations where the volume of data is relatively light (less than a -megabyte), like the user's preferences, notes, game high scores or other -stats, the Backup API provides a lightweight solution. This lesson walks you -through integrating the Backup API into your application, and restoring data to -new devices using the Backup API. - -

              -Note: Devices running Android 6.0 and higher -automatically back up -nearly all data by default. -

              - -

              Register for the Android Backup Service

              -

              This lesson requires the use of the Android Backup - Service, which requires registration. Go ahead and register here. Once -that's done, the service pre-populates an XML tag for insertion in your Android -Manifest, which looks like this:

              -
              -<meta-data android:name="com.google.android.backup.api_key"
              -android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" />
              -
              -

              Note that each backup key works with a specific package name. If you have -different applications, register separate keys for each one.

              - - -

              Configure Your Manifest

              -

              Use of the Android Backup Service requires two additions to your application -manifest. First, declare the name of the class that acts as your backup agent, -then add the snippet above as a child element of the Application tag. Assuming -your backup agent is going to be called {@code TheBackupAgent}, here's an example of -what the manifest looks like with this tag included:

              - -
              -<application android:label="MyApp"
              -             android:backupAgent="TheBackupAgent">
              -    ...
              -    <meta-data android:name="com.google.android.backup.api_key"
              -    android:value="ABcDe1FGHij2KlmN3oPQRs4TUvW5xYZ" />
              -    ...
              -</application>
              -
              -

              Write Your Backup Agent

              -

              The easiest way to create your backup agent is by extending the wrapper class -{@link android.app.backup.BackupAgentHelper}. Creating this helper class is -actually a very simple process. Just create a class with the same name as you -used in the manifest in the previous step (in this example, {@code -TheBackupAgent}), -and extend {@code BackupAgentHelper}. Then override the {@link -android.app.backup.BackupAgent#onCreate()}.

              - -

              Inside the {@link android.app.backup.BackupAgent#onCreate()} method, create a {@link -android.app.backup.BackupHelper}. These helpers are -specialized classes for backing up certain kinds of data. The Android framework -currently includes two such helpers: {@link -android.app.backup.FileBackupHelper} and {@link -android.app.backup.SharedPreferencesBackupHelper}. After you create the helper -and point it at the data you want to back up, just add it to the -BackupAgentHelper using the {@link android.app.backup.BackupAgentHelper#addHelper(String, BackupHelper) addHelper()} -method, adding a key which is used to -retrieve the data later. In most cases the entire -implementation is perhaps 10 lines of code.

              - -

              Here's an example that backs up a high scores file.

              - -
              -import android.app.backup.BackupAgentHelper;
              -import android.app.backup.FileBackupHelper;
              -
              -
              -public class TheBackupAgent extends BackupAgentHelper {
              -  // The name of the SharedPreferences file
              -  static final String HIGH_SCORES_FILENAME = "scores";
              -
              -  // A key to uniquely identify the set of backup data
              -  static final String FILES_BACKUP_KEY = "myfiles";
              -
              -  // Allocate a helper and add it to the backup agent
              -  @Override
              -  void onCreate() {
              -      FileBackupHelper helper = new FileBackupHelper(this, HIGH_SCORES_FILENAME);
              -      addHelper(FILES_BACKUP_KEY, helper);
              -  }
              -}
              -
              -

              For added flexibility, {@link android.app.backup.FileBackupHelper}'s -constructor can take a variable number of filenames. You could just as easily -have backed up both a high scores file and a game progress file just by adding -an extra parameter, like this:

              -
              -@Override
              -  void onCreate() {
              -      FileBackupHelper helper = new FileBackupHelper(this, HIGH_SCORES_FILENAME, PROGRESS_FILENAME);
              -      addHelper(FILES_BACKUP_KEY, helper);
              -  }
              -
              -

              Backing up preferences is similarly easy. Create a {@link -android.app.backup.SharedPreferencesBackupHelper} the same way you did a {@link -android.app.backup.FileBackupHelper}. In this case, instead of adding filenames -to the constructor, add the names of the shared preference groups being used by -your application. Here's an example of how your backup agent helper might look if -high scores are implemented as preferences instead of a flat file:

              - -
              -import android.app.backup.BackupAgentHelper;
              -import android.app.backup.SharedPreferencesBackupHelper;
              -
              -public class TheBackupAgent extends BackupAgentHelper {
              -    // The names of the SharedPreferences groups that the application maintains.  These
              -    // are the same strings that are passed to getSharedPreferences(String, int).
              -    static final String PREFS_DISPLAY = "displayprefs";
              -    static final String PREFS_SCORES = "highscores";
              -
              -    // An arbitrary string used within the BackupAgentHelper implementation to
              -    // identify the SharedPreferencesBackupHelper's data.
              -    static final String MY_PREFS_BACKUP_KEY = "myprefs";
              -
              -    // Simply allocate a helper and install it
              -    void onCreate() {
              -       SharedPreferencesBackupHelper helper =
              -                new SharedPreferencesBackupHelper(this, PREFS_DISPLAY, PREFS_SCORES);
              -        addHelper(MY_PREFS_BACKUP_KEY, helper);
              -    }
              -}
              -
              - -

              You can add as many backup helper instances to your backup agent helper as you -like, but remember that you only need one of each type. One {@link -android.app.backup.FileBackupHelper} handles all the files that you need to back up, and one -{@link android.app.backup.SharedPreferencesBackupHelper} handles all the shared -preferencegroups you need backed up. -

              - - -

              Request a Backup

              -

              In order to request a backup, just create an instance of the {@link -android.app.backup.BackupManager}, and call it's {@link -android.app.backup.BackupManager#dataChanged()} method.

              - -
              -import android.app.backup.BackupManager;
              -...
              -
              -public void requestBackup() {
              -  BackupManager bm = new BackupManager(this);
              -  bm.dataChanged();
              -}
              -
              - -

              This call notifies the backup manager that there is data ready to be backed -up to the cloud. At some point in the future, the backup manager then calls -your backup agent's {@link -android.app.backup.BackupAgent#onBackup(ParcelFileDescriptor, BackupDataOutput, -ParcelFileDescriptor) onBackup()} method. You can make -the call whenever your data has changed, without having to worry about causing -excessive network activity. If you request a backup twice before a backup -occurs, the backup only occurs once.

              - - -

              Restore from a Backup

              -

              Typically you shouldn't ever have to manually request a restore, as it -happens automatically when your application is installed on a device. However, -if it is necessary to trigger a manual restore, just call the -{@link android.app.backup.BackupManager#requestRestore(RestoreObserver) requestRestore()} method.

              diff --git a/docs/html/training/backup/index.jd b/docs/html/training/backup/index.jd deleted file mode 100644 index 4449fde1d5c3c12f2a72f283c2e62c93d91fec9b..0000000000000000000000000000000000000000 --- a/docs/html/training/backup/index.jd +++ /dev/null @@ -1,47 +0,0 @@ -page.title=Backing up App Data to the Cloud -page.tags=cloud,sync,backup - -trainingnavtop=true -startpage=true - -@jd:body - -
              -
              - -

              Dependencies and prerequisites

              -
                -
              • Android 2.2 (API level 8) and higher
              • -
              -
              -
              - -

              Users often invest significant time and effort creating data and setting -preferences within apps. Preserving that data for users if they replace a broken -device or upgrade to a new one is an important part of ensuring a great user -experience.

              - -

              This class covers techniques for backing up data to the cloud so that -users can restore their data when recovering from a data loss (such as a factory -reset) or installing your application on a new device.

              - -

              It is important to note that the API for cloud backup changed with the -release of Android 6.0 (API level 23). For your app to support backup both -on devices running Android 6.0, and those running Android 5.1 (API level -22) and lower, you must implement both techniques that this class explains.

              - -

              Lessons

              - -
              -
              Configuring Auto Backup for Apps
              -
              This lesson applies to Android 6.0 (API level 23) and higher. Learn how to accomplish - seamless app data backup and restore with zero additional lines of application code.
              -
              - -
              -
              Using the Backup API
              -
              This lesson applies to Android 5.1 (API level 22) and lower. Learn how to integrate the Backup - API into your Android app, so all of that app's user data, such as preferences, notes, and high - scores, updates seamlessly across all devices linked to that Google account.
              -
              - diff --git a/docs/html/training/basics/activity-lifecycle/index.jd b/docs/html/training/basics/activity-lifecycle/index.jd index afeab867860c2dd6e9e0dd3fe7b415001238ae8c..95ed21efe048e3a00488cfc29ba339d0d03002f7 100644 --- a/docs/html/training/basics/activity-lifecycle/index.jd +++ b/docs/html/training/basics/activity-lifecycle/index.jd @@ -41,7 +41,7 @@ class="button">Download the demo lifecycle. For instance, when your activity starts for the first time, it comes to the foreground of the system and receives user focus. During this process, the Android system calls a series of lifecycle methods on the -activity in which you set up the user interface and other components. If the user performs an +activity in which you set up the user interface and other components. If the user performs an action that starts another activity or switches to another app, the system calls another set of lifecycle methods on your activity as it moves into the background (where the activity is no longer visible, but the instance and its state remains intact).

              @@ -57,7 +57,7 @@ android.app.Activity} instance receives and how you can use them so your activit user expects and does not consume system resources when your activity doesn't need them.

              Lessons

              - +
              Starting an Activity
              Learn the basics about the activity lifecycle, how the user can launch your app, and how @@ -70,5 +70,5 @@ should do during these state changes.
              Recreating an Activity
              Learn what happens when your activity is destroyed and how you can rebuild the activity state when necessary.
              -
              + diff --git a/docs/html/training/basics/activity-lifecycle/pausing.jd b/docs/html/training/basics/activity-lifecycle/pausing.jd index 223e41a2b8a05d1dbea514f643025a965ab273a4..64fa60bcb4a03de30520e27296b5cbb227f5dd64 100644 --- a/docs/html/training/basics/activity-lifecycle/pausing.jd +++ b/docs/html/training/basics/activity-lifecycle/pausing.jd @@ -8,13 +8,13 @@ trainingnavtop=true
              - +

              This lesson teaches you to

              1. Pause Your Activity
              2. Resume Your Activity
              - +

              You should also read

              • Activities @@ -32,25 +32,34 @@ class="button">Download the demo
              -

              During normal app use, the foreground activity is sometimes obstructed by other -visual components that cause the activity to pause. For example, when a semi-transparent -activity opens (such as one in the style of a dialog), the previous activity pauses. As long as the -activity is still partially visible but currently not the activity in focus, it remains paused.

              +

              + During normal app use, the app sometimes loses focus, causing the activity to + pause. For example, when apps run in multi-window mode, only one + of the apps has the focus at any time; the system pauses all other apps. Similarly, + when a semi-transparent activity opens (such as one in the style of a + dialog), the previous activity pauses. As long as the activity is still + partially visible but currently not the activity in focus, it remains paused. +

              However, once the activity is fully-obstructed and not visible, it stops (which is discussed in the next lesson).

              As your activity enters the paused state, the system calls the {@link android.app.Activity#onPause onPause()} method on your {@link android.app.Activity}, which allows -you to stop ongoing actions that should not continue while paused (such as a video) or persist +you to stop ongoing actions that should not continue while paused or persist any information that should be permanently saved in case the user continues to leave your app. If the user returns to your activity from the paused state, the system resumes it and calls the {@link android.app.Activity#onResume onResume()} method.

              -

              Note: When your activity receives a call to {@link -android.app.Activity#onPause()}, it may be an indication that the activity will be paused for a -moment and the user may return focus to your activity. However, it's usually the first indication -that the user is leaving your activity.

              +

              + Note: When the system calls your activity's {@link + android.app.Activity#onPause()} method, the system may be signaling that the + activity will be paused for a moment and the user may return focus to your + activity, or that the app is running in multi-window mode. However, this + method call may also be the first indication that the user is leaving your + activity. +

              Figure 1. When a semi-transparent activity obscures @@ -60,14 +69,18 @@ system calls {@link android.app.Activity#onResume onResume()} (2).

              Pause Your Activity

              - +

              When the system calls {@link android.app.Activity#onPause()} for your activity, it technically means your activity is still partially visible, but most often is an indication that the user is leaving the activity and it will soon enter the Stopped state. You should usually use the {@link android.app.Activity#onPause()} callback to:

            @@ -33,55 +31,53 @@ helpoutsWidget=true

            After completing the previous lesson, you have an app that shows an activity (a single screen) with a text field and a button. In this lesson, you’ll add some -code to MyActivity that +code to MainActivity that starts a new activity when the user clicks the Send button.

            Respond to the Send Button

              -
            1. In Android Studio, from the res/layout directory, edit the content_my.xml -file.
            2. -
            3. Add the {@code android:onClick} -attribute to the {@link android.widget.Button <Button>} element. +
            4. In the file res > layout > activity_main.xml, add the + {@code android:onClick} + attribute to the {@link android.widget.Button <Button>} element as + shown below: +
              <Button
              +      android:layout_width="wrap_content"
              +      android:layout_height="wrap_content"
              +      android:text="@string/button_send"
              +      android:onClick="sendMessage" />
              +    
              +

              This attribute tells the system to call the sendMessage() + method in your activity whenever a user clicks on the button.

              +
            5. -

              res/layout/content_my.xml

              -
              -<Button
              -    android:layout_width="wrap_content"
              -    android:layout_height="wrap_content"
              -    android:text="@string/button_send"
              -    android:onClick="sendMessage" />
              -
              +
            6. In the file java > com.example.myfirstapp > MainActivity.java, + add the sendMessage() method stub as shown below: -

              The {@code -android:onClick} attribute’s value, "sendMessage", is the name of a method in your -activity that the system calls when the user clicks the button.

              -
            7. -
            8. In the java/com.mycompany.myfirstapp directory, open the MyActivity.java file.
            9. -
            10. Within the MyActivity class, add the {@code sendMessage()} method stub shown -below. +
              public class MainActivity extends AppCompatActivity {
              +    @Override
              +    protected void onCreate(Bundle savedInstanceState) {
              +        super.onCreate(savedInstanceState);
              +        setContentView(R.layout.activity_main);
              +    }
               
              -

              java/com.mycompany.myfirstapp/MyActivity.java

              -
              -/** Called when the user clicks the Send button */
              -public void sendMessage(View view) {
              -    // Do something in response to button
              -}
              -
              + /** Called when the user clicks the Send button */ + public void sendMessage(View view) { + // Do something in response to button + } +}
              -

              In order for the system to match this method to the method name given to {@code android:onClick}, -the signature must be exactly as shown. Specifically, the method must:

              +

              In order for the system to match this method to the method name given to {@code android:onClick}, + the signature must be exactly as shown. Specifically, the method must:

              -
                -
              • Be public
              • -
              • Have a void return value
              • -
              • Have a {@link android.view.View} as the only parameter (this will be the {@link -android.view.View} that was clicked)
              • -
              +
                +
              • Be public
              • +
              • Have a void return value
              • +
              • Have a {@link android.view.View} as the only parameter (this will be the {@link + android.view.View} that was clicked)
              • +
            @@ -89,423 +85,170 @@ android.view.View} that was clicked)
          3. Next, you’ll fill in this method to read the contents of the text field and deliver that text to another activity.

            -

            Build an Intent

            -
              -
            1. In MyActivity.java, inside the {@code sendMessage()} method, create an -{@link android.content.Intent} to start an activity called {@code DisplayMessageActivity} with the -following code: - -

              java/com.mycompany.myfirstapp/MyActivity.java

              -
              -public void sendMessage(View view) {
              -  Intent intent = new Intent(this, DisplayMessageActivity.class);
              -}
              -
              +

              Build an Intent

              - +

              An {@link android.content.Intent} is an object that provides runtime binding + between separate components (such as two activities). The + {@link android.content.Intent} represents an app’s "intent to do something." + You can use intents for a wide variety of tasks, but in this lesson, your intent + starts another activity.

              -

              Note: The reference to {@code DisplayMessageActivity} -will raise an error if you’re using an IDE such as Android Studio because the class doesn’t exist yet. -Ignore the error for now; you’ll create the class soon.

              +

              In MainActivity.java, add the code shown below to + sendMessage():

              -

              The constructor used here takes two parameters:

              -
                -
              • A {@link -android.content.Context} as its first parameter ({@code this} is used because the {@link -android.app.Activity} class is a subclass of {@link android.content.Context}) -
              • The {@link java.lang.Class} of the app component to which the system should deliver -the {@link android.content.Intent} (in this case, the activity that should be started) -
              +
              public class MainActivity extends AppCompatActivity {
              +    public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
              +    @Override
              +    protected void onCreate(Bundle savedInstanceState) {
              +        super.onCreate(savedInstanceState);
              +        setContentView(R.layout.activity_main);
              +    }
               
              -

              Android Studio indicates that you must import the {@link android.content.Intent} class.

              + /** Called when the user clicks the Send button */ + public void sendMessage(View view) { + Intent intent = new Intent(this, DisplayMessageActivity.class); + EditText editText = (EditText) findViewById(R.id.edit_message); + String message = editText.getText().toString(); + intent.putExtra(EXTRA_MESSAGE, message); + startActivity(intent); + } +}
              -
            2. -
            3. At the top of the file, import the {@link android.content.Intent} class: -

              java/com.mycompany.myfirstapp/MyActivity.java

              +

              Android Studio will display Cannot +resolve symbol errors because this code references classes that are not +imported. You can solve some of these with Android Studio's "import class" +functionality by pressing Alt + Enter (or Option + Return on Mac). +Your imports should end up as the following:

               import android.content.Intent;
              -
              -

              Tip: In Android Studio, press Alt + Enter (option + return on Mac) - to import missing classes.

              -
            4. - - - -
            5. Inside the {@code sendMessage()} method, -use {@link android.app.Activity#findViewById findViewById()} to get the -{@link android.widget.EditText} element. -

              java/com.mycompany.myfirstapp/MyActivity.java

              -
              -public void sendMessage(View view) {
              -  Intent intent = new Intent(this, DisplayMessageActivity.class);
              -  EditText editText = (EditText) findViewById(R.id.edit_message);
              -}
              -
              -
            6. - -
            7. At the top of the file, import the {@link android.widget.EditText} class. -

              In Android Studio, press Alt + Enter (option + return on Mac) to import missing classes.

              -
            8. - -
            9. Assign the text to a local message variable, and use the -{@link android.content.Intent#putExtra putExtra()} method to add its text value to the intent. -

              java/com.mycompany.myfirstapp/MyActivity.java

              -
              -public void sendMessage(View view) {
              -  Intent intent = new Intent(this, DisplayMessageActivity.class);
              -  EditText editText = (EditText) findViewById(R.id.edit_message);
              -  String message = editText.getText().toString();
              -  intent.putExtra(EXTRA_MESSAGE, message);
              -}
              +import android.support.v7.app.AppCompatActivity;
              +import android.os.Bundle;
              +import android.view.View;
              +import android.widget.EditText;
               
              -

              An {@link android.content.Intent} can carry data types as key-value -pairs called extras. The {@link android.content.Intent#putExtra putExtra()} method takes the -key name in the first parameter and the value in the second parameter.

              +

              An error remains for DisplayMessageActivity, but that's okay; +you'll fix that in the next section. -

            10. -
            11. At the top of the {@code MyActivity} class, add the {@code EXTRA_MESSAGE} definition as -follows: -

              java/com.mycompany.myfirstapp/MyActivity.java

              -
              -public class MyActivity extends AppCompatActivity {
              -    public final static String EXTRA_MESSAGE = "com.mycompany.myfirstapp.MESSAGE";
              -    ...
              -}
              -
              -

              For the next activity to query the extra data, you should define the key -for your intent's extra using a public constant. It's generally a good practice to define keys for -intent extras using your app's package name as a prefix. This ensures the keys are unique, in case -your app interacts with other apps.

              - -
            12. +

              There’s a lot going on in sendMessage(), so let’s explain + what's going on.

              - - -
            13. In the {@code sendMessage()} method, to finish the intent, call the -{@link android.app.Activity#startActivity startActivity()} method, passing it the -{@link android.content.Intent} object created in step 1. - -
            - -

            With this new code, the complete {@code sendMessage()} method that's invoked by the Send -button now looks like this:

            -

            java/com.mycompany.myfirstapp/MyActivity.java

            -
            -/** Called when the user clicks the Send button */
            -public void sendMessage(View view) {
            -    Intent intent = new Intent(this, DisplayMessageActivity.class);
            -    EditText editText = (EditText) findViewById(R.id.edit_message);
            -    String message = editText.getText().toString();
            -    intent.putExtra(EXTRA_MESSAGE, message);
            -    startActivity(intent);
            -}
            -
            +

            The {@link android.content.Intent} constructor takes two parameters:

            +
              +
            • A {@link android.content.Context} as its first parameter ({@code this} + is used because the {@link android.app.Activity} class is a subclass of + {@link android.content.Context}) +
            • The {@link java.lang.Class} of the app component to which the system + should deliver the {@link android.content.Intent} (in this case, the + activity that should be started). +

              Note: The reference to + DisplayMessageActivity will raise an error in Android Studio + because the class doesn’t exist yet. Ignore the error for now; you’ll + create the class soon.

              +
            -

            The system receives this call and starts an instance of the {@link android.app.Activity} -specified by the {@link android.content.Intent}. Now you need to create the -{@code DisplayMessageActivity} class in order for this to work.

            +

            The {@link android.content.Intent#putExtra(String, String) putExtra()} + method adds the EditText's value to the intent. An Intent + can carry data types as key-value pairs called extras. Your key is a + public constant EXTRA_MESSAGE because the next + activity uses the key to retrive the text value. It's a good practice to + define keys for intent extras using your app's package name as a prefix. This + ensures the keys are unique, in case your app interacts with other apps.

            - -
          +

          The {@link android.app.Activity#startActivity(Intent) startActivity()} + method starts an instance of the DisplayMessageActivity specified + by the {@link android.content.Intent}. Now you need to create the class.

          Create the Second Activity

          -

          All subclasses of {@link android.app.Activity} must implement the -{@link android.app.Activity#onCreate onCreate()} method. This method is where the activity receives -the intent with the message, then renders the message. Also, the -{@link android.app.Activity#onCreate onCreate()} method must define the activity -layout with the {@link android.app.Activity#setContentView setContentView()} method. This is where -the activity performs the initial setup of the activity components.

          - -

          Create a new activity using Android Studio

          - -

          Android Studio includes a stub for the -{@link android.app.Activity#onCreate onCreate()} method when you create a new activity. The -New Android Activity window appears.

          -
            -
          1. In Android Studio, in the java directory, select the package, - com.mycompany.myfirstapp, right-click, and select - New > Activity > Blank Activity.
          2. -
          3. In the Choose options window, fill in the activity details: -
              -
            • Activity Name: DisplayMessageActivity
            • -
            • Layout Name: activity_display_message
            • -
            • Title: My Message
            • -
            • Hierarchical Parent: com.mycompany.myfirstapp.MyActivity
            • -
            • Package name: com.mycompany.myfirstapp
            • -
            -

            Click Finish.

            +
          4. In the Project window, right-click the app folder and select + New > Activity > Empty Activity.
          5. +
          6. In the Configure Activity window, enter + "DisplayMessageActivity" for Activity Name and click + Finish
          7. - -
          8. Open the {@code DisplayMessageActivity.java} file. - -

            The class already includes an implementation of the required -{@link android.app.Activity#onCreate onCreate()} method. You update the implementation of this -method later.

            - - -
          - - -

          If you're developing with Android Studio, you can run the app now, but not much happens. -Clicking the Send button starts the second activity, but it uses -a default "Hello world" layout provided by the template. You'll soon update the -activity to instead display a custom text view.

          - - -

          Create the activity without Android Studio

          - -

          If you're using a different IDE or the command line tools, do the following:

          - -
            -
          1. Create a new file named {@code DisplayMessageActivity.java} in the project's src/ -directory, next to the original {@code MyActivity.java} file.
          2. -
          3. Add the following code to the file: - -
            -public class DisplayMessageActivity extends AppCompatActivity {
            -
            -    @Override
            -    protected void onCreate(Bundle savedInstanceState) {
            -        super.onCreate(savedInstanceState);
            -        setContentView(R.layout.activity_display_message);
            -
            -        if (savedInstanceState == null) {
            -            getSupportFragmentManager().beginTransaction()
            -                .add(R.id.container, new PlaceholderFragment()).commit();
            -        }
            -    }
            -
            -    @Override
            -    public boolean onOptionsItemSelected(MenuItem item) {
            -        // Handle app bar item clicks here. The app bar
            -        // automatically handles clicks on the Home/Up button, so long
            -        // as you specify a parent activity in AndroidManifest.xml.
            -        int id = item.getItemId();
            -        if (id == R.id.action_settings) {
            -            return true;
            -        }
            -        return super.onOptionsItemSelected(item);
            -    }
            -
            -    /**
            -     * A placeholder fragment containing a simple view.
            -     */
            -    public static class PlaceholderFragment extends Fragment {
            -
            -        public PlaceholderFragment() { }
            -
            -        @Override
            -        public View onCreateView(LayoutInflater inflater, ViewGroup container,
            -                  Bundle savedInstanceState) {
            -              View rootView = inflater.inflate(R.layout.fragment_display_message,
            -                      container, false);
            -              return rootView;
            -        }
            -    }
            -}
            -
            - -

            Note: If you are using an IDE other than Android Studio, your project -does not contain the {@code activity_display_message} layout that's requested by -{@link android.app.Activity#setContentView setContentView()}. That's OK because -you will update this method later and won't be using that layout.

            - -
          4. - -
          5. To your {@code strings.xml} file, add the new activity's title as follows: -
            -<resources>
            -    ...
            -    <string name="title_activity_display_message">My Message</string>
            -</resources>
            -
            -
          6. - -
          7. In your manifest file, AndroidManifest.xml, within the Application -element, add the -{@code } element -for your {@code DisplayMessageActivity} class, as follows: - -
            -<application ... >
            -    ...
            -    <activity
            -        android:name="com.mycompany.myfirstapp.DisplayMessageActivity"
            -        android:label="@string/title_activity_display_message"
            -        android:parentActivityName="com.mycompany.myfirstapp.MyActivity" >
            -        <meta-data
            -            android:name="android.support.PARENT_ACTIVITY"
            -            android:value="com.mycompany.myfirstapp.MyActivity" />
            -    </activity>
            -</application>
            -
            - -
          8. -
          +

          Android Studio automatically does three things:

          +
            +
          • Creates the class DisplayMessageActivity.java with an + implementation of the required {@link android.app.Activity#onCreate(Bundle) onCreate()} + method.
          • +
          • Creates the corresponding layout file activity_display_message.xml +
          • +
          • Adds the required + <activity> + element in AndroidManifest.xml. +
          -

          The {@code -android:parentActivityName} attribute declares the name of this activity's parent activity -within the app's logical hierarchy. The system uses this value -to implement default navigation behaviors, such as Up navigation on -Android 4.1 (API level 16) and higher. You can provide the same navigation behaviors for -older versions of Android by using the -Support Library and adding -the {@code -} element as shown here.

          - -

          Note: Your Android SDK should already include -the latest Android Support Library, which you installed during the -Adding SDK Packages step. -When using the templates in Android Studio, the Support Library is automatically added to your app project -(you can see the library's JAR file listed under Android Dependencies). If you're not using -Android Studio, you need to manually add the library to your project—follow the guide for setting up the Support Library -then return here.

          - -

          If you're using a different IDE than Android Studio, don't worry that the app won't yet compile. -You'll soon update the activity to display a custom text view.

          - - -

          Receive the Intent

          - -

          Every {@link android.app.Activity} is invoked by an {@link android.content.Intent}, regardless of -how the user navigated there. You can get the {@link android.content.Intent} that started your -activity by calling {@link android.app.Activity#getIntent()} and retrieve the data contained -within the intent.

          - -
            -
          1. In the java/com.mycompany.myfirstapp directory, edit the - {@code DisplayMessageActivity.java} file.
          2. -
          3. Get the intent and assign it to a local variable. -
            -Intent intent = getIntent();
            -
            -
          4. -
          5. At the top of the file, import the {@link android.content.Intent} class. -

            In Android Studio, press Alt + Enter (option + return on Mac) to import missing classes.

            -
          6. -
          7. Extract the message delivered by {@code MyActivity} with the -{@link android.content.Intent#getStringExtra getStringExtra()} method. -
            -String message = intent.getStringExtra(MyActivity.EXTRA_MESSAGE);
            -
            -
          8. -
          +

          If you run the app and click the Send button on the first activity, the + second activity starts but is empty. This is because the second activity uses + the default empty layout provided by the template.

          Display the Message

          +

          Now you will modify the second activity to display the message that was passed +by the first activity.

            -
          1. In the res/layout directory, edit the {@code content_display_message.xml} file.
          2. -
          3. Add an {@code android:id} attribute to the {@code RelativeLayout}. -You need this attribute to reference the object from your app code.
          4. - -
            -< RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            -...
            -android:id="@+id/content">
            -</RelativeLayout>
            -
            -
          5. Switch back to editing {@code DisplayMessageActivity.java}.
          6. - - -
          7. In the {@link android.app.Activity#onCreate onCreate()} method, create a {@link android.widget.TextView} object. -
            -TextView textView = new TextView(this);
            -
            -
          8. -
          9. Set the text size and message with {@link android.widget.TextView#setText setText()}. -
            -textView.setTextSize(40);
            -textView.setText(message);
            -
            -
          10. -
          11. Add the {@link android.widget.TextView} to the {@link android.widget.RelativeLayout} -identified by {@code R.id.content}. -
            -RelativeLayout layout = (RelativeLayout) findViewById(R.id.content);
            -layout.addView(textView);
            -
            -
          12. -
          13. At the top of the file, import the {@link android.widget.TextView} class. -

            In Android Studio, press Alt + Enter (option + return on Mac) to import missing classes.

            -
          14. -
          - -

          The complete {@link android.app.Activity#onCreate onCreate()} method for {@code -DisplayMessageActivity} now looks like this:

          - -
          -@Override
          +  
        3. In {@code DisplayMessageActivity.java}, add the following code to the + onCreate() method: +
          @Override
           protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_display_message);
          -   Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
          -   setSupportActionBar(toolbar);
          -
          -   FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
          -   fab.setOnClickListener(new View.OnClickListener() {
          -       @Override
          -       public void onClick(View view) {
          -           Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
          -                   .setAction("Action", null)
          -                   .show();
          -       }
          -   });
          -   getSupportActionBar().setDisplayHomeAsUpEnabled(true);
           
              Intent intent = getIntent();
          -   String message = intent.getStringExtra(MyActivity.EXTRA_MESSAGE);
          +   String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
              TextView textView = new TextView(this);
              textView.setTextSize(40);
              textView.setText(message);
           
          -   RelativeLayout layout = (RelativeLayout) findViewById(R.id.content);
          +   ViewGroup layout = (ViewGroup) findViewById(R.id.activity_display_message);
              layout.addView(textView);
          +}
          +
        4. +
        5. Press Alt + Enter (or Option + Return on Mac) to import missing classes. + Your imports should end up as the following: +
          +import android.content.Intent;
          +import android.support.v7.app.AppCompatActivity;
          +import android.os.Bundle;
          +import android.view.ViewGroup;
          +import android.widget.TextView;
           
          +
        6. +
        + +

        There’s a lot going on here, so let’s explain:

        + +
          +
        1. The call {@link android.app.Activity#getIntent()} grabs the intent + that started the activity. Every {@link android.app.Activity} is invoked by an + {@link android.content.Intent}, regardless of how the user navigated there. + The call {@link android.content.Intent#getStringExtra(String) getStringExtra()} + retrieves the data from the first activity.
        2. +
        3. You programmatically create a {@link android.widget.TextView} and set + its size and message. +
        4. +
        5. You add the TextView to the layout identified by + {@code R.id.activity_display_message}. You cast the layout to + {@link android.view.ViewGroup} because it is the superclass of all layouts and + contains the {@link android.view.ViewGroup#addView(View) addView()} + method.
        6. +
        + +

        Note: The XML layout generated by previous + versions of Android Studio might not include the android:id + attribute. The call findViewById() will fail if the layout + does not have the android:id attribute. If this is the case, + open activity_display_message.xml and add the attribute + android:id="@+id/activity_display_message" to the layout element. +

        You can now run the app. When it opens, type a message in the text field, and click Send. The second activity replaces the first one on the screen, showing @@ -513,8 +256,4 @@ the message you entered in the first activity.

        That's it, you've built your first Android app!

        -

        To learn more, follow the link below to the next class.

        - - - - +

        To learn more, follow the link below to the next class.

        \ No newline at end of file diff --git a/docs/html/training/basics/fragments/communicating.jd b/docs/html/training/basics/fragments/communicating.jd index 8c1ae21a70844207befb3005199a573ab66a9247..2e1207200068318bff2dcecdafea238f838fb06e 100644 --- a/docs/html/training/basics/fragments/communicating.jd +++ b/docs/html/training/basics/fragments/communicating.jd @@ -7,14 +7,14 @@ trainingnavtop=true @jd:body
        -
        +

        This lesson teaches you to

        1. Define an Interface
        2. Implement the Interface
        3. Deliver a Message to a Fragment
        - +

        You should also read

        • Fragments
        • @@ -31,21 +31,21 @@ class="button">Download the sample
        -

        In order to reuse the Fragment UI components, you should build each as a completely -self-contained, modular component that defines its own layout and behavior. Once you -have defined these reusable Fragments, you can associate them with an Activity and +

        In order to reuse the Fragment UI components, you should build each as a completely +self-contained, modular component that defines its own layout and behavior. Once you +have defined these reusable Fragments, you can associate them with an Activity and connect them with the application logic to realize the overall composite UI.

        -

        Often you will want one Fragment to communicate with another, for example to change -the content based on a user event. All Fragment-to-Fragment communication is done +

        Often you will want one Fragment to communicate with another, for example to change +the content based on a user event. All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.

        Define an Interface

        -

        To allow a Fragment to communicate up to its Activity, you can define an interface -in the Fragment class and implement it within the Activity. The Fragment captures -the interface implementation during its onAttach() lifecycle method and can then call +

        To allow a Fragment to communicate up to its Activity, you can define an interface +in the Fragment class and implement it within the Activity. The Fragment captures +the interface implementation during its onAttach() lifecycle method and can then call the Interface methods in order to communicate with the Activity.

        Here is an example of Fragment to Activity communication:

        @@ -62,7 +62,7 @@ public class HeadlinesFragment extends ListFragment { @Override public void onAttach(Activity activity) { super.onAttach(activity); - + // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { @@ -72,7 +72,7 @@ public class HeadlinesFragment extends ListFragment { + " must implement OnHeadlineSelectedListener"); } } - + ... }
        @@ -105,7 +105,7 @@ implement the interface defined in the fragment class.

        public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... - + public void onArticleSelected(int position) { // The user selected the headline of an article from the HeadlinesFragment // Do something here to display that article @@ -118,12 +118,12 @@ public static class MainActivity extends Activity

        Deliver a Message to a Fragment

        The host activity can deliver messages to a fragment by capturing the {@link -android.support.v4.app.Fragment} instance +android.support.v4.app.Fragment} instance with {@link android.support.v4.app.FragmentManager#findFragmentById findFragmentById()}, then directly call the fragment's public methods.

        For instance, imagine that the activity shown above may contain another fragment that's used to -display the item specified by the data returned in the above callback method. In this case, +display the item specified by the data returned in the above callback method. In this case, the activity can pass the information received in the callback method to the other fragment that will display the item:

        @@ -152,7 +152,7 @@ public static class MainActivity extends Activity Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); - + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, diff --git a/docs/html/training/basics/fragments/fragment-ui.jd b/docs/html/training/basics/fragments/fragment-ui.jd index c0bd0a45a2aaf02c3349b8bd50e543d7123b180a..4cfec76f20555ed02f214180273e4873c3f5958f 100644 --- a/docs/html/training/basics/fragments/fragment-ui.jd +++ b/docs/html/training/basics/fragments/fragment-ui.jd @@ -7,13 +7,13 @@ trainingnavtop=true @jd:body
        -
        +

        This lesson teaches you to

        1. Add a Fragment to an Activity at Runtime
        2. Replace One Fragment with Another
        - +

        You should also read

        • Fragments
        • @@ -52,14 +52,14 @@ remove, and replace fragments to an activity at runtime in order to create a dyn -

          Add a Fragment to an Activity at Runtime

          +

          Add a Fragment to an Activity at Runtime

          Rather than defining the fragments for an activity in the layout file—as shown in the previous lesson with the {@code } element—you can add a fragment to the activity during the activity runtime. This is necessary if you plan to change fragments during the life of the activity.

          -

          To perform a transaction such as add or +

          To perform a transaction such as add or remove a fragment, you must use the {@link android.support.v4.app.FragmentManager} to create a {@link android.support.v4.app.FragmentTransaction}, which provides APIs to add, remove, replace, and perform other fragment transactions.

          @@ -126,11 +126,11 @@ public class MainActivity extends FragmentActivity { // Create a new Fragment to be placed in the activity layout HeadlinesFragment firstFragment = new HeadlinesFragment(); - + // In case this activity was started with special instructions from an // Intent, pass the Intent's extras to the fragment as arguments firstFragment.setArguments(getIntent().getExtras()); - + // Add the fragment to the 'fragment_container' FrameLayout getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit(); diff --git a/docs/html/training/basics/fragments/index.jd b/docs/html/training/basics/fragments/index.jd index aba645923fdb822f8f8a3bbe87bd07b396f6ecad..4fb71e483848aa839302ffd3303efee959433555 100644 --- a/docs/html/training/basics/fragments/index.jd +++ b/docs/html/training/basics/fragments/index.jd @@ -56,7 +56,7 @@ app's user experience for devices with different screen sizes, all while continu devices running versions as old as Android 1.6.

          Lessons

          - +
          Creating a Fragment
          Learn how to build a fragment and implement basic behaviors within its callback @@ -67,5 +67,5 @@ different screens.
          Communicating with Other Fragments
          Learn how to set up communication paths from a fragment to the activity and other fragments.
          -
          + diff --git a/docs/html/training/basics/network-ops/connecting.jd b/docs/html/training/basics/network-ops/connecting.jd index 798a9ee718d71f401e88714aa9cec43cc4d717a4..9651269e8743186c680383312f416368a7da70c3 100644 --- a/docs/html/training/basics/network-ops/connecting.jd +++ b/docs/html/training/basics/network-ops/connecting.jd @@ -7,8 +7,8 @@ next.title=Managing Network Usage next.link=managing.html @jd:body - -

    You should also read

    @@ -32,7 +32,7 @@ next.link=managing.html
  • Application Fundamentals
  • -
    +

    This lesson shows you how to implement a simple application that connects to @@ -57,11 +57,11 @@ IPv6, and connection pooling.

    Check the Network Connection

    Before your app attempts to connect to the network, it should check to see whether a -network connection is available using +network connection is available using {@link android.net.ConnectivityManager#getActiveNetworkInfo getActiveNetworkInfo()} -and {@link android.net.NetworkInfo#isConnected isConnected()}. +and {@link android.net.NetworkInfo#isConnected isConnected()}. Remember, the device may be out of range of a -network, or the user may have disabled both Wi-Fi and mobile data access. +network, or the user may have disabled both Wi-Fi and mobile data access. For more discussion of this topic, see the lesson Managing Network Usage.

    @@ -69,7 +69,7 @@ Usage.

     public void myClickHandler(View view) {
         ...
    -    ConnectivityManager connMgr = (ConnectivityManager) 
    +    ConnectivityManager connMgr = (ConnectivityManager)
             getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
         if (networkInfo != null && networkInfo.isConnected()) {
    @@ -98,28 +98,28 @@ android.os.AsyncTask}. DownloadWebpageTask implements the following
     {@link android.os.AsyncTask} methods:

      - +
    • {@link android.os.AsyncTask#doInBackground doInBackground()} executes the method downloadUrl(). It passes the web page URL as a parameter. The method downloadUrl() fetches and processes the web page content. When it finishes, it passes back a result string.
    • - +
    • {@link android.os.AsyncTask#onPostExecute onPostExecute()} takes the returned string and displays it in the UI.
    • - - + +
    - +
     public class HttpExampleActivity extends Activity {
         private static final String DEBUG_TAG = "HttpExample";
         private EditText urlText;
         private TextView textView;
    -    
    +
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
    -        setContentView(R.layout.main);   
    +        setContentView(R.layout.main);
             urlText = (EditText) findViewById(R.id.myUrl);
             textView = (TextView) findViewById(R.id.myText);
         }
    @@ -129,7 +129,7 @@ public class HttpExampleActivity extends Activity {
         public void myClickHandler(View view) {
             // Gets the URL from the UI's text field.
             String stringUrl = urlText.getText().toString();
    -        ConnectivityManager connMgr = (ConnectivityManager) 
    +        ConnectivityManager connMgr = (ConnectivityManager)
                 getSystemService(Context.CONNECTIVITY_SERVICE);
             NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
             if (networkInfo != null && networkInfo.isConnected()) {
    @@ -139,7 +139,7 @@ public class HttpExampleActivity extends Activity {
             }
         }
     
    -     // Uses AsyncTask to create a task away from the main UI thread. This task takes a 
    +     // Uses AsyncTask to create a task away from the main UI thread. This task takes a
          // URL string and uses it to create an HttpUrlConnection. Once the connection
          // has been established, the AsyncTask downloads the contents of the webpage as
          // an InputStream. Finally, the InputStream is converted into a string, which is
    @@ -147,7 +147,7 @@ public class HttpExampleActivity extends Activity {
          private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
             @Override
             protected String doInBackground(String... urls) {
    -              
    +
                 // params comes from the execute() call: params[0] is the url.
                 try {
                     return downloadUrl(urls[0]);
    @@ -167,28 +167,28 @@ public class HttpExampleActivity extends Activity {
     

    The sequence of events in this snippet is as follows:

      -
    1. When users click the button that invokes {@code myClickHandler()}, +
    2. When users click the button that invokes {@code myClickHandler()}, the app passes the specified URL to the {@link android.os.AsyncTask} subclass DownloadWebpageTask.
    3. - +
    4. The {@link android.os.AsyncTask} method {@link -android.os.AsyncTask#doInBackground doInBackground()} calls the +android.os.AsyncTask#doInBackground doInBackground()} calls the downloadUrl() method.
    5. - +
    6. The downloadUrl() method takes a URL string as a parameter and uses it to create a {@link java.net.URL} object.
    7. - +
    8. The {@link java.net.URL} object is used to establish an {@link java.net.HttpURLConnection}.
    9. - +
    10. Once the connection has been established, the {@link java.net.HttpURLConnection} object fetches the web page content as an {@link java.io.InputStream}.
    11. - +
    12. The {@link java.io.InputStream} is passed to the readIt() method, which converts the stream to a string.
    13. - +
    14. Finally, the {@link android.os.AsyncTask}'s {@link android.os.AsyncTask#onPostExecute onPostExecute()} method displays the string in the main activity's UI.
    15. @@ -196,19 +196,19 @@ in the main activity's UI.

    Connect and Download Data

    - -

    In your thread that performs your network transactions, you can use - {@link java.net.HttpURLConnection} to perform a {@code GET} and download your data. - After you call {@code connect()}, you can get an {@link java.io.InputStream} of the data + +

    In your thread that performs your network transactions, you can use + {@link java.net.HttpURLConnection} to perform a {@code GET} and download your data. + After you call {@code connect()}, you can get an {@link java.io.InputStream} of the data by calling {@code getInputStream()}. - +

    In the following snippet, the {@link android.os.AsyncTask#doInBackground doInBackground()} method calls the method downloadUrl(). The downloadUrl() method takes the given URL and uses it to connect to the network via {@link java.net.HttpURLConnection}. Once a connection has been established, the app uses the method getInputStream() to retrieve the data as an {@link java.io.InputStream}.

    - +
     // Given a URL, establishes an HttpUrlConnection and retrieves
     // the web page content as a InputStream, which it returns as
    @@ -218,7 +218,7 @@ private String downloadUrl(String myurl) throws IOException {
         // Only display the first 500 characters of the retrieved
         // web page content.
         int len = 500;
    -        
    +
         try {
             URL url = new URL(myurl);
             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    @@ -235,13 +235,13 @@ private String downloadUrl(String myurl) throws IOException {
             // Convert the InputStream into a string
             String contentAsString = readIt(is, len);
             return contentAsString;
    -        
    +
         // Makes sure that the InputStream is closed after the app is
         // finished using it.
         } finally {
             if (is != null) {
                 is.close();
    -        } 
    +        }
         }
     }
    @@ -252,7 +252,7 @@ code of 200 indicates success.

    Convert the InputStream to a String

    -

    An {@link java.io.InputStream} is a readable source of bytes. Once you get an {@link java.io.InputStream}, +

    An {@link java.io.InputStream} is a readable source of bytes. Once you get an {@link java.io.InputStream}, it's common to decode or convert it into a target data type. For example, if you were downloading image data, you might decode and display it like this:

    @@ -271,7 +271,7 @@ a string so that the activity can display it in the UI:

    // Reads an InputStream and converts it to a String.
     public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
         Reader reader = null;
    -    reader = new InputStreamReader(stream, "UTF-8");        
    +    reader = new InputStreamReader(stream, "UTF-8");
         char[] buffer = new char[len];
         reader.read(buffer);
         return new String(buffer);
    diff --git a/docs/html/preview/features/data-saver.jd b/docs/html/training/basics/network-ops/data-saver.jd
    similarity index 85%
    rename from docs/html/preview/features/data-saver.jd
    rename to docs/html/training/basics/network-ops/data-saver.jd
    index abc47eaa3837e7d53d74a441339392c1946891b2..babf7c67a66355a0798f1eecfd2c53398fb4101d 100644
    --- a/docs/html/preview/features/data-saver.jd
    +++ b/docs/html/training/basics/network-ops/data-saver.jd
    @@ -1,42 +1,39 @@
    -page.title=Data Saver
    -metaDescription=User-enabled data usage optimization.
    -page.keywords="android N", "data usage", "metered network"
    -page.image=images/cards/card-nyc_2x.jpg
    +page.title=Optimizing Network Data Usage
    +parent.title=Performing Network Operations
    +parent.link=index.html
    +
    +trainingnavtop=true
    +next.title=Parsing XML Data
    +next.link=xml.html
    +
     @jd:body
     
    -
    - +

    Over the life of a smartphone, the cost of a cellular data plan can easily - exceed the cost of the device itself. In the N Developer Preview, users can - enable Data Saver on a device-wide basis in order to use less data, whether - roaming, near the end of the billing cycle, or on a small prepaid data pack. + exceed the cost of the device itself. From Android 7.0 (API level 24), + users users can enable Data Saver on a device-wide basis in order + optimize their device's data usage, and use less data. This ability + is especially useful when roaming, near the end of the billing cycle, + or for a small prepaid data pack.

    @@ -48,7 +45,7 @@ page.image=images/cards/card-nyc_2x.jpg

    - The N Developer Preview extends the {@link android.net.ConnectivityManager} + Android 7.0 (API level 24) extends the {@link android.net.ConnectivityManager} API to provide apps with a way to retrieve the user’s Data Saver preferences and monitor preference changes. It is considered good practice for apps to check whether the @@ -61,7 +58,7 @@ page.image=images/cards/card-nyc_2x.jpg

    - In the N Developer Preview, apps can use the {@link + In Android 7.0 (API level 24), apps can use the {@link android.net.ConnectivityManager} API to determine what data usage restrictions are being applied. The {@code getRestrictBackgroundStatus()} method returns one of the following values: @@ -253,4 +250,4 @@ if (connMgr.isActiveNetworkMetered()) { Sets wifi with the specified SSID as metered, allowing you to simulate a metered network on an unmetered network. - \ No newline at end of file + diff --git a/docs/html/training/basics/network-ops/index.jd b/docs/html/training/basics/network-ops/index.jd index 1f6493f1e581a70713877a59b78c2f97ce310711..14345624cf236c010379c5aaf6fe5f16fabaff1d 100644 --- a/docs/html/training/basics/network-ops/index.jd +++ b/docs/html/training/basics/network-ops/index.jd @@ -42,7 +42,7 @@ class="button">Download the sample

    This class explains the basic tasks involved in connecting to the network, monitoring the network connection (including connection changes), and giving users control over an app's network usage. It also describes how to parse and -consume XML data.

    +consume XML data.

    This class includes a sample application that illustrates how to perform common network operations. You can download the sample (to the right) and use it @@ -66,18 +66,18 @@ of your app's network operations.

    Connecting to the Network
    - +
    Learn how to connect to the network, choose an HTTP client, and perform network operations outside of the UI thread.
    Managing Network Usage
    - +
    Learn how to check a device's network connection, create a preferences UI for controlling network usage, and respond to connection changes.
    - +
    Parsing XML Data
    Learn how to parse and consume XML data.
    -
    + diff --git a/docs/html/training/basics/network-ops/managing.jd b/docs/html/training/basics/network-ops/managing.jd index a645b3fcc0b314b012a7b19d894c4813a68f6baa..a29e8745add97a3691245a97a4416e993d2dab52 100644 --- a/docs/html/training/basics/network-ops/managing.jd +++ b/docs/html/training/basics/network-ops/managing.jd @@ -6,12 +6,12 @@ trainingnavtop=true previous.title=Connecting to the Network previous.link=connecting.html -next.title=Parsing XML Data -next.link=xml.html +next.title=Optimizing Network Data Usage +next.link=data-saver.html @jd:body - -
    + +

    This lesson teaches you to

    @@ -37,7 +37,7 @@ class="button">Download the sample

    NetworkUsage.zip

    -
    +

    This lesson describes how to write applications that have fine-grained @@ -50,19 +50,19 @@ less likely to disable your app’s access to background data when they approach limits, because they can instead precisely control how much data your app uses.

    -

    For general guidelines on how to write apps that minimize the battery life -impact of downloads and network connections, see -Optimizing Battery Life +

    For general guidelines on how to write apps that minimize the battery life +impact of downloads and network connections, see +Optimizing Battery Life and Transferring Data Without Draining the Battery.

    Check a Device's Network Connection

    -

    A device can have various types of network connections. This lesson -focuses on using either a Wi-Fi or a mobile network connection. For the full +

    A device can have various types of network connections. This lesson +focuses on using either a Wi-Fi or a mobile network connection. For the full list of possible network types, see {@link android.net.ConnectivityManager}.

    Wi-Fi is typically faster. Also, mobile data is often metered, which can get -expensive. +expensive. A common strategy for apps is to only fetch large data if a Wi-Fi network is available.

    @@ -77,11 +77,11 @@ the following classes:

  • {@link android.net.ConnectivityManager}: Answers queries about the state of network connectivity. It also notifies applications when network connectivity changes.
  • - +
  • {@link android.net.NetworkInfo}: Describes the status of a network interface of a given type (currently either Mobile or Wi-Fi).
  • - + @@ -94,16 +94,16 @@ data):

     private static final String DEBUG_TAG = "NetworkStatusExample";
    -...      
    -ConnectivityManager connMgr = (ConnectivityManager) 
    +...
    +ConnectivityManager connMgr = (ConnectivityManager)
             getSystemService(Context.CONNECTIVITY_SERVICE);
    -NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 
    +NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
     boolean isWifiConn = networkInfo.isConnected();
     networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
     boolean isMobileConn = networkInfo.isConnected();
     Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);
     Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);
    -
    +

    Note that you should not base decisions on whether a network is "available." You should always check {@link @@ -122,7 +122,7 @@ internet connection is not available):

     public boolean isOnline() {
    -    ConnectivityManager connMgr = (ConnectivityManager) 
    +    ConnectivityManager connMgr = (ConnectivityManager)
                 getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
         return (networkInfo != null && networkInfo.isConnected());
    @@ -148,37 +148,37 @@ availability, time interval, and so on.
     
     
     
    -

    To write an app that supports network access and managing -network usage, your manifest must have the right permissions and +

    To write an app that supports network access and managing +network usage, your manifest must have the right permissions and intent filters.

    • The manifest excerpted below includes the following permissions:
        - +
      • {@link android.Manifest.permission#INTERNET android.permission.INTERNET}—Allows applications to open network sockets.
      • - +
      • {@link android.Manifest.permission#ACCESS_NETWORK_STATE android.permission.ACCESS_NETWORK_STATE}—Allows applications to access information about networks.
      • - +
    • - -
    • You can declare the intent filter for the + +
    • You can declare the intent filter for the {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} action (introduced in Android 4.0) to indicate that your application defines an activity that offers options to control data usage. {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} shows settings for managing -the network data usage of a specific application. When your app has a settings activity -that allows users to control network usage, you should declare this intent filter for that activity. +the network data usage of a specific application. When your app has a settings activity +that allows users to control network usage, you should declare this intent filter for that activity. In the sample application, this action is handled by the class SettingsActivity, which displays a preferences UI to let users decide when to download a feed.
    • - +
    @@ -188,9 +188,9 @@ decide when to download a feed. package="com.example.android.networkusage" ...> - <uses-sdk android:minSdkVersion="4" + <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14" /> - + <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> @@ -213,7 +213,7 @@ decide when to download a feed. SettingsActivity has an intent filter for the {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} action. SettingsActivity is a subclass of {@link -android.preference.PreferenceActivity}. It displays a preferences screen +android.preference.PreferenceActivity}. It displays a preferences screen (shown in figure 1) that lets users specify the following:

    @@ -221,10 +221,10 @@ lets users specify the following:

  • Whether to display summaries for each XML feed entry, or just a link for each entry.
  • - +
  • Whether to download the XML feed if any network connection is available, or only if Wi-Fi is available.
  • - + Preferences panel @@ -232,49 +232,49 @@ or only if Wi-Fi is available. Setting a network preference

    Figure 1. Preferences activity.

    -

    Here is SettingsActivity. Note that it implements -{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener OnSharedPreferenceChangeListener}. +

    Here is SettingsActivity. Note that it implements +{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener OnSharedPreferenceChangeListener}. When a user changes a preference, it fires -{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged onSharedPreferenceChanged()}, -which sets {@code refreshDisplay} to true. This causes the display to refresh when the user +{@link android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged onSharedPreferenceChanged()}, +which sets {@code refreshDisplay} to true. This causes the display to refresh when the user returns to the main activity:

    public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
    -    
    +
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
    -        
    +
             // Loads the XML preferences file
             addPreferencesFromResource(R.xml.preferences);
         }
    -  
    +
         @Override
         protected void onResume() {
             super.onResume();
     
    -        // Registers a listener whenever a key changes            
    +        // Registers a listener whenever a key changes
             getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
         }
    -  
    +
         @Override
         protected void onPause() {
             super.onPause();
     
            // Unregisters the listener set in onResume().
    -       // It's best practice to unregister listeners when your app isn't using them to cut down on 
    -       // unnecessary system overhead. You do this in onPause().            
    -       getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);    
    +       // It's best practice to unregister listeners when your app isn't using them to cut down on
    +       // unnecessary system overhead. You do this in onPause().
    +       getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
         }
    -  
    -    // When the user changes the preferences selection, 
    +
    +    // When the user changes the preferences selection,
         // onSharedPreferenceChanged() restarts the main activity as a new
         // task. Sets the refreshDisplay flag to "true" to indicate that
         // the main activity should update its display.
         // The main activity queries the PreferenceManager to get the latest settings.
    -    
    +
         @Override
    -    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {    
    +    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
             // Sets refreshDisplay to true so that when the user returns to the main
             // activity, the display refreshes to reflect the new settings.
             NetworkActivity.refreshDisplay = true;
    @@ -295,31 +295,31 @@ public class NetworkActivity extends Activity {
         public static final String WIFI = "Wi-Fi";
         public static final String ANY = "Any";
         private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
    -   
    +
         // Whether there is a Wi-Fi connection.
    -    private static boolean wifiConnected = false; 
    +    private static boolean wifiConnected = false;
         // Whether there is a mobile connection.
         private static boolean mobileConnected = false;
         // Whether the display should be refreshed.
         public static boolean refreshDisplay = true;
    -    
    +
         // The user's current network preference setting.
         public static String sPref = null;
    -    
    +
         // The BroadcastReceiver that tracks network connectivity changes.
         private NetworkReceiver receiver = new NetworkReceiver();
    -    
    +
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
    -        
    +
             // Registers BroadcastReceiver to track network connection changes.
             IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
             receiver = new NetworkReceiver();
             this.registerReceiver(receiver, filter);
         }
    -    
    -    @Override 
    +
    +    @Override
         public void onDestroy() {
             super.onDestroy();
             // Unregisters BroadcastReceiver when app is destroyed.
    @@ -327,34 +327,34 @@ public class NetworkActivity extends Activity {
                 this.unregisterReceiver(receiver);
             }
         }
    -    
    +
         // Refreshes the display if the network connection and the
         // pref settings allow it.
    -    
    +
         @Override
         public void onStart () {
    -        super.onStart();  
    -        
    +        super.onStart();
    +
             // Gets the user's network preference settings
             SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    -        
    +
             // Retrieves a string value for the preferences. The second parameter
             // is the default value to use if a preference value is not found.
             sPref = sharedPrefs.getString("listPref", "Wi-Fi");
     
    -        updateConnectedFlags(); 
    -       
    +        updateConnectedFlags();
    +
             if(refreshDisplay){
    -            loadPage();    
    +            loadPage();
             }
         }
    -    
    +
         // Checks the network connection and sets the wifiConnected and mobileConnected
    -    // variables accordingly. 
    +    // variables accordingly.
         public void updateConnectedFlags() {
    -        ConnectivityManager connMgr = (ConnectivityManager) 
    +        ConnectivityManager connMgr = (ConnectivityManager)
                     getSystemService(Context.CONNECTIVITY_SERVICE);
    -        
    +
             NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
             if (activeInfo != null && activeInfo.isConnected()) {
                 wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
    @@ -362,9 +362,9 @@ public class NetworkActivity extends Activity {
             } else {
                 wifiConnected = false;
                 mobileConnected = false;
    -        }  
    +        }
         }
    -      
    +
         // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
         public void loadPage() {
             if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
    @@ -376,7 +376,7 @@ public class NetworkActivity extends Activity {
             }
         }
     ...
    -    
    +
     }

    Detect Connection Changes

    @@ -388,36 +388,36 @@ the action {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION}, determines what the network connection status is, and sets the flags wifiConnected and mobileConnected to true/false accordingly. The upshot is that the next time the user returns to the app, the -app will only download the latest feed and update the display if +app will only download the latest feed and update the display if NetworkActivity.refreshDisplay is set to true.

    -

    Setting up a BroadcastReceiver that gets called unnecessarily can be a +

    Setting up a BroadcastReceiver that gets called unnecessarily can be a drain on system resources. -The sample application registers the -{@link android.content.BroadcastReceiver} {@code NetworkReceiver} in -{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()}, -and it unregisters it in -{@link android.app.Activity#onDestroy onDestroy()}. This is more lightweight +The sample application registers the +{@link android.content.BroadcastReceiver} {@code NetworkReceiver} in +{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()}, +and it unregisters it in +{@link android.app.Activity#onDestroy onDestroy()}. This is more lightweight than declaring a {@code } in the manifest. When you declare a {@code } in the manifest, it can wake up your app at any time, -even if you haven't run it for weeks. By registering and unregistering -{@code NetworkReceiver} within the main activity, you ensure that the app won't -be woken up after the user leaves the app. +even if you haven't run it for weeks. By registering and unregistering +{@code NetworkReceiver} within the main activity, you ensure that the app won't +be woken up after the user leaves the app. If you do declare a {@code } in the manifest and you know exactly -where you need it, you can use +where you need it, you can use {@link android.content.pm.PackageManager#setComponentEnabledSetting setComponentEnabledSetting()} to enable and disable it as appropriate.

    Here is NetworkReceiver:

    -
    public class NetworkReceiver extends BroadcastReceiver {   
    -      
    +
    public class NetworkReceiver extends BroadcastReceiver {
    +
     @Override
     public void onReceive(Context context, Intent intent) {
         ConnectivityManager conn =  (ConnectivityManager)
             context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo networkInfo = conn.getActiveNetworkInfo();
    -       
    +
         // Checks the user prefs and the network connection. Based on the result, decides whether
         // to refresh the display or keep the current display.
         // If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
    @@ -432,9 +432,9 @@ public void onReceive(Context context, Intent intent) {
         // (which by process of elimination would be mobile), sets refreshDisplay to true.
         } else if (ANY.equals(sPref) && networkInfo != null) {
             refreshDisplay = true;
    -                 
    +
         // Otherwise, the app can't download content--either because there is no network
    -    // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there 
    +    // connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
         // is no Wi-Fi connection.
         // Sets refreshDisplay to false.
         } else {
    diff --git a/docs/html/training/basics/network-ops/xml.jd b/docs/html/training/basics/network-ops/xml.jd
    index 0ea696d5368413ad4b9033a6654013421db62b22..3385a6365db335d4d57617ee378b5687956b9657 100644
    --- a/docs/html/training/basics/network-ops/xml.jd
    +++ b/docs/html/training/basics/network-ops/xml.jd
    @@ -9,7 +9,7 @@ previous.link=managing.html
     
     @jd:body
     
    -
    +
    @@ -38,7 +38,7 @@ class="button">Download the sample

    NetworkUsage.zip

    -
    +

    Extensible Markup Language (XML) is a set of rules for encoding documents in @@ -55,11 +55,11 @@ maintainable way to parse XML on Android. Historically Android has had two implementations of this interface:

      -
    • KXmlParser - via {@link org.xmlpull.v1.XmlPullParserFactory#newPullParser XmlPullParserFactory.newPullParser()}. +
    • KXmlParser + via {@link org.xmlpull.v1.XmlPullParserFactory#newPullParser XmlPullParserFactory.newPullParser()}.
    • -
    • ExpatPullParser, via - {@link android.util.Xml#newPullParser Xml.newPullParser()}. +
    • ExpatPullParser, via + {@link android.util.Xml#newPullParser Xml.newPullParser()}.
    @@ -69,15 +69,15 @@ example in this section uses ExpatPullParser, via

    Analyze the Feed

    -

    The first step in parsing a feed is to decide which fields you're interested in. +

    The first step in parsing a feed is to decide which fields you're interested in. The parser extracts data for those fields and ignores the rest.

    Here is an excerpt from the feed that's being parsed in the sample app. Each post to StackOverflow.com appears in the feed as an entry tag that contains several nested tags:

    -
    <?xml version="1.0" encoding="utf-8"?> 
    -<feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" ...">     
    +
    <?xml version="1.0" encoding="utf-8"?>
    +<feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" ...">
     <title type="text">newest questions tagged android - Stack Overflow</title>
     ...
         <entry>
    @@ -107,7 +107,7 @@ feed as an entry tag that contains several nested tags:

    ... </feed>
    -

    The sample app +

    The sample app extracts data for the entry tag and its nested tags title, link, and summary.

    @@ -125,7 +125,7 @@ interested in:

    public class StackOverflowXmlParser {
         // We don't use namespaces
         private static final String ns = null;
    -   
    +
         public List parse(InputStream in) throws XmlPullParserException, IOException {
             try {
                 XmlPullParser parser = Xml.newPullParser();
    @@ -137,7 +137,7 @@ interested in:

    in.close(); } } - ... + ... }

    Read the Feed

    @@ -166,7 +166,7 @@ private List readFeed(XmlPullParser parser) throws XmlPullParserException } else { skip(parser); } - } + } return entries; }
    @@ -187,7 +187,7 @@ example extracts data for the entry tag and its nested tags
  • A "read" method for each tag you're interested in. For example, readEntry(), readTitle(), and so on. The parser reads -tags from the input stream. When it encounters a tag named entry, +tags from the input stream. When it encounters a tag named entry, title, link or summary, it calls the appropriate method for that tag. Otherwise, it skips the tag. @@ -201,7 +201,7 @@ parser to the next tag. For example: readText(). This method extracts data for these tags by calling parser.getText().
  • -
  • For the link tag, the parser extracts data for links by first +
  • For the link tag, the parser extracts data for links by first determining if the link is the kind it's interested in. Then it uses parser.getAttributeValue() to extract the link's value.
  • @@ -215,7 +215,7 @@ object with the data members title, link, and
  • A helper skip() method that's recursive. For more discussion of this topic, see Skip Tags You Don't Care About.
  • - + @@ -231,7 +231,7 @@ object with the data members title, link, and this.link = link; } } - + // Parses the contents of an entry. If it encounters a title, summary, or link tag, hands them off // to their respective "read" methods for processing. Otherwise, skips the tag. private Entry readEntry(XmlPullParser parser) throws XmlPullParserException, IOException { @@ -264,18 +264,18 @@ private String readTitle(XmlPullParser parser) throws IOException, XmlPullParser parser.require(XmlPullParser.END_TAG, ns, "title"); return title; } - + // Processes link tags in the feed. private String readLink(XmlPullParser parser) throws IOException, XmlPullParserException { String link = ""; parser.require(XmlPullParser.START_TAG, ns, "link"); String tag = parser.getName(); - String relType = parser.getAttributeValue(null, "rel"); + String relType = parser.getAttributeValue(null, "rel"); if (tag.equals("link")) { if (relType.equals("alternate")){ link = parser.getAttributeValue(null, "href"); parser.nextTag(); - } + } } parser.require(XmlPullParser.END_TAG, ns, "link"); return link; @@ -350,7 +350,7 @@ which has 2 nested elements, <name> and
    • The first time through the while loop, the next tag the parser -encounters after <author> is the START_TAG for +encounters after <author> is the START_TAG for <name>. The value for depth is incremented to 2.
    • @@ -367,7 +367,7 @@ encounters is the END_TAG </uri>. The value for depth is decremented to 1.
    • The fifth time and final time through the while loop, the next -tag the parser encounters is the END_TAG +tag the parser encounters is the END_TAG </author>. The value for depth is decremented to 0, indicating that the <author> element has been successfully skipped.
    • @@ -377,7 +377,7 @@ skipped.

      Consume XML Data

      The example application fetches and parses the XML feed within an {@link -android.os.AsyncTask}. This takes the processing off the main UI thread. When +android.os.AsyncTask}. This takes the processing off the main UI thread. When processing is complete, the app updates the UI in the main activity (NetworkActivity).

      In the excerpt shown below, the loadPage() method does the @@ -386,33 +386,33 @@ following:

      • Initializes a string variable with the URL for the XML feed.
      • - +
      • If the user's settings and the network connection allow it, invokes -new DownloadXmlTask().execute(url). This instantiates a new +new DownloadXmlTask().execute(url). This instantiates a new DownloadXmlTask object ({@link android.os.AsyncTask} subclass) and runs its {@link android.os.AsyncTask#execute execute()} method, which downloads and parses the feed and returns a string result to be displayed in the UI.
      • - +
       public class NetworkActivity extends Activity {
           public static final String WIFI = "Wi-Fi";
           public static final String ANY = "Any";
           private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
      -   
      +
           // Whether there is a Wi-Fi connection.
      -    private static boolean wifiConnected = false; 
      +    private static boolean wifiConnected = false;
           // Whether there is a mobile connection.
           private static boolean mobileConnected = false;
           // Whether the display should be refreshed.
      -    public static boolean refreshDisplay = true; 
      +    public static boolean refreshDisplay = true;
           public static String sPref = null;
       
           ...
      -      
      +
           // Uses AsyncTask to download the XML feed from stackoverflow.com.
      -    public void loadPage() {  
      -      
      +    public void loadPage() {
      +
               if((sPref.equals(ANY)) && (wifiConnected || mobileConnected)) {
                   new DownloadXmlTask().execute(URL);
               }
      @@ -420,25 +420,25 @@ public class NetworkActivity extends Activity {
                   new DownloadXmlTask().execute(URL);
               } else {
                   // show error
      -        }  
      +        }
           }
      - +

      The {@link android.os.AsyncTask} subclass shown below, DownloadXmlTask, implements the following {@link android.os.AsyncTask} methods:

        - +
      • {@link android.os.AsyncTask#doInBackground doInBackground()} executes the method loadXmlFromNetwork(). It passes the feed URL as a parameter. The method loadXmlFromNetwork() fetches and processes the feed. When it finishes, it passes back a result string.
      • - +
      • {@link android.os.AsyncTask#onPostExecute onPostExecute()} takes the returned string and displays it in the UI.
      • - +
      - +
       // Implementation of AsyncTask used to download XML feed from stackoverflow.com.
       private class DownloadXmlTask extends AsyncTask<String, Void, String> {
      @@ -454,7 +454,7 @@ private class DownloadXmlTask extends AsyncTask<String, Void, String> {
           }
       
           @Override
      -    protected void onPostExecute(String result) {  
      +    protected void onPostExecute(String result) {
               setContentView(R.layout.main);
               // Displays the HTML string in the UI via a WebView
               WebView myWebView = (WebView) findViewById(R.id.webview);
      @@ -464,28 +464,28 @@ private class DownloadXmlTask extends AsyncTask<String, Void, String> {
       
          

      Below is the method loadXmlFromNetwork() that is invoked from DownloadXmlTask. It does the following:

      - +
        - +
      1. Instantiates a StackOverflowXmlParser. It also creates variables for -a {@link java.util.List} of Entry objects (entries), and +a {@link java.util.List} of Entry objects (entries), and title, url, and summary, to hold the values extracted from the XML feed for those fields.
      2. - -
      3. Calls downloadUrl(), which fetches the feed and returns it as + +
      4. Calls downloadUrl(), which fetches the feed and returns it as an {@link java.io.InputStream}.
      5. - -
      6. Uses StackOverflowXmlParser to parse the {@link java.io.InputStream}. - StackOverflowXmlParser populates a + +
      7. Uses StackOverflowXmlParser to parse the {@link java.io.InputStream}. + StackOverflowXmlParser populates a {@link java.util.List} of entries with data from the feed.
      8. - -
      9. Processes the entries {@link java.util.List}, + +
      10. Processes the entries {@link java.util.List}, and combines the feed data with HTML markup.
      11. - +
      12. Returns an HTML string that is displayed in the main activity UI by the {@link android.os.AsyncTask} method {@link android.os.AsyncTask#onPostExecute onPostExecute()}.
      13. - +
      @@ -499,35 +499,35 @@ private String loadXmlFromNetwork(String urlString) throws XmlPullParserExceptio
           String title = null;
           String url = null;
           String summary = null;
      -    Calendar rightNow = Calendar.getInstance(); 
      +    Calendar rightNow = Calendar.getInstance();
           DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa");
      -        
      +
           // Checks whether the user set the preference to include summary text
           SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
           boolean pref = sharedPrefs.getBoolean("summaryPref", false);
      -        
      +
           StringBuilder htmlString = new StringBuilder();
           htmlString.append("<h3>" + getResources().getString(R.string.page_title) + "</h3>");
      -    htmlString.append("<em>" + getResources().getString(R.string.updated) + " " + 
      +    htmlString.append("<em>" + getResources().getString(R.string.updated) + " " +
                   formatter.format(rightNow.getTime()) + "</em>");
      -        
      +
           try {
      -        stream = downloadUrl(urlString);        
      +        stream = downloadUrl(urlString);
               entries = stackOverflowXmlParser.parse(stream);
           // Makes sure that the InputStream is closed after the app is
           // finished using it.
           } finally {
               if (stream != null) {
                   stream.close();
      -        } 
      +        }
            }
      -    
      +
           // StackOverflowXmlParser returns a List (called "entries") of Entry objects.
           // Each Entry object represents a single post in the XML feed.
           // This section processes the entries list to combine each entry with HTML markup.
           // Each entry is displayed in the UI as a link that optionally includes
           // a text summary.
      -    for (Entry entry : entries) {       
      +    for (Entry entry : entries) {
               htmlString.append("<p><a href='");
               htmlString.append(entry.link);
               htmlString.append("'>" + entry.title + "</a></p>");
      diff --git a/docs/html/training/basics/supporting-devices/index.jd b/docs/html/training/basics/supporting-devices/index.jd
      index 4644c31c9cf6041bd021bec47befdddfa98de841..c9f2e6cd51c5102214b2a69cad6e89d2d6f0fac1 100644
      --- a/docs/html/training/basics/supporting-devices/index.jd
      +++ b/docs/html/training/basics/supporting-devices/index.jd
      @@ -35,7 +35,7 @@ resources and other features so your app can provide an optimized user experienc
       variety of Android-compatible devices, using a single application package (APK).

      Lessons

      - +
      Supporting Different Languages
      Learn how to support multiple languages with alternative string resources.
      @@ -44,5 +44,5 @@ variety of Android-compatible devices, using a single application package (APK).
      Supporting Different Platform Versions
      Learn how to use APIs available in new versions of Android while continuing to support older versions of Android.
      -
      + diff --git a/docs/html/training/basics/supporting-devices/languages.jd b/docs/html/training/basics/supporting-devices/languages.jd index ba7c0160fe51d151f9017828852e7083ec01d513..0ad1fafeb824003b3e8be971b6f324ad27c5224e 100644 --- a/docs/html/training/basics/supporting-devices/languages.jd +++ b/docs/html/training/basics/supporting-devices/languages.jd @@ -36,7 +36,7 @@ types. There are also a few default files such as res/values/strings.xml -

      Create Locale Directories and String Files

      +

      Create Locale Directories and String Files

      To add support for more languages, create additional values directories inside res/ that include a hyphen and the ISO language code at the end of the @@ -63,7 +63,7 @@ MyProject/

      At runtime, the Android system uses the appropriate set of string resources based on the locale currently set for the user's device.

      - +

      For example, the following are some different string resource files for different languages.

      @@ -112,7 +112,7 @@ resource name defined by the {@code } element's {@code name} attribute.<

      In your source code, you can refer to a string resource with the syntax {@code R.string.}. There are a variety of methods that accept a string resource this way.

      - +

      For example:

      diff --git a/docs/html/training/basics/supporting-devices/platforms.jd b/docs/html/training/basics/supporting-devices/platforms.jd
      index eecb3563344e39e216a7c15635e4f7a5ce4db93d..67120293b5e6e5d6cffc4407c2d0c7ef0d1e9c64 100644
      --- a/docs/html/training/basics/supporting-devices/platforms.jd
      +++ b/docs/html/training/basics/supporting-devices/platforms.jd
      @@ -10,14 +10,14 @@ trainingnavtop=true
       
       
      - +

      This lesson teaches you to

      1. Specify Minimum and Target API Levels
      2. Check System Version at Runtime
      3. Use Platform Styles and Themes
      - +

      You should also read

      • Android API Levels
      • @@ -27,19 +27,19 @@ href="{@docRoot}tools/support-library/index.html">Android Support Library
      -

      While the latest versions of Android often provide great APIs for your app, you should continue -to support older versions of Android until more devices get updated. This -lesson shows you how to take advantage of the latest APIs while continuing to support older +

      While the latest versions of Android often provide great APIs for your app, you should continue +to support older versions of Android until more devices get updated. This +lesson shows you how to take advantage of the latest APIs while continuing to support older versions as well.

      The dashboard for Platform Versions -is updated regularly to show the distribution of active -devices running each version of Android, based on the number of devices that visit the Google Play -Store. Generally, it’s a good practice to support about 90% of the active devices, while +is updated regularly to show the distribution of active +devices running each version of Android, based on the number of devices that visit the Google Play +Store. Generally, it’s a good practice to support about 90% of the active devices, while targeting your app to the latest version.

      -

      Tip: In order to provide the best features and +

      Tip: In order to provide the best features and functionality across several Android versions, you should use the Android Support Library in your app, which allows you to use several recent platform APIs on older versions.

      @@ -49,8 +49,8 @@ which allows you to use several recent platform APIs on older versions.

      Specify Minimum and Target API Levels

      The AndroidManifest.xml file -describes details about your app and -identifies which versions of Android it supports. Specifically, the minSdkVersion +describes details about your app and +identifies which versions of Android it supports. Specifically, the minSdkVersion and targetSdkVersion attributes for the {@code } element identify the lowest API level with which your app is compatible and the highest API level against @@ -65,9 +65,9 @@ which you’ve designed and tested your app.

      </manifest>
      -

      As new versions of Android are released, some style and behaviors may change. +

      As new versions of Android are released, some style and behaviors may change. To allow your app to take advantage of these changes and ensure that your app fits the style of -each user's device, you should set the +each user's device, you should set the {@code targetSdkVersion} value to match the latest Android version @@ -93,24 +93,24 @@ private void setUpActionBar() { -

      Note: When parsing XML resources, Android ignores XML +

      Note: When parsing XML resources, Android ignores XML attributes that aren’t supported by the current device. So you can safely use XML attributes that are only supported by newer versions without worrying about older versions breaking when they -encounter that code. For example, if you set the +encounter that code. For example, if you set the targetSdkVersion="11", your app includes the {@link android.app.ActionBar} by default -on Android 3.0 and higher. To then add menu items to the action bar, you need to set -android:showAsAction="ifRoom" in your menu resource XML. It's safe to do this -in a cross-version XML file, because the older versions of Android simply ignore the -showAsAction attribute (that is, you do not need a separate +on Android 3.0 and higher. To then add menu items to the action bar, you need to set +android:showAsAction="ifRoom" in your menu resource XML. It's safe to do this +in a cross-version XML file, because the older versions of Android simply ignore the +showAsAction attribute (that is, you do not need a separate version in res/menu-v11/).

      -

      Use Platform Styles and Themes

      +

      Use Platform Styles and Themes

      -

      Android provides user experience themes that give apps the look and feel of the -underlying operating system. These themes can be applied to your app within the -manifest file. By using these built in styles and themes, your app will +

      Android provides user experience themes that give apps the look and feel of the +underlying operating system. These themes can be applied to your app within the +manifest file. By using these built in styles and themes, your app will naturally follow the latest look and feel of Android with each new release.

      To make your activity look like a dialog box:

      @@ -126,7 +126,7 @@ naturally follow the latest look and feel of Android with each new release.

      <activity android:theme="@style/CustomTheme">

      To apply a theme to your entire app (all activities), add the android:theme -attribute +attribute to the {@code } element:

      diff --git a/docs/html/training/basics/supporting-devices/screens.jd b/docs/html/training/basics/supporting-devices/screens.jd index 4b54de8e243ca881bccab587baf532982ecac0b3..9d5e7c17ce2e878bc2b5a4a7ff4a88e36db79d0d 100644 --- a/docs/html/training/basics/supporting-devices/screens.jd +++ b/docs/html/training/basics/supporting-devices/screens.jd @@ -8,13 +8,13 @@ trainingnavtop=true -

      Android categorizes device screens using two general properties: size and density. You should -expect that your app will be installed on devices with screens that range in both size -and density. As such, you should include some alternative resources that optimize your app’s +

      Android categorizes device screens using two general properties: size and density. You should +expect that your app will be installed on devices with screens that range in both size +and density. As such, you should include some alternative resources that optimize your app’s appearance for different screen sizes and densities.

        @@ -46,12 +46,12 @@ screen size, so many apps should revise the layout to optimize the user experien orientation.

        -

        Create Different Layouts

        +

        Create Different Layouts

        To optimize your user experience on different screen sizes, you should create a unique layout XML -file for each screen size you want to support. Each layout should be -saved into the appropriate resources directory, named with a -<screen_size> -suffix. For example, a unique layout for large screens should be saved under +file for each screen size you want to support. Each layout should be +saved into the appropriate resources directory, named with a -<screen_size> +suffix. For example, a unique layout for large screens should be saved under res/layout-large/.

        Note: Android automatically scales your layout in order to @@ -85,7 +85,7 @@ an optimized UI for the corresponding screen size.

        }
      -

      The system loads the layout file from the appropriate layout directory based on screen size of +

      The system loads the layout file from the appropriate layout directory based on screen size of the device on which your app is running. More information about how Android selects the appropriate resource is available in the Providing Resources @@ -120,7 +120,7 @@ MyProject/ main.xml

      -

      Note: Android 3.2 and above supports an advanced method of +

      Note: Android 3.2 and above supports an advanced method of defining screen sizes that allows you to specify resources for screen sizes based on the minimum width and height in terms of density-independent pixels. This lesson does not cover this new technique. For more information, read Designing for Multiple Screens.

      - +

      Create Different Bitmaps

      You should always provide bitmap resources that are properly scaled to each of the generalized density buckets: low, medium, high and extra-high density. This helps you achieve good graphical quality and performance on all screen densities.

      -

      To generate these images, you should start with your raw resource in vector format and generate +

      To generate these images, you should start with your raw resource in vector format and generate the images for each density using the following size scale:

      • xhdpi: 2.0
      • @@ -144,7 +144,7 @@ the images for each density using the following size scale:

      • ldpi: 0.75
      -

      This means that if you generate a 200x200 image for xhdpi devices, you should generate the same +

      This means that if you generate a 200x200 image for xhdpi devices, you should generate the same resource in 150x150 for hdpi, 100x100 for mdpi, and 75x75 for ldpi devices.

      Then, place the files in the appropriate drawable resource directory:

      @@ -162,14 +162,14 @@ MyProject/ awesomeimage.png
    -

    Any time you reference @drawable/awesomeimage, the system selects the +

    Any time you reference @drawable/awesomeimage, the system selects the appropriate bitmap based on the screen's density.

    Note: Low-density (ldpi) resources aren’t always necessary. When you provide hdpi assets, the system scales them down by one half to properly fit ldpi screens.

    -

    For more tips and guidelines about creating icon assets for your app, see the +

    For more tips and guidelines about creating icon assets for your app, see the Iconography design guide.

    diff --git a/docs/html/training/best-performance.jd b/docs/html/training/best-performance.jd index 8ea6fd5be4e5104703a57224436411246e9643e0..bb88e990ce486161632d0e9b24d5e24307243fb2 100644 --- a/docs/html/training/best-performance.jd +++ b/docs/html/training/best-performance.jd @@ -5,4 +5,9 @@ page.trainingcourse=true

    These classes and articles help you build an app that's smooth, responsive, -and uses as little battery as possible.

    \ No newline at end of file +and uses as little battery as possible.

    + +

    Along with this section, you can find additional information about optimizing +your app in the Performance and +Power section.

    + diff --git a/docs/html/training/building-userinfo.jd b/docs/html/training/building-userinfo.jd index 40e5b94c6d8094355e99a60775c9de232234d76f..a08899d4d18246b35a40732d0354b9b53708a14f 100644 --- a/docs/html/training/building-userinfo.jd +++ b/docs/html/training/building-userinfo.jd @@ -4,6 +4,6 @@ page.trainingcourse=true @jd:body -

    These lessons teach you how to include contact information and authenticate users with the same -credentials they use for Google. These features allow your app to connect users with people they +

    These lessons teach you how to include contact information and authenticate users with the same +credentials they use for Google. These features allow your app to connect users with people they care about and provide a personalized experience without creating new user accounts.

    diff --git a/docs/html/training/camera/cameradirect.jd b/docs/html/training/camera/cameradirect.jd index 6f358a52befc9295341c7f078ffd9a3ed55b5320..851c7db0d198ffcf908e012f18e81a0ad287e53d 100644 --- a/docs/html/training/camera/cameradirect.jd +++ b/docs/html/training/camera/cameradirect.jd @@ -11,7 +11,7 @@ previous.link=videobasics.html
    - +

    This lesson teaches you to

    1. Open the Camera Object
    2. @@ -22,7 +22,7 @@ previous.link=videobasics.html
    3. Restart the Preview
    4. Stop the Preview and Release the Camera
    - +

    You should also read

    When it comes to impact on battery life, not all connection types are created equal. Not only does the Wi-Fi radio use significantly less battery than its wireless radio counterparts, but the radios used in different wireless radio technologies have different battery implications.

    - +

    Use Wi-Fi

    In most cases a Wi-Fi radio will offer greater bandwidth at a significantly lower battery cost. As a result, you should endeavor to perform data transfers when connected over Wi-Fi whenever possible.

    @@ -50,22 +50,22 @@ previous.link=redundant_redundant.html TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); - + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - + int PrefetchCacheSize = DEFAULT_PREFETCH_CACHE; - + switch (activeNetwork.getType()) { - case (ConnectivityManager.TYPE_WIFI): + case (ConnectivityManager.TYPE_WIFI): PrefetchCacheSize = MAX_PREFETCH_CACHE; break; case (ConnectivityManager.TYPE_MOBILE): { switch (tm.getNetworkType()) { - case (TelephonyManager.NETWORK_TYPE_LTE | - TelephonyManager.NETWORK_TYPE_HSPAP): + case (TelephonyManager.NETWORK_TYPE_LTE | + TelephonyManager.NETWORK_TYPE_HSPAP): PrefetchCacheSize *= 4; break; - case (TelephonyManager.NETWORK_TYPE_EDGE | - TelephonyManager.NETWORK_TYPE_GPRS): + case (TelephonyManager.NETWORK_TYPE_EDGE | + TelephonyManager.NETWORK_TYPE_GPRS): PrefetchCacheSize /= 2; break; default: break; diff --git a/docs/html/training/efficient-downloads/efficient-network-access.jd b/docs/html/training/efficient-downloads/efficient-network-access.jd index 1d3a8a59c681287b72b783e2076a115ee0acdde6..7f061cae38076de4c6e1f57bc5b4c5090f4d65b7 100644 --- a/docs/html/training/efficient-downloads/efficient-network-access.jd +++ b/docs/html/training/efficient-downloads/efficient-network-access.jd @@ -32,9 +32,9 @@ next.link=regular_updates.html

    Using the wireless radio to transfer data is potentially one of your app's most significant sources of battery drain. To minimize the battery drain associated with network activity, it's critical that you understand how your connectivity model will affect the underlying radio hardware.

    This lesson introduces the wireless radio state machine and explains how your app's connectivity model interacts with it. It goes on to propose ways to minimize your data connections, use prefetching, and bundle your transfers in order to minimize the battery drain associated with your data transfers.

    - -

    The Radio State Machine

    - + +

    The Radio State Machine

    +

    A fully active wireless radio consumes significant power, so it transitions between different energy states in order to conserve power when not in use, while attempting to minimize latency associated with "powering up" the radio when it's required.

    The state machine for a typical 3G network radio consists of three energy states: @@ -57,9 +57,9 @@ next.link=regular_updates.html

    This approach is particularly effective for typical web browsing as it prevents unwelcome latency while users browse the web. The relatively low tail-time also ensures that once a browsing session has finished, the radio can move to a lower energy state.

    Unfortunately, this approach can lead to inefficient apps on modern smartphone OSs like Android, where apps run both in the foreground (where latency is important) and in the background (where battery life should be prioritized).

    - -

    How Apps Impact the Radio State Machine

    - + +

    How Apps Impact the Radio State Machine

    +

    Every time you create a new network connection, the radio transitions to the full power state. In the case of the typical 3G radio state machine described above, it will remain at full power for the duration of your transfer—plus an additional 5 seconds of tail time—followed by 12 seconds at the low energy state. So for a typical 3G device, every data transfer session will cause the radio to draw energy for almost 20 seconds.

    In practice, this means an app that transfers unbundled data for 1 second every 18 seconds will keep the wireless radio perpetually active, moving it back to high power just as it was about to become idle. As a result, every minute it will consume battery at the high power state for 18 seconds, and at the low power state for the remaining 42 seconds.

    @@ -71,7 +71,7 @@ next.link=regular_updates.html

    Figure 2. Relative wireless radio power use for bundled versus unbundled transfers.

    -

    Prefetch Data

    +

    Prefetch Data

    Prefetching data is an effective way to reduce the number of independent data transfer sessions. Prefetching allows you to download all the data you are likely to need for a given time period in a single burst, over a single connection, at full capacity.

    @@ -135,7 +135,7 @@ Every time you initiate a connection—irrespective of the size of the assoc

    Rather than creating multiple simultaneous connections to download data, or chaining multiple consecutive GET requests, where possible you should bundle those requests into a single GET.

    -

    For example, it would be more efficient to make a single request for every news article to be returned in a single request / response than to make multiple queries for several news categories. +

    For example, it would be more efficient to make a single request for every news article to be returned in a single request / response than to make multiple queries for several news categories. The wireless radio needs to become active in order to transmit the termination / termination acknowledgement packets associated with server and client timeout, so it's also good practice to close your connections when they aren't in use, rather than waiting for these timeouts.

    That said, closing a connection too early can prevent it from being reused, which then requires additional overhead for establishing a new connection. A useful compromise is not to close the connection immediately, but to still close it before the inherent timeout expires.

    diff --git a/docs/html/training/efficient-downloads/index.jd b/docs/html/training/efficient-downloads/index.jd index d9d7ef078a448b5b897bc54aff8ba577a74c9d34..a4c2aa16e7b55ae8a7ec1cc20a5ffc646bd824a8 100644 --- a/docs/html/training/efficient-downloads/index.jd +++ b/docs/html/training/efficient-downloads/index.jd @@ -26,18 +26,18 @@ startpage=true

    In this class you will learn to minimize the battery life impact of downloads and network connections, particularly in relation to the wireless radio.

    This class demonstrates the best practices for scheduling and executing downloads using techniques such as caching, polling, and prefetching. You will learn how the power-use profile of the wireless radio can affect your choices on when, what, and how to transfer data in order to minimize impact on battery life.

    +

    This class demonstrates the best practices for scheduling and executing downloads using techniques such as caching, polling, and prefetching. You will learn how the power-use profile of the wireless radio can affect your choices on when, what, and how to transfer data in order to minimize impact on battery life.

    + +

    Lessons

    -

    Lessons

    - - -
    +will want to jump to a lesson or not.--> + +
    Optimizing Downloads for Efficient Network Access
    This lesson introduces the wireless radio state machine, explains how your app’s connectivity model interacts with it, and how you can minimize your data connection and use prefetching and bundling to minimize the battery drain associated with your data transfers.
    - +
    Minimizing the Effect of Regular Updates
    This lesson will examine how your refresh frequency can be varied to best mitigate the effect of background updates on the underlying wireless radio state machine.
    @@ -47,4 +47,4 @@ will want to jump to a lesson or not.-->
    Modifying your Download Patterns Based on the Connectivity Type
    When it comes to impact on battery life, not all connection types are created equal. Not only does the Wi-Fi radio use significantly less battery than its wireless radio counterparts, but the radios used in different wireless radio technologies have different battery implications.
    -
    +
    diff --git a/docs/html/training/efficient-downloads/regular_updates.jd b/docs/html/training/efficient-downloads/regular_updates.jd index 8e3842a80d4d90a6b93ddae1c5283c89ff88a4cf..b87c5122e39f742e4c81b84d24e292523b66f8fc 100644 --- a/docs/html/training/efficient-downloads/regular_updates.jd +++ b/docs/html/training/efficient-downloads/regular_updates.jd @@ -33,9 +33,9 @@ next.link=redundant_redundant.html

    Optimizing Battery Life discusses how to build battery-efficient apps that modify their refresh frequency based on the state of the host device. That includes disabling background service updates when you lose connectivity and reducing the rate of updates when the battery level is low.

    This lesson will examine how your refresh frequency can be varied to best mitigate the effect of background updates on the underlying wireless radio state machine.

    - -

    Use Google Cloud Messaging as an Alternative to Polling

    - + +

    Use Google Cloud Messaging as an Alternative to Polling

    +

    Every time your app polls your server to check if an update is required, you activate the wireless radio, drawing power unnecessarily, for up to 20 seconds on a typical 3G connection.

    Google Cloud Messaging for Android (GCM) is a lightweight mechanism used to transmit data from a server to a particular app instance. Using GCM, your server can notify your app running on a particular device that there is new data available for it.

    @@ -46,7 +46,7 @@ next.link=redundant_redundant.html

    GCM is implemented using a persistent TCP/IP connection. While it's possible to implement your own push service, it's best practice to use GCM. This minimizes the number of persistent connections and allows the platform to optimize bandwidth and minimize the associated impact on battery life.

    -

    Optimize Polling with Inexact Repeating Alarms and Exponential Backoffs

    +

    Optimize Polling with Inexact Repeating Alarms and Exponential Backoffs

    Where polling is required, it's good practice to set the default data refresh frequency of your app as low as possible without detracting from the user experience.

    @@ -68,14 +68,14 @@ alarmManager.setInexactRepeating(alarmType, start, interval, pi);

    One approach is to implement an exponential back-off pattern to reduce the frequency of your updates (and / or the degree of prefetching you perform) if the app hasn't been used since the previous update. It's often useful to assert a minimum update frequency and to reset the frequency whenever the app is used, for example:

    -
    SharedPreferences sp = 
    +
    SharedPreferences sp =
       context.getSharedPreferences(PREFS, Context.MODE_WORLD_READABLE);
     
     boolean appUsed = sp.getBoolean(PREFS_APPUSED, false);
     long updateInterval = sp.getLong(PREFS_INTERVAL, DEFAULT_REFRESH_INTERVAL);
     
     if (!appUsed)
    -  if ((updateInterval *= 2) > MAX_REFRESH_INTERVAL)  
    +  if ((updateInterval *= 2) > MAX_REFRESH_INTERVAL)
         updateInterval = MAX_REFRESH_INTERVAL;
     
     Editor spEdit = sp.edit();
    @@ -92,10 +92,10 @@ executeUpdateOrPrefetch();
    private void retryIn(long interval) {
       boolean success = attemptTransfer();
    -    
    +
       if (!success) {
    -    retryIn(interval*2 < MAX_RETRY_INTERVAL ? 
    -            interval*2 : MAX_RETRY_INTERVAL);      
    +    retryIn(interval*2 < MAX_RETRY_INTERVAL ?
    +            interval*2 : MAX_RETRY_INTERVAL);
       }
     }
    diff --git a/docs/html/training/gestures/detector.jd b/docs/html/training/gestures/detector.jd index 97f039c709a8af3565315026c90359ee0db7ea9b..0624e86335bce5fc8108fdf3d892dfdd083737ff 100644 --- a/docs/html/training/gestures/detector.jd +++ b/docs/html/training/gestures/detector.jd @@ -48,48 +48,48 @@ phases to gesture detection:

    1. Gathering data about touch events.
    2. - +
    3. Interpreting the data to see if it meets the criteria for any of the -gestures your app supports.
    4. +gestures your app supports.

    Support Library Classes

    The examples in this lesson use the {@link android.support.v4.view.GestureDetectorCompat} -and {@link android.support.v4.view.MotionEventCompat} classes. These classes are in the +and {@link android.support.v4.view.MotionEventCompat} classes. These classes are in the Support Library. You should use -Support Library classes where possible to provide compatibility with devices -running Android 1.6 and higher. Note that {@link android.support.v4.view.MotionEventCompat} is not a -replacement for the {@link android.view.MotionEvent} class. Rather, it provides static utility -methods to which you pass your {@link android.view.MotionEvent} object in order to receive +Support Library classes where possible to provide compatibility with devices +running Android 1.6 and higher. Note that {@link android.support.v4.view.MotionEventCompat} is not a +replacement for the {@link android.view.MotionEvent} class. Rather, it provides static utility +methods to which you pass your {@link android.view.MotionEvent} object in order to receive the desired action associated with that event.

    Gather Data

    When a user places one or more fingers on the screen, this triggers the -callback {@link android.view.View#onTouchEvent onTouchEvent()} +callback {@link android.view.View#onTouchEvent onTouchEvent()} on the View that received the touch events. -For each sequence of touch events (position, pressure, size, addition of another finger, etc.) +For each sequence of touch events (position, pressure, size, addition of another finger, etc.) that is ultimately identified as a gesture, {@link android.view.View#onTouchEvent onTouchEvent()} is fired several times.

    The gesture starts when the user first touches the screen, continues as the system tracks the position of the user's finger(s), and ends by capturing the final event of -the user's fingers leaving the screen. Throughout this interaction, -the {@link android.view.MotionEvent} delivered to {@link android.view.View#onTouchEvent onTouchEvent()} -provides the details of every interaction. Your app can use the data provided by the {@link android.view.MotionEvent} +the user's fingers leaving the screen. Throughout this interaction, +the {@link android.view.MotionEvent} delivered to {@link android.view.View#onTouchEvent onTouchEvent()} +provides the details of every interaction. Your app can use the data provided by the {@link android.view.MotionEvent} to determine if a gesture it cares about happened.

    Capturing touch events for an Activity or View

    -

    To intercept touch events in an Activity or View, override +

    To intercept touch events in an Activity or View, override the {@link android.view.View#onTouchEvent onTouchEvent()} callback.

    -

    The following snippet uses +

    The following snippet uses {@link android.support.v4.view.MotionEventCompat#getActionMasked getActionMasked()} -to extract the action the user performed from the {@code event} parameter. This gives you the raw +to extract the action the user performed from the {@code event} parameter. This gives you the raw data you need to determine if a gesture you care about occurred:

    @@ -98,10 +98,10 @@ public class MainActivity extends Activity {
     // This example shows an Activity, but you would use the same approach if
     // you were subclassing a View.
     @Override
    -public boolean onTouchEvent(MotionEvent event){ 
    -        
    +public boolean onTouchEvent(MotionEvent event){
    +
         int action = MotionEventCompat.getActionMasked(event);
    -        
    +
         switch(action) {
             case (MotionEvent.ACTION_DOWN) :
                 Log.d(DEBUG_TAG,"Action was DOWN");
    @@ -118,10 +118,10 @@ public boolean onTouchEvent(MotionEvent event){
             case (MotionEvent.ACTION_OUTSIDE) :
                 Log.d(DEBUG_TAG,"Movement occurred outside bounds " +
                         "of current screen element");
    -            return true;      
    -        default : 
    +            return true;
    +        default :
                 return super.onTouchEvent(event);
    -    }      
    +    }
     }

    You can then do your own processing on these events to determine if a @@ -143,22 +143,22 @@ setOnTouchListener()} method. This makes it possible to to listen for touch events without subclassing an existing {@link android.view.View}. For example:

    -
    View myView = findViewById(R.id.my_view); 
    +
    View myView = findViewById(R.id.my_view);
     myView.setOnTouchListener(new OnTouchListener() {
         public boolean onTouch(View v, MotionEvent event) {
    -        // ... Respond to touch events       
    +        // ... Respond to touch events
             return true;
         }
     });
    -

    Beware of creating a listener that returns {@code false} for the -{@link android.view.MotionEvent#ACTION_DOWN} event. If you do this, the listener will -not be called for the subsequent {@link android.view.MotionEvent#ACTION_MOVE} +

    Beware of creating a listener that returns {@code false} for the +{@link android.view.MotionEvent#ACTION_DOWN} event. If you do this, the listener will +not be called for the subsequent {@link android.view.MotionEvent#ACTION_MOVE} and {@link android.view.MotionEvent#ACTION_UP} string of events. This is because {@link android.view.MotionEvent#ACTION_DOWN} is the starting point for all touch events.

    -

    If you are creating a custom View, you can override -{@link android.view.View#onTouchEvent onTouchEvent()}, +

    If you are creating a custom View, you can override +{@link android.view.View#onTouchEvent onTouchEvent()}, as described above.

    Detect Gestures

    @@ -168,24 +168,24 @@ common gestures. Some of the gestures it supports include {@link android.view.GestureDetector.OnGestureListener#onDown onDown()}, {@link android.view.GestureDetector.OnGestureListener#onLongPress onLongPress()}, {@link android.view.GestureDetector.OnGestureListener#onFling onFling()}, and so -on. You can use {@link android.view.GestureDetector} in conjunction with the +on. You can use {@link android.view.GestureDetector} in conjunction with the {@link android.view.View#onTouchEvent onTouchEvent()} method described above.

    Detecting All Supported Gestures

    -

    When you instantiate a {@link android.support.v4.view.GestureDetectorCompat} -object, one of the parameters it takes is a class that implements the -{@link android.view.GestureDetector.OnGestureListener} interface. -{@link android.view.GestureDetector.OnGestureListener} notifies users when -a particular touch event has occurred. To make it possible for your -{@link android.view.GestureDetector} object to receive events, you override -the View or Activity's {@link android.view.View#onTouchEvent onTouchEvent()} method, +

    When you instantiate a {@link android.support.v4.view.GestureDetectorCompat} +object, one of the parameters it takes is a class that implements the +{@link android.view.GestureDetector.OnGestureListener} interface. +{@link android.view.GestureDetector.OnGestureListener} notifies users when +a particular touch event has occurred. To make it possible for your +{@link android.view.GestureDetector} object to receive events, you override +the View or Activity's {@link android.view.View#onTouchEvent onTouchEvent()} method, and pass along all observed events to the detector instance.

    -

    In the following snippet, a return value of {@code true} from the individual +

    In the following snippet, a return value of {@code true} from the individual on<TouchEvent> methods indicates that you have handled the touch event. A return value of {@code false} passes events down through the view stack until the touch has been successfully handled.

    @@ -195,14 +195,14 @@ you interact with the touch screen, and what the contents of the {@link android.view.MotionEvent} are for each touch event. You will realize how much data is being generated for even simple interactions.

    -
    public class MainActivity extends Activity implements 
    +
    public class MainActivity extends Activity implements
             GestureDetector.OnGestureListener,
             GestureDetector.OnDoubleTapListener{
    -    
    +
         private static final String DEBUG_TAG = "Gestures";
    -    private GestureDetectorCompat mDetector; 
    +    private GestureDetectorCompat mDetector;
     
    -    // Called when the activity is first created. 
    +    // Called when the activity is first created.
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
    @@ -216,21 +216,21 @@ data is being generated for even simple interactions.

    mDetector.setOnDoubleTapListener(this); } - @Override - public boolean onTouchEvent(MotionEvent event){ + @Override + public boolean onTouchEvent(MotionEvent event){ this.mDetector.onTouchEvent(event); // Be sure to call the superclass implementation return super.onTouchEvent(event); } @Override - public boolean onDown(MotionEvent event) { - Log.d(DEBUG_TAG,"onDown: " + event.toString()); + public boolean onDown(MotionEvent event) { + Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override - public boolean onFling(MotionEvent event1, MotionEvent event2, + public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString()); return true; @@ -238,7 +238,7 @@ data is being generated for even simple interactions.

    @Override public void onLongPress(MotionEvent event) { - Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); + Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); } @Override @@ -294,23 +294,23 @@ android.view.GestureDetector.SimpleOnGestureListener} and overrides {@link android.view.GestureDetector.OnGestureListener#onFling onFling()} and {@link android.view.GestureDetector.OnGestureListener#onDown onDown()}.

    -

    Whether or not you use {@link android.view.GestureDetector.OnGestureListener}, -it's best practice to implement an -{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} -method that returns {@code true}. This is because all gestures begin with an -{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} message. If you return -{@code false} from {@link android.view.GestureDetector.OnGestureListener#onDown onDown()}, -as {@link android.view.GestureDetector.SimpleOnGestureListener} does by default, -the system assumes that you want to ignore the rest of the gesture, and the other methods of -{@link android.view.GestureDetector.OnGestureListener} never get called. -This has the potential to cause unexpected problems in your app. -The only time you should return {@code false} from -{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} +

    Whether or not you use {@link android.view.GestureDetector.OnGestureListener}, +it's best practice to implement an +{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} +method that returns {@code true}. This is because all gestures begin with an +{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} message. If you return +{@code false} from {@link android.view.GestureDetector.OnGestureListener#onDown onDown()}, +as {@link android.view.GestureDetector.SimpleOnGestureListener} does by default, +the system assumes that you want to ignore the rest of the gesture, and the other methods of +{@link android.view.GestureDetector.OnGestureListener} never get called. +This has the potential to cause unexpected problems in your app. +The only time you should return {@code false} from +{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} is if you truly want to ignore an entire gesture.

    -
    public class MainActivity extends Activity { 
    -    
    -    private GestureDetectorCompat mDetector; 
    +
    public class MainActivity extends Activity {
    +
    +    private GestureDetectorCompat mDetector;
     
         @Override
         public void onCreate(Bundle savedInstanceState) {
    @@ -319,23 +319,23 @@ is if you truly want to ignore an entire gesture. 

    mDetector = new GestureDetectorCompat(this, new MyGestureListener()); } - @Override - public boolean onTouchEvent(MotionEvent event){ + @Override + public boolean onTouchEvent(MotionEvent event){ this.mDetector.onTouchEvent(event); return super.onTouchEvent(event); } - + class MyGestureListener extends GestureDetector.SimpleOnGestureListener { - private static final String DEBUG_TAG = "Gestures"; - + private static final String DEBUG_TAG = "Gestures"; + @Override - public boolean onDown(MotionEvent event) { - Log.d(DEBUG_TAG,"onDown: " + event.toString()); + public boolean onDown(MotionEvent event) { + Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override - public boolean onFling(MotionEvent event1, MotionEvent event2, + public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString()); return true; diff --git a/docs/html/training/gestures/index.jd b/docs/html/training/gestures/index.jd index 260cfff33073de0b27fa73d22f3c05cb4ff4805b..1b8f4c120a20645a9af3874efb9abb5b142c6d38 100644 --- a/docs/html/training/gestures/index.jd +++ b/docs/html/training/gestures/index.jd @@ -48,7 +48,7 @@ interaction to your app can greatly increase its usefulness and appeal.

    provide users with a consistent, intuitive experience, your app should follow the accepted Android conventions for touch gestures. The Gestures -design guide +design guide shows you how to use common gestures in Android apps. Also see the Design Guide for Touch Feedback.

    @@ -60,7 +60,7 @@ for Touch Feedback. Detecting Common Gestures
    - Learn how to detect basic touch gestures such as scrolling, flinging, and double-tapping, using + Learn how to detect basic touch gestures such as scrolling, flinging, and double-tapping, using {@link android.view.GestureDetector}.
    @@ -84,7 +84,7 @@ touch event.
    Learn how to detect multi-pointer (finger) gestures. -
    +
    Dragging and Scaling
    diff --git a/docs/html/training/gestures/movement.jd b/docs/html/training/gestures/movement.jd index ed4928eb30419fcbf7c6355e4739a87530e058e3..0a611b3d6daffdef294bc714bcf402b1b104c0b4 100644 --- a/docs/html/training/gestures/movement.jd +++ b/docs/html/training/gestures/movement.jd @@ -55,13 +55,13 @@ detecting touch events is often based more on movement than on simple contact. To help apps distinguish between movement-based gestures (such as a swipe) and non-movement gestures (such as a single tap), Android includes the notion of "touch slop." Touch slop refers to the distance in pixels a user's touch can wander -before the gesture is interpreted as a movement-based gesture. For more discussion of this +before the gesture is interpreted as a movement-based gesture. For more discussion of this topic, see Managing Touch Events in a ViewGroup.

    There are several different ways to track movement in a gesture, depending on -the needs of your application. For example:

    +the needs of your application. For example:

      @@ -89,8 +89,8 @@ details.

      You could have a movement-based gesture that is simply based on the distance and/or direction the pointer traveled. But velocity often is a determining factor in tracking a gesture's characteristics or even deciding whether the gesture occurred. To make velocity calculation easier, Android -provides the {@link android.view.VelocityTracker} class and the -{@link android.support.v4.view.VelocityTrackerCompat} class in the +provides the {@link android.view.VelocityTracker} class and the +{@link android.support.v4.view.VelocityTrackerCompat} class in the Support Library. {@link android.view.VelocityTracker} helps you track the velocity of touch events. This @@ -98,7 +98,7 @@ is useful for gestures in which velocity is part of the criteria for the gesture, such as a fling.

      -

      Here is a simple example that illustrates the purpose of the methods in the +

      Here is a simple example that illustrates the purpose of the methods in the {@link android.view.VelocityTracker} API:

      public class MainActivity extends Activity {
      @@ -126,16 +126,16 @@ gesture, such as a fling.

      break; case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); - // When you want to determine the velocity, call - // computeCurrentVelocity(). Then call getXVelocity() - // and getYVelocity() to retrieve the velocity for each pointer ID. + // When you want to determine the velocity, call + // computeCurrentVelocity(). Then call getXVelocity() + // and getYVelocity() to retrieve the velocity for each pointer ID. mVelocityTracker.computeCurrentVelocity(1000); // Log velocity of pixels per second // Best practice to use VelocityTrackerCompat where possible. - Log.d("", "X velocity: " + - VelocityTrackerCompat.getXVelocity(mVelocityTracker, + Log.d("", "X velocity: " + + VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId)); - Log.d("", "Y velocity: " + + Log.d("", "Y velocity: " + VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId)); break; @@ -150,8 +150,8 @@ gesture, such as a fling.

      }
      -

      Note: Note that you should calculate velocity after an -{@link android.view.MotionEvent#ACTION_MOVE} event, -not after {@link android.view.MotionEvent#ACTION_UP}. After an {@link android.view.MotionEvent#ACTION_UP}, +

      Note: Note that you should calculate velocity after an +{@link android.view.MotionEvent#ACTION_MOVE} event, +not after {@link android.view.MotionEvent#ACTION_UP}. After an {@link android.view.MotionEvent#ACTION_UP}, the X and Y velocities will be 0.

      diff --git a/docs/html/training/gestures/multi.jd b/docs/html/training/gestures/multi.jd index 58404827682dde7d539c0a1683b7806ae087e20d..21860fcaeb2c2bca2d069c846b70fd8e9450258e 100644 --- a/docs/html/training/gestures/multi.jd +++ b/docs/html/training/gestures/multi.jd @@ -47,15 +47,15 @@ multiple pointers.

      Track Multiple Pointers

      -

      When multiple pointers touch the screen at the same time, the system generates the +

      When multiple pointers touch the screen at the same time, the system generates the following touch events:

        -
      • {@link android.view.MotionEvent#ACTION_DOWN}—For the first pointer that -touches the screen. This starts the gesture. The pointer data for this pointer is +
      • {@link android.view.MotionEvent#ACTION_DOWN}—For the first pointer that +touches the screen. This starts the gesture. The pointer data for this pointer is always at index 0 in the {@link android.view.MotionEvent}.
      • -
      • {@link android.support.v4.view.MotionEventCompat#ACTION_POINTER_DOWN}—For -extra pointers that enter the screen beyond the first. The pointer data for this +
      • {@link android.support.v4.view.MotionEventCompat#ACTION_POINTER_DOWN}—For +extra pointers that enter the screen beyond the first. The pointer data for this pointer is at the index returned by {@link android.support.v4.view.MotionEventCompat#getActionIndex getActionIndex()}.
      • {@link android.view.MotionEvent#ACTION_MOVE}—A change has happened during a press gesture.
      • {@link android.support.v4.view.MotionEventCompat#ACTION_POINTER_UP}—Sent when a non-primary pointer goes up.
      • @@ -66,20 +66,20 @@ pointer is at the index returned by {@link android.support.v4.view.MotionEventCo android.view.MotionEvent} via each pointer's index and ID:

          -
        • Index: A {@link android.view.MotionEvent} effectively -stores information about each pointer in an array. The index of a pointer is its position +
        • Index: A {@link android.view.MotionEvent} effectively +stores information about each pointer in an array. The index of a pointer is its position within this array. Most of the {@link android.view.MotionEvent} methods you use to interact with pointers take the pointer index as a parameter, not the pointer ID.
        • - - + +
        • ID: Each pointer also has an ID mapping that stays -persistent across touch events to allow tracking an individual pointer across +persistent across touch events to allow tracking an individual pointer across the entire gesture.
        • - +
        -

        The order in which individual pointers appear within a motion event is +

        The order in which individual pointers appear within a motion event is undefined. Thus the index of a pointer can change from one event to the next, but the pointer ID of a pointer is guaranteed to remain constant as long as the pointer remains active. Use the {@link @@ -91,7 +91,7 @@ the pointer index for a given pointer ID in that motion event. For example:

        private int mActivePointerId;
        - 
        +
         public boolean onTouchEvent(MotionEvent event) {
             ....
             // Get the pointer ID
        @@ -99,7 +99,7 @@ public boolean onTouchEvent(MotionEvent event) {
         
             // ... Many touch events later...
         
        -    // Use the pointer ID to find the index of the active pointer 
        +    // Use the pointer ID to find the index of the active pointer
             // and fetch its position
             int pointerIndex = event.findPointerIndex(mActivePointerId);
             // Get the pointer's current position
        @@ -109,25 +109,25 @@ public boolean onTouchEvent(MotionEvent event) {
         
         

        Get a MotionEvent's Action

        -

        You should always use the method -{@link android.view.MotionEvent#getActionMasked getActionMasked()} (or better yet, the compatability version -{@link android.support.v4.view.MotionEventCompat#getActionMasked MotionEventCompat.getActionMasked()}) to retrieve +

        You should always use the method +{@link android.view.MotionEvent#getActionMasked getActionMasked()} (or better yet, the compatability version +{@link android.support.v4.view.MotionEventCompat#getActionMasked MotionEventCompat.getActionMasked()}) to retrieve the action of a -{@link android.view.MotionEvent}. Unlike the older {@link android.view.MotionEvent#getAction getAction()} -method, {@link android.support.v4.view.MotionEventCompat#getActionMasked getActionMasked()} is designed to work with -multiple pointers. It returns the masked action -being performed, without including the pointer index bits. You can then use -{@link android.support.v4.view.MotionEventCompat#getActionIndex getActionIndex()} to return the index of +{@link android.view.MotionEvent}. Unlike the older {@link android.view.MotionEvent#getAction getAction()} +method, {@link android.support.v4.view.MotionEventCompat#getActionMasked getActionMasked()} is designed to work with +multiple pointers. It returns the masked action +being performed, without including the pointer index bits. You can then use +{@link android.support.v4.view.MotionEventCompat#getActionIndex getActionIndex()} to return the index of the pointer associated with the action. This is illustrated in the snippet below.

        -

        Note: This example uses the +

        Note: This example uses the {@link android.support.v4.view.MotionEventCompat} -class. This class is in the +class. This class is in the Support Library. You should use {@link android.support.v4.view.MotionEventCompat} to provide the best support for a wide range of -platforms. Note that {@link android.support.v4.view.MotionEventCompat} is not a -replacement for the {@link android.view.MotionEvent} class. Rather, it provides static utility -methods to which you pass your {@link android.view.MotionEvent} object in order to receive +platforms. Note that {@link android.support.v4.view.MotionEventCompat} is not a +replacement for the {@link android.view.MotionEvent} class. Rather, it provides static utility +methods to which you pass your {@link android.view.MotionEvent} object in order to receive the desired action associated with that event.

        int action = MotionEventCompat.getActionMasked(event);
        @@ -137,17 +137,17 @@ int xPos = -1;
         int yPos = -1;
         
         Log.d(DEBUG_TAG,"The action is " + actionToString(action));
        -	    
        +
         if (event.getPointerCount() > 1) {
        -    Log.d(DEBUG_TAG,"Multitouch event"); 
        -    // The coordinates of the current screen contact, relative to 
        -    // the responding View or Activity.  
        +    Log.d(DEBUG_TAG,"Multitouch event");
        +    // The coordinates of the current screen contact, relative to
        +    // the responding View or Activity.
             xPos = (int)MotionEventCompat.getX(event, index);
             yPos = (int)MotionEventCompat.getY(event, index);
         
         } else {
             // Single touch event
        -    Log.d(DEBUG_TAG,"Single touch event"); 
        +    Log.d(DEBUG_TAG,"Single touch event");
             xPos = (int)MotionEventCompat.getX(event, index);
             yPos = (int)MotionEventCompat.getY(event, index);
         }
        @@ -156,7 +156,7 @@ if (event.getPointerCount() > 1) {
         // Given an action int, returns a string description
         public static String actionToString(int action) {
             switch (action) {
        -	        
        +
                 case MotionEvent.ACTION_DOWN: return "Down";
         	case MotionEvent.ACTION_MOVE: return "Move";
         	case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down";
        @@ -168,7 +168,7 @@ public static String actionToString(int action) {
             return "";
         }
        - +

        For more discussion of multi-touch and some examples, see the lesson Dragging and Scaling. diff --git a/docs/html/training/gestures/scale.jd b/docs/html/training/gestures/scale.jd index f2e4eb82d12285e6c4263c947586dc2c4d8594a6..d4aa91651db7f4b91939d61ba3a100232eeabf4a 100644 --- a/docs/html/training/gestures/scale.jd +++ b/docs/html/training/gestures/scale.jd @@ -44,13 +44,13 @@ class="button">Download the sample

        This lesson describes how to use touch gestures to drag and scale on-screen objects, using {@link android.view.View#onTouchEvent onTouchEvent()} to intercept -touch events. +touch events.

        Drag an Object

        -

        If you are targeting Android 3.0 or higher, you can use the built-in drag-and-drop event -listeners with {@link android.view.View.OnDragListener}, as described in +

        If you are targeting Android 3.0 or higher, you can use the built-in drag-and-drop event +listeners with {@link android.view.View.OnDragListener}, as described in Drag and Drop.

        A common operation for a touch gesture is to use it to drag an object across @@ -66,14 +66,14 @@ the touch screen and lifts the first finger. If your app is just tracking individual pointers, it will regard the second pointer as the default and move the image to that location. -

      • To prevent this from happening, your app needs to distinguish between the -original pointer and any follow-on pointers. To do this, it tracks the -{@link android.view.MotionEvent#ACTION_POINTER_DOWN} and -{@link android.view.MotionEvent#ACTION_POINTER_UP} events described in -Handling Multi-Touch Gestures. -{@link android.view.MotionEvent#ACTION_POINTER_DOWN} and -{@link android.view.MotionEvent#ACTION_POINTER_UP} are -passed to the {@link android.view.View#onTouchEvent onTouchEvent()} callback +
      • To prevent this from happening, your app needs to distinguish between the +original pointer and any follow-on pointers. To do this, it tracks the +{@link android.view.MotionEvent#ACTION_POINTER_DOWN} and +{@link android.view.MotionEvent#ACTION_POINTER_UP} events described in +Handling Multi-Touch Gestures. +{@link android.view.MotionEvent#ACTION_POINTER_DOWN} and +{@link android.view.MotionEvent#ACTION_POINTER_UP} are +passed to the {@link android.view.View#onTouchEvent onTouchEvent()} callback whenever a secondary pointer goes down or up.
      • @@ -90,16 +90,16 @@ calculate the distance to move using data from the correct pointer.

        The following snippet enables a user to drag an object around on the screen. It records the initial position of the active pointer, calculates the distance the pointer traveled, and moves the object to the new position. It correctly manages the possibility of additional pointers, as described -above.

        +above.

        -

        Notice that the snippet uses the {@link android.view.MotionEvent#getActionMasked getActionMasked()} method. -You should always use this method (or better yet, the compatability version -{@link android.support.v4.view.MotionEventCompat#getActionMasked MotionEventCompat.getActionMasked()}) +

        Notice that the snippet uses the {@link android.view.MotionEvent#getActionMasked getActionMasked()} method. +You should always use this method (or better yet, the compatability version +{@link android.support.v4.view.MotionEventCompat#getActionMasked MotionEventCompat.getActionMasked()}) to retrieve the action of a -{@link android.view.MotionEvent}. Unlike the older -{@link android.view.MotionEvent#getAction getAction()} -method, {@link android.support.v4.view.MotionEventCompat#getActionMasked getActionMasked()} -is designed to work with multiple pointers. It returns the masked action +{@link android.view.MotionEvent}. Unlike the older +{@link android.view.MotionEvent#getAction getAction()} +method, {@link android.support.v4.view.MotionEventCompat#getActionMasked getActionMasked()} +is designed to work with multiple pointers. It returns the masked action being performed, without including the pointer index bits.

        // The ‘active pointer’ is the one currently moving our object.
        @@ -109,15 +109,15 @@ private int mActivePointerId = INVALID_POINTER_ID;
         public boolean onTouchEvent(MotionEvent ev) {
             // Let the ScaleGestureDetector inspect all events.
             mScaleDetector.onTouchEvent(ev);
        -             
        -    final int action = MotionEventCompat.getActionMasked(ev); 
        -        
        -    switch (action) { 
        +
        +    final int action = MotionEventCompat.getActionMasked(ev);
        +
        +    switch (action) {
             case MotionEvent.ACTION_DOWN: {
        -        final int pointerIndex = MotionEventCompat.getActionIndex(ev); 
        -        final float x = MotionEventCompat.getX(ev, pointerIndex); 
        -        final float y = MotionEventCompat.getY(ev, pointerIndex); 
        -            
        +        final int pointerIndex = MotionEventCompat.getActionIndex(ev);
        +        final float x = MotionEventCompat.getX(ev, pointerIndex);
        +        final float y = MotionEventCompat.getY(ev, pointerIndex);
        +
                 // Remember where we started (for dragging)
                 mLastTouchX = x;
                 mLastTouchY = y;
        @@ -125,15 +125,15 @@ public boolean onTouchEvent(MotionEvent ev) {
                 mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                 break;
             }
        -            
        +
             case MotionEvent.ACTION_MOVE: {
                 // Find the index of the active pointer and fetch its position
        -        final int pointerIndex = 
        -                MotionEventCompat.findPointerIndex(ev, mActivePointerId);  
        -            
        +        final int pointerIndex =
        +                MotionEventCompat.findPointerIndex(ev, mActivePointerId);
        +
                 final float x = MotionEventCompat.getX(ev, pointerIndex);
                 final float y = MotionEventCompat.getY(ev, pointerIndex);
        -            
        +
                 // Calculate the distance moved
                 final float dx = x - mLastTouchX;
                 final float dy = y - mLastTouchY;
        @@ -149,62 +149,62 @@ public boolean onTouchEvent(MotionEvent ev) {
         
                 break;
             }
        -            
        +
             case MotionEvent.ACTION_UP: {
                 mActivePointerId = INVALID_POINTER_ID;
                 break;
             }
        -            
        +
             case MotionEvent.ACTION_CANCEL: {
                 mActivePointerId = INVALID_POINTER_ID;
                 break;
             }
        -        
        +
             case MotionEvent.ACTION_POINTER_UP: {
        -            
        -        final int pointerIndex = MotionEventCompat.getActionIndex(ev); 
        -        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); 
        +
        +        final int pointerIndex = MotionEventCompat.getActionIndex(ev);
        +        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
         
                 if (pointerId == mActivePointerId) {
                     // This was our active pointer going up. Choose a new
                     // active pointer and adjust accordingly.
                     final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
        -            mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex); 
        -            mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex); 
        +            mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
        +            mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
                     mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
                 }
                 break;
             }
        -    }       
        +    }
             return true;
         }

        Drag to Pan

        -

        The previous section showed an example of dragging an object around the screen. Another -common scenario is panning, which is when a user's dragging motion causes scrolling -in both the x and y axes. The above snippet directly intercepted the {@link android.view.MotionEvent} -actions to implement dragging. The snippet in this section takes advantage of the platform's -built-in support for common gestures. It overrides -{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in +

        The previous section showed an example of dragging an object around the screen. Another +common scenario is panning, which is when a user's dragging motion causes scrolling +in both the x and y axes. The above snippet directly intercepted the {@link android.view.MotionEvent} +actions to implement dragging. The snippet in this section takes advantage of the platform's +built-in support for common gestures. It overrides +{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in {@link android.view.GestureDetector.SimpleOnGestureListener}.

        -

        To provide a little more context, {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} -is called when a user is dragging his finger to pan the content. -{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} is only called when -a finger is down; as soon as the finger is lifted from the screen, the gesture either ends, -or a fling gesture is started (if the finger was moving with some speed just before it was lifted). +

        To provide a little more context, {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} +is called when a user is dragging his finger to pan the content. +{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} is only called when +a finger is down; as soon as the finger is lifted from the screen, the gesture either ends, +or a fling gesture is started (if the finger was moving with some speed just before it was lifted). For more discussion of scrolling vs. flinging, see Animating a Scroll Gesture.

        Here is the snippet for {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()}: -

        // The current viewport. This rectangle represents the currently visible 
        -// chart domain and range. 
        -private RectF mCurrentViewport = 
        +
        // The current viewport. This rectangle represents the currently visible
        +// chart domain and range.
        +private RectF mCurrentViewport =
                 new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
         
        -// The current destination rectangle (in pixel coordinates) into which the 
        +// The current destination rectangle (in pixel coordinates) into which the
         // chart data should be drawn.
         private Rect mContentRect;
         
        @@ -213,18 +213,18 @@ private final GestureDetector.SimpleOnGestureListener mGestureListener
         ...
         
         @Override
        -public boolean onScroll(MotionEvent e1, MotionEvent e2, 
        +public boolean onScroll(MotionEvent e1, MotionEvent e2,
                     float distanceX, float distanceY) {
             // Scrolling uses math based on the viewport (as opposed to math using pixels).
        -    
        +
             // Pixel offset is the offset in screen pixels, while viewport offset is the
        -    // offset within the current viewport. 
        -    float viewportOffsetX = distanceX * mCurrentViewport.width() 
        +    // offset within the current viewport.
        +    float viewportOffsetX = distanceX * mCurrentViewport.width()
                     / mContentRect.width();
        -    float viewportOffsetY = -distanceY * mCurrentViewport.height() 
        +    float viewportOffsetY = -distanceY * mCurrentViewport.height()
                     / mContentRect.height();
             ...
        -    // Updates the viewport, refreshes the display. 
        +    // Updates the viewport, refreshes the display.
             setViewportBottomLeft(
                     mCurrentViewport.left + viewportOffsetX,
                     mCurrentViewport.bottom + viewportOffsetY);
        @@ -232,20 +232,20 @@ public boolean onScroll(MotionEvent e1, MotionEvent e2,
             return true;
         }
        -

        The implementation of {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} +

        The implementation of {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} scrolls the viewport in response to the touch gesture:

         /**
          * Sets the current viewport (defined by mCurrentViewport) to the given
        - * X and Y positions. Note that the Y value represents the topmost pixel position, 
        + * X and Y positions. Note that the Y value represents the topmost pixel position,
          * and thus the bottom of the mCurrentViewport rectangle.
          */
         private void setViewportBottomLeft(float x, float y) {
             /*
        -     * Constrains within the scroll range. The scroll range is simply the viewport 
        -     * extremes (AXIS_X_MAX, etc.) minus the viewport size. For example, if the 
        -     * extremes were 0 and 10, and the viewport size was 2, the scroll range would 
        +     * Constrains within the scroll range. The scroll range is simply the viewport
        +     * extremes (AXIS_X_MAX, etc.) minus the viewport size. For example, if the
        +     * extremes were 0 and 10, and the viewport size was 2, the scroll range would
              * be 0 to 8.
              */
         
        @@ -270,11 +270,11 @@ provides {@link android.view.ScaleGestureDetector}. {@link
         android.view.GestureDetector} and {@link android.view.ScaleGestureDetector} can
         be used together when you  want a view to recognize additional gestures.

        -

        To report detected gesture events, gesture detectors use listener objects -passed to their constructors. {@link android.view.ScaleGestureDetector} uses -{@link android.view.ScaleGestureDetector.OnScaleGestureListener}. -Android provides -{@link android.view.ScaleGestureDetector.SimpleOnScaleGestureListener} +

        To report detected gesture events, gesture detectors use listener objects +passed to their constructors. {@link android.view.ScaleGestureDetector} uses +{@link android.view.ScaleGestureDetector.OnScaleGestureListener}. +Android provides +{@link android.view.ScaleGestureDetector.SimpleOnScaleGestureListener} as a helper class that you can extend if you don’t care about all of the reported events.

        @@ -311,7 +311,7 @@ public void onDraw(Canvas canvas) { canvas.restore(); } -private class ScaleListener +private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { @@ -329,14 +329,14 @@ private class ScaleListener

        More complex scaling example

        -

        Here is a more complex example from the {@code InteractiveChart} sample provided with this class. +

        Here is a more complex example from the {@code InteractiveChart} sample provided with this class. The {@code InteractiveChart} sample supports both scrolling (panning) and scaling with multiple fingers, -using the {@link android.view.ScaleGestureDetector} "span" -({@link android.view.ScaleGestureDetector#getCurrentSpanX getCurrentSpanX/Y}) and +using the {@link android.view.ScaleGestureDetector} "span" +({@link android.view.ScaleGestureDetector#getCurrentSpanX getCurrentSpanX/Y}) and "focus" ({@link android.view.ScaleGestureDetector#getFocusX getFocusX/Y}) features:

        @Override
        -private RectF mCurrentViewport = 
        +private RectF mCurrentViewport =
                 new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
         private Rect mContentRect;
         private ScaleGestureDetector mScaleGestureDetector;
        @@ -399,7 +399,7 @@ private final ScaleGestureDetector.OnScaleGestureListener mScaleGestureListener
                         0,
                         0);
                 mCurrentViewport.right = mCurrentViewport.left + newWidth;
        -        mCurrentViewport.bottom = mCurrentViewport.top + newHeight;     
        +        mCurrentViewport.bottom = mCurrentViewport.top + newHeight;
                 ...
                 // Invalidates the View to update the display.
                 ViewCompat.postInvalidateOnAnimation(InteractiveLineGraphView.this);
        diff --git a/docs/html/training/gestures/scroll.jd b/docs/html/training/gestures/scroll.jd
        index 4b82d6966e5c64d69300895b0295c00275a842dc..374ceff55f5dc0e76d5e706e87e845eea0f3cf6d 100644
        --- a/docs/html/training/gestures/scroll.jd
        +++ b/docs/html/training/gestures/scroll.jd
        @@ -41,12 +41,12 @@ class="button">Download the sample
         
    -

    In Android, scrolling is typically achieved by using the +

    In Android, scrolling is typically achieved by using the {@link android.widget.ScrollView} -class. Any standard layout that might extend beyond the bounds of its container should be -nested in a {@link android.widget.ScrollView} to provide a scrollable view that's -managed by the framework. Implementing a custom scroller should only be -necessary for special scenarios. This lesson describes such a scenario: displaying +class. Any standard layout that might extend beyond the bounds of its container should be +nested in a {@link android.widget.ScrollView} to provide a scrollable view that's +managed by the framework. Implementing a custom scroller should only be +necessary for special scenarios. This lesson describes such a scenario: displaying a scrolling effect in response to touch gestures using scrollers. @@ -54,8 +54,8 @@ a scrolling effect in response to touch gestures using scrollers. android.widget.OverScroller}) to collect the data you need to produce a scrolling animation in response to a touch event. They are similar, but {@link android.widget.OverScroller} -includes methods for indicating to users that they've reached the content edges -after a pan or fling gesture. The {@code InteractiveChart} sample +includes methods for indicating to users that they've reached the content edges +after a pan or fling gesture. The {@code InteractiveChart} sample uses the {@link android.widget.EdgeEffect} class (actually the {@link android.support.v4.widget.EdgeEffectCompat} class) to display a "glow" effect when users reach the content edges.

    @@ -68,7 +68,7 @@ compatibility with older devices.
    Also note that you generally only need to use scrollers when implementing scrolling yourself. {@link android.widget.ScrollView} and -{@link android.widget.HorizontalScrollView} do all of this for you if you nest your +{@link android.widget.HorizontalScrollView} do all of this for you if you nest your layout within them.

    @@ -86,71 +86,71 @@ scrolling animation look smooth.

    "Scrolling" is a word that can take on different meanings in Android, depending on the context.

    -

    Scrolling is the general process of moving the viewport (that is, the 'window' -of content you're looking at). When scrolling is in both the x and y axes, it's called -panning. The sample application provided with this class, {@code InteractiveChart}, illustrates +

    Scrolling is the general process of moving the viewport (that is, the 'window' +of content you're looking at). When scrolling is in both the x and y axes, it's called +panning. The sample application provided with this class, {@code InteractiveChart}, illustrates two different types of scrolling, dragging and flinging:

      -
    • Dragging is the type of scrolling that occurs when a user drags her -finger across the touch screen. Simple dragging is often implemented by overriding -{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in -{@link android.view.GestureDetector.OnGestureListener}. For more discussion of dragging, see +
    • Dragging is the type of scrolling that occurs when a user drags her +finger across the touch screen. Simple dragging is often implemented by overriding +{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in +{@link android.view.GestureDetector.OnGestureListener}. For more discussion of dragging, see Dragging and Scaling.
    • -
    • Flinging is the type of scrolling that occurs when a user -drags and lifts her finger quickly. After the user lifts her finger, you generally -want to keep scrolling (moving the viewport), but decelerate until the viewport stops moving. -Flinging can be implemented by overriding -{@link android.view.GestureDetector.OnGestureListener#onFling onFling()} -in {@link android.view.GestureDetector.OnGestureListener}, and by using -a scroller object. This is the use +
    • Flinging is the type of scrolling that occurs when a user +drags and lifts her finger quickly. After the user lifts her finger, you generally +want to keep scrolling (moving the viewport), but decelerate until the viewport stops moving. +Flinging can be implemented by overriding +{@link android.view.GestureDetector.OnGestureListener#onFling onFling()} +in {@link android.view.GestureDetector.OnGestureListener}, and by using +a scroller object. This is the use case that is the topic of this lesson.
    -

    It's common to use scroller objects +

    It's common to use scroller objects in conjunction with a fling gesture, but they can be used in pretty much any context where you want the UI to display -scrolling in response to a touch event. For example, you could override -{@link android.view.View#onTouchEvent onTouchEvent()} to process touch -events directly, and produce a scrolling effect or a "snapping to page" animation +scrolling in response to a touch event. For example, you could override +{@link android.view.View#onTouchEvent onTouchEvent()} to process touch +events directly, and produce a scrolling effect or a "snapping to page" animation in response to those touch events.

    -

    Implement Touch-Based Scrolling

    +

    Implement Touch-Based Scrolling

    This section describes how to use a scroller. -The snippet shown below comes from the {@code InteractiveChart} sample +The snippet shown below comes from the {@code InteractiveChart} sample provided with this class. -It uses a -{@link android.view.GestureDetector}, and overrides the -{@link android.view.GestureDetector.SimpleOnGestureListener} method +It uses a +{@link android.view.GestureDetector}, and overrides the +{@link android.view.GestureDetector.SimpleOnGestureListener} method {@link android.view.GestureDetector.OnGestureListener#onFling onFling()}. It uses {@link android.widget.OverScroller} to track the fling gesture. -If the user reaches the content edges +If the user reaches the content edges after the fling gesture, the app displays a "glow" effect.

    -

    Note: The {@code InteractiveChart} sample app displays a -chart that you can zoom, pan, scroll, and so on. In the following snippet, -{@code mContentRect} represents the rectangle coordinates within the view that the chart -will be drawn into. At any given time, a subset of the total chart domain and range are drawn -into this rectangular area. -{@code mCurrentViewport} represents the portion of the chart that is currently -visible in the screen. Because pixel offsets are generally treated as integers, -{@code mContentRect} is of the type {@link android.graphics.Rect}. Because the -graph domain and range are decimal/float values, {@code mCurrentViewport} is of +

    Note: The {@code InteractiveChart} sample app displays a +chart that you can zoom, pan, scroll, and so on. In the following snippet, +{@code mContentRect} represents the rectangle coordinates within the view that the chart +will be drawn into. At any given time, a subset of the total chart domain and range are drawn +into this rectangular area. +{@code mCurrentViewport} represents the portion of the chart that is currently +visible in the screen. Because pixel offsets are generally treated as integers, +{@code mContentRect} is of the type {@link android.graphics.Rect}. Because the +graph domain and range are decimal/float values, {@code mCurrentViewport} is of the type {@link android.graphics.RectF}.

    -

    The first part of the snippet shows the implementation of +

    The first part of the snippet shows the implementation of {@link android.view.GestureDetector.OnGestureListener#onFling onFling()}:

    -
    // The current viewport. This rectangle represents the currently visible 
    +
    // The current viewport. This rectangle represents the currently visible
     // chart domain and range. The viewport is the part of the app that the
     // user manipulates via touch gestures.
    -private RectF mCurrentViewport = 
    +private RectF mCurrentViewport =
             new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
     
    -// The current destination rectangle (in pixel coordinates) into which the 
    +// The current destination rectangle (in pixel coordinates) into which the
     // chart data should be drawn.
     private Rect mContentRect;
     
    @@ -171,7 +171,7 @@ private final GestureDetector.SimpleOnGestureListener mGestureListener
         }
         ...
         @Override
    -    public boolean onFling(MotionEvent e1, MotionEvent e2, 
    +    public boolean onFling(MotionEvent e1, MotionEvent e2,
                 float velocityX, float velocityY) {
             fling((int) -velocityX, (int) -velocityY);
             return true;
    @@ -184,10 +184,10 @@ private void fling(int velocityX, int velocityY) {
         // Flings use math in pixels (as opposed to math based on the viewport).
         Point surfaceSize = computeScrollSurfaceSize();
         mScrollerStartViewport.set(mCurrentViewport);
    -    int startX = (int) (surfaceSize.x * (mScrollerStartViewport.left - 
    +    int startX = (int) (surfaceSize.x * (mScrollerStartViewport.left -
                 AXIS_X_MIN) / (
                 AXIS_X_MAX - AXIS_X_MIN));
    -    int startY = (int) (surfaceSize.y * (AXIS_Y_MAX - 
    +    int startY = (int) (surfaceSize.y * (AXIS_Y_MAX -
                 mScrollerStartViewport.bottom) / (
                 AXIS_Y_MAX - AXIS_Y_MIN));
         // Before flinging, aborts the current animation.
    @@ -200,10 +200,10 @@ private void fling(int velocityX, int velocityY) {
                 velocityX,
                 velocityY,
                 /*
    -             * Minimum and maximum scroll positions. The minimum scroll 
    -             * position is generally zero and the maximum scroll position 
    -             * is generally the content size less the screen size. So if the 
    -             * content width is 1000 pixels and the screen width is 200  
    +             * Minimum and maximum scroll positions. The minimum scroll
    +             * position is generally zero and the maximum scroll position
    +             * is generally the content size less the screen size. So if the
    +             * content width is 1000 pixels and the screen width is 200
                  * pixels, the maximum scroll offset should be 800 pixels.
                  */
                 0, surfaceSize.x - mContentRect.width(),
    @@ -216,21 +216,21 @@ private void fling(int velocityX, int velocityY) {
         ViewCompat.postInvalidateOnAnimation(this);
     }
    -

    When {@link android.view.GestureDetector.OnGestureListener#onFling onFling()} calls -{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()}, -it triggers -{@link android.view.View#computeScroll computeScroll()} to update the values for x and y. +

    When {@link android.view.GestureDetector.OnGestureListener#onFling onFling()} calls +{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()}, +it triggers +{@link android.view.View#computeScroll computeScroll()} to update the values for x and y. This is typically be done when a view child is animating a scroll using a scroller object, as in this example.

    -

    Most views pass the scroller object's x and y position directly to -{@link android.view.View#scrollTo scrollTo()}. -The following implementation of {@link android.view.View#computeScroll computeScroll()} -takes a different approach—it calls -{@link android.widget.OverScroller#computeScrollOffset computeScrollOffset()} to get the current -location of x and y. When the criteria for displaying an overscroll "glow" edge effect are met -(the display is zoomed in, x or y is out of bounds, and the app isn't already showing an overscroll), -the code sets up the overscroll glow effect and calls -{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()} +

    Most views pass the scroller object's x and y position directly to +{@link android.view.View#scrollTo scrollTo()}. +The following implementation of {@link android.view.View#computeScroll computeScroll()} +takes a different approach—it calls +{@link android.widget.OverScroller#computeScrollOffset computeScrollOffset()} to get the current +location of x and y. When the criteria for displaying an overscroll "glow" edge effect are met +(the display is zoomed in, x or y is out of bounds, and the app isn't already showing an overscroll), +the code sets up the overscroll glow effect and calls +{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()} to trigger an invalidate on the view:

    // Edge effect / overscroll tracking objects.
    @@ -250,7 +250,7 @@ public void computeScroll() {
     
         boolean needsInvalidate = false;
     
    -    // The scroller isn't finished, meaning a fling or programmatic pan 
    +    // The scroller isn't finished, meaning a fling or programmatic pan
         // operation is currently active.
         if (mScroller.computeScrollOffset()) {
             Point surfaceSize = computeScrollSurfaceSize();
    @@ -262,7 +262,7 @@ public void computeScroll() {
             boolean canScrollY = (mCurrentViewport.top > AXIS_Y_MIN
                     || mCurrentViewport.bottom < AXIS_Y_MAX);
     
    -        /*          
    +        /*
              * If you are zoomed in and currX or currY is
              * outside of bounds and you're not already
              * showing overscroll, then render the overscroll
    @@ -272,7 +272,7 @@ public void computeScroll() {
                     && currX < 0
                     && mEdgeEffectLeft.isFinished()
                     && !mEdgeEffectLeftActive) {
    -            mEdgeEffectLeft.onAbsorb((int) 
    +            mEdgeEffectLeft.onAbsorb((int)
                         OverScrollerCompat.getCurrVelocity(mScroller));
                 mEdgeEffectLeftActive = true;
                 needsInvalidate = true;
    @@ -280,7 +280,7 @@ public void computeScroll() {
                     && currX > (surfaceSize.x - mContentRect.width())
                     && mEdgeEffectRight.isFinished()
                     && !mEdgeEffectRightActive) {
    -            mEdgeEffectRight.onAbsorb((int) 
    +            mEdgeEffectRight.onAbsorb((int)
                         OverScrollerCompat.getCurrVelocity(mScroller));
                 mEdgeEffectRightActive = true;
                 needsInvalidate = true;
    @@ -290,7 +290,7 @@ public void computeScroll() {
                     && currY < 0
                     && mEdgeEffectTop.isFinished()
                     && !mEdgeEffectTopActive) {
    -            mEdgeEffectTop.onAbsorb((int) 
    +            mEdgeEffectTop.onAbsorb((int)
                         OverScrollerCompat.getCurrVelocity(mScroller));
                 mEdgeEffectTopActive = true;
                 needsInvalidate = true;
    @@ -298,7 +298,7 @@ public void computeScroll() {
                     && currY > (surfaceSize.y - mContentRect.height())
                     && mEdgeEffectBottom.isFinished()
                     && !mEdgeEffectBottomActive) {
    -            mEdgeEffectBottom.onAbsorb((int) 
    +            mEdgeEffectBottom.onAbsorb((int)
                         OverScrollerCompat.getCurrVelocity(mScroller));
                 mEdgeEffectBottomActive = true;
                 needsInvalidate = true;
    @@ -316,14 +316,14 @@ private PointF mZoomFocalPoint = new PointF();
     // If a zoom is in progress (either programmatically or via double
     // touch), performs the zoom.
     if (mZoomer.computeZoom()) {
    -    float newWidth = (1f - mZoomer.getCurrZoom()) * 
    +    float newWidth = (1f - mZoomer.getCurrZoom()) *
                 mScrollerStartViewport.width();
    -    float newHeight = (1f - mZoomer.getCurrZoom()) * 
    +    float newHeight = (1f - mZoomer.getCurrZoom()) *
                 mScrollerStartViewport.height();
    -    float pointWithinViewportX = (mZoomFocalPoint.x - 
    +    float pointWithinViewportX = (mZoomFocalPoint.x -
                 mScrollerStartViewport.left)
                 / mScrollerStartViewport.width();
    -    float pointWithinViewportY = (mZoomFocalPoint.y - 
    +    float pointWithinViewportY = (mZoomFocalPoint.y -
                 mScrollerStartViewport.top)
                 / mScrollerStartViewport.height();
         mCurrentViewport.set(
    @@ -339,9 +339,9 @@ if (needsInvalidate) {
     }
     
    -

    This is the {@code computeScrollSurfaceSize()} method that's called in the above snippet. It -computes the current scrollable surface size, in pixels. For example, if the entire chart area is visible, -this is simply the current size of {@code mContentRect}. If the chart is zoomed in 200% in both directions, +

    This is the {@code computeScrollSurfaceSize()} method that's called in the above snippet. It +computes the current scrollable surface size, in pixels. For example, if the entire chart area is visible, +this is simply the current size of {@code mContentRect}. If the chart is zoomed in 200% in both directions, the returned size will be twice as large horizontally and vertically.

    private Point computeScrollSurfaceSize() {
    @@ -352,8 +352,8 @@ the returned size will be twice as large horizontally and vertically.

    / mCurrentViewport.height())); }
    -

    For another example of scroller usage, see the -source code for the -{@link android.support.v4.view.ViewPager} class. It scrolls in response to flings, +

    For another example of scroller usage, see the +source code for the +{@link android.support.v4.view.ViewPager} class. It scrolls in response to flings, and uses scrolling to implement the "snapping to page" animation.

    diff --git a/docs/html/training/gestures/viewgroup.jd b/docs/html/training/gestures/viewgroup.jd index 5b32300b99b06e2e2f3e89c71ba2bb0ff74d61bd..7b5b24e0285d1d9f9833e647ea9598a22c608bb3 100644 --- a/docs/html/training/gestures/viewgroup.jd +++ b/docs/html/training/gestures/viewgroup.jd @@ -52,38 +52,38 @@ onInterceptTouchEvent()} method.

    Intercept Touch Events in a ViewGroup

    -

    The {@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} -method is called whenever a touch event is detected on the surface of a -{@link android.view.ViewGroup}, including on the surface of its children. If -{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} -returns {@code true}, the {@link android.view.MotionEvent} is intercepted, -meaning it will be not be passed on to the child, but rather to the +

    The {@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} +method is called whenever a touch event is detected on the surface of a +{@link android.view.ViewGroup}, including on the surface of its children. If +{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} +returns {@code true}, the {@link android.view.MotionEvent} is intercepted, +meaning it will be not be passed on to the child, but rather to the {@link android.view.View#onTouchEvent onTouchEvent()} method of the parent.

    -

    The {@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} -method gives a parent the chance to see any touch event before its children do. -If you return {@code true} from -{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()}, -the child view that was previously handling touch events -receives an {@link android.view.MotionEvent#ACTION_CANCEL}, and the events from that -point forward are sent to the parent's -{@link android.view.View#onTouchEvent onTouchEvent()} method for the usual handling. -{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} can also -return {@code false} and simply spy on events as they travel down the view hierarchy +

    The {@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} +method gives a parent the chance to see any touch event before its children do. +If you return {@code true} from +{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()}, +the child view that was previously handling touch events +receives an {@link android.view.MotionEvent#ACTION_CANCEL}, and the events from that +point forward are sent to the parent's +{@link android.view.View#onTouchEvent onTouchEvent()} method for the usual handling. +{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} can also +return {@code false} and simply spy on events as they travel down the view hierarchy to their usual targets, which will handle the events with their own {@link android.view.View#onTouchEvent onTouchEvent()}. -

    In the following snippet, the class {@code MyViewGroup} extends -{@link android.view.ViewGroup}. -{@code MyViewGroup} contains multiple child views. If you drag your finger across -a child view horizontally, the child view should no longer get touch events, and -{@code MyViewGroup} should handle touch events by scrolling its contents. However, -if you press buttons in the child view, or scroll the child view vertically, -the parent shouldn't intercept those touch events, because the child is the -intended target. In those cases, +

    In the following snippet, the class {@code MyViewGroup} extends +{@link android.view.ViewGroup}. +{@code MyViewGroup} contains multiple child views. If you drag your finger across +a child view horizontally, the child view should no longer get touch events, and +{@code MyViewGroup} should handle touch events by scrolling its contents. However, +if you press buttons in the child view, or scroll the child view vertically, +the parent shouldn't intercept those touch events, because the child is the +intended target. In those cases, {@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()} should -return {@code false}, and {@code MyViewGroup}'s +return {@code false}, and {@code MyViewGroup}'s {@link android.view.View#onTouchEvent onTouchEvent()} won't be called.

    public class MyViewGroup extends ViewGroup {
    @@ -118,20 +118,20 @@ return {@code false}, and {@code MyViewGroup}'s
             switch (action) {
                 case MotionEvent.ACTION_MOVE: {
                     if (mIsScrolling) {
    -                    // We're currently scrolling, so yes, intercept the 
    +                    // We're currently scrolling, so yes, intercept the
                         // touch event!
                         return true;
                     }
     
    -                // If the user has dragged her finger horizontally more than 
    +                // If the user has dragged her finger horizontally more than
                     // the touch slop, start the scroll
     
                     // left as an exercise for the reader
    -                final int xDiff = calculateDistanceX(ev); 
    +                final int xDiff = calculateDistanceX(ev);
     
    -                // Touch slop should be calculated using ViewConfiguration 
    +                // Touch slop should be calculated using ViewConfiguration
                     // constants.
    -                if (xDiff > mTouchSlop) { 
    +                if (xDiff > mTouchSlop) {
                         // Start scrolling!
                         mIsScrolling = true;
                         return true;
    @@ -141,26 +141,26 @@ return {@code false}, and {@code MyViewGroup}'s
                 ...
             }
     
    -        // In general, we don't want to intercept touch events. They should be 
    +        // In general, we don't want to intercept touch events. They should be
             // handled by the child view.
             return false;
         }
     
         @Override
         public boolean onTouchEvent(MotionEvent ev) {
    -        // Here we actually handle the touch event (e.g. if the action is ACTION_MOVE, 
    +        // Here we actually handle the touch event (e.g. if the action is ACTION_MOVE,
             // scroll this container).
    -        // This method will only be called if the touch event was intercepted in 
    +        // This method will only be called if the touch event was intercepted in
             // onInterceptTouchEvent
             ...
         }
     }
    -

    Note that {@link android.view.ViewGroup} also provides a -{@link android.view.ViewGroup#requestDisallowInterceptTouchEvent requestDisallowInterceptTouchEvent()} method. -The {@link android.view.ViewGroup} calls this method when a child does not want the parent and its -ancestors to intercept touch events with -{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()}. +

    Note that {@link android.view.ViewGroup} also provides a +{@link android.view.ViewGroup#requestDisallowInterceptTouchEvent requestDisallowInterceptTouchEvent()} method. +The {@link android.view.ViewGroup} calls this method when a child does not want the parent and its +ancestors to intercept touch events with +{@link android.view.ViewGroup#onInterceptTouchEvent onInterceptTouchEvent()}.

    Use ViewConfiguration Constants

    @@ -176,10 +176,10 @@ before the gesture is interpreted as scrolling. Touch slop is typically used to prevent accidental scrolling when the user is performing some other touch operation, such as touching on-screen elements.

    -

    Two other commonly used {@link android.view.ViewConfiguration} methods are -{@link android.view.ViewConfiguration#getScaledMinimumFlingVelocity getScaledMinimumFlingVelocity()} +

    Two other commonly used {@link android.view.ViewConfiguration} methods are +{@link android.view.ViewConfiguration#getScaledMinimumFlingVelocity getScaledMinimumFlingVelocity()} and {@link android.view.ViewConfiguration#getScaledMaximumFlingVelocity getScaledMaximumFlingVelocity()}. -These methods return the minimum and maximum velocity (respectively) to initiate a fling, +These methods return the minimum and maximum velocity (respectively) to initiate a fling, as measured in pixels per second. For example:

    ViewConfiguration vc = ViewConfiguration.get(view.getContext());
    @@ -209,14 +209,14 @@ case MotionEvent.ACTION_UP: {
     
     

    Extend a Child View's Touchable Area

    -

    Android provides the {@link android.view.TouchDelegate} class to make it possible -for a parent to extend the touchable area of a child view beyond the child's bounds. +

    Android provides the {@link android.view.TouchDelegate} class to make it possible +for a parent to extend the touchable area of a child view beyond the child's bounds. This is useful when the child has to be small, but should have a larger touch region. You can also use this approach to shrink the child's touch region if need be.

    -

    In the following example, an {@link android.widget.ImageButton} is the -"delegate view" (that is, the child whose touch area the parent will extend). +

    In the following example, an {@link android.widget.ImageButton} is the +"delegate view" (that is, the child whose touch area the parent will extend). Here is the layout file:

    @@ -225,7 +225,7 @@ Here is the layout file:

    android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > - + <ImageButton android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -245,9 +245,9 @@ Here is the layout file:

    -In its capacity as touch delegate for the {@link android.widget.ImageButton} child view, the +In its capacity as touch delegate for the {@link android.widget.ImageButton} child view, the parent view will receive all touch events. If the touch event occurred within the child's hit -rectangle, the parent will pass the touch +rectangle, the parent will pass the touch event to the child for handling.

    @@ -261,7 +261,7 @@ public class MainActivity extends Activity { setContentView(R.layout.activity_main); // Get the parent view View parentView = findViewById(R.id.parent_layout); - + parentView.post(new Runnable() { // Post in the parent's message queue to make sure the parent // lays out its children before you call getHitRect() @@ -275,29 +275,29 @@ public class MainActivity extends Activity { myButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - Toast.makeText(MainActivity.this, - "Touch occurred within ImageButton touch region.", + Toast.makeText(MainActivity.this, + "Touch occurred within ImageButton touch region.", Toast.LENGTH_SHORT).show(); } }); - + // The hit rectangle for the ImageButton myButton.getHitRect(delegateArea); - + // Extend the touch area of the ImageButton beyond its bounds // on the right and bottom. delegateArea.right += 100; delegateArea.bottom += 100; - + // Instantiate a TouchDelegate. - // "delegateArea" is the bounds in local coordinates of + // "delegateArea" is the bounds in local coordinates of // the containing view to be mapped to the delegate view. // "myButton" is the child view that should receive motion // events. - TouchDelegate touchDelegate = new TouchDelegate(delegateArea, + TouchDelegate touchDelegate = new TouchDelegate(delegateArea, myButton); - - // Sets the TouchDelegate on the parent view, such that touches + + // Sets the TouchDelegate on the parent view, such that touches // within the touch delegate bounds are routed to the child. if (View.class.isInstance(myButton.getParent())) { ((View) myButton.getParent()).setTouchDelegate(touchDelegate); diff --git a/docs/html/training/id-auth/authenticate.jd b/docs/html/training/id-auth/authenticate.jd index 65dbc3987bd3ecb3f711448f3b8540f052d0c07f..bf32e8ed048864b0dfebeb507a8389fa13b07aa7 100644 --- a/docs/html/training/id-auth/authenticate.jd +++ b/docs/html/training/id-auth/authenticate.jd @@ -129,7 +129,7 @@ private class OnTokenAcquired implements AccountManagerCallback<Bundle> { public void run(AccountManagerFuture<Bundle> result) { // Get the result of the operation from the AccountManagerFuture. Bundle bundle = result.getResult(); - + // The token is a named value in the bundle. The name of the value // is stored in the constant AccountManager.KEY_AUTHTOKEN. token = bundle.getString(AccountManager.KEY_AUTHTOKEN); diff --git a/docs/html/training/id-auth/custom_auth.jd b/docs/html/training/id-auth/custom_auth.jd index def9b51418df07eb6fd1d49a01be1dfcf8b497a1..3c106a97317f38f399750fd88da4a5e3017ea19f 100644 --- a/docs/html/training/id-auth/custom_auth.jd +++ b/docs/html/training/id-auth/custom_auth.jd @@ -81,7 +81,7 @@ a database that is only accessible to root. But on a rooted device, the credentials would be readable by anyone with {@code adb} access to the device.

    With this in mind, you shouldn't pass the user's actual -password to {@link android.accounts.AccountManager#addAccountExplicitly +password to {@link android.accounts.AccountManager#addAccountExplicitly AccountManager.addAccountExplicitly()}. Instead, you should store a cryptographically secure token that would be of limited use to an attacker. If your user credentials are protecting something valuable, you should carefully diff --git a/docs/html/training/id-auth/index.jd b/docs/html/training/id-auth/index.jd index f15ee295fa9ca05ca369d5d71ed8d7e9fc1e55de..45c6309648e983e9f6e0d5f53158ef4d88732ee3 100644 --- a/docs/html/training/id-auth/index.jd +++ b/docs/html/training/id-auth/index.jd @@ -15,7 +15,7 @@ startpage=true

  • Android 2.0 (API level 5) or higher
  • Experience with Services
  • Experience with OAuth 2.0
  • - +

    You should also read

      diff --git a/docs/html/training/implementing-navigation/nav-drawer.jd b/docs/html/training/implementing-navigation/nav-drawer.jd index 679c240918315c56ae9f38a34499df71407b7f7c..8aebd4b091d9e1f0d64a69a6e5d15052b204ed3f 100644 --- a/docs/html/training/implementing-navigation/nav-drawer.jd +++ b/docs/html/training/implementing-navigation/nav-drawer.jd @@ -173,7 +173,7 @@ android.app.Fragment} into the main content view (the
       private class DrawerItemClickListener implements ListView.OnItemClickListener {
           @Override
      -    public void onItemClick(AdapterView parent, View view, int position, long id) {
      +    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
               selectItem(position);
           }
       }
      diff --git a/docs/html/training/improving-layouts/optimizing-layout.jd b/docs/html/training/improving-layouts/optimizing-layout.jd
      index e0baedfaef6431fbe906e75c3c4bcde567dbe9ca..2f9f32d92c601e4551481c2933c95b3f8639844c 100644
      --- a/docs/html/training/improving-layouts/optimizing-layout.jd
      +++ b/docs/html/training/improving-layouts/optimizing-layout.jd
      @@ -145,7 +145,7 @@ href="http://tools.android.com/tips/lint-checks">rules are:

    • Deep layouts - Layouts with too much nesting are bad for performance. Consider using flatter layouts such as {@link android.widget.RelativeLayout} or {@link android.widget.GridLayout} to improve performance. The default maximum depth is 10.
    -

    Another benefit of Lint is that it is integrated into Android Studio. Lint automatically runs +

    Another benefit of Lint is that it is integrated into Android Studio. Lint automatically runs whenever you compile your program. With Android Studio, you can also run lint inspections for a specific build variant, or for all build variants.

    @@ -153,7 +153,7 @@ specific build variant, or for all build variants.

    File>Settings>Project Settings option. The Inspection Configuration page appears with the supported inspections.

    -

    Figure 5. Inspection Configuration

    +

    Figure 5. Inspection Configuration

    Lint has the ability to automatically fix some issues, provide suggestions for others and jump directly to the offending code for review.

    diff --git a/docs/html/training/in-app-billing/list-iab-products.jd b/docs/html/training/in-app-billing/list-iab-products.jd index c423fc134892b47c3df1df4543129395304bf25d..c8de8232afe4199501258cd498d94f992c12e96d 100644 --- a/docs/html/training/in-app-billing/list-iab-products.jd +++ b/docs/html/training/in-app-billing/list-iab-products.jd @@ -36,7 +36,7 @@ next.link=purchase-iab-products.html

    To add new in-app products to your product list:

      -
    1. Build a signed APK file for your In-app Billing application. To learn how to build and sign your APK, see Building Your Application for Release. Make sure that you are using your final (not debug) certificate and private key to sign your application. +
    2. Build a signed APK file for your In-app Billing application. To learn how to build and sign your APK, see Building Your Application for Release. Make sure that you are using your final (not debug) certificate and private key to sign your application.
    3. In the Developer Console, open the application entry that you created earlier.
    4. Click on the APK tab then click on Upload new APK. Upload the signed APK file to the Developer Console. Don’t publish the app yet!
    5. @@ -48,9 +48,9 @@ next.link=purchase-iab-products.html

      Query Items Available for Purchase

      You can query Google Play to programmatically retrieve details of the in-app products that are associated with your application (such as the product’s price, title, description, and type). This is useful, for example, when you want to display a listing of unowned items that are still available for purchase to users.

      Note: When making the query, you will need to specify the product IDs for the products explicitly. You can manually find the product IDs from the Developer Console by opening the In-app Products tab for your application. The product IDs are listed under the column labeled Name/ID.

      -

      To retrieve the product details, call {@code queryInventoryAsync(boolean, List, QueryInventoryFinishedListener)} on your IabHelper instance. +

      To retrieve the product details, call {@code queryInventoryAsync(boolean, List, QueryInventoryFinishedListener)} on your IabHelper instance.

        -
      • The first input argument indicates whether product details should be retrieved (should be set to {@code true}).
      • +
      • The first input argument indicates whether product details should be retrieved (should be set to {@code true}).
      • The {@code List} argument consists of one or more product IDs (also called SKUs) for the products that you want to query.
      • Finally, the {@code QueryInventoryFinishedListener} argument specifies a listener is notified when the query operation has completed and handles the query response.
      @@ -70,9 +70,9 @@ mHelper.queryInventoryAsync(true, additionalSkuList,

      The following code shows how you can retrieve the item prices from the result set.

      -IabHelper.QueryInventoryFinishedListener 
      +IabHelper.QueryInventoryFinishedListener
          mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener() {
      -   public void onQueryInventoryFinished(IabResult result, Inventory inventory)   
      +   public void onQueryInventoryFinished(IabResult result, Inventory inventory)
          {
             if (result.isFailure()) {
                // handle error
      @@ -84,7 +84,7 @@ IabHelper.QueryInventoryFinishedListener
              String bananaPrice =
                 inventory.getSkuDetails(SKU_BANANA).getPrice();
       
      -       // update the UI 
      +       // update the UI
          }
       }
       
      diff --git a/docs/html/training/in-app-billing/preparing-iab-app.jd b/docs/html/training/in-app-billing/preparing-iab-app.jd old mode 100755 new mode 100644 index 2c6e9a074d31741ad97c4d75beabf7325dc120b5..780f2f800a7c93e3ad217685b820e0cd8c9ff11c --- a/docs/html/training/in-app-billing/preparing-iab-app.jd +++ b/docs/html/training/in-app-billing/preparing-iab-app.jd @@ -31,23 +31,32 @@ next.link=list-iab-products.html
    +href="https://www.youtube.com/watch?v=UvCl5Xx7Z5o" class="external-link">

    Video

    Implementing Freemium

    -

    Before you can start using the In-app Billing service, you'll need to add the library that contains the In-app Billing Version 3 API to your Android project. You also need to set the permissions for your application to communicate with Google Play. In addition, you'll need to establish a connection between your application and Google Play. You should also verify that the In-app Billing API version that you are using in your application is supported by Google Play.

    +

    Before you can start using the In-app Billing service, you need to add the library that + contains the In-app Billing Version 3 API to your Android project. You also need to set the + permissions for your application to communicate with Google Play. In addition, you need to + establish a connection between your application and Google Play. You must also verify that + the In-app Billing API version that you are using in your application is supported + by Google Play.

    Download the Sample Application

    -

    In this training class, you will use a reference implementation for the In-app Billing Version 3 API called the {@code TrivialDrive} sample application. The sample includes convenience classes to quickly set up the In-app Billing service, marshal and unmarshal data types, and handle In-app Billing requests from the main thread of your application.

    -

    To download the sample application:

    +

    In this training class, you use a reference implementation for the In-app Billing + Version 3 API + called the {@code TrivialDrive} sample application. The sample includes convenience classes to + quickly set up the In-app Billing service, marshal and unmarshal data types, and handle In-app + Billing requests from the main thread of your application.

    +

    To download the sample application, follow these steps:

    1. Open Android Studio and then close any open projects until you are presented with the welcome screen.
    2. -
    3. Choose Import an Android code sample from the - Quick Start list on the right side the window.
    4. +
    5. From the Quick Start list on the right side of the window, choose + Import an Android code sample.
    6. Type {@code Trivial Drive} into the search bar and select the Trivial Drive sample.
    7. Follow the rest of the instructions in the Import Sample @@ -56,66 +65,121 @@ presented with the welcome screen.

    Alternatively, you can use {@code git} to manually clone - the repository from https://github.com/googlesamples/android-play-billing

    + class="external-link">Google Samples GitHub site.

    Add Your Application to the Developer Console

    -

    The Google Play Developer Console is where you publish your In-app Billing application and manage the various digital goods that are available for purchase from your application. When you create a new application entry in the Developer Console, it automatically generates a public license key for your application. You will need this key to establish a trusted connection from your application to the Google Play servers. You only need to generate this key once per application, and don’t need to repeat these steps when you update the APK file for your application.

    -

    To add your application to the Developer Console:

    +

    The Google Play Developer Console is where you publish your In-app Billing application + and manage the various digital products that are available for purchase from your + application. + When you create a new application entry in the Developer Console, it automatically generates + a public license key for your application. You need this key to establish a trusted connection + from your application to the Google Play servers. You need to generate this key only once + per application, and you don’t need to repeat these steps when you update the APK file for + your application.

    +

    To add your application to the Developer Console, follow these steps:

      -
    1. Go to the Google Play Developer Console site and log in. You will need to register for a new developer account, if you have not registered previously. To sell in-app items, you also need to have a Google payments merchant account.
    2. -
    3. Click on Try the new design to access the preview version of the Developer Console, if you are not already logged on to that version.
    4. -
    5. In the All Applications tab, add a new application entry. +
    6. Go to the +Google Play Developer Console + site and log in. If you have not registered previously, you need to register for a new + developer account. To sell in-app products, you also need a + + Google payments merchant account.
    7. + +
    8. In the All Applications tab, complete these steps to add a new + application entry:
      1. Click Add new application.
      2. Enter a name for your new In-app Billing application.
      3. Click Prepare Store Listing.
    9. -
    10. In the Services & APIs tab, find and make a note of the public license key that Google Play generated for your application. This is a Base64 string that you will need to include in your application code later.
    11. +
    12. In the Services & APIs tab, find and make a note of the public license key + that Google Play generated for your application. This is a Base64 string that you need to + include in your application code later.

    Your application should now appear in the list of applications in Developer Console.

    Add the In-app Billing Library

    -

    To use the In-app Billing Version 3 features, you must add the {@code IInAppBillingService.aidl} file to your Android project. This Android Interface Definition Language (AIDL) file defines the interface to the Google Play service.

    -

    You can find the {@code IInAppBillingService.aidl} file in the provided sample app. Depending on whether you are creating a new application or modifying an existing application, follow the instructions below to add the In-app Billing Library to your project.

    -

    New Project

    -

    To add the In-app Billing Version 3 library to your new In-app Billing project:

    +

    To use the In-app Billing Version 3 features, you must add the + {@code IInAppBillingService.aidl} + file to your Android project. This Android Interface Definition Language + (AIDL) file defines the + interface to the Google Play service.

    +

    You can find the {@code IInAppBillingService.aidl} file in the provided sample app. + To add the + In-app Billing library to your project, follow the instructions below for a new or + existing project.

    +

    Adding in-app billing to a new project

    +

    To add the In-app Billing Version 3 library to a new project, follow these steps:

    1. Copy the {@code TrivialDrive} sample files into your Android project.
    2. -
    3. Modify the package name in the files you copied to use the package name for your project. In Android Studio, you can use this shortcut: right-click the package name, then select Refactor > Rename.
    4. -
    5. Open the {@code AndroidManifest.xml} file and update the package attribute value to use the package name for your project.
    6. -
    7. Fix import statements as needed so that your project compiles correctly. In Android Studio, you can use this shortcut: press Ctrl+Shift+O in each file showing errors.
    8. -
    9. Modify the sample to create your own application. Remember to copy the Base64 public license key for your application from the Developer Console over to your {@code MainActivity.java}.
    10. +
    11. Modify the package name in the files that you copied to use the package name + for your project. + In Android Studio, you can right-click the package name and then + select Refactor > Rename.
    12. +
    13. Open the {@code AndroidManifest.xml} file and update the package attribute value to + use the package name for your project.
    14. +
    15. Fix import statements as needed so that your project compiles correctly. + In Android Studio, you can press Ctrl+Shift+O + in each file showing errors.
    16. +
    17. Modify the sample to create your own application. Remember to copy the Base64 + public license key for your application from the Developer Console to + your {@code MainActivity.java}.
    -

    Existing Project

    -

    To add the In-app Billing Version 3 library to your existing In-app Billing project:

    +

    Adding in-app billing to an existing project

    +

    To add the In-app Billing Version 3 library to an existing project, follow these steps:

    1. Copy the {@code IInAppBillingService.aidl} file to your Android project.
        -
      • In Android Studio: Create a directory named {@code aidl} under {@code src/main}, add a new - package {@code com.android.vending.billing} in this directory, and import the +
      • In Android Studio: Create a directory named {@code aidl} under {@code src/main}, + add a new + package {@code com.android.vending.billing} in this directory, and then import the {@code IInAppBillingService.aidl} file into this package.
      • -
      • In other dev environments: Create the following directory {@code /src/com/android/vending/billing} and copy the {@code IInAppBillingService.aidl} file into this directory.
      • +
      • In other dev environments: Create the following directory + {@code /src/com/android/vending/billing} and copy the {@code IInAppBillingService.aidl} + file into this directory.
    2. -
    3. Build your application. You should see a generated file named {@code IInAppBillingService.java} in the {@code /gen} directory of your project.
    4. -
    5. Add the helper classes from the {@code /util} directory of the {@code TrivialDrive} sample to your project. Remember to change the package name declarations in those files accordingly so that your project compiles correctly.
    6. +
    7. Build your application. You should see a generated file named + {@code IInAppBillingService.java} + in the {@code /gen} directory of your project.
    8. +
    9. Add the helper classes from the {@code /util} directory of the {@code TrivialDrive} + sample to + your project. Remember to change the package name declarations in those files + accordingly so + that your project compiles correctly.

    Your project should now contain the In-app Billing Version 3 library.

    Set the Billing Permission

    -

    Your app needs to have permission to communicate request and response messages to the Google Play’s billing service. To give your app the necessary permission, add this line in your {@code AndroidManifest.xml} manifest file:

    +

    Your app needs to have permission to communicate request and response messages to + the Google Play billing service. To give your app the necessary permission, add the following + line in your {@code AndroidManifest.xml} manifest file:

     <uses-permission android:name="com.android.vending.BILLING" />
     

    Initiate a Connection with Google Play

    -

    You must bind your Activity to Google Play’s In-app Billing service to send In-app Billing requests to Google Play from your application. The convenience classes provided in the sample handles the binding to the In-app Billing service, so you don’t have to manage the network connection directly.

    -

    To set up synchronous communication with Google Play, create an {@code IabHelper} instance in your activity's {@code onCreate} method. In the constructor, pass in the {@code Context} for the activity, along with a string containing the public license key that was generated earlier by the Google Play Developer Console.

    -

    Security Recommendation: It is highly recommended that you do not hard-code the exact public license key string value as provided by Google Play. Instead, you can construct the whole public license key string at runtime from substrings, or retrieve it from an encrypted store, before passing it to the constructor. This approach makes it more difficult for malicious third-parties to modify the public license key string in your APK file.

    +

    To send In-app + Billing requests to Google Play from your application, you must bind your Activity + to the Google Play In-app Billing service. The sample includes convenience classes + that handle the binding to the In-app Billing service, so you don’t have to + manage the network connection directly.

    +

    To set up synchronous communication with Google Play, create an {@code IabHelper} + instance in your activity's {@code onCreate} method, as shown in the following example. + In the constructor, pass in the {@code Context} for the activity along with a string + containing the public license key that was generated earlier by the Google Play + Developer Console. +

    +

    Security Recommendation: Google highly recommends that + you do not hard-code the exact public license key string value as provided by Google Play. + Instead, construct the whole public license key string at runtime from substrings + or retrieve it from an encrypted store before passing it to the constructor. + This approach makes it more difficult for malicious third parties to modify the public + license key string in your APK file.

     IabHelper mHelper;
    @@ -130,13 +194,20 @@ public void onCreate(Bundle savedInstanceState) {
     }
     
    -

    Next, perform the service binding by calling the {@code startSetup} method on the {@code IabHelper} instance that you created. Pass the method an {@code OnIabSetupFinishedListener} instance, which is called once the {@code IabHelper} completes the asynchronous setup operation. As part of the setup process, the {@code IabHelper} also checks if the In-app Billing Version 3 API is supported by Google Play. If the API version is not supported, or if an error occured while establishing the service binding, the listener is notified and passed an {@code IabResult} object with the error message.

    +

    Next, perform the service binding by calling the {@code startSetup} method on the + {@code IabHelper} instance that you created, as shown in the following example. + Pass the method an {@code OnIabSetupFinishedListener} instance, which is called once + the {@code IabHelper} completes the asynchronous setup operation. As part of the + setup process, the {@code IabHelper} also checks if the In-app Billing Version 3 API + is supported by Google Play. If the API version is not supported, or if an error occurs + while establishing the service binding, the listener is notified and passed an + {@code IabResult} object with the error message.

     mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        public void onIabSetupFinished(IabResult result) {
           if (!result.isSuccess()) {
    -         // Oh noes, there was a problem.
    +         // Oh no, there was a problem.
              Log.d(TAG, "Problem setting up In-app Billing: " + result);
           }
              // Hooray, IAB is fully set up!
    @@ -144,9 +215,18 @@ mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
     });
     
    -

    If the setup completed successfully, you can now use the {@code mHelper} reference to communicate with the Google Play service. When your application is launched, it is a good practice to query Google Play to find out what in-app items are owned by a user. This is covered further in the Query Purchased Items section.

    +

    If the setup completed successfully, you can now use the {@code mHelper} reference + to communicate with the Google Play service. When your application is launched, it is + a good practice to query Google Play to find out what in-app items are owned by a user. + This is covered further in the + + Query Purchased Items section.

    -

    Important: Remember to unbind from the In-app Billing service when you are done with your activity. If you don’t unbind, the open service connection could cause your device’s performance to degrade. To unbind and free your system resources, call the {@code IabHelper}'s {@code dispose} method when your {@code Activity} is destroyed.

    +

    Important: Remember to unbind from the In-app Billing service + when you are done with your activity. If you don’t unbind, the open service connection could + degrade device performance. To unbind and free your system resources, call the + {@code IabHelper}'s {@code dispose} method when your {@code Activity} is destroyed, + as shown in the following example.

     @Override
    @@ -156,8 +236,3 @@ public void onDestroy() {
        mHelper = null;
     }
     
    - - - - - diff --git a/docs/html/training/in-app-billing/purchase-iab-products.jd b/docs/html/training/in-app-billing/purchase-iab-products.jd index 4e6e035afe568b6a29b098effaeff0b437cf76c6..165e311fbf8efb58584adec1dce26dd366e11233 100644 --- a/docs/html/training/in-app-billing/purchase-iab-products.jd +++ b/docs/html/training/in-app-billing/purchase-iab-products.jd @@ -45,7 +45,7 @@ next.link=test-iab-app.html

    The following example shows how you can make a purchase request for a product with ID {@code SKU_GAS}, using an arbitrary value of 10001 for the request code, and an encoded developer payload string.

    -mHelper.launchPurchaseFlow(this, SKU_GAS, 10001,   
    +mHelper.launchPurchaseFlow(this, SKU_GAS, 10001,
        mPurchaseFinishedListener, "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
     
    @@ -54,14 +54,14 @@ mHelper.launchPurchaseFlow(this, SKU_GAS, 10001,

    The following example shows how you can handle the purchase response in the listener, depending on whether the purchase order was completed successfully, and whether the user purchased gas or a premium upgrade. In this example, gas is an in-app product that can be purchased multiple times, so you should consume the purchase to allow the user to buy it again. To learn how to consume purchases, see the Consuming Products section. The premium upgrade is a one-time purchase so you don’t need to consume it. It is good practice to update the UI immediately so that your users can see their newly purchased items.

    -IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener 
    +IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
        = new IabHelper.OnIabPurchaseFinishedListener() {
    -   public void onIabPurchaseFinished(IabResult result, Purchase purchase) 
    +   public void onIabPurchaseFinished(IabResult result, Purchase purchase)
        {
           if (result.isFailure()) {
              Log.d(TAG, "Error purchasing: " + result);
              return;
    -      }      
    +      }
           else if (purchase.getSku().equals(SKU_GAS)) {
              // consume the gas and update the UI
           }
    @@ -86,7 +86,7 @@ mHelper.queryInventoryAsync(mGotInventoryListener);
     

    If the query is successful, the query results are stored in an {@code Inventory} object that is passed back to the listener. The In-app Billing service returns only the purchases made by the user account that is currently logged in to the device.

    -IabHelper.QueryInventoryFinishedListener mGotInventoryListener 
    +IabHelper.QueryInventoryFinishedListener mGotInventoryListener
        = new IabHelper.QueryInventoryFinishedListener() {
        public void onQueryInventoryFinished(IabResult result,
           Inventory inventory) {
    @@ -96,7 +96,7 @@ IabHelper.QueryInventoryFinishedListener mGotInventoryListener
           }
           else {
             // does the user have the premium upgrade?
    -        mIsPremium = inventory.hasPurchase(SKU_PREMIUM);        
    +        mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
             // update UI accordingly
           }
        }
    @@ -111,7 +111,7 @@ IabHelper.QueryInventoryFinishedListener mGotInventoryListener
     

    In this example, you want to consume the gas item that the user has previously purchased in your app.

    -mHelper.consumeAsync(inventory.getPurchase(SKU_GAS), 
    +mHelper.consumeAsync(inventory.getPurchase(SKU_GAS),
        mConsumeFinishedListener);
     
    diff --git a/docs/html/training/in-app-billing/test-iab-app.jd b/docs/html/training/in-app-billing/test-iab-app.jd index 9d47a96ce908c53056e1548c7e475c433f873fd5..fc7fe1aa7081205dc4021b57faae21266fa9b5ea 100644 --- a/docs/html/training/in-app-billing/test-iab-app.jd +++ b/docs/html/training/in-app-billing/test-iab-app.jd @@ -39,7 +39,7 @@ Test your In-app Billing application with static responses by using Google Play
  • Login to the Developer Console with your developer account.
  • Click Settings > Account details, then in the License Testing section, add the Google email addresses for your tester accounts.
  • -
  • Build a signed APK file for your In-app Billing application. To learn how to build and sign your APK, see Building Your Application for Release. Make sure that you are using your final (not debug) certificate and private key to sign your application. +
  • Build a signed APK file for your In-app Billing application. To learn how to build and sign your APK, see Building Your Application for Release. Make sure that you are using your final (not debug) certificate and private key to sign your application.
  • Make sure that you have uploaded the signed APK for your application to the Developer Console, and associated one or more in-app products with your application. You don't need to publish the application on Google Play to test it.

    Warning: It may take up to 2-3 hours after uploading the APK for Google Play to recognize your updated APK version. If you try to test your application before your uploaded APK is recognized by Google Play, your application will receive a ‘purchase cancelled’ response with an error message “This version of the application is not enabled for In-app Billing.”

  • Install the APK file to your physical test device by using the {@code adb} tool. To learn how to install the application, see Running on a Device. Make sure that: diff --git a/docs/html/training/keyboard-input/index.jd b/docs/html/training/keyboard-input/index.jd index 46795c4d9f4d268e0ba2c7de82e0364399da1cdf..bd7ad189be28bc5c3f166855d46255597d6a6f1d 100644 --- a/docs/html/training/keyboard-input/index.jd +++ b/docs/html/training/keyboard-input/index.jd @@ -32,9 +32,9 @@ through an attached keyboard.

    These topics and more are discussed in the following lessons.

    -

    Lessons

    - -
    +

    Lessons

    + +
    Specifying the Input Method Type
    Learn how to show certain soft input methods, such as those designed for phone numbers, web addresses, or other formats. Also learn how to specify characteristics such @@ -51,5 +51,5 @@ through an attached keyboard.

    Handling Keyboard Actions
    Learn how to respond directly to keyboard input for user actions.
    - -
    + +
    diff --git a/docs/html/training/keyboard-input/style.jd b/docs/html/training/keyboard-input/style.jd index b0e506cf756c9e33c6fdd40ca5d382d292496e74..714c8b3c3e32f468bcd2db82a7287f30da00ab33 100644 --- a/docs/html/training/keyboard-input/style.jd +++ b/docs/html/training/keyboard-input/style.jd @@ -71,7 +71,7 @@ so the text field conceals the user's input:

    android:id="@+id/password" android:hint="@string/password_hint" android:inputType="textPassword" - ... /> + ... />
  • There are several possible values documented with the diff --git a/docs/html/training/load-data-background/handle-results.jd b/docs/html/training/load-data-background/handle-results.jd index ce0024f031c2674c791758169a3517dbd4e09329..7439d3e99cf85ef2154fab8cfdd7eafa15bf2719 100644 --- a/docs/html/training/load-data-background/handle-results.jd +++ b/docs/html/training/load-data-background/handle-results.jd @@ -127,7 +127,7 @@ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { */ @Override public void onLoaderReset(Loader<Cursor> loader) { - + /* * Clears out the adapter's reference to the Cursor. * This prevents memory leaks. diff --git a/docs/html/training/location/display-address.jd b/docs/html/training/location/display-address.jd index 86066299e5d70dcebc4eba4848a905be7589bc25..daa6fd3832afc11f37ebe9ba029882481cae5f1d 100644 --- a/docs/html/training/location/display-address.jd +++ b/docs/html/training/location/display-address.jd @@ -324,7 +324,7 @@ public class FetchAddressIntentService extends IntentService { process if needed. If the service is already running then it remains running. Because the service extends {@link android.app.IntentService IntentService}, it shuts down automatically when all intents have been processed.

    - +

    Start the service from your app's main activity, and create an {@link android.content.Intent} to pass data to the service. You need an explicit intent, because you want only your service diff --git a/docs/html/training/location/geofencing.jd b/docs/html/training/location/geofencing.jd index 1cf89fdc8b920eb810af374dfe284d6d922cc383..ce6ad55ad8891d8a79a1ab769a1577b596bd46a5 100644 --- a/docs/html/training/location/geofencing.jd +++ b/docs/html/training/location/geofencing.jd @@ -369,7 +369,7 @@ reduce the alerts is to use a transition type of GEOFENCE_TRANSITION_DWELL instead of GEOFENCE_TRANSITION_ENTER. This way, the dwelling alert is sent only when the user stops -inside a geofence for a given period of time. You can choose the duration by setting a +inside a geofence for a given period of time. You can choose the duration by setting a loitering delay.

    diff --git a/docs/html/training/managing-audio/audio-output.jd b/docs/html/training/managing-audio/audio-output.jd index 416e5193f569459c5874e395ca9a04e5f4bf2053..ed1623beb6094c57337611007147c18c586cd586 100644 --- a/docs/html/training/managing-audio/audio-output.jd +++ b/docs/html/training/managing-audio/audio-output.jd @@ -8,8 +8,8 @@ previous.link=audio-focus.html @jd:body - -
    + +

    This lesson teaches you to

    @@ -25,16 +25,16 @@ previous.link=audio-focus.html -
    +

    Users have a number of alternatives when it comes to enjoying the audio from their Android devices. Most devices have a built-in speaker, headphone jacks for wired headsets, and many also feature Bluetooth connectivity and support for A2DP audio.

    - -

    Check What Hardware is Being Used

    - + +

    Check What Hardware is Being Used

    +

    How your app behaves might be affected by which hardware its output is being routed to.

    You can query the {@link android.media.AudioManager} to determine if the audio is currently @@ -48,13 +48,13 @@ if (isBluetoothA2dpOn()) { // Adjust output for Speakerphone. } else if (isWiredHeadsetOn()) { // Adjust output for headsets -} else { +} else { // If audio plays and noone can hear it, is it still playing? }

    -

    Handle Changes in the Audio Output Hardware

    +

    Handle Changes in the Audio Output Hardware

    When a headset is unplugged, or a Bluetooth device disconnected, the audio stream automatically reroutes to the built in speaker. If you listen to your music at as high a volume as I @@ -65,7 +65,7 @@ intent when this happens. It’s good practice to register a {@link android.cont that listens for this intent whenever you’re playing audio. In the case of music players, users typically expect the playback to be paused—while for games you may choose to significantly lower the volume.

    - +
     private class NoisyAudioStreamReceiver extends BroadcastReceiver {
         @Override
    diff --git a/docs/html/training/managing-audio/index.jd b/docs/html/training/managing-audio/index.jd
    index 9391449b57e239479dd818e585a27625c8a603c0..55b91c2c64ae7be28251a637e785d7176d3b70a3 100644
    --- a/docs/html/training/managing-audio/index.jd
    +++ b/docs/html/training/managing-audio/index.jd
    @@ -6,10 +6,10 @@ startpage=true
     
     @jd:body
     
    -
    +
    -

    Dependencies and prerequisites

    +

    Dependencies and prerequisites

    -
    +

    If your app plays audio, it’s important that your users can control the audio in a predictable manner. To ensure a great user experience, it’s also important that your app manages the audio focus -to ensure multiple apps aren’t playing audio at the same time.

    +to ensure multiple apps aren’t playing audio at the same time.

    -

    After this class, you will be able to build apps that respond to hardware audio key presses, +

    After this class, you will be able to build apps that respond to hardware audio key presses, which request audio focus when playing audio, and which respond appropriately to changes in audio -focus caused by the system or other applications.

    +focus caused by the system or other applications.

    + +

    Lessons

    -

    Lessons

    - - +will want to jump to a lesson or not.--> +
    Controlling Your App’s Volume and Playback
    Learn how to ensure your users can control the volume of your app using the hardware or software volume controls and where available the play, stop, pause, skip, and previous media -playback keys.
    - +playback keys. +
    Managing Audio Focus
    With multiple apps potentially playing audio it's important to think about how they should interact. To avoid every music app playing at the same time, Android uses audio focus to moderate audio playback. Learn how to request the audio focus, listen for a loss of audio focus, and how to -respond when that happens.
    - +respond when that happens. +
    Dealing with Audio Output Hardware
    Audio can be played from a number of sources. Learn how to find out where the audio is being -played and how to handle a headset being disconnected during playback.
    -
    +played and how to handle a headset being disconnected during playback. + diff --git a/docs/html/training/managing-audio/volume-playback.jd b/docs/html/training/managing-audio/volume-playback.jd index be0f583d50c7f4725dd85edc384f80785b6e0f79..7e2889300c8ae54840ac6fb0e906ef4df7f606f6 100644 --- a/docs/html/training/managing-audio/volume-playback.jd +++ b/docs/html/training/managing-audio/volume-playback.jd @@ -8,8 +8,8 @@ next.link=audio-focus.html @jd:body - -
    + +

    This lesson teaches you to

    @@ -26,11 +26,11 @@ Playback
  • Media Playback
  • -
    +
    - +

    A good user experience is a predictable one. If your app plays media it’s important that your users can control the volume of your app using the hardware or software volume controls of their device, bluetooth headset, or headphones.

    @@ -38,9 +38,9 @@ device, bluetooth headset, or headphones.

    Similarly, where appropriate and available, the play, stop, pause, skip, and previous media playback keys should perform their respective actions on the audio stream used by your app.

    - -

    Identify Which Audio Stream to Use

    - + +

    Identify Which Audio Stream to Use

    +

    The first step to creating a predictable audio experience is understanding which audio stream your app will use.

    @@ -53,11 +53,11 @@ clock, you’ll almost certainly be playing your audio using the {@link android.media.AudioManager#STREAM_MUSIC} stream.

    -

    Use Hardware Volume Keys to Control Your App’s Audio Volume

    +

    Use Hardware Volume Keys to Control Your App’s Audio Volume

    By default, pressing the volume controls modify the volume of the active audio stream. If your app isn't currently playing anything, hitting the volume keys adjusts the ringer volume.

    - +

    If you've got a game or music app, then chances are good that when the user hits the volume keys they want to control the volume of the game or music, even if they’re currently between songs or there’s no music in the current game location.

    @@ -65,8 +65,8 @@ there’s no music in the current game location.

    You may be tempted to try and listen for volume key presses and modify the volume of your audio stream that way. Resist the urge. Android provides the handy {@link android.app.Activity#setVolumeControlStream setVolumeControlStream()} method to direct volume key -presses to the audio stream you specify.

    - +presses to the audio stream you specify.

    +

    Having identified the audio stream your application will be using, you should set it as the volume stream target. You should make this call early in your app’s lifecycle—because you only need to call it once during the activity lifecycle, you @@ -85,7 +85,7 @@ specify (in this case “music”) whenever the target activity or fragment is v

    Use Hardware Playback Control Keys to Control Your App’s Audio -Playback

    +Playback

    Media playback buttons such as play, pause, stop, skip, and previous are available on some handsets and many connected or wireless headsets. Whenever a user presses one of these hardware diff --git a/docs/html/training/material/images/palette-library-color-profiles_2-1_2x.png b/docs/html/training/material/images/palette-library-color-profiles_2-1_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d14ec32c7500ca39065e3ecb9ff22228830def59 Binary files /dev/null and b/docs/html/training/material/images/palette-library-color-profiles_2-1_2x.png differ diff --git a/docs/html/training/material/images/palette-library-title-text-color_2-1_2x.png b/docs/html/training/material/images/palette-library-title-text-color_2-1_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..883adba6a430996ad178b9bb968fa797198be83f Binary files /dev/null and b/docs/html/training/material/images/palette-library-title-text-color_2-1_2x.png differ diff --git a/docs/html/training/material/index.jd b/docs/html/training/material/index.jd index 4001e6b7442f8c84d4d42266fb0cb3864227efd0..8baa0659e95b59ac487020c3f135f69dc6778784 100644 --- a/docs/html/training/material/index.jd +++ b/docs/html/training/material/index.jd @@ -3,7 +3,6 @@ page.type=design page.image=images/cards/material_2x.png page.metaDescription=Learn how to apply material design to your apps. - @jd:body

    @@ -58,6 +57,9 @@ specification and use the new components and functionality available in Andr
    Maintaining Compatibility
    Learn how to maintain compatibility with platform versions earlier than Android 5.0.
    + +
    Selecting Colors with the Palette API
    +
    Learn how to select colors for your app using the v7 Palette library.

    Video Training

    diff --git a/docs/html/training/material/palette-colors.html b/docs/html/training/material/palette-colors.html new file mode 100644 index 0000000000000000000000000000000000000000..27485d2decd813e2c0fe653c2819302616dbf84d --- /dev/null +++ b/docs/html/training/material/palette-colors.html @@ -0,0 +1,310 @@ + + + Selecting Colors with the Palette API + + + + + + + + +

    Good visual design is essential for a successful app, and color schemes are a primary component of design. The palette library is a +support library +that extracts prominent colors from images to help you create visually engaging apps.

    + +

    You can use the palette library to design layout +themes and apply custom colors to visual elements in your app. +For example, you can use a palette to create a color-coordinated title +card for a song based on its album cover or to adjust an app’s toolbar color when its +background image changes. The Palette object gives +you access to the colors in a Bitmap +image while also providing six main color profiles from the bitmap to help +inform your design choices.

    + +

    Set up the library

    + +

    To use the palette library, install or update the Android +Support Library to version 24.0.0 or higher and follow the instructions for Adding +Support Libraries to add the palette library to your app development project.

    + +

    Make sure that the version specified in your dependency identifier matches your +app’s compileSdkVersion, set in the build.gradle +file:

    + +
    +android {
    +  compileSdkVersion 24
    +  ...
    +}
    +
    +dependencies {
    +  ...
    +  compile 'com.android.support:palette-v7:24.2.1'
    +}
    +
    + +

    For more information about adding the palette dependency, read about the palette +feature in the support +library documentation.

    + +

    Create a palette

    + +

    A Palette object gives you access to the primary colors in an +image, as well as the corresponding colors for overlaid text. Use palettes to design +your app’s style and to dynamically change your app’s color scheme based on a +given source image.

    + +

    To create a palette, first instantiate a Palette.Builder +from a Bitmap. You can then use the +Palette.Builder to customize the palette before generating it. This +section will describe palette generation and customization from a bitmap +image.

    + +

    Generate a Palette instance

    + +

    Generate a Palette instance using Palette’s +from(Bitmap +bitmap) method to first create a Palette.Builder +from a Bitmap. The builder can then generate the palette either +synchronously or asynchronously.

    + +

    Use synchronous palette generation if you want to create the palette on +the same thread as the method being called. If you generate the palette +asynchronously on a different thread, use the onGenerated() +method to access the palette immediately after it has been created.

    + +

    The following code snippet provides example methods for both types of palette generation:

    + +
    +// Generate palette synchronously and return it
    +public Palette createPaletteSync(Bitmap bitmap) {
    +  Palette p = Palette.from(bitmap).generate();
    +  return p;
    +}
    +
    +// Generate palette asynchronously and use it on a different
    +// thread using onGenerated()
    +public void createPaletteAsync(Bitmap bitmap) {
    +  Palette.from(bitmap).generate(new PaletteAsyncListener() {
    +    public void onGenerated(Palette p) {
    +      // Use generated instance
    +    }
    +  });
    +}
    +
    + +

    If you need to continuously generate palettes for a sorted list of images +or objects, consider caching +the Palette instances to prevent slow UI performance. You also +should not create the palettes on your main thread.

    + +

    Customize your palette

    + +

    The Palette.Builder allows you to customize your palette by +choosing how many colors are in the resulting palette, what area of your +image the builder uses to generate the palette, and what colors are allowed in the +palette. For example, you can filter out the color black or ensure that the +builder only uses the top half of an image to generate your palette.

    + +

    Fine-tune your palette’s size and colors with the following methods from +the Palette.Builder class:

    + +
    + +
    addFilter()
    +
    This method adds a filter that indicates what colors are allowed in the + resulting palette. Pass in your own Palette.Filter + and modify its isAllowed() method to determine which colors are + filtered from the palette.
    + +
    maximumColorCount()
    +
    This method sets the maximum number of colors in your palette. The + default value is 16, and the optimal value depends on the source image. + For landscapes, optimal values range from 8-16 while pictures with faces + usually have values that fall between 24-32. The + Palette.Builder takes longer to generate palettes with more + colors.
    + +
    setRegion()
    +
    This method indicates what area of the bitmap the builder uses when + creating the palette. You can only use this method when generating the palette from + a bitmap, and it does not affect the original image.
    + +
    addTarget()
    +
    This method allows you to perform your own color matching by adding a + Target + color profile to the builder. If the default Targets are not + sufficient, advanced developers can create their own Targets + using a Target.Builder.
    + +
    + +

    Extract color profiles

    + +

    Based on the standards +of material design, the palette library extracts commonly used color +profiles from an image. Each profile is defined by a Target, +and colors extracted from the bitmap image are scored against each profile +based on saturation, luminance, and population (number of pixels in the bitmap +represented by the color). For each profile, the color with the best score +defines that color profile for the given image.

    + +

    By default, a Palette object contains 16 primary colors from +a given image. When generating your palette, you can customize its number of colors using the +Palette.Builder. Extracting more colors provides more potential +matches for each color profile but also causes Palette.Builder to +take longer when generating the palette.

    + +

    The palette library attempts to extract the following six color +profiles:

    + +
      +
    • Light Vibrant
    • +
    • Vibrant
    • +
    • Dark Vibrant
    • +
    • Light Muted
    • +
    • Muted
    • +
    • Dark Muted
    • +
    + +

    Each of Palette’s get<Profile>Color() +methods returns the color in the palette associated with that particular profile, +where <Profile> is replaced by the name of one of the six +color profiles. For example, the method to get the Dark Vibrant color profile is getDarkVibrantColor(). +Since not all images will contain all color profiles, you must also provide +a default color to return.

    + +

    Figure 1 displays a photo and its corresponding color +profiles from the get<Profile>Color() methods.

    + + + +

    Figure 1. An example image and its +extracted color profiles given the default maximum color count (16) for the palette.

    + +

    Use swatches to create color schemes

    + +

    The Palette class also generates Palette.Swatch +objects for each color profile. Palette.Swatch +objects contain the associated color for that profile, as well as the +color’s population in pixels.

    + +

    Swatches have additional methods for accessing more information about the color +profile, such as HSL values and pixel population. You can use swatches to help +create more comprehensive color schemes and app themes using the getBodyTextColor() +and getTitleTextColor() +methods. These methods return colors appropriate for use over the swatch’s +color.

    + +

    Each of Palette’s get<Profile>Swatch() +methods returns the swatch associated with that particular profile, +where <Profile> is replaced by the name of one of the six +color profiles. Although the palette’s get<Profile>Swatch() methods +do not require default value parameters, they return null if that +particular profile does not exist in the image. Therefore, you should check that +a swatch is not null before using it. For example, the following method +returns the Vibrant swatch from a palette if the swatch is not null:

    + +
    +// Return a palette's vibrant swatch after checking that it exists
    +private Palette.Swatch checkVibrantSwatch(Palette p) {
    +  Palette.Swatch vibrant = p.getVibrantSwatch();
    +  if (vibrant != null) {
    +    return vibrant;
    +  }
    +  // Throw error
    +}
    +
    + +

    To access all colors in a palette, the getSwatches() +method returns a list of all swatches generated from an +image, including the standard six color profiles.

    + +

    The following snippet of code uses the methods from the above code snippets to +synchronously generate a palette, get its vibrant swatch, and change the colors of a +toolbar to match the bitmap image. Figure 2 displays the resulting image and toolbar.

    + +
    + +
    + +
    +// Set the background and text colors of a toolbar given a
    +// bitmap image to match
    +public void setToolbarColor(Bitmap bitmap) {
    +  // Generate the palette and get the vibrant swatch
    +  // See the createPaletteSync() and checkVibrantSwatch() methods
    +  // from the code snippets above
    +  Palette p = createPaletteSync(bitmap);
    +  Palette.Swatch vibrantSwatch = checkVibrantSwatch(p);
    +  
    +  // Set the toolbar background and text colors
    +  Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    +  toolbar.setBackgroundColor(vibrantSwatch.getRgb());
    +  toolbar.setTitleTextColor(vibrantSwatch.getTitleTextColor());
    +}
    +
    + +
    + +
    + + + +

    Figure 2. An example image with its + vibrant-colored toolbar and corresponding title text color.

    + +
    + +
    + + + diff --git a/docs/html/training/monitoring-device-state/battery-monitoring.jd b/docs/html/training/monitoring-device-state/battery-monitoring.jd index db75aaf1f89986bb419b2c750c365026bb3726d4..bab9c9cf6baf80a0e8ad60e60029bae2c8420df2 100644 --- a/docs/html/training/monitoring-device-state/battery-monitoring.jd +++ b/docs/html/training/monitoring-device-state/battery-monitoring.jd @@ -141,10 +141,11 @@ receiver. The receiver is triggered whenever the device battery becomes low or e condition by listening for {@link android.content.Intent#ACTION_BATTERY_LOW} and {@link android.content.Intent#ACTION_BATTERY_OKAY}.

    -
    <receiver android:name=".BatteryLevelReceiver">
    -<intent-filter>
    -  <action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
    -  <action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
    +
    +<receiver android:name=".BatteryLevelReceiver">
    +  <intent-filter>
    +    <action android:name="android.intent.action.BATTERY_LOW"/>
    +    <action android:name="android.intent.action.BATTERY_OKAY"/>
       </intent-filter>
     </receiver>
    diff --git a/docs/html/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html/training/monitoring-device-state/connectivity-monitoring.jd index d5e7a859b1216df2718f053ef4ca39d5785f2c7e..c63822bea116b4012650feadfbe839e125d2f788 100644 --- a/docs/html/training/monitoring-device-state/connectivity-monitoring.jd +++ b/docs/html/training/monitoring-device-state/connectivity-monitoring.jd @@ -11,7 +11,7 @@ next.link=manifest-receivers.html @jd:body -
    +

    This lesson teaches you to

    @@ -27,33 +27,33 @@ next.link=manifest-receivers.html
  • Intents and Intent Filters -
  • +

    Some of the most common uses for repeating alarms and background services is to schedule regular updates of application data from Internet resources, cache data, or execute long running downloads. But if you aren't connected to the Internet, or the connection is too slow to complete your -download, why both waking the device to schedule the update at all?

    +download, why bother waking the device to schedule the update at all?

    You can use the {@link android.net.ConnectivityManager} to check that you're actually connected to the Internet, and if so, what type of connection is in place.

    -

    Determine if You Have an Internet Connection

    - +

    Determine if You Have an Internet Connection

    +

    There's no need to schedule an update based on an Internet resource if you aren't connected to -the Internet. The following snippet shows how to use the {@link android.net.ConnectivityManager} +the Internet. The following snippet shows how to use the {@link android.net.ConnectivityManager} to query the active network and determine if it has Internet connectivity.

    ConnectivityManager cm =
             (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    - 
    +
     NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
     boolean isConnected = activeNetwork != null &&
                           activeNetwork.isConnectedOrConnecting();
    -

    Determine the Type of your Internet Connection

    +

    Determine the Type of your Internet Connection

    It's also possible to determine the type of Internet connection currently available.

    @@ -71,7 +71,7 @@ suspended until you have a Wi-Fi connection.

    to resume them once an Internet connection has been established.

    -

    Monitor for Changes in Connectivity

    +

    Monitor for Changes in Connectivity

    The {@link android.net.ConnectivityManager} broadcasts the {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION} ({@code diff --git a/docs/html/training/monitoring-device-state/doze-standby.jd b/docs/html/training/monitoring-device-state/doze-standby.jd index 9250288a7dd4f39aa9c3fd02e25d3fa1e36361d8..7caef402e431a016a090aa308718d1f46f81fa30 100644 --- a/docs/html/training/monitoring-device-state/doze-standby.jd +++ b/docs/html/training/monitoring-device-state/doze-standby.jd @@ -306,25 +306,22 @@ Standby

    - An app that is whitelisted can use the network and hold - - - partial wake locks during Doze and - App Standby. However, other restrictions still apply to the - whitelisted app, just as they do to other apps. For example, the whitelisted - app’s jobs and syncs are deferred, and its regular {@link android.app.AlarmManager} alarms do not - fire. An app can check whether it is currently on the exemption whitelist by - calling {@link + An app that is whitelisted can use the network and hold partial + wake locks during Doze and App Standby. However, other + restrictions still apply to the whitelisted app, just as they do to + other apps. For example, the whitelisted app’s jobs and syncs are deferred + (on API level 23 and below), and its regular {@link android.app.AlarmManager} + alarms do not fire. An app can check whether it is currently on the exemption + whitelist by calling {@link android.os.PowerManager#isIgnoringBatteryOptimizations(java.lang.String) isIgnoringBatteryOptimizations()}. -

    Users can manually configure the whitelist in Settings > Battery > Battery Optimization. Alternatively, the system provides ways for apps to ask users to whitelist them. -

      diff --git a/docs/html/training/monitoring-device-state/manifest-receivers.jd b/docs/html/training/monitoring-device-state/manifest-receivers.jd index ca184aa54589987488919a277fa6219653cb2e9b..5efa2facf901911b498c25b251e31f5a0f9af978 100644 --- a/docs/html/training/monitoring-device-state/manifest-receivers.jd +++ b/docs/html/training/monitoring-device-state/manifest-receivers.jd @@ -9,7 +9,7 @@ previous.link=connectivity-monitoring.html @jd:body -
      +

      This lesson teaches you to

      @@ -21,10 +21,13 @@ Efficiency

      You should also read

      -
      +

      The simplest way to monitor device state changes is to create a {@link @@ -32,16 +35,25 @@ android.content.BroadcastReceiver} for each state you're monitoring and register your application manifest. Then within each of these receivers you simply reschedule your recurring alarms based on the current device state.

      -

      A side-effect of this approach is that your app will wake the device each time any of these -receivers is triggered—potentially much more frequently than required.

      -

      A better approach is to disable or enable the broadcast receivers at runtime. That way you can use the receivers you declared in the manifest as passive alarms that are triggered by system events only when necessary.

      - -

      Toggle and Cascade State Change Receivers to Improve Efficiency

      - +

      + Warning: Limit how many broadcast + receivers you set in your app. Instead of using broadcast receivers, + consider using other APIs for + performing background work. For example, in Android 5.0 (API level 21) and + higher, you can use the {@link android.app.job.JobScheduler} class for + assigning work to be completed in the background. + For more information about APIs you can use instead of the + {@link android.content.BroadcastReceiver} class for scheduling background + work, see + Background Optimizations. +

      + +

      Toggle and Cascade State Change Receivers to Improve Efficiency

      +

      You can use the {@link android.content.pm.PackageManager} to toggle the enabled state on any component defined in the manifest, including whichever broadcast receivers you wish to enable or disable as shown in the snippet below:

      @@ -59,6 +71,6 @@ your receivers except the connectivity-change receiver. Conversely, once you are stop listening for connectivity changes and simply check to see if you're online immediately before performing an update and rescheduling a recurring update alarm.

      -

      You can use the same technique to delay a download that requires higher bandwidth to complete. +

      You can use the same technique to delay a download that requires higher bandwidth to complete. Simply enable a broadcast receiver that listens for connectivity changes and initiates the download only after you are connected to Wi-Fi.

      diff --git a/docs/html/training/multiple-threads/create-threadpool.jd b/docs/html/training/multiple-threads/create-threadpool.jd index e22afd37c2221a13aec4fde40d23e7148131c7f6..df28833d3177d23c4fd00924d8a982ea76abc6af 100644 --- a/docs/html/training/multiple-threads/create-threadpool.jd +++ b/docs/html/training/multiple-threads/create-threadpool.jd @@ -48,7 +48,7 @@ trainingnavtop=true also occurs in any object that is only instantiated once. To learn more about this, read the Processes and Threads API guide. - +

      Define the Thread Pool Class

      diff --git a/docs/html/training/multiple-threads/define-runnable.jd b/docs/html/training/multiple-threads/define-runnable.jd index 40853d3329cd72146ec83d10820ff0a6235c1cf1..84c7bdffd593d00eef728b0be925f9886da317c1 100644 --- a/docs/html/training/multiple-threads/define-runnable.jd +++ b/docs/html/training/multiple-threads/define-runnable.jd @@ -23,11 +23,10 @@ trainingnavtop=true

      Download the sample

      ThreadSample.zip

      -
      -
    +
    -
    -
    +
    +

    This lesson shows you how to implement a {@link java.lang.Runnable} class, which runs the code diff --git a/docs/html/training/multiscreen/adaptui.jd b/docs/html/training/multiscreen/adaptui.jd index 34e9d7df7f8d57908196c75d066808ab6739e018..469012bd8ac8451b3cedba3e78528b4ac80010f6 100644 --- a/docs/html/training/multiscreen/adaptui.jd +++ b/docs/html/training/multiscreen/adaptui.jd @@ -10,9 +10,9 @@ previous.link=screendensities.html -

    -
    - +
    +
    +

    This lesson teaches you to

      @@ -28,18 +28,18 @@ previous.link=screendensities.html
    1. Supporting Tablets and Handsets
    2. - +

      Try it out

      - +
      Download the sample app -

      NewsReader.zip

      -
      - - -
    -
    +

    NewsReader.zip

    +
    + + +
    +

    Depending on the layout that your application is currently showing, the UI flow may be different. For example, if your application is in the dual-pane @@ -66,7 +66,7 @@ public class NewsReaderActivity extends FragmentActivity { setContentView(R.layout.main_layout); View articleView = findViewById(R.id.article); - mIsDualPane = articleView != null && + mIsDualPane = articleView != null && articleView.getVisibility() == View.VISIBLE; } } @@ -139,7 +139,7 @@ public void onCreate(Bundle savedInstanceState) { else { /* use list navigation (spinner) */ actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST); - SpinnerAdapter adap = new ArrayAdapter(this, + SpinnerAdapter adap = new ArrayAdapter(this, R.layout.headline_item, CATEGORIES); actionBar.setListNavigationCallbacks(adap, handler); } @@ -157,7 +157,7 @@ large screens, but is a separate activity on smaller screens.

    In cases like this, you can usually avoid code duplication by reusing the same {@link android.app.Fragment} subclass in several activities. For example, -ArticleFragment +ArticleFragment is used in the dual-pane layout:

    {@sample development/samples/training/multiscreen/newsreader/res/layout/twopanes.xml all} @@ -206,7 +206,7 @@ activity (as opposed to notifying a specific hard-coded activity):

    public class HeadlinesFragment extends ListFragment { ... @Override - public void onItemClick(AdapterView<?> parent, + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (null != mHeadlineSelectedListener) { mHeadlineSelectedListener.onHeadlineSelected(position); diff --git a/docs/html/training/multiscreen/index.jd b/docs/html/training/multiscreen/index.jd index 8eff246cd8ebcf96cfc4cb772bf8ba2d0968b424..2c59facbda77145878428947b555a7581e7b05f0 100644 --- a/docs/html/training/multiscreen/index.jd +++ b/docs/html/training/multiscreen/index.jd @@ -7,10 +7,10 @@ startpage=true @jd:body -
    -
    - -

    Dependencies and prerequisites

    +
    +
    + +

    Dependencies and prerequisites

    - +

    NewsReader.zip

    +
    + +
    +
    +

    Android powers hundreds of device types with several different screen sizes, ranging from small phones to large TV sets. Therefore, it’s important that you design your application to be compatible with all screen sizes so it’s available to as many @@ -62,26 +62,26 @@ of reusable code for your own application.

    href="{@docRoot}tools/support-library/index.html">support library in order to use the {@link android.app.Fragment} APIs on versions lower than Android 3.0. You must download and add the library to your application in order to use all APIs in this class.

    - -

    Lessons

    - -
    -
    Supporting Different Screen Sizes
    + +

    Lessons

    + +
    +
    Supporting Different Screen Sizes
    This lesson walks you through how to design layouts that adapts several different screen sizes (using flexible dimensions for views, {@link android.widget.RelativeLayout}, screen size and orientation qualifiers, - alias filters, and nine-patch bitmaps).
    - + alias filters, and nine-patch bitmaps). +
    Supporting Different Screen - Densities
    + Densities
    This lesson shows you how to support screens that have different pixel densities (using density-independent pixels and providing - bitmaps appropriate for each density).
    - -
    Implementing Adaptative UI Flows
    + bitmaps appropriate for each density). + +
    Implementing Adaptative UI Flows
    This lesson shows you how to implement your UI flow in a way that adapts to several screen size/density combinations (run-time detection of active layout, reacting according to - current layout, handling screen configuration changes).
    -
    + current layout, handling screen configuration changes). +
    diff --git a/docs/html/training/multiscreen/screensizes.jd b/docs/html/training/multiscreen/screensizes.jd index 2cd59ee90a564bfb5a640078a36891dc447591e0..040bb85a88e0cc25668b86a1aea8937379bf7e16 100755 --- a/docs/html/training/multiscreen/screensizes.jd +++ b/docs/html/training/multiscreen/screensizes.jd @@ -10,8 +10,8 @@ next.link=screendensities.html -
    -
    +
    +

    This lesson teaches you to

      @@ -30,27 +30,27 @@ next.link=screendensities.html
    1. Supporting Multiple Screens
    2. -

      Try it out

      - -
      +

      Try it out

      + +
      Download the sample app -

      NewsReader.zip

      -
      - -
      -
    +

    NewsReader.zip

    +
    + +
    +

    This lesson shows you how to support different screen sizes by:

    -
      -
    • Ensuring your layout can be adequately resized to fit the screen
    • -
    • Providing appropriate UI layout according to screen configuration
    • +
        +
      • Ensuring your layout can be adequately resized to fit the screen
      • +
      • Providing appropriate UI layout according to screen configuration
      • Ensuring the correct layout is applied to the correct screen
      • -
      • Providing bitmaps that scale correctly
      • -
      +
    • Providing bitmaps that scale correctly
    • +
    -

    Use "wrap_content" and "match_parent"

    +

    Use "wrap_content" and "match_parent"

    To ensure that your layout is flexible and adapts to different screen sizes, you should use "wrap_content" and "match_parent" for the width @@ -78,11 +78,11 @@ width and height:

    and landscape (right).

    -

    Use RelativeLayout

    +

    Use RelativeLayout

    You can construct fairly complex layouts using nested instances of {@link android.widget.LinearLayout} and -combinations of "wrap_content" and "match_parent" sizes. +combinations of "wrap_content" and "match_parent" sizes. However, {@link android.widget.LinearLayout} does not allow you to precisely control the spacial relationships of child views; views in a {@link android.widget.LinearLayout} simply line up side-by-side. If you need child views to be oriented in variations other than a straight line, a @@ -139,8 +139,8 @@ the right side of the screen.

    spatial relationships are preserved as specified by the {@link android.widget.RelativeLayout.LayoutParams}.

    - -

    Use Size Qualifiers

    + +

    Use Size Qualifiers

    There's only so much mileage you can get from a flexible layout or relative layout like the one in the previous sections. While those layouts adapt to @@ -148,7 +148,7 @@ different screens by stretching the space within and around components, they may not provide the best user experience for each screen size. Therefore, your application should not only implement flexible layouts, but should also provide several alternative layouts to target different screen configurations. You do -so by using configuration qualifiers, which allows the runtime +so by using configuration qualifiers, which allows the runtime to automatically select the appropriate resource based on the current device’s configuration (such as a different layout design for different screen sizes).

    @@ -209,13 +209,13 @@ layout.

    However, this won't work well on pre-3.2 devices, because they don't recognize sw600dp as a size qualifier, so you still have to use the large -qualifier as well. So, you should have a file named +qualifier as well. So, you should have a file named res/layout-large/main.xml which is identical to res/layout-sw600dp/main.xml. In the next section you'll see a technique that allows you to avoid duplicating the layout files this way.

    -

    Use Layout Aliases

    +

    Use Layout Aliases

    The smallest-width qualifier is available only on Android 3.2 and above. Therefore, you should also still use the abstract size bins (small, normal, @@ -271,7 +271,7 @@ applied to tablets and TVs regardless of Android version (pre-3.2 tablets and TV {@code large}, and post-3.2 will match sw600dp).

    -

    Use Orientation Qualifiers

    +

    Use Orientation Qualifiers

    Some layouts work well in both landscape and portrait orientations, but most of them can benefit from adjustments. In the News Reader sample app, here is how the layout @@ -287,7 +287,7 @@ behaves in each screen size and orientation:

  • TV, landscape: dual pane, wide, with action bar
  • -

    So each of these layouts is defined in an XML file in the +

    So each of these layouts is defined in an XML file in the res/layout/ directory. To then assign each layout to the various screen configurations, the app uses layout aliases to match them to each configuration:

    @@ -361,7 +361,7 @@ borders indicate the places where the image can be stretched, and the ones on the right and bottom borders indicate where the content should be placed.

    -

    Also, notice the .9.png extension. You must use this +

    Also, notice the .9.png extension. You must use this extension, since this is how the framework detects that this is a nine-patch image, as opposed to a regular PNG image.

    diff --git a/docs/html/training/notify-user/build-notification.jd b/docs/html/training/notify-user/build-notification.jd index d24a4960a98722039b2f91925ca46dc926d767e9..baa10748c4ec4c5c781bf1d75f07beeede865422 100644 --- a/docs/html/training/notify-user/build-notification.jd +++ b/docs/html/training/notify-user/build-notification.jd @@ -31,7 +31,7 @@ trainingnavtop=true
  • - Notifications Design Guide + Notifications Design Guide
  • @@ -42,9 +42,9 @@ trainingnavtop=true

    This lesson explains how to create and issue a notification.

    -

    The examples in this class are based on the -{@link android.support.v4.app.NotificationCompat.Builder} class. -{@link android.support.v4.app.NotificationCompat.Builder} +

    The examples in this class are based on the +{@link android.support.v4.app.NotificationCompat.Builder} class. +{@link android.support.v4.app.NotificationCompat.Builder} is in the Support Library. You should use {@link android.support.v4.app.NotificationCompat} and its subclasses, particularly {@link android.support.v4.app.NotificationCompat.Builder}, to @@ -52,9 +52,9 @@ provide the best notification support for a wide range of platforms.

    Create a Notification Builder

    -

    When creating a notification, specify the UI content and actions with a -{@link android.support.v4.app.NotificationCompat.Builder} object. At bare minimum, -a {@link android.support.v4.app.NotificationCompat.Builder Builder} +

    When creating a notification, specify the UI content and actions with a +{@link android.support.v4.app.NotificationCompat.Builder} object. At bare minimum, +a {@link android.support.v4.app.NotificationCompat.Builder Builder} object must include the following:

      @@ -96,7 +96,7 @@ of {@link android.app.Activity} you're starting. When you start an {@link android.app.Activity} from a notification, you must preserve the user's expected navigation experience. In the snippet below, clicking the notification opens a new activity that effectively extends the behavior of the notification. In this -case there is no need to create an artificial back stack (see +case there is no need to create an artificial back stack (see Preserving Navigation when Starting an Activity for more information):

      @@ -132,11 +132,11 @@ mBuilder.setContentIntent(resultPendingIntent);

      To issue the notification:

        -
      • Get an instance of {@link android.app.NotificationManager}.
      • +
      • Get an instance of {@link android.app.NotificationManager}.
      • Use the {@link android.app.NotificationManager#notify notify()} method to issue the -notification. When you call {@link android.app.NotificationManager#notify notify()}, specify a notification ID. -You can use this ID to update the notification later on. This is described in more detail in +notification. When you call {@link android.app.NotificationManager#notify notify()}, specify a notification ID. +You can use this ID to update the notification later on. This is described in more detail in Managing Notifications.
      • Call {@link @@ -152,7 +152,7 @@ NotificationCompat.Builder mBuilder; // Sets an ID for the notification int mNotificationId = 001; // Gets an instance of the NotificationManager service -NotificationManager mNotifyMgr = +NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // Builds the notification and issues it. mNotifyMgr.notify(mNotificationId, mBuilder.build()); diff --git a/docs/html/training/notify-user/display-progress.jd b/docs/html/training/notify-user/display-progress.jd index 3439571fe30641281cf5f9b8d013ac0966b1f370..9018eb1950c026b8f9a9dad78b502ec5daa183fc 100644 --- a/docs/html/training/notify-user/display-progress.jd +++ b/docs/html/training/notify-user/display-progress.jd @@ -29,7 +29,7 @@ trainingnavtop=true
      • - Notifications Design Guide + Notifications Design Guide
      @@ -59,9 +59,9 @@ trainingnavtop=true

      Display a Fixed-duration Progress Indicator

      To display a determinate progress bar, add the bar to your notification by calling - {@link android.support.v4.app.NotificationCompat.Builder#setProgress - setProgress(max, progress, false)} and then issue the notification. - The third argument is a boolean that indicates whether the + {@link android.support.v4.app.NotificationCompat.Builder#setProgress + setProgress(max, progress, false)} and then issue the notification. + The third argument is a boolean that indicates whether the progress bar is indeterminate (true) or determinate (false). As your operation proceeds, increment progress, and update the notification. At the end of the operation, @@ -74,7 +74,7 @@ trainingnavtop=true You can either leave the progress bar showing when the operation is done, or remove it. In either case, remember to update the notification text to show that the operation is complete. To remove the progress bar, call - {@link android.support.v4.app.NotificationCompat.Builder#setProgress + {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}. For example:

      @@ -136,14 +136,14 @@ new Thread(
       

      To display a continuing (indeterminate) activity indicator, add it to your notification with {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)} - and issue the notification. The first two arguments are ignored, and the third argument + and issue the notification. The first two arguments are ignored, and the third argument declares that the indicator is indeterminate. The result is an indicator that has the same style as a progress bar, except that its animation is ongoing.

      Issue the notification at the beginning of the operation. The animation will run until you modify your notification. When the operation is done, call - {@link android.support.v4.app.NotificationCompat.Builder#setProgress + {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)} and then update the notification to remove the activity indicator. Always do this; otherwise, the animation will run even when the operation is complete. Also remember to change the notification text to indicate that the operation is complete. @@ -160,7 +160,7 @@ mNotifyManager.notify(id, mBuilder.build());

      Replace the lines you've found with the following lines. Notice that the third parameter - in the {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()} + in the {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()} call is set to {@code true} to indicate that the progress bar is indeterminate:

      diff --git a/docs/html/training/notify-user/expanded.jd b/docs/html/training/notify-user/expanded.jd index b657426829565af6fab51a42db6687583b0de80c..60853caf047b2fef6598b9651da4f8702fea786a 100644 --- a/docs/html/training/notify-user/expanded.jd +++ b/docs/html/training/notify-user/expanded.jd @@ -29,7 +29,7 @@ trainingnavtop=true
    • - Notifications Design Guide + Notifications Design Guide
    @@ -75,7 +75,7 @@ big view give users access to same functionality:

    The normal view provides these features through a new activity that launches -when the user clicks the notification. Keep this in mind as you design your notifications—first +when the user clicks the notification. Keep this in mind as you design your notifications—first provide the functionality in the normal view, since this is how many users will interact with the notification.

    @@ -87,19 +87,19 @@ to construct and issue the notification.

    In this snippet, the {@link android.app.IntentService} method -{@link android.app.IntentService#onHandleIntent onHandleIntent()} specifies the new activity +{@link android.app.IntentService#onHandleIntent onHandleIntent()} specifies the new activity that will be launched if the user -clicks the notification itself. The method -{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()} +clicks the notification itself. The method +{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()} defines a pending intent that should be fired when the user clicks the notification, thereby launching the activity.

    Intent resultIntent = new Intent(this, ResultActivity.class);
     resultIntent.putExtra(CommonConstants.EXTRA_MESSAGE, msg);
    -resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 
    +resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
             Intent.FLAG_ACTIVITY_CLEAR_TASK);
    -     
    -// Because clicking the notification launches a new ("special") activity, 
    +
    +// Because clicking the notification launches a new ("special") activity,
     // there's no need to create an artificial back stack.
     PendingIntent resultPendingIntent =
              PendingIntent.getActivity(
    @@ -130,8 +130,8 @@ snoozeIntent.setAction(CommonConstants.ACTION_SNOOZE);
     PendingIntent piSnooze = PendingIntent.getService(this, 0, snoozeIntent, 0);
     
    -

    This snippet shows how to construct the -{@link android.support.v4.app.NotificationCompat.Builder Builder} object. +

    This snippet shows how to construct the +{@link android.support.v4.app.NotificationCompat.Builder Builder} object. It sets the style for the big view to be "big text," and sets its content to be the reminder message. It uses {@link android.support.v4.app.NotificationCompat.Builder#addAction addAction()} diff --git a/docs/html/training/notify-user/index.jd b/docs/html/training/notify-user/index.jd index 616e767873f8e1dcc2cbfb8aacb1db6610e3244b..4d930e0b2b947bc50a7ad38ad792d9555615ca2b 100644 --- a/docs/html/training/notify-user/index.jd +++ b/docs/html/training/notify-user/index.jd @@ -27,7 +27,7 @@ startpage=true

  • - Notifications Design Guide + Notifications Design Guide
  • @@ -43,14 +43,14 @@ class="button">Download the sample

    - A notification is a user interface element that you display outside your app's normal UI to indicate - that an event has occurred. Users can choose to view the notification while using other apps and respond - to it when it's convenient for them. + A notification is a user interface element that you display outside your app's normal UI to indicate + that an event has occurred. Users can choose to view the notification while using other apps and respond + to it when it's convenient for them.

    - The Notifications design guide shows + The Notifications design guide shows you how to design effective notifications and when to use them. This class shows you how to implement the most common notification designs.

    @@ -86,10 +86,10 @@ class="button">Download the sample
    - Learn how to create a big view within an expanded notification, while still maintaining + Learn how to create a big view within an expanded notification, while still maintaining backward compatibility.
    - +
    Displaying Progress in a Notification diff --git a/docs/html/training/notify-user/managing.jd b/docs/html/training/notify-user/managing.jd index fc12cfb9f32a2326fe4fe4e15b99ccb98b01f879..c68d6f9ab04cf0aaf5b4cec35075ea7cd0a21284 100644 --- a/docs/html/training/notify-user/managing.jd +++ b/docs/html/training/notify-user/managing.jd @@ -29,7 +29,7 @@ trainingnavtop=true
  • - Notifications Design Guide + Notifications Design Guide
  • diff --git a/docs/html/training/notify-user/navigation.jd b/docs/html/training/notify-user/navigation.jd index b7051ab5f1fabfa5c02c148877b3f6e2b208a40a..d0ec1cddc35ccc5b0763451b3d82e16745fedf7a 100644 --- a/docs/html/training/notify-user/navigation.jd +++ b/docs/html/training/notify-user/navigation.jd @@ -29,7 +29,7 @@ trainingnavtop=true
  • - Notifications Design Guide + Notifications Design Guide
  • @@ -37,7 +37,7 @@ trainingnavtop=true

    - Part of designing a notification is preserving the user's expected navigation experience. + Part of designing a notification is preserving the user's expected navigation experience. For a detailed discussion of this topic, see the Notifications API guide. @@ -49,7 +49,7 @@ trainingnavtop=true

    You're starting an {@link android.app.Activity} that's part of the application's normal - workflow. + workflow.
    Special activity @@ -202,10 +202,10 @@ NotificationCompat.Builder builder = new NotificationCompat.Builder(this); Intent notifyIntent = new Intent(new ComponentName(this, ResultActivity.class)); // Sets the Activity to start in a new, empty task -notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | +notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // Creates the PendingIntent -PendingIntent notifyIntent = +PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, @@ -214,7 +214,7 @@ PendingIntent notifyIntent = ); // Puts the PendingIntent into the notification builder -builder.setContentIntent(notifyIntent); +builder.setContentIntent(pendingIntent); // Notifications are issued by sending them to the // NotificationManager system service. NotificationManager mNotificationManager = diff --git a/docs/html/training/run-background-service/report-status.jd b/docs/html/training/run-background-service/report-status.jd index 41121c17e3e686646c8cd87a916f7abed993b23a..41fbb00e115ff596c6da798e5075b1aaffc8660c 100644 --- a/docs/html/training/run-background-service/report-status.jd +++ b/docs/html/training/run-background-service/report-status.jd @@ -91,7 +91,7 @@ public class RSSPullService extends IntentService {

    Receive Status Broadcasts from an IntentService

    - + To receive broadcast {@link android.content.Intent} objects, use a subclass of {@link android.content.BroadcastReceiver}. In the subclass, implement the {@link android.content.BroadcastReceiver#onReceive BroadcastReceiver.onReceive()} callback @@ -137,7 +137,7 @@ public class DisplayActivity extends FragmentActivity { // The filter's action is BROADCAST_ACTION IntentFilter mStatusIntentFilter = new IntentFilter( Constants.BROADCAST_ACTION); - + // Adds a data filter for the HTTP scheme mStatusIntentFilter.addDataScheme("http"); ... @@ -194,6 +194,6 @@ public class DisplayActivity extends FragmentActivity { {@link android.content.Intent}.

    - +

    diff --git a/docs/html/training/safebrowsing/index.jd b/docs/html/training/safebrowsing/index.jd new file mode 100644 index 0000000000000000000000000000000000000000..c6c72bfd1460a120668640cea0a857b2d2eb7bc1 --- /dev/null +++ b/docs/html/training/safebrowsing/index.jd @@ -0,0 +1,315 @@ +page.title=Checking URLs with the Safe Browsing API + +@jd:body + + + + +

    + SafetyNet provides services for determining whether a URL has been marked as + a known threat by Google. +

    + +

    + The service provides an API your app can use to determine whether a + particular URL has been classified by Google as a known threat. Internally, + SafetyNet implements a client for the Safe Browsing Network Protocol v4 + developed by Google. Both the client code and the v4 network protocol were + designed to preserve users' privacy, as well as keep battery and bandwidth + consumption to a minimum. This API allows you to take full advantage of + Google's Safe Browsing service on Android in the most resource-optimized way, + and without having to implement its network protocol. +

    + +

    + This document shows you how to use SafetyNet for checking a URL for threat + types of interest. +

    + +

    + Terms of Service +

    + +

    + By using the Safe Browsing API, you consent to be bound by the Terms of Service. + Please read and understand all applicable terms and policies before accessing + the Safe Browsing API. +

    + +

    + Requesting and Registering an Android API Key +

    + +

    + To create an API key, complete the following steps: +

    + +
      +
    1. Go to the Google Developers Console. +
    2. + +
    3. On the upper toolbar, choose Select a project > + your-project-name. +
    4. + +
    5. In the search box, enter Safe Browsing APIs; when the Safe + Browsing API name appears in the table, select it. +
    6. + +
    7. After the page redisplays, select Enable then select + Go to Credentials. +
    8. + +
    9. When the Add credentials to your project window appears, choose + your parameters then select What credentials do I need?. +
    10. + +
    11. Enter a name for your API key then select Create API + key. +
    12. + +
    13. +

      + Your new API key appears; copy and paste this key for future use. +

      + +

      + Note: Your API key allows you to perform a URL check + 10,000 times each day. The key, in this instance, should just be a + hexadecimal string, not part of a URL. +

      +
    14. + +
    15. Select Done to complete the process. +
    16. +
    + +

    + If you need more help, check out the Google Developers Console + Help Center. +

    + +

    + Adding the Android API key to your AndroidManifest.xml +

    + +

    + Once your key has been whitelisted, you need to add the key to the + AndroidManifest.xml file for your app: +

    + +
    +<application>
    +
    +    ...
    +
    +   <!-- SafetyNet API metadata -->
    +   <meta-data android:name="com.google.android.safetynet.API_KEY"
    +   android:value="your-API-key" />
    +
    +    ...
    +
    +</application>
    +
    +

    + Connect to Google Play Services +

    + +

    + The SafetyNet API is part of Google Play services. To connect to the API, you + need to create an instance of the Google Play services API client. For + details about using the client in your app, see Accessing + Google APIs. Once you have established a connection to Google Play + services, you can use the Google API client classes to connect to the + SafetyNet API. +

    + +

    + To connect to the API, in your activity's onCreate() + method, create an instance of Google API Client using + GoogleApiClient.Builder. Use the builder to add the SafetyNet API, + as shown in the following code example: +

    + +
    +protected synchronized void buildGoogleApiClient() {
    +    mGoogleApiClient = new GoogleApiClient.Builder(this)
    +            .addApi(SafetyNet.API)
    +            .addConnectionCallbacks(myMainActivity.this)
    +            .build();
    +}
    +
    +

    + Note: You can only call these methods after your app has + established a connection to Google Play services by receiving the + + onConnected() callback. For details about listening for a completed + client connection, see Accessing + Google APIs. +

    + +

    + Requesting a URL Check +

    + +

    + A URL check allows your app to determine if a URL has been marked as a threat + of interest. Some threat types may not be of interest to your particular + app, and the API allows you to choose which threat types are important for + your needs. You can specify multiple threat types of interest. +

    + +

    + Specifying threat types of interest +

    + +

    + The constants in the {@code SafeBrowsingThreat} class contain the + currently-supported threat types: +

    + +
    +package com.google.android.gms.safetynet;
    +
    +public class SafeBrowsingThreat {
    +
    +  /**
    +   * This threat type identifies URLs of pages that are flagged as containing potentially
    +   * harmful applications.
    +   */
    +  public static final int TYPE_POTENTIALLY_HARMFUL_APPLICATION = 4;
    +
    +  /**
    +   * This threat type identifies URLs of pages that are flagged as containing social
    +   * engineering threats.
    +   */
    +  public static final int TYPE_SOCIAL_ENGINEERING = 5;
    +}
    +
    +

    + When using the API, you must use constants that are not marked as deprecated. + You add threat type constants as arguments to the API. You may add as many + threat type constants as is required for your app. +

    + +

    + Send the URL check request +

    + +

    + The API is agnostic to the scheme used, so you can pass the URL with or + without a scheme. For example, either +

    + +
    +String url = "https://www.google.com";
    +
    +

    + or +

    + +
    +String url = "www.google.com";
    +
    +

    + is valid. +

    + +
    +SafetyNet.SafetyNetApi.lookupUri(mGoogleApiClient, url,
    +       SafeBrowsingThreat.TYPE_POTENTIALLY_HARMFUL_APPLICATION,
    +       SafeBrowsingThreat.TYPE_SOCIAL_ENGINEERING)
    +               .setResultCallback(
    +                       new ResultCallback<SafetyNetApi.SafeBrowsingResult>() {
    +
    +    @Override
    +    public void onResult(SafetyNetApi.SafeBrowsingResult result) {
    +        Status status = result.getStatus();
    +        if ((status != null) && status.isSuccess()) {
    +            // Indicates communication with the service was successful.
    +            // Identify any detected threats.
    +            if (result.getDetectedThreats().isEmpty()) {
    +
    +            }
    +        } else {
    +            // An error occurred. Let the user proceed without warning.
    +        }
    +    }
    +});
    +
    +

    + Read the URL check response +

    + +

    + The result is provided as a list of {@code SafeBrowsingThreat} objects by + calling the {@code SafetyNetApi.SafeBrowsingResult.getDetectedThreats()} + method of the returned {@code SafetyNetApi.SafeBrowsingResult} object. If the + list is empty, no threats were detected; otherwise, calling {@code + SafeBrowsingThreat.getThreatType()} on each element in the list enumerates + the threats that were detected. +

    + +

    + Suggested Warning Language +

    + +

    + Please see the Safe Browsing API Developer's Guide for + suggested warning language. +

    \ No newline at end of file diff --git a/docs/html/training/sign-in/index.jd b/docs/html/training/sign-in/index.jd index d7c8e1d397ab699ea553ce6f99b3fe044749ba2c..a5859441d64fd62d6809f3307a4b6cf01a3b7378 100644 --- a/docs/html/training/sign-in/index.jd +++ b/docs/html/training/sign-in/index.jd @@ -11,8 +11,8 @@ page.trainingcourse=true alt="Google maps sample image">

    - Google Sign-In for Android lets you authenticate a user with the same credentials they use on - Google. After a user signs in with Google, you can create more engaging experiences and drive + Google Sign-In for Android lets you authenticate a user with the same credentials they use on + Google. After a user signs in with Google, you can create more engaging experiences and drive usage of your app.

    @@ -34,8 +34,8 @@ page.trainingcourse=true

    Access the profile and social graph

    - After users have signed in with Google, your app can welcome them by name and display their - picture. If your app requests social scopes, it can connect users with friends, and access + After users have signed in with Google, your app can welcome them by name and display their + picture. If your app requests social scopes, it can connect users with friends, and access age range, language, and public profile information.
    Getting Profile Information. @@ -47,6 +47,6 @@ page.trainingcourse=true The Google Android APIs are part of the Google Play services platform. To use Google features, set up the Google Play services SDK in your app development project. For more information, see the Start Integrating + "https://developers.google.com/identity/sign-in/android/start-integrating">Start Integrating guide for Google Sign-In.

    \ No newline at end of file diff --git a/docs/html/training/testing/integration-testing/service-testing.jd b/docs/html/training/testing/integration-testing/service-testing.jd index 60b95ca08a6b234b76453025c16a757682f016d2..7ba00b04c72e5f71138e81b91bb35f51f4cbb579 100644 --- a/docs/html/training/testing/integration-testing/service-testing.jd +++ b/docs/html/training/testing/integration-testing/service-testing.jd @@ -81,7 +81,7 @@ JUnit 4 test classes and using JUnit 4 assertion methods, see Create an Instrumented Unit Test Class.

    -

    To create an integration test for your service, add the {@code @RunWith(AndroidJUnit4.class)} +

    To create an integration test for your service, add the {@code @RunWith(AndroidJUnit4.class)} annotation at the beginning of your test class definition. You also need to specify the {@code AndroidJUnitRunner} class that the Android Testing Support Library provides as your @@ -91,7 +91,7 @@ Run Instrumented Unit Tests.

    Next, create a ServiceTestRule -instance in your test by using the {@code @Rule} annotation.

    +instance in your test by using the {@code @Rule} annotation.

     @Rule
    diff --git a/docs/html/training/testing/ui-testing/espresso-testing.jd b/docs/html/training/testing/ui-testing/espresso-testing.jd
    index 7df67e7c23b843fc9e66354498a6891e9c275ca0..3d2bca7748eec289f8051860c803ebe1fa37df6e 100644
    --- a/docs/html/training/testing/ui-testing/espresso-testing.jd
    +++ b/docs/html/training/testing/ui-testing/espresso-testing.jd
    @@ -24,17 +24,11 @@ trainingnavtop=true
             
     
             
      -
    1. - Set Up Espresso -
    2. +
    3. Set Up Espresso
    4. -
    5. - Create an Espresso Test Class -
    6. +
    7. Create an Espresso Test Class
    8. -
    9. - Run Espresso Tests on a Device or Emulator -
    10. +
    11. Run Espresso Tests on a Device or Emulator

    @@ -59,31 +53,40 @@ trainingnavtop=true class="external-link">Android Testing Codelab

    -
    +

    Testing user interactions within a single app helps to ensure that users do not - encounter unexpected results or have a poor experience when interacting with your app. - You should get into the habit of creating user interface (UI) tests if you need to verify + encounter unexpected results or have a poor + experience when interacting with your app. + You should get into the habit of creating + user interface (UI) tests if you need to verify that the UI of your app is functioning correctly.

    The Espresso testing framework, provided by the Android Testing Support Library, - provides APIs for writing UI tests to simulate user interactions within a - single target app. Espresso tests can run on devices running Android 2.2 (API level 8) and - higher. A key benefit of using Espresso is that it provides automatic synchronization of test - actions with the UI of the app you are testing. Espresso detects when the main thread is idle, - so it is able to run your test commands at the appropriate time, improving the reliability of - your tests. This capability also relieves you from having to adding any timing workarounds, - such as a sleep period, in your test code. + provides APIs for writing UI tests to simulate + user interactions within a + single target app. Espresso tests can run on + devices running Android 2.3.3 (API level 10) and + higher. A key benefit of using Espresso is + that it provides automatic synchronization of test + actions with the UI of the app you are testing. + Espresso detects when the main thread is idle, + so it is able to run your test commands + at the appropriate time, improving the reliability of + your tests. This capability also relieves you + from having to add any timing workarounds, + such as {@link java.lang.Thread#sleep(long) Thread.sleep()} + in your test code.

    - The Espresso testing framework is an instrumentation-based API and works - with the + The Espresso testing framework is + an instrumentation-based API and works with the {@code AndroidJUnitRunner} test runner.

    @@ -92,105 +95,139 @@ trainingnavtop=true Set Up Espresso -

    Before building your UI test with Espresso, make sure to configure your test source code -location and project dependencies, as described in - -Getting Started with Testing.

    +

    + Before building your UI test with Espresso, + make sure to configure your test source code + location and project dependencies, as described in + Getting Started with Testing. +

    -

    In the {@code build.gradle} file of your Android app module, you must set a dependency - reference to the Espresso library:

    +

    + In the {@code build.gradle} file of your Android app + module, you must set a dependency + reference to the Espresso library: +

     dependencies {
    -    ...
    -    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    +    // Other dependencies ...
    +    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
     }
     
    -

    Turn off animations on your test device — leaving system animations turned on in the test -device might cause unexpected results or may lead your test to fail. Turn off animations from -Settings by opening Developing Options and turning all the following options off: +

    + Turn off animations on your test device — + leaving system animations turned on in the test + device might cause unexpected results or may + lead your test to fail. Turn off animations from + Settings by opening Developer options + and turning all the following options off:

    -
      -
    • - Window animation scale -
    • -
    • - Transition animation scale -
    • +

      +

        +
      • + Window animation scale +
      • + +
      • + Transition animation scale +
      • + +
      • + Animator duration scale +
      • +
      +

      -
    • - Animator duration scale -
    • -
    - - -

    If you want to set up your project to use Espresso features other than what the core API +

    + If you want to set up your project to use Espresso + features other than what the core API provides, see this resource.

    -

    - Create an Espresso Test Class -

    + -

    - To create an Espresso test, create a Java class that follows this programming model: -

    +

    + Create an Espresso Test Class +

    -
      -
    1. Find the UI component you want to test in an {@link android.app.Activity} (for example, a - sign-in button in the app) by calling the - - {@code onView()} method, or the - - {@code onData()} method for {@link android.widget.AdapterView} controls. -
    2. - -
    3. Simulate a specific user interaction to perform on that UI component, by calling the - {@code ViewInteraction.perform()} - or - {@code DataInteraction.perform()} - method and passing in the user action (for example, click on the sign-in button). To sequence - multiple actions on the same UI component, chain them using a comma-separated list in your - method argument. -
    4. - -
    5. Repeat the steps above as necessary, to simulate a user flow across multiple - activities in the target app. -
    6. - -
    7. Use the +

      + To create an Espresso test, create a Java + class that follows this programming model: +

      + +
        +
      1. + Find the UI component you want to test in + an {@link android.app.Activity} (for example, a + sign-in button in the app) by calling the + + {@code onView()} method, or the + + {@code onData()} method for {@link android.widget.AdapterView} controls. +
      2. + +
      3. + Simulate a specific user interaction to + perform on that UI component, by calling the + {@code ViewInteraction.perform()} + or + {@code DataInteraction.perform()} + method and passing in the user action + (for example, click on the sign-in button). To sequence + multiple actions on the same UI component, chain them using a comma-separated list in your + method argument. +
      4. + +
      5. + Repeat the steps above as necessary, to simulate a user flow across multiple + activities in the target app. +
      6. + +
      7. + Use the {@code ViewAssertions} - methods to check that the UI reflects the expected - state or behavior, after these user interactions are performed. -
      8. -
      + methods to check that the UI reflects the expected + state or behavior, after these user interactions are performed. +
    8. +
    -

    - These steps are covered in more detail in the sections below. -

    +

    + These steps are covered in more detail in the sections below. +

    -

    - The following code snippet shows how your test class might invoke this basic workflow: -

    +

    + The following code snippet shows how your test + class might invoke this basic workflow: +

     onView(withId(R.id.my_view))            // withId(R.id.my_view) is a ViewMatcher
             .perform(click())               // click() is a ViewAction
             .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion
     
    -

    Using Espresso with ActivityTestRule

    + + + +

    + Using Espresso with ActivityTestRule +

    +

    -The following section describes how to create a new Espresso test in the JUnit 4 style and use - -{@code ActivityTestRule} to reduce the amount of boilerplate code you need to write. By using - -{@code ActivityTestRule}, the testing framework launches the activity under test -before each test method annotated with {@code @Test} and before any method annotated with -{@code @Before}. The framework handles shutting down the activity after the test finishes -and all methods annotated with {@code @After} are run.

    + The following section describes how to create a + new Espresso test in the JUnit 4 style and use + {@code ActivityTestRule} + to reduce the amount of boilerplate code you need to write. By using + {@code ActivityTestRule}, + the testing framework launches the activity under test + before each test method annotated with + @Test and before any method annotated with + @Before. The framework handles + shutting down the activity after the test finishes + and all methods annotated with @After are run. +

     package com.example.android.testing.espresso.BasicSample;
    @@ -234,103 +271,57 @@ public class ChangeTextBehaviorTest {
     }
     
    -

    - Using Espresso with ActivityInstrumentationTestCase2 -

    -

    The following section describes how to migrate to Espresso if you have existing test classes -subclassed from {@link android.test.ActivityInstrumentationTestCase2} and you don't want to rewrite -them to use JUnit4.

    -

    Note: For new UI tests, we strongly recommend that you write your -test in the JUnit 4 style and use the - -{@code ActivityTestRule} class, instead of -{@link android.test.ActivityInstrumentationTestCase2}.

    -

    - If you are subclassing {@link android.test.ActivityInstrumentationTestCase2} - to create your Espresso test class, you must inject an - {@link android.app.Instrumentation} instance into your test class. This step is required in - order for your Espresso test to run with the - {@code AndroidJUnitRunner} - test runner. -

    + -

    - To do this, call the - {@link android.test.InstrumentationTestCase#injectInstrumentation(android.app.Instrumentation) injectInstrumentation()} - method and pass in the result of - - {@code InstrumentationRegistry.getInstrumentation()}, as shown in the following code - example: -

    - -
    -import android.support.test.InstrumentationRegistry;
    +

    + Accessing UI Components +

    -public class MyEspressoTest - extends ActivityInstrumentationTestCase2<MyActivity> { - - private MyActivity mActivity; - - public MyEspressoTest() { - super(MyActivity.class); - } - - @Before - public void setUp() throws Exception { - super.setUp(); - injectInstrumentation(InstrumentationRegistry.getInstrumentation()); - mActivity = getActivity(); - } - - ... -} -
    - -

    Note: Previously, {@link android.test.InstrumentationTestRunner} -would inject the {@link android.app.Instrumentation} instance, but this test runner is being -deprecated.

    - -

    - Accessing UI Components -

    - -

    - Before Espresso can interact with the app under test, you must first specify the UI component - or view. Espresso supports the use of -Hamcrest matchers - for specifying views and adapters in your app. -

    +

    + Before Espresso can interact with the app + under test, you must first specify the UI component + or view. Espresso supports the use of + Hamcrest matchers + for specifying views and adapters in your app. +

    -

    - To find the view, call the - {@code onView()} - method and pass in a view matcher that specifies the view that you are targeting. This is - described in more detail in Specifying a View Matcher. - The - {@code onView()} method returns a - - {@code ViewInteraction} - object that allows your test to interact with the view. - However, calling the - {@code onView()} method may not work if you want to locate a view in - an {@link android.widget.AdapterView} layout. In this case, follow the instructions in - Locating a view in an AdapterView instead. -

    +

    + To find the view, call the + {@code onView()} + method and pass in a view matcher that + specifies the view that you are targeting. This is + described in more detail in + Specifying a View Matcher. + The {@code onView()} + method returns a + {@code ViewInteraction} + object that allows your test to interact with the view. + However, calling the + + {@code onView()} + method may not work if you want to locate a view in + an {@link android.support.v7.widget.RecyclerView} layout. + In this case, follow the instructions in + Locating a view in an AdapterView + instead. +

    -

    - Note: The - {@code onView()} method does not check if the view you specified is - valid. Instead, Espresso searches only the current view hierarchy, using the matcher provided. - If no match is found, the method throws a - - {@code NoMatchingViewException}. -

    +

    + Note: + The {@code onView()} + method does not check if the view you specified is + valid. Instead, Espresso searches only the + current view hierarchy, using the matcher provided. + If no match is found, the method throws a + {@code NoMatchingViewException}. +

    -

    - The following code snippet shows how you might write a test that accesses an - {@link android.widget.EditText} field, enters a string of text, closes the virtual keyboard, - and then performs a button click. -

    +

    + The following code snippet shows how you might write a test that accesses an + {@link android.widget.EditText} field, + enters a string of text, closes the virtual keyboard, + and then performs a button click. +

     public void testChangeText_sameActivity() {
    @@ -344,231 +335,464 @@ public void testChangeText_sameActivity() {
     }
     
    -

    - Specifying a View Matcher -

    + +

    + Specifying a View Matcher +

    -

    - You can specify a view matcher by using these approaches: -

    +

    + You can specify a view matcher by using these approaches: +

    -
      -
    • Calling methods in the - - {@code ViewMatchers} class. For example, to find a view by looking for a text string it - displays, you can call a method like this: -
      +
        +
      • Calling methods in the + {@code ViewMatchers} + class. For example, to find a view by looking for a text string it + displays, you can call a method like this: +
         onView(withText("Sign-in"));
         
        -

        Similarly you can call - -{@code withId()} and providing the resource ID ({@code R.id}) of the view, as shown in the -following example:

        +

        + Similarly you can call + {@code withId()} + and providing the resource ID ({@code R.id}) of the view, + as shown in the + following example: +

         onView(withId(R.id.button_signin));
         

        - Android resource IDs are not guaranteed to be unique. If your test attempts to match to a + Android resource IDs are not guaranteed to be unique. + If your test attempts to match to a resource ID used by more than one view, Espresso throws an - - {@code AmbiguousViewMatcherException}. + {@code AmbiguousViewMatcherException}.

        -
      • -
      • Using the Hamcrest - {@code Matchers} class. You can use the - {@code allOf()} methods to combine multiple matchers, such as - {@code containsString()} and {@code instanceOf()}. This approach allows you to - filter the match results more narrowly, as shown in the following example: +
      • + +
      • + Using the Hamcrest + {@code Matchers} class. You can use the + {@code allOf()} methods to combine multiple matchers, such as + {@code containsString()} and {@code instanceOf()}. + This approach allows you to + filter the match results more narrowly, as shown in the following example: +
         onView(allOf(withId(R.id.button_signin), withText("Sign-in")));
         
        -

        You can use the {@code not} keyword to filter for views that don't correspond to the matcher, as -shown in the following example:

        + +

        + You can use the {@code not} keyword to filter + for views that don't correspond to the matcher, as + shown in the following example: +

        +
         onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));
         
        -

        To use these methods in your test, import the {@code org.hamcrest.Matchers} package. To -learn more about Hamcrest matching, see the -Hamcrest site. -

        -
      • -

      - To improve the performance of your Espresso tests, specify the minimum matching information - needed to find your target view. For example, if a view is uniquely identifiable by its - descriptive text, you do not need to specify that it is also assignable from the - {@link android.widget.TextView} instance. + To use these methods in your test, + import the {@code org.hamcrest.Matchers} package. To + learn more about Hamcrest matching, see the + Hamcrest site.

      +
    • +
    -

    - Locating a view in an AdapterView -

    +

    + To improve the performance of your Espresso tests, + specify the minimum matching information + needed to find your target view. For example, + if a view is uniquely identifiable by its + descriptive text, you do not need to specify + that it is also assignable from the + {@link android.widget.TextView} instance. +

    -

    - In an {@link android.widget.AdapterView} widget, the view is dynamically populated with child - views at runtime. If the target view you want to test is inside an - {@link android.widget.AdapterView} - (such as a {@link android.widget.ListView}, {@link android.widget.GridView}, or - {@link android.widget.Spinner}), the - - {@code onView()} method might not work because only a - subset of the views may be loaded in the current view hierarchy. -

    + -

    - Instead, call the {@code onData()} - method to obtain a - - {@code DataInteraction} - object to access the target view element. Espresso handles loading the target view element - into the current view hierarchy. Espresso also takes care of scrolling to the target element, - and putting the element into focus. -

    +

    + Locating a view in an AdapterView +

    + +

    + In an {@link android.widget.AdapterView} widget, + the view is dynamically populated with child + views at runtime. If the target view you want to test is inside an + {@link android.widget.AdapterView} + (such as a {@link android.widget.ListView}, + {@link android.widget.GridView}, or + {@link android.widget.Spinner}), the + {@code onView()} + method might not work because only a + subset of the views may be loaded in the current view hierarchy. +

    -

    - Note: The +

    + Instead, call the {@code onData()} - method does not check if if the item you specified corresponds with a view. Espresso searches - only the current view hierarchy. If no match is found, the method throws a - - {@code NoMatchingViewException}. -

    + method to obtain a + {@code DataInteraction} + object to access the target view element. + Espresso handles loading the target view element + into the current view hierarchy. Espresso + also takes care of scrolling to the target element, + and putting the element into focus. +

    -

    - The following code snippet shows how you can use the - {@code onData()} - method together - with Hamcrest matching to search for a specific row in a list that contains a given string. - In this example, the {@code LongListActivity} class contains a list of strings exposed - through a {@link android.widget.SimpleAdapter}. -

    +

    + Note: The + {@code onData()} + method does not check if the item you + specified corresponds with a view. Espresso searches + only the current view hierarchy. If no match is found, the method throws a + {@code NoMatchingViewException}. +

    + +

    + The following code snippet shows how you can use the + {@code onData()} + method together + with Hamcrest matching to search for a specific + row in a list that contains a given string. + In this example, the {@code LongListActivity} class + contains a list of strings exposed + through a {@link android.widget.SimpleAdapter}. +

     onData(allOf(is(instanceOf(Map.class)),
    -        hasEntry(equalTo(LongListActivity.ROW_TEXT), is(str))));
    +        hasEntry(equalTo(LongListActivity.ROW_TEXT), is("test input")));
     
    -

    - Performing Actions -

    + -

    - Call the {@code ViewInteraction.perform()} - or - {@code DataInteraction.perform()} - methods to - simulate user interactions on the UI component. You must pass in one or more - {@code ViewAction} - objects as arguments. Espresso fires each action in sequence according to - the given order, and executes them in the main thread. -

    +

    Performing Actions

    -

    - The - {@code ViewActions} - class provides a list of helper methods for specifying common actions. - You can use these methods as convenient shortcuts instead of creating and configuring - individual {@code ViewAction} - objects. You can specify such actions as: -

    +

    + Call the + {@code ViewInteraction.perform()} + or + {@code DataInteraction.perform()} + methods to + simulate user interactions on the UI component. You must pass in one or more + {@code ViewAction} + objects as arguments. Espresso fires each action in sequence according to + the given order, and executes them in the main thread. +

    - +

    + The + {@code ViewActions} + class provides a list of helper methods for specifying common actions. + You can use these methods as convenient shortcuts + instead of creating and configuring individual + {@code ViewAction} + objects. You can specify such actions as: +

    -

    - If the target view is inside a {@link android.widget.ScrollView}, perform the - {@code ViewActions.scrollTo()} - action first to display the view in the screen before other proceeding - with other actions. The - {@code ViewActions.scrollTo()} - action will have no effect if the view is already displayed. -

    + -

    - Verifying Results -

    +

    + If the target view is inside a {@link android.widget.ScrollView}, + perform the + {@code ViewActions.scrollTo()} + action first to display the view in the screen before other proceeding + with other actions. The + {@code ViewActions.scrollTo()} + action will have no effect if the view is already displayed. +

    -

    - Call the - {@code ViewInteraction.check()} - or - {@code DataInteraction.check()} - method to assert - that the view in the UI matches some expected state. You must pass in a - - {@code ViewAssertion} object as the argument. If the assertion fails, Espresso throws - an {@link junit.framework.AssertionFailedError}. -

    + -

    - The +

    + Test your activities in isolation with Espresso Intents +

    + +

    + Espresso Intents + enables validation and stubbing of intents sent out by an app. + With Espresso Intents, you can test an app, activity, or service in isolation + by intercepting outgoing intents, stubbing the result, and sending it back to + the component under test. +

    + +

    + To begin testing with Espresso Intents, you need + to add the following line to your app's build.gradle file: +

    + +
    +dependencies {
    +  // Other dependencies ...
    +  androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'
    +}
    +
    + +

    + To test an intent, you need to create an instance of the + IntentsTestRule + class, which is very similar to the + ActivityTestRule + class. + The + IntentsTestRule + class initializes Espresso Intents before each test, + terminates the host activity, + and releases Espresso Intents after each test. +

    + +

    + The test class shown in the following codes snippet provides a simple + test for an explicit intent. It tests the activities and intents created in the + Building Your First App + tutorial. +

    + +
    +@Large
    +@RunWith(AndroidJUnit4.class)
    +public class SimpleIntentTest {
    +
    +    private static final String MESSAGE = "This is a test";
    +    private static final String PACKAGE_NAME = "com.example.myfirstapp";
    +
    +    /* Instantiate an IntentsTestRule object. */
    +    @Rule
    +    public IntentsTestRule≶MainActivity> mIntentsRule =
    +      new IntentsTestRule≶>(MainActivity.class);
    +
    +    @Test
    +    public void verifyMessageSentToMessageActivity() {
    +
    +        // Types a message into a EditText element.
    +        onView(withId(R.id.edit_message))
    +                .perform(typeText(MESSAGE), closeSoftKeyboard());
    +
    +        // Clicks a button to send the message to another
    +        // activity through an explicit intent.
    +        onView(withId(R.id.send_message)).perform(click());
    +
    +        // Verifies that the DisplayMessageActivity received an intent
    +        // with the correct package name and message.
    +        intended(allOf(
    +                hasComponent(hasShortClassName(".DisplayMessageActivity")),
    +                toPackage(PACKAGE_NAME),
    +                hasExtra(MainActivity.EXTRA_MESSAGE, MESSAGE)));
    +
    +    }
    +}
    +
    + +

    + For more information about Espresso Intents, see the + Espresso Intents + documentation on the Android Testing Support Library site. + You can also download the + IntentsBasicSample and + IntentsAdvancedSample + code samples. +

    + + + +

    + Testing WebViews with Espresso Web +

    + +

    + Espresso Web allows you to test {@link android.webkit.WebView} components + contained within an activity. It uses the + WebDriver API to inspect and control the + behavior of a {@link android.webkit.WebView}. +

    + +

    + To begin testing with Espresso Web, you need + to add the following line to your app's build.gradle file: +

    + +
    +dependencies {
    +  // Other dependencies ...
    +  androidTestCompile 'com.android.support.test.espresso:espresso-web:2.2.2'
    +}
    +
    + +

    + When creating a test using Espresso Web, you need to enable + JavaScript on the {@link android.webkit.WebView} when you instantiate the + ActivityTestRule + object to test the activity. In the tests, you can select + HTML elements displayed in the + {@link android.webkit.WebView} and simulate user interactions, like + entering text into a text box and then clicking a button. After the actions + are completed, you can then verify that the results on the + Web page match the results that you expect. +

    + +

    + In the following code snippet, the class tests + a {@link android.webkit.WebView} component with the id value 'webview' + in the activity being tested. + The verifyValidInputYieldsSuccesfulSubmission() test selects an + <input> element on the + Web page, enters some text, and checks text that appears in + another element. +

    + +
    +@LargeTest
    +@RunWith(AndroidJUnit4.class)
    +public class WebViewActivityTest {
    +
    +    private static final String MACCHIATO = "Macchiato";
    +    private static final String DOPPIO = "Doppio";
    +
    +    @Rule
    +    public ActivityTestRule mActivityRule =
    +        new ActivityTestRule(WebViewActivity.class,
    +            false /* Initial touch mode */, false /*  launch activity */) {
    +
    +        @Override
    +        protected void afterActivityLaunched() {
    +            // Enable JavaScript.
    +            onWebView().forceJavascriptEnabled();
    +        }
    +    }
    +
    +    @Test
    +    public void typeTextInInput_clickButton_SubmitsForm() {
    +       // Lazily launch the Activity with a custom start Intent per test
    +       mActivityRule.launchActivity(withWebFormIntent());
    +
    +       // Selects the WebView in your layout.
    +       // If you have multiple WebViews you can also use a
    +       // matcher to select a given WebView, onWebView(withId(R.id.web_view)).
    +       onWebView()
    +           // Find the input element by ID
    +           .withElement(findElement(Locator.ID, "text_input"))
    +           // Clear previous input
    +           .perform(clearElement())
    +           // Enter text into the input element
    +           .perform(DriverAtoms.webKeys(MACCHIATO))
    +           // Find the submit button
    +           .withElement(findElement(Locator.ID, "submitBtn"))
    +           // Simulate a click via JavaScript
    +           .perform(webClick())
    +           // Find the response element by ID
    +           .withElement(findElement(Locator.ID, "response"))
    +           // Verify that the response page contains the entered text
    +           .check(webMatches(getText(), containsString(MACCHIATO)));
    +    }
    +}
    +
    + +

    + For more information about Espresso Web, see the + Espresso + Web documentation on the Android Testing Support Library site.. + You can also download this code snippet as part of the + Espresso Web code sample. +

    + + + +

    + Verifying Results +

    + +

    + Call the + {@code ViewInteraction.check()} + or + {@code DataInteraction.check()} + method to assert + that the view in the UI matches some expected state. You must pass in a + {@code ViewAssertion} + object as the argument. If the assertion fails, Espresso throws + an {@link junit.framework.AssertionFailedError}. +

    + +

    + The {@code ViewAssertions} - class provides a list of helper methods for specifying common - assertions. The assertions you can use include: -

    + class provides a list of helper methods for specifying common + assertions. The assertions you can use include: +

    -
      -
    • - {@code doesNotExist}: -Asserts that there is no view matching the specified criteria in the current view hierarchy. -
    • - -
    • - {@code matches}: - Asserts that the specified view exists in the current view hierarchy - and its state matches some given Hamcrest matcher. -
    • - -
    • - {@code selectedDescendentsMatch} - : Asserts that the specified children views for a - parent view exist, and their state matches some given Hamcrest matcher. -
    • -
    +
      +
    • + {@code doesNotExist}: + Asserts that there is no view matching the specified + criteria in the current view hierarchy. +
    • + +
    • + {@code matches}: + Asserts that the specified view exists in the current view hierarchy + and its state matches some given Hamcrest matcher. +
    • + +
    • + {@code selectedDescendentsMatch}: + Asserts that the specified children views for a + parent view exist, and their state matches some given Hamcrest matcher. +
    • +
    + +

    + The following code snippet shows how you might + check that the text displayed in the UI has + the same value as the text previously entered in the + {@link android.widget.EditText} field. +

    -

    - The following code snippet shows how you might check that the text displayed in the UI has - the same value as the text previously entered in the - {@link android.widget.EditText} field. -

     public void testChangeText_sameActivity() {
         // Type text and then press the button.
    @@ -580,14 +804,22 @@ public void testChangeText_sameActivity() {
     }
     
    -

    Run Espresso Tests on a Device or Emulator

    + + +

    + Run Espresso Tests on a Device or Emulator +

    +

    -You can run Espresso tests from Android Studio or -from the command-line. Make sure to specify - - {@code AndroidJUnitRunner} as the default instrumentation runner in your project. + You can run Espresso tests from + Android Studio or + from the command-line. Make sure to specify + {@code AndroidJUnitRunner} + as the default instrumentation runner in your project.

    +

    -To run your Espresso test, follow the steps for running instrumented tests -described in -Getting Started with Testing.

    + To run your Espresso test, follow the steps for running instrumented tests + described in + Getting Started with Testing. +

    diff --git a/docs/html/training/testing/ui-testing/uiautomator-testing.jd b/docs/html/training/testing/ui-testing/uiautomator-testing.jd index 05ddc348efdbe804dccc6ccf6043170f7d5aa1e8..53f497ad1c7d451f9c524a18d5ea376481436356 100644 --- a/docs/html/training/testing/ui-testing/uiautomator-testing.jd +++ b/docs/html/training/testing/ui-testing/uiautomator-testing.jd @@ -26,7 +26,7 @@ trainingnavtop=true

    You should also read

    @@ -172,7 +172,7 @@ about creating JUnit 4 test classes and using JUnit 4 assertions and annotations Create an Instrumented Unit Test Class.

    -

    Add the {@code @RunWith(AndroidJUnit4.class)} annotation at the beginning of your test class +

    Add the {@code @RunWith(AndroidJUnit4.class)} annotation at the beginning of your test class definition. You also need to specify the {@code AndroidJUnitRunner} class @@ -279,7 +279,7 @@ public class ChangeTextBehaviorTest { } -

    In the example, the {@code @SdkSuppress(minSdkVersion = 18)} statement helps to ensure that +

    In the example, the {@code @SdkSuppress(minSdkVersion = 18)} statement helps to ensure that tests will only run on devices with Android 4.3 (API level 18) or higher, as required by the UI Automator framework.

    diff --git a/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd b/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd index f65766d825a9ba9db7e744dc35c8896e41b91a85..dc94bdf05502ccdb116bb9a0e3fbc3ef65eb7cfd 100644 --- a/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd +++ b/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd @@ -53,8 +53,9 @@ you choose, to simulate any dependency relationships.

    In your Android Studio project, you must store the source files for instrumented tests at -module-name/src/androidTests/java/. This directory -already exists when you create a new project.

    +module-name/src/androidTest/java/. This directory +already exists when you create a new project and contains an example +instrumented test.

    Before you begin, you should download @@ -95,6 +96,19 @@ dependencies { } +

    To use JUnit 4 test classes, make sure to specify Create a Local Unit Test Class.

    -

    To create an instrumented JUnit 4 test class, add the {@code @RunWith(AndroidJUnit4.class)} +

    To create an instrumented JUnit 4 test class, add the {@code @RunWith(AndroidJUnit4.class)} annotation at the beginning of your test class definition. You also need to specify the {@code AndroidJUnitRunner} class @@ -200,8 +214,8 @@ To create a test suite for your unit tests, import the JUnit class="external-link">{@code RunWith} and {@code Suite} classes. In your test suite, add the -{@code @RunWith(Suite.class)} and the {@code @Suite.SuitClasses()} annotations. In -the {@code @Suite.SuiteClasses()} annotation, list the individual test classes or test +{@code @RunWith(Suite.class)} and the {@code @Suite.SuitClasses()} annotations. In +the {@code @Suite.SuiteClasses()} annotation, list the individual test classes or test suites as arguments.

    @@ -279,23 +293,21 @@ from the command line. Test results provide test logs and include the details of any app failures.

    - Before you can start using Firebase Test Lab, you need to: + Before you can start using Firebase Test Lab, you need to do the following +unless you already have a Google account and a Firebase project with the Blaze +billing plan enabled:

      -
    1. - Create a - Google Cloud Platform account to use with active billing. -
    2. - -
    3. - Create a Google - Cloud project for your app. -
    4. - -
    5. - Set up an active - billing account and associate it with the project you just created. +
    6. Create a Google account, + if you don't have one already.
    7. +
    8. In the Firebase + console, click Create New Project.
    9. +
    10. In the Firebase console, click Upgrade, and then click Select +Plan in the Blaze plan column. +

      Note: To learn about billing, +see Test +Lab billing.

    @@ -305,10 +317,10 @@ Configure a test matrix and run a test

    - Android Studio provides integrated tools that allow you to configure how you - want to deploy your tests to Firebase Test Lab. After you have created a Google - Cloud project with active billing, you can create a test configuration and - run your tests: +Android Studio provides integrated tools that allow you to configure how you +want to deploy your tests to Firebase Test Lab. After you have created a +Firebase project with Blaze plan billing, you can create a test configuration +and run your tests:

      @@ -316,7 +328,8 @@ Configure a test matrix and run a test the main menu. -
    1. Click Add New Configuration (+) and select +
    2. Click Add New Configuration and select Android Tests.
    3. @@ -327,7 +340,7 @@ Configure a test matrix and run a test
    4. From the Target drop-down menu under Deployment Target - Options, select Cloud Test Lab Device Matrix. + Options, select Firebase Test Lab Device Matrix.
    5. If you are not logged in, click Connect to Google Cloud @@ -335,9 +348,9 @@ Configure a test matrix and run a test
    6. Next to Cloud Project, click the wrench and nut button and select your Google Cloud - Platform project from the list. + "{@docRoot}images/tools/as-wrench.png" alt="" class="inline-icon"/> + button and select your Firebase + project from the list.
    @@ -346,7 +359,7 @@ Configure a test matrix and run a test
    1. Next to the Matrix Configuration drop-down list, click Open Dialog ellipses button. + alt="" class="inline-icon">.
    2. Click Add New Configuration (+). @@ -372,8 +385,7 @@ Configure a test matrix and run a test
    3. Run your tests by clicking Run . + "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon"/>.
    @@ -391,7 +403,7 @@ Configure a test matrix and run a test When Firebase Test Lab completes running your tests, the Run window will open to show the results, as shown in figure 2. You may need to click Show Passed - to see all your executed tests. + "" class="inline-icon"/> to see all your executed tests.

    @@ -403,15 +415,7 @@ Configure a test matrix and run a test

    You can also analyze your tests on the web by following the link displayed at - the beginning of the test execution log in the Run window, as shown - in figure 3. -

    - - - -

    - Figure 3. Click the link to view detailed test results on - the web. + the beginning of the test execution log in the Run window.

    diff --git a/docs/html/training/testing/unit-testing/local-unit-tests.jd b/docs/html/training/testing/unit-testing/local-unit-tests.jd index 25b62fa2e39329a40362a7364e5dd2c21698e211..d19de4f6544ad2174d3464f444f038665a964fd5 100644 --- a/docs/html/training/testing/unit-testing/local-unit-tests.jd +++ b/docs/html/training/testing/unit-testing/local-unit-tests.jd @@ -80,7 +80,7 @@ name with the {@code ‘test’} keyword, or use any classes in the {@code junit {@code junit.extensions} package.

    To create a basic JUnit 4 test class, create a Java class that contains one or more test methods. -A test method begins with the {@code @Test} annotation and contains the code to exercise +A test method begins with the {@code @Test} annotation and contains the code to exercise and verify a single functionality in the component that you want to test.

    The following example shows how you might implement a local unit test class. The test method @@ -112,12 +112,16 @@ Hamcrest matchers (such as the {@code is()} and {@code equalTo()} methods) t returned result against the expected result.

    Mock Android dependencies

    -

    -By default, the -Android Plug-in for Gradle executes your local unit tests against a modified -version of the {@code android.jar} library, which does not contain any actual code. Instead, method -calls to Android classes from your unit test throw an exception. -

    + +

    By default, the Android Plug-in for +Gradle executes your local unit tests against a modified version of the +{@code android.jar} library, which does not contain any actual code. Instead, +method calls to Android classes from your unit test throw an exception. This is +to make sure you test only your code and do not depend on any +particular behavior of the Android platform (that you have not explicitly +mocked).

    +

    You can use a mocking framework to stub out external dependencies in your code, to easily test that your component interacts with a dependency in an expected way. By substituting Android dependencies @@ -136,11 +140,11 @@ Include the Mockito library dependency in your {@code build.gradle} file, as des Set Up Your Testing Environment.

  • At the beginning of your unit test class definition, add the -{@code @RunWith(MockitoJUnitRunner.class)} annotation. This annotation tells the Mockito test +{@code @RunWith(MockitoJUnitRunner.class)} annotation. This annotation tells the Mockito test runner to validate that your usage of the framework is correct and simplifies the initialization of your mock objects.
  • -
  • To create a mock object for an Android dependency, add the {@code @Mock} annotation before +
  • To create a mock object for an Android dependency, add the {@code @Mock} annotation before the field declaration.
  • To stub the behavior of the dependency, you can specify a condition and return value when the condition is met by using the {@code when()} and {@code thenReturn()} methods. @@ -195,6 +199,26 @@ class="external-link">Mockito API reference and the class="external-link">sample code.

    +

    If the exceptions thrown by Android APIs in the +android.jar are problematic for your tests, you can change the behavior so that methods +instead return either null or zero by adding the following configuration in your project's +top-level build.gradle file:

    + +
    +android {
    +  ...
    +  testOptions {
    +    unitTests.returnDefaultValues = true
    +  }
    +}
    +
    + +

    Caution: +Setting the returnDefaultValues property to true +should be done with care. The null/zero return values can introduce +regressions in your tests, which are hard to debug and might allow failing tests +to pass. Only use it as a last resort.

    +

    Run Local Unit Tests

    diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index e2aa5f4dabe7a34d4a762a33453c7febb0072ce1..d2bf881859d5de3471d5feeb119d5f244f470f4e 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -649,25 +649,7 @@
  • -
  • Managing Your App's Memory
  • +
  • + Overview of Android Memory Management +
  • Note: For Android versions earlier than 4.4.2 (API level 19) -but greater than or equal to Android 4.0 (API level 14), use the animateLayoutChanges -attribute to animate layouts. To learn more, see -Property Animation and -Animating Layout Changes.

    - +but greater than or equal to Android 4.0 (API level 14), use the Android Support +Library's android.support.transition package.

    Lessons

    diff --git a/docs/html/training/tv/playback/card.jd b/docs/html/training/tv/playback/card.jd index a3a987252a8ae2861d5fc8c465ea3073e690e3cc..239118543c20d09102afd6d646042f540d18fd82 100644 --- a/docs/html/training/tv/playback/card.jd +++ b/docs/html/training/tv/playback/card.jd @@ -43,7 +43,7 @@ Leanback sample app image card view when selected.

    on demand. In the browse fragment where your app presents its content to the user, you create a {@link android.support.v17.leanback.widget.Presenter} for the content cards and pass it to the adapter that adds the content to the screen. In the following code, the CardPresenter is created -in the {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android.support.v4.content.Loader, java.lang.Object) onLoadFinished()} +in the {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} callback of the {@link android.support.v4.app.LoaderManager}.

    diff --git a/docs/html/training/tv/playback/index.jd b/docs/html/training/tv/playback/index.jd
    index d5e4e6712b053ade7fc0cd15df898194f344f352..34c6287173caa89fdea7c558fe0141e5b4043d04 100644
    --- a/docs/html/training/tv/playback/index.jd
    +++ b/docs/html/training/tv/playback/index.jd
    @@ -69,6 +69,10 @@ startpage=true
         
    Learn how to use the Leanback support library to guide a user through a series of decisions.
    +
    Introducing First-time Users to Your App
    +
    Learn how to use the Leanback support library to show first-time users + how to get the most out of your app.
    +
    Enabling Background Playback
    Learn how to continue playback when the user clicks on Home.
    diff --git a/docs/html/training/tv/playback/onboarding.jd b/docs/html/training/tv/playback/onboarding.jd new file mode 100644 index 0000000000000000000000000000000000000000..bb41bece1d285296ac1e4fb0c60b184767255fe6 --- /dev/null +++ b/docs/html/training/tv/playback/onboarding.jd @@ -0,0 +1,377 @@ +page.title=Introducing First-time Users to Your App +page.tags=tv,onboarding,OnboardingFragment +page.keywords=tv,onboarding,OnboardingFragment +helpoutsWidget=true + +trainingnavtop=true + +@jd:body + + + +

    +To show a first-time user how to get the most from your app, present +onboarding information at app startup. Here are some examples of onboarding +information: +

    + +
      +
    • Present detailed information on which channels are available when a user +first accesses a channel app.
    • +
    • Call attention to noteworthy features in your app.
    • +
    • Illustrate any required or recommended steps that users should take when +using the app for the first time.
    • +
    + +

    The v17 Leanback +support library provides the +{@link android.support.v17.leanback.app.OnboardingFragment} class for +presenting first-time user information. This lesson describes how to use the +{@link android.support.v17.leanback.app.OnboardingFragment} class to present +introductory information that is shown when the app launches for the first +time. {@link android.support.v17.leanback.app.OnboardingFragment} uses TV UI +best practices to present the information in a way that matches TV UI styles, +and is easy to navigate on TV devices.

    + + +

    Figure 1. An example +OnboardingFragment.

    + +

    Your {@link android.support.v17.leanback.app.OnboardingFragment} should +not contain UI elements that require user input, such as buttons and fields. +Similarly, it should not be used as a UI element for a task the user will do +regularly. If you need to present a multi-page UI that requires +user input, consider using a +{@link android.support.v17.leanback.app.GuidedStepFragment}.

    + +

    Add an OnboardingFragment

    + +

    To add an {@link android.support.v17.leanback.app.OnboardingFragment} +to your app, implement a class that extends +the {@link android.support.v17.leanback.app.OnboardingFragment} class. Add +this fragment to an activity, either via the activity's layout XML, or +programmatically. Make sure the activity or +fragment is using a theme derived from +{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding}, +as described in Customize Themes.

    + +

    In the {@link android.app.Activity#onCreate onCreate()} method of your +app's main activity, call +{@link android.app.Activity#startActivity startActivity()} +with an {@link android.content.Intent} that points to your +{@link android.support.v17.leanback.app.OnboardingFragment OnboardingFragment's} +parent activity. This ensures that your +{@link android.support.v17.leanback.app.OnboardingFragment} appears as +soon as your app starts.

    + +

    To ensure that the +{@link android.support.v17.leanback.app.OnboardingFragment} only appears the +first time that the user starts your app, use a +{@link android.content.SharedPreferences} object +to track whether the user has already viewed the +{@link android.support.v17.leanback.app.OnboardingFragment}. Define a boolean +value that changes to true when the user finishes viewing the +{@link android.support.v17.leanback.app.OnboardingFragment}. Check +this value in your main activity’s +{@link android.app.Activity#onCreate onCreate()}, and only start the +{@link android.support.v17.leanback.app.OnboardingFragment} parent activity if +the value is false. The following example shows an override of +{@link android.app.Activity#onCreate onCreate()} that checks for a +{@link android.content.SharedPreferences} value and, if not set to true, calls +{@link android.app.Activity#startActivity startActivity()} to +show the {@link android.support.v17.leanback.app.OnboardingFragment}:

    + +
    +@Override
    +protected void onCreate(Bundle savedInstanceState) {
    +    super.onCreate(savedInstanceState);
    +    setContentView(R.layout.activity_main);
    +    SharedPreferences sharedPreferences =
    +            PreferenceManager.getDefaultSharedPreferences(this);
    +    // Check if we need to display our OnboardingFragment
    +    if (!sharedPreferences.getBoolean(
    +            MyOnboardingFragment.COMPLETED_ONBOARDING_PREF_NAME, false)) {
    +        // The user hasn't seen the OnboardingFragment yet, so show it
    +        startActivity(new Intent(this, OnboardingActivity.class));
    +    }
    +}
    +
    + +

    After the user views the +{@link android.support.v17.leanback.app.OnboardingFragment}, mark it as viewed +using the {@link android.content.SharedPreferences} object. To do this, in your +{@link android.support.v17.leanback.app.OnboardingFragment}, override +{@link android.support.v17.leanback.app.OnboardingFragment#onFinishFragment +onFinishFragment()} and set your {@link android.content.SharedPreferences} value +to true, as shown in the following example: + +

    +@Override
    +protected void onFinishFragment() {
    +    super.onFinishFragment();
    +    // User has seen OnboardingFragment, so mark our SharedPreferences
    +    // flag as completed so that we don't show our OnboardingFragment
    +    // the next time the user launches the app.
    +    SharedPreferences.Editor sharedPreferencesEditor =
    +            PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
    +    sharedPreferencesEditor.putBoolean(
    +            COMPLETED_ONBOARDING_PREF_NAME, true);
    +    sharedPreferencesEditor.apply();
    +}
    +
    + +

    Add OnboardingFragment Pages

    + +

    After you add your +{@link android.support.v17.leanback.app.OnboardingFragment}, you need to define +the onboarding pages. An +{@link android.support.v17.leanback.app.OnboardingFragment} displays content +in a series of ordered pages. Each page can have a title, description, and +several sub-views that can contain images or animations.

    + +

    Figure 2. OnboardingFragment +page elements. +

    + +

    Figure 2 shows an example page with callouts marking customizable page +elements that your {@link android.support.v17.leanback.app.OnboardingFragment} +can provide. The page elements are:

    + +
      +
    1. The page title.
    2. +
    3. The page description.
    4. +
    5. The page content view, in this case a simple green checkmark in a grey box. +This view is optional. Use this view to illustrate page details such as a +screenshot that highlights the app feature that the page describes.
    6. +
    7. The page background view, in this case a simple blue gradient. This view +always renders behind other views on the page. This view is optional.
    8. +
    9. The page foreground view, in this case a logo. This view always renders +in front of all other views on the page. This view is optional.
    10. +
    + +

    Initialize page information when your +{@link android.support.v17.leanback.app.OnboardingFragment} is first created +or attached to the parent activity, as the system requests page +information when it creates the fragment's view. You can initialize page +information in your class constructor or in an override of +{@link android.app.Fragment#onAttach onAttach()}.

    + +

    Override each of the following methods that provide page information +to the system:

    + +
      +
    • {@link android.support.v17.leanback.app.OnboardingFragment#getPageCount +getPageCount()} returns the number of pages in your +{@link android.support.v17.leanback.app.OnboardingFragment}.
    • +
    • {@link android.support.v17.leanback.app.OnboardingFragment#getPageTitle +getPageTitle()} returns the title for the requested page number.
    • +
    • {@link android.support.v17.leanback.app.OnboardingFragment#getPageDescription +getPagedescription()} returns the description for the requested page +number.
    • +
    + +

    Override each of the following methods to provide optional sub-views used +to display images or animations:

    + +
      +
    • {@link android.support.v17.leanback.app.OnboardingFragment#onCreateBackgroundView +onCreateBackgroundView()} returns a {@link android.view.View} that you +create to act as the background view, or null if no background view is needed. +
    • {@link android.support.v17.leanback.app.OnboardingFragment#onCreateContentView +onCreateContentView()} returns a {@link android.view.View} that you +create to act as the content view, or null if no content view is needed. +
    • {@link android.support.v17.leanback.app.OnboardingFragment#onCreateForegroundView +onCreateForegroundView()} returns a {@link android.view.View} that you +create to act as the foreground view, or null if no foreground view is needed. +
    + +

    The system adds the {@link android.view.View} that you create to the page +layout. The following example overrides +{@link android.support.v17.leanback.app.OnboardingFragment#onCreateContentView +onCreateContentView()} and returns an {@link android.widget.ImageView}:

    + +
    +private ImageView mContentView;
    +...
    +@Override
    +protected View onCreateContentView(LayoutInflater inflater, ViewGroup container) {
    +    mContentView = new ImageView(getContext());
    +    mContentView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
    +    mContentView.setImageResource(R.drawable.onboarding_content_view);
    +    mContentView.setPadding(0, 32, 0, 32);
    +    return mContentView;
    +}
    +
    + +

    Add an Initial Logo Screen

    + +

    Your {@link android.support.v17.leanback.app.OnboardingFragment} can start +with an optional logo screen that introduces your app. If you want to display +a {@link android.graphics.drawable.Drawable} as your logo screen, in your +{@link android.support.v17.leanback.app.OnboardingFragment OnboardingFragment's} +{@link android.app.Fragment#onCreate onCreate()} method, call +{@link android.support.v17.leanback.app.OnboardingFragment#setLogoResourceId +setLogoResourceId()} with the ID of your +{@link android.graphics.drawable.Drawable}. The +system will fade in and briefly display this +{@link android.graphics.drawable.Drawable}, and then fade out the +{@link android.graphics.drawable.Drawable} +before displaying the first page of your +{@link android.support.v17.leanback.app.OnboardingFragment}.

    + +

    If you want to provide a custom animation for your logo screen, instead of +calling +{@link android.support.v17.leanback.app.OnboardingFragment#setLogoResourceId +setLogoResourceId()}, override +{@link android.support.v17.leanback.app.OnboardingFragment#onCreateLogoAnimation +onCreateLogoAnimation()} and return an {@link android.animation.Animator} +object that renders your custom animation, as shown in the following example: +

    + +
    +@Override
    +public Animator onCreateLogoAnimation() {
    +    return AnimatorInflater.loadAnimator(mContext,
    +            R.animator.onboarding_logo_screen_animation);
    +}
    +
    + +

    Customize Page Animations

    + +

    The system uses default animations when displaying the first page of your +{@link android.support.v17.leanback.app.OnboardingFragment} and when the user +navigates to a different page. You can customize these animations by +overriding methods in your +{@link android.support.v17.leanback.app.OnboardingFragment}.

    + +

    To customize the animation that appears on your first page, +override +{@link android.support.v17.leanback.app.OnboardingFragment#onCreateEnterAnimation +onCreateEnterAnimation()} and return an {@link android.animation.Animator}. +The following example creates an +{@link android.animation.Animator} that scales the content view +horizontally:

    + +
    +@Override
    +protected Animator onCreateEnterAnimation() {
    +    Animator startAnimator = ObjectAnimator.ofFloat(mContentView,
    +            View.SCALE_X, 0.2f, 1.0f).setDuration(ANIMATION_DURATION);
    +    return startAnimator;
    +}
    +
    + +

    To customize the animation used when the user navigates to a different page, +override +{@link android.support.v17.leanback.app.OnboardingFragment#onPageChanged +onPageChanged()}. In your +{@link android.support.v17.leanback.app.OnboardingFragment#onPageChanged +onPageChanged()} method, create {@link android.animation.Animator Animators} +that remove the previous page and display the next page, add these to an +{@link android.animation.AnimatorSet}, and play the set. The following +example uses a fade-out animation to remove the previous page, updates the +content view image, and uses a fade-in animation to display the next page:

    + +
    +@Override
    +protected void onPageChanged(final int newPage, int previousPage) {
    +    // Create a fade-out animation used to fade out previousPage and, once
    +    // done, swaps the contentView image with the next page's image.
    +    Animator fadeOut = ObjectAnimator.ofFloat(mContentView,
    +            View.ALPHA, 1.0f, 0.0f).setDuration(ANIMATION_DURATION);
    +    fadeOut.addListener(new AnimatorListenerAdapter() {
    +        @Override
    +        public void onAnimationEnd(Animator animation) {
    +            mContentView.setImageResource(pageImages[newPage]);
    +        }
    +    });
    +    // Create a fade-in animation used to fade in nextPage
    +    Animator fadeIn = ObjectAnimator.ofFloat(mContentView,
    +            View.ALPHA, 0.0f, 1.0f).setDuration(ANIMATION_DURATION);
    +    // Create AnimatorSet with our fade-out and fade-in animators, and start it
    +    AnimatorSet set = new AnimatorSet();
    +    set.playSequentially(fadeOut, fadeIn);
    +    set.start();
    +}
    +
    + +

    For more details about how to create +{@link android.animation.Animator Animators} and +{@link android.animation.AnimatorSet AnimatorSets}, see + +Property Animations.

    + +

    Customize Themes

    + +

    Any {@link android.support.v17.leanback.app.OnboardingFragment} +implementation must use either the +{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding} theme +or a theme that inherits from +{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding}. Set the +theme for your {@link android.support.v17.leanback.app.OnboardingFragment} by +doing one of the following:

    + +
      +
    • Set the {@link android.support.v17.leanback.app.OnboardingFragment +OnboardingFragment's} parent activity to use the desired theme. The following +example shows how to set an activity to use +{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding} in the +app manifest: +
      +<activity
      +   android:name=".OnboardingActivity"
      +   android:enabled="true"
      +   android:exported="true"
      +   android:theme="@style/Theme.Leanback.Onboarding">
      +</activity>
      +
      +
    • +
    • +Set the theme in the parent activity by using the +{@link android.support.v17.leanback.R.styleable#LeanbackOnboardingTheme_onboardingTheme} +attribute in a custom activity theme. Point this attribute to another +custom theme that only the +{@link android.support.v17.leanback.app.OnboardingFragment} +objects in your activity use. Use this approach if your activity already uses +a custom theme and you don't want to apply +{@link android.support.v17.leanback.app.OnboardingFragment} styles to other +views in the activity. +
    • +
    • Override +{@link android.support.v17.leanback.app.OnboardingFragment#onProvideTheme +onProvideTheme()} and return the desired theme. Use this approach if +multiple activities use your +{@link android.support.v17.leanback.app.OnboardingFragment} +or if the parent activity can't use the desired theme. +The following example overrides +{@link android.support.v17.leanback.app.OnboardingFragment#onProvideTheme +onProvideTheme()} and returns +{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding}: +
      +@Override
      +public int onProvideTheme() {
      +   return R.style.Theme_Leanback_Onboarding;
      +}
      +
      +
    • +
    \ No newline at end of file diff --git a/docs/html/preview/features/picture-in-picture.jd b/docs/html/training/tv/playback/picture-in-picture.jd similarity index 84% rename from docs/html/preview/features/picture-in-picture.jd rename to docs/html/training/tv/playback/picture-in-picture.jd index c089feb17670f70372840d05c7b11f9971dd907d..e48ae48d3f4e6754c3da23210cbd939f480f4599 100644 --- a/docs/html/preview/features/picture-in-picture.jd +++ b/docs/html/training/tv/playback/picture-in-picture.jd @@ -1,11 +1,14 @@ -page.title=Picture-in-picture +page.title=Adding Picture-in-picture page.keywords=preview,sdk,PIP,Picture-in-picture page.tags=androidn +helpoutsWidget=true + +trainingnavtop=true @jd:body -
    -
    +
    +

    In this document

      @@ -31,12 +34,12 @@ Support
    -

    In Android N, Android TV users can now watch a video -in a pinned window in a corner of the screen when navigating within -apps. Picture-in-picture (PIP) mode lets apps run a video +

    In Android 7.0, Android TV users can now watch a video +in a pinned window in a corner of the screen when navigating within or +between apps. Picture-in-picture (PIP) mode lets apps run a video activity in the pinned window while another activity continues in the -background. The PIP window lets users multitask while using your app, which -helps users be more productive.

    +background. The PIP window lets users multitask while using Android TV, +which helps users be more productive.

    Your app can decide when to trigger PIP mode. Here are some examples of when to enter PIP mode:

    @@ -57,14 +60,14 @@ the four corners of the screen, chosen by the system. The user can bring up a PIP menu that lets them toggle the PIP window to full-screen, or close the PIP window, by holding down the Home button on the remote. If another video starts playing on the main screen, the PIP window is automatically -closed. Users can also close the PIP window through Recents.

    +closed.

    - +

    Figure 1. A Picture-in-picture video visible in a corner of the screen while the user browses content on the main screen.

    -

    PIP leverages the multi-window APIs available in Android N to +

    PIP leverages the multi-window APIs available in Android 7.0 to provide the pinned video overlay window. To add PIP to your app, you need to register your activities that support PIP, switch your activity to PIP mode as needed, and make sure UI elements are hidden and video playback continues when @@ -99,7 +102,8 @@ in the PIP window.

    Switching Your Activity to Picture-in-picture

    When you need to switch your activity into PIP mode, call -Activity.enterPictureInPictureMode(). The following example +{@link android.app.Activity#enterPictureInPictureMode +enterPictureInPictureMode()}. The following example switches to PIP mode when the user selects a dedicated PIP button on a media control bar:

    @@ -116,12 +120,13 @@ public void onActionClicked(Action action) {

    Adding a PIP button to your media control bar lets your user easily switch to PIP mode while controlling video playback.

    - +

    Figure 1. A Picture-in-picture button on a media control bar.

    -

    Android N includes a new -PlaybackControlsRow.PictureInPictureAction class which defines +

    Android 7.0 includes a +{@link android.support.v17.leanback.widget.PlaybackControlsRow.PictureInPictureAction +PlaybackControlsRow.PictureInPictureAction} class which defines control bar PIP actions and uses the PIP icon.

    Handling UI During Picture-in-picture

    @@ -129,8 +134,10 @@ control bar PIP actions and uses the PIP icon.

    When your activity enters PIP mode, your activity should only show video playback. Remove UI elements before your activity enters PIP, and restore these elements when your activity becomes full-screen again. -Override Activity.onPictureInPictureModeChanged() or -Fragment.onPictureInPictureModeChanged() and enable or +Override {@link android.app.Activity#onPictureInPictureModeChanged +Activity.onPictureInPictureModeChanged()} or +{@link android.app.Fragment#onPictureInPictureModeChanged +Fragment.onPictureInPictureModeChanged()} and enable or disable your UI elements as needed, for example:

    @@ -154,7 +161,7 @@ paused state, and calls your activity's {@link android.app.Activity#onPause
     onPause()} method. Video playback should not be paused and should continue
     playing if the activity is paused due to PIP mode.

    -

    In Android N, you should pause and resume video playback when the system +

    In Android 7.0, you should pause and resume video playback when the system calls your activity's {@link android.app.Activity#onStop onStop()} and {@link android.app.Activity#onStart onStart()}. By doing this, you can avoid having to check if your app is in PIP mode in @@ -204,7 +211,7 @@ switched into or out of PIP mode as needed, set the activity's

    In your activity, override {@link android.app.Activity#onNewIntent -Activity.onNewIntent()} and handle the new video, stopping any existing video +onNewIntent()} and handle the new video, stopping any existing video playback if needed.

    Best Practices

    @@ -220,7 +227,11 @@ in any area that can be obscured by the PIP window.

    When an activity is in PIP mode, by default it doesn't get input focus. To receive input events while in PIP mode, use -MediaSession.setMediaButtonReceiver().

    +{@link android.media.session.MediaSession#setCallback +MediaSession.setCallback()}. For more information on using +{@link android.media.session.MediaSession#setCallback setCallback()} see +Displaying +a Now Playing Card.

    When your app is in PIP mode, video playback in the PIP window can cause audio interference with another app, such as a music player app or voice search @@ -228,4 +239,4 @@ app. To avoid this, request audio focus when you start playing the video, and handle audio focus change notifications, as described in Managing Audio Focus. If you receive notification of audio focus loss when in PIP mode, -pause or stop video playback.

    \ No newline at end of file +pause or stop video playback.

    diff --git a/docs/html/training/tv/start/hardware.jd b/docs/html/training/tv/start/hardware.jd index 97cf7ff6626d09652d0803c9017078e87a50c87f..063987159b7978e5a1156f41dbabbb5f95311aba 100644 --- a/docs/html/training/tv/start/hardware.jd +++ b/docs/html/training/tv/start/hardware.jd @@ -227,13 +227,19 @@ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} - {@code android.hardware.location} and
    - {@code android.hardware.location.network} + +

    {@code android.hardware.location}

    +

    {@code android.hardware.location.network} (Target API level 20 or lower + only.)

    + {@link android.Manifest.permission#ACCESS_FINE_LOCATION} - {@code android.hardware.location} and
    - {@code android.hardware.location.gps} + +

    {@code android.hardware.location}

    +

    {@code android.hardware.location.gps} (Target API level 20 or lower + only.)

    + @@ -246,6 +252,13 @@ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) required ({@code android:required="false"}).

    +

    + Note: If your app targets Android 5.0 (API level 21) or + higher and uses the ACCESS_COARSE_LOCATION or + ACCESS_FINE_LOCATION permission, users can still install your + app on a TV device, even if the TV device doesn't have a network card or a GPS + receiver. +

    Checking for hardware features

    diff --git a/docs/html/training/tv/tif/channel.jd b/docs/html/training/tv/tif/channel.jd index 999f1ca9c5c5e778490fbc849283ee6d956cd585..59e357a316ac05320f32ab133636ce78b67bf0d9 100644 --- a/docs/html/training/tv/tif/channel.jd +++ b/docs/html/training/tv/tif/channel.jd @@ -13,6 +13,7 @@ trainingnavtop=true
  • Get Permission
  • Register Channels in the Database
  • Update Channel Data
  • +
  • Add App Link Information
  • Try It Out

      @@ -22,10 +23,13 @@ trainingnavtop=true
    -

    Your TV input must provide Electronic Program Guide (EPG) data for at least one channel in its -setup activity. You should also periodically update that data, with consideration for the size of -the update and the processing thread that handles it. This lesson discusses creating and updating -channel and program data on the system database with these considerations in mind.

    +

    Your TV input must provide Electronic Program Guide (EPG) data for at least +one channel in its setup activity. You should also periodically update that +data, with consideration for the size of the update and the processing thread +that handles it. Additionally, you can provide app links for channels +that guide the user to related content and activities. +This lesson discusses creating and updating channel and program data on the +system database with these considerations in mind.

     

    @@ -70,6 +74,10 @@ addition to those above to better identify traditional broadcast channels:

    ID
  • +

    If you want to provide app link details for your channels, you need to +update some additional fields. For more information on app link fields, see +Add App Link Information. +

    For internet streaming based TV inputs, assign your own values to the above accordingly so that each channel can be identified uniquely.

    @@ -236,4 +244,112 @@ Android TV live TV sample app for an example.

    Other techniques to separate the data update tasks from the UI thread include using the {@link android.os.HandlerThread} class, or you may implement your own using {@link android.os.Looper} and {@link android.os.Handler} classes. See -Processes and Threads for more information.

    \ No newline at end of file +Processes and Threads for more information.

    + + + +

    Channels can use app links to let users easily launch a related +activity while they are watching channel content. Channel apps use +app links to extend user engagement by launching activities that show +related information or additional content. For example, you can use app links +to do the following:

    + +
      +
    • Guide the user to discover and purchase related content.
    • +
    • Provide additional information about currently playing content.
    • +
    • While viewing episodic content, start viewing the next episode in a +series.
    • +
    • Let the user interact with content—for example, rate or review +content—without interrupting content playback.
    • +
    + +

    App links are displayed when the user presses Select to show the +TV menu while watching channel content.

    + + +

    Figure 1. An example app link +displayed on the Channels row while channel content is shown.

    + +

    When the user selects the app link, the system starts an activity using +an intent URI specified by the channel app. Channel content continues to play +while the app link activity is active. The user can return to the channel +content by pressing Back.

    + +

    Provide App Link Channel Data

    + +

    Android TV automatically creates an app link for each channel, +using information from the channel data. To provide app link information, +specify the following details in your +{@link android.media.tv.TvContract.Channels} fields: +

    + +
      +
    • {@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_COLOR} - The +accent color of the app link for this channel. For an example accent color, +see figure 2, callout 3. +
    • +
    • {@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_ICON_URI} - +The URI for the app badge icon of the app link for this channel. For an +example app badge icon, see figure 2, callout 2. +
    • +
    • {@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_INTENT_URI} - +The intent URI of the app link for this channel. You can create the URI +using {@link android.content.Intent#toUri(int) toUri(int)} with +{@link android.content.Intent#URI_INTENT_SCHEME URI_INTENT_SCHEME} and +convert the URI back to the original intent with +{@link android.content.Intent#parseUri parseUri()}. +
    • +
    • {@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_POSTER_ART_URI} +- The URI for the poster art used as the background of the app link +for this channel. For an example poster image, see figure 2, callout 1.
    • +
    • {@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_TEXT} - +The descriptive link text of the app link for this channel. For an example +app link description, see the text in figure 2, callout 3.
    • +
    + + +

    Figure 2. App link details.

    + +

    If the channel data doesn't specify app link information, the system +creates a default app link. The system chooses default details as follows:

    + +
      +
    • For the intent URI +({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_INTENT_URI}), +the system uses the {@link android.content.Intent#ACTION_MAIN ACTION_MAIN} +activity for the {@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER +CATEGORY_LEANBACK_LAUNCHER} category, typically defined in the app manifest. +If this activity is not defined, a non-functioning app link appears—if +the user clicks it, nothing happens.
    • +
    • For the descriptive text +({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_TEXT}), the system +uses "Open app-name". If no viable app link intent URI is defined, +the system uses "No link available".
    • +
    • For the accent color +({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_COLOR}), +the system uses the default app color.
    • +
    • For the poster image +({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_POSTER_ART_URI}), +the system uses the app's home screen banner. If the app doesn't provide a +banner, the system uses a default TV app image.
    • +
    • For the badge icon +({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_ICON_URI}), the +system uses a badge that shows the app name. If the system is also using the +app banner or default app image for the poster image, no app badge is shown. +
    • +
    + +

    You specify app link details for your channels in your app's +setup activity. You can update these app link details at any point, so +if an app link needs to match channel changes, update app +link details and call +{@link android.content.ContentResolver#update(android.net.Uri, +android.content.ContentValues, java.lang.String, java.lang.String[]) +ContentResolver.update()} as needed. For more details on updating +channel data, see Update Channel Data. +

    + + + diff --git a/docs/html/training/tv/tif/content-recording.jd b/docs/html/training/tv/tif/content-recording.jd new file mode 100644 index 0000000000000000000000000000000000000000..ffdd14cb64398402ff279c4ca7bd1231916259eb --- /dev/null +++ b/docs/html/training/tv/tif/content-recording.jd @@ -0,0 +1,171 @@ +page.title=Supporting Content Recording +page.keywords=tv,recording,channel,tif +page.tags=tv, tif +helpoutsWidget=true + +trainingnavtop=true + +@jd:body + + + +

    TV input services let the user pause and resume channel playback via +time-shifting APIs. Android 7.0 expands on time-shifting +by letting the user save multiple recorded sessions.

    + +

    Users can schedule recordings in advance, or start a recording as they watch +a program. Once the system has saved a recording, the user can browse, manage, +and play back the recording using the system TV app.

    + +

    If you want to provide recording functionality for your TV input service, +you must indicate to the system that your app supports recording, implement +the ability to record programs, handle and communicate any errors that occur +during recording, and manage your recorded sessions.

    + +

    Note: The Live Channels app does not yet +provide a way for users to create or access recordings. Until changes are +made to the Live Channels app, it may be difficult to fully test the recording +experience for your TV input service.

    + +

    Indicating Support for Recording

    + +

    To tell the system that your TV input service supports recording, set +the android:canRecord attribute in your service metadata XML file +to true: +

    + +
    +<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
    +  android:canRecord="true"
    +  android:setupActivity="com.example.sampletvinput.SampleTvInputSetupActivity" />
    +
    + +

    For more information on the service metadata file, see +Declare Your TV Input +Service in the Manifest. +

    + +

    Alternatively, you can indicate recording support in your code using +these steps:

    + +
      +
    1. In your TV input service {@link android.app.Service#onCreate onCreate()} +method, create a new {@link android.media.tv.TvInputInfo} object using the +{@link android.media.tv.TvInputInfo.Builder TvInputInfo.Builder} class.
    2. +
    3. When creating the new {@link android.media.tv.TvInputInfo} object, call +{@link android.media.tv.TvInputInfo.Builder#setCanRecord +setCanRecord(true)} before calling +{@link android.media.tv.TvInputInfo.Builder#build build()} to indicate your +service supports recording.
    4. +
    5. Register your {@link android.media.tv.TvInputInfo} object with the +system by calling +{@link android.media.tv.TvInputManager#updateTvInputInfo +TvInputManager.updateTvInputInfo()}.
    6. +
    + +

    Recording a Session

    + +

    After your TV input service registers that it supports recording +functionality, the system calls your +{@link android.media.tv.TvInputService#onCreateRecordingSession +TvInputService.onCreateRecordingSession()} method when it needs to access +your app's recording implementation. Implement your own +{@link android.media.tv.TvInputService.RecordingSession +TvInputService.RecordingSession} subclass and return it +when the {@link android.media.tv.TvInputService#onCreateRecordingSession +onCreateRecordingSession()} callback fires. This subclass is responsible +for switching to the correct channel data, recording the requested data, +and communicating recording status and errors to the system.

    + +

    When the system calls +{@link android.media.tv.TvInputService.RecordingSession#onTune +RecordingSession.onTune()}, passing in a channel URI, tune to the channel +that the URI specifies. Notify the system that your app has tuned to the +desired channel by calling +{@link android.media.tv.TvInputService.RecordingSession#notifyTuned +notifyTuned()} or, if your app could not tune to the proper channel, call +{@link android.media.tv.TvInputService.RecordingSession#notifyError +notifyError()}.

    + +

    The system next invokes the +{@link android.media.tv.TvInputService.RecordingSession#onStartRecording +RecordingSession.onStartRecording()} callback. Your app must start recording +immediately. When the system invokes this callback, it may provide a URI +that contains information about the program that is about to be recorded. +When the recording is done, you'll copy this data to the +{@link android.media.tv.TvContract.RecordedPrograms RecordedPrograms} +data table.

    + +

    Finally, the system calls +{@link android.media.tv.TvInputService.RecordingSession#onStopRecording +RecordingSession.onStopRecording()}. At this point, your app must stop +recording immediately. You also need to create an entry in the +{@link android.media.tv.TvContract.RecordedPrograms RecordedPrograms} +table. This entry should include the recorded session data URI in the +{@link android.media.tv.TvContract.RecordedPrograms#COLUMN_RECORDING_DATA_URI +RecordedPrograms.COLUMN_RECORDING_DATA_URI} column, and any program +information that the system provided in the initial call to +{@link android.media.tv.TvInputService.RecordingSession#onStartRecording +onStartRecording()}.

    + +

    For more details on how to access the +{@link android.media.tv.TvContract.RecordedPrograms RecordedPrograms} table +see Managing Recorded Sessions.

    + +

    Handling Recording Errors

    + +

    If an error occurs during recording, resulting in unusable recorded data, +notify the system by calling +{@link android.media.tv.TvInputService.RecordingSession#notifyError +notifyError()}. Similarly, you can call +{@link android.media.tv.TvInputService.RecordingSession#notifyError +notifyError()} after a recording session is created to let the system know +that your app can no longer record sessions.

    + +

    If an error occurs during recording, but you'd like to provide a +partial recording to users for playback, call +{@link android.media.tv.TvInputService.RecordingSession#notifyRecordingStopped +notifyRecordingStopped()} to enable the system to +use the partial session.

    + +

    Managing Recorded Sessions

    + +

    The system maintains information for all recorded sessions from all +recording-capable channel apps in the +{@link android.media.tv.TvContract.RecordedPrograms RecordedPrograms} +content provider table. This information is accessible via the +{@link android.media.tv.TvContract.RecordedPrograms RecordedPrograms} +content recording URIs. Use content provider APIs to +read, add, and delete entries from this table.

    + +

    For more information on working with content provider data see + +Content Provider Basics.

    + +

    Best Practices

    + +

    TV devices may have limited storage, so use your best judgment when +allocating storage to save recorded sessions. Use +{@link android.media.tv.TvRecordingClient.RecordingCallback#onError +RecordingCallback.onError(RECORDING_ERROR_INSUFFICIENT_SPACE)} when +there isn't enough space to save a recorded session.

    + +

    When the user initiates recording, you should start recording data as soon +as possible. To facilitate this, complete any up-front time-consuming tasks, +like accessing and allocating storage space, when the system invokes the +{@link android.media.tv.TvInputService#onCreateRecordingSession +onCreateRecordingSession()} callback. Doing so lets you start +recording immediately when the +{@link android.media.tv.TvInputService.RecordingSession#onStartRecording +onStartRecording()} callback fires.

    diff --git a/docs/html/training/volley/index.jd b/docs/html/training/volley/index.jd index a8c4b84c7c478f3b7710f0c79db56c4b5cfd235a..d3645d9c89922f1eeaa4a2299a2206fd7fa07c5b 100755 --- a/docs/html/training/volley/index.jd +++ b/docs/html/training/volley/index.jd @@ -42,7 +42,7 @@ faster. Volley is available through the open
  • Automatic scheduling of network requests.
  • Multiple concurrent network connections.
  • Transparent disk and memory response caching with standard HTTP -cache coherence.
  • +cache coherence.
  • Support for request prioritization.
  • Cancellation request API. You can cancel a single request, or you can set blocks or scopes of requests to cancel.
  • @@ -66,13 +66,22 @@ alternative like {@link android.app.DownloadManager}.

    AOSP repository at {@code frameworks/volley} and contains the main request dispatch pipeline as well as a set of commonly applicable utilities, available in the Volley "toolbox." The -easiest way to add Volley to your project is to clone the Volley repository and set it as -a library project:

    +easiest way to add Volley to your project is to add the following dependency to your app's +build.gradle file: + +
    +dependencies {
    +    ...
    +    compile 'com.android.volley:volley:1.0.0'
    +}
    +
    + +You can also clone the Volley repository and set it as a library project:

    1. Git clone the repository by typing the following at the command line: -
      +
       git clone https://android.googlesource.com/platform/frameworks/volley
       
    2. diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd index 20f219d69188820fc012a60c0da7447c716358af..db0ffcf6d163969757c3f429ffacab8e9c6f0b63 100644 --- a/docs/html/training/wearables/data-layer/events.jd +++ b/docs/html/training/wearables/data-layer/events.jd @@ -242,7 +242,7 @@ Standard Android filter matching rules apply. You can specify multiple services per manifest, multiple intent filters per service, multiple actions per filter, and multiple data stanzas per filter. Filters can match on a wildcard host or on a specific one. To match on a wildcard host, use {@code host="*"}. To match -on a specific host, specify {@code host=<node_id>}. +on a specific host, specify {@code host=}.

      diff --git a/docs/html/training/wearables/data-layer/messages.jd b/docs/html/training/wearables/data-layer/messages.jd index ef9bfb176a5bcc381dad4c22a83b7ff5a535cf89..8c4b730c97cddaacbe132be50d8de6482dda3afa 100644 --- a/docs/html/training/wearables/data-layer/messages.jd +++ b/docs/html/training/wearables/data-layer/messages.jd @@ -10,12 +10,6 @@ page.title=Sending and Receiving Messages

    3. Send a Message
    4. Receive a Message
    -

    Try it out

    -
    @@ -27,6 +21,7 @@ and attach the following items to the message:

  • An arbitrary payload (optional)
  • A path that uniquely identifies the message's action
  • +

    Unlike with data items, there is no syncing between the handheld and wearable apps. Messages are a one-way communication mechanism that's good for remote procedure calls (RPC), @@ -149,11 +144,9 @@ If you create a service that extends WearableListenerService to detect capability changes, you may want to override the onConnectedNodes() -method to listen to finer-grained connectivity details, such as when a wearable device switches -from Wi-Fi to a Bluetooth connection to the handset. For an example implementation, see the -DisconnectListenerService class in the -FindMyPhone -sample. For more information on how to listen for important events, see +method to listen to finer-grained connectivity details, such as when a wearable +device switches from Wi-Fi to a Bluetooth connection to the handset. +For more information on how to listen for important events, see Listen for Data Layer Events.

    diff --git a/docs/html/training/wearables/notifications/creating.jd b/docs/html/training/wearables/notifications/creating.jd index 6f8497a21ec40db814d0ef5990873869021689ca..5663b585b94e7deb6e6e6b75f383e87cf22a29da 100644 --- a/docs/html/training/wearables/notifications/creating.jd +++ b/docs/html/training/wearables/notifications/creating.jd @@ -28,7 +28,7 @@ notifications properly, whether they appear on a handheld or wearable.

    Note: Notifications using {@link android.widget.RemoteViews} are stripped of custom -layouts and the wearable only displays the text and icons. However, you can create +layouts and the wearable only displays the text and icons. However, you can create custom notifications that use custom card layouts by creating a wearable app that runs on the wearable device.

    diff --git a/docs/html/tv/_project.yaml b/docs/html/tv/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d2d41e1ce267a68f0eb4c46b4a745a946f7aacad --- /dev/null +++ b/docs/html/tv/_project.yaml @@ -0,0 +1,6 @@ +name: "TV" +home_url: /tv/ +description: "Bring your apps, games, and content to the biggest screen in the house." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /about/_project.yaml diff --git a/docs/html/tv/index.jd b/docs/html/tv/index.jd index 7c958c006b54a582598c685ffac7bf9e85166d25..6ecc1ea7f6579b9a08463b16764b45877737e5d9 100644 --- a/docs/html/tv/index.jd +++ b/docs/html/tv/index.jd @@ -13,7 +13,7 @@ nonavpage=true diff --git a/docs/html/wear/_project.yaml b/docs/html/wear/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..114cc5b74d762a3f53208b8c24a462509ca8243d --- /dev/null +++ b/docs/html/wear/_project.yaml @@ -0,0 +1,6 @@ +name: "Wear" +home_url: /wear/ +description: "Small, powerful devices, worn on the body. Useful information when you need it most." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /about/_project.yaml diff --git a/docs/html/wear/images/partners/mkors.png b/docs/html/wear/images/partners/mkors.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1e8ec3aad4f4c159f1b7ff660bb597e1e9d877 Binary files /dev/null and b/docs/html/wear/images/partners/mkors.png differ diff --git a/docs/html/wear/images/partners/nixon.png b/docs/html/wear/images/partners/nixon.png new file mode 100644 index 0000000000000000000000000000000000000000..8674da27974d12015acf38ddd589103e5a8a7812 Binary files /dev/null and b/docs/html/wear/images/partners/nixon.png differ diff --git a/docs/html/wear/images/partners/polar.png b/docs/html/wear/images/partners/polar.png new file mode 100644 index 0000000000000000000000000000000000000000..2faeb063e1ff5ed9a8decfa30caa708eaa465dd7 Binary files /dev/null and b/docs/html/wear/images/partners/polar.png differ diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd index f5e9e87748b93513d72194eb85d21b1b50f0dc1a..1eb08bec612c31f3b0c9b688d4110d4e6c768534 100644 --- a/docs/html/wear/index.jd +++ b/docs/html/wear/index.jd @@ -9,7 +9,7 @@ nonavpage=true @@ -266,6 +266,9 @@ nonavpage=true
    MIPS +
    +
    + Michael
    Mobvoi @@ -276,6 +279,12 @@ nonavpage=true
    New Balance
    +
    + Nixon +
    +
    + Polar +
    Qualcomm
    diff --git a/docs/html/wear/preview/_book.yaml b/docs/html/wear/preview/_book.yaml index a4acad04afcc71e88690da94bcae389491c6eeb9..54d5442ec6314929a0990d28e5b3daa9ce1b7d07 100644 --- a/docs/html/wear/preview/_book.yaml +++ b/docs/html/wear/preview/_book.yaml @@ -8,16 +8,24 @@ toc: - title: API Overview path: /wear/preview/api-overview.html section: - - title: Notification Improvements - path: /wear/preview/features/notifications.html - - title: Input Method Framework - path: /wear/preview/features/ime.html - title: Complications path: /wear/preview/features/complications.html - title: Navigation and Actions path: /wear/preview/features/ui-nav-actions.html + - title: Curved Layout + path: /wear/preview/features/wearable-recycler-view.html + - title: Notification Improvements + path: /wear/preview/features/notifications.html - title: Bridging for Notifications path: /wear/preview/features/bridger.html + - title: Input Method Framework + path: /wear/preview/features/ime.html + - title: Wrist Gestures + path: /wear/preview/features/gestures.html + - title: Standalone apps + path: /wear/preview/features/standalone-apps.html + - title: App Distribution + path: /wear/preview/features/app-distribution.html - title: Get Started path: /wear/preview/start.html @@ -28,5 +36,8 @@ toc: - title: License Agreement path: /wear/preview/license.html +- title: Behavior Changes + path: /wear/preview/behavior-changes.html + - title: Support and Release Notes path: /wear/preview/support.html diff --git a/docs/html/wear/preview/_project.yaml b/docs/html/wear/preview/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4f7083ef32df557120be8b7f27a63c694bf13268 --- /dev/null +++ b/docs/html/wear/preview/_project.yaml @@ -0,0 +1,6 @@ +name: "Wear Preview" +home_url: /wear/preview/ +description: "Small, powerful devices, worn on the body. Useful information when you need it most." +content_license: cc3-apache2 +buganizer_id: 30209417 +parent_project_metadata_path: /wear/_project.yaml diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd index 11331a777d62ed2dfd075a0fb79d9ecb41c64c48..f4612a2599580b802298f9fc0c53ccad1f93d34b 100644 --- a/docs/html/wear/preview/api-overview.jd +++ b/docs/html/wear/preview/api-overview.jd @@ -13,18 +13,20 @@ page.image=images/cards/card-n-apis_2x.png
    1. Complications
    2. Navigation and Action Drawers
    3. +
    4. Curved Layout
  • Notifications and Input
      -
    1. Expanded Notification
    2. -
    3. Messaging Style Notification
    4. +
    5. Expanded Notifications
    6. +
    7. Messaging Style Notifications
    8. +
    9. Inline Action
    10. Smart Reply
    11. -
    12. Notification Content Action
    13. Remote Input
    14. Bridging Mode
    15. Input Method Framework
    16. +
    17. Wrist Gestures
  • @@ -39,291 +41,447 @@ page.image=images/cards/card-n-apis_2x.png
    - - -

    - The Android Wear Preview API is still in active development, but you can try - it now as part of the Wear 2.0 Developer Preview. The sections below - highlight some of the new features for Wear developers. -

    - - -

    User Interface Improvements

    - -

    The preview introduces powerful additions to the user interface, opening up -exciting possibilities to developers. -A complication is any feature in a watch face that displays more than hours and -minutes. With the Complications API, - watch faces can display extra information and separate apps can expose complication - data. -The navigation and action drawers provide users with new ways to interact with apps. -

    - - -

    Complications

    - - -

    - A complication is a - feature of a watch face that displays more than hours and minutes, such as a - battery indicator or a step counter. The Complications API helps watch face - developers create these features visual features and data connections they - require. -

    - -

    - Watch faces that use this API can display extra information without needing - code for getting the underlying data. Data providers can supply data to any - watch face using the API. -

    - -

    For examples of how to use this feature, -see - Watch Face Complications. -

    - - -

    Navigation and Action drawers

    - -

    Wear 2.0 introduces two new widgets, navigation drawer and action drawer. These - widgets give your users new ways to interact with your app. The navigation drawer - appears at the top of the screen and allows users to navigate between app views. - The action drawer appears at the bottom of the screen and allows users to choose - from a list of actions associated with the current usage context. These drawers - are accessible to users when they edge swipe from the top or bottom of the - screen; they peek when users scroll in an opposite direction. -

    - -
    -
    - -
    -
    - -
    -
    - -

    - To learn how to add these widgets to your app, see - - Wear Navigation and Actions. -

    - - -

    Notifications and Input

    - -

    In Wear 2.0, we’ve redesigned the key experiences on the watch to be even more - intuitive and provide users new ways to respond to messages. Some of the highlights - are below; for a complete list of changes, see - Notification Changes in Wear 2.0. - - - -

    Expanded notifications

    - -

    - When a user taps on a notification that is bridged from the phone to the - watch or that lacks a - - {@code contentIntent}, the user will be taken to the expanded view of - that notification. When you specify additional - content pages and actions for a notification, those are available to the - user within the expanded notification. Each expanded notification follows - Material Design for Android - Wear, so the user gets an app-like experience. -

    - - -

    Messaging Style notification

    -

    If you have a chat messaging app, your notifications should use -{@code Notification.MessagingStyle}, which is new in Android 6.0. Wear 2.0 uses -the chat messages included in a -{@code MessagingStyle} - notification -(see {@code addMessage()}) to provide a rich chat app-like experience in the -expanded notification. -

    - - -

    Smart Reply

    - -

    Android Wear 2.0 introduces support for Smart Reply in -{@code MessagingStyle} - notifications. Smart Reply provides the user with contextually relevant, - touchable choices in the expanded notification and in - {@code RemoteInput}. -

    - -

    By enabling Smart Reply for your {@code MessagingStyle} notifications, you provide -users a fast (single tap), discreet (no speaking aloud), and reliable way to respond - to chat messages they receive. -

    - - - - -

    Remote Input

    - -

    Wear 2.0 users can choose between various input options from -Remote Input. - These options include: -

    -
      -
    • Dictation
    • -
    • Emoji
    • -
    • Canned responses
    • -
    • Smart Reply -
    • Default IME -
    - -

    -For messaging notifications with Smart Reply, the system-generated Smart Reply - appears within {@code RemoteInput} - above the developer-provided list of canned responses. - You can also use the - setChoices() - method in the {@code RemoteInput} API to enable users to select from a list - of canned responses. -

    - -

    Bridging Mode

    -

    By default, notifications are - -bridged (shared) from an app on a companion phone -to the watch. Since a phone app and a standalone watch app may be sources of the - same notifications, the Android Wear 2.0 Preview includes a Bridging mode feature. - Developers can begin planning to change the behavior of notifications with the - following: -

    - -
      -
    • Specifying in the standalone app's Android manifest file that notifications from - the corresponding phone app should not be bridged to the watch.
    • -
    • Setting a dismissal ID so notification dismissals (by users) are synced across -devices.
    • -
    - -

    For an example of how to use this feature, see -Bridging Mode for Notifications.

    - -

    Input Method Framework

    - -

    Wear 2.0 extends the Android input method framework (IMF) to Android Wear. -This allows users to enter text on Wear using the system default IME or third party - IMEs. The Wear IME lets the user enter text via gesture typing as well as tapping - individual keys. The IMF APIs used for Wear devices are the same as other form - factors, though usage is slightly different due to limited screen real estate. -

    - -

    Wear provides user settings on the watch that let the user:

    -
      -
    • Enable multiple IMEs from the list of installed IMEs.
    • -
    • Set a single default IME from the list of enabled IMEs.
    • -
    • Change languages for various IMEs.
    • -
    - -

    To learn how to create an IME for Wear, see -Input Method Framework. -

    - - -

    Standalone Devices

    - -

    Standalone watches will enable Android Wear apps to work independently of phone - apps. This means your app can continue to offer full functionality even if the - paired phone is far away or turned off.

    - -

    Wear-Specific APKs

    - -

    For delivery to a watch, an Android Wear app is currently embedded in its corresponding -phone app. This delivery method can result in an increased download size for users, - regardless of whether they have an Android Wear device. -

    - -

    With standalone devices, the -Multi-APK - delivery method will be used. Developers will have the ability to release Android - Wear apps independently of the corresponding phone apps. Please stay tuned for - more information about this change. -

    - -

    Network Access

    - -

    Since Android Wear apps will work independently of phone apps, Android Wear's - network access will no longer require the - - Wearable Data Layer API. Android Wear apps will have the ability to make - their own network requests. Additionally, they will be able to directly use - Google Cloud Messaging. -

    - -

    No APIs for network access or GCM are specific to Android Wear; refer to the -existing documentation about - -Connecting to the Network and -Cloud Messaging. -

    - -

    We recommend using the following libraries:

    - - -

    You will still be able to use the - - Wearable Data Layer API to communicate with a phone app. - However, use of this API to connect to a network will be discouraged. -

    - - -

    Authentication

    - -

    Since Android Wear apps will work independently of phone apps, Android Wear's - authentication capabilities will be more powerful; apps will have new ways to - authenticate.

    - -

    Users can enter a username and password on a watch

    - -

    Google Keyboard will be standard on Android Wear, allowing for direct text -entry. This feature will work as expected with standard -EditText widgets. -For passwords, the {@code textPassword} attribute will be used.

    - -

    Utilizing Account Manager

    - -

    Android Wear will include the - -AccountManager, which will be accessible for syncing and storing account -data, as it is on an Android phone.

    - -

    Authentication tokens can be passed over the Wearable Data Layer

    - -

    For Android-paired watches (only), a phone securely -transfers authentication credentials to a watch app via the - -Wearable Data Layer API. The credentials can be transferred as -messages or data items.

    - -

    If your watch app needs to determine if your phone app is installed, you can -advertise a capability on the phone app and retrieve the capability on the -watch. For more information, see the following sections of - -Sending and Receiving Messages:

    - -
      -
    • Advertise Capabilities
    • -
    • Retrieve the Nodes with the Required Capabilities
    • -
    +

    + Wear 2.0 is still in active development, but you can try it as part of + the Wear 2.0 Developer Preview. The sections below highlight some of the + new features for developers. +

    + +

    + User Interface Improvements +

    + +

    + The preview introduces powerful additions to the user interface, opening + up exciting possibilities to developers. +

    + +

    + Complications +

    + + +

    + A complication + is a feature of a watch face that displays more than hours and minutes, + such as a battery indicator or a step counter. The Complications API thus + helps watch face developers create visual features and the data + connections they require. +

    + +

    + Watch faces that use this API can display extra information without + needing code for getting the underlying data. Data providers can supply + data to any watch face using the API. +

    + +

    + For information about this API, see Watch Face + Complications. +

    + +

    + Navigation and Action Drawers +

    + +

    + Wear 2.0 introduces two new widgets, navigation drawer and action drawer. + These widgets give your users new ways to interact with your app. The + navigation drawer appears at the top of the screen and allows users to + navigate between app views. The action drawer appears at the bottom of + the screen and allows users to choose from a list of actions associated + with the current usage context. These drawers are accessible to users + when they edge swipe from the top or bottom of the screen; they peek when + users scroll in an opposite direction. +

    + +
    +
    + +
    + +
    + +
    +
    + +

    + To learn how to add these widgets to your app, see Wear Navigation and + Actions. +

    + +

    + Curved Layout +

    + +

    + Wear 2.0 introduces the WearableRecyclerView class for + displaying and manipulating a vertical list of items, + optimized for round displays. +

    + +

    + The key features include the following: +

    + +
      +
    • A curved layout on round devices +
    • + +
    • A circular scrolling gesture, which can be toggled on and off +
    • +
    + +

    + To learn how to create a curved layout optimized for round devices, see + + Curved Layout. +

    + +

    + Notifications and Input +

    + +

    + In Wear 2.0, we’ve redesigned the key experiences on the watch to be even + more intuitive and provide users new ways to respond to messages. Some of + the highlights are below; for a complete list of changes, see Notification Changes + in Wear 2.0. +

    + +

    + Expanded Notifications +

    + +

    + When a user taps on a notification that is bridged from the phone to the + watch or that lacks a + {@code contentIntent}, the user will be taken to the expanded view of + that notification. When you specify + additional content pages and actions for a notification, those are + available to the user within the expanded notification. Each expanded + notification follows Material Design for Android + Wear, so the user gets an app-like experience. +

    + +

    + Messaging Style Notifications +

    + +

    + If you have a chat messaging app, your notifications should use {@code + Notification.MessagingStyle}, which is new in Android 6.0. Wear 2.0 uses + the chat messages included in a {@code + MessagingStyle} notification (see {@code addMessage()}) to provide a + rich chat, app-like experience in the expanded notification. +

    + +

    + Inline Action +

    + +

    + Wear 2.0 enables you to add an inline action within the notification + stream so that users can quickly take an action on a notification. + Examples of good use cases for an inline action within a notification stream + include replying to a text message, stopping a fitness activity, or + archiving an email message. +

    + +

    + To learn how to add an inline action to your notification stream, see + + Inline Action. +

    + +

    + Smart Reply +

    + +

    + Android Wear 2.0 introduces support for Smart Reply in {@code + MessagingStyle} notifications. Smart Reply provides the user with + contextually relevant, touchable choices in the expanded notification and + in {@code + RemoteInput}. +

    + +

    + By enabling Smart Reply for your {@code MessagingStyle} notifications, + you provide users a fast (single tap), discreet (no speaking aloud), and + reliable way to respond to chat messages they receive. +

    + + + +

    + Remote Input +

    + +

    + Wear 2.0 users can choose between various input options from Remote Input. + These options include: +

    + +
      +
    • Dictation +
    • + +
    • Emoji +
    • + +
    • Canned responses +
    • + +
    • Smart Reply +
    • + +
    • Default IME +
    • +
    + +

    + For messaging notifications with Smart Reply, the system-generated Smart + Reply appears within {@code + RemoteInput} above the developer-provided list of canned responses. + You can also use the + setChoices() method in the {@code RemoteInput} API to enable users to + select from a list of canned responses. +

    + +

    + Bridging Mode +

    + +

    + By default, notifications are bridged + (shared) from an app on a companion phone to the watch. Since a phone app + and a standalone watch app may be sources of the same notifications, the + Android Wear 2.0 Preview includes a Bridging mode feature. +

    + +

    + For information about this feature, see Bridging Mode for + Notifications. +

    + +

    + Input Method Framework +

    + +

    + Wear 2.0 extends the Android input method framework (IMF) to Android + Wear. This allows users to enter text on Wear using the system default + IME or third party IMEs. The Wear IME lets the user enter text via + gesture typing as well as tapping individual keys. The IMF APIs used for + Wear devices are the same as other form factors, though usage is slightly + different due to limited screen real estate. +

    + +

    + Wear provides user settings on the watch that let the user: +

    + +
      +
    • Enable multiple IMEs from the list of installed IMEs. +
    • + +
    • Set a single default IME from the list of enabled IMEs. +
    • + +
    • Change languages for various IMEs. +
    • +
    + +

    + To learn how to create an IME for Wear, see Input Method Framework. +

    + +

    + Wrist Gestures +

    + +

    + Wrist gestures can enable quick, one-handed interactions with your app + when use of a touch screen is inconvenient. The following wrist + gestures are available for use by apps: +

    + +
      +
    • Flick wrist out +
    • + +
    • Flick wrist in +
    • +
    + +

    + For more information, see Wrist Gestures. +

    + +

    + Standalone Devices +

    + +

    + Standalone watches enable Android Wear apps to work independently of + phone apps. This means your app can continue to offer full functionality + even if the paired phone is far away or turned off. +

    + +

    + Wear-Specific APKs +

    + +

    + For delivery to a watch, an Android Wear app is currently embedded in its + corresponding phone app. This delivery method can result in an increased + download size for users, regardless of whether they have an Android Wear + device. +

    + +

    + For information about planning and building your standalone app + for Wear 2.0, see + Standalone Apps. +

    + +

    + For information about distributing your app, see + App Distribution. +

    + +

    + Network Access +

    + +

    + Since Android Wear apps will work independently of phone apps, Android + Wear's network access will no longer require the Wearable Data Layer + API. Android Wear apps will have the ability to make their own + network requests. Additionally, they will be able to directly use Google + Cloud Messaging. For more information, see + + Network Access and Cloud Messaging. +

    + +

    + No APIs for network access or GCM are specific to Android Wear; refer to + the existing documentation about Connecting to the + Network and Cloud Messaging. +

    + +

    + We recommend using the following libraries: +

    + + + +

    + The Wearable Data Layer + API is available to communicate with a phone app. + However, use of this API to connect to a network will be discouraged. +

    + +

    + Authentication +

    + +

    + Since Android Wear apps will work independently of phone apps, Android + Wear's authentication capabilities will be more powerful; apps will have + new ways to authenticate. +

    + +

    + Users can enter a username and password on a watch +

    + +

    + Google Keyboard will be standard on Android Wear, allowing for direct + text entry. This feature will work as expected with standard EditText widgets. + For passwords, the {@code textPassword} attribute will be used. +

    + +

    + Utilizing Account Manager +

    + +

    + Android Wear will include the AccountManager, + which will be accessible for syncing and storing account data, as it is + on an Android phone. +

    + +

    + Authentication tokens can be passed over the Wearable Data Layer +

    + +

    + For Android-paired watches (only), a phone securely transfers + authentication credentials to a watch app via the Wearable Data Layer + API. The credentials can be transferred as messages or data items. +

    + +

    + If your watch app needs to determine if your phone app is installed, you + can advertise a capability on the phone app and retrieve the capability + on the watch. For more information, see the following sections of + Sending + and Receiving Messages: +

    + +
      +
    • Advertise Capabilities +
    • + +
    • Retrieve the Nodes with the Required Capabilities +
    • +
    diff --git a/docs/html/wear/preview/behavior-changes.jd b/docs/html/wear/preview/behavior-changes.jd new file mode 100644 index 0000000000000000000000000000000000000000..c93d337a0a8c0cd4941e7a534ec3313aeebb50bd --- /dev/null +++ b/docs/html/wear/preview/behavior-changes.jd @@ -0,0 +1,106 @@ +page.title=Behavior Changes +meta.keywords="preview", "wear" +page.tags="preview", "developer preview" + +@jd:body + +

    + Along with new features, Android Wear 2.0 includes a variety of behavior + changes. This document highlights some of the key changes to + account for in your apps. +

    + +

    + If you have previously published an app for Android Wear, be aware that + your app might be affected by these changes in the platform. +

    + + + +

    Activity Dismissal

    + +

    + Starting in Android Wear 2.0, + users dismiss apps and activities by using + the power (stem) button on the watch. + Long-pressing to dismiss an app is no longer suggested. + Additionally, developers should not implement the + long-press for dismissing + full screen + activities (panning or immersive activities such as Google Maps). +

    + +

    + In Android Wear 2.0, the power button of the watch is used + to navigate back in the + back stack, + including for full-screen panning activities. + Before Android Wear 2.0, the DismissOverlayView class was + used to implement the long-press for a user to dismiss an app. + (The DismissOverlayView class was added to a layout + for full-screen drawing and to draw over the other views.) + Developers should test the power button for going back + between an app's activities and for exiting an app. +

    + +

    + Additionally, swipe for exiting an app or activity is not available. + Developers can consider how their user interfaces + can be enhanced with swipe-left and swipe-right, + in a way similar to the functionality described for + navigation + drawers. +

    + +

    Invalid Fields for a Complication Type

    + +

    + When a watch face uses the + Complications API, the watch face requests data from a chosen provider. + A ComplicationData object, which contains + complication types, is returned. +

    + +

    + A complication type determines the + kinds of data that a watch face can render. This section describes + a behavior change related to the ComplicationData object. +

    + +

    + Starting with + + Developer Preview 3, when a watch face requests a field that is invalid + for a complication type, a default value for the field is returned. + For example, if a watch face tries to access a Long text + field in a SHORT_TEXT type, the default value for the + Long text field is returned. + In previous releases, such a request for an invalid field + (for a type) resulted in an exception. +

    + +

    Complication Types for Empty Data

    + +

    + Starting with + + Developer Preview 3, the complication types used for "empty" data are + changed. Apps that use the Complications API + may need to be updated to use + TYPE_NO_DATA. See the information + about TYPE_NO_DATA in the + + Types and fields section. +

    diff --git a/docs/html/wear/preview/downloads.jd b/docs/html/wear/preview/downloads.jd index 86895047d7d24eaf06e8a83c1939167e4ae20119..bfa384bf2f104079901d22314cb22a1775321809 100644 --- a/docs/html/wear/preview/downloads.jd +++ b/docs/html/wear/preview/downloads.jd @@ -171,7 +171,9 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
  • Set Up a Watch
  • - +
  • + Set Up a Phone +
  • Set Up an Emulator
  • @@ -180,7 +182,7 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement

    - You can run and test your app with the Android Wear 2.0 Developer Preview + You can run and test your app with the Android Wear 2.0 Preview in either of these ways:

    @@ -223,8 +225,8 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement

    - Warning: Installing a system image on a watch removes all data from the - watch, so you should back up your data first. + Warning: Installing a system image on a watch removes all + data from the watch, so you should back up your data first.

    @@ -233,8 +235,20 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement

    The preview includes system images for testing your app. Based on your - device, you can download a preview system image from the following tables - and flash it to the corresponding device. + device, you can download a preview system image from one of the + following tables and flash it to the corresponding device. +

    + +

    Caution: + After you flash an image to a watch, follow the steps for + setting up a phone with the beta version of + the Android Wear companion app. To use a Wear 2.0 image on a watch, + you must have the beta companion app on a paired phone. +

    + +

    + To restore your device to its original state during the preview, + you can flash the appropriate retail system image, below, to the device.

    @@ -261,9 +275,9 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement Preview image for testing - nemo-nvd36i-factory-9cdd2ac0.tgz
    - MD5: b33ba8e59780fbe5c83d8936b108640f
    - SHA-1: 9cdd2ac01f2976cafe5a21958298dac159b7a325 + nemo-nve68j-factory-302a33ea.tgz
    + MD5: ddfccc3e050c7e2db8d657c82f7d6291
    + SHA-1: 302a33eac348c401fcb165bad4b9aaa40c7beb2b @@ -271,9 +285,9 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement Non-preview image (for after testing) - nemo-mnc40x-factory-fa528bec.tgz
    - MD5: 0b8ba3653d5a93cb854f4d7409d7b6c9
    - SHA-1: fa528bec8aba3bf6c7d901ba63cd6ea0a08dbeb0 + nemo-mfd18l-factory-3faf6f2d.tgz
    + MD5: f3a0090c0e99da82ad095b5d2a9acc6d
    + SHA-1: 3faf6f2d7f422a17a5f6c54cf5e1d2c5622689b0 @@ -302,18 +316,18 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement Preview image for testing - sturgeon-nvd36i-factory-2cbe5080.tgz
    - MD5: ccc972cdc33cba778a2f624066ef5713
    - SHA-1: 2cbe5080ded060ce43ba65ff27e2290b28981634 + sturgeon-nve68j-factory-6607cd31.tgz
    + MD5: f78ac6ba8bb84038d163cc2d7ca85040
    + SHA-1: 6607cd31858af1bfd50b905c68f7cf1f0b6e570e Non-preview image (for after testing) - sturgeon-mec23l-factory-48003078.tgz
    - MD5: 417b5cbddb29a2262bce133e283d2732
    - SHA-1: 4800307843580f818557dd7c43d8ba2161e289b2 + sturgeon-m6e69f-factory-e659286a.tgz
    + MD5: 12ce6cb0b0e43b67ea46a886eae052ae
    + SHA-1: e659286aa9004f4555a476ede4e8b690f56cfefd @@ -332,7 +346,8 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement

    - Warning: Installing a system image on a watch removes all data from the + Warning: Installing a system image on a watch + removes all data from the watch, so you should back up your data first.

    @@ -341,8 +356,7 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement

    - From the phone, unpair ("Forget") the watch. - Then on the watch, enable the Developer Options menu and ADB debugging as + On the watch, enable the Developer Options menu and ADB debugging as follows:

    @@ -351,14 +365,14 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
  • Scroll to the bottom of the menu. If no Developer - Options item is provided, tap About. + Options item is provided, tap System + and then About.
  • Tap the build number 7 times.
  • -
  • From the Settings menu, tap the Developer Options - item. +
  • From the Settings menu, tap Developer Options.
  • Enable ADB debugging. @@ -404,7 +418,9 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
  • Use the following adb - command to confirm that the watch is available for flashing: + command to confirm that the watch is recognized. + You may need to turn ADB debugging off and then on for the watch to + be recognized: adb devices
  • @@ -418,11 +434,11 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement devices, fastboot oem unlock -
  • On the watch, select the Unlock option. +
  • On the watch, select the option to unlock the bootloader.
  • -
  • Navigate to the directory where you unzipped the system image in Step - 1. At the top level of that directory, +
  • On your computer, navigate to the directory where you unzipped the + system image in Step 1. At the top level of that directory, execute the flash-all script by typing flash-all.sh or, in the case of Windows, flash-all.bat. The following may need to @@ -432,18 +448,19 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement

    - Set up the watch and begin testing + Set up the watch

    -

    - After the flash-all script finishes, your watch reboots. - Pair the watch with a phone or tablet. The preview now is available - for testing on the watch. Before installing an app, perform the - following steps on the watch to re-secure the watch's bootloader: +

    + After the flash-all script finishes, the watch reboots. + Only pair the watch with a phone (so you can begin testing the preview) + by using the instructions in Set Up a Phone. + Additionally, before installing an app, perform the + following steps on the watch to re-secure the watch's bootloader:

      -
    1. Open the Settings menu (on the watch). +
    2. Open the Settings menu by long-pressing the physical button.
    3. Scroll to the bottom of the menu and tap About. @@ -452,15 +469,16 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
    4. Tap the build number 7 times.
    5. -
    6. From the Settings menu, tap the Developer Options - item. +
    7. From the Settings menu, tap Developer Options.
    8. Enable ADB debugging.
    9. Connect the watch to your computer and tap Always allow from - this computer. + this computer. (You may need to turn ADB debugging off + and then on, to be prompted to always allow ADB debugging from + the connected computer.)
    10. Use the following adb command to start the device in fastboot mode: @@ -472,13 +490,18 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement devices, fastboot oem lock
    11. -
    12. On the watch, continue the boot by choosing - Start and touching '0'. +
    13. On the watch, continue the boot as follows: + On an LGE Watch Urbane 2nd Edition, choose + Start and touch '0'. + On a Huawei Watch, confirm that Reboot is chosen and + long-press the physical button.

    - Your watch is ready for you to Set Up a Phone, + your watch will be ready for you to install and run your app:

    @@ -534,13 +557,116 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement device reset and removes all user data on the device.

    +

    + Set Up a Phone +

    + +

    + On a phone, follow the instructions in this section to install the beta + version of the Android Wear companion app. The beta version cannot be run + on a phone at the same time as the non-beta version. Additionally, the + beta version is English-only. +

    + +

    +

    Caution: If you have an existing + pairing of the phone to a Wear 1.x + watch, installation of the beta companion app will cause a loss of that + pairing. +

    + +

    + Join the Wear 2.0 preview group +

    + +

    + To access the beta companion app, you must join + the preview group in Google Groups. +

    + +

    + Opt in for beta testing +

    + +

    + On the Testing + Opt-in page, select Become a Tester. +

    + +

    + Download and install the beta version of the companion app +

    + +

    + On the Play Store on your phone, go to the + Android Wear app listing. Tap Update to download and + install the beta version of the app. After installation, confirm that + Auto-update is selected for the app (see + the "Set up automatic updates for specific apps" section of Update downloaded + apps). Tap Open to start the app. +

    + +

    + Pair the phone to the watch +

    + +

    + After you install the beta version of the companion app on a phone, + unpair ("Forget") any obsolete watch pairings, if necessary. + Then you can pair the phone to a newly-imaged watch: +

    + +
      +
    1. On the phone, select your device name from the list of devices. + A pairing code is displayed on the phone and on the watch. + Ensure that the codes match. +
    2. + +
    3. Tap Pair to + continue the pairing process. When the watch is connected to + the phone, a confirmation message is displayed. + On the phone, a screen is displayed that lists + the accounts on the phone. +
    4. + +
    5. Choose a Google Account to add and sync to your watch. +
    6. + +
    7. Confirm the screen lock and enter the password to start the copying of + the account from the phone to the watch. +
    8. + +
    9. Follow the instructions in the wizard to finish the + pairing process. +
    10. +
    + +

    + You can begin testing your app with the preview. +

    +

    Set Up an Emulator

    - To test with the Android Emulator, create a virtual device in Android - Studio as follows: + To test with the Android Emulator, + confirm that you have the latest version of the Android SDK + Platform-tools from the SDK Manager. +

    + +

    + After you create a virtual device as described below, follow the steps for + setting up a phone with the beta version of + the Android Wear companion app. +

    + +

    Create a new virtual device in Android Studio as follows:

      @@ -551,19 +677,19 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
    1. Click Create Virtual Device.
    2. -
    3. In the Category pane, select Wear and - choose a hardware profile. +
    4. In the Category pane, select Wear + and choose a hardware profile. The Android Wear 2.0 Developer Preview is only optimized for round devices currently, so we recommend not using the square or chin profiles for now. Click Next.
    5. -
    6. Select an N image to download. The images may be on +
    7. Select a Nougat image to download. The images may be on the x86 tab instead of the Recommended tab, until installed. For example, select the image with the - Release Name of N, the API Level of N, - and the Target of "Android 6.X (with Android Wear)". + Release Name of Nougat, the API Level of 24, + and the Target of "Android 7.0 (with Android Wear)". When the download and installation are complete, click Finish and then click Next.
    8. @@ -571,16 +697,68 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
    9. Verify the configuration of the Android Virtual Device (AVD) and click Finish.
    10. + +
    11. Start the emulator by selecting the new virtual device, clicking the + Play button, and waiting until + the emulator initializes and shows the Android Wear home screen. +

    - You can now test an application with a virtual preview device + Pair the phone with the emulator, and sync a Google Account, as follows: +

    + +
      +
    1. Follow the steps for + setting up a phone with the beta version of + the Android Wear companion app. +
    2. + +
    3. On the phone, enable Developer Options and USB Debugging. +
    4. + +
    5. Connect the phone to your computer through USB. +
    6. + +
    7. Forward the AVD's communication port to the connected handheld device + (each time the phone is connected):
      + adb -d forward tcp:5601 tcp:5601 +
    8. + +
    9. On the phone, in the Android Wear app, begin the standard pairing + process. For example, on the Welcome screen, tap the + Set It Up button. + Alternatively, if an existing watch already is paired, in the upper-left + drop-down, tap Add a New Watch. +
    10. + +
    11. On the phone, in the Android Wear app, tap the + Overflow button, and then tap + Pair with Emulator. +
    12. + +
    13. Tap the Settings icon. +
    14. + +
    15. Under Device Settings, tap Emulator. +
    16. + +
    17. Tap Accounts and select a Google Account, + and follow the steps in the wizard to + sync the account with the emulator. If necessary, type the screen-lock + device password, and Google Account password, to start the account sync. +
    18. +
    + +

    + You can now test an app with a virtual preview device in the Android Emulator. For more information about using virtual devices, see Managing AVDs with the AVD - Manager. + "{@docRoot}studio/run/managing-avds.html"> + Create and Manage Virtual Devices.

    +
  • diff --git a/docs/html/wear/preview/features/app-distribution.jd b/docs/html/wear/preview/features/app-distribution.jd new file mode 100644 index 0000000000000000000000000000000000000000..afc95165e49b7c1ffb38cbe0a418840ae41fc1f1 --- /dev/null +++ b/docs/html/wear/preview/features/app-distribution.jd @@ -0,0 +1,329 @@ +page.title=App Distribution +meta.keywords="wear-preview" +page.tags="wear-preview" +page.image=images/cards/card-n-sdk_2x.png +@jd:body + + + +

    + With Android Wear 2.0, a user can visit the Play Store on a watch and + download a Wear app directly to the watch. +

    + +

    + Generally, a Wear 2.0 app in the Play Store needs + a minimum and target API level of 24 or higher in + the Android manifest file. The minimum SDK level can be 23 + only if you are using the same APK + for Wear 1.0 and 2.0 (and thus have an embedded Wear 1.0 APK). +

    + +

    + Publish Your APKs +

    + +

    + To make your app appear in the on-watch Play Store, upload + the watch APK in the Play Developer Console just as you would any other + APK. If you only have a watch APK and no phone APK, no other steps + are required. +

    + +

    + If you have a phone APK in addition to a watch APK, you must use the + Multi-APK delivery method. +

    + +

    + Run-time + permissions are required. +

    + +

    + Also see + + Standalone Apps. +

    + +

    + Distribution to Wear 2.0 watches +

    + +

    + If you only want your app to be distributed to Wear 2.0 watches, + it is unnecessary to embed the watch APK inside the the phone APK. +

    + +

    + If you want your app to + be distributed to Wear 1.0 watches, you need to embed the + watch APK inside the phone APK, as described directly below. +

    + +

    + Distribution to Wear 1.0 and 2.0 watches +

    + +

    + If you are already distributing your app to Wear 1.0 watches, + follow these steps: +

    + +
      +
    1. Provide a Wear 2.0 (standalone) version of your watch APK that can be made + available in the Play Store on Wear. +
    2. + +
    3. Continue embedding a Wear 1.0 APK in your phone APK, + for use by watches that do not have Wear 2.0. +
    4. +
    + +

    + Specifying a version code +

    + +

    + To ensure that a standalone APK acts as an upgrade to an embedded Wear APK, the + standalone Wear APK's + version code generally should be higher than the embedded Wear APK's version code. + (A phone APK's version code scheme can be independent from that of a watch + APK, although they must be unique.) However, the version codes + of the standalone APK and the embedded Wear APK can be the same if + the APKs are equivalent. If the APKs are not equivalent, + but the version code is the same, then when a watch updates from Wear 1.0 + to 2.0, the watch may get the new APK only after waiting for a + longer-than-expected period of time. +

    + +

    + Note that it currently is not possible to create a single APK that works + on a phone and watch. +

    + +

    + Support in the Gradle file +

    + +

    + If you have a Wear app that is intended for both Wear 1.0 and Wear 2.0, + consider using + product flavors. For example, + if you want to target both SDK version 23 and version 24, + update your Wear module's build.gradle file to include + the following if an existing embedded app has a minimum SDK version of 23: +

    + +
    +android {
    +    // Allows you to reference product flavors in your
    +    // phone module's build.gradle file
    +    publishNonDefault true
    +    ...
    +    defaultConfig
    +    {
    +       // This is the minSdkVersion of the Wear 1.0 embedded app
    +       minSdkVersion 23
    +       ...
    +    }
    +    buildTypes {...}
    +    productFlavors {
    +        wear1 {
    +          // Use the defaultConfig value
    +        }
    +        wear2 {
    +            minSdkVersion 24
    +        }
    +    }
    +}
    +
    + +

    + Then update your phone module’s build.gradle file, replacing + wearApp as follows: +

    + +
    +dependencies {
    +    ...
    +    wearApp project(path: ':wear', configuration: 'wear1Release')
    +}
    +
    + +

    + A + build variant is a combination of the product flavor and build type. + In Android Studio, select the appropriate build variant when + debugging or publishing your app. For example, if wear2 is a + product flavor, select wear2Release as the + release build variant. +

    + +

    + For purposes of code that is Wear 2.0-specific or Wear 1.0-specific, + consider + source sets for build variants. +

    + + +

    + Setting Up Targeting for a Watch +

    + +

    + In your Android Manifest file, you must specify the following feature + restriction: the uses-feature element is set to + android.hardware.type.watch. Do not set + the required attribute to false. + A single APK for Wear and non-Wear devices presently is not supported. +

    + +

    + Thus, if an APK has the following setting, Google Play provides the APK + to watches only: +

    + +
    +<manifest package="com.example.standalone"
    +    xmlns:android="http://schemas.android.com/apk/res/android">
    +    <uses-feature
    +        android:name="android.hardware.type.watch"
    +    ...
    +</manifest>
    +
    + +

    + The android.hardware.type.watch setting above can be + combined with other criteria such as SDK version, screen resolution, and + CPU architecture. Thus, different Wear APKs can target different hardware + configurations. +

    + +

    + Using the Play Developer Console +

    + +

    + Below is an introduction to uploading + a standalone Wear APK to an application listing using the Play Developer + Console. +

    + +

    + If your app supports both Wear 1.0 and Wear 2.0, continue embedding the + Wear 1.0 APK (minimum SDK version of 20, 21, or 22, or 23) in the phone + APK and upload the phone APK. In addition, upload your standalone Wear + 2.0 APK (which has a minimum SDK version of 24). +

    + +

    + Also see + Multiple APK Support and + Manage Your App. + Before uploading an APK as described below, the APK + must be + signed. +

    + +

    + Uploading your APK +

    + +

    + Go to the Play Developer + Console, navigate to your application listing, and select + APK in the left-navigation panel. An APK screen similar to + the following is displayed: +

    + alt_text + +

    + You may need to use advanced mode for uploads, as follows: +

    + +
      +
    • Advanced mode is unnecessary if you only have a Wear 2.0 app and no + phone app. Instead of advanced mode, use simple mode.
    • + +
    • Use advanced mode if you support Wear 1.0 or have a phone app.
    • +
    + +

    + Therefore, on the above APK screen, to determine whether to click + the Switch to advanced mode + button, consider the following: +

    + +
      +
    • If your app does not support Wear 1.0, and only has a watch APK, + upload it using simple mode. +
    • + +
    • If your app does not support Wear 1.0 and has both a watch APK and a + phone APK, click Switch to advanced mode + to upload the watch and phone APKs. +
    • +
    + +

    + See + Simple mode and advanced mode for more information about toggling + between modes. +

    + +

    + Select the appropriate tab (Production, Beta + Testing, or Alpha Testing) for your upload. + Then click + the Upload New APK button and select your standalone + Wear APK for upload. +

    + +

    + Reviewing and publishing +

    + +

    + After you upload your standalone Wear APK and scroll down the resulting + page, the APK is shown in the Current APK table, with a + version number, in a similar way to the following: +

    + alt_text + +

    + Finally, in the Current APK table above, click the line + with the Version to review the APK. The APK + Details panel is displayed. You can verify, for example, that + the number in the Supported Android Devices line is far + fewer than the number would be for a typical phone APK: +

    + alt_text + +

    + When you are ready, publish + your app. +

    diff --git a/docs/html/wear/preview/features/bridger.jd b/docs/html/wear/preview/features/bridger.jd index b7be093ed2987b3c5970d58593110c3dc4dd8542..2d879caeccc2e1e862dc66784c8032f05d64cd46 100644 --- a/docs/html/wear/preview/features/bridger.jd +++ b/docs/html/wear/preview/features/bridger.jd @@ -6,19 +6,26 @@ page.tags="wear-preview"
    -
      +
    +
  • + Existing Method of Preventing Bridging +
  • + +
  • + Using a Dismissal ID to Sync Notification Dismissals +
  • +
    @@ -27,19 +34,20 @@ page.tags="wear-preview" "{@docRoot}training/wearables/notifications/index.html">are bridged (shared) from an app on a companion phone to the watch. If you build a standalone watch app and have a companion phone app, they may duplicate - notifications. The Android Wear 2.0 Preview includes a Bridging mode - feature to handle this problem of repeated notifications. + notifications. The Android Wear 2.0 Preview includes + features to handle this problem of repeated notifications.

    - With the Android Wear 2.0 Preview, developers can change the - behavior of notifications with the following: + With the Android Wear 2.0 Preview, developers can change the behavior of + notifications with one or more of the following:

      -
    • Specifying in the standalone app's Android manifest file that - notifications from the corresponding phone app should not be - bridged to the watch +
    • Specifying a bridging configuration in the manifest file +
    • + +
    • Specifying a bridging configuration at runtime
    • Setting a dismissal ID so notification dismissals are synced across @@ -47,43 +55,201 @@ page.tags="wear-preview"
    -

    - Preventing Bridging with the Bridging Mode Feature +

    + Specifying a Bridging Configuration in the Manifest File

    - To prevent bridging of notifications from a phone app, you can use an + An app's Android manifest file can indicate that notifications from the + corresponding phone app should not be bridged to the watch. Specifically, + to prevent bridging of notifications from a phone app, you can use a + <meta-data> entry in the manifest file of the watch app (e.g. the standalone watch app), as follows:

    -
    +
     com.google.android.wearable.notificationBridgeMode
    -    
    +

    Setting that entry to NO_BRIDGING will prevent bridging:

    -
    -<meta-data android:name="com.google.android.wearable.notificationBridgeMode"
    -                   android:value="NO_BRIDGING" />
    +
    +<meta-data android:name="com.google.android.wearable.notificationBridgeMode"
    +                   android:value="NO_BRIDGING" />
     
    +

    - The default bridging behavior occurs if you do not include the entry or + The default bridging behavior occurs if you do not + include the <meta-data> entry or if you specify a value of BRIDGING instead of NO_BRIDGING.

    -

    - Existing method of preventing bridging +

    + For an existing app, if you are using + Google Cloud Messaging (GCM) or Firebase Cloud + Messaging (FCM) to send notification alerts to devices, + you may already have disabled bridging in case a phone is not + connected at the time of receiving an alert. + In this case, you may still want to dismiss the notification + across other devices when it is dismissed in a watch app. +

    + +

    + The bridging configuration that is set in the manifest takes effect as + soon as a watch app is installed. +

    + +

    + Specifying a Bridging Configuration at Runtime +

    + +

    + This section describes how to specify a bridging configuration at runtime + using the BridgingManager class + (android.support.wearable.notifications.BridgingManager). +

    + +

    + You can set a bridging mode, and optionally set tags for notifications + that are exempt from the bridging mode, using a + BridgingManager object. Specifically, create a + BridgingConfig object and set it as shown in this section, + optionally using the setBridgingEnabled method. If you + specify a bridging configuration at runtime, then if the + setBridgingEnabled method is not set, bridging is enabled by + default. +

    + +

    + Specifying a bridging configuration at runtime overrides a + bridging-related setting in the Android manifest file. +

    + +

    + Disable bridging for all notifications +

    + +

    + You can use the setBridgingEnabled method, as follows: +

    + +
    +BridgingManager.setConfig(context,
    +  new BridgingConfig.Builder(context)
    +    .setBridgingEnabled(false)
    +    .build());
    +
    +

    + If the above setter is not called, the bridging mode defaults to true. + Here is an example of setting tags without using the + setBridgingEnabled method, excluding notifications with a + tag of foo or bar: +

    + +
    +BridgingManager.setConfig(context,
    +  new BridgingConfig.Builder(context)
    +    .addExcludedTag("foo")
    +    .addExcludedTag("bar")
    +    .build());
    +
    +

    + Exempt notifications that are tagged

    +

    + You can disable bridging for all notifications except those with certain + tags. +

    + +

    + For example, you can disable bridging, except for notifications tagged as + foo or bar, with the following: +

    + +
    +BridgingManager.setConfig(context,
    +  new BridgingConfig.Builder(context)
    +    .setBridgingEnabled(false)
    +    .addExcludedTag("foo")
    +    .addExcludedTag("bar")
    +    .build());
    +
    + +

    + As another example, you can disable bridging for all notifications except + for notifications tagged as foo, bar or + baz. +

    + +
    +BridgingManager.setConfig(context,
    +  new BridgingConfig.Builder(context)
    +    .setBridgingEnabled(false)
    +    .addExcludedTags(Arrays.asList("foo", "bar", "baz"))
    +    .build());
    +
    +

    + Enable bridging except for notifications with certain tags +

    + +

    + You can enable bridging for all notifications except those with certain + tags. +

    + +

    + For example, you can enable bridging for all notifications, except for + notifications tagged as foo or bar, with the + following: +

    + +
    +BridgingManager.setConfig(context,
    +  new BridgingConfig.Builder(context)
    +    .setBridgingEnabled(true)
    +    .addExcludedTag("foo")
    +    .addExcludedTag("bar")
    +    .build());
    +
    + +

    + Setting a bridge tag +

    + +

    + A bridge tag can be set on a notification by calling the + setNotificationBridgeTag method as follows: +

    + +
    +BridgingManager.setNotificationBridgeTag(<NotificationCompat.Builder>, <String>);
    +
    + +

    + For example: +

    + +
    +NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
    +<set other fields>;
    +BridgingManager.setNotificationBridgeTag(builder, "foo");
    +Notification notification =  builder.build();
    +
    + +

    + Existing Method of Preventing Bridging +

    +

    An existing way to prevent bridging is with the Notification.Builder class; specify true in the + "http://developer.android.com/reference/android/app/Notification.Builder.html#setLocalOnly(boolean)"> setLocalOnly method.

    @@ -95,12 +261,6 @@ com.google.android.wearable.notificationBridgeMode the watch app may not be installed on all of them.

    -

    - Thus, if bridging should be prevented when the watch app - is installed, use the Bridging mode - feature. -

    Using a Dismissal ID to Sync Notification Dismissals @@ -110,7 +270,7 @@ com.google.android.wearable.notificationBridgeMode If you prevent bridging with the Bridging mode feature, dismissals (cancellations) of notifications are not synced across a user's devices. However, the following methods of the + "http://developer.android.com/reference/android/support/v4/app/NotificationCompat.WearableExtender.html"> NotificationCompat.WearableExtender class enable you to use dismissal IDs:

    @@ -118,7 +278,7 @@ com.google.android.wearable.notificationBridgeMode
     public WearableExtender setDismissalId(String dismissalId)
     public String getDismissalId()
    -    
    +

    To enable a dismissal to be synced, use the setDismissalId() method. For each notification, pass a globally unique ID, as a string, @@ -135,12 +295,12 @@ public String getDismissalId()

     NotificationCompat.WearableExtender wearableExtender =
    -new NotificationCompat.WearableExtender().setDismissalId(“abc123”);
    +new NotificationCompat.WearableExtender().setDismissalId("abc123");
     Notification notification = new NotificationCompat.Builder(context)
     <set other fields>
     .extend(wearableExtender)
     .build();
    -    
    +

    Dismissal IDs work if a watch is paired to an Android phone, but not if a watch is paired to an iPhone. diff --git a/docs/html/wear/preview/features/complications.jd b/docs/html/wear/preview/features/complications.jd index d33fd2a789e5fa4f551643115061f9dc0f821004..c8661188eb0a13de59320feaf5a5de358ae9e7e9 100644 --- a/docs/html/wear/preview/features/complications.jd +++ b/docs/html/wear/preview/features/complications.jd @@ -12,6 +12,13 @@ page.image=/wear/preview/images/complications-main-image.png Adding Complications to a Watch Face +

  • + Permissions + for Complication Data +
  • +
  • + Default Providers for Watch Faces +
  • Exposing Data to Complications @@ -27,12 +34,14 @@ page.image=/wear/preview/images/complications-main-image.png API Additions
  • +

    See Also

    1. Watch Face sample app with complications
    +
    @@ -56,9 +65,12 @@ page.image=/wear/preview/images/complications-main-image.png

    - Along with reviewing this page, download the Android Wear 2.0 Preview - Reference (see the Complications API additions) and review the Javadoc for complications. + You can review the Javadoc for complications by downloading + the Android Wear 2.0 Preview + Reference. Also see the API additions for + complications and the + + behavior changes for Wear 2.0.

    @@ -113,12 +125,12 @@ page.image=/wear/preview/images/complications-main-image.png

    To start receiving complication data, a watch face calls - setActiveComplications within the - WatchFaceService.Engine class with a list of watch face + setActiveComplications, in the + WatchFaceService.Engine class, with a list of watch face complication IDs. A watch face creates these IDs to uniquely identify slots on the watch face where complications can appear, and passes them - to the createProviderChooserIntent method (of the - ProviderChooserIntent class) to allow the user to decide + to the createProviderChooserIntent method + to allow the user to decide which complication should go in which slot.

    @@ -186,6 +198,406 @@ page.image=/wear/preview/images/complications-main-image.png where possible.

    +

    + Permissions for Complication Data +

    + +

    + A watch face must have the following permission + to receive complication data and open the provider chooser: +

    + +
    +com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
    +
    + +

    + Opening the provider chooser +

    + +

    + A watch face that was not granted the above permission will be unable to + start the provider chooser. +

    + +

    + To make it easier to request the permission and start the chooser, the + ComplicationHelperActivity class is available in the + wearable support library. This class should be used instead of + ProviderChooserIntent to start the chooser in almost all + cases. +

    + +

    + Requesting the necessary permission +

    + +

    + To use ComplicationHelperActivity, add it to the watch face + in the + manifest file: +

    + +
    +<activity android:name="android.support.wearable.complications.ComplicationHelperActivity"/>
    +
    + +

    + To start the provider chooser, call the + ComplicationHelperActivity.createProviderChooserHelperIntent + method, to obtain an intent. +

    + +

    + The new intent can be used with either startActivity or + startActivityForResult to launch the chooser. +

    + +

    + Here is an example of using the new intent with + startActivityForResult: +

    + +
    +startActivityForResult(
    +  ComplicationHelperActivity.createProviderChooserHelperIntent(
    +     getActivity(),
    +     watchFace,
    +     complicationId,
    +     ComplicationData.TYPE_LARGE_IMAGE),
    +  PROVIDER_CHOOSER_REQUEST_CODE);
    +
    +

    + When the helper activity is started, the helper activity checks if the + permission was granted. If the permission was not granted, the helper + activity makes a runtime permission request. If the permission request is + accepted (or is unneeded), the provider chooser is shown. +

    + +

    + If startActivityForResult was used with the intent, the + result delivered back to the calling Activity will have a result code of + RESULT_OK if a provider was successfully set, or a result + code of RESULT_CANCELLED if no provider was set. +

    + +

    + In the case where a provider was set, + ComplicationProviderInfo for the chosen provider will be + included in the data intent of the result, as an extra with the key + ProviderChooserIntent#EXTRA_PROVIDER_INFO. +

    + +

    + Receiving complication data +

    + +

    + In general, watch faces need the above permission in order to receive + complication data, but there are some exceptions. Specifically, a watch + face can only receive data from a provider if one of the following is + true: +

    + +
      +
    • The provider is a "safe" system provider, +
    • + +
    • The provider and watch face are from the same app, +
    • + +
    • The provider whitelists the watch face as a "safe" watch face, or +
    • + +
    • The watch face has the permission +
    • +
    + +

    + Lack of appropriate permission +

    + +

    + If none of the above is true, then when ComplicationData + normally would be sent by a provider to a watch face, the system instead + sends data of the type TYPE_NO_PERMISSION. This type + includes an icon (an exclamation mark) and short text ("--") to allow it + to be rendered as if it were of the short text type or icon type, for + convenience. +

    + +

    + When a watch face receives data of TYPE_NO_PERMISSION, the + watch face should render this appropriately, so the user can see that + action is needed for the complication to work. If possible, a tap on a + complication in this state should launch a permission request. This can + be done using + ComplicationHelperActivity.createPermissionRequestHelperIntent, + if the helper activity was added to the watch face app. +

    + +

    + If a user accepts the permission request created by the helper activity, + updates are requested for all the active complications on the watch face + automatically, allowing the TYPE_NO_PERMISSION data to be + replaced by real data. +

    + +

    + Safe providers +

    + +

    + Some system providers are considered "safe", because they only supply + information that the watch face already could obtain itself. +

    + +

    + These providers are listed in the new SystemProviders class + in the wearable support library. Whether a system provider is safe is + stated in the Javadoc (in the Android Wear 2.0 Preview Reference). Also + see System providers for a list. +

    + +

    + Provider-specified safe watch faces +

    + +

    + Providers can specify certain watch faces as "safe" to receive their + data. This is intended to be used only when the watch face will attempt + to use the provider as a default (see below), + and the provider trusts the watch face app. +

    + +

    + To declare watch faces as safe, the provider adds metadata with a key of + android.support.wearable.complications.SAFE_WATCH_FACES. The + metadata value should be a comma-separated list (whitespace is ignored). + Entries in the list can be component names (of + WatchFaceServices, given as if + ComponentName.flattenToString() had been called), or they + can be package names (of apps, in which case every watch face within a + specified app is considered safe). +

    + +

    + For example: +

    + +
    +<meta-data
    +       android:name="android.support.wearable.complications.SAFE_WATCH_FACES"
    +        android:value="
    +          com.app.watchface/com.app.watchface.MyWatchFaceService,
    +          com.anotherapp.anotherwatchface/com.something.WatchFaceService,
    +          com.something.text
    +        "/>
    +
    + +

    + Default Providers for Watch Faces +

    + +

    + Watch faces can specify default providers that are used until a user + selects a provider. +

    + +

    + Setting default providers +

    + +

    + Set default providers using the + setDefaultComplicationProvider method in + WatchFaceService.Engine. This method may be called at any + time, but it does nothing if the user already chose a provider for the + given complication. +

    + +

    + Safe providers +

    + +

    + For most providers, the RECEIVE_COMPLICATION_DATA permission + must be granted to a watch face before data can flow to it. However, some + system providers are considered "safe", and do not require the watch face + to have the permission for data to be sent (see Safe Providers and System providers). These providers may be + preferable to use as defaults, as they can supply data immediately. +

    + +

    + Alternatively, if a watch face has a partnership with a certain provider + and wishes to use it as a default, it can request that the provider list + it as a safe watch face (see Provider-specified safe watch + faces). +

    + +

    + System providers +

    + +

    + The system includes providers that can be used as defaults. These are + listed in the SystemProviders class in the wearable support + library. +

    + +

    + The following table has details about providers that are considered safe: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Method name in the SystemProviders class + + Safety + + Can be the default + + Notes +
    + dateProvider() + + Yes + + Yes + + The standard system date provider. Tapping opens the standard Agenda + app. +
    + currentTimeProvider() + + Yes + + Yes + + The standard system "time and date" provider. No tap action. +
    + batteryProvider() + + Yes + + Yes + + The standard system battery provider. No tap action. +
    + stepCountProvider() + + Yes + + Yes + + Shows a daily total of steps, as reported by + readDailyTotal. +
    + unreadCountProvider() + + Yes + + Yes + + Shows the number of unread notifications in the stream. +
    + worldClockProvider() + + Yes + + Yes + + Will default to London or New York. Can be tapped to change the time + zone. +
    + appsProvider() + + Yes + + Yes + + Will show an "apps" icon at first, which can be tapped to choose an + app. +
    + nextEventProvider() + + No + + Yes (but not a safe provider) + + The standard system "next event" provider. Tapping opens + the standard Agenda app. +

    +
    + +

    Exposing Data to Complications

    @@ -203,6 +615,11 @@ page.image=/wear/preview/images/complications-main-image.png be used to send data back to the system.

    +

    Note: When you provide data as a + complication data provider, the watch face receives the raw values + you send so it can draw them on the watch face. +

    +

    In your app's manifest, declare the service and add an intent filter for the following: @@ -210,7 +627,8 @@ page.image=/wear/preview/images/complications-main-image.png

     android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST
    -
    + +

    The service's manifest entry should also include an android:icon attribute. The provided icon should be a @@ -227,6 +645,21 @@ android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST API Additions).

    +

    + Additionally, a permission for provider services ensures that only the Android Wear system + can bind to provider services. Only the Android Wear system can have this + permission. +

    + +

    + Provider services should add the following to their service declarations + in the manifest: +

    + +
    +android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER"
    +
    +

    Update period

    @@ -283,7 +716,12 @@ android.support.wearable.complications.UPDATE_PERIOD_SECONDS

    - The configuration activity may also be used as an opportunity to request + If a data provider needs a specific permission to access a user's data, + then standard code + for runtime + permissions is needed. + A + configuration activity may be used as an opportunity to request any permissions required by the provider.

    @@ -366,6 +804,11 @@ METADATA_KEY_PROVIDER_CONFIG_ACTION

    The following table describes the types and fields of the ComplicationData object. + If a watch face requests a field that is invalid for a complication type, + a default value for the field is returned. + For example, if a watch face tries to access a Long text + field in a SHORT_TEXT type, the default value for the + Long text field is returned.

    @@ -484,56 +927,80 @@ METADATA_KEY_PROVIDER_CONFIG_ACTION

    - In addition, the following two types have no fields. These two types may - be sent for any complication slot and do not need to be included in a - list of supported types: + In addition, the types in the table below are for empty data and + may be sent for any complication slot. These types have no fields + and do not need to be included in a + list of supported types. These types enable watch + faces to differentiate among the following three cases: +

    + +
      +
    • No provider was chosen +
    • + +
    • The user has selected "empty" for a slot +
    • + +
    • A provider has no data to send +
    • +
    + +

    + Providers should not send TYPE_EMPTY in response to + update requests. Providers should send TYPE_NO_DATA instead. +

    + +

    + Details on the complication types for "empty" data are in the + following table:

    - - - - - - + + +
    - Type - - Required fields + Complication type - Optional fields - - Notes + Description
    - NOT_CONFIGURED - - None - - None + TYPE_NOT_CONFIGURED - Sent when a provider has not yet been chosen for a complication. + Sent by the system when a complication is activated but the user has + not selected a provider, and no default was set. +

    + Cannot be sent by providers. +

    - EMPTY + TYPE_EMPTY - None + Sent by the system when a complication is activated and the user has + chosen "empty" instead of a provider, or when the watch face has + chosen no provider, and this type, as the default. +

    + Cannot be sent by providers. +

    - None + TYPE_NO_DATA - Sent by a provider when there is no data to display in a - complication, or sent by the system when nothing should be shown in a - complication. + Sent by the system when a complication (that has a provider) is + activated, to clear the complication before actual data is received + from the provider. +

    + Should be sent by providers if they have no actual data to send. +

    @@ -695,8 +1162,8 @@ METADATA_KEY_PROVIDER_CONFIG_ACTION

    - The Complications API includes new classes in the Wearable Support - Library. For more information, download the Android Wear 2.0 Preview Reference.

    @@ -717,14 +1184,26 @@ METADATA_KEY_PROVIDER_CONFIG_ACTION
  • - ComplicationText + ComplicationHelperActivity
      -
    • Used to supply text-based values in a - ComplicationData object +
    • Used to request the following permission:
      +com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA
    • -
    • Includes options for time-dependent values, whose text value - depends on the current time +
    • Used instead of ProviderChooserIntent + to start the chooser in almost all cases +
    • +
    +
  • + +
  • + ComplicationManager +
      +
    • A wrapper for the complication manager service, for use by + providers +
    • + +
    • Allows providers to send complication data to the system
  • @@ -742,13 +1221,14 @@ METADATA_KEY_PROVIDER_CONFIG_ACTION
  • - ComplicationManager + ComplicationText
      -
    • A wrapper for the complication manager service, for use by - providers +
    • Used to supply text-based values in a + ComplicationData object
    • -
    • Allows providers to send complication data to the system +
    • Includes options for time-dependent values, whose text value + depends on the current time
  • @@ -756,11 +1236,8 @@ METADATA_KEY_PROVIDER_CONFIG_ACTION
  • ProviderChooserIntent
      -
    • Non-instantiable utility class -
    • - -
    • Includes a method that a watch face can call for starting a - provider chooser (to allow a user to configure complications) +
    • Non-instantiable utility class that is not commonly used; use + ComplicationHelperActivity instead
  • @@ -784,6 +1261,16 @@ METADATA_KEY_PROVIDER_CONFIG_ACTION + +
  • + SystemProviders +
      +
    • Lists system providers that are considered "safe", + because they only supply information that the watch face + already could obtain itself +
    • +
    +
  • diff --git a/docs/html/wear/preview/features/gestures.jd b/docs/html/wear/preview/features/gestures.jd new file mode 100644 index 0000000000000000000000000000000000000000..7806c4e9983683283d3f2f93247b73464d8bff06 --- /dev/null +++ b/docs/html/wear/preview/features/gestures.jd @@ -0,0 +1,323 @@ +page.title=Wrist Gestures +meta.keywords="wear-preview" +page.tags="wear-preview" +page.image=images/cards/card-n-sdk_2x.png + +@jd:body + +

    + +
    + +

    + Wrist gestures can enable quick, one-handed interactions with your app + when use of a touch screen is inconvenient. For example, a user can scroll + through notifications with one hand while holding a cup of water with the + other. Other examples of using wrist gestures when a touch screen would + be inconvenient include: +

    + +
      +
    • In an app for jogging, navigating through vertical screens that show + the steps taken, time elapsed, and current pace +
    • + +
    • At the airport with luggage, scrolling through flight and gate + information +
    • + +
    • Scrolling through news articles +
    • +
    + +

    + To review the wrist gestures on your watch, first confirm gestures are + turned on by selecting Settings > Gestures > Wrist Gestures + On. (Wrist gestures are on by default.) Then complete the + Gestures tutorial on the watch (Settings > Gestures > + Launch Tutorial). +

    + +

    + The following gestures from the Android Wear + Help are unavailable to apps: +

    + +
      +
    • Push wrist down +
    • + +
    • Raise wrist up +
    • + +
    • Shaking the wrist +
    • +
    + +

    + Wrist gestures can be used in these ways: +

    + + + +

    + Each wrist gesture is mapped to an int constant from the + KeyEvent + class, as shown in the following table: +

    + + + + + + + + + + + + + + + + + + + +
    + Gesture + + KeyEvent + + Description +
    + Flick wrist out + + + KEYCODE_NAVIGATE_NEXT + + This key code goes to the next item. +
    + Flick wrist in + + + KEYCODE_NAVIGATE_PREVIOUS + + This key code goes to the previous item. +
    + +

    + Using a WearableListView +

    + +

    + A + WearableListView has predefined actions for occurrences of + wrist gestures when the View has the focus. For more information, see + Best Practices. For information about using + WearableListView, see Creating + Lists. +

    + +

    + Even if you use a WearableListView, you may want to use + constants from the KeyEvent + class. The predefined actions can be overridden by subclassing the + WearableListView and re-implementing the + onKeyDown() callback. The behavior can be disabled entirely + by using setEnableGestureNavigation(false). Also see + + Handling Keyboard Actions. +

    + +

    + Using Key Events Directly +

    + +

    + You can use key events outside of a + WearableListView to trigger new actions in response to gesture + events. Importantly, these gesture events: +

    + +
      +
    • Are recognized when a device is in Active mode +
    • + +
    • Are delivered in the same way as all key events +
    • +
    + +

    + Specifically, these events are delivered to the top Activity, to the View + with keyboard focus. Just as any other key event, a class that relates to + user interaction (such as a View or an Activity) that implements + + KeyEvent.Callback can listen to key events that relate to + wrist gestures. The Android framework calls the View or Activity that has + the focus with the key events; for gestures, the onKeyDown() + method callback is called when gestures occur. +

    + +

    + As an example, an app may override predefined actions in a View or + Activity (both implementing KeyEvent.Callback) as follows: +

    + +
    +public final class GesturesActivity extends Activity {
    +
    + @Override /* KeyEvent.Callback */
    + public boolean onKeyDown(int keyCode, KeyEvent event) {
    +  switch (keyCode) {
    +   case KeyEvent.KEYCODE_NAVIGATE_NEXT:
    +    // Do something that advances a user View to the next item in an ordered list.
    +    return moveToNextItem();
    +   case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:
    +    // Do something that advances a user View to the previous item in an ordered list.
    +    return moveToPreviousItem();
    +  }
    +  // If you did not handle it, let it be handled by the next possible element as deemed by the Activity.
    +  return super.onKeyDown(keyCode, event);
    + }
    +
    + /** Shows the next item in the custom list. */
    + private boolean moveToNextItem() {
    +  boolean handled = false;
    +  …
    +  // Return true if handled successfully, otherwise return false.
    +  return handled;
    + }
    +
    + /** Shows the previous item in the custom list. */
    + private boolean moveToPreviousItem() {
    +  boolean handled = false;
    +  …
    +  // Return true if handled successfully, otherwise return false.
    +  return handled;
    + }
    +}
    +
    + +

    + Best Practices +

    + +
      +
    • Review the KeyEvent + and + KeyEvent.Callback pages for the delivery of key events to + your View and Activity. +
    • + +
    • Keep a consistent directional affordance: +
        +
      • Use "Flick wrist out" for next, "Flick wrist in" for previous +
      • +
      +
    • + +
    • Have a touch parallel for a gesture. +
    • + +
    • Provide visual feedback. +
    • + +
    • Don't use a keycode to implement functionality that would be + counter-intuitive to the rest of the system. For example, do not use + KEYCODE_NAVIGATE_NEXT to cancel an action or to navigate the + left-right axis with flicks. +
    • + +
    • Don't intercept the key events on elements that are not part of the + user interface, for example the Views that are offscreen or partially + covered. This is the same as any other key event. +
    • + +
    • Don't reinterpret repeated flick gestures into your own, new gesture. + It may conflict with the system's "Shaking the wrist" gesture. +
    • + +
    • For a View to receive gesture key events, it must have + focus; see + View::setFocusable(). Because gestures are treated as key events, + they trigger a transition out of "Touch mode" that may do unexpected + things. Therefore, since users may alternate between using touch and + gestures, the + View::setFocusableInTouchmode() method may be necessary. In some + cases, it also may be necessary to use + setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS) so + that when focus changes after a change to or from "Touch mode," your + intended View gets the focus. +
    • + +
    • Use requestFocus() and clearFocus() + carefully: +
        +
      • When calling + requestFocus(), be sure that the View really should have + focus. If the View is offscreen, or is covered by another View, + surprises can occur when gestures trigger callbacks. +
      • + +
      • The + clearFocus() initiates a focus search to find another + suitable View. Depending on the View hierarchy, this search might + require non-trivial computation. It can also end up assigning focus + to a View you don’t expect to receive focus. +
      • +
      +
    • + +
    • Key events are delivered first to the View with focus in the View + hierarchy. If the focused View does not handle the event (i.e., returns + false), the event is not delivered to the parent View, even + if it can receive focus and has a + KeyListener. Rather, the event is delivered to the current Activity + holding the View hierarchy with focus. Thus, it may be necessary to + catch all events at the higher level and then pass relevant codes down. + Alternatively, you might subclass the Activity and override the + + dispatchKeyEvent(KeyEvent event) method to ensure that keys + are intercepted when necessary, or are handled when not handled at + lower layers. +
    • +
    diff --git a/docs/html/wear/preview/features/ime.jd b/docs/html/wear/preview/features/ime.jd index 1301be9afb2a7503e2c97bc4da915a9145c41e2d..b07736f1da30e6d2038a7c2ce23ef9b9e78c8d64 100644 --- a/docs/html/wear/preview/features/ime.jd +++ b/docs/html/wear/preview/features/ime.jd @@ -19,14 +19,14 @@ page.tags="wear"
    -

    Wear 2.0 supports input methods beyond voice by extending the Android +

    Wear 2.0 supports input methods beyond voice by extending the Android Input Method Framework (IMF) to Android Wear. IMF allows for virtual, on-screen - keyboards and other input methods to be used for text entry. The IMF APIs used - for Wear devices are the same as other form factors, though usage is slightly + keyboards and other input methods to be used for text entry. The IMF APIs used + for Wear devices are the same as other form factors, though usage is slightly different due to limited screen real estate.

    -

    Wear 2.0 comes with the system default Input Method Editor (IME) -and opens up the IMF APIs for third-party developers to create custom input +

    Wear 2.0 comes with the system default Input Method Editor (IME) +and opens up the IMF APIs for third-party developers to create custom input methods for Wear.

    @@ -46,17 +46,17 @@ documentation for

    Invoking an Input Method

    -If you are developing an IME for Wear, remember that the -feature is supported only on Android 6.0 (API level 23) and higher versions of -the platform. -To ensure that your IME can only be installed on Wearables that support input +If you are developing an IME for Wear, remember that the +feature is supported only on Android 6.0 (API level 23) and higher versions of +the platform. +To ensure that your IME can only be installed on Wearables that support input methods beyond voice, add the following to your app's manifest:
     <uses-sdk android:minSdkVersion="23" />
     
    -This indicates that your app requires Android 6.0 or higher. +This indicates that your app requires Android 6.0 or higher. For more information, see API Levels - and the documentation for the <uses-sdk> + and the documentation for the <uses-sdk> element.

    To control how your app is filtered from devices that do not support Wear @@ -67,14 +67,14 @@ IMEs (for example, on Phone), add the following to your app's manifest:

    Wear provides user settings on the watch that lets the user to enable multiple - IMEs from the list of installed IMEs. Once the users enable your IME, they + IMEs from the list of installed IMEs. Once the users enable your IME, they can invoke your IME from:

      -
    • A notification or an app using the +
    • A notification or an app using the RemoteInput API.
    • -
    • Wear apps with an +
    • Wear apps with an EditText - field. Touching a text field places the cursor in the field and automatically + field. Touching a text field places the cursor in the field and automatically displays the IME on focus.
    @@ -86,10 +86,10 @@ IMEs (for example, on Phone), add the following to your app's manifest:
    • Set Default Action

      -{@code RemoteInput} +{@code RemoteInput} and Wear apps expect only single-line text entry. The ENTER key should always trigger a call to sendDefaultEditorAction, - which causes the app to dismiss the keyboard and continue on to the next step + which causes the app to dismiss the keyboard and continue on to the next step or action.

    • @@ -97,22 +97,22 @@ and Wear apps expect only single-line text entry. The ENTER key should always tr

      Input methods on Wear consume most of the screen, leaving very little of the app visible; using full-screen mode ensures an optimal user experience regardless - of the app UI. In full-screen mode, an + of the app UI. In full-screen mode, an {@code ExtractEditText} provides a mirrored view of the text field being edited and can be styled to blend with the rest of - the input method UI. For more details on full-screen mode, see + the input method UI. For more details on full-screen mode, see InputMethodService.

    • Handle InputType flags

      -For privacy reasons, at a minimum you should handle the {@code InputType} -flag {@code TYPE_TEXT_VARIATION_PASSWORD} in your IME. When your IME is in -password mode, make sure that your keyboard is optimized for single key press -(auto spelling correction, auto completion and gesture input are disabled). -Most importantly, keyboard in password mode should support ASCII symbols -regardless of the input language. For more details, see +For privacy reasons, at a minimum you should handle the {@code InputType} +flag {@code TYPE_TEXT_VARIATION_PASSWORD} in your IME. When your IME is in +password mode, make sure that your keyboard is optimized for single key press +(auto spelling correction, auto completion and gesture input are disabled). +Most importantly, keyboard in password mode should support ASCII symbols +regardless of the input language. For more details, see Specifying The Input Method Type.

    • @@ -120,9 +120,9 @@ regardless of the input language. For more details, see
    • Provide a key for switching to the next input method

      Android allows users to easily switch between all IMEs supported by the platform. - In your IME implementation, set the boolean + In your IME implementation, set the boolean supportsSwitchingToNextInputMethod = true - to enable your IME to support the switching mechanism + to enable your IME to support the switching mechanism (so that apps can switch to the next platform-supported IME).

    • diff --git a/docs/html/wear/preview/features/notifications.jd b/docs/html/wear/preview/features/notifications.jd index c84a47002f9d1473c054ffab6233dfcfbc907119..b546978a8b9cc480e4c86b42d2feb75afc176c52 100644 --- a/docs/html/wear/preview/features/notifications.jd +++ b/docs/html/wear/preview/features/notifications.jd @@ -1,6 +1,5 @@ page.title=Notification Changes in Android Wear 2.0 -meta.tags="wear", "wear-preview", "notifications" -page.tags="wear" +meta.tags="wear", "wear-preview", "notifications" page.tags="wear" page.image=/wear/preview/images/expanded_diagram.png @@ -12,6 +11,7 @@ page.image=/wear/preview/images/expanded_diagram.png

      This document includes

      1. Visual Updates
      2. +
      3. Inline Action
      4. Expanded Notifications
      5. MessagingStyle
      @@ -67,7 +67,8 @@ material design visual changes. We recommended that you don't set color for bridged notifications. When Wear apps post local notifications, you can work around this by checking - the API level of the device they're running on and using an appropriate color + the API level of the device + they're running on and using an appropriate color for Wear 1.x and a different color for Wear 2.0. @@ -77,6 +78,85 @@ material design visual changes. you must update the text of your notification.
    + +

    Inline Action

    + + +

    + Wear 2.0 now supports inline action, which allows users to take actions on a + notification from within the notification stream card. On Wear, the inline + action appears as an additional button displayed at the bottom of the notification. +

    +

    + Inline actions are optional but recommended for cases in which users are likely + to take an action on a notification after viewing the contents in the + notification stream card (without going to the + expanded notification). + Examples of good use cases for inline action on a notification include: replying to a + text message, stopping a fitness activity, and archiving an email message. +

    + +

    + A notification can provide only one inline action. + To display the inline action as an additional button in the notification, set + the {@code setHintDisplayActionInline()} + method to true. When a user taps the inline action, the system invokes + the intent that you specified in the notification action. +

    + +

    Adding an inline action

    +

    + The following code example shows how to create a notification with an inline + reply action: +

    + +
      +
    1. Create an instance of + {@code RemoteInput.Builder} + that you can add to your notification action. This class's constructor accepts a + string that the system uses as the key for the text input. Later, your app + uses that key to retrieve the text of the input. + +
      +String[] choices = context.getResources().getStringArray(R.array.notification_reply_choices);
      +    choices = WearUtil.addEmojisToCannedResponse(choices);
      +  RemoteInput remoteInput = new RemoteInput.Builder(Intent.EXTRA_TEXT)
      +        .setLabel(context.getString(R.string.notification_prompt_reply))
      +        .setChoices(choices)
      +        .build();
      +
      + +
    2. + +
    3. + Use the {@code addRemoteInput()} + method to attach the {@code RemoteInput} + object to an action. + +
      +NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.Builder(
      +        R.drawable.ic_full_reply, R.string.notification_reply, replyPendingIntent);
      +    actionBuilder.addRemoteInput(remoteInput);
      +    actionBuilder.setAllowGeneratedReplies(true);
      +
      +
    4. + +
    5. + Add a hint to display the reply action inline, and use the + {@code addAction} + method to add this action to the notification. + +
      +// Android Wear 2.0 requires a hint to display the reply action inline.
      +    Action.WearableExtender actionExtender =
      +        new Action.WearableExtender()
      +            .setHintLaunchesActivity(true)
      +            .setHintDisplayActionInline(true);
      +    wearableExtender.addAction(actionBuilder.extend(actionExtender).build());
      +
      +
    6. +
    +

    Expanded Notifications

    Android Wear 2.0 introduces expanded notifications, which provide substantial additional content and actions for each notification. @@ -152,51 +232,52 @@ action in the notification unless a different action is specified using

    MessagingStyle

    -

    If you have a chat messaging app, your notifications should use -{@code Notification.MessagingStyle}, - which is new in Android N. Wear 2.0 uses the chat messages included - in a {@code MessagingStyle} notification - - (see {@code addMessage()}) to provide - a rich chat app-like experience in the expanded notification. +

    + If you have a chat messaging app, your notifications should use + {@code NotificationCompat.MessagingStyle}, + which is new in Android 7.0. Wear 2.0 uses the chat messages included in a + {@code MessagingStyle} notification + (see {@code addMessage()}) + to provide a rich chat app-like experience in the expanded notification.

    -

    Note: {@code MessagingStyle} +

    Note: {@code MessagingStyle} expanded notifications require that you have at least version 1.5.0.2861804 of the Android Wear app - on your paired Android phone. That version will be available within the next - few weeks in the Play Store. + on your paired Android phone.

    Smart Reply

    -

    Wear 2.0 also introduces Smart Reply -for {@code MessagingStyle} notifications. +

    Wear 2.0 also introduces Smart Reply for + {@code MessagingStyle} notifications. Smart Reply provides the user with contextually relevant, touchable choices in the expanded notification and in {@code RemoteInput}. These augment the fixed list of choices that the developer provides in - {@code RemoteInput} - using the - {@code setChoices()} method. + {@code RemoteInput} + using the + {@code setChoices()} method.

    -

    By enabling Smart Reply for your MessagingStyle notifications, - you provide users with a fast (single tap), discreet (no speaking aloud), and - reliable way to respond to chat messages. +

    Smart Reply provides users with a fast (single tap), discreet (no speaking aloud), + private (messages received by a user never leave the watch), and reliable (no + internet connection needed) way to respond to chat messages.

    -

    Responses generated by Smart Reply are shown in addition to those set using the - {@code setChoices()} method. +

    + Smart Reply responses are generated by an entirely on-watch machine learning + model using the context provided by the MessagingStyle notification. No user + notification data is sent to Google servers to generate Smart Reply responses.

    +

    To enable Smart Reply for your notification action, you need to do the following:

      -
    1. Use {@code Notification.MessagingStyle}. +
    2. Use {@code NotificationCompat.MessagingStyle}.
    3. -
    4. Call the method {@code setAllowGeneratedReplies()} for the notification action. - For more information, see the downloadable - API reference. +
    5. Call the method {@code setAllowGeneratedReplies(true)} + for the notification action.
    6. Ensure that the notification action has a {@code RemoteInput} @@ -236,3 +317,29 @@ Notification noti = new NotificationCompat.Builder() // 3) add an action with RemoteInput .extend(new WearableExtender().addAction(action)).build(); + +

      Adding images to a MessagingStyle notification

      +

      + You can add images to a notification message by setting the appropriate MIME + type and placing the URI to the image in {@code NotificationCompat.MessagingStyle.Message.} + {@code setData()} method. +

      +

      + Here is the code snippet to set data of type image in a notification: +

      +
      +NotificationCompat.MessagingStyle.Message message = new Message("sticker", 1, "Jeff")
      +                      .setData("image/png", stickerUri);
      +
      +  NotificationCompat notification = new NotificationCompat.Builder()
      +             .setStyle(new NotificationComapt.MessagingStyle("Me")
      +             .addMessage(message)
      +             .build());
      +
      +
      +

      + In the above code snippet the variable stickerUri is a Uri that + points to a publicly-accessible location, as described here + . +

      \ No newline at end of file diff --git a/docs/html/wear/preview/features/standalone-apps.jd b/docs/html/wear/preview/features/standalone-apps.jd new file mode 100644 index 0000000000000000000000000000000000000000..5c1930dedf86685b6da5c376aa0b7dd8fdac92b1 --- /dev/null +++ b/docs/html/wear/preview/features/standalone-apps.jd @@ -0,0 +1,499 @@ +page.title=Standalone Apps +meta.keywords="wear-preview" +page.tags="wear-preview" +page.image=images/cards/card-n-sdk_2x.png + +@jd:body + + + +

      + In Android Wear 2.0, apps can work independently of a phone. Users can + complete more tasks on a watch, without access to an Android or iOS + phone. +

      + +

      + Planning Your Phone and Watch Apps +

      + +

      + A watch APK targeting Wear 2.0 should not be embedded in a phone APK. + For more information, see + + App Distribution. +

      + +

      + Generally, the minimum and target API level for a standalone app, and + for Wear 2.0, is level 24. The minimum SDK level can be 23 + only if you are using the same APK + for Wear 1.0 and 2.0 (and thus have an embedded Wear 1.0 APK). +

      + +

      + If you build a standalone Wear 2.0 APK and will continue to have a + Wear 1.0 APK, please do both of the following: +

      + +
        +
      • Provide a standalone version of the Wear APK, and +
      • + +
      • Continue embedding a version of the Wear APK in your phone APK +
      • +
      + +

      + Caution: For the Wear 2.0 Developer Preview, if you + publish an update to your production phone APK that has removed an embedded + Wear APK, production users who update the phone APK before installing + your standalone Wear APK will lose their existing Wear app and its data. + Therefore, it's important that you continue to embed + your watch APK into your phone APK. +

      + +

      + + Run-time permissions are required for standalone apps. +

      + +

      + Shared code and data storage +

      + +

      + Code can be shared between a Wear app and a phone app. Optionally, code + that is specific to a form factor can be in a separate module. +

      + +

      + For example, common code for networking can be in a shared library. +

      + +

      + You can use standard Android storage APIs to store data locally. + For example, you can use + the + SharedPreferences APIs, SQLite, or internal storage (as you would in + the case of a phone). +

      + +

      + Detecting your phone app or watch app +

      + +

      + If a user of your watch app needs your phone app, your watch app can + detect if the phone app is available. Using the + CapabilityApi, your phone app or watch app can advertise its presence + to a paired device. It can do so statically and dynamically. When an app + is on a node in a user's Wear network (i.e., on a phone, paired watch, or + in the cloud), the CapabilityApi enables another + app to detect if it is installed. For more information, see + Advertise capabilities. +

      + +

      + If your phone app is unavailable, your can check if the Play Store is + available on the phone, as described below, before directing the user to + go to the Play Store (to install your phone app). +

      + +

      + Checking for Play Store availability on a phone +

      + +

      + iPhones and some Android phones lack the Play Store. A standalone Wear + app can check if the paired phone has the Play Store, before directing a + user to go there to install your phone app. The + PlayStoreAvailability class contains a + getPlayStoreAvailabilityOnPhone() method that enables your + Wear app to check if a companion phone has the Play Store. +

      + +

      + More information about the PlayStoreAvailability class is + available when you + download the Android Wear 2.0 Preview Reference. Here is a snippet + that uses the getPlayStoreAvailabilityOnPhone() method to + determine if the paired phone has the Play Store: +

      + +
      +int playStoreAvailabilityOnPhone =
      +PlayStoreAvailability.getPlayStoreAvailabilityOnPhone(context);
      +
      + +

      + The value returned by the getPlayStoreAvailabilityOnPhone() + method is one of the following: +

      + + + + + + + + + + + + + + + + + + + + + +
      + Return value + + Description +
      + PLAY_STORE_ON_PHONE_AVAILABLE + + The Play Store is available on the companion phone. +
      + PLAY_STORE_ON_PHONE_UNAVAILABLE + + The Play Store is not available on the companion phone. +
      + PLAY_STORE_ON_PHONE_ERROR_UNKNOWN + + An error occurred in the check for the Play Store; another check + should be made later. +
      + +

      + Network Access and Cloud Messaging +

      + +

      + Android Wear apps can make their own network requests. When a watch has a + Bluetooth connection to a phone, the watch's network traffic is proxied + through the phone. When a phone is unavailable, Wi-Fi and cellular + networks are used, depending on the hardware. The Wear platform handles + transitions between networks. A watch's network access thus does not + require the + Wearable Data Layer API. +

      + +

      + For sending notifications, apps can directly use Firebase Cloud Messaging + (FCM), which replaces Google Cloud Messaging, or continue to use GCM. +

      + +

      + No APIs for network access or FCM are specific to Android Wear. + Refer to the existing documentation about + connecting to a network and cloud messaging. +

      + +

      + You can use protocols such as HTTP, TCP, and UDP. However, + the + android.webkit APIs are not available. Therefore, + use of cookies is available by reading and writing headers on + requests and responses, but the + CookieManager class is not available. +

      + +

      + FCM works well with + + Doze. +

      + +

      + Additionally, we recommend using the following: +

      + + + +

      + For foreground use cases, we currently recommend that you make a + request for an unmetered network. Here is an example of using + the multi-networking APIs to request an unmetered network: +

      + +
      +ConnectivityManager.NetworkCallback networkCallback =
      +  new ConnectivityManager.NetworkCallback() {
      +    @Override
      +    public void onAvailable(Network network) {
      +      // access network
      +      }
      +    };
      +ConnectivityManager connectivityManager =
      +  (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
      +
      +connectivityManager.requestNetwork(new NetworkRequest.Builder()
      +  .addCapability(NET_CAPABILITY_NOT_METERED)
      +  .build(), networkCallback);
      +
      + +

      + We also recommend setting a timer for frontend scenarios + to prevent a user from potentially waiting for a long time. + When the network is no longer needed, or if the timer fires, + the network callback needs to be unregistered: +

      + +
      +connectivityManager.unregisterNetworkCallback(networkCallback):
      +
      + +

      + A Wear app can communicate with a phone app using the Wearable + Data Layer API, but connecting to a network using that API is + discouraged. +

      + +

      + Obtaining only the necessary data +

      + +

      + When obtaining data from the cloud, get only the necessary data. + Otherwise, you may introduce unnecessary latency, memory use, and battery + use. +

      + +

      + When a watch is connected over a Bluetooth LE connection, your app may + have access to a bandwidth of only 10 kilobytes per second. Therefore, + the following steps are recommended: +

      + +
        +
      • Audit your network requests and responses for extra data that only is + for a phone app +
      • + +
      • Shrink large images before sending them over a network to a watch +
      • +
      + +

      + Using Background Services +

      + +

      + To ensure that background tasks are correctly executed, they must account + for + Doze. In Android 6.0, Doze and App Standby resulted in significant + improvements to battery life by allowing devices to enter deep sleep when + idle and stationary. +

      + +

      + Doze is enhanced + in Android Nougat and Android Wear 2.0. When a screen turns off or enters + ambient mode for a long enough time, a subset of Doze can occur and + background tasks may be deferred for certain periods. Later, when a + device is stationary for an extended time, regular Doze occurs. +

      + +

      + You should schedule jobs with the + JobScheduler API, which enables your app to register for Doze-safe + code execution. When scheduling jobs, you can select constraints such as + periodic execution and the need for connectivity or device charging. + It is important to configure jobs in a way that does not adversely + impact battery life. Jobs should use a + + JobInfo.Builder object to provide constraints and metadata, e.g. with + one or more of the following methods for a task: +

      + +
        +
      • To schedule a task that requires networking, use + setRequiredNetworkType(int networkType), specifying + NETWORK_TYPE_ANY or NETWORK_TYPE_UNMETERED; + note that NETWORK_TYPE_UNMETERED is for large data transfers + while NETWORK_TYPE_ANY is for small transfers +
      • + +
      • To schedule a task while charging, use + setRequiresCharging(boolean requiresCharging) +
      • + +
      • For specifying that a device is idle for a task, use + setRequiresDeviceIdle(boolean requiresDeviceIdle); this + method can be useful for lower-priority background work or + synchronization, especially when used with + setRequiresCharging +
      • +
      + +

      + Note that some low-bandwidth networks, such as Bluetooth LE, are + considered metered. +

      + +

      + Scheduling with constraints +

      + +

      + You can schedule a task that requires constraints. In the example below, + a JobScheduler object activates MyJobService + when the following constraints are met: +

      + +
        +
      • Unmetered networking +
      • + +
      • Device charging +
      • +
      + +

      + You can use the builder method setExtras to attach a bundle + of app-specific metadata to the job request. When your job executes, this + bundle is provided to your job service. Note the MY_JOB_ID + value passed to the JobInfo.Builder constructor. This + MY_JOB_ID value is an app-provided identifier. Subsequent + calls to cancel, and subsequent jobs created with that same value, will + update the existing job: +

      + +
      +JobInfo jobInfo = new JobInfo.Builder(MY_JOB_ID,
      +        new ComponentName(this, MyJobService.class))
      +        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
      +        .setRequiresCharging(true)
      +        .setExtras(extras)
      +        .build();
      +((JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE))
      +        .schedule(jobInfo);
      +
      + +

      + Below is an implementation of + JobService to handle the job above. When the job executes, a + JobParameters object is passed into the + onStartJob method. The JobParameters object + enables you to get the job ID value along with any extras bundle provided + when scheduling the job. The onStartJob method is called on + the main application thread, and therefore any expensive logic should be + run from a separate thread. In the example, an AsyncTask is + used to run code in the background. When work is complete, you would call + the jobFinished method to notify JobScheduler + that the task is done: +

      + +
      +public class MyJobService extends JobService {
      +    @Override public boolean onStartJob(JobParameters params) {
      +        new JobAsyncTask().execute(params);
      +        return true;
      +    }
      +
      +    private class JobAsyncTask extends AsyncTask
      +
      + +

      + Cloud Notifications Using FCM +

      + +

      + FCM is the recommended way to send notifications to a watch. +

      + +

      + Provide for messages from FCM by collecting a registration token for a + device when your Wear app runs. Then include the token as part of the + destination when your server sends messages to the FCM REST endpoint. FCM + sends messages to the device identified by the token. +

      + +

      + An FCM message is in JSON format and can include one or both of the + following payloads: +

      + +
        +
      • + Notification payload. When a notification payload is + received by a watch, the data is displayed to a user directly in the + notification stream. When the user taps the notification, your app is + launched. +
      • + +
      • + Data payload. The payload has a set of custom + key/value pairs. The payload and is delivered as data to your Wear app. +
      • +
      + +

      + For more information and examples of payloads, see About + FCM Messages. +

      + +

      + Notifications from a Companion Phone +

      + +

      + By default, notifications are bridged (shared) from a phone app to a + watch. If you have a standalone Wear app and a corresponding phone app, + duplicate notifications can occur. For example, the same notification + from FCM, received by both a phone and a watch, could be + displayed by both devices independently. +

      + +

      + For information about preventing duplicate notifications, see Bridging + Mode for Notifications. +

      diff --git a/docs/html/wear/preview/features/ui-nav-actions.jd b/docs/html/wear/preview/features/ui-nav-actions.jd index 1ba275fa97c14c86d07d7e05690c818708451756..fb1426401695a74451b55d5322e8c60967142b72 100644 --- a/docs/html/wear/preview/features/ui-nav-actions.jd +++ b/docs/html/wear/preview/features/ui-nav-actions.jd @@ -12,7 +12,7 @@ page.image=/wear/preview/images/card_drawer.png
      1. Create a Drawer Layout
      2. Initialize the Drawer List
      3. -
      4. Create a Custom View Drawer
      5. +
      6. Create a Custom Drawer View
      7. Listen for Drawer Events
      8. Peeking Drawers
      @@ -37,8 +37,8 @@ page.image=/wear/preview/images/card_drawer.png

    As part of the Material Design - for Android Wear, Wear 2.0 adds interactive navigation and action drawers. - The navigation drawer appears at the top of the screen and lets users jump to + for Android Wear, Wear 2.0 adds interactive navigation and action drawers. + The navigation drawer appears at the top of the screen and lets users jump to different views within the app, similar to the navigation drawer on a phone. The action drawer appears at the bottom of the screen and provides context-specific actions for the user, @@ -59,7 +59,8 @@ the opposite direction.

    This lesson describes how to implement action and navigation drawers in your -app using the {@code WearableDrawerLayout} APIs. +app using the {@code WearableDrawerLayout} APIs. For more information, see the +downloadable API reference.

    Create a Drawer Layout

    @@ -99,41 +100,44 @@ To add an action or a navigation drawer, declare your user interface with a </android.support.wearable.view.drawer.WearableDrawerLayout> +

    Initialize the Drawer List

    One of the first things you need to do in your activity is to initialize the drawers list of items. You should implement {@code WearableNavigationDrawerAdapter} to populate the navigation drawer contents. To populate the action drawer with -a list of actions, inflate an XML file into the Menu (via MenuInflater).

    +a list of actions, inflate an XML file into the Menu (via {@code MenuInflater}). +

    The following code snippet shows how to initialize the contents of your drawers:

    +
     public class MainActivity extends  WearableActivity implements
     WearableActionDrawer.OnMenuItemClickListener{
         private WearableDrawerLayout mwearableDrawerLayout;
         private WearableNavigationDrawer mWearableNavigationDrawer;
         private WearableActionDrawer mWearableActionDrawer;
    -    
    +
         ...
    -    
    +
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
    -        
    +
             ......
    -        
    -        
    +
    +
             // Main Wearable Drawer Layout that wraps all content
             mWearableDrawerLayout = (WearableDrawerLayout) findViewById(R.id.drawer_layout);
    -        
    +
             // Top Navigation Drawer
             mWearableNavigationDrawer = (WearableNavigationDrawer) findViewById(R.id.top_navigation_drawer);
             mWearableNavigationDrawer.setAdapter(new YourImplementationNavigationAdapter(this));
     
             // Peeks Navigation drawer on the top.
             mWearableDrawerLayout.peekDrawer(Gravity.TOP);
    -        
    +
             // Bottom Action Drawer
             mWearableActionDrawer = (WearableActionDrawer) findViewById(R.id.bottom_action_drawer);
     
    @@ -149,44 +153,58 @@ WearableActionDrawer.OnMenuItemClickListener{
     }
     
     
    -

    Create a Custom View Drawer

    - -

    To use custom views in drawers, add WearableDrawerView to the -WearableDrawerLayout. To set the contents of the drawer, call -setDrawerContent(View) - instead of manually adding the view to the hierarchy. You must also specify the - drawer position with the android:layout_gravity attribute.

    -

    The following example specifies a top drawer:

    + +

    Create a Custom Drawer View

    + +

    To use custom views in drawers, add WearableDrawerView to the +WearableDrawerLayout. To set the peek view and drawer contents, add + them as children of the {@code WearableDrawerView} and specify their IDs in the + {@code peek_view} and {@code drawer_content} attributes respectively. You must + also specify the drawer position with the {@code android:layout_gravity} + attribute.

    + +

    The following example specifies a top drawer with peek view and drawer +contents:

    +
    -<android.support.wearable.view.drawer.WearableDrawerLayout>
    -    <FrameLayout 
    -    android:id=”@+id/content” />
    -
    -    <WearableDrawerView
    -        android:layout_width=”match_parent”
    -        andndroid:layout_height=”match_parent”
    -        android:layout_gravity=”top”>
    -        <FrameLayout 
    -            android:id=”@+id/top_drawer_content” />
    -    </WearableDrawerView>
    -</android.support.wearable.view.drawer.WearableDrawerView>
    +   <android.support.wearable.view.drawer.WearableDrawerView
    +        android:layout_width="match_parent"
    +        android:layout_height="match_parent"
    +        android:layout_gravity="top"
    +        android:background="@color/red"
    +        app:drawer_content="@+id/drawer_content"
    +        app:peek_view="@+id/peek_view">
    +        <FrameLayout
    +            android:id="@id/drawer_content"
    +            android:layout_width="match_parent"
    +            android:layout_height="match_parent">
    +            <!-- Drawer content goes here.  -->
    +        </FrameLayout>
    +        <LinearLayout
    +            android:id="@id/peek_view"
    +            android:layout_width="wrap_content"
    +            android:layout_height="wrap_content"
    +            android:layout_gravity="center_horizontal"
    +            android:orientation="horizontal">
    +            <!-- Peek view content goes here.  -->
    +        <LinearLayout>
    +    </android.support.wearable.view.drawer.WearableDrawerView>
     
     

    Listen for Drawer Events

    -

    To listen for drawer events, call {@code setDrawerStateCallback()}on your +

    To listen for drawer events, call {@code setDrawerStateCallback()} on your {@code WearableDrawerLayout} and pass it an implementation of {@code WearableDrawerLayout.DrawerStateCallback}. This interface provides callbacks for drawer events such as onDrawerOpened(), onDrawerClosed(), and onDrawerStatechanged().

    Peeking Drawers

    -

    To set the drawers to temporarily appear, call peekDrawer() on +

    To set the drawers to temporarily appear, call peekDrawer() on your {@code WearableDrawerLayout} and pass it the {@code Gravity} of the drawer. This feature is especially useful because it allows immediate access to the - alternate drawer views or actions associated with it.

    + alternate drawer views or actions associated with it:

    + +
    {@code mWearableDrawerLayout.peekDrawer(Gravity.BOTTOM);}
    -
    {@code mWearableDrawerLayout.peekDrawer(Gravity.BOTTOM);}
    -

    You can also call {@code setPeekContent()} on your drawer to display a custom - view when the drawer is peeking.

    diff --git a/docs/html/wear/preview/features/wearable-recycler-view.jd b/docs/html/wear/preview/features/wearable-recycler-view.jd new file mode 100644 index 0000000000000000000000000000000000000000..f28a4722377e7bab3b9612bafd9d9975557635f2 --- /dev/null +++ b/docs/html/wear/preview/features/wearable-recycler-view.jd @@ -0,0 +1,223 @@ + +page.title=Curved Layout +meta.tags="wear", "wear-preview", "RecyclerView" +page.tags="wear" + +@jd:body + + + + + +

    + Wear 2.0 introduces the {@code WearableRecyclerView} class for displaying + and manipulating a vertical list of items optimized for round displays. + {@code WearableRecyclerView} extends the existing + {@code RecyclerView} + class to provide a curved layout and a circular scrolling gesture in wearable apps. +

    + + +

    + You can adapt to this interface in your wearable app by creating a new + {@code WearableRecyclerView} container. +

    + +

    + You should decide whether to use a {@code WearableRecyclerView}, based on + the kind of user experience you want to provide. We recommend using the + {@code WearableRecyclerView} for a simple, long list of items, such as an + application launcher, or a list contacts. Each item might have a short string + and an associated icon. Alternatively, each item might have only a string or + an icon. We do not recommend using a {@code WearableRecyclerView} for short + or complex lists. +

    + +

    + This document describes how to create a curved layout for your scrollable items + and properly align them along the curve. +

    + + +

    Creating a Curved Layout

    +

    To create a curved layout for scrollable items in your wearable app: +

    +
      +
    • Use {@code WearableRecyclerView} as your main container in the relevant + xml layout. +
    • + +
    • By default, {@code WearableRecyclerView} uses the {@code + DefaultOffsettingHelper} class to offset items in a curved layout on round + devices. If you wish to implement your own offsetting logic, you can extend the + abstract {@code WearableRecyclerView.OffsettingHelper} class and attach it to + the {@code WearableRecyclerView} using {@code + WearableRecyclerView.setOffsettingHelper} method. + +
      +      CircularOffsettingHelper circularHelper = new CircularOffsettingHelper();
      +      mRecyclerView.setOffsettingHelper(circularHelper);
      +    
      + +
      +      public class CircularOffsettingHelper extends OffsettingHelper {
      +
      +        @Override
      +        public void updateChild(View child, WearableRecyclerView parent) {
      +          int progress = child.getTop() / parent.getHeight();
      +          child.setTranslationX(-child.getHeight() * progress);
      +         }
      +      }
      +    
      + +
    • + +
    + +

    + Note: {@code DefaultOffsettingHelper} class + offsets the child items + along a predefined UX curve, but the operation can cut off part of the child + view if it is not scaled down accordingly. This is because the default curve + attempts to fit 5 items on the screen, regardless of their size. + If you do not wish to scale your items, you should consider additional padding. +

    + +

    Examples

    +

    + The following code example demonstrates how to add {@code WearableRecyclerView} + to a layout: +

    +
    +<android.support.wearable.view.WearableRecyclerView
    +   xmlns:android="http://schemas.android.com/apk/res/android"
    +   xmlns:tools="http://schemas.android.com/tools"
    +   android:id="@+id/recycler_launcher_view"
    +   android:layout_width="match_parent"
    +   android:layout_height="match_parent"
    +   android:scrollbars="vertical" />
    + 
    + + +

    + To customize the appearance of the children while scrolling (for example, + scale the icons and text while the items scroll away from the center), extend + the {@code DefaultOffsettingHelper} and override the {@code updateChild } + method. It is important to call the {@code super.updateChild(child, parent)} to + offset the children along the curve. However, if for any particular child you do + not wish them to follow a curve, you can chose not to call the super method for + that particular child. +

    + +
    +
    +public class MyOffsettingHelper extends DefaultOffsettingHelper {
    +
    +   /** How much should we scale the icon at most. */
    +   private static final float MAX_ICON_PROGRESS = 0.65f;
    +
    +   private float mProgressToCenter;
    +
    +   public OffsettingHelper() {}
    +
    +   @Override
    +
    +   public void updateChild(View child,  WearableRecyclerView parent) {
    +       super.updateChild(child, parent);
    +
    +
    +       // Figure out % progress from top to bottom
    +       float centerOffset = ((float) child.getHeight() / 2.0f) /  (float) mParentView.getHeight();
    +       float yRelativeToCenterOffset = (child.getY() / mParentView.getHeight()) + centerOffset;
    +
    +       // Normalize for center
    +       mProgressToCenter = Math.abs(0.5f - yRelativeToCenterOffset);
    +       // Adjust to the maximum scale
    +       mProgressToCenter = Math.min(mProgressToCenter, MAX_ICON_PROGRESS);
    +
    +       child.setScaleX(1 - mProgressToCenter);
    +       child.setScaleY(1 - mProgressToCenter);
    +   }
    +}
    +
    +
    +
    + + +

    Adding a Circular Scrolling Gesture

    + +

    + By default, circular scrolling is disabled in the {@code + WearableRecyclerView}. If you want to enable circular scrolling gesture + in your child view, use the {@code WearavleRecyclerView}’s {@code + setCircularScrollingGestureEnabled()} method. You can also customize the + circular scrolling gesture by defining one or both of the following: +

    + +
      +
    • How many degrees the user has to rotate by to scroll through one screen height. + This effectively influences the speed of the scolling - + {@code setScrollDegreesPerScreen} - the default value is set at 180 degrees. +
    • + +
    • + The width of a virtual ‘bezel’ near the the edge of the screen in which the + gesture will be recognized - {@code setBezelWidth} - the default value is set + at 1. This is expressed as a fraction of the radius of the view. +
    + + +

    The following code snippet shows how to set these methods:

    + +
    +  setCircularScrollingGestureEnabled(true);
    +  setBezelWidth(0.5f);
    +  setScrollDegreesPerScreen(90);
    +
    + +

    Anchoring Children to the Curve

    + +

    + To ensure that the layout for WearableRecyclerView is adaptable to different + types of child views, the WearableRecyclerView class, by default, chooses the + middle left edge (X=0, Y=Half the child height) as the anchor coordinates for + the child item. Using the default anchor coordinates can result in offsetting + the child items from the left edge of the watch face. To customize the anchor + coordinates of your child view along the curve, you can overwrite the + {@code adjustAnchorOffsetXY()} method. You can calculate the X (horizontal) + and Y (vertical) offset of the child item, and set it using the + {@code adjustAnchorOffsetXY()} method to properly align items + along the curve. The coordinates should be with relation to the child view. +

    + +

    +

    Figure 1. Imaginary UX curve and anchor points on the curve.

    + +

    + The code snippet below, calculates the X offset for a child item in which the + width of the icon is same as the height of the child item. In this case, the + anchor coordinates for the child item are at the center of the icon. + +

    + + +
    + @Override
    +  protected void adjustAnchorOffsetXY(View child, float[] anchorOffsetXY) {
    +    anchorOffsetXY[0] = child.getHeight() / 2.0f;
    +  }
    +
    + + diff --git a/docs/html/wear/preview/images/alignment.png b/docs/html/wear/preview/images/alignment.png new file mode 100644 index 0000000000000000000000000000000000000000..525b3341789a86aaf9d2e6380efcb72739c2e838 Binary files /dev/null and b/docs/html/wear/preview/images/alignment.png differ diff --git a/docs/html/wear/preview/images/apk-details.png b/docs/html/wear/preview/images/apk-details.png new file mode 100644 index 0000000000000000000000000000000000000000..eb3b8591f53fa919c95fa3acdac602b45587ac15 Binary files /dev/null and b/docs/html/wear/preview/images/apk-details.png differ diff --git a/docs/html/wear/preview/images/apk-tabs.png b/docs/html/wear/preview/images/apk-tabs.png new file mode 100644 index 0000000000000000000000000000000000000000..949b98f75b7d35ad78a87b51da9046073625e580 Binary files /dev/null and b/docs/html/wear/preview/images/apk-tabs.png differ diff --git a/docs/html/wear/preview/images/center_align.png b/docs/html/wear/preview/images/center_align.png new file mode 100644 index 0000000000000000000000000000000000000000..ca88ad77bac4c6fc9c98214c2823c3c77a90e5d5 Binary files /dev/null and b/docs/html/wear/preview/images/center_align.png differ diff --git a/docs/html/wear/preview/images/current-apk.png b/docs/html/wear/preview/images/current-apk.png new file mode 100644 index 0000000000000000000000000000000000000000..2545f925f60812cdb52b87a303fd73af94f68655 Binary files /dev/null and b/docs/html/wear/preview/images/current-apk.png differ diff --git a/docs/html/wear/preview/images/inline_action.png b/docs/html/wear/preview/images/inline_action.png new file mode 100644 index 0000000000000000000000000000000000000000..7ecaafeb25441ff8fd4c3b2b26725901774d444c Binary files /dev/null and b/docs/html/wear/preview/images/inline_action.png differ diff --git a/docs/html/wear/preview/images/wrv_new.png b/docs/html/wear/preview/images/wrv_new.png new file mode 100644 index 0000000000000000000000000000000000000000..c413c59a77c35d2cc6d0ed9ffd14b9a4d7be2a73 Binary files /dev/null and b/docs/html/wear/preview/images/wrv_new.png differ diff --git a/docs/html/wear/preview/index.jd b/docs/html/wear/preview/index.jd index 4b3c1f2ed86a2b759334d4633f8d435704e1e328..629257736e148e5d41779a7825ecc21c77b39346 100644 --- a/docs/html/wear/preview/index.jd +++ b/docs/html/wear/preview/index.jd @@ -7,16 +7,6 @@ header.hide=1 footer.hide=1 @jd:body - -
    @@ -55,7 +45,7 @@ footer.hide=1
    - @@ -90,7 +95,7 @@ page.image=images/cards/card-n-sdk_2x.png

    The Android Wear 2.0 Developer Preview runs from 18 May 2016 until the - final Android Wear public release to OEMs, planned for Q4 2016. + final Android Wear public release to OEMs.

    @@ -136,10 +141,11 @@ page.image=images/cards/card-n-sdk_2x.png

    - At milestones 4 and 5 you'll have access to the final Android Wear 2.0 + At milestone 4, you'll have access to the final Android Wear 2.0 APIs and SDK to develop with, as well as near-final system images to test - system behaviors and features. Android Wear 2.0 will use the Android N - API level at this time. You can begin final compatibility testing of your + system behaviors and features. Android Wear 2.0 will use the + Android 7.0 API level at this time. + You can begin final compatibility testing of your legacy apps and refine any new code that is using the Android Wear 2.0 APIs or features.

    @@ -196,9 +202,9 @@ page.image=images/cards/card-n-sdk_2x.png

    - You can download these hardware system images at Download and Test with a - Device: + Device page:

      @@ -210,7 +216,15 @@ page.image=images/cards/card-n-sdk_2x.png

    - Please keep in mind that the Developer Preview system images + To restore your device to its + original state during the preview, you can flash the + appropriate retail system image from + the Download and + Test with a Device page. +

    + +

    + Please keep in mind that the preview system images are for app developers only, and for compatibility testing and early development only, and are not ready for day-to-day use.

    diff --git a/docs/html/wear/preview/start.jd b/docs/html/wear/preview/start.jd index 65d4b56e164d410eea9f80215c69702ae6cc9dc3..c9720dceb842d3e0825fe23accb64602a7356050 100644 --- a/docs/html/wear/preview/start.jd +++ b/docs/html/wear/preview/start.jd @@ -29,7 +29,7 @@ page.image=images/cards/card-n-sdk_2x.png

    If you want an environment for basic compatibility - testing of your app, you can use your current APK and a + testing, you can use your current APK and a supported watch or an emulator. You don't necessarily need to update your full development environment to do basic testing. To simply test your app's compatibility with a preview system image, see

    - 1. For compatibility with the N - Developer Preview, follow the setup instructions for installing - the latest version of Android Studio. + 1. For compatibility with Android 7.0, install the latest version of + Android Studio.

    @@ -63,7 +61,7 @@ page.image=images/cards/card-n-sdk_2x.png

    • Under the SDK Platforms tab:
        -
      • Android N Preview +
      • Android 7.0 (Nougat)
    • @@ -107,10 +105,10 @@ page.image=images/cards/card-n-sdk_2x.png - wearable-support-preview-1-docs.zip + wearable-support-preview-3-docs.zip - MD5: 02f9dc7714c00076b323c9081655c3b2
      - SHA-1: 075f3821ee9b66a919a0e8086f79c12bc9576fb2 + MD5: 22bae00e473e39e320aae8ea09a001a5
      + SHA-1: 474502cc7092bcf0bd671441b8654aa8d6c155ed @@ -146,16 +144,26 @@ page.image=images/cards/card-n-sdk_2x.png plugin. -
    • In the build.gradle file for the Wear module, in the - dependencies section, update the existing reference to the +
    • In the build.gradle file for the Wear module: +
        +
      • In the android section, update the + compileSdkVersion to 24. +
      • + +
      • In the android section, update the + targetSdkVersion to 24. +
      • + +
      • In the dependencies section, update + the existing reference to the Wearable Support Library (for example, compile 'com.google.android.support:wearable:1.4.0') by changing it to the following, which requires that your the Google Repository is the latest version: -
        -compile 'com.google.android.support:wearable:2.0.0-alpha1'
        -      
        + compile 'com.google.android.support:wearable:2.0.0-alpha3' +
      • +
    • See the following page for setting up a watch or emulator with a @@ -180,23 +188,34 @@ compile 'com.google.android.support:wearable:2.0.0-alpha1'
    • Optionally, select the Phone and Tablet option. If - you plan to use N Preview APIs in a phone app, then the Minimum SDK - option list, select API N: Android 6.x (N Preview). + you plan to use Android 7.0 APIs in a phone app, then the Minimum SDK + option list, select API 24: Android 7.0 (Nougat).
    • Select the Wear option, and in the Minimum SDK - option list, select the latest available (N Preview) + option list, select the latest available (API Nougat) option. Click Next until you exit the Create New Project wizard.
    • -
    • In the build.gradle file for the Wear module, in the - dependencies section, update the existing reference to the - Wearable Support Library (perhaps compile - 'com.google.android.support:wearable:1.4.0') to: -
      -compile 'com.google.android.support:wearable:2.0.0-alpha1'
      -      
      +
    • In the build.gradle file for the Wear module: +
        +
      • In the android section, update the + compileSdkVersion to 24. +
      • +
      • In the android section, update the + targetSdkVersion to 24. +
      • +
      • In the dependencies section, update + the existing reference to the + Wearable Support Library (for example, compile + 'com.google.android.support:wearable:1.4.0') by changing it to the + following, which requires that your the Google Repository is the latest + version: + compile 'com.google.android.support:wearable:2.0.0-alpha3' +
      • +
    • See the following page for setting up a watch or emulator with a diff --git a/docs/html/wear/preview/support.jd b/docs/html/wear/preview/support.jd index d03edf31aacdb49820e88d4d8c835bdbd8304962..6006627a4e1615a323a77839917b06f70ceb2367 100644 --- a/docs/html/wear/preview/support.jd +++ b/docs/html/wear/preview/support.jd @@ -16,48 +16,568 @@ page.tags="preview", "developer preview" Wear Developer Google+ community.

      -

      Developer Preview 1

      + + +

      General Advisories

      + +

      + The developer preview is for app developers and other early + adopters and is available for daily use, development, or + compatibility testing. Please be aware of these general notes about the + release: +

      + +
        +
      • The developer preview may have various stability issues on + supported devices. Users may encounter system instability, such as kernel + panics and crashes. +
      • +
      • Some apps may not function as expected on the new + platform version. This includes Google's apps and other apps. +
      • +
      + +

      + Platform API Version +

      + +

      + The Android Platform API version is incremented to 24 to match Android 7.0. + You can update the following in your Android Wear 2.0 Preview project + to 24: +

      + +
        +
      • compileSdkVersion
      • +
      • targetSdkVersion
      • +
      + +

      Deprecations

      + +

      The following fields are deprecated in the preview:

      + +
        +
      • The Notification.WearableExtender#setCustomSizePreset(int) + method no longer accepts SIZE_FULL_SCREEN and this value is now + undefined. +
      • +
      • The Notification.WearableExtender#setContentIcon(int) method + is deprecated. +
      • +
      + +

      Developer Preview 3

      -

      Date: May 2016
      - Builds: Wearable Support 2.0.0-alpha1, NVD36I
      +

      Date: September 2016
      + Builds: Wearable Support 2.0.0-alpha3, NVE68J
      + Emulator support: x86 & ARM (32-bit)
      +

      +
      +
      +
      + +

      + New in Preview 3 +

      + +

      + For access to system images and the companion app for Preview 3, see + + Download and Test with a Device. +

      + +

      + Additions for standalone apps and the Play Store on Wear +

      + +

      + For information about planning your Wear 2.0 app, see + Standalone Apps. +

      + +

      + Generally, the minimum and target SDK level for Wear 2.0, and for a + standalone APK, is level 24. The minimum SDK level can be 23 + only if you are using the same APK + for Wear 1.0 and 2.0 (and thus have an embedded Wear 1.0 APK). +

      + +

      + Run-time permissions are required. +

      + +

      + For information about distributing your Wear 2.0 app, see + App Distribution. +

      + +

      + Complications API additions +

      + +

      + For Preview 3, additions and changes have been made to the Complications + API. The documentation + includes information about the following additions and changes: +

      + +
        +
      • To receive complication data and open the provider chooser, a watch + face must have the RECEIVE_COMPLICATION_DATA permission. +
      • + +
      • To ease a request for the new permission and the starting of the + chooser, the ComplicationHelperActivity class is available + in the wearable support library. This class should be used instead of + ProviderChooserIntent to start the chooser in almost all + cases. +
      • + +
      • Watch faces can specify default providers that are used until a user + selects a provider. +
      • + +
      • The complication types used for "empty" data are changed. +
      • + +
      • A new permission was added to ensure that only the Android Wear + system can bind to provider services. +
      • +
      + +

      + For changes related to the ComplicationData object, see + Behavior + Changes. +

      + +

      + Curved Layout +

      + +

      + For information about creating a curved layout using + the WearableRecyclerView API in your Wear 2.0 app, see + + Curved Layout. +

      + +

      + Notifications features +

      + +

      + To learn about adding an inline action to a notification, + see Inline + Action. +

      + +

      + To learn about adding images to a notification, see + Adding + images to a notification. +

      + +

      + For additions related to the bridging of notifications from a companion + app to a watch, see Bridging + Mode for Notifications. +

      + +

      + Smart Reply additions +

      + +

      + Smart Reply responses are generated by an entirely on-watch, + machine-learning model using the context provided by + MessagingStyle notifications. Use the + setAllowGeneratedReplies(boolean) method to enable Smart Reply for + your MessagingStyle notification. +

      + +

      + Known Issues +

      + +

      + Notifications +

      + +
        +
      • The MessagingStyle + notifications with images posted by standalone apps don't show + images in the notification (i.e., bridged notifications show images, + but standalone notifications don't). +
      • + +
      • This preview release does not include support for notification + groups. +
      • + +
      • With Wear 2.0, a watch can receive notifications directly from + Firebase Cloud Messaging (FCM), which replaces Google Cloud Messaging + (GCM). However, in Preview 3 of Wear 2.0, FCM does not function with + iOS-paired watches. +
      • + +
      • Smart Reply responses are only shown in RemoteInput when + RemoteInput is called from a MessagingStyle + expanded notification. Smart Reply responses are not shown in + RemoteInput when RemoteInput is called from an + + inline action within the stream—an action set with the + setHintDisplayActionInline(true) method. +
      • +
      + +

      + Companion app +

      + +
        +
      • The preview companion app is not compatible with Android 4.3 + (Jelly Bean MR2), which has an SDK build version code of: + JELLY_BEAN_MR2
      • +
      + +
        +
      • In permission screens in the preview companion app: + If you deny a permission, you cannot + proceed. Instead of denying a permission, tap Skip. +
      • +
      + + +

      + Developer Console +

      + +
        +
      • If you set a minimum SDK version of 24, the Play Developer Console + states that there are few supported devices. +
      • +
      + +

      + System user interface and apps +

      + +
        +
      • Dismissing multiple notifications can cause an app to forcibly close. +
      • + +
      • The "Ok Google" detection and voice transcription may not work + reliably. +
      • + +
      • Google Fit is not available with Preview 3. +
      • + +
      • Syncing for embedded apps is not enabled for the preview. Therefore, + to test an app on a device, add it to the Play Store or side-load it + onto a watch. Some existing Wear apps, e.g. Google Maps, are only + using the embedded apps mechanism currently, and are therefore not + installable on the preview (and therefore do not appear on the watch). +
      • + +
      • In Play Store search results on the watch, + results other than apps sometimes appear. +
      • + +
      • Media controls/notifications are not bridged + to the watch from an Android KitKat phone. +
      • +
      + +

      + Account sync +

      + +
        +
      • Account sync initiated from watch settings may not work reliably. + Instead, add accounts from the setup flow of the Android Wear app, or using + the Accounts settings for a device from the Android Wear app. +
      • + +
      • The list of accounts that can be synced is the same as the list of accounts + on the phone. So to add a new account, use the Android settings on the phone, + and then proceed to Android Wear app to sync that account. +
      • +
      + +

      + Devices +

      + +
        +
      • In Android Wear emulators, the Play Store app requires that an + account is synced to the device before the app can be opened. +
      • + +
      • On the Huawei Watch, selecting the language, followed by multiple + acknowledgement dialogues, results in a black screen. +
      • + +
      • On the LG Watch Urbane 2nd Edition, when answering a call from the + watch, the watch does not provide audio from the caller. +
      • +
      + +

      + Smart Reply +

      + +
        +
      • Smart Reply is only available if your watch's system language is + English. +
      • + +
      • Smart Reply responses are not generated for all messages. +
      • +
      + +

      Developer Preview 2

      + +
      +
      +
      +

      Date: July 2016
      + Builds: Wearable Support 2.0.0-alpha2, NVD83H
      Emulator support: x86 & ARM (32-bit)

      +

      + New in Preview 2 +

      -

      General advisories

      +

      + Wearable drawers +

      - This Developer Preview release is for app developers only and is designed for - use in compatibility testing and early development only. + The following are feature additions for + wearable drawers:

      -

      Deprecations

      +
        +
      • Drawer peeking is now supported in the onCreate() method + of your app's activity. +
      • +
      • The automatic drawer peeking behavior is + inverted. Now the bottom drawer peeks when the user scrolls down the view + and top drawer peeks when the user scrolls to the top of the view + (previously scrolling down did not show peek view). +
      • -

        The following fields are deprecated in the Preview:

        +
      • Two new attributes, peek_view and + drawer_content, are added to + WearableDrawerView to specify contents of custom drawers and + peek view in your XML layout (previously, custom drawer contents were + specified only through Java code). +
      • + +
      • The Navigation drawer now displays page indicator dots. +
      • + +
      • Peek views now close automatically after one second. +
      • + +
      • The WearableNavigationDrawer now automatically closes + after five seconds or when an item is tapped. +
      • + +
      • There is improved drawer handling (size and margins) for devices with chins: +
          +
        • Size: The bottom drawer is slightly smaller when there is a + chin. +
        • +
        • Margins: WearableDrawerLayout sets its bottom margin + size equal to the size of the chin, so that the bottom drawer is + fully visible. +
        • +
        +
      • The navigation drawer contents are now updated when + + notifyDataSetChanged is called on the adapter. +
      • + +
      • In your WearableActionDrawer, when there is only one + action, its icon is shown in the peek view and the action is executed + when the peek view is tapped. +
      • + +
      • When the peek view of your WearableActionDrawer has + more than one action, both the first action and the overflow icons are + shown. +
      • +
      + +

      + Wrist gestures +

      + +

      + Wrist gestures can enable quick, one-handed interactions with your app. + For example, a user can + scroll through notifications with one hand while holding a cup of water + with the other. For more information, see + Wrist Gestures. +

      + +

      + Known Issues +

      + +

      + Notifications +

        -
      • The Notification.WearableExtender#setCustomSizePreset(int) - method no longer accepts SIZE_FULL_SCREEN and this value is now - undefined. +
      • This preview release does not include support for notification + groups.
      • -
      • The Notification.WearableExtender#setContentIcon(int) method - is deprecated. +
      • The user interface for the action drawer can sometimes have a + transparent background. +
      • + +
      • The system does not generate Smart Reply responses even if + setAllowGeneratedReplies(true) is set.
      -

      Known Issues

      +

      + Complications +

      + +
        +
      • When tapping on the music complication on a watch face, Play Music + crashes if the Apps launcher provider is used. +
      • +
      +

      + System User Interface +

      -

      Notifications

      +
        +
      • Pressing the hardware button in ambient mode triggers active mode + with the app launcher instead of active mode only. +
      • + +
      • Double pressing the power hardware button while on the launcher + causes the watch screen to turn black. +
      • +
      • Dismissing multiple notifications can cause app to forcibly close. +
      • + +
      • Turning screen lock to off (Enable and disable) functionality is not + reliable. +
      • + +
      • The "Ok Google" detection and voice transcription may not work + reliably. Additionally, Search does not retrieve results. +
      • + +
      • Tapping Google keyboard English (United States) displays a "Settings + under construction" message. +
      • + +
      • First calendar event notification must be dismissed in order to show + the rest of the event card. +
      • + +
      • Unable to turn off the Wi-Fi on a wearable. +
      • + +
      • After music is played on a companion phone, + music card notifications are not mirrored to the watch. +
      • +
      + +

      + Companion App +

      + +
        +
      • An actions card is shown in the Android Wear companion app, even + though there are no actions. +
      • +
      + +

      + Devices +

      + +
        +
      • On the Huawei Watch, selecting the language, followed by multiple + acknowledgement dialogues results in a black screen. +
      • + +
      • On the LG Watch Urbane 2nd Edition, when answering a call from the watch, the + watch does not provide audio from the caller. +
      • + +
      • On the LG Watch Urbane 2nd Edition, + please do the following to prevent battery drain: + Turn on Airplane mode (to disable the cellular radio) and then + turn on Bluetooth. +
      • +
      + +

      Developer Preview 1

      + +
      +
      +
      +

      Date: May 2016
      + Builds: Wearable Support 2.0.0-alpha1, NVD36I
      + Emulator support: x86 & ARM (32-bit)
      +

      +
      +
      +
      + +

      Known Issues

      + +

      Notifications

      • This preview release does not include support for notification groups, @@ -74,18 +594,17 @@ page.tags="preview", "developer preview"
      -

      Complications

        -
      • Battery information is not synchronized between watch face and drop down - quick menu. +
      • Battery information is not synchronized between the + watch face and the drop-down Quick menu.
      • -
      • Play music crashes when tapping on music complication in watch face. +
      • When tapping on the music complication on a watch face, Play Music + crashes if the Apps launcher provider is used.
      -

      System User Interface

        @@ -114,26 +633,24 @@ page.tags="preview", "developer preview"
      -

      Companion App

        -
      • 'More actions' via Companion app shows a blank screen on phone running - nyc-release and watch running feldspar-release. -
      • -
      • Select watch face on companion wear app will not change watch face on - wearable. -
      • +
      • Selecting a watch face on the companion app will not change the watch face on + wearable.
      • +
      • An actions card is shown in the Android Wear companion app, even + though there are no actions. +
      -

      Devices

      • On the Huawei Watch, selecting the language, followed by multiple acknowledgement dialogues results in a black screen.
      • -
      • On the LG Watch Urbane LTE, when answering call from the watch, the watch +
      • On the LG Watch Urbane 2nd Edition, when + answering a call from the watch, the watch does not provide audio from the caller.
      diff --git a/docs/html/work/_project.yaml b/docs/html/work/_project.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9db0466a3f517ef80bf026f40a0a66c8e6214a74 --- /dev/null +++ b/docs/html/work/_project.yaml @@ -0,0 +1,5 @@ +name: "Work" +home_url: /work/ +description: "Develop apps for Android for Work to take advantage of security and management features built into Android." +content_license: cc3-apache2 +buganizer_id: 30209417 diff --git a/docs/html/work/cosu.jd b/docs/html/work/cosu.jd index 8bc54d49bc8ec7f8028fc4cc7d6b7db2ebff3ee2..f66006bab1f5d9ca30aa359a89e8c71dc4d488da 100644 --- a/docs/html/work/cosu.jd +++ b/docs/html/work/cosu.jd @@ -223,7 +223,7 @@ and {@link android.app.Activity#onPause()}

    -Starting from Marshmallow, if your app is whitelisted by an EMM using {@link +Starting from Marshmallow, if your app is whitelisted by an EMM using {@link android.app.admin.DevicePolicyManager#setLockTaskPackages setLockTaskPackages}, your activities can automatically start lock task mode when the app is launched. @@ -253,15 +253,15 @@ launch into lock task mode. Non-privileged apps are treated as normal.

  • The default value of the {@link android.R.attr#lockTaskMode} attribute is -normal. When this attribute is set to normal, tasks don’t launch into -{@link android.R.attr#lockTaskMode}, unless {@link android.app.Activity#startLockTask()} +normal. When this attribute is set to normal, tasks don’t launch into +{@link android.R.attr#lockTaskMode}, unless {@link android.app.Activity#startLockTask()} is called. To call {@link android.app.Activity#startLockTask()}, -applications still need to be whitelisted using -{@link android.app.admin.DevicePolicyManager#setLockTaskPackages setLockTaskPackages}, +applications still need to be whitelisted using +{@link android.app.admin.DevicePolicyManager#setLockTaskPackages setLockTaskPackages}, otherwise, the user sees a dialog to approve entering pinned mode.
  • - +

    To have your activity automatically enter {@link android.R.attr#lockTaskMode}, change the value of this attribute to if_whitelisted. Doing so causes your app to behave in this manner: @@ -289,7 +289,7 @@ Example XML as follows:

    Given either of these options, you still need to create a mechanism for calling {@link android.app.Activity#stopLockTask()} so that users can -exit {@link android.R.attr#lockTaskMode}. +exit {@link android.R.attr#lockTaskMode}.

    @@ -298,7 +298,7 @@ exit {@link android.R.attr#lockTaskMode}.

    To manage applications in COSU, you need a DPC running as device -owner to set several policies on the device. +owner to set several policies on the device.

    diff --git a/docs/html/work/device-management-policy.jd b/docs/html/work/device-management-policy.jd index d564b8969512f1ef5c899be92b2b6b03c1e772fd..fd0915083c705aa0b53cb211560385046f5038d0 100644 --- a/docs/html/work/device-management-policy.jd +++ b/docs/html/work/device-management-policy.jd @@ -14,7 +14,7 @@ parent.link=index.html

  • Activate the Device Administrator
  • Implement the Device Policy Controller
  • - +

    You should also read

      diff --git a/docs/html/work/guide.jd b/docs/html/work/guide.jd index 30b895bdb66bfd629874d53e3768bfc1ddeb075e..b2be94990ff1a56a19b5bdf48367b6db0b19c0fa 100644 --- a/docs/html/work/guide.jd +++ b/docs/html/work/guide.jd @@ -412,6 +412,17 @@ page.image=images/work/cards/android-studio_600px.png +

      Caution: When running your app with Instant Run in +Android Studio, attempting to open your app with a Work profile or secondary +profile will crash your app. To use your app with the Work profile, we +recommend you create a new run +configuration that includes the --user user_id flag, +specifying the Work profile user ID. You can find the user ID by executing +adb shell pm list users from command line. For more information, +see the Instant Run +documentation.

      + +

      Provision a device owner

      diff --git a/docs/html/work/managed-configurations.jd b/docs/html/work/managed-configurations.jd index dc3ef0da2ab2f8df964730899deadd7af407fd6d..6de4d8ba758941ff0231ba46bf14c51a7eec630a 100644 --- a/docs/html/work/managed-configurations.jd +++ b/docs/html/work/managed-configurations.jd @@ -35,7 +35,10 @@ enterprise administrator to:

    - This guide shows how to implement these configuration settings in your app. + This guide shows how to implement managed configuration settings in + your app. If you're an EMM developer, refer to the + Build a Device Policy Controller guide.

    @@ -71,8 +74,8 @@ enterprise administrator to:

    • Declare the managed configurations in your app manifest. Doing - so allows the enterprise administrator to read the app's - configurations through Google Play APIs. + so allows the enterprise administrator to read the app's + configurations through Google Play APIs.
    • Whenever the app resumes, use the {@link @@ -82,11 +85,11 @@ enterprise administrator to:

    • Listen for the - {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED - ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. When you receive this - broadcast, check the {@link android.content.RestrictionsManager} to see what - the current managed configurations are, and make any necessary changes to your - app's behavior. + {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED + ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. When you receive this + broadcast, check the {@link android.content.RestrictionsManager} to see what + the current managed configurations are, and make any necessary changes to your + app's behavior.
    @@ -96,11 +99,11 @@ enterprise administrator to:

    Your app can support any managed configuration you want to define. You declare the - app's managed configurations in a managed configurations file, and declare the - configurations file in the manifest. Creating a configurations file allows other - apps to examine the managed configurations your app provides. Enterprise Mobility - Management (EMM) partners can read your app's configurations by using Google - Play APIs. + app's managed configurations in a managed configurations file, and declare + the configurations file in the manifest. Creating a configurations file allows + other apps to examine the managed configurations your app provides. Enterprise + Mobility Management (EMM) partners can read your app's configurations by using + Google Play APIs.

    @@ -137,6 +140,14 @@ enterprise administrator to:

    application.

    +

    + The managed configuration provider can query the app to find details + on the app's available configurations, including their description + text. The configurations provider and enterprise administrator can + change your app's managed configurations at any time, even when the + app is not running. +

    +

    For example, suppose your app can be remotely configured to allow or forbid it to download data over a cellular connection. Your app could have a @@ -145,23 +156,18 @@ enterprise administrator to:

     <?xml version="1.0" encoding="utf-8"?>
    -<restrictions xmlns:android="http://schemas.android.com/apk/res/android" >
    +<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
     
       <restriction
         android:key="downloadOnCellular"
    -    android:title="App is allowed to download data via cellular"
    +    android:title="@string/download_on_cell_title"
         android:restrictionType="bool"
    -    android:description="If 'false', app can only download data via Wi-Fi"
    +    android:description="@string/download_on_cell_description"
         android:defaultValue="true" />
     
     </restrictions>
     
    -

    - The supported types for the android:restrictionType element are - documented in the reference for {@link android.content.RestrictionsManager}. -

    -

    You use each configuration's android:key attribute to read its value from a managed configuration bundle. For this reason, @@ -172,18 +178,144 @@ enterprise administrator to:

    Note: In a production app, android:title and android:description should be drawn from a localized resource - file, as described in Localizing with - Resources. + file, as described in + Localizing with Resources.

    +

    + An app can define one or multiple nested restriction elements using + the restriction types + {@link android.content.RestrictionEntry#TYPE_BUNDLE bundle} and + {@link android.content.RestrictionEntry#TYPE_BUNDLE_ARRAY bundle_array}. + For example, an app with multiple VPN connection options could define + each VPN server configuration in a bundle, with multiple bundles grouped + together in a bundle array: +

    + +
    +<?xml version="1.0" encoding="utf-8"?>
    +<restrictions xmlns:android="http://schemas.android.com/apk/res/android" >
    +
    +  <restriction
    +    android:key="vpn_configuration_list"
    +    android:restrictionType="bundle_array">
    +    <restriction
    +      android:key="vpn_configuration"
    +      android:restrictionType="bundle">
    +      <restriction
    +        android:key="vpn_server"
    +        android:restrictionType="string"/>
    +      <restriction
    +        android:key="vpn_username"
    +        android:restrictionType="string"/>
    +      <restriction
    +        android:key="vpn_password"
    +        android:restrictionType="string"/>
    +    </restriction>
    +  </restriction>
    +
    +</restrictions>
    +
    +

    - The managed configuration provider can query the app to find details - on the app's available configurations, including their description - text. Configurations providers and enterprise administrators can - change your app's managed configurations at any time, even when the - app is not running. + The supported types for the android:restrictionType element + are listed in Table 1 and documented in + the reference for {@link android.content.RestrictionsManager} and + {@link android.content.RestrictionEntry}. +

    + +

    + Table 1. Restriction entry types and usage.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Typeandroid:restrictionTypeTypical usage
    + {@link android.content.RestrictionEntry#TYPE_BOOLEAN TYPE_BOOLEAN} + "bool" + A boolean value, true or false. +
    + {@link android.content.RestrictionEntry#TYPE_STRING TYPE_STRING} + "string" + A string value, such as a name. +
    + {@link android.content.RestrictionEntry#TYPE_INTEGER TYPE_INTEGER} + "integer" + An integer with a value from + {@link java.lang.Integer#MIN_VALUE MIN_VALUE} to + {@link java.lang.Integer#MAX_VALUE MAX_VALUE}. +
    + {@link android.content.RestrictionEntry#TYPE_CHOICE TYPE_CHOICE} + "choice" + A string value, typically presented as a single-select list. +
    + {@link android.content.RestrictionEntry#TYPE_MULTI_SELECT TYPE_MULTI_SELECT} + "multi-select" + Use this for presenting a multi-select list where more than + one entry can be selected, such as for choosing specific + titles to white-list. +
    + {@link android.content.RestrictionEntry#TYPE_NULL TYPE_NULL} + "hidden" + Hidden restriction type. Use this type for information that + needs to be transferred across but shouldn't be presented to + the user in the UI. Stores a single string value. +
    {@link android.content.RestrictionEntry#TYPE_BUNDLE TYPE_BUNDLE}"bundle" + Use this for storing {@link android.os.Bundle bundles} of + restrictions. Available in Android 6.0 (API level 23). +
    + {@link android.content.RestrictionEntry#TYPE_BUNDLE_ARRAY TYPE_BUNDLE_ARRAY} + "bundle_array" + Use this for storing arrays of restriction + bundles. Available in Android 6.0 (API level 23). +

    Check Managed Configurations @@ -292,11 +424,10 @@ enterprise administrator to:

     boolean appCanUseCellular;
     
    -if appRestrictions.containsKey("downloadOnCellular") {
    +if (appRestrictions.containsKey("downloadOnCellular")) {
         appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular");
     } else {
    -    // here, cellularDefault is a boolean set with the restriction's
    -    // default value
    +    // cellularDefault is a boolean using the restriction's default value
         appCanUseCellular = cellularDefault;
     }
     
    @@ -305,6 +436,37 @@ if (!appCanUseCellular) {
         // ...show appropriate notices to user
     }
    +

    + To apply multiple nested restrictions, read + the {@link android.content.RestrictionEntry#TYPE_BUNDLE_ARRAY bundle_array} + restriction entry as a collection of {@link android.os.Parcelable} objects + and cast as a {@link android.os.Bundle}. In this example, each VPN's configuration + data is parsed and used to build a list of server connection choices: +

    + +
    +// VpnConfig is a sample class used store config data, not defined
    +List<VpnConfig> vpnConfigs = new ArrayList<>();
    +
    +Parcelable[] parcelables =
    +    appRestrictions.getParcelableArray("vpn_configuration_list");
    +
    +if (parcelables != null && parcelables.length > 0) {
    +    // iterate parcelables and cast as bundle
    +    for (int i = 0; i < parcelables.length; i++) {
    +        Bundle vpnConfigBundle = (Bundle) parcelables[i];
    +        // parse bundle data and store in VpnConfig array
    +        vpnConfigs.add(new VpnConfig()
    +            .setServer(vpnConfigBundle.getString("vpn_server"))
    +            .setUsername(vpnConfigBundle.getString("vpn_username"))
    +            .setPassword(vpnConfigBundle.getString("vpn_password")));
    +    }
    +}
    +
    +if (!vpnConfigs.isEmpty()) {
    +    // ...choose a VPN configuration or prompt user to select from list
    +}
    +

    Listen for Managed Configuration Changes

    diff --git a/docs/image_sources/brand/android_logo_no.graffle/data.plist b/docs/image_sources/brand/android_logo_no.graffle/data.plist new file mode 100644 index 0000000000000000000000000000000000000000..1132a59772410f7c08ba798190982c6812fd2eef Binary files /dev/null and b/docs/image_sources/brand/android_logo_no.graffle/data.plist differ diff --git a/docs/image_sources/brand/android_logo_no.graffle/image1.jpg b/docs/image_sources/brand/android_logo_no.graffle/image1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff2959958de4f0d8353640da38f2a2ec0f45468a Binary files /dev/null and b/docs/image_sources/brand/android_logo_no.graffle/image1.jpg differ diff --git a/docs/image_sources/training/tv/playback/onboarding-fragment-diagram.graffle.zip b/docs/image_sources/training/tv/playback/onboarding-fragment-diagram.graffle.zip new file mode 100644 index 0000000000000000000000000000000000000000..89a799bb57c3bae498dc4093ee46392fadfdc3bd Binary files /dev/null and b/docs/image_sources/training/tv/playback/onboarding-fragment-diagram.graffle.zip differ diff --git a/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip b/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip new file mode 100644 index 0000000000000000000000000000000000000000..8b6779d68c1c1a5c079066f08eb4056c81b991d1 Binary files /dev/null and b/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip differ diff --git a/docs/source.properties b/docs/source.properties new file mode 100644 index 0000000000000000000000000000000000000000..77a760bce900e089d933488471cb1fc574505fd9 --- /dev/null +++ b/docs/source.properties @@ -0,0 +1,3 @@ +Pkg.Revision=24.0 +Pkg.Desc=Android offline API reference +Pkg.Path=docs \ No newline at end of file diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 1fdc1f575bd49a96577aa384c763284be04dfb70..49721cf426664ab2a9bead3f23d1f0c165e6fe8d 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -1667,10 +1667,10 @@ public final class Bitmap implements Parcelable { * and therefore is harmless. */ public void prepareToDraw() { - // TODO: Consider having this start an async upload? - // With inPurgeable no-op'd there's currently no use for this - // method, but it could have interesting future uses. checkRecycled("Can't prepareToDraw on a recycled bitmap!"); + // Kick off an update/upload of the bitmap outside of the normal + // draw path. + nativePrepareToDraw(mNativePtr); } /** @@ -1741,4 +1741,5 @@ public final class Bitmap implements Parcelable { private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap); private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1); private static native long nativeRefPixelRef(long nativeBitmap); + private static native void nativePrepareToDraw(long nativeBitmap); } diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index cb6c92e871727eb0fe7ef3fb4b7a5ab5537ca9b1..40b877de131cfc08932039599fcf46534c60f6d8 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -788,7 +788,7 @@ public class Canvas { * @return true if the resulting is non-empty */ public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) { - return native_clipPath(mNativeCanvasWrapper, path.ni(), op.nativeInt); + return native_clipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt); } /** @@ -907,7 +907,7 @@ public class Canvas { * does not intersect with the canvas' clip */ public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) { - return native_quickReject(mNativeCanvasWrapper, path.ni()); + return native_quickReject(mNativeCanvasWrapper, path.readOnlyNI()); } /** @@ -1259,7 +1259,7 @@ public class Canvas { if (path.isSimplePath && path.rects != null) { native_drawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance()); } else { - native_drawPath(mNativeCanvasWrapper, path.ni(), paint.getNativeInstance()); + native_drawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance()); } } @@ -1895,7 +1895,7 @@ public class Canvas { throw new ArrayIndexOutOfBoundsException(); } native_drawTextOnPath(mNativeCanvasWrapper, text, index, count, - path.ni(), hOffset, vOffset, + path.readOnlyNI(), hOffset, vOffset, paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface); } @@ -1915,7 +1915,7 @@ public class Canvas { public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) { if (text.length() > 0) { - native_drawTextOnPath(mNativeCanvasWrapper, text, path.ni(), hOffset, vOffset, + native_drawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset, paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface); } } diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 054e29fd9ff4a33c13295d0dcc28c76fd51746ab..cfbe672a4cd60b46b71a43a2c4bd250ad36351b1 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -1021,7 +1021,7 @@ public class Paint { * drawn with a hairline (width == 0) */ public boolean getFillPath(Path src, Path dst) { - return nGetFillPath(mNativePaint, src.ni(), dst.ni()); + return nGetFillPath(mNativePaint, src.readOnlyNI(), dst.mutateNI()); } /** @@ -2394,7 +2394,7 @@ public class Paint { throw new ArrayIndexOutOfBoundsException(); } nGetTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, index, count, x, y, - path.ni()); + path.mutateNI()); } /** @@ -2416,7 +2416,7 @@ public class Paint { throw new IndexOutOfBoundsException(); } nGetTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, start, end, x, y, - path.ni()); + path.mutateNI()); } /** diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index de391af5d4ce2abb14e13b596c61ba7e37b84e5a..be31bbe0c086bba63734b293bfabd1167cd776bf 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -775,7 +775,12 @@ public class Path { } } - final long ni() { + final long readOnlyNI() { + return mNativePath; + } + + final long mutateNI() { + isSimplePath = false; return mNativePath; } diff --git a/graphics/java/android/graphics/PathDashPathEffect.java b/graphics/java/android/graphics/PathDashPathEffect.java index 4f43f680ff3e9bba182181a4e940088c5d2a9939..2b6a6edcc266f14f7e47dcece1b67c283395acde 100644 --- a/graphics/java/android/graphics/PathDashPathEffect.java +++ b/graphics/java/android/graphics/PathDashPathEffect.java @@ -41,7 +41,7 @@ public class PathDashPathEffect extends PathEffect { */ public PathDashPathEffect(Path shape, float advance, float phase, Style style) { - native_instance = nativeCreate(shape.ni(), advance, phase, + native_instance = nativeCreate(shape.readOnlyNI(), advance, phase, style.native_style); } diff --git a/graphics/java/android/graphics/PathMeasure.java b/graphics/java/android/graphics/PathMeasure.java index 2848949eb72f4a381779a8291c237d3667c4b0f3..78d892e94cf05cb3df882432b804d566924a4c97 100644 --- a/graphics/java/android/graphics/PathMeasure.java +++ b/graphics/java/android/graphics/PathMeasure.java @@ -50,7 +50,7 @@ public class PathMeasure { public PathMeasure(Path path, boolean forceClosed) { // The native implementation does not copy the path, prevent it from being GC'd mPath = path; - native_instance = native_create(path != null ? path.ni() : 0, + native_instance = native_create(path != null ? path.readOnlyNI() : 0, forceClosed); } @@ -60,7 +60,7 @@ public class PathMeasure { public void setPath(Path path, boolean forceClosed) { mPath = path; native_setPath(native_instance, - path != null ? path.ni() : 0, + path != null ? path.readOnlyNI() : 0, forceClosed); } @@ -134,8 +134,7 @@ public class PathMeasure { return false; } - dst.isSimplePath = false; - return native_getSegment(native_instance, startD, stopD, dst.ni(), startWithMoveTo); + return native_getSegment(native_instance, startD, stopD, dst.mutateNI(), startWithMoveTo); } /** diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java index 28d869063225c556e8846b37a977a9729465aa9d..08eeaff69f9b381bfdfa1770d0ad99238b5b97bf 100644 --- a/graphics/java/android/graphics/Picture.java +++ b/graphics/java/android/graphics/Picture.java @@ -21,11 +21,14 @@ import java.io.OutputStream; /** * A Picture records drawing calls (via the canvas returned by beginRecording) - * and can then play them back into Canvas (via {@link Picture#draw(Canvas)} or + * and can then play them back into Canvas (via {@link Picture#draw(Canvas)} or * {@link Canvas#drawPicture(Picture)}).For most content (e.g. text, lines, rectangles), * drawing a sequence from a picture can be faster than the equivalent API * calls, since the picture performs its playback without incurring any * method-call overhead. + * + *

    Note: Prior to API level 23 a picture cannot + * be replayed on a hardware accelerated canvas.

    */ public class Picture { private Canvas mRecordingCanvas; @@ -135,10 +138,6 @@ public class Picture { * have been persisted across device restarts are not guaranteed to decode * properly and are highly discouraged. * - *

    - * Note: Prior to API level 23 a picture created from an - * input stream cannot be replayed on a hardware accelerated canvas. - * * @see #writeToStream(java.io.OutputStream) * @deprecated The recommended alternative is to not use writeToStream and * instead draw the picture into a Bitmap from which you can persist it as @@ -155,10 +154,6 @@ public class Picture { * The resulting stream is NOT to be persisted across device restarts as * there is no guarantee that the Picture can be successfully reconstructed. * - *

    - * Note: Prior to API level 23 a picture created from an - * input stream cannot be replayed on a hardware accelerated canvas. - * * @see #createFromStream(java.io.InputStream) * @deprecated The recommended alternative is to draw the picture into a * Bitmap from which you can persist it as raw or compressed pixels. diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java index de89ad07d873538e0c30cf6385df8d4e2781060b..dca6d9ed3b2f1f475239e30ee16f67749dc0fcf8 100644 --- a/graphics/java/android/graphics/Region.java +++ b/graphics/java/android/graphics/Region.java @@ -110,7 +110,7 @@ public class Region implements Parcelable { * (with no antialiasing). */ public boolean setPath(Path path, Region clip) { - return nativeSetPath(mNativeRegion, path.ni(), clip.mNativeRegion); + return nativeSetPath(mNativeRegion, path.readOnlyNI(), clip.mNativeRegion); } /** @@ -155,7 +155,7 @@ public class Region implements Parcelable { */ public Path getBoundaryPath() { Path path = new Path(); - nativeGetBoundaryPath(mNativeRegion, path.ni()); + nativeGetBoundaryPath(mNativeRegion, path.mutateNI()); return path; } @@ -164,7 +164,7 @@ public class Region implements Parcelable { * path will also be empty. */ public boolean getBoundaryPath(Path path) { - return nativeGetBoundaryPath(mNativeRegion, path.ni()); + return nativeGetBoundaryPath(mNativeRegion, path.mutateNI()); } /** diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index 5c54324d81070c77a44fee9c736446b1c2f159c6..c3861083e2fda53a462809889c20e421e6b317ae 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -77,6 +77,8 @@ public class SurfaceTexture { private long mProducer; private long mFrameAvailableListener; + private boolean mIsSingleBuffered; + /** * Callback interface for being notified that a new stream frame is available. */ @@ -130,6 +132,7 @@ public class SurfaceTexture { */ public SurfaceTexture(int texName, boolean singleBufferMode) { mCreatorLooper = Looper.myLooper(); + mIsSingleBuffered = singleBufferMode; nativeInit(false, texName, singleBufferMode, new WeakReference(this)); } @@ -157,6 +160,7 @@ public class SurfaceTexture { */ public SurfaceTexture(boolean singleBufferMode) { mCreatorLooper = Looper.myLooper(); + mIsSingleBuffered = singleBufferMode; nativeInit(true, 0, singleBufferMode, new WeakReference(this)); } @@ -378,6 +382,14 @@ public class SurfaceTexture { } } + /** + * Returns true if the SurfaceTexture is single-buffered + * @hide + */ + public boolean isSingleBuffered() { + return mIsSingleBuffered; + } + private native void nativeInit(boolean isDetached, int texName, boolean singleBufferMode, WeakReference weakSelf) throws Surface.OutOfResourcesException; diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 6762bea1ca3503603c949d5f1a3a7c25bfbba42a..c24d31334be003b6f8fd8aaa38a2eb53185636a6 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -46,6 +46,7 @@ import android.util.IntArray; import android.util.Log; import android.util.LongArray; import android.util.PathParser; +import android.util.Property; import android.util.TimeUtils; import android.view.Choreographer; import android.view.DisplayListCanvas; @@ -64,19 +65,36 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; /** - * This class uses {@link android.animation.ObjectAnimator} and - * {@link android.animation.AnimatorSet} to animate the properties of a - * {@link android.graphics.drawable.VectorDrawable} to create an animated drawable. + * This class animates properties of a {@link android.graphics.drawable.VectorDrawable} with + * animations defined using {@link android.animation.ObjectAnimator} or + * {@link android.animation.AnimatorSet}. *

    - * AnimatedVectorDrawable are normally defined as 3 separate XML files. + * Starting from API 25, AnimatedVectorDrawable runs on RenderThread (as opposed to on UI thread for + * earlier APIs). This means animations in AnimatedVectorDrawable can remain smooth even when there + * is heavy workload on the UI thread. Note: If the UI thread is unresponsive, RenderThread may + * continue animating until the UI thread is capable of pushing another frame. Therefore, it is not + * possible to precisely coordinate a RenderThread-enabled AnimatedVectorDrawable with UI thread + * animations. Additionally, + * {@link android.graphics.drawable.Animatable2.AnimationCallback#onAnimationEnd(Drawable)} will be + * called the frame after the AnimatedVectorDrawable finishes on the RenderThread. *

    *

    - * First is the XML file for {@link android.graphics.drawable.VectorDrawable}. - * Note that we allow the animation to happen on the group's attributes and path's - * attributes, which requires they are uniquely named in this XML file. Groups - * and paths without animations do not need names. + * AnimatedVectorDrawable can be defined in either three separate XML files, + * or one XML. *

    - *
  • Here is a simple VectorDrawable in this vectordrawable.xml file. + * + *

    Define an AnimatedVectorDrawable in three separate XML files

    + *
      + * + *
    • XML for the VectorDrawable containing properties to be animated

      + *

      + * Animations can be performed on both group and path attributes, which requires groups and paths to + * have unique names in the same VectorDrawable. Groups and paths without animations do not need to + * be named. + *

      + * Below is an example of a VectorDrawable defined in vectordrawable.xml. This VectorDrawable is + * referred to by its file name (not including file suffix) in the + * AnimatedVectorDrawable XML example. *
        * <vector xmlns:android="http://schemas.android.com/apk/res/android"
        *     android:height="64dp"
      @@ -95,17 +113,20 @@ import java.util.ArrayList;
        *     </group>
        * </vector>
        * 
    • + * + * + *
    • XML for AnimatedVectorDrawable

      *

      - * Second is the AnimatedVectorDrawable's XML file, which defines the target - * VectorDrawable, the target paths and groups to animate, the properties of the - * path and group to animate and the animations defined as the ObjectAnimators - * or AnimatorSets. + * An AnimatedVectorDrawable element has a VectorDrawable attribute, and one or more target + * element(s). The target elements can be the path or group to be animated. Each target element + * contains a name attribute that references a property (of a path or a group) to animate, and an + * animation attribute that points to an ObjectAnimator or an AnimatorSet. *

      - *
    • Here is a simple AnimatedVectorDrawable defined in this avd.xml file. - * Note how we use the names to refer to the groups and paths in the vectordrawable.xml. + * The following code sample defines an AnimatedVectorDrawable. Note that the names refer to the + * groups and paths in the VectorDrawable XML above. *
        * <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
      - *   android:drawable="@drawable/vectordrawable" >
      + *     android:drawable="@drawable/vectordrawable" >
        *     <target
        *         android:name="rotationGroup"
        *         android:animation="@anim/rotation" />
      @@ -113,36 +134,89 @@ import java.util.ArrayList;
        *         android:name="v"
        *         android:animation="@anim/path_morph" />
        * </animated-vector>
      - * 
    • + * + * + * + *
    • XML for Animations defined using ObjectAnimator or AnimatorSet

      *

      - * Last is the Animator XML file, which is the same as a normal ObjectAnimator - * or AnimatorSet. - * To complete this example, here are the 2 animator files used in avd.xml: - * rotation.xml and path_morph.xml. + * From the previous example of AnimatedVectorDrawable, two animations + * were used: rotation.xml and path_morph.xml. *

      - *
    • Here is the rotation.xml, which will rotate the target group for 360 degrees. + * rotation.xml rotates the target group from 0 degree to 360 degrees over 6000ms: *
        * <objectAnimator
        *     android:duration="6000"
        *     android:propertyName="rotation"
        *     android:valueFrom="0"
        *     android:valueTo="360" />
      - * 
    • - *
    • Here is the path_morph.xml, which will morph the path from one shape to - * the other. Note that the paths must be compatible for morphing. - * In more details, the paths should have exact same length of commands , and - * exact same length of parameters for each commands. - * Note that the path strings are better stored in strings.xml for reusing. + * + * + * path_morph.xml morphs the path from one shape into the other. Note that the paths must be + * compatible for morphing. Specifically, the paths must have the same commands, in the same order, + * and must have the same number of parameters for each command. It is recommended to store path + * strings as string resources for reuse. *
        * <set xmlns:android="http://schemas.android.com/apk/res/android">
        *     <objectAnimator
        *         android:duration="3000"
        *         android:propertyName="pathData"
      - *         android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
      + *         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"/>
        * </set>
      - * 
    • + * + *
    + * + *

    Define an AnimatedVectorDrawable all in one XML file

    + *

    + * Since the AAPT tool supports a new format that bundles several related XML files together, we can + * merge the XML files from the previous examples into one XML file: + *

    + *
    + * <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" >
    + *     <aapt:attr name="android:drawable">
    + *         <vector
    + *             android:height="64dp"
    + *             android:width="64dp"
    + *             android:viewportHeight="600"
    + *             android:viewportWidth="600" >
    + *             <group
    + *                 android:name="rotationGroup"
    + *                 android:pivotX="300.0"
    + *                 android:pivotY="300.0"
    + *                 android:rotation="45.0" >
    + *                 <path
    + *                     android:name="v"
    + *                     android:fillColor="#000000"
    + *                     android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    + *             </group>
    + *         </vector>
    + *     </aapt:attr>
    + *
    + *     <target android:name="rotationGroup"> *
    + *         <aapt:attr name="android:animation">
    + *             <objectAnimator
    + *             android:duration="6000"
    + *             android:propertyName="rotation"
    + *             android:valueFrom="0"
    + *             android:valueTo="360" />
    + *         </aapt:attr>
    + *     </target>
    + *
    + *     <target android:name="v" >
    + *         <aapt:attr name="android:animation">
    + *             <set>
    + *                 <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"/>
    + *             </set>
    + *         </aapt:attr>
    + *      </target>
    + * </animated-vector>
    + * 
    * * @attr ref android.R.styleable#AnimatedVectorDrawable_drawable * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name @@ -157,7 +231,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false; /** Local, mutable animator set. */ - private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorUI(this); + private VectorDrawableAnimator mAnimatorSet; /** * The resources against which this drawable was created. Used to attempt @@ -182,6 +256,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) { mAnimatedVectorState = new AnimatedVectorDrawableState(state, mCallback, res); + mAnimatorSet = new VectorDrawableAnimatorRT(this); mRes = res; } @@ -208,7 +283,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { /** * In order to avoid breaking old apps, we only throw exception on invalid VectorDrawable - * animations * for apps targeting N and later. For older apps, we ignore (i.e. quietly skip) + * animations for apps targeting N and later. For older apps, we ignore (i.e. quietly skip) * these animations. * * @return whether invalid animations for vector drawable should be ignored. @@ -235,8 +310,27 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { return super.getChangingConfigurations() | mAnimatedVectorState.getChangingConfigurations(); } + /** + * Draws the AnimatedVectorDrawable into the given canvas. + *

    + * Note: Calling this method with a software canvas when the + * AnimatedVectorDrawable is being animated on RenderThread (for API 25 and later) may yield + * outdated result, as the UI thread is not guaranteed to be in sync with RenderThread on + * VectorDrawable's property changes during RenderThread animations. + *

    + * + * @param canvas The canvas to draw into + */ @Override public void draw(Canvas canvas) { + if (!canvas.isHardwareAccelerated() && mAnimatorSet instanceof VectorDrawableAnimatorRT) { + // If we have SW canvas and the RT animation is waiting to start, We need to fallback + // to UI thread animation for AVD. + if (!mAnimatorSet.isRunning() && + ((VectorDrawableAnimatorRT) mAnimatorSet).mPendingAnimationActions.size() > 0) { + fallbackOntoUI(); + } + } mAnimatorSet.onDraw(canvas); mAnimatedVectorState.mVectorDrawable.draw(canvas); } @@ -262,9 +356,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } /** - * AnimatedVectorDrawable is running on render thread now. Therefore, if the root alpha is being - * animated, then the root alpha value we get from this call could be out of sync with alpha - * value used in the render thread. Otherwise, the root alpha should be always the same value. + * For API 25 and later, AnimatedVectorDrawable runs on RenderThread. Therefore, when the + * root alpha is being animated, this getter does not guarantee to return an up-to-date alpha + * value. * * @return the containing vector drawable's root alpha value. */ @@ -361,7 +455,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { int eventType = parser.getEventType(); float pathErrorScale = 1; - while (eventType != XmlPullParser.END_DOCUMENT) { + final int innerDepth = parser.getDepth() + 1; + + // Parse everything until the end of the animated-vector element. + while (eventType != XmlPullParser.END_DOCUMENT + && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) { if (eventType == XmlPullParser.START_TAG) { final String tagName = parser.getName(); if (ANIMATED_VECTOR.equals(tagName)) { @@ -390,9 +488,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { R.styleable.AnimatedVectorDrawableTarget_animation, 0); if (animResId != 0) { if (theme != null) { - final Animator objectAnimator = AnimatorInflater.loadAnimator( + // The animator here could be ObjectAnimator or AnimatorSet. + final Animator animator = AnimatorInflater.loadAnimator( res, theme, animResId, pathErrorScale); - state.addTargetAnimator(target, objectAnimator); + updateAnimatorProperty(animator, target, state.mVectorDrawable, + state.mShouldIgnoreInvalidAnim); + state.addTargetAnimator(target, animator); } else { // The animation may be theme-dependent. As a // workaround until Animator has full support for @@ -414,6 +515,55 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mRes = state.mPendingAnims == null ? null : res; } + private static void updateAnimatorProperty(Animator animator, String targetName, + VectorDrawable vectorDrawable, boolean ignoreInvalidAnim) { + if (animator instanceof ObjectAnimator) { + // Change the property of the Animator from using reflection based on the property + // name to a Property object that wraps the setter and getter for modifying that + // specific property for a given object. By replacing the reflection with a direct call, + // we can largely reduce the time it takes for a animator to modify a VD property. + PropertyValuesHolder[] holders = ((ObjectAnimator) animator).getValues(); + for (int i = 0; i < holders.length; i++) { + PropertyValuesHolder pvh = holders[i]; + String propertyName = pvh.getPropertyName(); + Object targetNameObj = vectorDrawable.getTargetByName(targetName); + Property property = null; + if (targetNameObj instanceof VectorDrawable.VObject) { + property = ((VectorDrawable.VObject) targetNameObj).getProperty(propertyName); + } else if (targetNameObj instanceof VectorDrawable.VectorDrawableState) { + property = ((VectorDrawable.VectorDrawableState) targetNameObj) + .getProperty(propertyName); + } + if (property != null) { + if (containsSameValueType(pvh, property)) { + pvh.setProperty(property); + } else if (!ignoreInvalidAnim) { + throw new RuntimeException("Wrong valueType for Property: " + propertyName + + ". Expected type: " + property.getType().toString() + ". Actual " + + "type defined in resources: " + pvh.getValueType().toString()); + + } + } + } + } else if (animator instanceof AnimatorSet) { + for (Animator anim : ((AnimatorSet) animator).getChildAnimations()) { + updateAnimatorProperty(anim, targetName, vectorDrawable, ignoreInvalidAnim); + } + } + } + + private static boolean containsSameValueType(PropertyValuesHolder holder, Property property) { + Class type1 = holder.getValueType(); + Class type2 = property.getType(); + if (type1 == float.class || type1 == Float.class) { + return type2 == float.class || type2 == Float.class; + } else if (type1 == int.class || type1 == Integer.class) { + return type2 == int.class || type2 == Integer.class; + } else { + return type1 == type2; + } + } + /** * Force to animate on UI thread. * @hide @@ -425,10 +575,22 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { throw new UnsupportedOperationException("Cannot force Animated Vector Drawable to" + " run on UI thread when the animation has started on RenderThread."); } + fallbackOntoUI(); + } + } + + private void fallbackOntoUI() { + if (mAnimatorSet instanceof VectorDrawableAnimatorRT) { + VectorDrawableAnimatorRT oldAnim = (VectorDrawableAnimatorRT) mAnimatorSet; mAnimatorSet = new VectorDrawableAnimatorUI(this); if (mAnimatorSetFromXml != null) { mAnimatorSet.init(mAnimatorSetFromXml); } + // Transfer the listener from RT animator to UI animator + if (oldAnim.mListener != null) { + mAnimatorSet.setListener(oldAnim.mListener); + } + oldAnim.transferPendingActions(mAnimatorSet); } } @@ -462,6 +624,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { @Config int mChangingConfigurations; VectorDrawable mVectorDrawable; + private final boolean mShouldIgnoreInvalidAnim; + /** Animators that require a theme before inflation. */ ArrayList mPendingAnims; @@ -473,6 +637,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy, Callback owner, Resources res) { + mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation(); if (copy != null) { mChangingConfigurations = copy.mChangingConfigurations; @@ -616,8 +781,10 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { for (int i = 0, count = pendingAnims.size(); i < count; i++) { final PendingAnimator pendingAnimator = pendingAnims.get(i); - final Animator objectAnimator = pendingAnimator.newInstance(res, t); - addTargetAnimator(pendingAnimator.target, objectAnimator); + final Animator animator = pendingAnimator.newInstance(res, t); + updateAnimatorProperty(animator, pendingAnimator.target, mVectorDrawable, + mShouldIgnoreInvalidAnim); + addTargetAnimator(pendingAnimator.target, animator); } } } @@ -982,6 +1149,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static final int REVERSE_ANIMATION = 2; private static final int RESET_ANIMATION = 3; private static final int END_ANIMATION = 4; + + // If the duration of an animation is more than 300 frames, we cap the sample size to 300. + private static final int MAX_SAMPLE_POINTS = 300; private AnimatorListener mListener = null; private final LongArray mStartDelays = new LongArray(); private PropertyValuesHolder.PropertyValues mTmpValues = @@ -992,14 +1162,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private boolean mInitialized = false; private boolean mIsReversible = false; private boolean mIsInfinite = false; - // This needs to be set before parsing starts. - private boolean mShouldIgnoreInvalidAnim; // TODO: Consider using NativeAllocationRegistery to track native allocation private final VirtualRefBasePtr mSetRefBasePtr; private WeakReference mLastSeenTarget = null; private int mLastListenerId = 0; private final IntArray mPendingAnimationActions = new IntArray(); - private final Drawable mDrawable; + private final AnimatedVectorDrawable mDrawable; VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) { mDrawable = drawable; @@ -1016,8 +1184,10 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " + "re-initialized"); } - mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation(); parseAnimatorSet(set, 0); + long vectorDrawableTreePtr = mDrawable.mAnimatedVectorState.mVectorDrawable + .getNativeTree(); + nSetVectorDrawableTarget(mSetPtr, vectorDrawableTreePtr); mInitialized = true; mIsInfinite = set.getTotalDuration() == Animator.DURATION_INFINITE; @@ -1077,7 +1247,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } else if (target instanceof VectorDrawable.VFullPath) { createRTAnimatorForFullPath(animator, (VectorDrawable.VFullPath) target, startTime); - } else if (!mShouldIgnoreInvalidAnim) { + } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { throw new IllegalArgumentException("ClipPath only supports PathData " + "property"); } @@ -1086,7 +1256,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } else if (target instanceof VectorDrawable.VectorDrawableState) { createRTAnimatorForRootGroup(values, animator, (VectorDrawable.VectorDrawableState) target, startTime); - } else if (!mShouldIgnoreInvalidAnim) { + } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { // Should never get here throw new UnsupportedOperationException("Target should be either VGroup, VPath, " + "or ConstantState, " + target == null ? "Null target" : target.getClass() + @@ -1121,8 +1291,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { long propertyPtr = nCreateGroupPropertyHolder(nativePtr, propertyId, (Float) mTmpValues.startValue, (Float) mTmpValues.endValue); if (mTmpValues.dataSource != null) { - float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator - .getDuration()); + float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource, + animator.getDuration()); nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); } createNativeChildAnimator(propertyPtr, startTime, animator); @@ -1149,7 +1319,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { long nativePtr = target.getNativePtr(); if (mTmpValues.type == Float.class || mTmpValues.type == float.class) { if (propertyId < 0) { - if (mShouldIgnoreInvalidAnim) { + if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { return; } else { throw new IllegalArgumentException("Property: " + mTmpValues.propertyName @@ -1158,12 +1328,24 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId, (Float) mTmpValues.startValue, (Float) mTmpValues.endValue); + if (mTmpValues.dataSource != null) { + // Pass keyframe data to native, if any. + float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource, + animator.getDuration()); + nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); + } } else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) { propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId, (Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue); + if (mTmpValues.dataSource != null) { + // Pass keyframe data to native, if any. + int[] dataPoints = createIntDataPoints(mTmpValues.dataSource, + animator.getDuration()); + nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); + } } else { - if (mShouldIgnoreInvalidAnim) { + if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { return; } else { throw new UnsupportedOperationException("Unsupported type: " + @@ -1171,45 +1353,63 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { "supported for Paths."); } } - if (mTmpValues.dataSource != null) { - float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator - .getDuration()); - nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); - } createNativeChildAnimator(propertyPtr, startTime, animator); } private void createRTAnimatorForRootGroup(PropertyValuesHolder[] values, ObjectAnimator animator, VectorDrawable.VectorDrawableState target, long startTime) { - long nativePtr = target.getNativeRenderer(); - if (!animator.getPropertyName().equals("alpha")) { - if (mShouldIgnoreInvalidAnim) { - return; - } else { - throw new UnsupportedOperationException("Only alpha is supported for root " - + "group"); - } + long nativePtr = target.getNativeRenderer(); + if (!animator.getPropertyName().equals("alpha")) { + if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { + return; + } else { + throw new UnsupportedOperationException("Only alpha is supported for root " + + "group"); } - Float startValue = null; - Float endValue = null; - for (int i = 0; i < values.length; i++) { - values[i].getPropertyValues(mTmpValues); - if (mTmpValues.propertyName.equals("alpha")) { - startValue = (Float) mTmpValues.startValue; - endValue = (Float) mTmpValues.endValue; - break; - } + } + Float startValue = null; + Float endValue = null; + for (int i = 0; i < values.length; i++) { + values[i].getPropertyValues(mTmpValues); + if (mTmpValues.propertyName.equals("alpha")) { + startValue = (Float) mTmpValues.startValue; + endValue = (Float) mTmpValues.endValue; + break; } - if (startValue == null && endValue == null) { - if (mShouldIgnoreInvalidAnim) { - return; - } else { - throw new UnsupportedOperationException("No alpha values are specified"); - } + } + if (startValue == null && endValue == null) { + if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { + return; + } else { + throw new UnsupportedOperationException("No alpha values are specified"); } - long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue); - createNativeChildAnimator(propertyPtr, startTime, animator); + } + long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue); + if (mTmpValues.dataSource != null) { + // Pass keyframe data to native, if any. + float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource, + animator.getDuration()); + nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); + } + createNativeChildAnimator(propertyPtr, startTime, animator); + } + + /** + * Calculate the amount of frames an animation will run based on duration. + */ + private static int getFrameCount(long duration) { + long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos(); + int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS); + int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs); + // We need 2 frames of data minimum. + numAnimFrames = Math.max(2, numAnimFrames); + if (numAnimFrames > MAX_SAMPLE_POINTS) { + Log.w("AnimatedVectorDrawable", "Duration for the animation is too long :" + + duration + ", the animation will subsample the keyframe or path data."); + numAnimFrames = MAX_SAMPLE_POINTS; + } + return numAnimFrames; } // These are the data points that define the value of the animating properties. @@ -1217,11 +1417,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { // a point on the path corresponds to the values of translateX and translateY. // TODO: (Optimization) We should pass the path down in native and chop it into segments // in native. - private static float[] createDataPoints( + private static float[] createFloatDataPoints( PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) { - long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos(); - int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS); - int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs); + int numAnimFrames = getFrameCount(duration); float values[] = new float[numAnimFrames]; float lastFrame = numAnimFrames - 1; for (int i = 0; i < numAnimFrames; i++) { @@ -1231,6 +1429,18 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { return values; } + private static int[] createIntDataPoints( + PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) { + int numAnimFrames = getFrameCount(duration); + int values[] = new int[numAnimFrames]; + float lastFrame = numAnimFrames - 1; + for (int i = 0; i < numAnimFrames; i++) { + float fraction = i / lastFrame; + values[i] = (Integer) dataSource.getValueAtFraction(fraction); + } + return values; + } + private void createNativeChildAnimator(long propertyPtr, long extraDelay, ObjectAnimator animator) { long duration = animator.getDuration(); @@ -1245,7 +1455,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mStartDelays.add(startDelay); nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration, - repeatCount); + repeatCount, animator.getRepeatMode()); } /** @@ -1254,16 +1464,19 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * to the last seen RenderNode target and start right away. */ protected void recordLastSeenTarget(DisplayListCanvas canvas) { - mLastSeenTarget = new WeakReference( - RenderNodeAnimatorSetHelper.getTarget(canvas)); - if (mPendingAnimationActions.size() > 0 && useLastSeenTarget()) { - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "Target is set in the next frame"); - } - for (int i = 0; i < mPendingAnimationActions.size(); i++) { - handlePendingAction(mPendingAnimationActions.get(i)); + final RenderNode node = RenderNodeAnimatorSetHelper.getTarget(canvas); + mLastSeenTarget = new WeakReference(node); + // Add the animator to the list of animators on every draw + if (mInitialized || mPendingAnimationActions.size() > 0) { + if (useTarget(node)) { + if (DBG_ANIMATION_VECTOR_DRAWABLE) { + Log.d(LOGTAG, "Target is set in the next frame"); + } + for (int i = 0; i < mPendingAnimationActions.size(); i++) { + handlePendingAction(mPendingAnimationActions.get(i)); + } + mPendingAnimationActions.clear(); } - mPendingAnimationActions.clear(); } } @@ -1285,10 +1498,15 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private boolean useLastSeenTarget() { if (mLastSeenTarget != null) { final RenderNode target = mLastSeenTarget.get(); - if (target != null && target.isAttached()) { - target.addAnimator(this); - return true; - } + return useTarget(target); + } + return false; + } + + private boolean useTarget(RenderNode target) { + if (target != null && target.isAttached()) { + target.registerVectorDrawableAnimator(this); + return true; } return false; } @@ -1316,7 +1534,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } else { addPendingAction(START_ANIMATION); } - } @Override @@ -1480,11 +1697,32 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static void callOnFinished(VectorDrawableAnimatorRT set, int id) { set.onAnimationEnd(id); } + + private void transferPendingActions(VectorDrawableAnimator animatorSet) { + for (int i = 0; i < mPendingAnimationActions.size(); i++) { + int pendingAction = mPendingAnimationActions.get(i); + if (pendingAction == START_ANIMATION) { + animatorSet.start(); + } else if (pendingAction == END_ANIMATION) { + animatorSet.end(); + } else if (pendingAction == REVERSE_ANIMATION) { + animatorSet.reverse(); + } else if (pendingAction == RESET_ANIMATION) { + animatorSet.reset(); + } else { + throw new UnsupportedOperationException("Animation action " + + pendingAction + "is not supported"); + } + } + mPendingAnimationActions.clear(); + } } private static native long nCreateAnimatorSet(); + private static native void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr); private static native void nAddAnimator(long setPtr, long propertyValuesHolder, - long nativeInterpolator, long startDelay, long duration, int repeatCount); + long nativeInterpolator, long startDelay, long duration, int repeatCount, + int repeatMode); private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId, float startValue, float endValue); @@ -1498,6 +1736,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue, float endValue); private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length); + private static native void nSetPropertyHolderData(long nativePtr, int[] data, int length); private static native void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id); private static native void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id); private static native void nEnd(long animatorSetPtr); diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 9d8ede048924923632abf0e2f8499f2a4307393f..df107f5ce3ef5a88befad1be41cd51bbf46834b1 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -463,31 +463,14 @@ public class BitmapDrawable extends Drawable { return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL; } - private void updateMirrorMatrix(float dx) { - if (mMirrorMatrix == null) { - mMirrorMatrix = new Matrix(); - } - mMirrorMatrix.setTranslate(dx, 0); - mMirrorMatrix.preScale(-1.0f, 1.0f); - } - @Override protected void onBoundsChange(Rect bounds) { mDstRectAndInsetsDirty = true; + final Bitmap bitmap = mBitmapState.mBitmap; final Shader shader = mBitmapState.mPaint.getShader(); - if (shader != null) { - if (needMirroring()) { - updateMirrorMatrix(bounds.right - bounds.left); - shader.setLocalMatrix(mMirrorMatrix); - mBitmapState.mPaint.setShader(shader); - } else { - if (mMirrorMatrix != null) { - mMirrorMatrix = null; - shader.setLocalMatrix(Matrix.IDENTITY_MATRIX); - mBitmapState.mPaint.setShader(shader); - } - } + if (bitmap != null && shader != null) { + updateShaderMatrix(bitmap, mBitmapState.mPaint, shader, needMirroring()); } } @@ -548,19 +531,7 @@ public class BitmapDrawable extends Drawable { canvas.restore(); } } else { - if (needMirroring) { - // Mirror the bitmap - updateMirrorMatrix(mDstRect.right - mDstRect.left); - shader.setLocalMatrix(mMirrorMatrix); - paint.setShader(shader); - } else { - if (mMirrorMatrix != null) { - mMirrorMatrix = null; - shader.setLocalMatrix(Matrix.IDENTITY_MATRIX); - paint.setShader(shader); - } - } - + updateShaderMatrix(bitmap, paint, shader, needMirroring); canvas.drawRect(mDstRect, paint); } @@ -573,6 +544,51 @@ public class BitmapDrawable extends Drawable { } } + /** + * Updates the {@code paint}'s shader matrix to be consistent with the + * destination size and layout direction. + * + * @param bitmap the bitmap to be drawn + * @param paint the paint used to draw the bitmap + * @param shader the shader to set on the paint + * @param needMirroring whether the bitmap should be mirrored + */ + private void updateShaderMatrix(@NonNull Bitmap bitmap, @NonNull Paint paint, + @NonNull Shader shader, boolean needMirroring) { + final int sourceDensity = bitmap.getDensity(); + final int targetDensity = mTargetDensity; + final boolean needScaling = sourceDensity != 0 && sourceDensity != targetDensity; + if (needScaling || needMirroring) { + final Matrix matrix = getOrCreateMirrorMatrix(); + matrix.reset(); + + if (needMirroring) { + final int dx = mDstRect.right - mDstRect.left; + matrix.setTranslate(dx, 0); + matrix.setScale(-1, 1); + } + + if (needScaling) { + final float densityScale = targetDensity / (float) sourceDensity; + matrix.postScale(densityScale, densityScale); + } + + shader.setLocalMatrix(matrix); + } else { + mMirrorMatrix = null; + shader.setLocalMatrix(Matrix.IDENTITY_MATRIX); + } + + paint.setShader(shader); + } + + private Matrix getOrCreateMirrorMatrix() { + if (mMirrorMatrix == null) { + mMirrorMatrix = new Matrix(); + } + return mMirrorMatrix; + } + private void updateDstRectAndInsetsIfDirty() { if (mDstRectAndInsetsDirty) { if (mBitmapState.mTileModeX == null && mBitmapState.mTileModeY == null) { diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 7f3a4373639b74c9f050b56eb460881d515e357a..c2e302e184c90029ec03db6cadd3ec624746ecc9 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -109,6 +109,9 @@ import java.util.Collection; *
  • Nine Patch: an extension to the PNG format allows it to * specify information about how to stretch it and place things inside of * it. + *
  • Vector: a drawable defined in an XML file as a set of points, + * lines, and curves along with its associated color information. This type + * of drawable can be scaled without loss of display quality. *
  • Shape: contains simple drawing commands instead of a raw * bitmap, allowing it to resize better in some cases. *
  • Layers: a compound drawable, which draws multiple underlying @@ -1422,9 +1425,10 @@ public abstract class Drawable { /** * Obtains styled attributes from the theme, if available, or unstyled * resources if the theme is null. + * @hide */ - static @NonNull TypedArray obtainAttributes(@NonNull Resources res, @Nullable Theme theme, - @NonNull AttributeSet set, @NonNull int[] attrs) { + protected static @NonNull TypedArray obtainAttributes(@NonNull Resources res, + @Nullable Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs) { if (theme == null) { return res.obtainAttributes(set, attrs); } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index d5143dae785171f5239d61c449e5b5931505b9fc..c7a3c75f3545a763506bce024b29762f858942b8 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -27,8 +27,8 @@ import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.Outline; import android.graphics.PixelFormat; -import android.graphics.Rect; import android.graphics.PorterDuff.Mode; +import android.graphics.Rect; import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.LayoutDirection; @@ -601,8 +601,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { * during inflation. * * @param res the resources used to inflate density-dependent values + * @hide */ - final void updateDensity(Resources res) { + protected final void updateDensity(Resources res) { mDrawableContainerState.updateDensity(res); } @@ -711,7 +712,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mHasTintList; boolean mHasTintMode; - DrawableContainerState(DrawableContainerState orig, DrawableContainer owner, + /** + * @hide + */ + protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner, Resources res) { mOwner = owner; mSourceRes = res != null ? res : (orig != null ? orig.mSourceRes : null); @@ -851,8 +855,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { private Drawable prepareDrawable(Drawable child) { child.setLayoutDirection(mLayoutDirection); - child.setCallback(mOwner); child = child.mutate(); + child.setCallback(mOwner); return child; } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index bcc354c5b73663d542a359fe75788227a5427e3b..8c633b0da93a3204731f406541de1e4b658d21c6 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -475,16 +475,17 @@ public class GradientDrawable extends Drawable { } /** - * Sets the center location in pixels of the gradient. The radius is - * honored only when the gradient type is set to {@link #RADIAL_GRADIENT} - * or {@link #SWEEP_GRADIENT}. + * Sets the position of the center of the gradient as a fraction of the + * width and height. + *

    + * The default value is (0.5, 0.5). *

    * Note: changing this property will affect all instances * of a drawable loaded from a resource. It is recommended to invoke * {@link #mutate()} before changing this property. * - * @param x the x coordinate of the gradient's center in pixels - * @param y the y coordinate of the gradient's center in pixels + * @param x the X-position of the center of the gradient + * @param y the Y-position of the center of the gradient * * @see #mutate() * @see #setGradientType(int) @@ -498,9 +499,10 @@ public class GradientDrawable extends Drawable { } /** - * Returns the center X location of this gradient in pixels. + * Returns the X-position of the center of the gradient as a fraction of + * the width. * - * @return the center X location of this gradient in pixels + * @return the X-position of the center of the gradient * @see #setGradientCenter(float, float) */ public float getGradientCenterX() { @@ -508,9 +510,10 @@ public class GradientDrawable extends Drawable { } /** - * Returns the center Y location of this gradient in pixels. + * Returns the Y-position of the center of this gradient as a fraction of + * the height. * - * @return the center Y location of this gradient in pixels + * @return the Y-position of the center of the gradient * @see #setGradientCenter(float, float) */ public float getGradientCenterY() { @@ -554,19 +557,43 @@ public class GradientDrawable extends Drawable { } /** - * Sets whether or not this drawable will honor its {@code level} property. + * Sets whether this drawable's {@code level} property will be used to + * scale the gradient. If a gradient is not used, this property has no + * effect. *

    - * Note: changing this property will affect all instances + * Scaling behavior varies based on gradient type: + *

      + *
    • {@link #LINEAR_GRADIENT} adjusts the ending position along the + * gradient's axis of orientation (see {@link #getOrientation()}) + *
    • {@link #RADIAL_GRADIENT} adjusts the outer radius + *
    • {@link #SWEEP_GRADIENT} adjusts the ending angle + *
        + *

        + * The default value for this property is {@code false}. + *

        + * Note: This property corresponds to the + * {@code android:useLevel} attribute on the inner {@code <gradient>} + * tag, NOT the {@code android:useLevel} attribute on the outer + * {@code <shape>} tag. For example, + *

        {@code
        +     * 
        +     *     
        +     * 
        +     * }

        + * Note: Changing this property will affect all instances * of a drawable loaded from a resource. It is recommended to invoke * {@link #mutate()} before changing this property. * - * @param useLevel {@code true} if this drawable should honor its level, - * {@code false} otherwise + * @param useLevel {@code true} if the gradient should be scaled based on + * level, {@code false} otherwise * * @see #mutate() * @see #setLevel(int) * @see #getLevel() * @see #getUseLevel() + * @attr ref android.R.styleable#GradientDrawableGradient_useLevel */ public void setUseLevel(boolean useLevel) { mGradientState.mUseLevel = useLevel; @@ -575,12 +602,13 @@ public class GradientDrawable extends Drawable { } /** - * Returns whether or not this drawable will honor its {@code level} - * property. + * Returns whether this drawable's {@code level} property will be used to + * scale the gradient. * - * @return {@code true} if this drawable should honor its level, + * @return {@code true} if the gradient should be scaled based on level, * {@code false} otherwise * @see #setUseLevel(boolean) + * @attr ref android.R.styleable#GradientDrawableGradient_useLevel */ public boolean getUseLevel() { return mGradientState.mUseLevel; @@ -699,7 +727,7 @@ public class GradientDrawable extends Drawable { float rad = mStrokePaint.getStrokeWidth(); canvas.saveLayer(mRect.left - rad, mRect.top - rad, mRect.right + rad, mRect.bottom + rad, - mLayerPaint, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); + mLayerPaint); // don't perform the filter in our individual paints // since the layer will do it for us diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 1864206118b2155f8b29f6bbf19f9cacbe986931..c30c4c2f02d6c4a0e72dc347b685a7dcfe5b13c3 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -269,7 +269,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { // If the layer doesn't have a drawable or unresolved theme // attribute for a drawable, attempt to parse one from the child - // element. + // element. If multiple child elements exist, we'll only use the + // first one. if (layer.mDrawable == null && (layer.mThemeAttrs == null || layer.mThemeAttrs[R.styleable.LayerDrawableItem_drawable] == 0)) { while ((type = parser.next()) == XmlPullParser.TEXT) { @@ -279,13 +280,12 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { + ": tag requires a 'drawable' attribute or " + "child tag defining a drawable"); } - layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme); - } - if (layer.mDrawable != null) { + // We found a child drawable. Take ownership. + layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme); + layer.mDrawable.setCallback(this); state.mChildrenChangingConfigurations |= layer.mDrawable.getChangingConfigurations(); - layer.mDrawable.setCallback(this); } addLayer(layer); @@ -387,7 +387,19 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { final Drawable dr = a.getDrawable(R.styleable.LayerDrawableItem_drawable); if (dr != null) { + if (layer.mDrawable != null) { + // It's possible that a drawable was already set, in which case + // we should clear the callback. We may have also integrated the + // drawable's changing configurations, but we don't have enough + // information to revert that change. + layer.mDrawable.setCallback(null); + } + + // Take ownership of the new drawable. layer.mDrawable = dr; + layer.mDrawable.setCallback(this); + state.mChildrenChangingConfigurations |= + layer.mDrawable.getChangingConfigurations(); } } diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index f5592fa7e40795474ab1f1edf20f3dc05d9062c7..1ca15525c8a1aca39001f30813612676137f5119 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -27,16 +27,19 @@ import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Insets; import android.graphics.PixelFormat; +import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; -import android.graphics.PorterDuff.Mode; import android.graphics.Shader; import android.util.ArrayMap; import android.util.AttributeSet; import android.util.DisplayMetrics; +import android.util.FloatProperty; +import android.util.IntProperty; import android.util.LayoutDirection; import android.util.Log; import android.util.PathParser; +import android.util.Property; import android.util.Xml; import com.android.internal.R; @@ -73,27 +76,36 @@ import dalvik.system.VMRuntime; *

        *
        android:name
        *
        Defines the name of this vector drawable.
        + *
        Animatable : No.
        *
        android:width
        *
        Used to define the intrinsic width of the drawable. * This support all the dimension units, normally specified with dp.
        + *
        Animatable : No.
        *
        android:height
        *
        Used to define the intrinsic height the drawable. * This support all the dimension units, normally specified with dp.
        + *
        Animatable : No.
        *
        android:viewportWidth
        *
        Used to define the width of the viewport space. Viewport is basically * the virtual canvas where the paths are drawn on.
        + *
        Animatable : No.
        *
        android:viewportHeight
        *
        Used to define the height of the viewport space. Viewport is basically * the virtual canvas where the paths are drawn on.
        + *
        Animatable : No.
        *
        android:tint
        *
        The color to apply to the drawable as a tint. By default, no tint is applied.
        + *
        Animatable : No.
        *
        android:tintMode
        *
        The Porter-Duff blending mode for the tint color. The default value is src_in.
        + *
        Animatable : No.
        *
        android:autoMirrored
        *
        Indicates if the drawable needs to be mirrored when its layout direction is * RTL (right-to-left).
        + *
        Animatable : No.
        *
        android:alpha
        *
        The opacity of this drawable.
        + *
        Animatable : Yes.
        *
        * * @@ -105,24 +117,32 @@ import dalvik.system.VMRuntime; *
        *
        android:name
        *
        Defines the name of the group.
        + *
        Animatable : No.
        *
        android:rotation
        *
        The degrees of rotation of the group.
        + *
        Animatable : Yes.
        *
        android:pivotX
        *
        The X coordinate of the pivot for the scale and rotation of the group. * This is defined in the viewport space.
        + *
        Animatable : Yes.
        *
        android:pivotY
        *
        The Y coordinate of the pivot for the scale and rotation of the group. * This is defined in the viewport space.
        + *
        Animatable : Yes.
        *
        android:scaleX
        *
        The amount of scale on the X Coordinate.
        + *
        Animatable : Yes.
        *
        android:scaleY
        *
        The amount of scale on the Y coordinate.
        + *
        Animatable : Yes.
        *
        android:translateX
        *
        The amount of translation on the X coordinate. * This is defined in the viewport space.
        + *
        Animatable : Yes.
        *
        android:translateY
        *
        The amount of translation on the Y coordinate. * This is defined in the viewport space.
        + *
        Animatable : Yes.
        *
        * * @@ -132,40 +152,60 @@ import dalvik.system.VMRuntime; *
        *
        android:name
        *
        Defines the name of the path.
        + *
        Animatable : No.
        *
        android:pathData
        *
        Defines path data using exactly same format as "d" attribute * in the SVG's path data. This is defined in the viewport space.
        + *
        Animatable : Yes.
        *
        android:fillColor
        *
        Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list - * or a gradient color. If this property is animated, any value set by the animation will - * override the original value. No path fill is drawn if this property is not specified.
        + * or a gradient color (See {@link android.R.styleable#GradientColor} + * and {@link android.R.styleable#GradientColorItem}). + * If this property is animated, any value set by the animation will override the original value. + * No path fill is drawn if this property is not specified. + *
        Animatable : Yes.
        *
        android:strokeColor
        *
        Specifies the color used to draw the path outline. May be a color or, for SDK 24+, a color - * state list or a gradient color. If this property is animated, any value set by the animation will - * override the original value. No path outline is drawn if this property is not specified.
        + * state list or a gradient color (See {@link android.R.styleable#GradientColor} + * and {@link android.R.styleable#GradientColorItem}). + * If this property is animated, any value set by the animation will override the original value. + * No path outline is drawn if this property is not specified. + *
        Animatable : Yes.
        *
        android:strokeWidth
        *
        The width a path stroke.
        + *
        Animatable : Yes.
        *
        android:strokeAlpha
        *
        The opacity of a path stroke.
        + *
        Animatable : Yes.
        *
        android:fillAlpha
        *
        The opacity to fill the path with.
        + *
        Animatable : Yes.
        *
        android:trimPathStart
        *
        The fraction of the path to trim from the start, in the range from 0 to 1.
        + *
        Animatable : Yes.
        *
        android:trimPathEnd
        *
        The fraction of the path to trim from the end, in the range from 0 to 1.
        + *
        Animatable : Yes.
        *
        android:trimPathOffset
        *
        Shift trim region (allows showed region to include the start and end), in the range * from 0 to 1.
        + *
        Animatable : Yes.
        *
        android:strokeLineCap
        *
        Sets the linecap for a stroked path: butt, round, square.
        + *
        Animatable : No.
        *
        android:strokeLineJoin
        *
        Sets the lineJoin for a stroked path: miter,round,bevel.
        + *
        Animatable : No.
        *
        android:strokeMiterLimit
        *
        Sets the Miter limit for a stroked path.
        + *
        Animatable : No.
        *
        android:fillType
        - *
        Sets the fillType for a path. It is the same as SVG's "fill-rule" properties. - * For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
        + *
        Sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the + * same as SVG's "fill-rule" properties. For more details, see + * FillRuleProperty
        + *
        Animatable : No.
        *
        + * * * *
        @@ -175,9 +215,11 @@ import dalvik.system.VMRuntime; *
        *
        android:name
        *
        Defines the name of the clip path.
        + *
        Animatable : No.
        *
        android:pathData
        *
        Defines clip path using the same format as "d" attribute * in the SVG's path data.
        + *
        Animatable : Yes.
        *
        *
        *
      • Here is a simple VectorDrawable in this vectordrawable.xml file. @@ -198,7 +240,26 @@ import dalvik.system.VMRuntime; * android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> * </group> * </vector> - *
      • + * + * + *
      • And here is an example of linear gradient color, which is supported in SDK 24+. + * See more details in {@link android.R.styleable#GradientColor} and + * {@link android.R.styleable#GradientColorItem}. + *
        + * <gradient xmlns:android="http://schemas.android.com/apk/res/android"
        + *     android:angle="90"
        + *     android:startColor="?android:attr/colorPrimary"
        + *     android:endColor="?android:attr/colorControlActivated"
        + *     android:centerColor="#f00"
        + *     android:startX="0"
        + *     android:startY="0"
        + *     android:endX="100"
        + *     android:endY="100"
        + *     android:type="linear">
        + * </gradient>
        + * 
        + *
      • + * */ public class VectorDrawable extends Drawable { @@ -232,7 +293,7 @@ public class VectorDrawable extends Drawable { private final Rect mTmpBounds = new Rect(); public VectorDrawable() { - this(new VectorDrawableState(), null); + this(new VectorDrawableState(null), null); } /** @@ -386,6 +447,11 @@ public class VectorDrawable extends Drawable { protected boolean onStateChange(int[] stateSet) { boolean changed = false; + // When the VD is stateful, we need to mutate the drawable such that we don't share the + // cache bitmap with others. Such that the state change only affect this new cached bitmap. + if (isStateful()) { + mutate(); + } final VectorDrawableState state = mVectorState; if (state.onStateChange(stateSet)) { changed = true; @@ -678,7 +744,11 @@ public class VectorDrawable extends Drawable { groupStack.push(state.mRootGroup); int eventType = parser.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { + final int innerDepth = parser.getDepth() + 1; + + // Parse everything until the end of the vector element. + while (eventType != XmlPullParser.END_DOCUMENT + && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) { if (eventType == XmlPullParser.START_TAG) { final String tagName = parser.getName(); final VGroup currentGroup = groupStack.peek(); @@ -758,6 +828,13 @@ public class VectorDrawable extends Drawable { return mVectorState.mAutoMirrored; } + /** + * @hide + */ + public long getNativeTree() { + return mVectorState.getNativeRenderer(); + } + static class VectorDrawableState extends ConstantState { // Variables below need to be copied (deep copy if applicable) for mutation. int[] mThemeAttrs; @@ -790,12 +867,33 @@ public class VectorDrawable extends Drawable { int mLastSWCachePixelCount = 0; int mLastHWCachePixelCount = 0; + final static Property ALPHA = + new FloatProperty("alpha") { + @Override + public void setValue(VectorDrawableState state, float value) { + state.setAlpha(value); + } + + @Override + public Float get(VectorDrawableState state) { + return state.getAlpha(); + } + }; + + Property getProperty(String propertyName) { + if (ALPHA.getName().equals(propertyName)) { + return ALPHA; + } + return null; + } + // This tracks the total native allocation for all the nodes. private int mAllocationOfAllNodes = 0; private static final int NATIVE_ALLOCATION_SIZE = 316; - // Deep copy for mutate() or implicitly mutate. + // If copy is not null, deep copy the given VectorDrawableState. Otherwise, create a + // native vector drawable tree with an empty root group. public VectorDrawableState(VectorDrawableState copy) { if (copy != null) { mThemeAttrs = copy.mThemeAttrs; @@ -816,8 +914,11 @@ public class VectorDrawable extends Drawable { if (copy.mRootName != null) { mVGTargetsMap.put(copy.mRootName, this); } - onTreeConstructionFinished(); + } else { + mRootGroup = new VGroup(); + createNativeTree(mRootGroup); } + onTreeConstructionFinished(); } private void createNativeTree(VGroup rootGroup) { @@ -835,7 +936,8 @@ public class VectorDrawable extends Drawable { VMRuntime.getRuntime().registerNativeAllocation(NATIVE_ALLOCATION_SIZE); } - + // This should be called every time after a new RootGroup and all its subtrees are created + // (i.e. in constructors of VectorDrawableState and in inflate). void onTreeConstructionFinished() { mRootGroup.setTree(mNativeTree); mAllocationOfAllNodes = mRootGroup.getNativeSize(); @@ -883,11 +985,6 @@ public class VectorDrawable extends Drawable { || super.canApplyTheme(); } - public VectorDrawableState() { - mRootGroup = new VGroup(); - createNativeTree(mRootGroup); - } - @Override public Drawable newDrawable() { return new VectorDrawable(this, null); @@ -967,7 +1064,7 @@ public class VectorDrawable extends Drawable { } static class VGroup extends VObject { - private static final int ROTATE_INDEX = 0; + private static final int ROTATION_INDEX = 0; private static final int PIVOT_X_INDEX = 1; private static final int PIVOT_Y_INDEX = 2; private static final int SCALE_X_INDEX = 3; @@ -978,7 +1075,7 @@ public class VectorDrawable extends Drawable { private static final int NATIVE_ALLOCATION_SIZE = 100; - private static final HashMap sPropertyMap = + private static final HashMap sPropertyIndexMap = new HashMap() { { put("translateX", TRANSLATE_X_INDEX); @@ -987,19 +1084,123 @@ public class VectorDrawable extends Drawable { put("scaleY", SCALE_Y_INDEX); put("pivotX", PIVOT_X_INDEX); put("pivotY", PIVOT_Y_INDEX); - put("rotation", ROTATE_INDEX); + put("rotation", ROTATION_INDEX); } }; static int getPropertyIndex(String propertyName) { - if (sPropertyMap.containsKey(propertyName)) { - return sPropertyMap.get(propertyName); + if (sPropertyIndexMap.containsKey(propertyName)) { + return sPropertyIndexMap.get(propertyName); } else { // property not found return -1; } } + // Below are the Properties that wrap the setters to avoid reflection overhead in animations + private static final Property TRANSLATE_X = + new FloatProperty ("translateX") { + @Override + public void setValue(VGroup object, float value) { + object.setTranslateX(value); + } + + @Override + public Float get(VGroup object) { + return object.getTranslateX(); + } + }; + + private static final Property TRANSLATE_Y = + new FloatProperty ("translateY") { + @Override + public void setValue(VGroup object, float value) { + object.setTranslateY(value); + } + + @Override + public Float get(VGroup object) { + return object.getTranslateY(); + } + }; + + private static final Property SCALE_X = + new FloatProperty ("scaleX") { + @Override + public void setValue(VGroup object, float value) { + object.setScaleX(value); + } + + @Override + public Float get(VGroup object) { + return object.getScaleX(); + } + }; + + private static final Property SCALE_Y = + new FloatProperty ("scaleY") { + @Override + public void setValue(VGroup object, float value) { + object.setScaleY(value); + } + + @Override + public Float get(VGroup object) { + return object.getScaleY(); + } + }; + + private static final Property PIVOT_X = + new FloatProperty ("pivotX") { + @Override + public void setValue(VGroup object, float value) { + object.setPivotX(value); + } + + @Override + public Float get(VGroup object) { + return object.getPivotX(); + } + }; + + private static final Property PIVOT_Y = + new FloatProperty ("pivotY") { + @Override + public void setValue(VGroup object, float value) { + object.setPivotY(value); + } + + @Override + public Float get(VGroup object) { + return object.getPivotY(); + } + }; + + private static final Property ROTATION = + new FloatProperty ("rotation") { + @Override + public void setValue(VGroup object, float value) { + object.setRotation(value); + } + + @Override + public Float get(VGroup object) { + return object.getRotation(); + } + }; + + private static final HashMap sPropertyMap = + new HashMap() { + { + put("translateX", TRANSLATE_X); + put("translateY", TRANSLATE_Y); + put("scaleX", SCALE_X); + put("scaleY", SCALE_Y); + put("pivotX", PIVOT_X); + put("pivotY", PIVOT_Y); + put("rotation", ROTATION); + } + }; // Temp array to store transform values obtained from native. private float[] mTransform; ///////////////////////////////////////////////////// @@ -1055,6 +1256,15 @@ public class VectorDrawable extends Drawable { mNativePtr = nCreateGroup(); } + Property getProperty(String propertyName) { + if (sPropertyMap.containsKey(propertyName)) { + return sPropertyMap.get(propertyName); + } else { + // property not found + return null; + } + } + public String getGroupName() { return mGroupName; } @@ -1102,7 +1312,7 @@ public class VectorDrawable extends Drawable { throw new RuntimeException("Error: inconsistent property count"); } float rotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, - mTransform[ROTATE_INDEX]); + mTransform[ROTATION_INDEX]); float pivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mTransform[PIVOT_X_INDEX]); float pivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, @@ -1288,6 +1498,27 @@ public class VectorDrawable extends Drawable { String mPathName; @Config int mChangingConfigurations; + private static final Property PATH_DATA = + new Property(PathParser.PathData.class, "pathData") { + @Override + public void set(VPath object, PathParser.PathData data) { + object.setPathData(data); + } + + @Override + public PathParser.PathData get(VPath object) { + return object.getPathData(); + } + }; + + Property getProperty(String propertyName) { + if (PATH_DATA.getName().equals(propertyName)) { + return PATH_DATA; + } + // property not found + return null; + } + public VPath() { // Empty constructor. } @@ -1410,7 +1641,7 @@ public class VectorDrawable extends Drawable { private static final int NATIVE_ALLOCATION_SIZE = 264; // Property map for animatable attributes. - private final static HashMap sPropertyMap + private final static HashMap sPropertyIndexMap = new HashMap () { { put("strokeWidth", STROKE_WIDTH_INDEX); @@ -1424,6 +1655,125 @@ public class VectorDrawable extends Drawable { } }; + // Below are the Properties that wrap the setters to avoid reflection overhead in animations + private static final Property STROKE_WIDTH = + new FloatProperty ("strokeWidth") { + @Override + public void setValue(VFullPath object, float value) { + object.setStrokeWidth(value); + } + + @Override + public Float get(VFullPath object) { + return object.getStrokeWidth(); + } + }; + + private static final Property STROKE_COLOR = + new IntProperty ("strokeColor") { + @Override + public void setValue(VFullPath object, int value) { + object.setStrokeColor(value); + } + + @Override + public Integer get(VFullPath object) { + return object.getStrokeColor(); + } + }; + + private static final Property STROKE_ALPHA = + new FloatProperty ("strokeAlpha") { + @Override + public void setValue(VFullPath object, float value) { + object.setStrokeAlpha(value); + } + + @Override + public Float get(VFullPath object) { + return object.getStrokeAlpha(); + } + }; + + private static final Property FILL_COLOR = + new IntProperty("fillColor") { + @Override + public void setValue(VFullPath object, int value) { + object.setFillColor(value); + } + + @Override + public Integer get(VFullPath object) { + return object.getFillColor(); + } + }; + + private static final Property FILL_ALPHA = + new FloatProperty ("fillAlpha") { + @Override + public void setValue(VFullPath object, float value) { + object.setFillAlpha(value); + } + + @Override + public Float get(VFullPath object) { + return object.getFillAlpha(); + } + }; + + private static final Property TRIM_PATH_START = + new FloatProperty ("trimPathStart") { + @Override + public void setValue(VFullPath object, float value) { + object.setTrimPathStart(value); + } + + @Override + public Float get(VFullPath object) { + return object.getTrimPathStart(); + } + }; + + private static final Property TRIM_PATH_END = + new FloatProperty ("trimPathEnd") { + @Override + public void setValue(VFullPath object, float value) { + object.setTrimPathEnd(value); + } + + @Override + public Float get(VFullPath object) { + return object.getTrimPathEnd(); + } + }; + + private static final Property TRIM_PATH_OFFSET = + new FloatProperty ("trimPathOffset") { + @Override + public void setValue(VFullPath object, float value) { + object.setTrimPathOffset(value); + } + + @Override + public Float get(VFullPath object) { + return object.getTrimPathOffset(); + } + }; + + private final static HashMap sPropertyMap + = new HashMap () { + { + put("strokeWidth", STROKE_WIDTH); + put("strokeColor", STROKE_COLOR); + put("strokeAlpha", STROKE_ALPHA); + put("fillColor", FILL_COLOR); + put("fillAlpha", FILL_ALPHA); + put("trimPathStart", TRIM_PATH_START); + put("trimPathEnd", TRIM_PATH_END); + put("trimPathOffset", TRIM_PATH_OFFSET); + } + }; + // Temp array to store property data obtained from native getter. private byte[] mPropertyData; ///////////////////////////////////////////////////// @@ -1446,11 +1796,24 @@ public class VectorDrawable extends Drawable { mFillColors = copy.mFillColors; } + Property getProperty(String propertyName) { + Property p = super.getProperty(propertyName); + if (p != null) { + return p; + } + if (sPropertyMap.containsKey(propertyName)) { + return sPropertyMap.get(propertyName); + } else { + // property not found + return null; + } + } + int getPropertyIndex(String propertyName) { - if (!sPropertyMap.containsKey(propertyName)) { + if (!sPropertyIndexMap.containsKey(propertyName)) { return -1; } else { - return sPropertyMap.get(propertyName); + return sPropertyIndexMap.get(propertyName); } } @@ -1784,6 +2147,7 @@ public class VectorDrawable extends Drawable { abstract boolean onStateChange(int[] state); abstract boolean isStateful(); abstract int getNativeSize(); + abstract Property getProperty(String propertyName); } private static native long nCreateTree(long rootGroupPtr); diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java index 2b70b6a45f827f7ed32a2a7afe375d5ded232fe5..cd1f8de6ee0f824147c5024dd6d03e915113bb48 100644 --- a/graphics/java/android/graphics/pdf/PdfEditor.java +++ b/graphics/java/android/graphics/pdf/PdfEditor.java @@ -79,8 +79,12 @@ public final class PdfEditor { } mInput = input; - mNativeDocument = nativeOpen(mInput.getFd(), size); - mPageCount = nativeGetPageCount(mNativeDocument); + + synchronized (PdfRenderer.sPdfiumLock) { + mNativeDocument = nativeOpen(mInput.getFd(), size); + mPageCount = nativeGetPageCount(mNativeDocument); + } + mCloseGuard.open("close"); } @@ -102,7 +106,10 @@ public final class PdfEditor { public void removePage(int pageIndex) { throwIfClosed(); throwIfPageNotInDocument(pageIndex); - mPageCount = nativeRemovePage(mNativeDocument, pageIndex); + + synchronized (PdfRenderer.sPdfiumLock) { + mPageCount = nativeRemovePage(mNativeDocument, pageIndex); + } } /** @@ -125,11 +132,16 @@ public final class PdfEditor { if (clip == null) { Point size = new Point(); getPageSize(pageIndex, size); - nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, - 0, 0, size.x, size.y); + + synchronized (PdfRenderer.sPdfiumLock) { + nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, + 0, 0, size.x, size.y); + } } else { - nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, - clip.left, clip.top, clip.right, clip.bottom); + synchronized (PdfRenderer.sPdfiumLock) { + nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance, + clip.left, clip.top, clip.right, clip.bottom); + } } } @@ -143,7 +155,10 @@ public final class PdfEditor { throwIfClosed(); throwIfOutSizeNull(outSize); throwIfPageNotInDocument(pageIndex); - nativeGetPageSize(mNativeDocument, pageIndex, outSize); + + synchronized (PdfRenderer.sPdfiumLock) { + nativeGetPageSize(mNativeDocument, pageIndex, outSize); + } } /** @@ -156,7 +171,10 @@ public final class PdfEditor { throwIfClosed(); throwIfOutMediaBoxNull(outMediaBox); throwIfPageNotInDocument(pageIndex); - return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox); + + synchronized (PdfRenderer.sPdfiumLock) { + return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox); + } } /** @@ -169,7 +187,10 @@ public final class PdfEditor { throwIfClosed(); throwIfMediaBoxNull(mediaBox); throwIfPageNotInDocument(pageIndex); - nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox); + + synchronized (PdfRenderer.sPdfiumLock) { + nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox); + } } /** @@ -182,7 +203,10 @@ public final class PdfEditor { throwIfClosed(); throwIfOutCropBoxNull(outCropBox); throwIfPageNotInDocument(pageIndex); - return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox); + + synchronized (PdfRenderer.sPdfiumLock) { + return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox); + } } /** @@ -195,7 +219,10 @@ public final class PdfEditor { throwIfClosed(); throwIfCropBoxNull(cropBox); throwIfPageNotInDocument(pageIndex); - nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox); + + synchronized (PdfRenderer.sPdfiumLock) { + nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox); + } } /** @@ -205,7 +232,10 @@ public final class PdfEditor { */ public boolean shouldScaleForPrinting() { throwIfClosed(); - return nativeScaleForPrinting(mNativeDocument); + + synchronized (PdfRenderer.sPdfiumLock) { + return nativeScaleForPrinting(mNativeDocument); + } } /** @@ -219,7 +249,10 @@ public final class PdfEditor { public void write(ParcelFileDescriptor output) throws IOException { try { throwIfClosed(); - nativeWrite(mNativeDocument, output.getFd()); + + synchronized (PdfRenderer.sPdfiumLock) { + nativeWrite(mNativeDocument, output.getFd()); + } } finally { IoUtils.closeQuietly(output); } @@ -247,7 +280,9 @@ public final class PdfEditor { } private void doClose() { - nativeClose(mNativeDocument); + synchronized (PdfRenderer.sPdfiumLock) { + nativeClose(mNativeDocument); + } IoUtils.closeQuietly(mInput); mInput = null; mCloseGuard.close(); diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index 520ebe5f2db88016145635e839d66711b03b869a..cfc130990e926a2f2874a354e16dc9605225c812 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -99,6 +99,12 @@ import java.lang.annotation.RetentionPolicy; * @see #close() */ public final class PdfRenderer implements AutoCloseable { + /** + * Any call the native pdfium code has to be single threaded as the library does not support + * parallel use. + */ + final static Object sPdfiumLock = new Object(); + private final CloseGuard mCloseGuard = CloseGuard.get(); private final Point mTempPoint = new Point(); @@ -154,8 +160,12 @@ public final class PdfRenderer implements AutoCloseable { } mInput = input; - mNativeDocument = nativeCreate(mInput.getFd(), size); - mPageCount = nativeGetPageCount(mNativeDocument); + + synchronized (sPdfiumLock) { + mNativeDocument = nativeCreate(mInput.getFd(), size); + mPageCount = nativeGetPageCount(mNativeDocument); + } + mCloseGuard.open("close"); } @@ -189,7 +199,10 @@ public final class PdfRenderer implements AutoCloseable { */ public boolean shouldScaleForPrinting() { throwIfClosed(); - return nativeScaleForPrinting(mNativeDocument); + + synchronized (sPdfiumLock) { + return nativeScaleForPrinting(mNativeDocument); + } } /** @@ -224,7 +237,9 @@ public final class PdfRenderer implements AutoCloseable { if (mCurrentPage != null) { mCurrentPage.close(); } - nativeClose(mNativeDocument); + synchronized (sPdfiumLock) { + nativeClose(mNativeDocument); + } try { mInput.close(); } catch (IOException ioe) { @@ -277,7 +292,9 @@ public final class PdfRenderer implements AutoCloseable { private Page(int index) { Point size = mTempPoint; - mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); + synchronized (sPdfiumLock) { + mNativePage = nativeOpenPageAndGetSize(mNativeDocument, index, size); + } mIndex = index; mWidth = size.x; mHeight = size.y; @@ -384,8 +401,10 @@ public final class PdfRenderer implements AutoCloseable { final long transformPtr = (transform != null) ? transform.native_instance : 0; - nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft, - contentTop, contentRight, contentBottom, transformPtr, renderMode); + synchronized (sPdfiumLock) { + nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft, + contentTop, contentRight, contentBottom, transformPtr, renderMode); + } } /** @@ -412,7 +431,9 @@ public final class PdfRenderer implements AutoCloseable { } private void doClose() { - nativeClosePage(mNativePage); + synchronized (sPdfiumLock) { + nativeClosePage(mNativePage); + } mNativePage = 0; mCloseGuard.close(); mCurrentPage = null; diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index cce58c2096f352b64c2c3cc7685af7b8f9ea52b3..a96ca3922296628bce81c930cfec112f2fd670a7 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.annotation.WorkerThread; import android.app.Activity; import android.app.PendingIntent; +import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -356,6 +357,9 @@ public final class KeyChain { * *

        This method may block while waiting for a connection to another process, and must never * be called from the main thread. + *

        As {@link Activity} and {@link Service} contexts are short-lived and can be destroyed + * at any time from the main thread, it is safer to rely on a long-lived context such as one + * returned from {@link Context#getApplicationContext()}. * * @param alias The alias of the desired private key, typically returned via * {@link KeyChainAliasCallback#alias}. @@ -368,7 +372,7 @@ public final class KeyChain { if (alias == null) { throw new NullPointerException("alias == null"); } - KeyChainConnection keyChainConnection = bind(context); + KeyChainConnection keyChainConnection = bind(context.getApplicationContext()); try { final IKeyChainService keyChainService = keyChainConnection.getService(); final String keyId = keyChainService.requestPrivateKey(alias); @@ -400,6 +404,9 @@ public final class KeyChain { * *

        This method may block while waiting for a connection to another process, and must never * be called from the main thread. + *

        As {@link Activity} and {@link Service} contexts are short-lived and can be destroyed + * at any time from the main thread, it is safer to rely on a long-lived context such as one + * returned from {@link Context#getApplicationContext()}. * * @param alias The alias of the desired certificate chain, typically * returned via {@link KeyChainAliasCallback#alias}. @@ -412,7 +419,7 @@ public final class KeyChain { if (alias == null) { throw new NullPointerException("alias == null"); } - KeyChainConnection keyChainConnection = bind(context); + KeyChainConnection keyChainConnection = bind(context.getApplicationContext()); try { IKeyChainService keyChainService = keyChainConnection.getService(); diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index d8493175e63fa8db660d3750cc26f678e51f3304..d023866ca7024c94db2ece65763e60121f31d585 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -251,8 +251,9 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Builder class for {@link KeyPairGeneratorSpec} objects. *

        - * This will build a parameter spec for use with the Android KeyStore facility. + * This will build a parameter spec for use with the + * Android KeyStore + * facility. *

        * The required fields must be filled in with the builder. *

        diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 70e4b6ff2e59081603b171bc39e5d554d2a7a8f7..00d786a93626d4fd69d27b582193229710fec395 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -626,6 +626,16 @@ public class KeyStore { } } + /** + * Notify keystore that the device went off-body. + */ + public void onDeviceOffBody() { + try { + mBinder.onDeviceOffBody(); + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + } + } /** * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java index 8c20ddcc33ad4a3e0769f83d0c407b6034a3e440..f36c00ce8b86209a8e57403843b940d0d98fc98b 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java @@ -228,7 +228,7 @@ public class AndroidKeyStoreProvider extends Provider { if (exportResult.resultCode != KeyStore.NO_ERROR) { throw (UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain X.509 form of public key") - .initCause(KeyStore.getKeyStoreException(errorCode)); + .initCause(KeyStore.getKeyStoreException(exportResult.resultCode)); } final byte[] x509EncodedPublicKey = exportResult.exportData; diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index cbef540562e12e4efc9e4c5033e366a3965d6026..ed40b77be4a49c7e42c94f3ba7955b9d3784c208 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -571,13 +571,12 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { * *

        If this method returns {@code null}, and the spec is used to generate an asymmetric (RSA * or EC) key pair, the public key will have a self-signed certificate if it has purpose {@link - * KeyProperties#PURPOSE_SIGN} (see {@link #KeyGenParameterSpec(String, int)). If does not have - * purpose {@link KeyProperties#PURPOSE_SIGN}, it will have a fake certificate. + * KeyProperties#PURPOSE_SIGN}. If does not have purpose {@link KeyProperties#PURPOSE_SIGN}, it + * will have a fake certificate. * *

        Symmetric keys, such as AES and HMAC keys, do not have public key certificates. If a - * {@link KeyGenParameterSpec} with {@link #hasAttestationCertificate()} returning - * non-{@code null} is used to generate a symmetric (AES or HMAC) key, - * {@link KeyGenerator#generateKey())} will throw + * KeyGenParameterSpec with getAttestationChallenge returning non-null is used to generate a + * symmetric (AES or HMAC) key, {@link javax.crypto.KeyGenerator#generateKey()} will throw * {@link java.security.InvalidAlgorithmParameterException}. * * @see Builder#setAttestationChallenge(byte[]) @@ -1050,11 +1049,6 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { return this; } - /* - * TODO(swillden): Update this documentation to describe the hardware and software root - * keys, including information about CRL/OCSP services for discovering revocations, and to - * link to documentation of the extension format and content. - */ /** * Sets whether an attestation certificate will be generated for this key pair, and what * challenge value will be placed in the certificate. The attestation certificate chain @@ -1074,17 +1068,15 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { * *

        If {@code attestationChallenge} is {@code null}, and this spec is used to generate an * asymmetric (RSA or EC) key pair, the public key certificate will be self-signed if the - * key has purpose {@link KeyProperties#PURPOSE_SIGN} (see - * {@link #KeyGenParameterSpec(String, int)). If the key does not have purpose - * {@link KeyProperties#PURPOSE_SIGN}, it is not possible to use the key to sign a - * certificate, so the public key certificate will contain a dummy signature. + * key has purpose {@link android.security.keystore.KeyProperties#PURPOSE_SIGN}. If the key + * does not have purpose {@link android.security.keystore.KeyProperties#PURPOSE_SIGN}, it is + * not possible to use the key to sign a certificate, so the public key certificate will + * contain a dummy signature. * *

        Symmetric keys, such as AES and HMAC keys, do not have public key certificates. If a - * {@code getAttestationChallenge} returns non-{@code null} and the spec is used to - * generate a symmetric (AES or HMAC) key, {@link KeyGenerator#generateKey()} will throw + * {@link #getAttestationChallenge()} returns non-null and the spec is used to generate a + * symmetric (AES or HMAC) key, {@link javax.crypto.KeyGenerator#generateKey()} will throw * {@link java.security.InvalidAlgorithmParameterException}. - * - * @see Builder#setAttestationChallenge(String attestationChallenge) */ @NonNull public Builder setAttestationChallenge(byte[] attestationChallenge) { diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 7a103430feb5f0e773c89cf4fb85520a35379d06..81e91a80783b807f98709495fbb17d1717a8c67f 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -79,6 +79,7 @@ static volatile int32_t gCount = 0; const char* AssetManager::RESOURCES_FILENAME = "resources.arsc"; const char* AssetManager::IDMAP_BIN = "/system/bin/idmap"; const char* AssetManager::OVERLAY_DIR = "/vendor/overlay"; +const char* AssetManager::OVERLAY_SKU_DIR_PROPERTY = "ro.boot.vendor.overlay.sku"; const char* AssetManager::TARGET_PACKAGE_NAME = "android"; const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk"; const char* AssetManager::IDMAP_DIR = "/data/resource-cache"; diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h index 1a59e445613678d7ddc2e95a17a87fffa49a3a1d..b39dccf44a8b6984c7d4f55d1214705fc4ed73b2 100644 --- a/libs/androidfw/include/androidfw/AssetManager.h +++ b/libs/androidfw/include/androidfw/AssetManager.h @@ -63,6 +63,12 @@ public: static const char* RESOURCES_FILENAME; static const char* IDMAP_BIN; static const char* OVERLAY_DIR; + /* + * If OVERLAY_SKU_DIR_PROPERTY is set, search for runtime resource overlay + * APKs in OVERLAY_DIR/ rather than in + * OVERLAY_DIR. + */ + static const char* OVERLAY_SKU_DIR_PROPERTY; static const char* TARGET_PACKAGE_NAME; static const char* TARGET_APK_PATH; static const char* IDMAP_DIR; diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 5dcfa4e102fd21a358fbc3eef867bed72aab3923..a7cbf5e562d161811c6c07facb12f3f9e4fadd82 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -3,6 +3,7 @@ include $(CLEAR_VARS) LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk HWUI_NEW_OPS := true +BUGREPORT_FONT_CACHE_USAGE := false # Enables fine-grained GLES error checking # If set to true, every GLES call is wrapped & error checked @@ -113,6 +114,10 @@ hwui_cflags := \ -DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \ -Wall -Wno-unused-parameter -Wunreachable-code -Werror +ifeq ($(TARGET_USES_HWC2),true) + hwui_cflags += -DUSE_HWC2 +endif + # GCC false-positives on this warning, and since we -Werror that's # a problem hwui_cflags += -Wno-free-nonheap-object @@ -131,6 +136,13 @@ ifeq (true, $(HWUI_NEW_OPS)) endif +ifeq (true, $(BUGREPORT_FONT_CACHE_USAGE)) + hwui_src_files += \ + font/FontCacheHistoryTracker.cpp + hwui_cflags += -DBUGREPORT_FONT_CACHE_USAGE +endif + + ifndef HWUI_COMPILE_SYMBOLS hwui_cflags += -fvisibility=hidden endif diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h index 395dc73cfdf08644e8836e9877494a515bd97223..71ee8602a29f2cacfa86797cedb19a2d83f2487b 100644 --- a/libs/hwui/AnimationContext.h +++ b/libs/hwui/AnimationContext.h @@ -100,6 +100,8 @@ public: ANDROID_API virtual void destroy(); + ANDROID_API virtual void pauseAnimators() {} + private: friend class AnimationHandle; void addAnimationHandle(AnimationHandle* handle); diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index 4d65782f684be19348821aafc7a461ee4feeafd7..74aa3033ee122203e83b8a4f04ced5e4031cc756 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -123,22 +123,27 @@ void BaseRenderNodeAnimator::resolveStagingRequest(Request request) { mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? mPlayTime : 0; mPlayState = PlayState::Running; + mPendingActionUponFinish = Action::None; break; case Request::Reverse: mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? mPlayTime : mDuration; mPlayState = PlayState::Reversing; + mPendingActionUponFinish = Action::None; break; case Request::Reset: mPlayTime = 0; mPlayState = PlayState::Finished; + mPendingActionUponFinish = Action::Reset; break; case Request::Cancel: mPlayState = PlayState::Finished; + mPendingActionUponFinish = Action::None; break; case Request::End: mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration; mPlayState = PlayState::Finished; + mPendingActionUponFinish = Action::End; break; default: LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast(request)); @@ -176,8 +181,6 @@ void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) { mStagingRequests.clear(); if (mStagingPlayState == PlayState::Finished) { - // Set the staging play time and end the animation - updatePlayTime(mPlayTime); callOnFinishedListener(context); } else if (mStagingPlayState == PlayState::Running || mStagingPlayState == PlayState::Reversing) { @@ -236,6 +239,15 @@ bool BaseRenderNodeAnimator::animate(AnimationContext& context) { return false; } if (mPlayState == PlayState::Finished) { + if (mPendingActionUponFinish == Action::Reset) { + // Skip to start. + updatePlayTime(0); + } else if (mPendingActionUponFinish == Action::End) { + // Skip to end. + updatePlayTime(mDuration); + } + // Reset pending action. + mPendingActionUponFinish = Action ::None; return true; } @@ -274,6 +286,10 @@ bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) { return playTime >= mDuration; } +nsecs_t BaseRenderNodeAnimator::getRemainingPlayTime() { + return mPlayState == PlayState::Reversing ? mPlayTime : mDuration - mPlayTime; +} + void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) { if (mPlayState < PlayState::Finished) { mPlayState = PlayState::Finished; diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 1954b88107a36298b0811c038b529e7cb486a42c..aac355c11ac901165235e101a9f25d0c4f882403 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -44,6 +44,12 @@ protected: ANDROID_API virtual ~AnimationListener() {} }; +enum class RepeatMode { + // These are the same values as the RESTART and REVERSE in ValueAnimator.java. + Restart = 1, + Reverse = 2 +}; + class BaseRenderNodeAnimator : public VirtualLightRefBase { PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator); public: @@ -62,19 +68,23 @@ public: } bool mayRunAsync() { return mMayRunAsync; } ANDROID_API void start(); - ANDROID_API void reset(); + ANDROID_API virtual void reset(); ANDROID_API void reverse(); // Terminates the animation at its current progress. ANDROID_API void cancel(); // Terminates the animation and skip to the end of the animation. - ANDROID_API void end(); + ANDROID_API virtual void end(); void attach(RenderNode* target); virtual void onAttached() {} void detach() { mTarget = nullptr; } - void pushStaging(AnimationContext& context); - bool animate(AnimationContext& context); + ANDROID_API void pushStaging(AnimationContext& context); + ANDROID_API bool animate(AnimationContext& context); + + // Returns the remaining time in ms for the animation. Note this should only be called during + // an animation on RenderThread. + ANDROID_API nsecs_t getRemainingPlayTime(); bool isRunning() { return mPlayState == PlayState::Running || mPlayState == PlayState::Reversing; } @@ -155,6 +165,17 @@ private: Cancel, End }; + + // Defines different actions upon finish. + enum class Action { + // For animations that got canceled or finished normally. no more action needs to be done. + None, + // For animations that get reset, the reset will happen in the next animation pulse. + Reset, + // For animations being ended, in the next animation pulse the animation will skip to end. + End + }; + inline void checkMutable(); virtual void transitionToRunning(AnimationContext& context); void doSetStartValue(float value); @@ -162,7 +183,7 @@ private: void resolveStagingRequest(Request request); std::vector mStagingRequests; - + Action mPendingActionUponFinish = Action::None; }; class RenderPropertyAnimator : public BaseRenderNodeAnimator { diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 949ad450d5f75b0b17fb7894836cfa36a21cbff7..a8ced9b2597b0cee0a3a0fffeeca975f0e5d658c 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -21,6 +21,9 @@ #include "Properties.h" #include "renderstate/RenderState.h" #include "ShadowTessellator.h" +#ifdef BUGREPORT_FONT_CACHE_USAGE +#include "font/FontCacheHistoryTracker.h" +#endif #include "utils/GLUtils.h" #include @@ -195,12 +198,7 @@ void Caches::dumpMemoryUsage(String8 &log) { log.appendFormat(" PatchCache %8d / %8d\n", patchCache.getSize(), patchCache.getMaxSize()); - const uint32_t sizeA8 = fontRenderer.getFontRendererSize(GL_ALPHA); - const uint32_t sizeRGBA = fontRenderer.getFontRendererSize(GL_RGBA); - log.appendFormat(" FontRenderer A8 %8d / %8d\n", sizeA8, sizeA8); - log.appendFormat(" FontRenderer RGBA %8d / %8d\n", sizeRGBA, sizeRGBA); - log.appendFormat(" FontRenderer total %8d / %8d\n", sizeA8 + sizeRGBA, - sizeA8 + sizeRGBA); + fontRenderer.dumpMemoryUsage(log); log.appendFormat("Other:\n"); log.appendFormat(" FboCache %8d / %8d\n", @@ -213,11 +211,14 @@ void Caches::dumpMemoryUsage(String8 &log) { total += tessellationCache.getSize(); total += dropShadowCache.getSize(); total += patchCache.getSize(); - total += fontRenderer.getFontRendererSize(GL_ALPHA); - total += fontRenderer.getFontRendererSize(GL_RGBA); + total += fontRenderer.getSize(); log.appendFormat("Total memory usage:\n"); log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f); + +#ifdef BUGREPORT_FONT_CACHE_USAGE + fontRenderer.getFontRenderer().historyTracker().dump(log); +#endif } /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp index fe6823925083cc8b7880ba522936dc2d0d75dc4e..84451bacbc091ef2e8066e1fc4276a7b0a9b79a0 100644 --- a/libs/hwui/ClipArea.cpp +++ b/libs/hwui/ClipArea.cpp @@ -464,10 +464,7 @@ const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator, } case ClipMode::Region: other = getRegion(recordedClip); - - // TODO: handle non-translate transforms properly! - other.translate(recordedClipTransform.getTranslateX(), - recordedClipTransform.getTranslateY()); + applyTransformToRegion(recordedClipTransform, &other); } ClipRegion* regionClip = allocator.create(); @@ -527,11 +524,29 @@ void ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) { } } else { SkRegion region(getRegion(clip)); - // TODO: handle non-translate transforms properly! - region.translate(transform.getTranslateX(), transform.getTranslateY()); + applyTransformToRegion(transform, ®ion); clipRegion(region, SkRegion::kIntersect_Op); } } +void ClipArea::applyTransformToRegion(const Matrix4& transform, SkRegion* region) { + if (transform.rectToRect() && !transform.isPureTranslate()) { + // handle matrices with scale manually by mapping each rect + SkRegion other; + SkRegion::Iterator it(*region); + while (!it.done()) { + Rect rect(it.rect()); + transform.mapRect(rect); + rect.snapGeometryToPixelBoundaries(true); + other.op(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kUnion_Op); + it.next(); + } + region->swap(other); + } else { + // TODO: handle non-translate transforms properly! + region->translate(transform.getTranslateX(), transform.getTranslateY()); + } +} + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h index 32ab501478f79f638ea80830e362efb22e97d835..2e561601d452d1ed9df690076b34abf5e20d5205 100644 --- a/libs/hwui/ClipArea.h +++ b/libs/hwui/ClipArea.h @@ -179,6 +179,8 @@ public: const ClipBase* recordedClip, const Matrix4& recordedClipTransform); void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform); + static void applyTransformToRegion(const Matrix4& transform, SkRegion* region); + private: void enterRectangleMode(); void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op); diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index b572bdaccb860d8f06e586e057c8c417ca6467f7..28be05c52cfcb8a44f8e0968b77e54ee9787fcdc 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -45,7 +45,7 @@ DisplayList::DisplayList() , regions(stdAllocator) , referenceHolders(stdAllocator) , functors(stdAllocator) - , pushStagingFunctors(stdAllocator) + , vectorDrawables(stdAllocator) , hasDrawOps(false) { } diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index 5b3227b7db97d87134d9cb301ee7137941b62825..ccf71c6d360b733b5b63086ad95d98611d9a5a5c 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -69,6 +69,11 @@ typedef DisplayListOp BaseOpType; typedef DrawRenderNodeOp NodeOpType; #endif +namespace VectorDrawable { +class Tree; +}; +typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; + /** * Holds data used in the playback a tree of DisplayLists. */ @@ -110,16 +115,6 @@ struct ReplayStateStruct : public PlaybackStateStruct { LinearAllocator mReplayAllocator; }; -/** - * Functor that can be used for objects with data in both UI thread and RT to keep the data - * in sync. This functor, when added to DisplayList, will be call during DisplayList sync. - */ -struct PushStagingFunctor { - PushStagingFunctor() {} - virtual ~PushStagingFunctor() {} - virtual void operator ()() {} -}; - struct FunctorContainer { Functor* functor; GlFunctorLifecycleListener* listener; @@ -161,7 +156,7 @@ public: const LsaVector& getBitmapResources() const { return bitmapResources; } const LsaVector& getFunctors() const { return functors; } - const LsaVector& getPushStagingFunctors() { return pushStagingFunctors; } + const LsaVector& getVectorDrawables() { return vectorDrawables; } size_t addChild(NodeOpType* childOp); @@ -203,10 +198,10 @@ private: // List of functors LsaVector functors; - // List of functors that need to be notified of pushStaging. Note that this list gets nothing + // List of VectorDrawables that need to be notified of pushStaging. Note that this list gets nothing // but a callback during sync DisplayList, unlike the list of functors defined above, which // gets special treatment exclusive for webview. - LsaVector pushStagingFunctors; + LsaVector vectorDrawables; bool hasDrawOps; // only used if !HWUI_NEW_OPS diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp index ca968cef91b2a483bf741333e54b868bee049a37..bec662959f9155f011d8b4ffaf0111ce6f0967c3 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -417,7 +417,7 @@ void DisplayListCanvas::drawPoints(const float* points, int count, const SkPaint void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { mDisplayList->ref(tree); - mDisplayList->pushStagingFunctors.push_back(tree->getFunctor()); + mDisplayList->vectorDrawables.push_back(tree); addDrawOp(new (alloc()) DrawVectorDrawableOp(tree, tree->stagingProperties()->getBounds())); } diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 276c18d0d3f9e9777eed539ee284ef72afedb6b3..681cf55066b4e2bed3bab26561c640d5649d402f 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -168,10 +168,17 @@ void FontRenderer::flushAllAndInvalidate() { for (uint32_t i = 0; i < mACacheTextures.size(); i++) { mACacheTextures[i]->init(); + +#ifdef BUGREPORT_FONT_CACHE_USAGE + mHistoryTracker.glyphsCleared(mACacheTextures[i]); +#endif } for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) { mRGBACacheTextures[i]->init(); +#ifdef BUGREPORT_FONT_CACHE_USAGE + mHistoryTracker.glyphsCleared(mRGBACacheTextures[i]); +#endif } mDrawn = false; @@ -183,6 +190,9 @@ void FontRenderer::flushLargeCaches(std::vector& cacheTextures) { CacheTexture* cacheTexture = cacheTextures[i]; if (cacheTexture->getPixelBuffer()) { cacheTexture->init(); +#ifdef BUGREPORT_FONT_CACHE_USAGE + mHistoryTracker.glyphsCleared(cacheTexture); +#endif LruCache::Iterator it(mActiveFonts); while (it.next()) { it.value()->invalidateTextureCache(cacheTexture); @@ -385,6 +395,10 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp } cachedGlyph->mIsValid = true; + +#ifdef BUGREPORT_FONT_CACHE_USAGE + mHistoryTracker.glyphUploaded(cacheTexture, startX, startY, glyph.fWidth, glyph.fHeight); +#endif } CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format, @@ -747,19 +761,68 @@ static uint32_t calculateCacheSize(const std::vector& cacheTextur return size; } -uint32_t FontRenderer::getCacheSize(GLenum format) const { +static uint32_t calculateFreeCacheSize(const std::vector& cacheTextures) { + uint32_t size = 0; + for (uint32_t i = 0; i < cacheTextures.size(); i++) { + CacheTexture* cacheTexture = cacheTextures[i]; + if (cacheTexture && cacheTexture->getPixelBuffer()) { + size += cacheTexture->calculateFreeMemory(); + } + } + return size; +} + +const std::vector& FontRenderer::cacheTexturesForFormat(GLenum format) const { switch (format) { case GL_ALPHA: { - return calculateCacheSize(mACacheTextures); + return mACacheTextures; } case GL_RGBA: { - return calculateCacheSize(mRGBACacheTextures); + return mRGBACacheTextures; } default: { - return 0; + LOG_ALWAYS_FATAL("Unsupported format: %d", format); + // Impossible to hit this, but the compiler doesn't know that + return *(new std::vector()); } } } +static void dumpTextures(String8& log, const char* tag, + const std::vector& cacheTextures) { + for (uint32_t i = 0; i < cacheTextures.size(); i++) { + CacheTexture* cacheTexture = cacheTextures[i]; + if (cacheTexture && cacheTexture->getPixelBuffer()) { + uint32_t free = cacheTexture->calculateFreeMemory(); + uint32_t total = cacheTexture->getPixelBuffer()->getSize(); + log.appendFormat(" %-4s texture %d %8d / %8d\n", tag, i, total - free, total); + } + } +} + +void FontRenderer::dumpMemoryUsage(String8& log) const { + const uint32_t sizeA8 = getCacheSize(GL_ALPHA); + const uint32_t usedA8 = sizeA8 - getFreeCacheSize(GL_ALPHA); + const uint32_t sizeRGBA = getCacheSize(GL_RGBA); + const uint32_t usedRGBA = sizeRGBA - getFreeCacheSize(GL_RGBA); + log.appendFormat(" FontRenderer A8 %8d / %8d\n", usedA8, sizeA8); + dumpTextures(log, "A8", cacheTexturesForFormat(GL_ALPHA)); + log.appendFormat(" FontRenderer RGBA %8d / %8d\n", usedRGBA, sizeRGBA); + dumpTextures(log, "RGBA", cacheTexturesForFormat(GL_RGBA)); + log.appendFormat(" FontRenderer total %8d / %8d\n", usedA8 + usedRGBA, sizeA8 + sizeRGBA); +} + +uint32_t FontRenderer::getCacheSize(GLenum format) const { + return calculateCacheSize(cacheTexturesForFormat(format)); +} + +uint32_t FontRenderer::getFreeCacheSize(GLenum format) const { + return calculateFreeCacheSize(cacheTexturesForFormat(format)); +} + +uint32_t FontRenderer::getSize() const { + return getCacheSize(GL_ALPHA) + getCacheSize(GL_RGBA); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index d656864c51331c84754f2ac9c4c9a3ee274f0fe8..1e59a966750e48ed4c69c3de071d3ccd231f882d 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -21,8 +21,12 @@ #include "font/CacheTexture.h" #include "font/CachedGlyphInfo.h" #include "font/Font.h" +#ifdef BUGREPORT_FONT_CACHE_USAGE +#include "font/FontCacheHistoryTracker.h" +#endif #include +#include #include #include @@ -132,7 +136,12 @@ public: mLinearFiltering = linearFiltering; } - uint32_t getCacheSize(GLenum format) const; + uint32_t getSize() const; + void dumpMemoryUsage(String8& log) const; + +#ifdef BUGREPORT_FONT_CACHE_USAGE + FontCacheHistoryTracker& historyTracker() { return mHistoryTracker; } +#endif private: friend class Font; @@ -175,6 +184,10 @@ private: mUploadTexture = true; } + const std::vector& cacheTexturesForFormat(GLenum format) const; + uint32_t getCacheSize(GLenum format) const; + uint32_t getFreeCacheSize(GLenum format) const; + uint32_t mSmallCacheWidth; uint32_t mSmallCacheHeight; uint32_t mLargeCacheWidth; @@ -199,6 +212,10 @@ private: bool mLinearFiltering; +#ifdef BUGREPORT_FONT_CACHE_USAGE + FontCacheHistoryTracker mHistoryTracker; +#endif + #ifdef ANDROID_ENABLE_RENDERSCRIPT // RS constructs RSC::sp mRs; diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp index 41e22332d8ed5bd331d9008e143fd71bf8770bcd..826f0bba294cf73928ed8b220c5429449e711195 100644 --- a/libs/hwui/FrameInfo.cpp +++ b/libs/hwui/FrameInfo.cpp @@ -35,8 +35,17 @@ const std::string FrameInfoNames[] = { "IssueDrawCommandsStart", "SwapBuffers", "FrameCompleted", + "DequeueBufferDuration", + "QueueBufferDuration", }; +static_assert((sizeof(FrameInfoNames)/sizeof(FrameInfoNames[0])) + == static_cast(FrameInfoIndex::NumIndexes), + "size mismatch: FrameInfoNames doesn't match the enum!"); + +static_assert(static_cast(FrameInfoIndex::NumIndexes) == 16, + "Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)"); + void FrameInfo::importUiThreadInfo(int64_t* info) { memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t)); } diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h index afab84c3542c97f459d88c60782725f2f772adb6..bac9d12d273c9ea1ee730922b73afcbbd5c4073b 100644 --- a/libs/hwui/FrameInfo.h +++ b/libs/hwui/FrameInfo.h @@ -48,7 +48,11 @@ enum class FrameInfoIndex { SwapBuffers, FrameCompleted, + DequeueBufferDuration, + QueueBufferDuration, + // Must be the last value! + // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT NumIndexes }; diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h index 5813e7f717ee628227b684d5568f3eb9e962a699..bd27a1a720609d3348e830cc82e4933eaad3c6e7 100644 --- a/libs/hwui/GammaFontRenderer.h +++ b/libs/hwui/GammaFontRenderer.h @@ -22,6 +22,8 @@ #include +#include + namespace android { namespace uirenderer { @@ -46,8 +48,16 @@ public: return *mRenderer; } - uint32_t getFontRendererSize(GLenum format) const { - return mRenderer ? mRenderer->getCacheSize(format) : 0; + void dumpMemoryUsage(String8& log) const { + if (mRenderer) { + mRenderer->dumpMemoryUsage(log); + } else { + log.appendFormat("FontRenderer doesn't exist.\n"); + } + } + + uint32_t getSize() const { + return mRenderer ? mRenderer->getSize() : 0; } void endPrecaching(); diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp index ebe9c4240221c57883f478e5429ecaefec68f2d8..ed6b211eef1bb60d29282bd727dac3a2813f8023 100644 --- a/libs/hwui/JankTracker.cpp +++ b/libs/hwui/JankTracker.cpp @@ -16,6 +16,7 @@ #include "JankTracker.h" #include "Properties.h" +#include "utils/TimeUtils.h" #include #include @@ -119,11 +120,27 @@ static uint32_t frameTimeForFrameCountIndex(uint32_t index) { return index; } -JankTracker::JankTracker(nsecs_t frameIntervalNanos) { +JankTracker::JankTracker(const DisplayInfo& displayInfo) { // By default this will use malloc memory. It may be moved later to ashmem // if there is shared space for it and a request comes in to do that. mData = new ProfileData; reset(); + nsecs_t frameIntervalNanos = static_cast(1_s / displayInfo.fps); +#if USE_HWC2 + nsecs_t sfOffset = frameIntervalNanos - (displayInfo.presentationDeadline - 1_ms); + nsecs_t offsetDelta = sfOffset - displayInfo.appVsyncOffset; + // There are two different offset cases. If the offsetDelta is positive + // and small, then the intention is to give apps extra time by leveraging + // pipelining between the UI & RT threads. If the offsetDelta is large or + // negative, the intention is to subtract time from the total duration + // in which case we can't afford to wait for dequeueBuffer blockage. + if (offsetDelta <= 4_ms && offsetDelta >= 0) { + // SF will begin composition at VSYNC-app + offsetDelta. If we are triple + // buffered, this is the expected time at which dequeueBuffer will + // return due to the staggering of VSYNC-app & VSYNC-sf. + mDequeueTimeForgiveness = offsetDelta + 4_ms; + } +#endif setFrameInterval(frameIntervalNanos); } @@ -213,6 +230,19 @@ void JankTracker::addFrame(const FrameInfo& frame) { mData->totalFrameCount++; // Fast-path for jank-free frames int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted); + if (mDequeueTimeForgiveness + && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) { + nsecs_t expectedDequeueDuration = + mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync] + - frame[FrameInfoIndex::IssueDrawCommandsStart]; + if (expectedDequeueDuration > 0) { + // Forgive only up to the expected amount, but not more than + // the actual time spent blocked. + nsecs_t forgiveAmount = std::min(expectedDequeueDuration, + frame[FrameInfoIndex::DequeueBufferDuration]); + totalDuration -= forgiveAmount; + } + } uint32_t framebucket = frameCountIndexForFrameTime(totalDuration); // Keep the fast path as fast as possible. if (CC_LIKELY(totalDuration < mFrameInterval)) { diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h index a23dd78071695d8d6c68c2246ec50e33ee612819..8b482d5a804d53c28398ab15a7f17736939eb2e2 100644 --- a/libs/hwui/JankTracker.h +++ b/libs/hwui/JankTracker.h @@ -21,6 +21,7 @@ #include "utils/RingBuffer.h" #include +#include #include #include @@ -56,7 +57,7 @@ struct ProfileData { // TODO: Replace DrawProfiler with this class JankTracker { public: - explicit JankTracker(nsecs_t frameIntervalNanos); + explicit JankTracker(const DisplayInfo& displayInfo); ~JankTracker(); void addFrame(const FrameInfo& frame); @@ -79,6 +80,14 @@ private: std::array mThresholds; int64_t mFrameInterval; + // The amount of time we will erase from the total duration to account + // for SF vsync offsets with HWC2 blocking dequeueBuffers. + // (Vsync + mDequeueBlockTolerance) is the point at which we expect + // SF to have released the buffer normally, so we will forgive up to that + // point in time by comparing to (IssueDrawCommandsStart + DequeueDuration) + // This is only used if we are in pipelined mode and are using HWC2, + // otherwise it's 0. + nsecs_t mDequeueTimeForgiveness = 0; ProfileData* mData; bool mIsMapped = false; }; diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp index b29f91ff34aada6d439c664ca7fbcf0c5f630181..e3258e3c1a48f7e23f29210a83a6326ae3f81945 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.cpp +++ b/libs/hwui/PropertyValuesAnimatorSet.cpp @@ -23,13 +23,17 @@ namespace android { namespace uirenderer { void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, - Interpolator* interpolator, nsecs_t startDelay, - nsecs_t duration, int repeatCount) { + Interpolator* interpolator, nsecs_t startDelay, nsecs_t duration, int repeatCount, + RepeatMode repeatMode) { PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder, - interpolator, startDelay, duration, repeatCount); + interpolator, startDelay, duration, repeatCount, repeatMode); mAnimators.emplace_back(animator); - setListener(new PropertyAnimatorSetListener(this)); + + // Check whether any child animator is infinite after adding it them to the set. + if (repeatCount == -1) { + mIsInfinite = true; + } } PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() @@ -37,12 +41,22 @@ PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() setStartValue(0); mLastFraction = 0.0f; setInterpolator(new LinearInterpolator()); + setListener(new PropertyAnimatorSetListener(this)); } void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) { if (mOneShotListener.get()) { - mOneShotListener->onAnimationFinished(animator); + sp listener = std::move(mOneShotListener); + // Set the listener to nullptr before the onAnimationFinished callback, rather than after, + // for two reasons: + // 1) We need to prevent changes to mOneShotListener during the onAnimationFinished + // callback (specifically in AnimationListenerBridge::onAnimationFinished(...) from + // triggering dtor of the bridge and potentially unsafely re-entering + // AnimationListenerBridge::onAnimationFinished(...). + // 2) It's possible that there are changes to the listener during the callback, therefore + // we need to reset the listener before the callback rather than afterwards. mOneShotListener = nullptr; + listener->onAnimationFinished(animator); } } @@ -61,14 +75,9 @@ void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { // Note that this set may containing animators modifying the same property, so when we // reset the animators, we need to make sure the animators that end the first will // have the final say on what the property value should be. - (*it)->setFraction(0); - } - } else if (playTime >= mDuration) { - // Skip all the animators to end - for (auto& anim : mAnimators) { - anim->setFraction(1); + (*it)->setFraction(0, 0); } - } else { + } else { for (auto& anim : mAnimators) { anim->setCurrentPlayTime(playTime); } @@ -78,15 +87,27 @@ void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { void PropertyValuesAnimatorSet::start(AnimationListener* listener) { init(); mOneShotListener = listener; + mRequestId++; BaseRenderNodeAnimator::start(); } void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { init(); mOneShotListener = listener; + mRequestId++; BaseRenderNodeAnimator::reverse(); } +void PropertyValuesAnimatorSet::reset() { + mRequestId++; + BaseRenderNodeAnimator::reset(); +} + +void PropertyValuesAnimatorSet::end() { + mRequestId++; + BaseRenderNodeAnimator::end(); +} + void PropertyValuesAnimatorSet::init() { if (mInitialized) { return; @@ -98,7 +119,7 @@ void PropertyValuesAnimatorSet::init() { std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) { return a->getTotalDuration() < b->getTotalDuration(); }); - mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration(); + mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration(); mInitialized = true; } @@ -107,7 +128,8 @@ uint32_t PropertyValuesAnimatorSet::dirtyMask() { } PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, - nsecs_t startDelay, nsecs_t duration, int repeatCount) + nsecs_t startDelay, nsecs_t duration, int repeatCount, + RepeatMode repeatMode) : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay), mDuration(duration) { if (repeatCount < 0) { @@ -115,24 +137,44 @@ PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* i } else { mRepeatCount = repeatCount; } + mRepeatMode = repeatMode; mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay; } void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { - if (playTime >= mStartDelay && playTime < mTotalDuration) { - nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration; - float fraction = currentIterationPlayTime / (float) mDuration; - setFraction(fraction); - } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) { - // This makes sure we only set the fraction = 1 once. It is needed because there might - // be another animator modifying the same property after this animator finishes, we need - // to make sure we don't set conflicting values on the same property within one frame. - setFraction(1.0f); + if (playTime < mStartDelay) { + return; + } + + float currentIterationFraction; + long iteration; + if (playTime >= mTotalDuration) { + // Reached the end of the animation. + iteration = mRepeatCount; + currentIterationFraction = 1.0f; + } else { + // play time here is in range [mStartDelay, mTotalDuration) + iteration = (playTime - mStartDelay) / mDuration; + currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float) mDuration; } + setFraction(currentIterationFraction, iteration); } -void PropertyAnimator::setFraction(float fraction) { - mLatestFraction = fraction; +void PropertyAnimator::setFraction(float fraction, long iteration) { + double totalFraction = fraction + iteration; + // This makes sure we only set the fraction = repeatCount + 1 once. It is needed because there + // might be another animator modifying the same property after this animator finishes, we need + // to make sure we don't set conflicting values on the same property within one frame. + if ((mLatestFraction == mRepeatCount + 1.0) && (totalFraction >= mRepeatCount + 1.0)) { + return; + } + + mLatestFraction = totalFraction; + // Check the play direction (i.e. reverse or restart) every other iteration, and calculate the + // fraction based on the play direction. + if (iteration % 2 && mRepeatMode == RepeatMode::Reverse) { + fraction = 1.0f - fraction; + } float interpolatedFraction = mInterpolator->interpolate(fraction); mPropertyValuesHolder->setFraction(interpolatedFraction); } diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h index 602fd91b04126da12a315acf4b70262e839a4f14..a5d9e869196f22ac877bc0f208ad163d62a5f6df 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.h +++ b/libs/hwui/PropertyValuesAnimatorSet.h @@ -26,12 +26,13 @@ namespace uirenderer { class PropertyAnimator { public: PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay, - nsecs_t duration, int repeatCount); + nsecs_t duration, int repeatCount, RepeatMode repeatMode); void setCurrentPlayTime(nsecs_t playTime); nsecs_t getTotalDuration() { return mTotalDuration; } - void setFraction(float fraction); + // fraction range: [0, 1], iteration range [0, repeatCount] + void setFraction(float fraction, long iteration); private: std::unique_ptr mPropertyValuesHolder; @@ -40,9 +41,11 @@ private: nsecs_t mDuration; uint32_t mRepeatCount; nsecs_t mTotalDuration; - float mLatestFraction = 0.0f; + RepeatMode mRepeatMode; + double mLatestFraction = 0; }; +// TODO: This class should really be named VectorDrawableAnimator class ANDROID_API PropertyValuesAnimatorSet : public BaseRenderNodeAnimator { public: friend class PropertyAnimatorSetListener; @@ -50,11 +53,19 @@ public: void start(AnimationListener* listener); void reverse(AnimationListener* listener); + virtual void reset() override; + virtual void end() override; void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, Interpolator* interpolators, int64_t startDelays, - nsecs_t durations, int repeatCount); + nsecs_t durations, int repeatCount, RepeatMode repeatMode); virtual uint32_t dirtyMask(); + bool isInfinite() { return mIsInfinite; } + void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; } + VectorDrawableRoot* getVectorDrawable() const { return mVectorDrawable.get(); } + AnimationListener* getOneShotListener() { return mOneShotListener.get(); } + void clearOneShotListener() { mOneShotListener = nullptr; } + uint32_t getRequestId() const { return mRequestId; } protected: virtual float getValue(RenderNode* target) const override; @@ -69,6 +80,11 @@ private: std::vector< std::unique_ptr > mAnimators; float mLastFraction = 0.0f; bool mInitialized = false; + sp mVectorDrawable; + bool mIsInfinite = false; + // This request id gets incremented (on UI thread only) when a new request to modfiy the + // lifecycle of an animation happens, namely when start/end/reset/reverse is called. + uint32_t mRequestId = 0; }; class PropertyAnimatorSetListener : public AnimationListener { diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp index 0932d653fd5ec128994f03b4032511372b482a4b..6ba0ab59a88c41ce176935cebd02bb85ee6aa895 100644 --- a/libs/hwui/PropertyValuesHolder.cpp +++ b/libs/hwui/PropertyValuesHolder.cpp @@ -25,7 +25,27 @@ namespace uirenderer { using namespace VectorDrawable; -float PropertyValuesHolder::getValueFromData(float fraction) { +inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) { + return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction); +} + +// TODO: Add a test for this +void ColorEvaluator::evaluate(SkColor* outColor, + const SkColor& fromColor, const SkColor& toColor, float fraction) const { + U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction); + U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction); + U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction); + U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction); + *outColor = SkColorSetARGB(alpha, red, green, blue); +} + +void PathEvaluator::evaluate(PathData* out, + const PathData& from, const PathData& to, float fraction) const { + VectorDrawableUtils::interpolatePaths(out, from, to, fraction); +} + +template +const T PropertyValuesHolderImpl::getValueFromData(float fraction) const { if (mDataSource.size() == 0) { LOG_ALWAYS_FATAL("No data source is defined"); return 0; @@ -41,57 +61,44 @@ float PropertyValuesHolder::getValueFromData(float fraction) { int lowIndex = floor(fraction); fraction -= lowIndex; - float value = mDataSource[lowIndex] * (1.0f - fraction) - + mDataSource[lowIndex + 1] * fraction; + T value; + mEvaluator->evaluate(&value, mDataSource[lowIndex], mDataSource[lowIndex + 1], fraction); return value; } -void GroupPropertyValuesHolder::setFraction(float fraction) { - float animatedValue; +template +const T PropertyValuesHolderImpl::calculateAnimatedValue(float fraction) const { if (mDataSource.size() > 0) { - animatedValue = getValueFromData(fraction); + return getValueFromData(fraction); } else { - animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; + T value; + mEvaluator->evaluate(&value, mStartValue, mEndValue, fraction); + return value; } - mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue); } -inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) { - return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction); -} - -// TODO: Add a test for this -SkColor FullPathColorPropertyValuesHolder::interpolateColors(SkColor fromColor, SkColor toColor, - float fraction) { - U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction); - U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction); - U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction); - U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction); - return SkColorSetARGB(alpha, red, green, blue); +void GroupPropertyValuesHolder::setFraction(float fraction) { + float animatedValue = calculateAnimatedValue(fraction); + mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue); } void FullPathColorPropertyValuesHolder::setFraction(float fraction) { - SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction); + SkColor animatedValue = calculateAnimatedValue(fraction); mFullPath->mutateProperties()->setColorPropertyValue(mPropertyId, animatedValue); } void FullPathPropertyValuesHolder::setFraction(float fraction) { - float animatedValue; - if (mDataSource.size() > 0) { - animatedValue = getValueFromData(fraction); - } else { - animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; - } + float animatedValue = calculateAnimatedValue(fraction); mFullPath->mutateProperties()->setPropertyValue(mPropertyId, animatedValue); } void PathDataPropertyValuesHolder::setFraction(float fraction) { - VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction); + mEvaluator->evaluate(&mPathData, mStartValue, mEndValue, fraction); mPath->mutateProperties()->setData(mPathData); } void RootAlphaPropertyValuesHolder::setFraction(float fraction) { - float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; + float animatedValue = calculateAnimatedValue(fraction); mTree->mutateProperties()->setRootAlpha(animatedValue); } diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h index b905faef104c80736b1c711d2ac7bc4d038afbbf..432f8ba82afb660d347208e7f8fcad3290bf12c4 100644 --- a/libs/hwui/PropertyValuesHolder.h +++ b/libs/hwui/PropertyValuesHolder.h @@ -31,91 +31,130 @@ namespace uirenderer { class ANDROID_API PropertyValuesHolder { public: virtual void setFraction(float fraction) = 0; - void setPropertyDataSource(float* dataSource, int length) { + virtual ~PropertyValuesHolder() {} +}; + +template +class Evaluator { +public: + virtual void evaluate(T* out, const T& from, const T& to, float fraction) const {}; + virtual ~Evaluator() {} +}; + +class FloatEvaluator : public Evaluator { +public: + virtual void evaluate(float* out, const float& from, const float& to, float fraction) + const override { + *out = from * (1 - fraction) + to * fraction; + } +}; + +class ANDROID_API ColorEvaluator : public Evaluator { +public: + virtual void evaluate(SkColor* outColor, const SkColor& from, const SkColor& to, + float fraction) const override; +}; + +class ANDROID_API PathEvaluator : public Evaluator { + virtual void evaluate(PathData* out, const PathData& from, const PathData& to, float fraction) + const override; +}; + +template +class ANDROID_API PropertyValuesHolderImpl : public PropertyValuesHolder { +public: + PropertyValuesHolderImpl(const T& startValue, const T& endValue) + : mStartValue(startValue) + , mEndValue(endValue) {} + void setPropertyDataSource(T* dataSource, int length) { mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length); } - float getValueFromData(float fraction); - virtual ~PropertyValuesHolder() {} + // Calculate the animated value from the data source. + const T getValueFromData(float fraction) const; + // Convenient method to favor getting animated value from data source. If no data source is set + // fall back to linear interpolation. + const T calculateAnimatedValue(float fraction) const; protected: - std::vector mDataSource; + std::unique_ptr> mEvaluator = nullptr; + // This contains uniformly sampled data throughout the animation duration. The first element + // should be the start value and the last should be the end value of the animation. When the + // data source is set, we'll favor data source over the linear interpolation of start/end value + // for calculation of animated value. + std::vector mDataSource; + T mStartValue; + T mEndValue; }; -class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolderImpl { public: GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue, float endValue) - : mGroup(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue){ + : PropertyValuesHolderImpl(startValue, endValue) + , mGroup(ptr) + , mPropertyId(propertyId) { + mEvaluator.reset(new FloatEvaluator()); } void setFraction(float fraction) override; private: VectorDrawable::Group* mGroup; int mPropertyId; - float mStartValue; - float mEndValue; }; -class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolderImpl { public: - FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, int32_t startValue, - int32_t endValue) - : mFullPath(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue) {}; + FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, + SkColor startValue, SkColor endValue) + : PropertyValuesHolderImpl(startValue, endValue) + , mFullPath(ptr) + , mPropertyId(propertyId) { + mEvaluator.reset(new ColorEvaluator()); + } void setFraction(float fraction) override; static SkColor interpolateColors(SkColor fromColor, SkColor toColor, float fraction); private: VectorDrawable::FullPath* mFullPath; int mPropertyId; - int32_t mStartValue; - int32_t mEndValue; }; -class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolderImpl { public: FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue, float endValue) - : mFullPath(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue) {}; + : PropertyValuesHolderImpl(startValue, endValue) + , mFullPath(ptr) + , mPropertyId(propertyId) { + mEvaluator.reset(new FloatEvaluator()); + }; void setFraction(float fraction) override; private: VectorDrawable::FullPath* mFullPath; int mPropertyId; - float mStartValue; - float mEndValue; }; -class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolderImpl { public: PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue, PathData* endValue) - : mPath(ptr) - , mStartValue(*startValue) - , mEndValue(*endValue) {}; + : PropertyValuesHolderImpl(*startValue, *endValue) + , mPath(ptr) { + mEvaluator.reset(new PathEvaluator()); + }; void setFraction(float fraction) override; private: VectorDrawable::Path* mPath; PathData mPathData; - PathData mStartValue; - PathData mEndValue; }; -class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolder { +class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolderImpl { public: RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue) - : mTree(tree) - , mStartValue(startValue) - , mEndValue(endValue) {} + : PropertyValuesHolderImpl(startValue, endValue) + , mTree(tree) { + mEvaluator.reset(new FloatEvaluator()); + } void setFraction(float fraction) override; private: VectorDrawable::Tree* mTree; - float mStartValue; - float mEndValue; }; } } diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index 55f823dfe2264a1bc8a503462682616e9f72818c..0ab247dc80529be0ec7c9591e489ac89645506de 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -136,7 +136,7 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs); if (sourceImage == EGL_NO_IMAGE_KHR) { - ALOGW("Error creating image (%#x)", eglGetError()); + ALOGW("eglCreateImageKHR failed (%#x)", eglGetError()); return CopyResult::UnknownError; } GLuint sourceTexId; @@ -147,7 +147,8 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread, GLenum status = GL_NO_ERROR; while ((status = glGetError()) != GL_NO_ERROR) { - ALOGW("Error creating image (%#x)", status); + ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status); + eglDestroyImageKHR(display, sourceImage); return CopyResult::UnknownError; } @@ -183,6 +184,13 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread, caches.textureState().deleteTexture(texture); renderState.deleteFramebuffer(fbo); + sourceTexture.deleteTexture(); + // All we're flushing & finishing is the deletion of the texture since + // copyTextureInto already did a major flush & finish as an implicit + // part of glReadPixels, so this shouldn't pose any major stalls. + glFinish(); + eglDestroyImageKHR(display, sourceImage); + GL_CHECKPOINT(MODERATE); return CopyResult::Success; diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index b49f9b52998943194709ea8fa75194f605f1b5c2..0c552bac1d7f08afbcf6365e4230a053235b950a 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -127,7 +127,8 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom, // operations will be able to store and restore the current clip and transform info, and // quick rejection will be correct (for display lists) - const Rect unmappedBounds(left, top, right, bottom); + Rect unmappedBounds(left, top, right, bottom); + unmappedBounds.roundOut(); // determine clipped bounds relative to previous viewport. Rect visibleBounds = unmappedBounds; @@ -148,50 +149,53 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom, // Map visible bounds back to layer space, and intersect with parameter bounds Rect layerBounds = visibleBounds; - Matrix4 inverse; - inverse.loadInverse(*previous.transform); - inverse.mapRect(layerBounds); - layerBounds.doIntersect(unmappedBounds); + if (CC_LIKELY(!layerBounds.isEmpty())) { + // if non-empty, can safely map by the inverse transform + Matrix4 inverse; + inverse.loadInverse(*previous.transform); + inverse.mapRect(layerBounds); + layerBounds.doIntersect(unmappedBounds); + } int saveValue = mState.save((int) flags); Snapshot& snapshot = *mState.writableSnapshot(); // layerBounds is in original bounds space, but clipped by current recording clip - if (layerBounds.isEmpty() || unmappedBounds.isEmpty()) { - // Don't bother recording layer, since it's been rejected + if (!layerBounds.isEmpty() && !unmappedBounds.isEmpty()) { if (CC_LIKELY(clippedLayer)) { - snapshot.resetClip(0, 0, 0, 0); + auto previousClip = getRecordedClip(); // capture before new snapshot clip has changed + if (addOp(alloc().create_trivial( + unmappedBounds, + *previous.transform, // transform to *draw* with + previousClip, // clip to *draw* with + refPaint(paint))) >= 0) { + snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer; + snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight()); + snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f); + + Rect clip = layerBounds; + clip.translate(-unmappedBounds.left, -unmappedBounds.top); + snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom); + snapshot.roundRectClipState = nullptr; + return saveValue; + } + } else { + if (addOp(alloc().create_trivial( + unmappedBounds, + *mState.currentSnapshot()->transform, + getRecordedClip(), + refPaint(paint))) >= 0) { + snapshot.flags |= Snapshot::kFlagIsLayer; + return saveValue; + } } - return saveValue; } + // Layer not needed, so skip recording it... if (CC_LIKELY(clippedLayer)) { - auto previousClip = getRecordedClip(); // note: done before new snapshot's clip has changed - - snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer; - snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight()); - snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f); - - Rect clip = layerBounds; - clip.translate(-unmappedBounds.left, -unmappedBounds.top); - snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom); - snapshot.roundRectClipState = nullptr; - - addOp(alloc().create_trivial( - unmappedBounds, - *previous.transform, // transform to *draw* with - previousClip, // clip to *draw* with - refPaint(paint))); - } else { - snapshot.flags |= Snapshot::kFlagIsLayer; - - addOp(alloc().create_trivial( - unmappedBounds, - *mState.currentSnapshot()->transform, - getRecordedClip(), - refPaint(paint))); + // ... and set empty clip to reject inner content, if possible + snapshot.resetClip(0, 0, 0, 0); } - return saveValue; } @@ -267,7 +271,7 @@ static Rect calcBoundsOfPoints(const float* points, int floatCount) { // Geometry void RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPaint& paint) { - if (floatCount < 2) return; + if (CC_UNLIKELY(floatCount < 2 || PaintUtils::paintWillNotDraw(paint))) return; floatCount &= ~0x1; // round down to nearest two addOp(alloc().create_trivial( @@ -278,7 +282,7 @@ void RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPa } void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPaint& paint) { - if (floatCount < 4) return; + if (CC_UNLIKELY(floatCount < 4 || PaintUtils::paintWillNotDraw(paint))) return; floatCount &= ~0x3; // round down to nearest four addOp(alloc().create_trivial( @@ -289,6 +293,8 @@ void RecordingCanvas::drawLines(const float* points, int floatCount, const SkPai } void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) { + if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return; + addOp(alloc().create_trivial( Rect(left, top, right, bottom), *(mState.currentSnapshot()->transform), @@ -330,6 +336,8 @@ void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const } void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { + if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return; + if (paint.getStyle() == SkPaint::kFill_Style && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) { int count = 0; @@ -354,8 +362,11 @@ void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { } } } + void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const SkPaint& paint) { + if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return; + if (CC_LIKELY(MathUtils::isPositive(rx) || MathUtils::isPositive(ry))) { addOp(alloc().create_trivial( Rect(left, top, right, bottom), @@ -390,7 +401,8 @@ void RecordingCanvas::drawRoundRect( void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { // TODO: move to Canvas.h - if (radius <= 0) return; + if (CC_UNLIKELY(radius <= 0 || PaintUtils::paintWillNotDraw(paint))) return; + drawOval(x - radius, y - radius, x + radius, y + radius, paint); } @@ -410,6 +422,8 @@ void RecordingCanvas::drawCircle( } void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { + if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return; + addOp(alloc().create_trivial( Rect(left, top, right, bottom), *(mState.currentSnapshot()->transform), @@ -419,6 +433,8 @@ void RecordingCanvas::drawOval(float left, float top, float right, float bottom, void RecordingCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) { + if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return; + if (fabs(sweepAngle) >= 360.0f) { drawOval(left, top, right, bottom, paint); } else { @@ -432,6 +448,8 @@ void RecordingCanvas::drawArc(float left, float top, float right, float bottom, } void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) { + if (CC_UNLIKELY(PaintUtils::paintWillNotDraw(paint))) return; + addOp(alloc().create_trivial( Rect(path.getBounds()), *(mState.currentSnapshot()->transform), @@ -440,8 +458,8 @@ void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) { } void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { - mDisplayList->pushStagingFunctors.push_back(tree->getFunctor()); mDisplayList->ref(tree); + mDisplayList->vectorDrawables.push_back(tree); addOp(alloc().create_trivial( tree, Rect(tree->stagingProperties()->getBounds()), @@ -604,7 +622,7 @@ void RecordingCanvas::callDrawGLFunction(Functor* functor, functor)); } -size_t RecordingCanvas::addOp(RecordedOp* op) { +int RecordingCanvas::addOp(RecordedOp* op) { // skip op with empty clip if (op->localClip && op->localClip->rect.isEmpty()) { // NOTE: this rejection happens after op construction/content ref-ing, so content ref'd diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 372be241042a37cf70577f606f83567af6a5c5e2..337e97bf450b0af66da5aacbd2eb8526bb557765 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -208,7 +208,7 @@ private: void drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint); - size_t addOp(RecordedOp* op); + int addOp(RecordedOp* op); // ---------------------------------------------------------------------------- // lazy object copy // ---------------------------------------------------------------------------- diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h index dbd188fa15c5d49c1800ac3e100b5f12ba5958a6..eb05e917133531f5001394b333aa4fcab6ffe3f4 100644 --- a/libs/hwui/Rect.h +++ b/libs/hwui/Rect.h @@ -73,6 +73,13 @@ public: bottom(height) { } + inline Rect(const SkIRect& rect): // NOLINT, implicit + left(rect.fLeft), + top(rect.fTop), + right(rect.fRight), + bottom(rect.fBottom) { + } + inline Rect(const SkRect& rect): // NOLINT, implicit left(rect.fLeft), top(rect.fTop), diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index d48d54438ae94f407fbaf8021d72ea4677d9d7e8..bdcad798f05edec9a3292c96f4069407ebd95f76 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -301,7 +301,10 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { LayerType layerType = properties().effectiveLayerType(); // If we are not a layer OR we cannot be rendered (eg, view was detached) // we need to destroy any Layers we may have had previously - if (CC_LIKELY(layerType != LayerType::RenderLayer) || CC_UNLIKELY(!isRenderable())) { + if (CC_LIKELY(layerType != LayerType::RenderLayer) + || CC_UNLIKELY(!isRenderable()) + || CC_UNLIKELY(properties().getWidth() == 0) + || CC_UNLIKELY(properties().getHeight() == 0)) { if (CC_UNLIKELY(mLayer)) { destroyLayer(mLayer); mLayer = nullptr; @@ -419,6 +422,16 @@ void RenderNode::prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer) { pushStagingDisplayListChanges(info); } prepareSubTree(info, childFunctorsNeedLayer, mDisplayList); + + if (mDisplayList) { + for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) { + // If any vector drawable in the display list needs update, damage the node. + if (vectorDrawable->isDirty()) { + damageSelf(info); + } + vectorDrawable->setPropertyChangeWillBeConsumed(true); + } + } pushLayerUpdate(info); info.damageAccumulator->popTransform(); @@ -479,8 +492,8 @@ void RenderNode::syncDisplayList(TreeInfo* info) { for (auto& iter : mDisplayList->getFunctors()) { (*iter.functor)(DrawGlInfo::kModeSync, nullptr); } - for (size_t i = 0; i < mDisplayList->getPushStagingFunctors().size(); i++) { - (*mDisplayList->getPushStagingFunctors()[i])(); + for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) { + vectorDrawable->syncProperties(); } } } diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index c1221f7f7981aa6e0c6fb42e409a83e2660a5c3a..6a6e8dbb3fcd4f440d8a09a1de3d48665e20f042 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -611,9 +611,7 @@ public: bool fitsOnLayer() const { const DeviceInfo* deviceInfo = DeviceInfo::get(); return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize() - && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize() - && mPrimitiveFields.mWidth > 0 - && mPrimitiveFields.mHeight > 0; + && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize(); } bool promotedToLayer() const { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 0693804d57700adde82a30e2f4c848416eb07ce1..3b6fae08773da82286f1af8a863e4b87f0e55ccd 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -329,9 +329,10 @@ void SkiaCanvas::restoreToCount(int restoreCount) { static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) { SkCanvas::SaveLayerFlags layerFlags = 0; - if (!(flags & SaveFlags::HasAlphaLayer)) { - layerFlags |= SkCanvas::kIsOpaque_SaveLayerFlag; - } + // We intentionally ignore the SaveFlags::HasAlphaLayer and + // SkCanvas::kIsOpaque_SaveLayerFlag flags because HWUI ignores it + // and our Android client may use it incorrectly. + // In Skia, this flag is purely for performance optimization. if (!(flags & SaveFlags::ClipToLayer)) { layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag; diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp index 760d814f27a8c45dec1515e91f164f076b9e6b85..cc96a137c3064573a09b514361692dc0e630db27 100644 --- a/libs/hwui/SpotShadow.cpp +++ b/libs/hwui/SpotShadow.cpp @@ -942,9 +942,13 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength AlphaVertex::set(&shadowVertices[vertexBufferIndex++], newPenumbra[i].x, newPenumbra[i].y, PENUMBRA_ALPHA); } + // Since the umbra can be a faked one when the occluder is too high, the umbra should be lighter + // in this case. + float scaledUmbraAlpha = UMBRA_ALPHA * shadowStrengthScale; + for (int i = 0; i < umbraLength; i++) { AlphaVertex::set(&shadowVertices[vertexBufferIndex++], umbra[i].x, umbra[i].y, - UMBRA_ALPHA); + scaledUmbraAlpha); } for (int i = 0; i < verticesPairIndex; i++) { @@ -984,14 +988,14 @@ void SpotShadow::generateTriangleStrip(bool isCasterOpaque, float shadowStrength indexBuffer[indexBufferIndex++] = newPenumbraLength + i; indexBuffer[indexBufferIndex++] = vertexBufferIndex; AlphaVertex::set(&shadowVertices[vertexBufferIndex++], - closerVertex.x, closerVertex.y, UMBRA_ALPHA); + closerVertex.x, closerVertex.y, scaledUmbraAlpha); } } else { // If there is no occluded umbra at all, then draw the triangle fan // starting from the centroid to all umbra vertices. int lastCentroidIndex = vertexBufferIndex; AlphaVertex::set(&shadowVertices[vertexBufferIndex++], centroid.x, - centroid.y, UMBRA_ALPHA); + centroid.y, scaledUmbraAlpha); for (int i = 0; i < umbraLength; i++) { indexBuffer[indexBufferIndex++] = newPenumbraLength + i; indexBuffer[indexBufferIndex++] = lastCentroidIndex; diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index ade8600ab78b365b6d79aadfc0300ec02a568bd0..523924af5ef13dbee48cb46ef0293f5226e55c2a 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -167,6 +167,10 @@ bool TextureCache::prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap return texture; } +bool TextureCache::prefetch(const SkBitmap* bitmap) { + return getCachedTexture(bitmap, AtlasUsageType::Use); +} + Texture* TextureCache::get(const SkBitmap* bitmap, AtlasUsageType atlasUsageType) { Texture* texture = getCachedTexture(bitmap, atlasUsageType); diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index a4317cee73fd0d2782f9222879c6f9dcbc6304eb..0a61b6b1a52223c62420ac1d6b7962589b3e47b7 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -77,6 +77,13 @@ public: */ bool prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap); + /** + * Attempts to precache the SkBitmap. Returns true if a Texture was successfully + * acquired for the bitmap, false otherwise. Does not mark the Texture + * as in use and won't update currently in-use Textures. + */ + bool prefetch(const SkBitmap* bitmap); + /** * Returns the texture associated with the specified bitmap from either within the cache, or * the AssetAtlas. If the texture cannot be found in the cache, a new texture is generated. diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 2b7994139641009068779d28eed96722416c535c..aeee66106fb347f92f50f36f54c66823980f2c96 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -202,7 +202,9 @@ void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeSca if (properties.getFillGradient() != nullptr) { paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha())); SkShader* newShader = properties.getFillGradient()->newWithLocalMatrix(matrix); - paint.setShader(newShader); + // newWithLocalMatrix(...) creates a new SkShader and returns a bare pointer. We need to + // remove the extra ref so that the ref count is correctly managed. + paint.setShader(newShader)->unref(); needsFill = true; } else if (properties.getFillColor() != SK_ColorTRANSPARENT) { paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha())); @@ -222,7 +224,9 @@ void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeSca if (properties.getStrokeGradient() != nullptr) { paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha())); SkShader* newShader = properties.getStrokeGradient()->newWithLocalMatrix(matrix); - paint.setShader(newShader); + // newWithLocalMatrix(...) creates a new SkShader and returns a bare pointer. We need to + // remove the extra ref so that the ref count is correctly managed. + paint.setShader(newShader)->unref(); needsStroke = true; } else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) { paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha())); diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index 3586d8a1d967c910514cb78cfe3cce0876d6fcce..6c1815fe130108b852879750d272af43c02ee4a0 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -673,21 +673,17 @@ public: void onPropertyChanged(TreeProperties* prop); TreeProperties* mutateStagingProperties() { return &mStagingProperties; } const TreeProperties* stagingProperties() const { return &mStagingProperties; } - PushStagingFunctor* getFunctor() { return &mFunctor;} // This should only be called from animations on RT TreeProperties* mutateProperties() { return &mProperties; } + // This should always be called from RT. + void markDirty() { mCache.dirty = true; } + bool isDirty() const { return mCache.dirty; } + bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; } + void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; } + private: - class VectorDrawableFunctor : public PushStagingFunctor { - public: - VectorDrawableFunctor(Tree* tree) : mTree(tree) {} - virtual void operator ()() { - mTree->syncProperties(); - } - private: - Tree* mTree; - }; SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop); bool allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height); @@ -704,8 +700,6 @@ private: TreeProperties mProperties = TreeProperties(this); TreeProperties mStagingProperties = TreeProperties(this); - VectorDrawableFunctor mFunctor = VectorDrawableFunctor(this); - SkPaint mPaint; struct Cache { SkBitmap bitmap; @@ -717,6 +711,8 @@ private: PropertyChangedListener mPropertyChangedListener = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty); + + mutable bool mWillBeConsumed = false; }; } // namespace VectorDrawable diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp index fcdde45c49f2e378c3d7b36be27a23b708ab3452..49e9f65582ae69a21589ebec5f04956d7f8c505f 100644 --- a/libs/hwui/font/CacheTexture.cpp +++ b/libs/hwui/font/CacheTexture.cpp @@ -330,5 +330,17 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_ return false; } +uint32_t CacheTexture::calculateFreeMemory() const { + CacheBlock* cacheBlock = mCacheBlocks; + uint32_t free = 0; + // currently only two formats are supported: GL_ALPHA or GL_RGBA; + uint32_t bpp = mFormat == GL_RGBA ? 4 : 1; + while (cacheBlock) { + free += bpp * cacheBlock->mWidth * cacheBlock->mHeight; + cacheBlock = cacheBlock->mNext; + } + return free; +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h index 4dfb41dafcc7041bc601817614b1d98abbb8f96d..6750a8ae11cf824b1c407abe13d7feab602e4260 100644 --- a/libs/hwui/font/CacheTexture.h +++ b/libs/hwui/font/CacheTexture.h @@ -178,6 +178,8 @@ public: return mCurrentQuad == mMaxQuadCount; } + uint32_t calculateFreeMemory() const; + private: void setDirty(bool dirty); diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp index 8e04c8715f62a37d5dbe243b5610b499d557ce6e..a95454a4c0101bff5a8d3c3d8ad536b6f50f6c9c 100644 --- a/libs/hwui/font/Font.cpp +++ b/libs/hwui/font/Font.cpp @@ -408,9 +408,15 @@ void Font::render(const SkPaint* paint, const glyph_t* glyphs, if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) { int penX = x + (int) roundf(positions[(glyphsCount << 1)]); int penY = y + (int) roundf(positions[(glyphsCount << 1) + 1]); - +#ifdef BUGREPORT_FONT_CACHE_USAGE + mState->historyTracker().glyphRendered(cachedGlyph, penX, penY); +#endif (*this.*render)(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH, bounds, positions); + } else { +#ifdef BUGREPORT_FONT_CACHE_USAGE + mState->historyTracker().glyphRendered(cachedGlyph, -1, -1); +#endif } glyphsCount++; diff --git a/libs/hwui/font/FontCacheHistoryTracker.cpp b/libs/hwui/font/FontCacheHistoryTracker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a2bfb27535e521497f3281cded0519a84843aeac --- /dev/null +++ b/libs/hwui/font/FontCacheHistoryTracker.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FontCacheHistoryTracker.h" + +#include "CachedGlyphInfo.h" +#include "CacheTexture.h" + +namespace android { +namespace uirenderer { + +void FontCacheHistoryTracker::dumpCachedGlyph(String8& log, const CachedGlyph& glyph) { + log.appendFormat("glyph (texture %p, position: (%d, %d), size: %dx%d, gen: %d)", glyph.texture, + glyph.startX, glyph.startY, glyph.bitmapW, glyph.bitmapH, glyph.generation); +} + +void FontCacheHistoryTracker::dumpRenderEntry(String8& log, const RenderEntry& entry) { + if (entry.penX == -1 && entry.penY == -1) { + log.appendFormat(" glyph skipped in gen: %d\n", entry.glyph.generation); + } else { + log.appendFormat(" rendered "); + dumpCachedGlyph(log, entry.glyph); + log.appendFormat(" at (%d, %d)\n", entry.penX, entry.penY); + } +} + +void FontCacheHistoryTracker::dumpUploadEntry(String8& log, const CachedGlyph& glyph) { + if (glyph.bitmapW == 0 && glyph.bitmapH == 0) { + log.appendFormat(" cleared cachetexture %p in gen %d\n", glyph.texture, + glyph.generation); + } else { + log.appendFormat(" uploaded "); + dumpCachedGlyph(log, glyph); + log.appendFormat("\n"); + } +} + +void FontCacheHistoryTracker::dump(String8& log) const { + log.appendFormat("FontCacheHistory: \n"); + log.appendFormat(" Upload history: \n"); + for (size_t i = 0; i < mUploadHistory.size(); i++) { + dumpUploadEntry(log, mUploadHistory[i]); + } + log.appendFormat(" Render history: \n"); + for (size_t i = 0; i < mRenderHistory.size(); i++) { + dumpRenderEntry(log, mRenderHistory[i]); + } +} + +void FontCacheHistoryTracker::glyphRendered(CachedGlyphInfo* glyphInfo, int penX, int penY) { + RenderEntry& entry = mRenderHistory.next(); + entry.glyph.generation = generation; + entry.glyph.texture = glyphInfo->mCacheTexture; + entry.glyph.startX = glyphInfo->mStartX; + entry.glyph.startY = glyphInfo->mStartY; + entry.glyph.bitmapW = glyphInfo->mBitmapWidth; + entry.glyph.bitmapH = glyphInfo->mBitmapHeight; + entry.penX = penX; + entry.penY = penY; +} + +void FontCacheHistoryTracker::glyphUploaded(CacheTexture* texture, uint32_t x, uint32_t y, + uint16_t glyphW, uint16_t glyphH) { + CachedGlyph& glyph = mUploadHistory.next(); + glyph.generation = generation; + glyph.texture = texture; + glyph.startX = x; + glyph.startY = y; + glyph.bitmapW = glyphW; + glyph.bitmapH = glyphH; +} + +void FontCacheHistoryTracker::glyphsCleared(CacheTexture* texture) { + CachedGlyph& glyph = mUploadHistory.next(); + glyph.generation = generation; + glyph.texture = texture; + glyph.startX = 0; + glyph.startY = 0; + glyph.bitmapW = 0; + glyph.bitmapH = 0; +} + +void FontCacheHistoryTracker::frameCompleted() { + generation++; +} +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/font/FontCacheHistoryTracker.h b/libs/hwui/font/FontCacheHistoryTracker.h new file mode 100644 index 0000000000000000000000000000000000000000..f1d9b9f10dc03555c6e4877d65b8cd07d6286b13 --- /dev/null +++ b/libs/hwui/font/FontCacheHistoryTracker.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include "../utils/RingBuffer.h" + +#include + +namespace android { +namespace uirenderer { + +class CacheTexture; +struct CachedGlyphInfo; + +// Tracks glyph uploads and recent rendered/skipped glyphs, so it can give an idea +// what a missing character is: skipped glyph, wrong coordinates in cache texture etc. +class FontCacheHistoryTracker { +public: + void glyphRendered(CachedGlyphInfo*, int penX, int penY); + void glyphUploaded(CacheTexture*, uint32_t x, uint32_t y, uint16_t glyphW, uint16_t glyphH); + void glyphsCleared(CacheTexture*); + void frameCompleted(); + + void dump(String8& log) const; +private: + struct CachedGlyph { + void* texture; + uint16_t generation; + uint16_t startX; + uint16_t startY; + uint16_t bitmapW; + uint16_t bitmapH; + }; + + struct RenderEntry { + CachedGlyph glyph; + int penX; + int penY; + }; + + static void dumpCachedGlyph(String8& log, const CachedGlyph& glyph); + static void dumpRenderEntry(String8& log, const RenderEntry& entry); + static void dumpUploadEntry(String8& log, const CachedGlyph& glyph); + + RingBuffer mRenderHistory; + RingBuffer mUploadHistory; + uint16_t generation = 0; +}; + +}; // namespace uirenderer +}; // namespace android \ No newline at end of file diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 75e7fdf1309159727d0d9c1b01404df542686fe4..975ac8368e3def4be09045642b56d8c595c675ed 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -67,7 +67,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, , mEglManager(thread.eglManager()) , mOpaque(!translucent) , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) - , mJankTracker(thread.timeLord().frameIntervalNanos()) + , mJankTracker(thread.mainDisplayInfo()) , mProfiler(mFrames) , mContentDrawBounds(0, 0, 0, 0) { mRenderNodes.emplace_back(rootRenderNode); @@ -198,6 +198,48 @@ static bool wasSkipped(FrameInfo* info) { return info && ((*info)[FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame); } +bool CanvasContext::isSwapChainStuffed() { + static const auto SLOW_THRESHOLD = 6_ms; + + if (mSwapHistory.size() != mSwapHistory.capacity()) { + // We want at least 3 frames of history before attempting to + // guess if the queue is stuffed + return false; + } + nsecs_t frameInterval = mRenderThread.timeLord().frameIntervalNanos(); + auto& swapA = mSwapHistory[0]; + + // Was there a happy queue & dequeue time? If so, don't + // consider it stuffed + if (swapA.dequeueDuration < SLOW_THRESHOLD + && swapA.queueDuration < SLOW_THRESHOLD) { + return false; + } + + for (size_t i = 1; i < mSwapHistory.size(); i++) { + auto& swapB = mSwapHistory[i]; + + // If there's a multi-frameInterval gap we effectively already dropped a frame, + // so consider the queue healthy. + if (swapA.swapCompletedTime - swapB.swapCompletedTime > frameInterval * 3) { + return false; + } + + // Was there a happy queue & dequeue time? If so, don't + // consider it stuffed + if (swapB.dequeueDuration < SLOW_THRESHOLD + && swapB.queueDuration < SLOW_THRESHOLD) { + return false; + } + + swapA = swapB; + } + + // All signs point to a stuffed swap chain + ATRACE_NAME("swap chain stuffed"); + return true; +} + void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target) { mRenderThread.removeFrameCallback(this); @@ -243,7 +285,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, if (CC_LIKELY(mSwapHistory.size())) { nsecs_t latestVsync = mRenderThread.timeLord().latestVsync(); - const SwapHistory& lastSwap = mSwapHistory.back(); + SwapHistory& lastSwap = mSwapHistory.back(); nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync); // The slight fudge-factor is to deal with cases where // the vsync was estimated due to being slow handling the signal. @@ -253,15 +295,17 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, // Already drew for this vsync pulse, UI draw request missed // the deadline for RT animations info.out.canDrawThisFrame = false; - } else if (lastSwap.swapTime < latestVsync) { + } else if (vsyncDelta >= mRenderThread.timeLord().frameIntervalNanos() * 3 + || (latestVsync - mLastDropVsync) < 500_ms) { + // It's been several frame intervals, assume the buffer queue is fine + // or the last drop was too recent info.out.canDrawThisFrame = true; } else { - // We're maybe behind? Find out for sure - int runningBehind = 0; - // TODO: Have this method be on Surface, too, not just ANativeWindow... - ANativeWindow* window = mNativeSurface.get(); - window->query(window, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind); - info.out.canDrawThisFrame = !runningBehind; + info.out.canDrawThisFrame = !isSwapChainStuffed(); + if (!info.out.canDrawThisFrame) { + // dropping frame + mLastDropVsync = mRenderThread.timeLord().latestVsync(); + } } } else { info.out.canDrawThisFrame = true; @@ -282,6 +326,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, void CanvasContext::stopDrawing() { mRenderThread.removeFrameCallback(this); + mAnimationContext->pauseAnimators(); } void CanvasContext::notifyFramePending() { @@ -515,10 +560,27 @@ void CanvasContext::draw() { } SwapHistory& swap = mSwapHistory.next(); swap.damage = screenDirty; - swap.swapTime = systemTime(CLOCK_MONOTONIC); + swap.swapCompletedTime = systemTime(CLOCK_MONOTONIC); swap.vsyncTime = mRenderThread.timeLord().latestVsync(); + if (mNativeSurface.get()) { + int durationUs; + mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs); + swap.dequeueDuration = us2ns(durationUs); + mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs); + swap.queueDuration = us2ns(durationUs); + } else { + swap.dequeueDuration = 0; + swap.queueDuration = 0; + } + mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) + = swap.dequeueDuration; + mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) + = swap.queueDuration; mHaveNewSurface = false; mFrameNumber = -1; + } else { + mCurrentFrameInfo->set(FrameInfoIndex::DequeueBufferDuration) = 0; + mCurrentFrameInfo->set(FrameInfoIndex::QueueBufferDuration) = 0; } // TODO: Use a fence for real completion? @@ -546,6 +608,10 @@ void CanvasContext::draw() { } GpuMemoryTracker::onFrameCompleted(); +#ifdef BUGREPORT_FONT_CACHE_USAGE + caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted(); +#endif + } // Called by choreographer to do an RT-driven animation @@ -571,6 +637,9 @@ void CanvasContext::prepareAndDraw(RenderNode* node) { prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC), node); if (info.out.canDrawThisFrame) { draw(); + } else { + // wait on fences so tasks don't overlap next frame + waitOnFences(); } } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index a6eb7adc356825234d09fd43062ca84cd93e560e..e1821751b57fea2a12fbb1e2b295635e76f3c6e5 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -168,6 +168,8 @@ public: ANDROID_API int64_t getFrameNumber(); + void waitOnFences(); + private: friend class RegisterFrameCallbackTask; // TODO: Replace with something better for layer & other GL object @@ -178,7 +180,7 @@ private: void freePrefetchedLayers(TreeObserver* observer); - void waitOnFences(); + bool isSwapChainStuffed(); EGLint mLastFrameWidth = 0; EGLint mLastFrameHeight = 0; @@ -198,12 +200,17 @@ private: struct SwapHistory { SkRect damage; nsecs_t vsyncTime; - nsecs_t swapTime; + nsecs_t swapCompletedTime; + nsecs_t dequeueDuration; + nsecs_t queueDuration; }; RingBuffer mSwapHistory; int64_t mFrameNumber = -1; + // last vsync for a dropped frame due to stuffed queue + nsecs_t mLastDropVsync = 0; + bool mOpaque; #if HWUI_NEW_OPS BakedOpRenderer::LightInfo mLightInfo; diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index c9c07b3df292c72b770c0f18b0787b83a5d69801..e3b6dc6fd9fee88ecfc9708c664270a6af3a9677 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -104,6 +104,9 @@ void DrawFrameTask::run() { if (CC_LIKELY(canDrawThisFrame)) { context->draw(); + } else { + // wait on fences so tasks don't overlap next frame + context->waitOnFences(); } if (!canUnblockUiThread) { diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 54af2829cf40d282b9f9b6c2495ef352959b1f8a..a734401a2be60d80135338f6ca3060ab70f68b32 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -22,9 +22,11 @@ #include "Readback.h" #include "Rect.h" #include "renderthread/CanvasContext.h" +#include "renderthread/EglManager.h" #include "renderthread/RenderTask.h" #include "renderthread/RenderThread.h" #include "utils/Macros.h" +#include "utils/TimeUtils.h" namespace android { namespace uirenderer { @@ -44,6 +46,8 @@ namespace renderthread { typedef struct { \ a1; a2; a3; a4; a5; a6; a7; a8; \ } ARGS(name); \ + static_assert(std::is_trivially_destructible::value, \ + "Error, ARGS must be trivially destructible!"); \ static void* Bridge_ ## name(ARGS(name)* args) #define SETUP_TASK(method) \ @@ -154,7 +158,7 @@ void RenderProxy::updateSurface(const sp& surface) { SETUP_TASK(updateSurface); args->context = mContext; args->surface = surface.get(); - postAndWait(task); + post(task); } CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) { @@ -514,6 +518,10 @@ void RenderProxy::setProcessStatsBuffer(int fd) { post(task); } +int RenderProxy::getRenderThreadTid() { + return mRenderThread.getTid(); +} + CREATE_BRIDGE3(addRenderNode, CanvasContext* context, RenderNode* node, bool placeFront) { args->context->addRenderNode(args->node, args->placeFront); return nullptr; @@ -632,6 +640,41 @@ int RenderProxy::copySurfaceInto(sp& surface, SkBitmap* bitmap) { reinterpret_cast( staticPostAndWait(task) )); } +CREATE_BRIDGE2(prepareToDraw, RenderThread* thread, SkBitmap* bitmap) { + if (Caches::hasInstance() && args->thread->eglManager().hasEglContext()) { + ATRACE_NAME("Bitmap#prepareToDraw task"); + Caches::getInstance().textureCache.prefetch(args->bitmap); + } + delete args->bitmap; + args->bitmap = nullptr; + return nullptr; +} + +void RenderProxy::prepareToDraw(const SkBitmap& bitmap) { + // If we haven't spun up a hardware accelerated window yet, there's no + // point in precaching these bitmaps as it can't impact jank. + // We also don't know if we even will spin up a hardware-accelerated + // window or not. + if (!RenderThread::hasInstance()) return; + RenderThread* renderThread = &RenderThread::getInstance(); + SETUP_TASK(prepareToDraw); + args->thread = renderThread; + args->bitmap = new SkBitmap(bitmap); + nsecs_t lastVsync = renderThread->timeLord().latestVsync(); + nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos(); + nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC); + // We expect the UI thread to take 4ms and for RT to be active from VSYNC+4ms to + // VSYNC+12ms or so, so aim for the gap during which RT is expected to + // be idle + // TODO: Make this concept a first-class supported thing? RT could use + // knowledge of pending draws to better schedule this task + if (timeToNextVsync > -6_ms && timeToNextVsync < 1_ms) { + renderThread->queueAt(task, estimatedNextVsync + 8_ms); + } else { + renderThread->queue(task); + } +} + void RenderProxy::post(RenderTask* task) { mRenderThread.queue(task); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 898b31421aad86368e4f7eb46c0fb07caa9891ba..bb111bd0de25537e6eede1b864fd3612a581ee26 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -115,6 +115,7 @@ public: ANDROID_API void setTextureAtlas(const sp& buffer, int64_t* map, size_t size); ANDROID_API void setProcessStatsBuffer(int fd); + ANDROID_API int getRenderThreadTid(); ANDROID_API void serializeDisplayListTree(); @@ -128,6 +129,7 @@ public: ANDROID_API long getDroppedFrameReportCount(); ANDROID_API static int copySurfaceInto(sp& surface, SkBitmap* bitmap); + ANDROID_API static void prepareToDraw(const SkBitmap& bitmap); private: RenderThread& mRenderThread; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 0d9ede063c79a8173063efc54f8c3b9b2a762735..9c10c4fdbad1576b7cd70b6d17e10d427ab2d6bc 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -191,7 +191,7 @@ void RenderThread::initThreadLocals() { initializeDisplayEventReceiver(); mEglManager = new EglManager(*this); mRenderState = new RenderState(*this); - mJankTracker = new JankTracker(frameIntervalNanos); + mJankTracker = new JankTracker(mDisplayInfo); } int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) { diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp index 146e735839d17e113df38dac45a3600140e1b8f4..99569755205f4a04e00895d17d008b9d7f02d7a5 100644 --- a/libs/hwui/tests/common/TestContext.cpp +++ b/libs/hwui/tests/common/TestContext.cpp @@ -33,7 +33,6 @@ static android::DisplayInfo DUMMY_DISPLAY { false, // secure? 0, // appVsyncOffset 0, // presentationDeadline - 0, // colorTransform }; DisplayInfo getBuiltInDisplay() { diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp index 54ca68d63dbe5d5706b94a8c39ffdae619b50c37..d4d7919f9eee4aeff5e1621a86da2dfdaf9e1441 100644 --- a/libs/hwui/tests/unit/ClipAreaTests.cpp +++ b/libs/hwui/tests/unit/ClipAreaTests.cpp @@ -275,5 +275,73 @@ TEST(ClipArea, serializeIntersectedClip_snap) { } } +TEST(ClipArea, serializeIntersectedClip_scale) { + ClipArea area(createClipArea()); + area.setClip(0, 0, 400, 400); + LinearAllocator allocator; + + SkPath circlePath; + circlePath.addCircle(50, 50, 50); + + ClipRegion recordedClip; + recordedClip.region.setPath(circlePath, SkRegion(SkIRect::MakeWH(100, 100))); + recordedClip.rect = Rect(100, 100); + + Matrix4 translateScale; + translateScale.loadTranslate(100, 100, 0); + translateScale.scale(2, 2, 1); + auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale); + + ASSERT_NE(nullptr, resolvedClip); + EXPECT_EQ(ClipMode::Region, resolvedClip->mode); + EXPECT_EQ(Rect(100, 100, 300, 300), resolvedClip->rect); + auto clipRegion = reinterpret_cast(resolvedClip); + EXPECT_EQ(SkIRect::MakeLTRB(100, 100, 300, 300), clipRegion->region.getBounds()); +} + +TEST(ClipArea, applyTransformToRegion_identity) { + SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4)); + ClipArea::applyTransformToRegion(Matrix4::identity(), ®ion); + EXPECT_TRUE(region.isRect()); + EXPECT_EQ(SkIRect::MakeLTRB(1, 2, 3, 4), region.getBounds()); +} + +TEST(ClipArea, applyTransformToRegion_translate) { + SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4)); + Matrix4 transform; + transform.loadTranslate(10, 20, 0); + ClipArea::applyTransformToRegion(transform, ®ion); + EXPECT_TRUE(region.isRect()); + EXPECT_EQ(SkIRect::MakeLTRB(11, 22, 13, 24), region.getBounds()); +} + +TEST(ClipArea, applyTransformToRegion_scale) { + SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4)); + Matrix4 transform; + transform.loadScale(2, 3, 1); + ClipArea::applyTransformToRegion(transform, ®ion); + EXPECT_TRUE(region.isRect()); + EXPECT_EQ(SkIRect::MakeLTRB(2, 6, 6, 12), region.getBounds()); +} + +TEST(ClipArea, applyTransformToRegion_translateScale) { + SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4)); + Matrix4 transform; + transform.translate(10, 20); + transform.scale(2, 3, 1); + ClipArea::applyTransformToRegion(transform, ®ion); + EXPECT_TRUE(region.isRect()); + EXPECT_EQ(SkIRect::MakeLTRB(12, 26, 16, 32), region.getBounds()); +} + +TEST(ClipArea, applyTransformToRegion_rotate90) { + SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4)); + Matrix4 transform; + transform.loadRotate(90); + ClipArea::applyTransformToRegion(transform, ®ion); + EXPECT_TRUE(region.isRect()); + EXPECT_EQ(SkIRect::MakeLTRB(-4, 1, -2, 3), region.getBounds()); +} + } // namespace uirenderer } // namespace android diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp index af54e079daab249a65f81702a60ced106075318e..53dbede2f8e1e07ec40d41f566630503e65c3bd0 100644 --- a/libs/hwui/tests/unit/FrameBuilderTests.cpp +++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp @@ -1459,7 +1459,8 @@ RENDERTHREAD_TEST(FrameBuilder, buildLayer) { static void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { SkPaint paint; - paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel + // order put in blue channel, transparent so overlapped content doesn't get rejected + paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder)); canvas->drawRect(0, 0, 100, 100, paint); } static void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp index 18171de250d0e2d8e7875d2a2942cd8848ce777a..c072d0b801354999f8c9219c768895bae06aba59 100644 --- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp +++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp @@ -81,6 +81,27 @@ TEST(RecordingCanvas, emptyClipRect) { ASSERT_EQ(0u, dl->getOps().size()) << "Must be zero ops. Rect should be rejected."; } +TEST(RecordingCanvas, emptyPaintRejection) { + auto dl = TestUtils::createDisplayList(200, 200, [](RecordingCanvas& canvas) { + SkPaint emptyPaint; + emptyPaint.setColor(Color::Transparent); + + float points[] = {0, 0, 200, 200}; + canvas.drawPoints(points, 4, emptyPaint); + canvas.drawLines(points, 4, emptyPaint); + canvas.drawRect(0, 0, 200, 200, emptyPaint); + canvas.drawRegion(SkRegion(SkIRect::MakeWH(200, 200)), emptyPaint); + canvas.drawRoundRect(0, 0, 200, 200, 10, 10, emptyPaint); + canvas.drawCircle(100, 100, 100, emptyPaint); + canvas.drawOval(0, 0, 200, 200, emptyPaint); + canvas.drawArc(0, 0, 200, 200, 0, 360, true, emptyPaint); + SkPath path; + path.addRect(0, 0, 200, 200); + canvas.drawPath(path, emptyPaint); + }); + EXPECT_EQ(0u, dl->getOps().size()) << "Op should be rejected"; +} + TEST(RecordingCanvas, drawArc) { auto dl = TestUtils::createDisplayList(200, 200, [](RecordingCanvas& canvas) { canvas.drawArc(0, 0, 200, 200, 0, 180, true, SkPaint()); @@ -340,6 +361,36 @@ TEST(RecordingCanvas, saveLayer_simple) { EXPECT_EQ(3, count); } +TEST(RecordingCanvas, saveLayer_rounding) { + auto dl = TestUtils::createDisplayList(100, 100, [](RecordingCanvas& canvas) { + canvas.saveLayerAlpha(10.25f, 10.75f, 89.25f, 89.75f, 128, SaveFlags::ClipToLayer); + canvas.drawRect(20, 20, 80, 80, SkPaint()); + canvas.restore(); + }); + int count = 0; + playbackOps(*dl, [&count](const RecordedOp& op) { + Matrix4 expectedMatrix; + switch(count++) { + case 0: + EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId); + EXPECT_EQ(Rect(10, 10, 90, 90), op.unmappedBounds) << "Expect bounds rounded out"; + break; + case 1: + EXPECT_EQ(RecordedOpId::RectOp, op.opId); + expectedMatrix.loadTranslate(-10, -10, 0); + EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix) << "Expect rounded offset"; + break; + case 2: + EXPECT_EQ(RecordedOpId::EndLayerOp, op.opId); + // Don't bother asserting recording state data - it's not used + break; + default: + ADD_FAILURE(); + } + }); + EXPECT_EQ(3, count); +} + TEST(RecordingCanvas, saveLayer_missingRestore) { auto dl = TestUtils::createDisplayList(200, 200, [](RecordingCanvas& canvas) { canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer); @@ -494,6 +545,21 @@ TEST(RecordingCanvas, saveLayer_rotateClipped) { EXPECT_EQ(3, count); } +TEST(RecordingCanvas, saveLayer_rejectBegin) { + auto dl = TestUtils::createDisplayList(200, 200, [](RecordingCanvas& canvas) { + canvas.save(SaveFlags::MatrixClip); + canvas.translate(0, -20); // avoid identity case + // empty clip rect should force layer + contents to be rejected + canvas.clipRect(0, -20, 200, -20, SkRegion::kIntersect_Op); + canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer); + canvas.drawRect(0, 0, 200, 200, SkPaint()); + canvas.restore(); + canvas.restore(); + }); + + ASSERT_EQ(0u, dl->getOps().size()) << "Begin/Rect/End should all be rejected."; +} + TEST(RecordingCanvas, drawRenderNode_rejection) { auto child = TestUtils::createNode(50, 50, 150, 150, [](RenderProperties& props, RecordingCanvas& canvas) { diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp index b2997dfb357fc3886183129880a86de04fd51b6d..cf76a8691dcd03bdbfbfeb4e270f1064dc7edd5a 100644 --- a/libs/hwui/tests/unit/RenderNodeTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeTests.cpp @@ -16,13 +16,26 @@ #include +#include "AnimationContext.h" +#include "DamageAccumulator.h" +#include "IContextFactory.h" #include "RenderNode.h" #include "TreeInfo.h" +#include "renderthread/CanvasContext.h" #include "tests/common/TestUtils.h" #include "utils/Color.h" using namespace android; using namespace android::uirenderer; +using namespace android::uirenderer::renderthread; + +class ContextFactory : public android::uirenderer::IContextFactory { +public: + android::uirenderer::AnimationContext* createAnimationContext + (android::uirenderer::renderthread::TimeLord& clock) override { + return new android::uirenderer::AnimationContext(clock); + } +}; TEST(RenderNode, hasParents) { auto child = TestUtils::createNode(0, 0, 200, 400, @@ -89,3 +102,31 @@ TEST(RenderNode, releasedCallback) { TestUtils::syncHierarchyPropertiesAndDisplayList(node); EXPECT_EQ(0, refcnt); } + +RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) { + ContextFactory contextFactory; + CanvasContext canvasContext(renderThread, false, nullptr, &contextFactory); + TreeInfo info(TreeInfo::MODE_RT_ONLY, canvasContext); + DamageAccumulator damageAccumulator; + info.damageAccumulator = &damageAccumulator; + info.observer = nullptr; + + { + auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400, + [](RenderProperties& props, TestCanvas& canvas) { + canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode); + }); + TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode); + EXPECT_TRUE(nonNullDLNode->getDisplayList()); + nonNullDLNode->prepareTree(info); + } + + { + auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr); + TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode); + EXPECT_FALSE(nullDLNode->getDisplayList()); + nullDLNode->prepareTree(info); + } + + canvasContext.destroy(nullptr); +} diff --git a/libs/hwui/tests/unit/RenderPropertiesTests.cpp b/libs/hwui/tests/unit/RenderPropertiesTests.cpp index 90010983f154720f3504cb630713544249cc5275..85655fc2728a38d6b3c756607eb6cdd1930141fb 100644 --- a/libs/hwui/tests/unit/RenderPropertiesTests.cpp +++ b/libs/hwui/tests/unit/RenderPropertiesTests.cpp @@ -42,7 +42,7 @@ TEST(RenderProperties, layerValidity) { props.setLeftTopRightBottom(0, 0, maxTextureSize + 1, maxTextureSize + 1); ASSERT_FALSE(props.fitsOnLayer()); - // Too small - can't have 0 dimen layer + // Too small, but still 'fits'. Not fitting is an error case, so don't report empty as such. props.setLeftTopRightBottom(0, 0, 100, 0); - ASSERT_FALSE(props.fitsOnLayer()); + ASSERT_TRUE(props.fitsOnLayer()); } diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp index 83b485fa705e8b8f4fb012173998d408cac009ac..8e0d3ee572a6888d38280887bd25da8ab5c18f2a 100644 --- a/libs/hwui/tests/unit/VectorDrawableTests.cpp +++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp @@ -426,5 +426,49 @@ TEST(VectorDrawable, groupProperties) { EXPECT_EQ(1.0f, properties->getPivotY()); } + +static SkShader* createShader(bool* isDestroyed) { + class TestShader : public SkShader { + public: + TestShader(bool* isDestroyed) : SkShader(), mDestroyed(isDestroyed) { + } + ~TestShader() { + *mDestroyed = true; + } + + Factory getFactory() const override { return nullptr; } + private: + bool* mDestroyed; + }; + return new TestShader(isDestroyed); +} + +TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) { + VectorDrawable::FullPath path("m1 1", 4); + SkBitmap bitmap; + SkImageInfo info = SkImageInfo::Make(5, 5, kN32_SkColorType, kPremul_SkAlphaType); + bitmap.setInfo(info); + bitmap.allocPixels(info); + SkCanvas canvas(bitmap); + + bool shaderIsDestroyed = false; + + // Initial ref count is 1 + SkShader* shader = createShader(&shaderIsDestroyed); + + // Setting the fill gradient increments the ref count of the shader by 1 + path.mutateStagingProperties()->setFillGradient(shader); + path.draw(&canvas, SkMatrix::I(), 1.0f, 1.0f, true); + // Resetting the fill gradient decrements the ref count of the shader by 1 + path.mutateStagingProperties()->setFillGradient(nullptr); + + // Expect ref count to be 1 again, i.e. nothing else to have a ref to the shader now. Unref() + // again should bring the ref count to zero and consequently trigger detor. + shader->unref(); + + // Verify that detor is called. + EXPECT_TRUE(shaderIsDestroyed); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/utils/TimeUtils.h b/libs/hwui/utils/TimeUtils.h index 8d42d7e5552191e08f5409c0f6245728690a38a6..ce181b766841e05bc2d74ef735cdc3473ccd4998 100644 --- a/libs/hwui/utils/TimeUtils.h +++ b/libs/hwui/utils/TimeUtils.h @@ -21,10 +21,18 @@ namespace android { namespace uirenderer { +constexpr nsecs_t operator"" _s (unsigned long long s) { + return seconds_to_nanoseconds(s); +} + constexpr nsecs_t operator"" _ms (unsigned long long ms) { return milliseconds_to_nanoseconds(ms); } +constexpr nsecs_t operator"" _us (unsigned long long us) { + return microseconds_to_nanoseconds(us); +} + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 27193b74337964b4559c40199b711dfd681211b1..abef66f9ecd9f13f13baa00e196b9ac114b13fbb 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -36,6 +36,29 @@ namespace android { +// --- WeakLooperCallback --- + +class WeakLooperCallback: public LooperCallback { +protected: + virtual ~WeakLooperCallback() { } + +public: + WeakLooperCallback(const wp& callback) : + mCallback(callback) { + } + + virtual int handleEvent(int fd, int events, void* data) { + sp callback = mCallback.promote(); + if (callback != NULL) { + return callback->handleEvent(fd, events, data); + } + return 0; // the client is gone, remove the callback + } + +private: + wp mCallback; +}; + // --- PointerController --- // Time to wait before starting the fade when the pointer is inactive. @@ -57,10 +80,11 @@ PointerController::PointerController(const sp& const sp& looper, const sp& spriteController) : mPolicy(policy), mLooper(looper), mSpriteController(spriteController) { mHandler = new WeakMessageHandler(this); + mCallback = new WeakLooperCallback(this); if (mDisplayEventReceiver.initCheck() == NO_ERROR) { mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK, - Looper::EVENT_INPUT, this, nullptr); + Looper::EVENT_INPUT, mCallback, nullptr); } else { ALOGE("Failed to initialize DisplayEventReceiver."); } diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index 99292d7ca8a6c5acd17fa514666d0e0ea2ffdc61..4794f3da824ccb41d68bf8b07182ddc34154ed02 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -144,6 +144,7 @@ private: sp mLooper; sp mSpriteController; sp mHandler; + sp mCallback; DisplayEventReceiver mDisplayEventReceiver; diff --git a/location/java/android/location/Address.java b/location/java/android/location/Address.java index b152f48a3e9e0dfcfc03c155840cc314a7d9ce26..335ad5ebcde5d80b1bb36bf3e5802356b0a94022 100644 --- a/location/java/android/location/Address.java +++ b/location/java/android/location/Address.java @@ -28,7 +28,7 @@ import android.os.Parcelable; /** * A class representing an Address, i.e, a set of Strings describing a location. * - * The addres format is a simplified version of xAL (eXtensible Address Language) + * The address format is a simplified version of xAL (eXtensible Address Language) * http://www.oasis-open.org/committees/ciq/ciq.html#6 */ public class Address implements Parcelable { diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java index 315169472a7c3a7c7ac76ed6cda014de547e3963..7db04663c83beb9499b7b5cef9eeb7fb2adf581a 100644 --- a/location/java/android/location/GnssMeasurementsEvent.java +++ b/location/java/android/location/GnssMeasurementsEvent.java @@ -98,13 +98,13 @@ public final class GnssMeasurementsEvent implements Parcelable { throw new InvalidParameterException("Parameter 'clock' must not be null."); } if (measurements == null || measurements.length == 0) { - throw new InvalidParameterException( - "Parameter 'measurements' must not be null or empty."); + mReadOnlyMeasurements = Collections.emptyList(); + } else { + Collection measurementCollection = Arrays.asList(measurements); + mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection); } mClock = clock; - Collection measurementCollection = Arrays.asList(measurements); - mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection); } /** diff --git a/location/java/android/location/IFusedProvider.aidl b/location/java/android/location/IFusedProvider.aidl index e86ad1ac5147a8134e6a5e660de5b7a6468bdd4d..8870d2a2a4206a9cc44f8ffa85a2183b3ee05cc2 100644 --- a/location/java/android/location/IFusedProvider.aidl +++ b/location/java/android/location/IFusedProvider.aidl @@ -22,11 +22,11 @@ import android.hardware.location.IFusedLocationHardware; * Interface definition for Location providers that require FLP services. * @hide */ -oneway interface IFusedProvider { +interface IFusedProvider { /** * Provides access to a FusedLocationHardware instance needed for the provider to work. * * @param instance The FusedLocationHardware available for the provider to use. */ void onFusedLocationHardwareChange(in IFusedLocationHardware instance); -} +} \ No newline at end of file diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index 5286f8fa5ad31bbbda6c1c7b0a1f7a51ee9207b3..89709ee6b95a147800e02a690308a519a16514cc 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -24,6 +24,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; +import android.util.SparseIntArray; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -169,6 +170,66 @@ public final class AudioAttributes implements Parcelable { */ public final static int USAGE_VIRTUAL_SOURCE = 15; + /** + * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES + * if applicable. + */ + + /** + * @hide + * Denotes a usage for notifications that do not expect immediate intervention from the user, + * will be muted when the Zen mode disables notifications + * @see #SUPPRESSIBLE_USAGES + */ + public final static int SUPPRESSIBLE_NOTIFICATION = 1; + /** + * @hide + * Denotes a usage for notifications that do expect immediate intervention from the user, + * will be muted when the Zen mode disables calls + * @see #SUPPRESSIBLE_USAGES + */ + public final static int SUPPRESSIBLE_CALL = 2; + + /** + * @hide + * Array of all usage types for calls and notifications to assign the suppression behavior, + * used by the Zen mode restrictions. + * @see com.android.server.notification.ZenModeHelper + */ + public static final SparseIntArray SUPPRESSIBLE_USAGES; + + static { + SUPPRESSIBLE_USAGES = new SparseIntArray(); + SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION); + SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL); + SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL); + SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION); + SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION); + SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION); + } + + /** + * @hide + * Array of all usage types exposed in the SDK that applications can use. + */ + public final static int[] SDK_USAGES = { + USAGE_UNKNOWN, + USAGE_MEDIA, + USAGE_VOICE_COMMUNICATION, + USAGE_VOICE_COMMUNICATION_SIGNALLING, + USAGE_ALARM, + USAGE_NOTIFICATION, + USAGE_NOTIFICATION_RINGTONE, + USAGE_NOTIFICATION_COMMUNICATION_REQUEST, + USAGE_NOTIFICATION_COMMUNICATION_INSTANT, + USAGE_NOTIFICATION_COMMUNICATION_DELAYED, + USAGE_NOTIFICATION_EVENT, + USAGE_ASSISTANCE_ACCESSIBILITY, + USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, + USAGE_ASSISTANCE_SONIFICATION, + USAGE_GAME + }; + /** * Flag defining a behavior where the audibility of the sound will be ensured by the system. */ diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index a4484e757ac5b0324c1a60fe5caab34e4dc16dcd..81cc93da2e6fee06fc1967fd7a70967ce44da8e8 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -263,6 +263,9 @@ public final class AudioFormat implements Parcelable { * on some platforms when converting to short internally. */ public static final int ENCODING_IEC61937 = 13; + /** Audio data format: DOLBY TRUEHD compressed + **/ + public static final int ENCODING_DOLBY_TRUEHD = 14; /** Invalid audio channel configuration */ /** @deprecated Use {@link #CHANNEL_INVALID} instead. */ diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 4bdc70e376218283fa273ad037eada0e9f011a6b..33c1c3f6acc0c82188ed20264dc787a0c234c41b 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -2744,6 +2744,7 @@ public class AudioManager { * to be notified. * Use {@link AudioManager#getActiveRecordingConfigurations()} to query the current * configuration. + * @see AudioRecordingConfiguration */ public static abstract class AudioRecordingCallback { /** @@ -2850,6 +2851,7 @@ public class AudioManager { * Returns the current active audio recording configurations of the device. * @return a non-null list of recording configurations. An empty list indicates there is * no recording active when queried. + * @see AudioRecordingConfiguration */ public @NonNull List getActiveRecordingConfigurations() { final IAudioService service = getService(); @@ -3287,7 +3289,10 @@ public class AudioManager { /** * Used as a key for {@link #getProperty} to request the native or optimal output sample rate - * for this device's primary output stream, in decimal Hz. + * for this device's low latency output stream, in decimal Hz. Latency-sensitive apps + * should use this value as a default, and offer the user the option to override it. + * The low latency output stream is typically either the device's primary output stream, + * or another output stream with smaller buffers. */ // FIXME Deprecate public static final String PROPERTY_OUTPUT_SAMPLE_RATE = @@ -3295,7 +3300,10 @@ public class AudioManager { /** * Used as a key for {@link #getProperty} to request the native or optimal output buffer size - * for this device's primary output stream, in decimal PCM frames. + * for this device's low latency output stream, in decimal PCM frames. Latency-sensitive apps + * should use this value as a minimum, and offer the user the option to override it. + * The low latency output stream is typically either the device's primary output stream, + * or another output stream with smaller buffers. */ // FIXME Deprecate public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java index 593516639e29af75d599b99082f88b09d23303de..50dbd035b84da2a2bebbeb4916361ea215d2e3c0 100644 --- a/media/java/android/media/AudioRecordingConfiguration.java +++ b/media/java/android/media/AudioRecordingConfiguration.java @@ -28,8 +28,18 @@ import java.util.Objects; /** * The AudioRecordingConfiguration class collects the information describing an audio recording - * session. This information is returned through the - * {@link AudioManager#getActiveRecordingConfigurations()} method. + * session. + *

        Direct polling (see {@link AudioManager#getActiveRecordingConfigurations()}) or callback + * (see {@link AudioManager#registerAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback, android.os.Handler)} + * methods are ways to receive information about the current recording configuration of the device. + *

        An audio recording configuration contains information about the recording format as used by + * the application ({@link #getClientFormat()}, as well as the recording format actually used by + * the device ({@link #getFormat()}). The two recording formats may, for instance, be at different + * sampling rates due to hardware limitations (e.g. application recording at 44.1kHz whereas the + * device always records at 48kHz, and the Android framework resamples for the application). + *

        The configuration also contains the use case for which audio is recorded + * ({@link #getClientAudioSource()}), enabling the ability to distinguish between different + * activities such as ongoing voice recognition or camcorder recording. * */ public final class AudioRecordingConfiguration implements Parcelable { @@ -47,12 +57,12 @@ public final class AudioRecordingConfiguration implements Parcelable { /** * @hide */ - public AudioRecordingConfiguration(int session, int source, AudioFormat devFormat, - AudioFormat clientFormat, int patchHandle) { + public AudioRecordingConfiguration(int session, int source, AudioFormat clientFormat, + AudioFormat devFormat, int patchHandle) { mSessionId = session; mClientSource = source; - mDeviceFormat = devFormat; mClientFormat = clientFormat; + mDeviceFormat = devFormat; mPatchHandle = patchHandle; } @@ -198,4 +208,4 @@ public final class AudioRecordingConfiguration implements Parcelable { && (mClientFormat.equals(that.mClientFormat)) && (mDeviceFormat.equals(that.mDeviceFormat))); } -} \ No newline at end of file +} diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index d808c22d5cd0298099a9de616f1ce7f58d14eb53..160751db3ac2b85513d22a9dd2e8cd427f552918 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -679,14 +679,14 @@ public class ExifInterface { if (value instanceof long[]) { long[] array = (long[]) value; if (array.length == 1) { - return (double) array[0]; + return array[0]; } throw new NumberFormatException("There are more than one component"); } if (value instanceof int[]) { int[] array = (int[]) value; if (array.length == 1) { - return (double) array[0]; + return array[0]; } throw new NumberFormatException("There are more than one component"); } @@ -1083,6 +1083,7 @@ public class ExifInterface { private int mThumbnailOffset; private int mThumbnailLength; private byte[] mThumbnailBytes; + private boolean mIsSupportedFile; // Pattern to check non zero timestamp private static final Pattern sNonZeroTimePattern = Pattern.compile(".*[1-9].*"); @@ -1472,9 +1473,11 @@ public class ExifInterface { // Process JPEG input stream getJpegAttributes(in); + mIsSupportedFile = true; } catch (IOException e) { // Ignore exceptions in order to keep the compatibility with the old versions of // ExifInterface. + mIsSupportedFile = false; Log.w(TAG, "Invalid image: ExifInterface got an unsupported image format file" + "(ExifInterface supports JPEG and some RAW image formats only) " + "or a corrupted JPEG file to ExifInterface.", e); @@ -1551,14 +1554,16 @@ public class ExifInterface { * copying all the data from one file to another and deleting the old file and renaming the * other. It's best to use {@link #setAttribute(String,String)} to set all attributes to write * and make a single call rather than multiple calls for each attribute. + *

        + * This method is only supported for JPEG files. + *

        */ public void saveAttributes() throws IOException { - if (mIsRaw) { - throw new UnsupportedOperationException( - "ExifInterface does not support saving attributes on RAW formats."); + if (!mIsSupportedFile || mIsRaw) { + throw new IOException("ExifInterface only supports saving attributes on JPEG formats."); } if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) { - throw new UnsupportedOperationException( + throw new IOException( "ExifInterface does not support saving attributes for the current input."); } @@ -2359,7 +2364,7 @@ public class ExifInterface { for (int i = 0; i < EXIF_TAGS.length; ++i) { int sum = 0; for (Map.Entry entry : (Set) mAttributes[i].entrySet()) { - final ExifAttribute exifAttribute = (ExifAttribute) ((Map.Entry) entry).getValue(); + final ExifAttribute exifAttribute = (ExifAttribute) entry.getValue(); final int size = exifAttribute.size(); if (size > 4) { sum += size; diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index ec2d4bc9170fa78a62396eded2fd05128ce2d17a..ed718493bd7899efcb8ad889a67430e9dcf44623 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -241,6 +241,10 @@ public class ImageReader implements AutoCloseable { * same {@link Surface} can be reused with a different API once the first source is * disconnected from the {@link Surface}.

        * + *

        Please note that holding on to the Surface object returned by this method is not enough + * to keep its parent ImageReader from being reclaimed. In that sense, a Surface acts like a + * {@link java.lang.ref.WeakReference weak reference} to the ImageReader that provides it.

        + * * @return A {@link Surface} to use for a drawing target for various APIs. */ public Surface getSurface() { @@ -512,11 +516,36 @@ public class ImageReader implements AutoCloseable { mAcquiredImages.clear(); nativeClose(); + + if (mEstimatedNativeAllocBytes > 0) { + VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes); + mEstimatedNativeAllocBytes = 0; + } } + } - if (mEstimatedNativeAllocBytes > 0) { - VMRuntime.getRuntime().registerNativeFree(mEstimatedNativeAllocBytes); - mEstimatedNativeAllocBytes = 0; + /** + * Discard any free buffers owned by this ImageReader. + * + *

        + * Generally, the ImageReader caches buffers for reuse once they have been + * allocated, for best performance. However, sometimes it may be important to + * release all the cached, unused buffers to save on memory. + *

        + *

        + * Calling this method will discard all free cached buffers. This does not include any buffers + * associated with Images acquired from the ImageReader, any filled buffers waiting to be + * acquired, and any buffers currently in use by the source rendering buffers into the + * ImageReader's Surface. + *

        + * The ImageReader continues to be usable after this call, but may need to reallocate buffers + * when more buffers are needed for rendering. + *

        + * @hide + */ + public void discardFreeBuffers() { + synchronized (mCloseLock) { + nativeDiscardFreeBuffers(); } } @@ -872,6 +901,7 @@ public class ImageReader implements AutoCloseable { private synchronized native void nativeReleaseImage(Image i); private synchronized native Surface nativeGetSurface(); private synchronized native int nativeDetachImage(Image i); + private synchronized native void nativeDiscardFreeBuffers(); /** * @return A return code {@code ACQUIRE_*} diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 71d1aaafe45f37b3a91ce30ce81127d6b6278a18..264944f43baea2b3d2135f949d880dd9585a039b 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -133,9 +133,10 @@ import java.util.Map;

        Note that on some devices the slice-height is advertised as 0. This could mean either that the slice-height is the same as the frame height, or that the slice-height is the frame height - aligned to some value (usually a power of 2). Unfortunately, there is no way to tell the actual - slice height in this case. Furthermore, the vertical stride of the {@code U} plane in planar - formats is also not specified or defined, though usually it is half of the slice height. + aligned to some value (usually a power of 2). Unfortunately, there is no standard and simple way + to tell the actual slice height in this case. Furthermore, the vertical stride of the {@code U} + plane in planar formats is also not specified or defined, though usually it is half of the slice + height.

        The {@link MediaFormat#KEY_WIDTH} and {@link MediaFormat#KEY_HEIGHT} keys specify the size of the video frames; however, for most encondings the video (picture) only occupies a portion of the @@ -297,8 +298,8 @@ import java.util.Map; Codec-specific data in the format is automatically submitted to the codec upon {@link #start}; you MUST NOT submit this data explicitly. If the format did not contain codec specific data, you can choose to submit it using the specified number of buffers in the correct - order, according to the format requirements. Alternately, you can concatenate all codec-specific - data and submit it as a single codec-config buffer. + order, according to the format requirements. In case of H.264 AVC, you can also concatenate all + codec-specific data and submit it as a single codec-config buffer.

        Android uses the following codec-specific data buffers. These are also required to be set in the track format for proper {@link MediaMuxer} track configuration. Each parameter set and the @@ -355,6 +356,13 @@ import java.util.Map; Not Used Not Used + + VP9 + VP9 CodecPrivate Data + (optional) + Not Used + Not Used + @@ -606,6 +614,33 @@ import java.util.Map; Also since {@link android.os.Build.VERSION_CODES#M}, you can change the output Surface dynamically using {@link #setOutputSurface setOutputSurface}. +

        Transformations When Rendering onto Surface

        + + If the codec is configured into Surface mode, any crop rectangle, {@linkplain + MediaFormat#KEY_ROTATION rotation} and {@linkplain #setVideoScalingMode video scaling + mode} will be automatically applied with one exception: +

        + Prior to the {@link android.os.Build.VERSION_CODES#M} release, software decoders may not + have applied the rotation when being rendered onto a Surface. Unfortunately, there is no standard + and simple way to identify software decoders, or if they apply the rotation other than by trying + it out. +

        + There are also some caveats. +

        + Note that the pixel aspect ratio is not considered when displaying the output onto the + Surface. This means that if you are using {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT} mode, you + must position the output Surface so that it has the proper final display aspect ratio. Conversely, + you can only use {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING} mode for content with + square pixels (pixel aspect ratio or 1:1). +

        + Note also that as of {@link android.os.Build.VERSION_CODES#N} release, {@link + #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING} mode may not work correctly for videos rotated + by 90 or 270 degrees. +

        + When setting the video scaling mode, note that it must be reset after each time the output + buffers change. Since the {@link #INFO_OUTPUT_BUFFERS_CHANGED} event is deprecated, you can + do this after each time the output format changes. +

        Using an Input Surface

        When using an input Surface, there are no accessible input buffers, as buffers are automatically @@ -3055,7 +3090,13 @@ final public class MediaCodec { /** * The content is scaled, maintaining its aspect ratio, the whole - * surface area is used, content may be cropped + * surface area is used, content may be cropped. + *

        + * This mode is only suitable for content with 1:1 pixel aspect ratio as you cannot + * configure the pixel aspect ratio for a {@link Surface}. + *

        + * As of {@link android.os.Build.VERSION_CODES#N} release, this mode may not work if + * the video is {@linkplain MediaFormat#KEY_ROTATION rotated} by 90 or 270 degrees. */ public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; @@ -3070,10 +3111,15 @@ final public class MediaCodec { /** * If a surface has been specified in a previous call to {@link #configure} * specifies the scaling mode to use. The default is "scale to fit". - *

        The scaling mode may be reset to the default each time an + *

        + * The scaling mode may be reset to the default each time an * {@link #INFO_OUTPUT_BUFFERS_CHANGED} event is received from the codec; therefore, the client * must call this method after every buffer change event (and before the first output buffer is - * released for rendering) to ensure consistent scaling mode.

        + * released for rendering) to ensure consistent scaling mode. + *

        + * Since the {@link #INFO_OUTPUT_BUFFERS_CHANGED} event is deprecated, this can also be done + * after each {@link #INFO_OUTPUT_FORMAT_CHANGED} event. + * * @throws IllegalArgumentException if mode is not recognized. * @throws IllegalStateException if in the Released state. */ diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 07d1f7542b26315d958a53bf311bc9b5dc18c6e5..0bfeaed36282fa87661c89ee1554edf8ba46c7da 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -541,6 +541,72 @@ public final class MediaCodecInfo { * frame rate}. Use * format.setString(MediaFormat.KEY_FRAME_RATE, null) * to clear any existing frame rate setting in the format. + *

        + * + * The following table summarizes the format keys considered by this method. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        OS Version(s){@code MediaFormat} keys considered for + *
        Audio CodecsVideo CodecsEncoders
        {@link android.os.Build.VERSION_CODES#LOLLIPOP} + * {@link MediaFormat#KEY_MIME}*,
        + * {@link MediaFormat#KEY_SAMPLE_RATE},
        + * {@link MediaFormat#KEY_CHANNEL_COUNT},
        {@link MediaFormat#KEY_MIME}*,
        + * {@link CodecCapabilities#FEATURE_AdaptivePlayback}D,
        + * {@link CodecCapabilities#FEATURE_SecurePlayback}D,
        + * {@link CodecCapabilities#FEATURE_TunneledPlayback}D,
        + * {@link MediaFormat#KEY_WIDTH},
        + * {@link MediaFormat#KEY_HEIGHT},
        + * no {@code KEY_FRAME_RATE}
        {@link MediaFormat#KEY_BITRATE_MODE},
        + * {@link MediaFormat#KEY_PROFILE} + * (and/or {@link MediaFormat#KEY_AAC_PROFILE}~),
        + * + * {@link MediaFormat#KEY_COMPLEXITY} + * (and/or {@link MediaFormat#KEY_FLAC_COMPRESSION_LEVEL}~)
        {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} + * as above, plus
        + * {@link MediaFormat#KEY_FRAME_RATE}
        {@link android.os.Build.VERSION_CODES#M} + *
        {@link android.os.Build.VERSION_CODES#N} + * as above, plus
        + * {@link MediaFormat#KEY_PROFILE},
        + * + * {@link MediaFormat#KEY_BIT_RATE}
        as above, plus
        + * {@link MediaFormat#KEY_PROFILE},
        + * {@link MediaFormat#KEY_LEVEL}+,
        + * + * {@link MediaFormat#KEY_BIT_RATE},
        + * {@link CodecCapabilities#FEATURE_IntraRefresh}E
        + *

        Notes:
        + * *: must be specified; otherwise, method returns {@code false}.
        + * +: method does not verify that the format parameters are supported + * by the specified level.
        + * D: decoders only
        + * E: encoders only
        + * ~: if both keys are provided values must match + *

        * * @param format media format with optional feature directives. * @throws IllegalArgumentException if format is not a valid media format. diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java index 42ce5110f134be51f167ca8255c6fcdcc307d3f2..3cb4cbe99a4b200c05619f6ca44b2ebc9ad1d046 100644 --- a/media/java/android/media/MediaCodecList.java +++ b/media/java/android/media/MediaCodecList.java @@ -201,6 +201,9 @@ final public class MediaCodecList { * format.setString(MediaFormat.KEY_FRAME_RATE, null) * to clear any existing frame rate setting in the format. * + * @see MediaCodecList.CodecCapabilities.isFormatSupported for format keys + * considered per android versions when evaluating suitable codecs. + * * @param format A decoder media format with optional feature directives. * @throws IllegalArgumentException if format is not a valid media format. * @throws NullPointerException if format is null. @@ -222,6 +225,9 @@ final public class MediaCodecList { * format.setString(MediaFormat.KEY_FRAME_RATE, null) * to clear any existing frame rate setting in the format. * + * @see MediaCodecList.CodecCapabilities.isFormatSupported for format keys + * considered per android versions when evaluating suitable codecs. + * * @param format An encoder media format with optional feature directives. * @throws IllegalArgumentException if format is not a valid media format. * @throws NullPointerException if format is null. diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java index 24a400e481899d586cd8354e864f3d530cb95fe9..c8aedd09d60c81da215c4736437c52fa09825f20 100644 --- a/media/java/android/media/MediaExtractor.java +++ b/media/java/android/media/MediaExtractor.java @@ -333,7 +333,113 @@ final public class MediaExtractor { /** * Get the track format at the specified index. + * * More detail on the representation can be found at {@link android.media.MediaCodec} + *

        + * The following table summarizes support for format keys across android releases: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        OS Version(s){@code MediaFormat} keys used for + *
        All TracksAudio TracksVideo Tracks
        {@link android.os.Build.VERSION_CODES#JELLY_BEAN}{@link MediaFormat#KEY_MIME},
        + * {@link MediaFormat#KEY_DURATION},
        + * {@link MediaFormat#KEY_MAX_INPUT_SIZE}
        {@link MediaFormat#KEY_SAMPLE_RATE},
        + * {@link MediaFormat#KEY_CHANNEL_COUNT},
        + * {@link MediaFormat#KEY_CHANNEL_MASK},
        + * gapless playback information.mp3, .mp4,
        + * {@link MediaFormat#KEY_IS_ADTS}AAC if streaming,
        + * codec-specific dataAAC, Vorbis
        {@link MediaFormat#KEY_WIDTH},
        + * {@link MediaFormat#KEY_HEIGHT},
        + * codec-specific dataAVC, MPEG4
        {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
        {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}as above, plus
        + * Pixel aspect ratio informationAVC, *
        {@link android.os.Build.VERSION_CODES#KITKAT}
        {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}
        {@link android.os.Build.VERSION_CODES#LOLLIPOP}as above, plus
        + * {@link MediaFormat#KEY_BIT_RATE}AAC,
        + * codec-specific dataOpus
        as above, plus
        + * {@link MediaFormat#KEY_ROTATION}.mp4,
        + * {@link MediaFormat#KEY_BIT_RATE}MPEG4,
        + * codec-specific dataHEVC
        {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}
        {@link android.os.Build.VERSION_CODES#M}as above, plus
        + * gapless playback informationOpus
        as above, plus
        + * {@link MediaFormat#KEY_FRAME_RATE} (integer)
        {@link android.os.Build.VERSION_CODES#N}as above, plus
        + * {@link MediaFormat#KEY_TRACK_ID},
        + * + * {@link MediaFormat#KEY_BIT_RATE}#, .mp4
        as above, plus
        + * {@link MediaFormat#KEY_PCM_ENCODING},
        + * {@link MediaFormat#KEY_PROFILE}AAC
        as above, plus
        + * {@link MediaFormat#KEY_HDR_STATIC_INFO}#, .webm,
        + * {@link MediaFormat#KEY_COLOR_STANDARD}#,
        + * {@link MediaFormat#KEY_COLOR_TRANSFER}#,
        + * {@link MediaFormat#KEY_COLOR_RANGE}#,
        + * {@link MediaFormat#KEY_PROFILE}MPEG2, H.263, MPEG4, AVC, HEVC, VP9,
        + * {@link MediaFormat#KEY_LEVEL}H.263, MPEG4, AVC, HEVC, VP9,
        + * codec-specific dataVP9
        + *

        Notes:
        + * #: container-specified value only.
        + * .mp4, .webm…: for listed containers
        + * MPEG4, AAC…: for listed codecs + *

        + *

        Note that that level information contained in the container many times + * does not match the level of the actual bitstream. You may want to clear the level using + * {@code MediaFormat.setString(KEY_LEVEL, null)} before using the track format to find a + * decoder that can play back a particular track. + *

        + *

        *Pixel (sample) aspect ratio is returned in the following + * keys. The display width can be calculated for example as: + *

        + * display-width = display-height * crop-width / crop-height * sar-width / sar-height + *

        Format KeyValue TypeDescription
        {@code "sar-width"}IntegerPixel aspect ratio width
        {@code "sar-height"}IntegerPixel aspect ratio height
        + * */ @NonNull public MediaFormat getTrackFormat(int index) { @@ -390,6 +496,11 @@ final public class MediaExtractor { /** * Advance to the next sample. Returns false if no more sample data * is available (end of stream). + * + * When extracting a local file, the behaviors of {@link #advance} and + * {@link #readSampleData} are undefined in presence of concurrent + * writes to the same local file; more specifically, end of stream + * could be signalled earlier than expected. */ public native boolean advance(); diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index f7becf54d340811c575bb983045917b2b532e035..da490b9f7497688c842dd4fafa6b429879236999 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -69,8 +69,9 @@ public class MediaFile { // More video file types public static final int FILE_TYPE_MP2PS = 200; + public static final int FILE_TYPE_QT = 201; private static final int FIRST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS; - private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS; + private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_QT; // Image file types public static final int FILE_TYPE_JPEG = 31; @@ -211,6 +212,8 @@ public class MediaFile { addFileType("MPG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG); addFileType("MP4", FILE_TYPE_MP4, "video/mp4", MtpConstants.FORMAT_MPEG); addFileType("M4V", FILE_TYPE_M4V, "video/mp4", MtpConstants.FORMAT_MPEG); + addFileType("MOV", FILE_TYPE_QT, "video/quicktime", MtpConstants.FORMAT_MPEG); + addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp", MtpConstants.FORMAT_3GP_CONTAINER); addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp", MtpConstants.FORMAT_3GP_CONTAINER); addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2", MtpConstants.FORMAT_3GP_CONTAINER); diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index a2fd0aa8952f8b7da5699a04406b52e6b44076ec..d74aa81a6bd2bc03e5c43952fbe3d3712138da20 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -49,12 +49,18 @@ import java.util.Map; * {@link #KEY_FRAME_RATE}Integer or Floatrequired for encoders, * optional for decoders * {@link #KEY_CAPTURE_RATE}Integer - * {@link #KEY_I_FRAME_INTERVAL}Integerencoder-only + * {@link #KEY_I_FRAME_INTERVAL}Integer (or Float)encoder-only, + * time-interval between key frames. + * Float support added in {@link android.os.Build.VERSION_CODES#N_MR1} * {@link #KEY_INTRA_REFRESH_PERIOD}Integerencoder-only, optional * {@link #KEY_MAX_WIDTH}Integerdecoder-only, optional, max-resolution width * {@link #KEY_MAX_HEIGHT}Integerdecoder-only, optional, max-resolution height - * {@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}Longvideo encoder in surface-mode only - * {@link #KEY_PUSH_BLANK_BUFFERS_ON_STOP}Integer(1)video decoder rendering to a surface only + * {@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}Longencoder in surface-mode + * only, optional + * {@link #KEY_PUSH_BLANK_BUFFERS_ON_STOP}Integer(1)decoder rendering + * to a surface only, optional + * {@link #KEY_TEMPORAL_LAYERING}Stringencoder only, optional, + * temporal-layering schema * * Specify both {@link #KEY_MAX_WIDTH} and {@link #KEY_MAX_HEIGHT} to enable * adaptive playback (seamless resolution change) for a video decoder that @@ -258,9 +264,20 @@ public final class MediaFormat { public static final String KEY_CAPTURE_RATE = "capture-rate"; /** - * A key describing the frequency of I frames expressed in secs - * between I frames. - * The associated value is an integer. + * A key describing the frequency of key frames expressed in seconds between key frames. + *

        + * This key is used by video encoders. + * A negative value means no key frames are requested after the first frame. + * A zero value means a stream containing all key frames is requested. + *

        + * Most video encoders will convert this value of the number of non-key-frames between + * key-frames, using the {@linkplain #KEY_FRAME_RATE frame rate} information; therefore, + * if the actual frame rate differs (e.g. input frames are dropped or the frame rate + * changes), the time interval between key frames will not be the + * configured value. + *

        + * The associated value is an integer (or float since + * {@link android.os.Build.VERSION_CODES#N_MR1}). */ public static final String KEY_I_FRAME_INTERVAL = "i-frame-interval"; @@ -280,12 +297,18 @@ public final class MediaFormat { /** * A key describing the temporal layering schema. This is an optional parameter - * that applies only to video encoders. Use {@link MediaCodec#getInputFormat} + * that applies only to video encoders. Use {@link MediaCodec#getOutputFormat} * after {@link MediaCodec#configure configure} to query if the encoder supports - * the desired schema. Supported values are {@code webrtc.vp8.1-layer}, - * {@code webrtc.vp8.2-layer}, {@code webrtc.vp8.3-layer}, and {@code none}. - * If the encoder does not support temporal layering, the input format will - * not have an entry with this key. + * the desired schema. Supported values are {@code webrtc.vp8.N-layer}, + * {@code android.generic.N}, {@code android.generic.N+M} and {@code none}, where + * {@code N} denotes the total number of non-bidirectional layers (which must be at least 1) + * and {@code M} denotes the total number of bidirectional layers (which must be non-negative). + *

        {@code android.generic.*} schemas have been added in {@link + * android.os.Build.VERSION_CODES#N_MR1}. + *

        + * The encoder may support fewer temporal layers, in which case the output format + * will contain the configured schema. If the encoder does not support temporal + * layering, the output format will not have an entry with this key. * The associated value is a string. */ public static final String KEY_TEMPORAL_LAYERING = "ts-schema"; @@ -554,7 +577,9 @@ public final class MediaFormat { /** * A key describing the desired clockwise rotation on an output surface. * This key is only used when the codec is configured using an output surface. - * The associated value is an integer, representing degrees. + * The associated value is an integer, representing degrees. Supported values + * are 0, 90, 180 or 270. This is an optional field; if not specified, rotation + * defaults to 0. * * @see MediaCodecInfo.CodecCapabilities#profileLevels */ diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 92adfd9c1b9daa6056da9f58965fb9d1cbcb6660..949acc0e1758439dc1615a8037c6ce48a83dd64f 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -1641,7 +1641,8 @@ public class MediaPlayer extends PlayerBase * (i.e. reaches the end of the stream). * The media framework will attempt to transition from this player to * the next as seamlessly as possible. The next player can be set at - * any time before completion. The next player must be prepared by the + * any time before completion, but shall be after setDataSource has been + * called successfully. The next player must be prepared by the * app, and the application should not call start() on it. * The next MediaPlayer must be different from 'this'. An exception * will be thrown if next == this. @@ -3494,7 +3495,7 @@ public class MediaPlayer extends PlayerBase * @param extra an extra code, specific to the info. Typically * implementation dependent. * @return True if the method handled the info, false if it didn't. - * Returning false, or not having an OnErrorListener at all, will + * Returning false, or not having an OnInfoListener at all, will * cause the info to be discarded. */ boolean onInfo(MediaPlayer mp, int what, int extra); diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 73485afcecffd0034eeaee6c0cdb76a5b22b0f3a..94e894f9ce9d3a47d8e26c72698ac9defdac0916 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -745,6 +745,27 @@ public class MediaRecorder setParameter("video-param-encoding-bitrate=" + bitRate); } + /** + * Sets the video encoding profile for recording. Call this method before prepare(). + * Prepare() may perform additional checks on the parameter to make sure whether the + * specified profile and level are applicable, and sometimes the passed profile or + * level will be discarded due to codec capablity or to ensure the video recording + * can proceed smoothly based on the capabilities of the platform. + * @hide + * @param profile declared in {@link MediaCodecInfo.CodecProfileLevel}. + * @param level declared in {@link MediaCodecInfo.CodecProfileLevel}. + */ + public void setVideoEncodingProfileLevel(int profile, int level) { + if (profile <= 0) { + throw new IllegalArgumentException("Video encoding profile is not positive"); + } + if (level <= 0) { + throw new IllegalArgumentException("Video encoding level is not positive"); + } + setParameter("video-param-encoder-profile=" + profile); + setParameter("video-param-encoder-level=" + level); + } + /** * Currently not implemented. It does nothing. * @deprecated Time lapse mode video recording using camera still image capture diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index 101facd4909bba0f2a2ded64868a8f8c9ea219f2..79195d6de29fd6489b1f976e1a3ebef012452972 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -220,8 +220,7 @@ public class MediaRouter { if (mBluetoothA2dpRoute != null) { final boolean a2dpEnabled = isBluetoothA2dpOn(); - if (mainType != AudioRoutesInfo.MAIN_SPEAKER && - mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) { + if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) { selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false); } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) && a2dpEnabled) { diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 8b6c38b374f90f7d61f9636acfb6b7bef1238238..ddfa0258ab9a4243e0027e02b1f3904a4818eb41 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -21,12 +21,14 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; +import android.content.SharedPreferences; import android.database.Cursor; import android.database.SQLException; import android.drm.DrmManagerClient; import android.graphics.BitmapFactory; import android.mtp.MtpConstants; import android.net.Uri; +import android.os.Build; import android.os.Environment; import android.os.RemoteException; import android.os.SystemProperties; @@ -60,11 +62,14 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.text.SimpleDateFormat; +import java.text.ParseException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; +import java.util.TimeZone; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -150,6 +155,11 @@ public class MediaScanner implements AutoCloseable { private static final String MUSIC_DIR = "/music/"; private static final String PODCAST_DIR = "/podcasts/"; + public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild"; + public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint"; + private static final String SYSTEM_SOUNDS_DIR = "/system/media/audio"; + private static String sLastInternalScanFingerprint; + private static final String[] ID3_GENRES = { // ID3v1 Genres "Blues", @@ -399,6 +409,13 @@ public class MediaScanner implements AutoCloseable { mMediaProvider = mContext.getContentResolver() .acquireContentProviderClient(MediaStore.AUTHORITY); + if (sLastInternalScanFingerprint == null) { + final SharedPreferences scanSettings = + mContext.getSharedPreferences(SCANNED_BUILD_PREFS_NAME, Context.MODE_PRIVATE); + sLastInternalScanFingerprint = + scanSettings.getString(LAST_INTERNAL_SCAN_FINGERPRINT, new String()); + } + mAudioUri = Audio.Media.getContentUri(volumeName); mVideoUri = Video.Media.getContentUri(volumeName); mImagesUri = Images.Media.getContentUri(volumeName); @@ -451,6 +468,8 @@ public class MediaScanner implements AutoCloseable { private class MyMediaScannerClient implements MediaScannerClient { + private final SimpleDateFormat mDateFormatter; + private String mArtist; private String mAlbumArtist; // use this if mArtist is missing private String mAlbum; @@ -463,6 +482,7 @@ public class MediaScanner implements AutoCloseable { private int mYear; private int mDuration; private String mPath; + private long mDate; private long mLastModified; private long mFileSize; private String mWriter; @@ -472,6 +492,11 @@ public class MediaScanner implements AutoCloseable { private int mWidth; private int mHeight; + public MyMediaScannerClient() { + mDateFormatter = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + mDateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); + } + public FileEntry beginFile(String path, String mimeType, long lastModified, long fileSize, boolean isDirectory, boolean noMedia) { mMimeType = mimeType; @@ -537,6 +562,7 @@ public class MediaScanner implements AutoCloseable { mYear = 0; mDuration = 0; mPath = path; + mDate = 0; mLastModified = lastModified; mWriter = null; mCompilation = 0; @@ -573,16 +599,24 @@ public class MediaScanner implements AutoCloseable { entry.mRowId = 0; } - if (entry.mPath != null && - ((!mDefaultNotificationSet && + if (entry.mPath != null) { + if (((!mDefaultNotificationSet && doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename)) || (!mDefaultRingtoneSet && doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename)) || (!mDefaultAlarmSet && doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)))) { - Log.w(TAG, "forcing rescan of " + entry.mPath + - "since ringtone setting didn't finish"); - scanAlways = true; + Log.w(TAG, "forcing rescan of " + entry.mPath + + "since ringtone setting didn't finish"); + scanAlways = true; + } else if (isSystemSoundWithMetadata(entry.mPath) + && !Build.FINGERPRINT.equals(sLastInternalScanFingerprint)) { + // file is located on the system partition where the date cannot be trusted: + // rescan if the build fingerprint has changed since the last scan. + Log.i(TAG, "forcing rescan of " + entry.mPath + + " since build fingerprint changed"); + scanAlways = true; + } } // rescan for metadata if file was modified since last scan @@ -627,6 +661,14 @@ public class MediaScanner implements AutoCloseable { return result; } + private long parseDate(String date) { + try { + return mDateFormatter.parse(date).getTime(); + } catch (ParseException e) { + return 0; + } + } + private int parseSubstring(String s, int start, int defaultValue) { int length = s.length(); if (start == length) return defaultValue; @@ -684,6 +726,8 @@ public class MediaScanner implements AutoCloseable { mCompilation = parseSubstring(value, 0, 0); } else if (name.equalsIgnoreCase("isdrm")) { mIsDrm = (parseSubstring(value, 0, 0) == 1); + } else if (name.equalsIgnoreCase("date")) { + mDate = parseDate(value); } else if (name.equalsIgnoreCase("width")) { mWidth = parseSubstring(value, 0, 0); } else if (name.equalsIgnoreCase("height")) { @@ -830,6 +874,9 @@ public class MediaScanner implements AutoCloseable { if (resolution != null) { map.put(Video.Media.RESOLUTION, resolution); } + if (mDate > 0) { + map.put(Video.Media.DATE_TAKEN, mDate); + } } else if (MediaFile.isImageFileType(mFileType)) { // FIXME - add DESCRIPTION } else if (MediaFile.isAudioFileType(mFileType)) { @@ -1103,6 +1150,15 @@ public class MediaScanner implements AutoCloseable { }; // end of anonymous MediaScannerClient instance + private static boolean isSystemSoundWithMetadata(String path) { + if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR) + || path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR) + || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)) { + return true; + } + return false; + } + private String settingSetIndicatorName(String base) { return base + "_set"; } @@ -1227,16 +1283,6 @@ public class MediaScanner implements AutoCloseable { } } - private boolean inScanDirectory(String path, String[] directories) { - for (int i = 0; i < directories.length; i++) { - String directory = directories[i]; - if (path.startsWith(directory)) { - return true; - } - } - return false; - } - private void pruneDeadThumbnailFiles() { HashSet existingFiles = new HashSet(); String directory = "/sdcard/DCIM/.thumbnails"; diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java index 0f7dc9a819c7f03ffc5bf22e5f0d36251516d451..b262d97cfb8e10503c1994949ca80ddd5b2ba032 100644 --- a/media/java/android/media/PlayerBase.java +++ b/media/java/android/media/PlayerBase.java @@ -181,10 +181,15 @@ public abstract class PlayerBase { * @return */ boolean isRestricted_sync() { + // check app ops + if (mHasAppOpsPlayAudio) { + return false; + } + // check bypass flag if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { return false; } - return !mHasAppOpsPlayAudio; + return true; } // Abstract methods a subclass needs to implement diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java index c2bcd930dd2944cb2e321e1c50ad0e6a188346aa..6658e88184b06650b63acded775771958519f017 100644 --- a/media/java/android/media/Ringtone.java +++ b/media/java/android/media/Ringtone.java @@ -368,6 +368,7 @@ public class Ringtone { private void destroyLocalPlayer() { if (mLocalPlayer != null) { + mLocalPlayer.setOnCompletionListener(null); mLocalPlayer.reset(); mLocalPlayer.release(); mLocalPlayer = null; @@ -464,11 +465,14 @@ public class Ringtone { } class MyOnCompletionListener implements MediaPlayer.OnCompletionListener { - public void onCompletion(MediaPlayer mp) - { + @Override + public void onCompletion(MediaPlayer mp) { synchronized (sActiveRingtones) { sActiveRingtones.remove(Ringtone.this); } + if (mLocalPlayer != null) { + mLocalPlayer.setOnCompletionListener(null); + } } } } diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java index 3164930aa7492f0d647547e01b54f90bc24ece5a..9fafda48d65212ab102e9568321d14d220458a37 100644 --- a/media/java/android/media/SoundPool.java +++ b/media/java/android/media/SoundPool.java @@ -133,6 +133,8 @@ public class SoundPool { private final IAppOpsService mAppOps; private final IAppOpsCallback mAppOpsCallback; + private static IAudioService sService; + /** * Constructor. Constructs a SoundPool object with the following * characteristics: @@ -492,11 +494,42 @@ public class SoundPool { } } + private static IAudioService getService() + { + if (sService != null) { + return sService; + } + IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); + sService = IAudioService.Stub.asInterface(b); + return sService; + } + private boolean isRestricted() { + // check app ops + if (mHasAppOpsPlayAudio) { + return false; + } + // check bypass flag if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { return false; } - return !mHasAppOpsPlayAudio; + // check force audibility flag and camera restriction + if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) { +// FIXME: should also check usage when set properly by camera app +// && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) + boolean cameraSoundForced = false; + try { + cameraSoundForced = getService().isCameraSoundForced(); + } catch (RemoteException e) { + Log.e(TAG, "Cannot access AudioService in isRestricted()"); + } catch (NullPointerException e) { + Log.e(TAG, "Null AudioService in isRestricted()"); + } + if (cameraSoundForced) { + return false; + } + } + return true; } private void updateAppOpsPlayAudio() { diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java index b94a7e62b6a338cf25ebdd07a8a40ea7c2761a41..7dbca3b9d7e178b9667c6fd77f3c4ffcc0aeb182 100644 --- a/media/java/android/media/audiofx/AudioEffect.java +++ b/media/java/android/media/audiofx/AudioEffect.java @@ -53,7 +53,7 @@ import java.util.UUID; * than the priority used by the current effect engine owner, the control will be transfered to the * new object. Otherwise control will remain with the previous object. In this case, the new * application will be notified of changes in effect engine state or control ownership by the - * appropiate listener. + * appropriate listener. */ public class AudioEffect { diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java index df0961bd17d43c6828c8328b11032024adc40f58..d5296ae4203155f171972c37483ff4c0ca33df6e 100644 --- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java +++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java @@ -15,6 +15,7 @@ */ package android.media.soundtrigger; +import static android.hardware.soundtrigger.SoundTrigger.STATUS_OK; import android.annotation.IntDef; import android.annotation.NonNull; @@ -243,27 +244,29 @@ public final class SoundTriggerDetector { boolean allowMultipleTriggers = (recognitionFlags & RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS) != 0; + int status = STATUS_OK; try { - mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId), + status = mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId), mRecognitionCallback, new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers, null, null)); } catch (RemoteException e) { return false; } - return true; + return status == STATUS_OK; } /** * Stops recognition for the associated model. */ public boolean stopRecognition() { + int status = STATUS_OK; try { - mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId), + status = mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId), mRecognitionCallback); } catch (RemoteException e) { return false; } - return true; + return status == STATUS_OK; } /** diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java index 4082778986c62b0df081849e9a80077c5eb1ee02..e7ea1a5a12cffff3abde1e6afa5d419dcd55f330 100644 --- a/media/java/android/mtp/MtpDevice.java +++ b/media/java/android/mtp/MtpDevice.java @@ -18,11 +18,13 @@ package android.mtp; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; +import android.os.UserManager; import com.android.internal.util.Preconditions; import java.io.IOException; @@ -62,7 +64,17 @@ public final class MtpDevice { * @return true if the device was successfully opened. */ public boolean open(UsbDeviceConnection connection) { - boolean result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor()); + boolean result = false; + + Context context = connection.getContext(); + if (context != null) { + UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + + if (!userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) { + result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor()); + } + } + if (!result) { connection.close(); } diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp index c3993ae2018368bfacaa44438628232a077dd03f..724fc02271e302db1e994dd2871dc03ae0aaf2cd 100644 --- a/media/jni/android_media_ImageReader.cpp +++ b/media/jni/android_media_ImageReader.cpp @@ -611,6 +611,23 @@ static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) { return OK; } +static void ImageReader_discardFreeBuffers(JNIEnv* env, jobject thiz) { + ALOGV("%s:", __FUNCTION__); + JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); + if (ctx == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed"); + return; + } + + BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer(); + status_t res = bufferConsumer->discardFreeBuffers(); + if (res != OK) { + ALOGE("Buffer discard failed: %s (%d)", strerror(-res), res); + jniThrowRuntimeException(env, + "nativeDicardFreebuffers failed"); + } +} + static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz) { ALOGV("%s: ", __FUNCTION__); @@ -773,6 +790,7 @@ static const JNINativeMethod gImageReaderMethods[] = { {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup }, {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, {"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage }, + {"nativeDiscardFreeBuffers", "()V", (void*)ImageReader_discardFreeBuffers } }; static const JNINativeMethod gImageMethods[] = { diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp index d07942b5fd89497e560ba2abddae07e40ee67c3a..2ab7e39fad17b623be53e7b8c25ee927f6441cd3 100644 --- a/media/jni/android_media_MediaDataSource.cpp +++ b/media/jni/android_media_MediaDataSource.cpp @@ -26,6 +26,7 @@ #include "JNIHelp.h" #include +#include #include #include @@ -159,4 +160,8 @@ String8 JMediaDataSource::toString() { return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid()); } +sp JMediaDataSource::DrmInitialization(const char * /* mime */) { + return NULL; +} + } // namespace android diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h index 378baf433fedc4b00caf7aef317f0e4d99e7b706..39405d2db579c31d24b446a3670e5a47570750e1 100644 --- a/media/jni/android_media_MediaDataSource.h +++ b/media/jni/android_media_MediaDataSource.h @@ -47,6 +47,7 @@ public: virtual void close(); virtual uint32_t getFlags(); virtual String8 toString(); + virtual sp DrmInitialization(const char *mime); private: // Protect all member variables with mLock because this object will be diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp index 75a3b6fcd4690e04e41d297ce8d6b6f7540e00df..0645543d4a74af05fe93a52d1055c47226af6d30 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -435,14 +435,12 @@ setup_failure: // ---------------------------------------------------------------------------- static void android_media_visualizer_native_release(JNIEnv *env, jobject thiz) { - // ensure that lpVisualizer is deleted before lpJniStorage - { + { //limit scope so that lpVisualizer is deleted before JNI storage data. sp lpVisualizer = setVisualizer(env, thiz, 0); if (lpVisualizer == 0) { return; } } - // delete the JNI data VisualizerJniStorage* lpJniStorage = (VisualizerJniStorage *)env->GetLongField(thiz, fields.fidJniData); diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 38ed9321653d50c05025f5bf3d4ad5e2a6d59cf6..0f5dd3aa56678dbc3a325c46831ed4a91cbc6326 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -16,6 +16,13 @@ package android.opengl; +import android.content.Context; +import android.os.Trace; +import android.util.AttributeSet; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + import java.io.Writer; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -29,15 +36,6 @@ import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL; import javax.microedition.khronos.opengles.GL10; -import android.content.Context; -import android.content.pm.ConfigurationInfo; -import android.os.SystemProperties; -import android.os.Trace; -import android.util.AttributeSet; -import android.util.Log; -import android.view.SurfaceHolder; -import android.view.SurfaceView; - /** * An implementation of SurfaceView that uses the dedicated surface for * displaying OpenGL rendering. @@ -119,9 +117,9 @@ import android.view.SurfaceView; * {@link #setRenderMode}. The default is continuous rendering. *

        *

        Activity Life-cycle

        - * A GLSurfaceView must be notified when the activity is paused and resumed. GLSurfaceView clients - * are required to call {@link #onPause()} when the activity pauses and - * {@link #onResume()} when the activity resumes. These calls allow GLSurfaceView to + * A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients + * are required to call {@link #onPause()} when the activity stops and + * {@link #onResume()} when the activity starts. These calls allow GLSurfaceView to * pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate * the OpenGL display. *

        @@ -294,10 +292,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback * resumed. *

        * If set to true, then the EGL context may be preserved when the GLSurfaceView is paused. - * Whether the EGL context is actually preserved or not depends upon whether the - * Android device that the program is running on can support an arbitrary number of EGL - * contexts or not. Devices that can only support a limited number of EGL contexts must - * release the EGL context in order to allow multiple applications to share the GPU. + *

        + * Prior to API level 11, whether the EGL context is actually preserved or not + * depends upon whether the Android device can support an arbitrary number of + * EGL contexts or not. Devices that can only support a limited number of EGL + * contexts must release the EGL context in order to allow multiple applications + * to share the GPU. *

        * If set to false, the EGL context will be released when the GLSurfaceView is paused, * and recreated when the GLSurfaceView is resumed. @@ -554,9 +554,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback /** - * Inform the view that the activity is paused. The owner of this view must - * call this method when the activity is paused. Calling this method will - * pause the rendering thread. + * Pause the rendering thread, optionally tearing down the EGL context + * depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}. + * + * This method should be called when it is no longer desirable for the + * GLSurfaceView to continue rendering, such as in response to + * {@link android.app.Activity#onStop Activity.onStop}. + * * Must not be called before a renderer has been set. */ public void onPause() { @@ -564,10 +568,12 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } /** - * Inform the view that the activity is resumed. The owner of this view must - * call this method when the activity is resumed. Calling this method will - * recreate the OpenGL display and resume the rendering - * thread. + * Resumes the rendering thread, re-creating the OpenGL context if necessary. It + * is the counterpart to {@link #onPause()}. + * + * This method should typically be called in + * {@link android.app.Activity#onStart Activity.onStart}. + * * Must not be called before a renderer has been set. */ public void onResume() { @@ -1354,7 +1360,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback GLSurfaceView view = mGLSurfaceViewWeakRef.get(); boolean preserveEglContextOnPause = view == null ? false : view.mPreserveEGLContextOnPause; - if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) { + if (!preserveEglContextOnPause) { stopEglContextLocked(); if (LOG_SURFACE) { Log.i("GLThread", "releasing EGL context because paused tid=" + getId()); @@ -1362,16 +1368,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback } } - // When pausing, optionally terminate EGL: - if (pausing) { - if (sGLThreadManager.shouldTerminateEGLWhenPausing()) { - mEglHelper.finish(); - if (LOG_SURFACE) { - Log.i("GLThread", "terminating EGL because paused tid=" + getId()); - } - } - } - // Have we lost the SurfaceView surface? if ((! mHasSurface) && (! mWaitingForSurface)) { if (LOG_SURFACE) { @@ -1411,7 +1407,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback if (! mHaveEglContext) { if (askedToReleaseEglContext) { askedToReleaseEglContext = false; - } else if (sGLThreadManager.tryAcquireEglContextLocked(this)) { + } else { try { mEglHelper.start(); } catch (RuntimeException t) { @@ -1506,7 +1502,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback if (createGlInterface) { gl = (GL10) mEglHelper.createGL(); - sGLThreadManager.checkGLDriver(gl); createGlInterface = false; } @@ -1888,111 +1883,16 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback Log.i("GLThread", "exiting tid=" + thread.getId()); } thread.mExited = true; - if (mEglOwner == thread) { - mEglOwner = null; - } notifyAll(); } - /* - * Tries once to acquire the right to use an EGL - * context. Does not block. Requires that we are already - * in the sGLThreadManager monitor when this is called. - * - * @return true if the right to use an EGL context was acquired. - */ - public boolean tryAcquireEglContextLocked(GLThread thread) { - if (mEglOwner == thread || mEglOwner == null) { - mEglOwner = thread; - notifyAll(); - return true; - } - checkGLESVersion(); - if (mMultipleGLESContextsAllowed) { - return true; - } - // Notify the owning thread that it should release the context. - // TODO: implement a fairness policy. Currently - // if the owning thread is drawing continuously it will just - // reacquire the EGL context. - if (mEglOwner != null) { - mEglOwner.requestReleaseEglContextLocked(); - } - return false; - } - /* * Releases the EGL context. Requires that we are already in the * sGLThreadManager monitor when this is called. */ public void releaseEglContextLocked(GLThread thread) { - if (mEglOwner == thread) { - mEglOwner = null; - } notifyAll(); } - - public synchronized boolean shouldReleaseEGLContextWhenPausing() { - // Release the EGL context when pausing even if - // the hardware supports multiple EGL contexts. - // Otherwise the device could run out of EGL contexts. - return mLimitedGLESContexts; - } - - public synchronized boolean shouldTerminateEGLWhenPausing() { - checkGLESVersion(); - return !mMultipleGLESContextsAllowed; - } - - public synchronized void checkGLDriver(GL10 gl) { - if (! mGLESDriverCheckComplete) { - checkGLESVersion(); - String renderer = gl.glGetString(GL10.GL_RENDERER); - if (mGLESVersion < kGLES_20) { - mMultipleGLESContextsAllowed = - ! renderer.startsWith(kMSM7K_RENDERER_PREFIX); - notifyAll(); - } - mLimitedGLESContexts = !mMultipleGLESContextsAllowed; - if (LOG_SURFACE) { - Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = " - + mMultipleGLESContextsAllowed - + " mLimitedGLESContexts = " + mLimitedGLESContexts); - } - mGLESDriverCheckComplete = true; - } - } - - private void checkGLESVersion() { - if (! mGLESVersionCheckComplete) { - mGLESVersion = SystemProperties.getInt( - "ro.opengles.version", - ConfigurationInfo.GL_ES_VERSION_UNDEFINED); - if (mGLESVersion >= kGLES_20) { - mMultipleGLESContextsAllowed = true; - } - if (LOG_SURFACE) { - Log.w(TAG, "checkGLESVersion mGLESVersion =" + - " " + mGLESVersion + " mMultipleGLESContextsAllowed = " + mMultipleGLESContextsAllowed); - } - mGLESVersionCheckComplete = true; - } - } - - /** - * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides - * support for hardware-accelerated views, therefore multiple EGL contexts are - * supported on all Android 3.0+ EGL drivers. - */ - private boolean mGLESVersionCheckComplete; - private int mGLESVersion; - private boolean mGLESDriverCheckComplete; - private boolean mMultipleGLESContextsAllowed; - private boolean mLimitedGLESContexts; - private static final int kGLES_20 = 0x20000; - private static final String kMSM7K_RENDERER_PREFIX = - "Q3Dimension MSM7500 "; - private GLThread mEglOwner; } private static final GLThreadManager sGLThreadManager = new GLThreadManager(); diff --git a/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml b/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml index 440cb647c0245d7fc9fd46db1b2f25107ec2683b..2b69d5bfd5409a7095349e6bc6bfd13900b4146d 100644 --- a/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-bn-rBD/strings.xml @@ -24,13 +24,13 @@ "একটি সংযুক্ত ডেস্কটপ কম্পিউটার থেকে সমস্ত ডেটার সম্পূর্ণ ব্যাকআপ নেওয়ার অনুরোধ করা হয়েছে৷ আপনি কি এটি করার অনুমতি দিতে চান?\n\nযদি আপনি নিজের থেকে এই ব্যাকআপ নেওয়ার অনুরোধ না করে থাকেন, তবে এই প্রক্রিয়াটিতে অনুমতি প্রদান করবেন না৷ এটি বর্তমানে ডিভাইসটিতে থাকা সমস্ত ডেটাকে প্রতিস্থাপন করবে!" "আমার ডেটা পুনরুদ্ধার করুন" "পুনরুদ্ধার করবেন না" - "দয়া করে নীচে আপনার বর্তমান ব্যাকআপের পাসওয়ার্ড দিন:" - "দয়া করে নীচে আপনার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷" - "দয়া করে নীচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাকআপ সংরক্ষণাগার এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷" + "দয়া করে নিচে আপনার বর্তমান ব্যাকআপের পাসওয়ার্ড দিন:" + "দয়া করে নিচে আপনার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷" + "দয়া করে নিচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাকআপ সংরক্ষণাগার এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷" "সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে দয়া করে একটি পাসওয়ার্ড লিখুন৷ যদি এটি খালি রেখে দেওয়া হয় তবে আপনার বর্তমান ব্যাকআপ পাসওয়ার্ডটি ব্যবহার করা হবে:" - "আপনি যদি সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে চান তাহলে নীচে একটি পাসওয়ার্ড লিখুন:" - "আপনার ডিভাইস এনক্রিপ্ট হয়ে থাকার কারণে আপনার ব্যাকআপকে এনক্রিপ্ট করতে হবে। দয়া করে নীচে একটি পাসওয়ার্ড দিন:" - "যদি পুনরুদ্ধার করা ডেটা এনক্রিপ্ট করা থাকে, তবে দয়া করে নীচে পাসওয়ার্ডটি লিখুন:" + "আপনি যদি সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে চান তাহলে নিচে একটি পাসওয়ার্ড লিখুন:" + "আপনার ডিভাইস এনক্রিপ্ট হয়ে থাকার কারণে আপনার ব্যাকআপকে এনক্রিপ্ট করতে হবে। দয়া করে নিচে একটি পাসওয়ার্ড দিন:" + "যদি পুনরুদ্ধার করা ডেটা এনক্রিপ্ট করা থাকে, তবে দয়া করে নিচে পাসওয়ার্ডটি লিখুন:" "ব্যাকআপ নেওয়া শুরু হয়েছে..." "ব্যাকআপ নেওয়া সম্পূর্ণ হয়েছে" "পুনরুদ্ধার করা শুরু হচ্ছে..." diff --git a/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml b/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml index d499771663c6403bf2996f509fe700e5acb96962..91346499bd2a84a8beb6705bcc6cb0de749c99ae 100644 --- a/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-my-rMM/strings.xml @@ -26,7 +26,7 @@ "ပြန်လည်ရယူခြင်းအား မပြုလုပ်ပါနှင့်" "သင့်လက်ရှိ အရံသိမ်းဆည်းမှု လျှို့ဝှက်စကားဝှက်အား ထည့်သွင်းပါ။" "သင့်စက်၏ လျှို့ဝှက်အသွင်ပြောင်းခြင်းအတွက်စကားဝှက်ကို ထည့်သွင်းပါ။" - "သင့်စက်၏လျှို့ဝှက်အသွင်ပြောင်းခြင်းအတွက် လျှို့ဝှက်စကားဝှက်အားထည့်ပါ။ အရံသိမ်းဆည်းမှု သိမ်းဆည်းနေရာတွင်လည်း အသုံးပြုမည်ဖြစ်သည်။" + "သင့်စက်၏အသွင်ပြောင်းခြင်းအတွက် စကားဝှက်ကို ထည့်ပါ။ အရန်မှတ်တမ်းတွင်လည်း အသုံးပြုပါမည်။" "ဒေတာအားလုံးအားအရန်သိမ်းဆည်းခြင်းပြီးလျှို့ဝှက်အသွင်ပြောင်းခြင်းအတွက် လျှို့ဝှက်နံပါတ်/စာကိုထည့်ပါ။ အကယ်၍ ကွက်လပ်ထားပါက ယခုသင့်လက်ရှိလျှို့ဝှက်စကားဝှက်အား အသုံးပြုပါမည်။" "အကယ်၍ ဒေတာအားလုံးအားအရန်သိမ်းဆည်းခြင်းကို ဝှက်လိုပါက အောက်တွင်လျှို့ဝှက်နံပါတ်/စာကိုထည့်ပါ။" "သင်၏ ကိရိယာကို လျှို့ဝျက်ကုဒ် သွင်းထားရာ၊ သင်သည် သင်၏ ဘက်အာပ်ကိုပါ လျှို့ဝျက်ကုဒ် သွင်းရန် လိုအပ်သည်။ ကျေးဇူးပြုပြီး အောက်မှာ စကားဝှက်ကို ထည့်သွင်းပါ:" diff --git a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml index 804f980b16744b7a4ea1208e5345bc12419c5b58..44d01deafe6bb68ae5b0e4eabb7e96af0d74a31f 100644 --- a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml @@ -19,7 +19,7 @@ "Úplná záloha" "Úplné obnovenie" "Bola vyžiadaná úplná záloha všetkých dát do pripojeného počítača. Chcete túto akciu povoliť?\n\nAk ste zálohu nevyžiadali vy, túto operáciu nepovoľujte." - "Zálohovať dáta" + "Zálohovať moje dáta" "Nezálohovať" "Z pripojeného počítača bolo vyžiadané úplné obnovenie všetkých údajov. Chcete túto akciu povoliť?\n\nAk ste toto obnovenie nevyžiadali vy, túto operáciu nepovoľujte. Táto akcia nahradí všetky údaje v zariadení." "Obnoviť údaje" diff --git a/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml b/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml index 20173b0dc3bf6a4a55d3f2574d685821b81e65b4..24cbfbd6430ef2b115162c5807336dc5ae9b1268 100644 --- a/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml +++ b/packages/CaptivePortalLogin/res/values-bn-rBD/strings.xml @@ -4,7 +4,7 @@ "CaptivePortalLogin" "যেভাবে আছে সেভাবেই এই নেটওয়ার্ক ব্যবহার করুন" "এই নেটওয়ার্ক ব্যবহার করবেন না" - "নেটওয়ার্কে প্রবেশ করুন করুন" + "নেটওয়ার্কে প্রবেশ করুন" "আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।" "উদাহরণস্বরূপ, লগইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷" "যাই হোক না কেন ব্রাউজারের মাধ্যমে অবিরত রাখুন" diff --git a/packages/CaptivePortalLogin/res/values-my-rMM/strings.xml b/packages/CaptivePortalLogin/res/values-my-rMM/strings.xml index 41d3d79683f13217540c836cc6adc98b626b11b7..e25570d180c7c89ec97ebfca539860b0dc581bf6 100644 --- a/packages/CaptivePortalLogin/res/values-my-rMM/strings.xml +++ b/packages/CaptivePortalLogin/res/values-my-rMM/strings.xml @@ -7,5 +7,5 @@ "ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်" "သင်ချိတ်ဆက်ရန် ကြိုးစားနေသည့် ကွန်ရက်သည် လုံခြုံရေးပြဿနာ ရှိနေသည်။" "ဥပမာ၊ ဝင်ရောက်ရန် စာမျက်နှာသည် ပြသထားသည့် အဖွဲ့အစည်းနှင့် သက်ဆိုင်မှု မရှိနိုင်ပါ။" - "ဘရောက်ဇာမှတစ်ဆင့် ရှေ့ဆက်ရန်" + "ဘရောက်ဇာမှတစ်ဆင့် ဆက်လုပ်ရန်" diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index 6fb8b518acf5a2e109654fcca07d1d49ded43aa7..b58c87a5094d34adcd3e48ef7f82414772386250 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -96,7 +96,7 @@ public class CaptivePortalLoginActivity extends Activity { // Exit app if Network disappears. final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork); if (networkCapabilities == null) { - finish(); + finishAndRemoveTask(); return; } mNetworkCallback = new NetworkCallback() { @@ -163,7 +163,7 @@ public class CaptivePortalLoginActivity extends Activity { mCaptivePortal.useNetwork(); break; } - finish(); + finishAndRemoveTask(); } @Override diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index 69912ab12098c511b52a8f12ac775dcbf5db8ffa..a3edae35cc2b8fd3f4e121ba9dd7d8fdc3a1d056 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -11,6 +11,7 @@ diff --git a/packages/DocumentsUI/res/mipmap-hdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-hdpi/ic_app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..cd3a0370b606fa28757a944389b6124e36d68cfe Binary files /dev/null and b/packages/DocumentsUI/res/mipmap-hdpi/ic_app_icon.png differ diff --git a/packages/DocumentsUI/res/mipmap-mdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-mdpi/ic_app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8d08e9b4d32f8edae0756a37f2d252a60b81eb20 Binary files /dev/null and b/packages/DocumentsUI/res/mipmap-mdpi/ic_app_icon.png differ diff --git a/packages/DocumentsUI/res/mipmap-xhdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-xhdpi/ic_app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f3bacb7f3d0573bbf1910e018302b657c8789c30 Binary files /dev/null and b/packages/DocumentsUI/res/mipmap-xhdpi/ic_app_icon.png differ diff --git a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5156171931b50a657b29b32ab211f9eafa2b3760 Binary files /dev/null and b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_app_icon.png differ diff --git a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6dc2f7682684c2646bd8ad510199b7d1c35e44a1 Binary files /dev/null and b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_app_icon.png differ diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml index c4a5eeab75d52bd6e5566dad6da45b0ff1acd316..e3098a27bf6112b3d39c88a7fdc2148d75fc671c 100644 --- a/packages/DocumentsUI/res/values-af/strings.xml +++ b/packages/DocumentsUI/res/values-af/strings.xml @@ -16,7 +16,7 @@ - "Dokumente" + "Lêers" "Aflaaie" "Maak oop vanuit" "Stoor na" diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml index c3db7230250571a1642ca7a4b4ec76d3d361b8db..84f11f58c7aacbabe3492da9ecb9f9c7ce7f31b8 100644 --- a/packages/DocumentsUI/res/values-am/strings.xml +++ b/packages/DocumentsUI/res/values-am/strings.xml @@ -16,7 +16,7 @@ - "ሰነዶች" + "ፋይሎች" "የወረዱ" "ክፈት ከ" "አስቀምጥ ወደ" diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml index 2b122a21e8f8ad99e1d821253164e2dbcaebca59..6fee984a6a3e0d3f4788143a859a0d19276b3d68 100644 --- a/packages/DocumentsUI/res/values-ar/strings.xml +++ b/packages/DocumentsUI/res/values-ar/strings.xml @@ -16,7 +16,7 @@ - "مستندات" + "الملفات" "التنزيلات" "فتح من" "حفظ في" diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml index dfdc71a74c7af58c42448bd5a4b2cf94cae5092c..56108a19c8a14ed980d7cc8b72ef756f1a1c6471 100644 --- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml +++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml @@ -16,7 +16,7 @@ - "Sənədlər" + "Fayllar" "Endirmələr" "Vasitəsilə açın" "buraya saxlayın" diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml index e068a10e7a4e7259b897d57050087cbd5beb80c9..8b5fdd84325c727b9bcf3cccdd87a726a899f679 100644 --- a/packages/DocumentsUI/res/values-bg/strings.xml +++ b/packages/DocumentsUI/res/values-bg/strings.xml @@ -16,7 +16,7 @@ - "Документи" + "Файлове" "Изтегляния" "Отваряне от" "Запазване във:" diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml index 1bdc2049041bcad5521f601865ebcb2e9120db1d..7d4692d07da3d0d29fb7db4afba746ef1401d7e9 100644 --- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml +++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml @@ -16,7 +16,7 @@ - "দস্তাবেজগুলি" + "ফাইল" "ডাউনলোডগুলি" "এখান থেকে খুলুন" "এতে সংরক্ষণ করুন" diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml index 3436ed439e01ebf0bb5f2e52d9cdb9c10e561cf0..e25731d4915f942af0ee2e876a4f9272c7e188bb 100644 --- a/packages/DocumentsUI/res/values-ca/strings.xml +++ b/packages/DocumentsUI/res/values-ca/strings.xml @@ -16,7 +16,7 @@ - "Documents" + "Fitxers" "Baixades" "Obre des de" "Desa a" diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml index 90d30bcc8ec19e9249af4df84d000a8979a6e3cf..190f60e72672966c4dc04c26c8a696605811b4e9 100644 --- a/packages/DocumentsUI/res/values-cs/strings.xml +++ b/packages/DocumentsUI/res/values-cs/strings.xml @@ -16,7 +16,7 @@ - "Dokumenty" + "Soubory" "Stahování" "Otevřít" "Uložit do" diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml index 4900cd0a5aaa3ec13e86dcdab2db329c9be41771..73350d7f003bb74183dac6625f458e25d5130d4c 100644 --- a/packages/DocumentsUI/res/values-da/strings.xml +++ b/packages/DocumentsUI/res/values-da/strings.xml @@ -16,7 +16,7 @@ - "Dokumenter" + "Filer" "Downloads" "Åbn fra" "Gem i" diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml index 4cd2527a12eca58377815bb49a1ea2fc43ccece0..21a298f70a6244f95bd18e959df7eb7b4601da52 100644 --- a/packages/DocumentsUI/res/values-de/strings.xml +++ b/packages/DocumentsUI/res/values-de/strings.xml @@ -16,7 +16,7 @@ - "Dokumente" + "Dateien" "Downloads" "Öffnen von" "Speichern unter" diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml index 461b19152fcc7f326b128dcea0b0a0a323015def..afa4d89d7a5bd5816b6d7ce6746500a405b318ac 100644 --- a/packages/DocumentsUI/res/values-el/strings.xml +++ b/packages/DocumentsUI/res/values-el/strings.xml @@ -16,7 +16,7 @@ - "Έγγραφα" + "Αρχεία" "Λήψεις" "Άνοιγμα από" "Αποθήκευση σε" diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml index e062d20549b4d176dca209f7f0b25f6e8438d9af..c743e88c402fcea1043420daf62d19e24a24ac8c 100644 --- a/packages/DocumentsUI/res/values-en-rAU/strings.xml +++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml @@ -16,7 +16,7 @@ - "Documents" + "Files" "Downloads" "Open from" "Save to" @@ -107,7 +107,7 @@ Copied %1$d file to clipboard. "Cannot paste the selected files in this location." - "rename" + "Rename" "Failed to rename document" "Some files were converted" "Grant ^1 access to ^2 directory on ^3?" diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml index e062d20549b4d176dca209f7f0b25f6e8438d9af..c743e88c402fcea1043420daf62d19e24a24ac8c 100644 --- a/packages/DocumentsUI/res/values-en-rGB/strings.xml +++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml @@ -16,7 +16,7 @@ - "Documents" + "Files" "Downloads" "Open from" "Save to" @@ -107,7 +107,7 @@ Copied %1$d file to clipboard. "Cannot paste the selected files in this location." - "rename" + "Rename" "Failed to rename document" "Some files were converted" "Grant ^1 access to ^2 directory on ^3?" diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml index e062d20549b4d176dca209f7f0b25f6e8438d9af..c743e88c402fcea1043420daf62d19e24a24ac8c 100644 --- a/packages/DocumentsUI/res/values-en-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml @@ -16,7 +16,7 @@ - "Documents" + "Files" "Downloads" "Open from" "Save to" @@ -107,7 +107,7 @@ Copied %1$d file to clipboard. "Cannot paste the selected files in this location." - "rename" + "Rename" "Failed to rename document" "Some files were converted" "Grant ^1 access to ^2 directory on ^3?" diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml index cbb148fc21b63f57ce9bcf9fe49ef8558713977f..4007db2c91120543689752cca28142b74673ed9e 100644 --- a/packages/DocumentsUI/res/values-es-rUS/strings.xml +++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml @@ -16,7 +16,7 @@ - "Documentos" + "Archivos" "Descargas" "Abrir desde" "Guardar en" diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml index 1efe13fbae1a6f3e276fb5a08023454f7701ca52..3eb14a79033c261eac38948cce2f63da1cb09ca4 100644 --- a/packages/DocumentsUI/res/values-es/strings.xml +++ b/packages/DocumentsUI/res/values-es/strings.xml @@ -16,7 +16,7 @@ - "Documentos" + "Archivos" "Descargas" "Abrir desde" "Guardar en" diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml index ad1937fa277699a8905cc7ff1f133fd2d645fc89..ea8b1e56ad97b13e6f03b68a58c19c10c52ad442 100644 --- a/packages/DocumentsUI/res/values-et-rEE/strings.xml +++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml @@ -16,7 +16,7 @@ - "Dokumendid" + "Failid" "Allalaadimised" "Ava asukohast:" "Salvesta:" diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml index 28b8178e9ad6a8d45f526089f693f93691354d28..e2214be0a846253bb627f9adf67ba03d691c2415 100644 --- a/packages/DocumentsUI/res/values-eu-rES/strings.xml +++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml @@ -16,7 +16,7 @@ - "Dokumentuak" + "Fitxategiak" "Deskargak" "Ireki hemendik" "Gorde hemen" diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml index b5158e2cb962a20a26392624f1aa3dd5e22d3b7f..cc27e8e9a0b55e2a93940ca7a34282d942fdfc33 100644 --- a/packages/DocumentsUI/res/values-fa/strings.xml +++ b/packages/DocumentsUI/res/values-fa/strings.xml @@ -16,7 +16,7 @@ - "اسناد" + "Files" "بارگیری‌ها" "باز کردن از" "ذخیره در" @@ -36,8 +36,8 @@ "پنجره جدید" "کپی" "جای‌گذاری" - "نمایش فضای ذخیره‌سازی داخلی" - "پنهان کردن فضای ذخیره‌سازی داخلی" + "نمایش حافظه داخلی" + "پنهان کردن حافظه داخلی" "نمایش اندازه فایل" "پنهان کردن اندازه فایل" "انتخاب" @@ -112,7 +112,7 @@ "بعضی از فایل‌ها تبدیل شدند" "به ^1 اجازه داده شود به فهرست راهنمای ^2 در ^3 دسترسی داشته باشد؟" "به ^1 اجازه دسترسی به دایرکتوری ^2 داده شود؟" - "به ^1 اجازه می‌دهید به داده‌هایتان دسترسی پیدا کند، از جمله عکس‌ها و ویدیوهایتان در ^2؟" + "به ^1 اجازه می‌دهید به داده‌هایتان دسترسی پیدا کند، از جمله عکس‌ها و ویدئوهایتان در ^2؟" "دوباره سؤال نشود" "ارزیابی‌شده" "اجازه ندارد" diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml index 2a27ddeb4ff7faf9e28f095a49d5d1e9d90d3f33..32cde21b9b708969d2ee6ec571aa9b6487724bdb 100644 --- a/packages/DocumentsUI/res/values-fi/strings.xml +++ b/packages/DocumentsUI/res/values-fi/strings.xml @@ -16,7 +16,7 @@ - "Asiakirjat" + "Tiedostot" "Lataukset" "Avaa sijainnista" "Tallenna kohteeseen" diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml index 9583b8a3319b9d5827ae2c17a2d98487e2a24a55..54a5c0a1e586cc2035e03b7bd5ad6b93c87bc13e 100644 --- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml +++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml @@ -16,7 +16,7 @@ - "Documents" + "Fichiers" "Téléchargements" "Ouvrir à partir de" "Enregistrer dans" diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml index 630a492ef888c0de1e1524d78ff323fa569cab75..20292b62c04efe0c876f0898aa1a08364eba4691 100644 --- a/packages/DocumentsUI/res/values-fr/strings.xml +++ b/packages/DocumentsUI/res/values-fr/strings.xml @@ -16,7 +16,7 @@ - "Docs" + "Fichiers" "Téléchargements" "Ouvrir à partir de" "Enregistrer sous" diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml index 47fc1c7252d3cc551a1c20e4c9017b96c0c562cb..37197cfdfa721527f51623c98f3d64281fd1a938 100644 --- a/packages/DocumentsUI/res/values-gl-rES/strings.xml +++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml @@ -16,7 +16,7 @@ - "Documentos" + "Ficheiros" "Descargas" "Abrir desde" "Gardar en" diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml index 4d87d9705c93869e4179e19cc9008cccdfab41b4..5b0db064e7052211f825728a6580cf905fcf3f32 100644 --- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml @@ -16,7 +16,7 @@ - "દસ્તાવેજો" + "ફાઇલો" "ડાઉનલોડ્સ" "અહીંથી ખોલો" "આમાં સાચવો" diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml index 8420b0203d9d3e06a773e390bc7537f426e84ccb..04094f381913451d8885617f89d83a6ba690a864 100644 --- a/packages/DocumentsUI/res/values-hi/strings.xml +++ b/packages/DocumentsUI/res/values-hi/strings.xml @@ -16,7 +16,7 @@ - "दस्तावेज़" + "फ़ाइल" "डाउनलोड" "यहां से खोलें" "यहां सहेजें" diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml index 8fe0a4d456395767ccbb587b5f5b17474e2494db..15fb9348711eeeec68e5730dbfe4916774c48099 100644 --- a/packages/DocumentsUI/res/values-hr/strings.xml +++ b/packages/DocumentsUI/res/values-hr/strings.xml @@ -16,7 +16,7 @@ - "Dokumenti" + "Datoteke" "Preuzimanja" "Otvori iz" "Spremi u" diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml index aa9d799f59cdceb8e276c5c776c8c21f3237bcd5..627cac1d5344f16cdb152ebfc8399eb58ba86634 100644 --- a/packages/DocumentsUI/res/values-hu/strings.xml +++ b/packages/DocumentsUI/res/values-hu/strings.xml @@ -16,7 +16,7 @@ - "Dokumentumok" + "Fájlok" "Letöltések" "Megnyitás innen" "Mentés ide" diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml index fe4bcf8c3fd296952334a6f2ea53a8c29962a81b..15c05eb4e14cd504fd5a599fd6a0a8812a3ebf08 100644 --- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml +++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml @@ -16,7 +16,7 @@ - "Փաստաթղթեր" + "Ֆայլեր" "Ներբեռնումներ" "Բացել այստեղից" "Պահել այստեղ" diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml index 81f9f496634fe56a59bf580acd96ccc3b9cc59fb..fb9fed62ad072c7fafd348325b70d4911d5b4e1c 100644 --- a/packages/DocumentsUI/res/values-in/strings.xml +++ b/packages/DocumentsUI/res/values-in/strings.xml @@ -16,7 +16,7 @@ - "Dokumen" + "File" "Unduhan" "Buka dari" "Simpan ke" diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml index 6f86ad1d6bd0a6e7ef09ab6e4265cb0d9a268117..ff229ce9d5d607000e38f468a44a487d64acb77c 100644 --- a/packages/DocumentsUI/res/values-is-rIS/strings.xml +++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml @@ -16,7 +16,7 @@ - "Skjöl" + "Skrár" "Niðurhal" "Opna frá" "Vista í" diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml index 5ad9fb29153075c8841661160b778b28fca232b0..e7f1b68b830933b6098c1c1862ca0ea14392d67a 100644 --- a/packages/DocumentsUI/res/values-it/strings.xml +++ b/packages/DocumentsUI/res/values-it/strings.xml @@ -16,7 +16,7 @@ - "Documenti" + "File" "Download" "Apri da" "Salva in" diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml index 51414e30ec653fb0cfa4d095effd47dc9c19b6e9..ad24b4e494ce280666041ce920a86a21b62bc6d4 100644 --- a/packages/DocumentsUI/res/values-iw/strings.xml +++ b/packages/DocumentsUI/res/values-iw/strings.xml @@ -16,7 +16,7 @@ - "מסמכים" + "קבצים" "הורדות" "פתח מ-" "שמור ב-" diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml index 48f482aff344b4ff88f57f360784803966a32c8d..e1b2c50438d6eb5581ab1f1af0fa8fab30997f6b 100644 --- a/packages/DocumentsUI/res/values-ja/strings.xml +++ b/packages/DocumentsUI/res/values-ja/strings.xml @@ -16,7 +16,7 @@ - "ドキュメント" + "ファイル" "ダウンロード" "次から開く:" "次に保存:" @@ -110,9 +110,9 @@ "名前を変更" "ドキュメントの名前を変更できませんでした" "一部のファイルが変換されました" - "「^3」の「^2」ディレクトリに「^1」へのアクセスを許可しますか?" - "「^1」アプリに「^2」ディレクトリへのアクセスを許可しますか?" - "^2の写真や動画などのデータへのアクセスを「^1」に許可しますか?" + "^3^2 ディレクトリに ^1 へのアクセスを許可しますか?" + "^1 アプリに ^2 ディレクトリへのアクセスを許可しますか?" + "^2の写真や動画などのデータへのアクセスを ^1 に許可しますか?" "今後表示しない" "許可" "拒否" diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml index 1be969c2f8c4f508929fd01399c9eb1bc393ebe1..024194fbe67cfc8453a962e09a5400792e3fe0f5 100644 --- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml +++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml @@ -16,7 +16,7 @@ - "დოკუმენტები" + "ფაილები" "ჩამოტვირთვები" "გახსნა აქედან:" "შენახვა აქ:" diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml index dcb846433a69b31f45d9846f6994fc2d7ed293c7..075f2560b3f5f4036ab4b47fd25ea18befe3d327 100644 --- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml +++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml @@ -16,14 +16,14 @@ - "Құжаттар" + "Файлдар" "Жүктеулер" "Мынадан ашу:" "Сақталатын орны" "Жаңа қалта" "Торлы көрініс" "Тізім көрінісі" - "Белгіге қарай сұрыптау" + "Сұрыптау" "Іздеу" "Жад параметрлері" "Ашу" @@ -53,7 +53,7 @@ "Құжатты сақтау орындалмады" "Қалта жасақтау іске аспады" "Қазір мазмұнды жүктеу мүмкін емес" - "Жуықта қолданылған" + "Соңғы" "%1$s бос" "Жад қызметтері" "Төте пернелер" diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml index 7c0e8c226ac12726dc21fe9a2a4cb6002495759c..7e7843de3db5b9ef72831f8e7a6f16bcf13bcda1 100644 --- a/packages/DocumentsUI/res/values-km-rKH/strings.xml +++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml @@ -16,7 +16,7 @@ - "ឯកសារ" + "ឯកសារ" "ទាញយក" "បើក​ពី" "រក្សា​ទុក​ទៅ" diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml index c7d414fbe638ebd7047ba646c5185919c539084c..7becf4e7776ace6c4606acc3b29a5f2b9e18f7ca 100644 --- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml @@ -16,7 +16,7 @@ - "ಡಾಕ್ಯುಮೆಂಟ್‌ಗಳು" + "ಫೈಲ್‌ಗಳು" "ಡೌನ್‌ಲೋಡ್‌ಗಳು" "ಇದರ ಮೂಲಕ ತೆರೆಯಿರಿ" "ಇವುಗಳಲ್ಲಿ ಉಳಿಸಿ" @@ -24,7 +24,7 @@ "ಗ್ರಿಡ್ ವೀಕ್ಷಣೆ" "ಪಟ್ಟಿ ವೀಕ್ಷಣೆ" "ಈ ಪ್ರಕಾರ ವಿಂಗಡಿಸು" - "ಹುಡುಕು" + "ಹುಡುಕಿ" "ಸಂಗ್ರಹಣೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ತೆರೆ" "ಉಳಿಸು" diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml index 8f5cc9f1e8d67ff0d8f14c0564c74d6b34fcadc4..5d2b162d5539f7b2b74cc8b7e6d82167d1d3ee57 100644 --- a/packages/DocumentsUI/res/values-ko/strings.xml +++ b/packages/DocumentsUI/res/values-ko/strings.xml @@ -16,7 +16,7 @@ - "문서" + "파일" "다운로드" "열기:" "저장 위치:" diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml index db8b04c7b6a2b599ff0caa3c7ab881bc8b56f890..be3276587677d9236607bbf4ebb41904026c993a 100644 --- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml +++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml @@ -16,7 +16,7 @@ - "Документтер" + "Файлдар" "Жүктөлүп алынгандар" "Кийинкиден ачуу:" "Кийинкиге сактоо:" diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml index 6c2bfd6a147155d6e36009ef50b67d756adef15c..fe4c0b626342e4db1d997e14de4ada7c8949d7d7 100644 --- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml +++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml @@ -16,7 +16,7 @@ - "ເອ​ກະ​ສານ" + "​ໄຟລ໌" "ການດາວໂຫລດ" "ເປີດ​ຈາກ" "ບັນທຶກໄປທີ່" diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml index 6ee4fb83e6d4e4bd17be7d2efa19eebad5f995c7..091861681644e9351e3c01a7ebae49fc6a9ad0a0 100644 --- a/packages/DocumentsUI/res/values-lt/strings.xml +++ b/packages/DocumentsUI/res/values-lt/strings.xml @@ -16,7 +16,7 @@ - "Dokumentai" + "Failai" "Atsisiuntimai" "Atidaryti iš" "Išsaugoti į" diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml index fa3a05200935f98f3bccefd20f303b3ada4afe80..e767ea1adf64fe6f94991a72b138a2f49fcd9b4b 100644 --- a/packages/DocumentsUI/res/values-lv/strings.xml +++ b/packages/DocumentsUI/res/values-lv/strings.xml @@ -16,7 +16,7 @@ - "Dokumenti" + "Faili" "Lejupielādes" "Atvēršana no:" "Saglabāšana:" diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml index 14633dfaac7e76a02ad9f92f98b6c2648efba415..b568211d22f580cb64319326a3114f0c5c89b9a2 100644 --- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml +++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml @@ -16,7 +16,7 @@ - "Документи" + "Датотеки" "Преземања" "Отвори од" "Зачувај во" diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml index 6f1bdfd717e0f9e864e3ddf0adebc704c9847050..bdeeaa5e4e493ba25070b7b1e59e035dba453729 100644 --- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml @@ -16,7 +16,7 @@ - "പ്രമാണങ്ങൾ" + "ഫയലുകൾ" "ഡൗണ്‍ലോഡുകൾ" "ഇതിൽ നിന്നും തുറക്കുക" "ഇതില്‍‌ സംരക്ഷിക്കുക" diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml index da55ab0f293f47d7285b2fa94a9a622b062ff716..b98125b461adc3ac27f65a3657933a1d20290cbf 100644 --- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml +++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml @@ -16,7 +16,7 @@ - "Документүүд" + "Файл" "Таталт" "Нээх" "Хадгалах" diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml index 7453aa2c6c5b5235308eb34eed09802707d2092c..3ff4fc035db73ee8c560dc1d6d2c7253268e5460 100644 --- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml @@ -16,7 +16,7 @@ - "दस्तऐवज" + "फायली" "डाउनलोड" "वरून उघडा" "येथे जतन करा" diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml index 7180bc2557baaec2521b9bebaa57ff38f017ed7b..602a52dfc2de482e57564661182a6aea8cf4f2fb 100644 --- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml +++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml @@ -16,7 +16,7 @@ - "Dokumen" + "Fail" "Muat turun" "Buka dari" "Simpan ke" diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml index fc7e05b66a4c461e2663581b177549a72f85cb32..2b0cc1fdfaf65c1d4cd363fbbacbae3b6de0a85c 100644 --- a/packages/DocumentsUI/res/values-my-rMM/strings.xml +++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml @@ -16,7 +16,7 @@ - "စာရွက်စာတန်းများ" + "ဖိုင်များ" "ဒေါင်းလုဒ်များ" "မှ ဖွင့်ပါ" "သို့ သိမ်းပါ" @@ -27,9 +27,9 @@ "ရှာဖွေရန်" "သိုလှောင်မှု ဆက်တင်များ" "ဖွင့်ရန်" - "သိမ်းပါ" + "သိမ်းရန်" "မျှဝေခြင်း" - "ဖျက်ပစ်ရန်" + "ဖျက်ရန်" "အားလုံးကို ရွေးရန်" "…သို့ကူးယူရန်" "...သို့ ရွှေ့ရန်" diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml index bd5da812face72628eec323b30aa609a948d95e1..ab5634182cca201d37c5ae8ed353fd83a31fd44c 100644 --- a/packages/DocumentsUI/res/values-nb/strings.xml +++ b/packages/DocumentsUI/res/values-nb/strings.xml @@ -16,7 +16,7 @@ - "Dokumenter" + "Filer" "Nedlastinger" "Åpne fra" "Lagre i" diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml index 0ab0b785c9fb94c58558909d3b5f85134d6d331b..48fcbc136fe3b74a6fe3034a461320f97f81d670 100644 --- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml +++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml @@ -16,7 +16,7 @@ - "कागजातहरू" + "फाइलहरू" "डाउनलोडहरू" "यसबाट खोल्नुहोस्" "यसमा सुरक्षित गर्नुहोस्" diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml index 7ede6f575da8bcf5b3dd1d49146a08b43679c74c..7bcd8539ad03d2263fdf8c7b7f85f1ecaa3d8e0d 100644 --- a/packages/DocumentsUI/res/values-nl/strings.xml +++ b/packages/DocumentsUI/res/values-nl/strings.xml @@ -16,7 +16,7 @@ - "Documenten" + "Bestanden" "Downloads" "Openen vanuit" "Opslaan in" @@ -125,14 +125,14 @@ %1$d item "%1$s verwijderen?" - "Map %1$s en de bijbehorende inhoud verwijderen?" + "Map %1$s en de bijbehorende content verwijderen?" %1$d bestanden verwijderen? %1$d bestand verwijderen? - %1$d mappen en de bijbehorende inhoud verwijderen? - %1$d map en de bijbehorende inhoud verwijderen? + %1$d mappen en de bijbehorende content verwijderen? + %1$d map en de bijbehorende content verwijderen? %1$d items verwijderen? diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml index 7e04403badd986c6ff2e596caa93b3eec5a17dfc..178e3b4fd7098e1da82cf070524c8129723e93f1 100644 --- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml @@ -16,7 +16,7 @@ - "ਦਸਤਾਵੇਜ਼" + "ਫ਼ਾਈਲਾਂ" "ਡਾਊਨਲੋਡ" "ਤੋਂ ਖੋਲ੍ਹੋ" "ਇਸ ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੋ" diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml index 2a66e59cd17165a9b3e074d4ffabe0c8044216e6..6c17ed63568471b1f1a7053d4ea0f6c8180dacf1 100644 --- a/packages/DocumentsUI/res/values-pl/strings.xml +++ b/packages/DocumentsUI/res/values-pl/strings.xml @@ -16,7 +16,7 @@ - "Dokumenty" + "Pliki" "Pobrane" "Otwórz z" "Zapisz w" diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml index b86438ff05ca650dc494616c7f35a0bdca951000..21aa72097f469ae0c54a3d3d6a130e0a0cf935d0 100644 --- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml +++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml @@ -16,7 +16,7 @@ - "Documentos" + "Arquivos" "Downloads" "Abrir de" "Salvar em" diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml index e15662ffa423828bee748edd6ddc1661cd5943e5..186defa2899953b5c12dcf1929b2a8cb53eae4e7 100644 --- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml +++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml @@ -16,7 +16,7 @@ - "Documentos" + "Ficheiros" "Transferências" "Abrir de" "Guardar em" diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml index b86438ff05ca650dc494616c7f35a0bdca951000..21aa72097f469ae0c54a3d3d6a130e0a0cf935d0 100644 --- a/packages/DocumentsUI/res/values-pt/strings.xml +++ b/packages/DocumentsUI/res/values-pt/strings.xml @@ -16,7 +16,7 @@ - "Documentos" + "Arquivos" "Downloads" "Abrir de" "Salvar em" diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml index 1f519f5cae7d987336c5c7ddb0a65840d95e259f..e25fa1dc17bdfae1c56d879cdc2180e771c577d2 100644 --- a/packages/DocumentsUI/res/values-ro/strings.xml +++ b/packages/DocumentsUI/res/values-ro/strings.xml @@ -16,7 +16,7 @@ - "Documente" + "Fișiere" "Descărcări" "Deschideți din" "Salvați în" diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml index 37cf0658283dc482ab59a4a43170c4f7e1df2942..37b1b45c6ac42e341543a80321a4f088d575fa2d 100644 --- a/packages/DocumentsUI/res/values-ru/strings.xml +++ b/packages/DocumentsUI/res/values-ru/strings.xml @@ -16,7 +16,7 @@ - "Документы" + "Файлы" "Загрузки" "Открыть" "Сохранить" diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml index bf9406645c644b7e0618fe211f1d94aae01bba50..d43f5f3544ebcc94d185afbcc7d545bcdd148d05 100644 --- a/packages/DocumentsUI/res/values-si-rLK/strings.xml +++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml @@ -16,7 +16,7 @@ - "ලේඛන" + "ගොනු" "බාගැනීම්" "විවෘත වන්නේ" "සුරකින්නේ" diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml index 9a4ee9001259eb5979e1e1110e93b1a602e849cd..edc2027364a14bda6f5e824331638c9cdd128e96 100644 --- a/packages/DocumentsUI/res/values-sk/strings.xml +++ b/packages/DocumentsUI/res/values-sk/strings.xml @@ -16,7 +16,7 @@ - "Dokumenty" + "Súbory" "Stiahnuté súbory" "Otvoriť z" "Uložiť do" diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml index 0c7816ccc1f29579ae7ea24f27d45328c0cf8f8e..1779eef4ce766f21fc06ffe3f7acecafb68dc1ef 100644 --- a/packages/DocumentsUI/res/values-sl/strings.xml +++ b/packages/DocumentsUI/res/values-sl/strings.xml @@ -16,7 +16,7 @@ - "Dokumenti" + "Datoteke" "Prenosi" "Odpri iz mape" "Shrani v" diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml index 6cfe3986357e179e87bace856a5e3f1f589c2365..7e784818c880d06dbd40d56b56a6b111790c7681 100644 --- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml +++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml @@ -16,7 +16,7 @@ - "Dokumente" + "Skedarët" "Shkarkimet" "Hap nga" "Ruaje te" diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml index d44b89b9150724efc1b6450574409c03fa7b3885..ee9a9edf6c3df827f65bcc4099ef4c07372eb528 100644 --- a/packages/DocumentsUI/res/values-sr/strings.xml +++ b/packages/DocumentsUI/res/values-sr/strings.xml @@ -16,7 +16,7 @@ - "Документи" + "Датотеке" "Преузимања" "Отвори са" "Сачувај у" @@ -44,7 +44,7 @@ "Копирај" "Премести" "Одбаци" - "Покушај поново" + "Пробај поново" "Према имену" "Према датуму измене" "Према величини" diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml index 760a45679fca081e2211a85f12f2723c74ae02fa..5fd3c8c1437b37faa5e9c14538b0b8dcfb4d7369 100644 --- a/packages/DocumentsUI/res/values-sv/strings.xml +++ b/packages/DocumentsUI/res/values-sv/strings.xml @@ -16,7 +16,7 @@ - "Dokument" + "Filer" "Nedladdningar" "Öppna från" "Spara till" @@ -43,7 +43,7 @@ "Välj" "Kopiera" "Flytta" - "Ta bort permanent" + "Avvisa" "Försök igen" "Efter namn" "Efter ändringsdatum" diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml index eb37ad0d0624d7e3112a8001e0ce819cf947ee65..9df96f40aa0c3b998c631e74bf8ccf1386cae778 100644 --- a/packages/DocumentsUI/res/values-sw/strings.xml +++ b/packages/DocumentsUI/res/values-sw/strings.xml @@ -16,7 +16,7 @@ - "Hati" + "Faili" "Vipakuliwa" "Fungua kutoka" "Hifadhi kwenye" diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml index 1f54641854c8b650e0bfacdbef6b83b1c78611be..123664719fb9bb2dc6ec6f92528388d37d211975 100644 --- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml @@ -16,7 +16,7 @@ - "ஆவணங்கள்" + "கோப்புகள்" "இறக்கங்கள்" "இதில் திற" "இதில் சேமி" diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml index 7449913e6aab26f00568013493006a1fbb2e9b97..e24184188cb6e8135565c087568f47fef154aac7 100644 --- a/packages/DocumentsUI/res/values-te-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml @@ -16,7 +16,7 @@ - "పత్రాలు" + "ఫైల్‌లు" "డౌన్‌లోడ్‌లు" "ఇక్కడి నుండి తెరువు" "ఇందులో సేవ్ చేయి" diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml index 77cb9b134bb53e7dfef7ac329608f988db68dc2e..ec3a3cdf834a885655e52812738f6aa7de7f26f9 100644 --- a/packages/DocumentsUI/res/values-th/strings.xml +++ b/packages/DocumentsUI/res/values-th/strings.xml @@ -16,7 +16,7 @@ - "เอกสาร" + "ไฟล์" "การดาวน์โหลด" "เปิดจาก" "บันทึกไปยัง" diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml index adf1b72bb25bb231432d005cd46f70ad1593970c..927109204522843d65c0d0a7a400d5a2bdaa8c88 100644 --- a/packages/DocumentsUI/res/values-tl/strings.xml +++ b/packages/DocumentsUI/res/values-tl/strings.xml @@ -16,7 +16,7 @@ - "Mga Dokumento" + "Mga File" "Mga Download" "Buksan mula sa" "I-save sa" diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml index bdc598399202a8be24b683803a1744515f99f527..4ba5f4bbf6bb3972b676a6cf870490602df7be5f 100644 --- a/packages/DocumentsUI/res/values-tr/strings.xml +++ b/packages/DocumentsUI/res/values-tr/strings.xml @@ -16,7 +16,7 @@ - "Dokümanlar" + "Dosyalar" "İndirilenler" "Şuradan aç:" "Şuraya kaydet:" @@ -96,7 +96,7 @@ %1$d dosya silinemedi %1$d dosya silinemedi - "Ayrıntıları görmek için hafifçe dokunun" + "Ayrıntıları görmek için dokunun" "Kapat" "Şu dosyalar kopyalanamadı: %1$s" "Şu dosyalar taşınamadı: %1$s" diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml index 192042ca6fa58350882cfacdcca3860a6304527e..1d6c4fd48cff35abe51949671f5959a3f49fafcb 100644 --- a/packages/DocumentsUI/res/values-uk/strings.xml +++ b/packages/DocumentsUI/res/values-uk/strings.xml @@ -16,7 +16,7 @@ - "Документи" + "Файли" "Завантаження" "Відкрити" "Зберегти в" diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml index bea73265fa8dbe1e6b35821464dc818fc344085f..f098443dd006ea811a75dc89e6ab08a9e5787400 100644 --- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml +++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml @@ -16,7 +16,7 @@ - "دستاویزات" + "فائلیں" "ڈاؤن لوڈز" "کھولیں از" "اس میں محفوظ کریں" diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml index a3e117aa34fb0365adf9fdf3e598530a9b13af4c..a0ac3296678c5b08f0cd869deced3019b788a604 100644 --- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml +++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml @@ -16,7 +16,7 @@ - "Hujjatlar" + "Fayllar" "Yuklanmalar" "Ochish" "Saqlash" @@ -115,7 +115,7 @@ "^1 ilovasiga ^2 xotirasidagi ma’lumotlardan, jumladan, rasmlar va videolardan foydalanishiga ruxsat berilsinmi?" "Boshqa so‘ralmasin" "Ruxsat berish" - "Rad qilish" + "Rad etish" %1$d ta belgilandi %1$d ta belgilandi diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml index 3979535a8c429f330372f22e0d15e929381486df..4e34725e92fee659087f79c012e12ac41b3e1cf5 100644 --- a/packages/DocumentsUI/res/values-vi/strings.xml +++ b/packages/DocumentsUI/res/values-vi/strings.xml @@ -16,7 +16,7 @@ - "Tài liệu" + "Tệp" "Tải xuống" "Mở từ" "Lưu vào" diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml index d11362bc7e02d9a400cbe17bf255d51ac24662aa..80b867c08dca6379aaf2dffc3115dabf73875a0f 100644 --- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml @@ -16,7 +16,7 @@ - "文档" + "文件" "下载" "打开文件" "保存文件" diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml index 971afdcfcaf940294674b9f043028bab3139d041..7984070f003a988f464ecde7295c57ae92b22734 100644 --- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml @@ -16,7 +16,7 @@ - "文件" + "檔案" "下載" "開啟檔案" "儲存至" diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml index 16afeb4eb25f1d98773a5b69ddcbf5d93eb8aae5..0d591ae1218ceb4964c413ce8fec10a5aed2a0ab 100644 --- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml @@ -16,7 +16,7 @@ - "文件" + "檔案" "下載" "開啟檔案" "儲存至" diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml index 925f9899b718ebc758d307421caadf7bbc8ee135..30b8ad16627054a3f65000566841c74c1ee40359 100644 --- a/packages/DocumentsUI/res/values-zu/strings.xml +++ b/packages/DocumentsUI/res/values-zu/strings.xml @@ -16,7 +16,7 @@ - "Amadokhumenti" + "Amafayela" "Okulandiwe" "Vula kusuka ku-" "Londoloza ku-" diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml index cf0643d8ceaa10ae0fc0f931a365067808552566..366a8a42dd18ab0a16d928319ad89e6b0b368914 100644 --- a/packages/DocumentsUI/res/values/colors.xml +++ b/packages/DocumentsUI/res/values/colors.xml @@ -15,9 +15,6 @@ --> - #ffbdbdbd - #ff00796b - @@ -26,22 +23,19 @@ #fff7f7f7 @android:color/transparent - @*android:color/primary_dark_material_dark - @*android:color/material_blue_grey_900 - @*android:color/accent_material_light - @*android:color/accent_material_dark - @color/material_grey_400 - @*android:color/material_blue_grey_950 + @*android:color/primary_dark_device_default_settings + @*android:color/primary_device_default_settings + @*android:color/accent_device_default_light + @*android:color/accent_device_default_dark #88ffffff #44000000 - #fff4f4f4 - - @color/material_teal_700 + @*android:color/accent_device_default_700 #fffafafa - #ffe0f2f1 + #fff4f4f4 + @*android:color/accent_device_default_50 diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml index e67cc8a06da273e8e740b965d7fd02dbab1ee74d..c2d4d04e6aa4a907a2f5a6d63ffa597d39d36132 100644 --- a/packages/DocumentsUI/res/values/strings.xml +++ b/packages/DocumentsUI/res/values/strings.xml @@ -16,7 +16,7 @@ - Documents + Files Downloads diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml index 9f09ebc480e58785e49173afe4190c105887b1df..b5e32d405ac73537358c06a003d3eb2c44cb0327 100644 --- a/packages/DocumentsUI/res/values/styles.xml +++ b/packages/DocumentsUI/res/values/styles.xml @@ -28,9 +28,8 @@ @color/primary_dark @color/primary @color/accent - @color/action_mode + ?android:attr/colorAccent @color/menu_search_background - @color/status_bar_color @*android:drawable/list_divider_material diff --git a/packages/DocumentsUI/src/com/android/documentsui/Events.java b/packages/DocumentsUI/src/com/android/documentsui/Events.java index 14d4e2d942d97f8217c97ec507e86cc6c2aca38e..02a912734239300bcb57ed7324154c43ba9e08a4 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Events.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Events.java @@ -53,7 +53,8 @@ public final class Events { */ public static boolean isTouchType(int toolType) { return toolType == MotionEvent.TOOL_TYPE_FINGER - || toolType == MotionEvent.TOOL_TYPE_STYLUS; + || toolType == MotionEvent.TOOL_TYPE_STYLUS + || toolType == MotionEvent.TOOL_TYPE_UNKNOWN; } /** diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java index b82f8dd3d7a3b6abfda7bb0cffe9761845faf0ff..7186339dbfa621410aba830b0ccd59906343cd57 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java @@ -341,8 +341,18 @@ public class FilesActivity extends BaseActivity { // Fall back to traditional VIEW action... intent = new Intent(Intent.ACTION_VIEW); - intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setData(doc.derivedUri); + intent.setDataAndType(doc.derivedUri, doc.mimeType); + + // Downloads has traditionally added the WRITE permission + // in the TrampolineActivity. Since this behavior is long + // established, we set the same permission for non-managed files + // This ensures consistent behavior between the Downloads root + // and other roots. + int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION; + if (doc.isWriteSupported()) { + flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + } + intent.setFlags(flags); if (DEBUG && intent.getClipData() != null) { Log.d(TAG, "Starting intent w/ clip data: " + intent.getClipData()); diff --git a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java index c28fae85cb8bf399dc806d3a2e0cabb56a74cf89..d87bc11a8495c0f5540163247f1b57ec6f845654 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java +++ b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java @@ -23,181 +23,7 @@ import android.graphics.drawable.Drawable; import android.provider.DocumentsContract.Document; import android.util.TypedValue; -import java.util.HashMap; - public class IconUtils { - - private static HashMap sMimeIcons = new HashMap<>(); - - private static void add(String mimeType, int resId) { - if (sMimeIcons.put(mimeType, resId) != null) { - throw new RuntimeException(mimeType + " already registered!"); - } - } - - static { - int icon; - - // Package - icon = R.drawable.ic_doc_apk; - add("application/vnd.android.package-archive", icon); - - // Audio - icon = R.drawable.ic_doc_audio; - add("application/ogg", icon); - add("application/x-flac", icon); - - // Certificate - icon = R.drawable.ic_doc_certificate; - add("application/pgp-keys", icon); - add("application/pgp-signature", icon); - add("application/x-pkcs12", icon); - add("application/x-pkcs7-certreqresp", icon); - add("application/x-pkcs7-crl", icon); - add("application/x-x509-ca-cert", icon); - add("application/x-x509-user-cert", icon); - add("application/x-pkcs7-certificates", icon); - add("application/x-pkcs7-mime", icon); - add("application/x-pkcs7-signature", icon); - - // Source code - icon = R.drawable.ic_doc_codes; - add("application/rdf+xml", icon); - add("application/rss+xml", icon); - add("application/x-object", icon); - add("application/xhtml+xml", icon); - add("text/css", icon); - add("text/html", icon); - add("text/xml", icon); - add("text/x-c++hdr", icon); - add("text/x-c++src", icon); - add("text/x-chdr", icon); - add("text/x-csrc", icon); - add("text/x-dsrc", icon); - add("text/x-csh", icon); - add("text/x-haskell", icon); - add("text/x-java", icon); - add("text/x-literate-haskell", icon); - add("text/x-pascal", icon); - add("text/x-tcl", icon); - add("text/x-tex", icon); - add("application/x-latex", icon); - add("application/x-texinfo", icon); - add("application/atom+xml", icon); - add("application/ecmascript", icon); - add("application/json", icon); - add("application/javascript", icon); - add("application/xml", icon); - add("text/javascript", icon); - add("application/x-javascript", icon); - - // Compressed - icon = R.drawable.ic_doc_compressed; - add("application/mac-binhex40", icon); - add("application/rar", icon); - add("application/zip", icon); - add("application/x-apple-diskimage", icon); - add("application/x-debian-package", icon); - add("application/x-gtar", icon); - add("application/x-iso9660-image", icon); - add("application/x-lha", icon); - add("application/x-lzh", icon); - add("application/x-lzx", icon); - add("application/x-stuffit", icon); - add("application/x-tar", icon); - add("application/x-webarchive", icon); - add("application/x-webarchive-xml", icon); - add("application/gzip", icon); - add("application/x-7z-compressed", icon); - add("application/x-deb", icon); - add("application/x-rar-compressed", icon); - - // Contact - icon = R.drawable.ic_doc_contact; - add("text/x-vcard", icon); - add("text/vcard", icon); - - // Event - icon = R.drawable.ic_doc_event; - add("text/calendar", icon); - add("text/x-vcalendar", icon); - - // Font - icon = R.drawable.ic_doc_font; - add("application/x-font", icon); - add("application/font-woff", icon); - add("application/x-font-woff", icon); - add("application/x-font-ttf", icon); - - // Image - icon = R.drawable.ic_doc_image; - add("application/vnd.oasis.opendocument.graphics", icon); - add("application/vnd.oasis.opendocument.graphics-template", icon); - add("application/vnd.oasis.opendocument.image", icon); - add("application/vnd.stardivision.draw", icon); - add("application/vnd.sun.xml.draw", icon); - add("application/vnd.sun.xml.draw.template", icon); - - // PDF - icon = R.drawable.ic_doc_pdf; - add("application/pdf", icon); - - // Presentation - icon = R.drawable.ic_doc_presentation; - add("application/vnd.stardivision.impress", icon); - add("application/vnd.sun.xml.impress", icon); - add("application/vnd.sun.xml.impress.template", icon); - add("application/x-kpresenter", icon); - add("application/vnd.oasis.opendocument.presentation", icon); - - // Spreadsheet - icon = R.drawable.ic_doc_spreadsheet; - add("application/vnd.oasis.opendocument.spreadsheet", icon); - add("application/vnd.oasis.opendocument.spreadsheet-template", icon); - add("application/vnd.stardivision.calc", icon); - add("application/vnd.sun.xml.calc", icon); - add("application/vnd.sun.xml.calc.template", icon); - add("application/x-kspread", icon); - - // Document - icon = R.drawable.ic_doc_document; - add("application/vnd.oasis.opendocument.text", icon); - add("application/vnd.oasis.opendocument.text-master", icon); - add("application/vnd.oasis.opendocument.text-template", icon); - add("application/vnd.oasis.opendocument.text-web", icon); - add("application/vnd.stardivision.writer", icon); - add("application/vnd.stardivision.writer-global", icon); - add("application/vnd.sun.xml.writer", icon); - add("application/vnd.sun.xml.writer.global", icon); - add("application/vnd.sun.xml.writer.template", icon); - add("application/x-abiword", icon); - add("application/x-kword", icon); - - // Video - icon = R.drawable.ic_doc_video; - add("application/x-quicktimeplayer", icon); - add("application/x-shockwave-flash", icon); - - // Word - icon = R.drawable.ic_doc_word; - add("application/msword", icon); - add("application/vnd.openxmlformats-officedocument.wordprocessingml.document", icon); - add("application/vnd.openxmlformats-officedocument.wordprocessingml.template", icon); - - // Excel - icon = R.drawable.ic_doc_excel; - add("application/vnd.ms-excel", icon); - add("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", icon); - add("application/vnd.openxmlformats-officedocument.spreadsheetml.template", icon); - - // Powerpoint - icon = R.drawable.ic_doc_powerpoint; - add("application/vnd.ms-powerpoint", icon); - add("application/vnd.openxmlformats-officedocument.presentationml.presentation", icon); - add("application/vnd.openxmlformats-officedocument.presentationml.template", icon); - add("application/vnd.openxmlformats-officedocument.presentationml.slideshow", icon); - } - public static Drawable loadPackageIcon(Context context, String authority, int icon) { if (icon != 0) { if (authority != null) { @@ -216,16 +42,10 @@ public class IconUtils { public static Drawable loadMimeIcon( Context context, String mimeType, String authority, String docId, int mode) { if (Document.MIME_TYPE_DIR.equals(mimeType)) { - // TODO: eventually move these hacky assets into that package - if ("com.android.providers.media.documents".equals(authority) - && docId.startsWith("album")) { - return context.getDrawable(R.drawable.ic_doc_album); - } - if (mode == State.MODE_GRID) { return context.getDrawable(R.drawable.ic_grid_folder); } else { - return context.getDrawable(R.drawable.ic_doc_folder); + return context.getDrawable(com.android.internal.R.drawable.ic_doc_folder); } } @@ -233,34 +53,7 @@ public class IconUtils { } public static Drawable loadMimeIcon(Context context, String mimeType) { - if (Document.MIME_TYPE_DIR.equals(mimeType)) { - return context.getDrawable(R.drawable.ic_doc_folder); - } - - // Look for exact match first - Integer resId = sMimeIcons.get(mimeType); - if (resId != null) { - return context.getDrawable(resId); - } - - if (mimeType == null) { - // TODO: generic icon? - return null; - } - - // Otherwise look for partial match - final String typeOnly = mimeType.split("/")[0]; - if ("audio".equals(typeOnly)) { - return context.getDrawable(R.drawable.ic_doc_audio); - } else if ("image".equals(typeOnly)) { - return context.getDrawable(R.drawable.ic_doc_image); - } else if ("text".equals(typeOnly)) { - return context.getDrawable(R.drawable.ic_doc_text); - } else if ("video".equals(typeOnly)) { - return context.getDrawable(R.drawable.ic_doc_video); - } else { - return context.getDrawable(R.drawable.ic_doc_generic); - } + return context.getContentResolver().getTypeDrawable(mimeType); } public static Drawable applyTintColor(Context context, int drawableId, int tintColorId) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java index af6aee759eec56654ecaaad0492da735925a885c..5e3bbbb86486176f796703231a19b2d8fc28b12a 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java @@ -28,6 +28,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; import android.support.annotation.Nullable; @@ -73,7 +74,7 @@ final class QuickViewIntentBuilder { @Nullable Intent build() { if (DEBUG) Log.d(TAG, "Preparing intent for doc:" + mDocument.documentId); - String trustedPkg = mResources.getString(R.string.trusted_quick_viewer_package); + String trustedPkg = getQuickViewPackage(); if (!TextUtils.isEmpty(trustedPkg)) { Intent intent = new Intent(Intent.ACTION_QUICK_VIEW); @@ -116,6 +117,16 @@ final class QuickViewIntentBuilder { return null; } + private String getQuickViewPackage() { + String resValue = mResources.getString(R.string.trusted_quick_viewer_package); + if (Build.IS_DEBUGGABLE ) { + // Allow users of debug devices to override default quick viewer + // for the purposes of testing. + return android.os.SystemProperties.get("debug.quick_viewer", resValue); + } + return resValue; + } + private int collectViewableUris(ArrayList uris) { final String[] siblingIds = mModel.getModelIds(); uris.ensureCapacity(siblingIds.length); diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java index cebc9b05679e6d480bd376689f859130d5d10666..557a2f6abc9f325af008f90b5c949f3c3c3987a1 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsLoader.java @@ -157,6 +157,9 @@ public class RecentsLoader extends AsyncTaskLoader { throw new RuntimeException(e); } catch (ExecutionException e) { // We already logged on other side + } catch (Exception e) { + Log.e(TAG, "Failed to query Recents for authority: " + task.authority + + ". Skip this authority in Recents.", e); } } else { allDone = false; diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java index d830c61f30e711a730db05adf9a501634ce9f822..a37590d2e0a6c75769bb5a40e694cdcb6df16dd5 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java @@ -22,6 +22,7 @@ import android.app.FragmentTransaction; import android.content.Context; import android.os.Bundle; import android.text.Editable; +import android.text.TextUtils; import android.text.TextWatcher; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -91,6 +92,14 @@ public class SaveFragment extends Fragment { return false; } + // Returning false in this method will bubble the event up to + // {@link BaseActivity#onKeyDown}. In order to prevent backspace popping + // documents once the textView is empty, we are going to trap it here. + if (keyCode == KeyEvent.KEYCODE_DEL + && TextUtils.isEmpty(mDisplayName.getText())) { + return true; + } + if (keyCode == KeyEvent.KEYCODE_ENTER && mSave.isEnabled()) { performSave(); return true; diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java index 870c3439b8a9f6886fa3ec68dff870a23fbbbd5e..8a6723f6cd34a06cb33ed3911dc857ddaa6fb412 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -53,10 +53,13 @@ import android.provider.DocumentsContract.Document; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v13.view.DragStartHelper; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager.SpanSizeLookup; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.OnItemTouchListener; +import android.support.v7.widget.RecyclerView.Recycler; import android.support.v7.widget.RecyclerView.RecyclerListener; import android.support.v7.widget.RecyclerView.ViewHolder; import android.text.BidiFormatter; @@ -243,7 +246,40 @@ public class DirectoryFragment extends Fragment mRecView.setAdapter(mAdapter); - mLayout = new GridLayoutManager(getContext(), mColumnCount); + // Switch Access Accessibility API needs an {@link AccessibilityDelegate} to know the proper + // route when user selects an UI element. It usually guesses this if the element has an + // {@link OnClickListener}, but since we do not have one for itemView, we will need to + // manually route it to the right behavior. RecyclerView has its own AccessibilityDelegate, + // and routes it to its LayoutManager; so we must override the LayoutManager's accessibility + // methods to route clicks correctly. + mLayout = new GridLayoutManager(getContext(), mColumnCount) { + @Override + public void onInitializeAccessibilityNodeInfoForItem( + RecyclerView.Recycler recycler, RecyclerView.State state, + View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfoForItem(recycler, state, host, info); + info.addAction(AccessibilityActionCompat.ACTION_CLICK); + } + + @Override + public boolean performAccessibilityActionForItem( + RecyclerView.Recycler recycler, RecyclerView.State state, View view, + int action, Bundle args) { + // We are only handling click events; route all other to default implementation + if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) { + RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(view); + if (vh instanceof DocumentHolder) { + DocumentHolder dh = (DocumentHolder) vh; + if (dh.mEventListener != null) { + dh.mEventListener.onActivate(dh); + return true; + } + } + } + return super.performAccessibilityActionForItem(recycler, state, view, action, + args); + } + }; SpanSizeLookup lookup = mAdapter.createSpanSizeLookup(); if (lookup != null) { mLayout.setSpanSizeLookup(lookup); @@ -664,10 +700,10 @@ public class DirectoryFragment extends Fragment return true; case R.id.menu_copy_to: - transferDocuments(selection, FileOperationService.OPERATION_COPY); // TODO: Only finish selection mode if copy-to is not canceled. // Need to plum down into handling the way we do with deleteDocuments. mode.finish(); + transferDocuments(selection, FileOperationService.OPERATION_COPY); return true; case R.id.menu_move_to: @@ -717,63 +753,57 @@ public class DirectoryFragment extends Fragment private void openDocuments(final Selection selected) { Metrics.logUserAction(getContext(), Metrics.USER_ACTION_OPEN); - new GetDocumentsTask() { - @Override - void onDocumentsReady(List docs) { - // TODO: Implement support in Files activity for opening multiple docs. - BaseActivity.get(DirectoryFragment.this).onDocumentsPicked(docs); - } - }.execute(selected); + // Model must be accessed in UI thread, since underlying cursor is not threadsafe. + List docs = mModel.getDocuments(selected); + // TODO: Implement support in Files activity for opening multiple docs. + BaseActivity.get(DirectoryFragment.this).onDocumentsPicked(docs); } private void shareDocuments(final Selection selected) { Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SHARE); - new GetDocumentsTask() { - @Override - void onDocumentsReady(List docs) { - Intent intent; - - // Filter out directories and virtual files - those can't be shared. - List docsForSend = new ArrayList<>(); - for (DocumentInfo doc: docs) { - if (!doc.isDirectory() && !doc.isVirtualDocument()) { - docsForSend.add(doc); - } - } + // Model must be accessed in UI thread, since underlying cursor is not threadsafe. + List docs = mModel.getDocuments(selected); + Intent intent; - if (docsForSend.size() == 1) { - final DocumentInfo doc = docsForSend.get(0); - - intent = new Intent(Intent.ACTION_SEND); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.setType(doc.mimeType); - intent.putExtra(Intent.EXTRA_STREAM, doc.derivedUri); - - } else if (docsForSend.size() > 1) { - intent = new Intent(Intent.ACTION_SEND_MULTIPLE); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.addCategory(Intent.CATEGORY_DEFAULT); - - final ArrayList mimeTypes = new ArrayList<>(); - final ArrayList uris = new ArrayList<>(); - for (DocumentInfo doc : docsForSend) { - mimeTypes.add(doc.mimeType); - uris.add(doc.derivedUri); - } + // Filter out directories and virtual files - those can't be shared. + List docsForSend = new ArrayList<>(); + for (DocumentInfo doc: docs) { + if (!doc.isDirectory() && !doc.isVirtualDocument()) { + docsForSend.add(doc); + } + } - intent.setType(findCommonMimeType(mimeTypes)); - intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + if (docsForSend.size() == 1) { + final DocumentInfo doc = docsForSend.get(0); - } else { - return; - } + intent = new Intent(Intent.ACTION_SEND); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setType(doc.mimeType); + intent.putExtra(Intent.EXTRA_STREAM, doc.derivedUri); - intent = Intent.createChooser(intent, getActivity().getText(R.string.share_via)); - startActivity(intent); + } else if (docsForSend.size() > 1) { + intent = new Intent(Intent.ACTION_SEND_MULTIPLE); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.addCategory(Intent.CATEGORY_DEFAULT); + + final ArrayList mimeTypes = new ArrayList<>(); + final ArrayList uris = new ArrayList<>(); + for (DocumentInfo doc : docsForSend) { + mimeTypes.add(doc.mimeType); + uris.add(doc.derivedUri); } - }.execute(selected); + + intent.setType(findCommonMimeType(mimeTypes)); + intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + + } else { + return; + } + + intent = Intent.createChooser(intent, getActivity().getText(R.string.share_via)); + startActivity(intent); } private String generateDeleteMessage(final List docs) { @@ -819,52 +849,51 @@ public class DirectoryFragment extends Fragment assert(!selected.isEmpty()); final DocumentInfo srcParent = getDisplayState().stack.peek(); - new GetDocumentsTask() { - @Override - void onDocumentsReady(final List docs) { - - TextView message = - (TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null); - message.setText(generateDeleteMessage(docs)); - - // This "insta-hides" files that are being deleted, because - // the delete operation may be not execute immediately (it - // may be queued up on the FileOperationService.) - // To hide the files locally, we call the hide method on the adapter - // ...which a live object...cannot be parceled. - // For that reason, for now, we implement this dialog NOT - // as a fragment (which can survive rotation and have its own state), - // but as a simple runtime dialog. So rotating a device with an - // active delete dialog...results in that dialog disappearing. - // We can do better, but don't have cycles for it now. - new AlertDialog.Builder(getActivity()) - .setView(message) - .setPositiveButton( - android.R.string.yes, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - // Finish selection mode first which clears selection so we - // don't end up trying to deselect deleted documents. - // This is done here, rather in the onActionItemClicked - // so we can avoid de-selecting items in the case where - // the user cancels the delete. - if (mActionMode != null) { - mActionMode.finish(); - } else { - Log.w(TAG, "Action mode is null before deleting documents."); - } - // Hide the files in the UI...since the operation - // might be queued up on FileOperationService. - // We're walking a line here. - mAdapter.hide(selected.getAll()); - FileOperations.delete( - getActivity(), docs, srcParent, getDisplayState().stack); - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); - } - }.execute(selected); + + // Model must be accessed in UI thread, since underlying cursor is not threadsafe. + List docs = mModel.getDocuments(selected); + + TextView message = + (TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null); + message.setText(generateDeleteMessage(docs)); + + // This "insta-hides" files that are being deleted, because + // the delete operation may be not execute immediately (it + // may be queued up on the FileOperationService.) + // To hide the files locally, we call the hide method on the adapter + // ...which a live object...cannot be parceled. + // For that reason, for now, we implement this dialog NOT + // as a fragment (which can survive rotation and have its own state), + // but as a simple runtime dialog. So rotating a device with an + // active delete dialog...results in that dialog disappearing. + // We can do better, but don't have cycles for it now. + new AlertDialog.Builder(getActivity()) + .setView(message) + .setPositiveButton( + android.R.string.yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + // Finish selection mode first which clears selection so we + // don't end up trying to deselect deleted documents. + // This is done here, rather in the onActionItemClicked + // so we can avoid de-selecting items in the case where + // the user cancels the delete. + if (mActionMode != null) { + mActionMode.finish(); + } else { + Log.w(TAG, "Action mode is null before deleting documents."); + } + // Hide the files in the UI...since the operation + // might be queued up on FileOperationService. + // We're walking a line here. + mAdapter.hide(selected.getAll()); + FileOperations.delete( + getActivity(), docs, srcParent, getDisplayState().stack); + } + }) + .setNegativeButton(android.R.string.no, null) + .show(); } private void transferDocuments(final Selection selected, final @OpType int mode) { @@ -898,25 +927,21 @@ public class DirectoryFragment extends Fragment ? R.string.menu_move : R.string.menu_copy; intent.putExtra(DocumentsContract.EXTRA_PROMPT, getResources().getString(drawerTitleId)); - new GetDocumentsTask() { - @Override - void onDocumentsReady(List docs) { - // TODO: Can this move to Fragment bundle state? - getDisplayState().selectedDocumentsForCopy = docs; - - // Determine if there is a directory in the set of documents - // to be copied? Why? Directory creation isn't supported by some roots - // (like Downloads). This informs DocumentsActivity (the "picker") - // to restrict available roots to just those with support. - intent.putExtra(Shared.EXTRA_DIRECTORY_COPY, hasDirectory(docs)); - intent.putExtra(FileOperationService.EXTRA_OPERATION, mode); - - // This just identifies the type of request...we'll check it - // when we reveive a response. - startActivityForResult(intent, REQUEST_COPY_DESTINATION); - } + // Model must be accessed in UI thread, since underlying cursor is not threadsafe. + List docs = mModel.getDocuments(selected); + // TODO: Can this move to Fragment bundle state? + getDisplayState().selectedDocumentsForCopy = docs; + + // Determine if there is a directory in the set of documents + // to be copied? Why? Directory creation isn't supported by some roots + // (like Downloads). This informs DocumentsActivity (the "picker") + // to restrict available roots to just those with support. + intent.putExtra(Shared.EXTRA_DIRECTORY_COPY, hasDirectory(docs)); + intent.putExtra(FileOperationService.EXTRA_OPERATION, mode); - }.execute(selected); + // This just identifies the type of request...we'll check it + // when we reveive a response. + startActivityForResult(intent, REQUEST_COPY_DESTINATION); } private static boolean hasDirectory(List docs) { @@ -935,12 +960,9 @@ public class DirectoryFragment extends Fragment // Rename option is only available in menu when 1 document selected assert(selected.size() == 1); - new GetDocumentsTask() { - @Override - void onDocumentsReady(List docs) { - RenameDocumentFragment.show(getFragmentManager(), docs.get(0)); - } - }.execute(selected); + // Model must be accessed in UI thread, since underlying cursor is not threadsafe. + List docs = mModel.getDocuments(selected); + RenameDocumentFragment.show(getFragmentManager(), docs.get(0)); } @Override @@ -1099,19 +1121,17 @@ public class DirectoryFragment extends Fragment } } - void copySelectionToClipboard(Selection selection) { - assert(!selection.isEmpty()); - new GetDocumentsTask() { - @Override - void onDocumentsReady(List docs) { - mClipper.clipDocuments(docs); - Activity activity = getActivity(); - Snackbars.makeSnackbar(activity, - activity.getResources().getQuantityString( - R.plurals.clipboard_files_clipped, docs.size(), docs.size()), - Snackbar.LENGTH_SHORT).show(); - } - }.execute(selection); + void copySelectionToClipboard(Selection selected) { + assert(!selected.isEmpty()); + + // Model must be accessed in UI thread, since underlying cursor is not threadsafe. + List docs = mModel.getDocuments(selected); + mClipper.clipDocuments(docs); + Activity activity = getActivity(); + Snackbars.makeSnackbar(activity, + activity.getResources().getQuantityString( + R.plurals.clipboard_files_clipped, docs.size(), docs.size()), + Snackbar.LENGTH_SHORT).show(); } public void pasteFromClipboard() { @@ -1391,7 +1411,7 @@ public class DirectoryFragment extends Fragment return mIconHelper.getDocumentIcon(mContext, doc.authority, doc.documentId, doc.mimeType, doc.icon); } - return mContext.getDrawable(R.drawable.ic_doc_generic); + return mContext.getDrawable(com.android.internal.R.drawable.ic_doc_generic); } private String getTitle(List docs) { @@ -1420,25 +1440,6 @@ public class DirectoryFragment extends Fragment mShadowView.draw(canvas); } } - /** - * Abstract task providing support for loading documents *off* - * the main thread. And if it isn't obvious, creating a list - * of documents (especially large lists) can be pretty expensive. - */ - private abstract class GetDocumentsTask - extends AsyncTask> { - @Override - protected final List doInBackground(Selection... selected) { - return mModel.getDocuments(selected[0]); - } - - @Override - protected final void onPostExecute(List docs) { - onDocumentsReady(docs); - } - - abstract void onDocumentsReady(List docs); - } @Override public boolean isSelected(String modelId) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java index 0a2960f8ffe0497267750bbe8eb6aca3de759514..94b8277f4eddc0b14d0d4e880d60760501a27483 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java @@ -107,7 +107,13 @@ public class Model { mSortOrder = result.sortOrder; doc = result.doc; - updateModelData(); + try { + updateModelData(); + } catch (Exception e) { + Log.e(TAG, "Error while accessing cursors", e); + notifyUpdateListeners(e); + return; + } final Bundle extras = mCursor.getExtras(); if (extras != null) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java index 3a86a51b2d1886595b7fb762d0497096623ae77a..63f66de9ad842718ac06b3f139eb2af200c26997 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java @@ -235,6 +235,10 @@ public class DocumentInfo implements Durable, Parcelable { return (flags & Document.FLAG_DIR_PREFERS_GRID) != 0; } + public boolean isWriteSupported() { + return (flags & Document.FLAG_SUPPORTS_WRITE) != 0; + } + public boolean isDeleteSupported() { return (flags & Document.FLAG_SUPPORTS_DELETE) != 0; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java index d54bdfd580ebeec1e98069d5e98a930e2a43a673..649dde049fc48a67498131b784c5e780a96d5185 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java @@ -213,13 +213,13 @@ public class RootInfo implements Durable, Parcelable, Comparable { derivedIcon = R.drawable.ic_root_download; } else if (isImages()) { derivedType = TYPE_IMAGES; - derivedIcon = R.drawable.ic_doc_image; + derivedIcon = com.android.internal.R.drawable.ic_doc_image; } else if (isVideos()) { derivedType = TYPE_VIDEO; - derivedIcon = R.drawable.ic_doc_video; + derivedIcon = com.android.internal.R.drawable.ic_doc_video; } else if (isAudio()) { derivedType = TYPE_AUDIO; - derivedIcon = R.drawable.ic_doc_audio; + derivedIcon = com.android.internal.R.drawable.ic_doc_audio; } else if (isRecents()) { derivedType = TYPE_RECENTS; } else { diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java index 111817132fa1db289ad230a2427735a725dfa51d..1de3bbc204965572dd4ef29e813c0762e84c28a9 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java +++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java @@ -117,7 +117,9 @@ final class MoveJob extends CopyJob { byteCopyDocument(src, dest); // Remove the source document. - deleteDocument(src, srcParent); + if(!isCanceled()) { + deleteDocument(src, srcParent); + } } @Override diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml index 50e8b5ca7d2bdeddebafb4337014f724aa6ac09b..fbc2386576471a6343aa797696cf8f9a8e2b634e 100644 --- a/packages/EasterEgg/AndroidManifest.xml +++ b/packages/EasterEgg/AndroidManifest.xml @@ -31,6 +31,7 @@ Copyright (C) 2016 The Android Open Source Project android:label="@string/app_name"> + diff --git a/packages/EasterEgg/res/drawable/collar.xml b/packages/EasterEgg/res/drawable/collar.xml index 6c0d90a9bf224c55e5eebc3471f99cbe459c4b4c..5e4d0fd4f8865d30538fd33f44fdb84bdbdec92b 100644 --- a/packages/EasterEgg/res/drawable/collar.xml +++ b/packages/EasterEgg/res/drawable/collar.xml @@ -18,5 +18,5 @@ Copyright (C) 2016 The Android Open Source Project android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> - + diff --git a/packages/EasterEgg/res/drawable/leg1.xml b/packages/EasterEgg/res/drawable/leg1.xml index 625733318e72b977326638ead78e4956f36e54a6..d72c746b62322b43e4b992d851f62b9499374bd5 100644 --- a/packages/EasterEgg/res/drawable/leg1.xml +++ b/packages/EasterEgg/res/drawable/leg1.xml @@ -18,5 +18,5 @@ Copyright (C) 2016 The Android Open Source Project android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> - + diff --git a/packages/EasterEgg/res/drawable/leg2.xml b/packages/EasterEgg/res/drawable/leg2.xml index 73352f69e80a9eaac03eba444f0a478478cde5a8..a772a870af7d18aae25d884371be10562dc0c461 100644 --- a/packages/EasterEgg/res/drawable/leg2.xml +++ b/packages/EasterEgg/res/drawable/leg2.xml @@ -18,5 +18,5 @@ Copyright (C) 2016 The Android Open Source Project android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> - + diff --git a/packages/EasterEgg/res/drawable/leg2_shadow.xml b/packages/EasterEgg/res/drawable/leg2_shadow.xml index 77f4893194fe3c7b36702884bed578379c024260..b01bd6995c0b1296d7ae48757c7f127db2e0fd0a 100644 --- a/packages/EasterEgg/res/drawable/leg2_shadow.xml +++ b/packages/EasterEgg/res/drawable/leg2_shadow.xml @@ -18,5 +18,5 @@ Copyright (C) 2016 The Android Open Source Project android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> - + diff --git a/packages/EasterEgg/res/drawable/leg3.xml b/packages/EasterEgg/res/drawable/leg3.xml index 53dea5c2becf4d42432452b8ec08917d827f0c07..d471236687b5829de66ffc93f00b61c5c2c3d9bf 100644 --- a/packages/EasterEgg/res/drawable/leg3.xml +++ b/packages/EasterEgg/res/drawable/leg3.xml @@ -18,5 +18,5 @@ Copyright (C) 2016 The Android Open Source Project android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> - + diff --git a/packages/EasterEgg/res/drawable/leg4.xml b/packages/EasterEgg/res/drawable/leg4.xml index f2ce73e195a29c21200a97ac9c6203342bc5b919..e5868eb80c5986db89dd7e126e6b8b8e5727915e 100644 --- a/packages/EasterEgg/res/drawable/leg4.xml +++ b/packages/EasterEgg/res/drawable/leg4.xml @@ -18,5 +18,5 @@ Copyright (C) 2016 The Android Open Source Project android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> - + diff --git a/packages/EasterEgg/res/layout/cat_view.xml b/packages/EasterEgg/res/layout/cat_view.xml index 82ced2f240b531cca5a0315d51f0caae42cde864..85b494d2e68d3a251208205113d430391c28b9f8 100644 --- a/packages/EasterEgg/res/layout/cat_view.xml +++ b/packages/EasterEgg/res/layout/cat_view.xml @@ -20,12 +20,14 @@ android:minHeight="?android:attr/listPreferredItemHeightSmall" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:paddingTop="8dp" + android:paddingBottom="8dp" android:background="?android:attr/selectableItemBackgroundBorderless" android:gravity="center_horizontal" android:clipToPadding="false"> + + + 64dp + diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml index a2440c7bc786646849dd6831ad0236413e596c6c..8478a438a0e482a15dee7b113a1bda4d91ae8c3f 100644 --- a/packages/EasterEgg/res/values/strings.xml +++ b/packages/EasterEgg/res/values/strings.xml @@ -21,6 +21,7 @@ Copyright (C) 2016 The Android Open Source Project A cat is here. Cat #%s Cats + Forget %s? Empty dish Bits diff --git a/packages/EasterEgg/src/com/android/egg/neko/Cat.java b/packages/EasterEgg/src/com/android/egg/neko/Cat.java index 864b20c73fbfec6351bacfb47f20c8991f536c1c..a4df372ef835c52e6b93d15400b31f8f0069ba87 100644 --- a/packages/EasterEgg/src/com/android/egg/neko/Cat.java +++ b/packages/EasterEgg/src/com/android/egg/neko/Cat.java @@ -24,10 +24,12 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.os.Bundle; +import java.io.ByteArrayOutputStream; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import com.android.egg.R; +import com.android.internal.logging.MetricsLogger; public class Cat extends Drawable { public static final long[] PURR = {0, 40, 20, 40, 20, 40, 20, 40, 20, 40, 20, 40}; @@ -37,6 +39,8 @@ public class Cat extends Drawable { private long mSeed; private String mName; private int mBodyColor; + private int mFootType; + private boolean mBowTie; private synchronized Random notSoRandom(long seed) { if (mNotSoRandom == null) { @@ -66,6 +70,15 @@ public class Cat extends Drawable { return a[i+1]; } + public static final int getColorIndex(int q, int[] a) { + for(int i = 1; i < a.length; i+=2) { + if (a[i] == q) { + return i/2; + } + } + return -1; + } + public static final int[] P_BODY_COLORS = { 180, 0xFF212121, // black 180, 0xFFFFFFFF, // white @@ -130,7 +143,7 @@ public class Cat extends Drawable { mSeed = seed; setName(context.getString(R.string.default_cat_name, - String.valueOf(mSeed).substring(0, 3))); + String.valueOf(mSeed % 1000))); final Random nsr = notSoRandom(seed); @@ -155,14 +168,19 @@ public class Cat extends Drawable { tint(0xFF000000, D.mouth, D.nose); } + mFootType = 0; if (nsr.nextFloat() < 0.25f) { + mFootType = 4; tint(0xFFFFFFFF, D.foot1, D.foot2, D.foot3, D.foot4); } else { if (nsr.nextFloat() < 0.25f) { - tint(0xFFFFFFFF, D.foot1, D.foot2); + mFootType = 2; + tint(0xFFFFFFFF, D.foot1, D.foot3); } else if (nsr.nextFloat() < 0.25f) { - tint(0xFFFFFFFF, D.foot3, D.foot4); + mFootType = 3; // maybe -2 would be better? meh. + tint(0xFFFFFFFF, D.foot2, D.foot4); } else if (nsr.nextFloat() < 0.1f) { + mFootType = 1; tint(0xFFFFFFFF, (Drawable) choose(nsr, D.foot1, D.foot2, D.foot3, D.foot4)); } } @@ -175,7 +193,8 @@ public class Cat extends Drawable { final int collarColor = chooseP(nsr, P_COLLAR_COLORS); tint(collarColor, D.collar); - tint((nsr.nextFloat() < 0.1f) ? collarColor : 0, D.bowtie); + mBowTie = nsr.nextFloat() < 0.1f; + tint(mBowTie ? collarColor : 0, D.bowtie); } public static Cat create(Context context) { @@ -190,7 +209,7 @@ public class Cat extends Drawable { .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return new Notification.Builder(context) .setSmallIcon(Icon.createWithResource(context, R.drawable.stat_icon)) - .setLargeIcon(createLargeIcon(context)) + .setLargeIcon(createNotificationLargeIcon(context)) .setColor(getBodyColor()) .setPriority(Notification.PRIORITY_LOW) .setContentTitle(context.getString(R.string.notification_title)) @@ -240,11 +259,24 @@ public class Cat extends Drawable { return result; } - public Icon createLargeIcon(Context context) { + public static Icon recompressIcon(Icon bitmapIcon) { + if (bitmapIcon.getType() != Icon.TYPE_BITMAP) return bitmapIcon; + final Bitmap bits = bitmapIcon.getBitmap(); + final ByteArrayOutputStream ostream = new ByteArrayOutputStream( + bits.getWidth() * bits.getHeight() * 2); // guess 50% compression + final boolean ok = bits.compress(Bitmap.CompressFormat.PNG, 100, ostream); + if (!ok) return null; + return Icon.createWithData(ostream.toByteArray(), 0, ostream.size()); + } + + public Icon createNotificationLargeIcon(Context context) { final Resources res = context.getResources(); - final int w = res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width); - final int h = res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height); + final int w = 2*res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width); + final int h = 2*res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height); + return recompressIcon(createIcon(context, w, h)); + } + public Icon createIcon(Context context, int w, int h) { Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(result); final Paint pt = new Paint(); @@ -290,6 +322,30 @@ public class Cat extends Drawable { return mBodyColor; } + public void logAdd(Context context) { + logCatAction(context, "egg_neko_add"); + } + + public void logRename(Context context) { + logCatAction(context, "egg_neko_rename"); + } + + public void logRemove(Context context) { + logCatAction(context, "egg_neko_remove"); + } + + public void logShare(Context context) { + logCatAction(context, "egg_neko_share"); + } + + private void logCatAction(Context context, String prefix) { + MetricsLogger.count(context, prefix, 1); + MetricsLogger.histogram(context, prefix +"_color", + getColorIndex(mBodyColor, P_BODY_COLORS)); + MetricsLogger.histogram(context, prefix + "_bowtie", mBowTie ? 1 : 0); + MetricsLogger.histogram(context, prefix + "_feet", mFootType); + } + public static class CatParts { public Drawable leftEar; public Drawable rightEar; diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java b/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java index 88a7968da16cca97fe697c6e37a5afbf59e925fe..c0b725c058997310db8d4114e8d86a75a5c580de 100644 --- a/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java +++ b/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java @@ -20,6 +20,8 @@ import android.content.pm.PackageManager; import android.util.Log; import android.widget.Toast; +import com.android.internal.logging.MetricsLogger; + public class NekoActivationActivity extends Activity { private void toastUp(String s) { Toast toast = Toast.makeText(this, s, Toast.LENGTH_SHORT); @@ -39,6 +41,7 @@ public class NekoActivationActivity extends Activity { } pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + MetricsLogger.histogram(this, "egg_neko_enable", 0); toastUp("\uD83D\uDEAB"); } else { if (NekoLand.DEBUG) { @@ -46,6 +49,7 @@ public class NekoActivationActivity extends Activity { } pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + MetricsLogger.histogram(this, "egg_neko_enable", 1); toastUp("\uD83D\uDC31"); } finish(); diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java b/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java index a2ffd3e21887a589b281de0a00a6d93ee049bd3b..2d2fbe8207af56dd6d7c9c7e24da8a68a41f6d43 100644 --- a/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java +++ b/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java @@ -26,6 +26,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.android.egg.R; +import com.android.internal.logging.MetricsLogger; import java.util.ArrayList; @@ -51,6 +52,7 @@ public class NekoDialog extends Dialog { if (currentState == 0 && food.getType() != 0) { NekoService.registerJob(getContext(), food.getInterval(getContext())); } + MetricsLogger.histogram(getContext(), "egg_neko_offered_food", food.getType()); prefs.setFoodState(food.getType()); dismiss(); } diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java index e6a41774f3cb91273c65e1dcffd9aab662c05ae5..f59f0d97d24b783e0ff9737e2b8bfc83ce8e1629 100644 --- a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java +++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java @@ -24,6 +24,7 @@ import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; +import android.graphics.Color; import android.graphics.drawable.Drawable; import android.media.MediaScannerConnection; import android.net.Uri; @@ -44,16 +45,22 @@ import android.widget.TextView; import com.android.egg.R; import com.android.egg.neko.PrefState.PrefsListener; +import com.android.internal.logging.MetricsLogger; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; public class NekoLand extends Activity implements PrefsListener { public static boolean DEBUG = false; public static boolean DEBUG_NOTIFICATIONS = false; + private static final int EXPORT_BITMAP_SIZE = 600; + private static final int STORAGE_PERM_REQUEST = 123; private static boolean CAT_GEN = false; @@ -79,7 +86,8 @@ public class NekoLand extends Activity implements PrefsListener { mAdapter = new CatAdapter(); recyclerView.setAdapter(mAdapter); recyclerView.setLayoutManager(new GridLayoutManager(this, 3)); - updateCats(); + int numCats = updateCats(); + MetricsLogger.histogram(this, "egg_neko_visit_gallery", numCats); } @Override @@ -88,7 +96,7 @@ public class NekoLand extends Activity implements PrefsListener { mPrefs.setListener(null); } - private void updateCats() { + private int updateCats() { Cat[] cats; if (CAT_GEN) { cats = new Cat[50]; @@ -96,9 +104,22 @@ public class NekoLand extends Activity implements PrefsListener { cats[i] = Cat.create(this); } } else { - cats = mPrefs.getCats().toArray(new Cat[0]); + final float[] hsv = new float[3]; + List list = mPrefs.getCats(); + Collections.sort(list, new Comparator() { + @Override + public int compare(Cat cat, Cat cat2) { + Color.colorToHSV(cat.getBodyColor(), hsv); + float bodyH1 = hsv[0]; + Color.colorToHSV(cat2.getBodyColor(), hsv); + float bodyH2 = hsv[0]; + return Float.compare(bodyH1, bodyH2); + } + }); + cats = list.toArray(new Cat[0]); } mAdapter.setCats(cats); + return cats.length; } private void onCatClick(Cat cat) { @@ -115,18 +136,21 @@ public class NekoLand extends Activity implements PrefsListener { } private void onCatRemove(Cat cat) { + cat.logRemove(this); mPrefs.removeCat(cat); } private void showNameDialog(final Cat cat) { - Context context = new ContextThemeWrapper(this, + final Context context = new ContextThemeWrapper(this, android.R.style.Theme_Material_Light_Dialog_NoActionBar); // TODO: Move to XML, add correct margins. View view = LayoutInflater.from(context).inflate(R.layout.edit_text, null); final EditText text = (EditText) view.findViewById(android.R.id.edit); text.setText(cat.getName()); text.setSelection(cat.getName().length()); - Drawable catIcon = cat.createLargeIcon(this).loadDrawable(this); + final int size = context.getResources() + .getDimensionPixelSize(android.R.dimen.app_icon_size); + Drawable catIcon = cat.createIcon(this, size, size).loadDrawable(this); new AlertDialog.Builder(context) .setTitle(" ") .setIcon(catIcon) @@ -134,6 +158,7 @@ public class NekoLand extends Activity implements PrefsListener { .setPositiveButton(android.R.string.ok, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { + cat.logRename(context); cat.setName(text.getText().toString().trim()); mPrefs.addCat(cat); } @@ -160,10 +185,36 @@ public class NekoLand extends Activity implements PrefsListener { .inflate(R.layout.cat_view, parent, false)); } + private void setContextGroupVisible(final CatHolder holder, boolean vis) { + final View group = holder.contextGroup; + if (vis && group.getVisibility() != View.VISIBLE) { + group.setAlpha(0); + group.setVisibility(View.VISIBLE); + group.animate().alpha(1.0f).setDuration(333); + Runnable hideAction = new Runnable() { + @Override + public void run() { + setContextGroupVisible(holder, false); + } + }; + group.setTag(hideAction); + group.postDelayed(hideAction, 5000); + } else if (!vis && group.getVisibility() == View.VISIBLE) { + group.removeCallbacks((Runnable) group.getTag()); + group.animate().alpha(0f).setDuration(250).withEndAction(new Runnable() { + @Override + public void run() { + group.setVisibility(View.INVISIBLE); + } + }); + } + } + @Override public void onBindViewHolder(final CatHolder holder, int position) { Context context = holder.itemView.getContext(); - holder.imageView.setImageIcon(mCats[position].createLargeIcon(context)); + final int size = context.getResources().getDimensionPixelSize(R.dimen.neko_display_size); + holder.imageView.setImageIcon(mCats[position].createIcon(context, size, size)); holder.textView.setText(mCats[position].getName()); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override @@ -174,30 +225,30 @@ public class NekoLand extends Activity implements PrefsListener { holder.itemView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { - holder.contextGroup.removeCallbacks((Runnable) holder.contextGroup.getTag()); - holder.contextGroup.setVisibility(View.VISIBLE); - Runnable hideAction = new Runnable() { - @Override - public void run() { - holder.contextGroup.setVisibility(View.INVISIBLE); - } - }; - holder.contextGroup.setTag(hideAction); - holder.contextGroup.postDelayed(hideAction, 5000); + setContextGroupVisible(holder, true); return true; } }); holder.delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - holder.contextGroup.setVisibility(View.INVISIBLE); - holder.contextGroup.removeCallbacks((Runnable) holder.contextGroup.getTag()); - onCatRemove(mCats[holder.getAdapterPosition()]); + setContextGroupVisible(holder, false); + new AlertDialog.Builder(NekoLand.this) + .setTitle(getString(R.string.confirm_delete, mCats[position].getName())) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onCatRemove(mCats[holder.getAdapterPosition()]); + } + }) + .show(); } }); holder.share.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + setContextGroupVisible(holder, false); Cat cat = mCats[holder.getAdapterPosition()]; if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { @@ -227,7 +278,7 @@ public class NekoLand extends Activity implements PrefsListener { return; } final File png = new File(dir, cat.getName().replaceAll("[/ #:]+", "_") + ".png"); - Bitmap bitmap = cat.createBitmap(512, 512); + Bitmap bitmap = cat.createBitmap(EXPORT_BITMAP_SIZE, EXPORT_BITMAP_SIZE); if (bitmap != null) { try { OutputStream os = new FileOutputStream(png); @@ -244,6 +295,7 @@ public class NekoLand extends Activity implements PrefsListener { intent.putExtra(Intent.EXTRA_SUBJECT, cat.getName()); intent.setType("image/png"); startActivity(Intent.createChooser(intent, null)); + cat.logShare(this); } catch (IOException e) { Log.e("NekoLand", "save: error: " + e); } diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java index 1ee385136f4725dc2e56024b237d520ac6255f81..808ec361fb4f059bb676a17387933bce23d50a3f 100644 --- a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java +++ b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java @@ -82,6 +82,7 @@ public class NekoService extends JobService { if (cats.size() == 0 || rng.nextFloat() <= new_cat_prob) { cat = Cat.create(this); prefs.addCat(cat); + cat.logAdd(this); Log.v(TAG, "A new cat is here: " + cat.getName()); } else { cat = cats.get(rng.nextInt(cats.size())); @@ -101,6 +102,14 @@ public class NekoService extends JobService { return false; } + public static void registerJobIfNeeded(Context context, long intervalMinutes) { + JobScheduler jss = context.getSystemService(JobScheduler.class); + JobInfo info = jss.getPendingJob(JOB_ID); + if (info == null) { + registerJob(context, intervalMinutes); + } + } + public static void registerJob(Context context, long intervalMinutes) { JobScheduler jss = context.getSystemService(JobScheduler.class); jss.cancel(JOB_ID); diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java b/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java index d5e143cade0f0a729187e15bcdd3660d5d826dc7..159b40a3e5afd757e3d553305ae3a5ce138e0fcf 100644 --- a/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java +++ b/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java @@ -20,6 +20,7 @@ import android.service.quicksettings.TileService; import android.util.Log; import com.android.egg.neko.PrefState.PrefsListener; +import com.android.internal.logging.MetricsLogger; public class NekoTile extends TileService implements PrefsListener { @@ -46,6 +47,18 @@ public class NekoTile extends TileService implements PrefsListener { mPrefs.setListener(null); } + @Override + public void onTileAdded() { + super.onTileAdded(); + MetricsLogger.count(this, "egg_neko_tile_added", 1); + } + + @Override + public void onTileRemoved() { + super.onTileRemoved(); + MetricsLogger.count(this, "egg_neko_tile_removed", 1); + } + @Override public void onPrefsChanged() { updateState(); @@ -55,6 +68,9 @@ public class NekoTile extends TileService implements PrefsListener { Tile tile = getQsTile(); int foodState = mPrefs.getFoodState(); Food food = new Food(foodState); + if (foodState != 0) { + NekoService.registerJobIfNeeded(this, food.getInterval(this)); + } tile.setIcon(food.getIcon(this)); tile.setLabel(food.getName(this)); tile.setState(foodState != 0 ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); @@ -65,6 +81,7 @@ public class NekoTile extends TileService implements PrefsListener { public void onClick() { if (mPrefs.getFoodState() != 0) { // there's already food loaded, let's empty it + MetricsLogger.count(this, "egg_neko_empty_food", 1); mPrefs.setFoodState(0); NekoService.cancelJob(this); } else { @@ -91,6 +108,7 @@ public class NekoTile extends TileService implements PrefsListener { private void showNekoDialog() { Log.d(TAG, "showNekoDialog"); + MetricsLogger.count(this, "egg_neko_select_food", 1); showDialog(new NekoDialog(this)); } } diff --git a/packages/EasterEgg/src/com/android/egg/neko/PrefState.java b/packages/EasterEgg/src/com/android/egg/neko/PrefState.java index 5f54180bc2e09e93730685cb8193f91bbb0c8df1..bf71b197d3cb8f2f50506b4cb7ab1b7ffbc8fc83 100644 --- a/packages/EasterEgg/src/com/android/egg/neko/PrefState.java +++ b/packages/EasterEgg/src/com/android/egg/neko/PrefState.java @@ -43,13 +43,11 @@ public class PrefState implements OnSharedPreferenceChangeListener { public void addCat(Cat cat) { mPrefs.edit() .putString(CAT_KEY_PREFIX + String.valueOf(cat.getSeed()), cat.getName()) - .commit(); + .apply(); } public void removeCat(Cat cat) { - mPrefs.edit() - .remove(CAT_KEY_PREFIX + String.valueOf(cat.getSeed())) - .commit(); + mPrefs.edit().remove(CAT_KEY_PREFIX + String.valueOf(cat.getSeed())).apply(); } public List getCats() { @@ -71,7 +69,7 @@ public class PrefState implements OnSharedPreferenceChangeListener { } public void setFoodState(int foodState) { - mPrefs.edit().putInt(FOOD_STATE, foodState).commit(); + mPrefs.edit().putInt(FOOD_STATE, foodState).apply(); } public void setListener(PrefsListener listener) { diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 62f33bf490a85fc68934fa42bcd4efb18c3b052f..3ef9b8e1b8c4ec4bb5454431a11d2c1eaeb72d90 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -466,10 +466,7 @@ public class ExternalStorageProvider extends DocumentsProvider { displayName = FileUtils.buildValidFatFilename(displayName); final File before = getFileForDocId(docId); - final File after = new File(before.getParentFile(), displayName); - if (after.exists()) { - throw new IllegalStateException("Already exists " + after); - } + final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName); if (!before.renameTo(after)) { throw new IllegalStateException("Failed to rename to " + after); } @@ -484,6 +481,8 @@ public class ExternalStorageProvider extends DocumentsProvider { @Override public void deleteDocument(String docId) throws FileNotFoundException { final File file = getFileForDocId(docId); + final File visibleFile = getFileForDocId(docId, true); + final boolean isDirectory = file.isDirectory(); if (isDirectory) { FileUtils.deleteContents(file); @@ -492,23 +491,25 @@ public class ExternalStorageProvider extends DocumentsProvider { throw new IllegalStateException("Failed to delete " + file); } - final ContentResolver resolver = getContext().getContentResolver(); - final Uri externalUri = MediaStore.Files.getContentUri("external"); + if (visibleFile != null) { + final ContentResolver resolver = getContext().getContentResolver(); + final Uri externalUri = MediaStore.Files.getContentUri("external"); - // Remove media store entries for any files inside this directory, using - // path prefix match. Logic borrowed from MtpDatabase. - if (isDirectory) { - final String path = file.getAbsolutePath() + "/"; + // Remove media store entries for any files inside this directory, using + // path prefix match. Logic borrowed from MtpDatabase. + if (isDirectory) { + final String path = visibleFile.getAbsolutePath() + "/"; + resolver.delete(externalUri, + "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)", + new String[] { path + "%", Integer.toString(path.length()), path }); + } + + // Remove media store entry for this exact file. + final String path = visibleFile.getAbsolutePath(); resolver.delete(externalUri, - "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)", - new String[] { path + "%", Integer.toString(path.length()), path }); + "_data LIKE ?1 AND lower(_data)=lower(?2)", + new String[] { path, path }); } - - // Remove media store entry for this exact file. - final String path = file.getAbsolutePath(); - resolver.delete(externalUri, - "_data LIKE ?1 AND lower(_data)=lower(?2)", - new String[] { path, path }); } @Override @@ -562,6 +563,7 @@ public class ExternalStorageProvider extends DocumentsProvider { throws FileNotFoundException { final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection)); + query = query.toLowerCase(); final File parent; synchronized (mRootsLock) { parent = mRoots.get(rootId).path; diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml index 7d4501749c44d18bdf884d05cbba6ef1fbbc98bb..29c93d5adb03b14bff90bfaacbcdf1339f697814 100644 --- a/packages/Keyguard/res/layout/keyguard_password_view.xml +++ b/packages/Keyguard/res/layout/keyguard_password_view.xml @@ -26,7 +26,6 @@ androidprv:layout_maxWidth="@dimen/keyguard_security_width" androidprv:layout_maxHeight="@dimen/keyguard_security_height" android:gravity="bottom" - android:contentDescription="@string/keyguard_accessibility_password_unlock" > "SIM-kaart is gesluit." "SIM-kaart is PUK-geslote." "Ontsluit tans SIM-kaart…" - "Patroon ontsluit." - "PIN ontsluit." - "Wagwoord ontsluit." - "Patroonarea." - "Sleep-area." "PIN-area" "SIM-PIN-area" "SIM-PUK-area" diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml index 68e9ff3fd8247a4cba19e8949fd6f5d4c63ac7ca..67fdc321837d9b46118040ed6bc26e09ee1edf01 100644 --- a/packages/Keyguard/res/values-am/strings.xml +++ b/packages/Keyguard/res/values-am/strings.xml @@ -46,11 +46,6 @@ "ሲም ካርድ ተዘግቷል።" "ሲም ካርድ በፒዩኬ ተዘግቷል።" "ሲም ካርዱን በመክፈት ላይ…" - "በስርዓተ-ጥለት መክፈት።" - "በፒን መክፈት።" - "በይለፍ ቃል መክፈት።" - "የስርዓተ-ጥለት አካባቢ።" - "የማንሸራተቻ አካባቢ።" "የፒን አካባቢ" "የሲም ፒን አካባቢ" "የሲም PUK አካባቢ" diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml index 09b78e44a2ca4d364042d7a7f7c4de02e6cc3687..8438699d031901ba2d2b6222cb9926c490661ed2 100644 --- a/packages/Keyguard/res/values-ar/strings.xml +++ b/packages/Keyguard/res/values-ar/strings.xml @@ -46,11 +46,6 @@ "‏شريحة SIM مؤمّنة." "‏شريحة SIM مؤمّنة بكود PUK." "‏جارٍ إلغاء تأمين شريحة SIM…" - "إلغاء القفل باستخدام النقش." - "‏إلغاء القفل باستخدام رمز PIN." - "إلغاء القفل باستخدام كلمة المرور." - "منطقة النقش." - "منطقة التمرير." "منطقة رقم التعريف الشخصي" "‏منطقة رقم التعريف الشخصي لبطاقة SIM" "‏منطقة PUK لبطاقة SIM" diff --git a/packages/Keyguard/res/values-az-rAZ/strings.xml b/packages/Keyguard/res/values-az-rAZ/strings.xml index a8a115534b79c467a7153695c7d9ffa0f527342e..c7a80919c67005db9ee3510449cd25e78fcf8765 100644 --- a/packages/Keyguard/res/values-az-rAZ/strings.xml +++ b/packages/Keyguard/res/values-az-rAZ/strings.xml @@ -46,11 +46,6 @@ "SIM kart kilidlənib." "SİM kart PUK ilə kilidlənib." "SİM kartın kilidi açılır..." - "Kild açma modeli." - "Pin kilid açması." - "Şifrə kilidi." - "Model sahəsi." - "Sürüşdürmə sahəsi." "PIN sahəsi" "SIM PIN sahəsi" "SIM PUK sahəsi" diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml index 7eb2dbdf0532c9d9b2614f822c933755051b02dd..988e97f6b482e36d002ea5dbc50ccf8e336da985 100644 --- a/packages/Keyguard/res/values-bg/strings.xml +++ b/packages/Keyguard/res/values-bg/strings.xml @@ -46,11 +46,6 @@ "SIM картата е заключена." "SIM картата е заключена с PUK код." "SIM картата се отключва…" - "Отключване с фигура." - "Отключване с ПИН код." - "Отключване с парола." - "Област на фигурата." - "Област на плъзгане." "Област за ПИН кода" "Област за ПИН кода на SIM картата" "Област за PUK кода на SIM картата" diff --git a/packages/Keyguard/res/values-bn-rBD/strings.xml b/packages/Keyguard/res/values-bn-rBD/strings.xml index 7a33e2101cf1c8262edb8677267e2e7c72596b43..1a2a8dde99c16c957b327af04ee55584cf6e6476 100644 --- a/packages/Keyguard/res/values-bn-rBD/strings.xml +++ b/packages/Keyguard/res/values-bn-rBD/strings.xml @@ -46,11 +46,6 @@ "সিম কার্ড লক করা আছে৷" "সিম কার্ডটি PUK কোড দিয়ে লক করা আছে৷" "সিম কার্ড আনলক করা হচ্ছে…" - "প্যাটার্ন দিয়ে আনলক৷" - "পিন দিয়ে আনলক৷" - "পাসওয়ার্ড দিয়ে আনলক৷" - "প্যাটার্ন এলাকা৷" - "স্লাইড করার এলাকা৷" "পিন অঞ্চল" "SIM পিন অঞ্চল" "SIM PUK অঞ্চল" diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml index b542866e6df6a6684a8a39ee79d026323e85c250..9207e0e201fef5d40aaedd928e309a695696d85e 100644 --- a/packages/Keyguard/res/values-ca/strings.xml +++ b/packages/Keyguard/res/values-ca/strings.xml @@ -46,11 +46,6 @@ "La targeta SIM està bloquejada." "La targeta SIM està bloquejada pel PUK." "S\'està desbloquejant la targeta SIM..." - "Desbloqueig mitjançant patró" - "Desbloqueig mitjançant PIN" - "Desbloqueig mitjançant contrasenya" - "Àrea de patró" - "Àrea per lliscar el dit" "Zona del PIN" "Zona del PIN de la SIM" "Zona del PUK de la SIM" diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml index b3103239f6542a8e13dcd244081ca4488730b459..aa7115dede281e7353875205fee1a4c4d9759dc9 100644 --- a/packages/Keyguard/res/values-cs/strings.xml +++ b/packages/Keyguard/res/values-cs/strings.xml @@ -46,11 +46,6 @@ "SIM karta je zablokována." "SIM karta je zablokována pomocí kódu PUK." "Odblokování SIM karty…" - "Odemknutí gestem." - "Odemknutí kódem PIN." - "Odemknutí heslem." - "Oblast pro zadání bezpečnostního gesta." - "Oblast pro přejetí prstem." "Oblast kódu PIN" "Oblast kódu PIN SIM karty" "Oblast kódu PUK SIM karty" diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml index b46b536fffe9b9c7f0d4e99cacdd5962f47197be..b98a2536c2d2b2fff50b709742ec511b4151c748 100644 --- a/packages/Keyguard/res/values-da/strings.xml +++ b/packages/Keyguard/res/values-da/strings.xml @@ -46,11 +46,6 @@ "SIM-kortet er låst." "SIM-kort er låst med PUK-koden." "SIM-kortet låses op…" - "Lås op med mønster." - "Lås op med pinkode." - "Lås op med adgangskode." - "Mønsterområde." - "Strygeområde." "Område for pinkoden" "Område for pinkoden til simkortet" "Område for PUK-koden til simkortet" @@ -133,5 +128,5 @@ Enheden blev sidst låst op for %d timer siden. Bekræft adgangskoden. Enheden blev sidst låst op for %d timer siden. Bekræft adgangskoden. - "Kan ikke genkendes" + "Ikke genkendt" diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml index ae731c34390941346acf506fb708bedb53d2f76d..a519ce84b86272c9034fb64434f8a74d37df4ceb 100644 --- a/packages/Keyguard/res/values-de/strings.xml +++ b/packages/Keyguard/res/values-de/strings.xml @@ -46,11 +46,6 @@ "SIM-Karte ist gesperrt." "SIM-Karte ist gesperrt. PUK-Eingabe erforderlich." "SIM-Karte wird entsperrt…" - "Entsperrung mit Muster" - "Entsperrung mit PIN" - "Entsperrung mit Passwort" - "Bereich für Muster" - "Bereich für Fingerbewegung" "PIN-Bereich" "SIM-PIN-Bereich" "SIM-PUK-Bereich" diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml index c54a7fc87aa4dcbf908088b01a6e9fcde9e65314..d9692667ba0f1b6741bd63896dd1f17fadc778b0 100644 --- a/packages/Keyguard/res/values-el/strings.xml +++ b/packages/Keyguard/res/values-el/strings.xml @@ -46,11 +46,6 @@ "Η κάρτα SIM είναι κλειδωμένη." "Η κάρτα SIM είναι κλειδωμένη με κωδικό PUK." "Ξεκλείδωμα κάρτας SIM…" - "Ξεκλείδωμα μοτίβου." - "Ξεκλείδωμα κωδικού ασφαλείας" - "Ξεκλείδωμα κωδικού πρόσβασης." - "Περιοχή μοτίβου." - "Περιοχή ολίσθησης" "Περιοχή PIN" "Περιοχή PIN SIM" "Περιοχή PUK SIM" diff --git a/packages/Keyguard/res/values-en-rAU/strings.xml b/packages/Keyguard/res/values-en-rAU/strings.xml index e88516679f4598a2563debce0cff2267fd402c13..9ecd979163f25447671ea78fe32e4f37bf3f57d2 100644 --- a/packages/Keyguard/res/values-en-rAU/strings.xml +++ b/packages/Keyguard/res/values-en-rAU/strings.xml @@ -46,11 +46,6 @@ "SIM card is locked." "SIM card is PUK-locked." "Unlocking SIM card…" - "Pattern unlock." - "Pin unlock." - "Password unlock." - "Pattern area." - "Slide area." "PIN area" "SIM PIN area" "SIM PUK area" diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml index e88516679f4598a2563debce0cff2267fd402c13..9ecd979163f25447671ea78fe32e4f37bf3f57d2 100644 --- a/packages/Keyguard/res/values-en-rGB/strings.xml +++ b/packages/Keyguard/res/values-en-rGB/strings.xml @@ -46,11 +46,6 @@ "SIM card is locked." "SIM card is PUK-locked." "Unlocking SIM card…" - "Pattern unlock." - "Pin unlock." - "Password unlock." - "Pattern area." - "Slide area." "PIN area" "SIM PIN area" "SIM PUK area" diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml index e88516679f4598a2563debce0cff2267fd402c13..9ecd979163f25447671ea78fe32e4f37bf3f57d2 100644 --- a/packages/Keyguard/res/values-en-rIN/strings.xml +++ b/packages/Keyguard/res/values-en-rIN/strings.xml @@ -46,11 +46,6 @@ "SIM card is locked." "SIM card is PUK-locked." "Unlocking SIM card…" - "Pattern unlock." - "Pin unlock." - "Password unlock." - "Pattern area." - "Slide area." "PIN area" "SIM PIN area" "SIM PUK area" diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml index df0db2d32d4cdfe2d10371fcfeb687a400f48ac2..61f5c0d538b68605f6ba672420780e3cd9eb243c 100644 --- a/packages/Keyguard/res/values-es-rUS/strings.xml +++ b/packages/Keyguard/res/values-es-rUS/strings.xml @@ -46,11 +46,6 @@ "La tarjeta SIM está bloqueada." "La tarjeta SIM está bloqueada por código PUK." "Desbloqueando tarjeta SIM…" - "Desbloqueo por patrón" - "Desbloqueo por PIN" - "Desbloqueo por contraseña" - "Área de patrón" - "Área de deslizamiento" "Área de PIN" "Área de PIN de SIM" "Área de PUK de SIM" diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml index 6061b784378f60eaa742e6f0b19dde713cb83138..3ef737c22764830bad183a74bd6fcb8532e74c33 100644 --- a/packages/Keyguard/res/values-es/strings.xml +++ b/packages/Keyguard/res/values-es/strings.xml @@ -46,11 +46,6 @@ "La tarjeta SIM está bloqueada." "La tarjeta SIM está bloqueada con el código PUK." "Desbloqueando tarjeta SIM…" - "Desbloqueo por patrón" - "Desbloqueo por PIN" - "Desbloqueo por contraseña" - "Área de patrón" - "Área para deslizar" "Área de PIN" "Área de PIN de SIM" "Área de PUK de SIM" diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml index 78ae3cacaea512276c7ecc424ed8bff3016914d1..47b6332c92c2404976a4453ff99f600a8552c5d8 100644 --- a/packages/Keyguard/res/values-et-rEE/strings.xml +++ b/packages/Keyguard/res/values-et-rEE/strings.xml @@ -46,11 +46,6 @@ "SIM-kaart on lukus." "SIM-kaart on PUK-lukus." "SIM-kaardi avamine ..." - "Mustriga avamine." - "PIN-koodiga avamine." - "Parooliga avamine." - "Mustri ala." - "Lohistamisala." "PIN-koodi ala" "SIM-kaardi PIN-koodi ala" "SIM-kaardi PUK-koodi ala" diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml index 7855b16e82b9d01049c8f2d2fb522121314894f8..5f4abce03f1b91cd8f733529bd0ab845a86029a6 100644 --- a/packages/Keyguard/res/values-eu-rES/strings.xml +++ b/packages/Keyguard/res/values-eu-rES/strings.xml @@ -46,11 +46,6 @@ "SIM txartela blokeatuta dago." "SIM txartela PUK bidez blokeatuta dago." "SIM txartela desblokeatzen…" - "Ereduaren bidez desblokeatzea." - "PIN kodearen bidez desblokeatzea." - "Pasahitzaren bidez desblokeatzea." - "Eredua marrazteko eremua." - "Hatza lerratzeko eremua." "PIN kodearen eremua" "SIM txartelaren PIN kodearen eremua" "SIM txartelaren PUK kodearen eremua" diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml index 39fd4608de516c60c1e188e8159bd292bba15f7d..40952e256a5f6d6a013e36458aa864a37e0f0003 100644 --- a/packages/Keyguard/res/values-fa/strings.xml +++ b/packages/Keyguard/res/values-fa/strings.xml @@ -46,11 +46,6 @@ "سیم کارت قفل شد." "‏سیم کارت با PUK قفل شده است." "درحال بازگشایی قفل سیم کارت..." - "باز کردن قفل با الگو." - "باز کردن قفل با پین." - "باز کردن قفل با گذرواژه." - "ناحیه الگو." - "ناحیه کشیدن انگشت روی صفحه." "قسمت پین" "قسمت پین سیم‌کارت" "‏قسمت PUK سیم‌کارت" diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml index 7a0c00f83bf76864684be0697427b5d9819e842b..a1b96ca2f6711732645155200069a6fbbf0ad21c 100644 --- a/packages/Keyguard/res/values-fi/strings.xml +++ b/packages/Keyguard/res/values-fi/strings.xml @@ -46,11 +46,6 @@ "SIM-kortti on lukittu." "SIM-kortti on PUK-lukittu." "SIM-kortin lukitusta poistetaan…" - "Lukituksen poisto salasanalla." - "Lukituksen poisto PIN-koodilla." - "Lukituksen poisto salasanalla." - "Kuvioalue." - "Liu\'utusalue." "PIN-koodin alue" "SIM-kortin PIN-koodin alue" "SIM-kortin PUK-koodin alue" diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml index 9bc2456809d6ea2b5853a2995e5ab64bd999dbf0..d920415a69cc427c97811fcd590e0a819ea5f7f5 100644 --- a/packages/Keyguard/res/values-fr-rCA/strings.xml +++ b/packages/Keyguard/res/values-fr-rCA/strings.xml @@ -46,11 +46,6 @@ "La carte SIM est verrouillée." "La carte SIM est verrouillée par clé PUK." "Déverrouillage de la carte SIM en cours…" - "Déverrouillage par schéma" - "Déverrouillage par NIP" - "Déverrouillage par mot de passe" - "Zone du schéma" - "Zone où faire glisser votre doigt sur l\'écran" "Zone du NIP" "Zone du NIP de la carte SIM" "Zone du code PUK de la carte SIM" diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml index ecb2575d2e9a268e587b8b44b5ace1698db0789c..8615b99df2bf98858b0849ba909498e695ad5227 100644 --- a/packages/Keyguard/res/values-fr/strings.xml +++ b/packages/Keyguard/res/values-fr/strings.xml @@ -46,11 +46,6 @@ "La carte SIM est verrouillée." "La carte SIM est verrouillée par clé PUK." "Déverrouillage de la carte SIM en cours…" - "Déverrouillage par schéma" - "Déverrouillage par code PIN" - "Déverrouillage par mot de passe" - "Zone du schéma" - "Zone où faire glisser votre doigt sur l\'écran" "Champ du code PIN" "Champ du code PIN de la carte SIM" "Champ du code PUK de la carte SIM" diff --git a/packages/Keyguard/res/values-gl-rES/strings.xml b/packages/Keyguard/res/values-gl-rES/strings.xml index 382dd7bf3e13c7ca53df853a1c77e08dc59ea4c0..a894fc5b9ccdc4c4db48eefd15e636e24beeb2af 100644 --- a/packages/Keyguard/res/values-gl-rES/strings.xml +++ b/packages/Keyguard/res/values-gl-rES/strings.xml @@ -46,11 +46,6 @@ "A tarxeta SIM está bloqueada." "A tarxeta SIM está bloqueada mediante un PUK." "Desbloqueando tarxeta SIM…" - "Desbloqueo mediante padrón" - "Desbloqueo mediante PIN" - "Desbloqueo mediante contrasinal" - "Zona do padrón" - "Zona para pasar o dedo" "Área do PIN" "Área do PIN da tarxeta SIM" "Área do PUK da tarxeta SIM" diff --git a/packages/Keyguard/res/values-gu-rIN/strings.xml b/packages/Keyguard/res/values-gu-rIN/strings.xml index eddd1a158486839ff52c8afff54e7fd4f60d2c77..d288b3f9da781e4e16438fb93f7792c1692a6e52 100644 --- a/packages/Keyguard/res/values-gu-rIN/strings.xml +++ b/packages/Keyguard/res/values-gu-rIN/strings.xml @@ -46,11 +46,6 @@ "SIM કાર્ડ લૉક કરેલ છે." "SIM કાર્ડ, PUK-લૉક કરેલ છે." "SIM કાર્ડ અનલૉક કરી રહ્યાં છે…" - "પેટર્ન અનલૉક." - "પિન અનલૉક." - "પાસવર્ડ અનલૉક કરો." - "પેટર્ન ક્ષેત્ર." - "સ્લાઇડ ક્ષેત્ર." "PIN ક્ષેત્ર" "SIM PIN ક્ષેત્ર" "SIM PUK ક્ષેત્ર" diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml index 8069c5e9c464b0c7811c9833b8ecc8ea55ddac15..bf36312870e5d6a1d113be8ef6c83ac0380c93f3 100644 --- a/packages/Keyguard/res/values-hi/strings.xml +++ b/packages/Keyguard/res/values-hi/strings.xml @@ -46,11 +46,6 @@ "सिम कार्ड लॉक है." "सिम कार्ड PUK द्वारा लॉक किया हुआ है." "सिम कार्ड अनलॉक हो रहा है…" - "आकार अनलॉक." - "पिन अनलॉक." - "पासवर्ड अनलॉक." - "आकार क्षेत्र." - "स्लाइड क्षेत्र." "पिन क्षेत्र" "सिम पिन क्षेत्र" "सिम पिइउके क्षेत्र" diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml index 044786d6297d38826cbc1640a2112eff167616b4..169bc5716bbb6809009f72d0f550419da60e00ae 100644 --- a/packages/Keyguard/res/values-hr/strings.xml +++ b/packages/Keyguard/res/values-hr/strings.xml @@ -46,11 +46,6 @@ "SIM kartica je zaključana." "SIM kartica zaključana je PUK-om." "Otključavanje SIM kartice…" - "Uzorak za otključavanje." - "Otključavanje PIN-om." - "Otključavanje zaporkom." - "Područje uzorka." - "Područje klizanja." "Područje PIN-a" "Područje PIN-a za SIM" "Područje PUK-a za SIM" diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml index e54a89f42fa64c97cd343fbb663478d9bc9b956b..bc3bf4e0427fa9d7cc0eab45690f1352fa2275fd 100644 --- a/packages/Keyguard/res/values-hu/strings.xml +++ b/packages/Keyguard/res/values-hu/strings.xml @@ -46,11 +46,6 @@ "A SIM kártya le van zárva." "A SIM kártya le van zárva a PUK kóddal." "SIM kártya feloldása..." - "Feloldás mintával" - "Feloldás PIN kóddal" - "Feloldás jelszóval" - "Mintaterület" - "Csúsztatási terület" "PIN-kód területe" "SIM PIN-kód területe" "SIM PUK kód területe" diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml index 6758a2e962c461817a1769f0f114cc1f49e56813..4aacf8fb927a378fa5d74f2ce27eee3d326fece7 100644 --- a/packages/Keyguard/res/values-hy-rAM/strings.xml +++ b/packages/Keyguard/res/values-hy-rAM/strings.xml @@ -46,11 +46,6 @@ "SIM քարտը կողպված է:" "SIM քարտը PUK-ով կողպված է:" "SIM քարտը ապակողպվում է..." - "Սխեմայով ապակողպում:" - "Pin-ն ապակողպված է:" - "Գաղտնաբառի ապակողպում:" - "Սխեմայի տարածք:" - "Սահեցման տարածք:" "PIN կոդի տարածք" "SIM քարտի PIN կոդի տարածք" "SIM քարտի PUK կոդի տարածք" diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml index 6f8e7f1c6ddb1b8b4fe9c02397dd524fddeef657..dda63a88568cc87f8fc5b6480a47b98d3fae2030 100644 --- a/packages/Keyguard/res/values-in/strings.xml +++ b/packages/Keyguard/res/values-in/strings.xml @@ -46,11 +46,6 @@ "Kartu SIM terkunci." "Kartu SIM terkunci PUK." "Membuka kartu SIM…" - "Buka kunci dengan pola." - "Buka kunci dengan PIN." - "Buka kunci dengan sandi." - "Area pola." - "Area geser." "Bidang PIN" "Bidang PIN SIM" "Bidang PUK SIM" diff --git a/packages/Keyguard/res/values-is-rIS/strings.xml b/packages/Keyguard/res/values-is-rIS/strings.xml index 279ffcfb51b44b7ee32059f70e422c85bebd6a80..278e03113673577b4832db18e9d2de1101d60a2f 100644 --- a/packages/Keyguard/res/values-is-rIS/strings.xml +++ b/packages/Keyguard/res/values-is-rIS/strings.xml @@ -46,11 +46,6 @@ "SIM-kortið er læst." "SIM-kortið er PUK-læst." "Tekur SIM-kort úr lás…" - "Opnun með mynstri." - "Opnun með PIN-númeri." - "Opnun með aðgangsorði." - "Svæði mynsturs." - "Stroksvæði." "PIN-svæði" "PIN-svæði SIM-korts" "PUK-svæði SIM-korts" diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml index 728974df96bcadc6a3b881d9986c7f3373a35235..98bcae4775b9d94cdefc42566a183bbd85f8092f 100644 --- a/packages/Keyguard/res/values-it/strings.xml +++ b/packages/Keyguard/res/values-it/strings.xml @@ -46,11 +46,6 @@ "La SIM è bloccata." "La SIM è bloccata tramite PUK." "Sblocco scheda SIM..." - "Sblocco con sequenza." - "Sblocco con PIN." - "Sblocco con password." - "Area sequenza." - "Area di scorrimento." "Area PIN" "Area PIN SIM" "Area PUK SIM" diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml index 47d0728af3ff25f0404517a67ed05e869ddd119b..8d1ada3a342a34c048107defec13ba7eb49cf656 100644 --- a/packages/Keyguard/res/values-iw/strings.xml +++ b/packages/Keyguard/res/values-iw/strings.xml @@ -46,11 +46,6 @@ "‏כרטיס ה-SIM נעול." "‏כרטיס SIM נעול באמצעות PUK." "‏מבטל נעילה של כרטיס SIM…" - "ביטול נעילה באמצעות ציור קו." - "‏ביטול נעילה באמצעות מספר PIN." - "ביטול נעילה באמצעות סיסמה." - "אזור ציור קו." - "אזור הסטה." "‏אזור עבור קוד PIN" "‏אזור עבור קוד PIN של SIM" "‏אזור עבור קוד PUK של SIM" diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml index d30355fedce820b2daa7449f795f57d8b9684c48..c4b4c98564879a18cb4c9f0ed4320d96313d2036 100644 --- a/packages/Keyguard/res/values-ja/strings.xml +++ b/packages/Keyguard/res/values-ja/strings.xml @@ -46,11 +46,6 @@ "SIMカードはロックされています。" "SIMカードはPUKでロックされています。" "SIMカードをロック解除しています…" - "パターンロックを解除します。" - "PINロックを解除します。" - "パスワードロックを解除します。" - "パターンエリアです。" - "スライドエリアです。" "PINエリア" "SIM PINエリア" "SIM PUKエリア" diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml index a398e00838ec4b317931c1e111cd2ea7f2889c04..658194ff0c4ae5a92646aa505ed8075da2ab14d7 100644 --- a/packages/Keyguard/res/values-ka-rGE/strings.xml +++ b/packages/Keyguard/res/values-ka-rGE/strings.xml @@ -46,11 +46,6 @@ "SIM ბარათი დაბლოკილია." "SIM ბარათი დაბლოკილია PUK კოდით." "მიმდინარეობს SIM ბარათის განბლოკვა…" - "განბლოკვა ნიმუშით." - "განბლოკვა Pin-ით." - "პაროლის განბლოკვა" - "ნიმუშების სივრცე." - "გადასრიალების სივრცე." "PIN-ის არე" "SIM-ის PIN-ის არე" "SIM-ის PUK-ის არე" diff --git a/packages/Keyguard/res/values-kk-rKZ/strings.xml b/packages/Keyguard/res/values-kk-rKZ/strings.xml index be261fb332abacee268baad5423f4e062c2d634e..2eb3948778aff6a6ce4095411bfe77984ab4c751 100644 --- a/packages/Keyguard/res/values-kk-rKZ/strings.xml +++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml @@ -46,11 +46,6 @@ "SIM картасы бекітулі." "SIM картасының PUK коды бекітілген." "SIM картасының бекітпесін ашуда…" - "Кескін арқылы ашу." - "Pin арқылы ашу." - "Құпия сөз арқылы ашу." - "Кескін арқылы ашу аймағы." - "Сырғыту аймағы." "PIN аумағы" "SIM PIN аумағы" "SIM PUK аумағы" diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml index 4d3f6e86efbe4192b30b220107c7a89261c7f00b..fce46c732a5a7858a52299418b2b6404c1bcaf8f 100644 --- a/packages/Keyguard/res/values-km-rKH/strings.xml +++ b/packages/Keyguard/res/values-km-rKH/strings.xml @@ -46,11 +46,6 @@ "ស៊ីម​កាត​​ជាប់​សោ។" "ស៊ីម​កាត​ជាប់​កូដ​​ PUK ។" "កំពុង​ដោះ​សោ​ស៊ីម​កាត..." - "លំនាំ​ដោះ​សោ​។" - "កូដ PIN ដោះ​សោ។" - "ពាក្យ​សម្ងាត់​ដោះ​សោ​។" - "ផ្ទៃ​លំនាំ។" - "ផ្ទៃ​រុញ។" "ប្រអប់លេខសម្ងាត់" "ប្រអប់លេខសម្ងាត់ស៊ីម" "ប្រអប់ PUK ស៊ីម" diff --git a/packages/Keyguard/res/values-kn-rIN/strings.xml b/packages/Keyguard/res/values-kn-rIN/strings.xml index 5691a6354b22008755a6b1083889dcfddff798fe..7bac9c6c4c1b60fc2d58e9599a14dcfbafe4e1be 100644 --- a/packages/Keyguard/res/values-kn-rIN/strings.xml +++ b/packages/Keyguard/res/values-kn-rIN/strings.xml @@ -46,11 +46,6 @@ "ಸಿಮ್‌ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ." "ಸಿಮ್‌ ಕಾರ್ಡ್ ಅನ್ನು PUK-ಲಾಕ್ ಮಾಡಲಾಗಿದೆ." "ಸಿಮ್‌ ಕಾರ್ಡ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ…" - "ಪ್ಯಾಟರ್ನ್ ಅನ್‌ಲಾಕ್." - "ಪಿನ್ ಅನ್‌ಲಾಕ್." - "ಪಾಸ್‌ವರ್ಡ್ ಅನ್‌ಲಾಕ್." - "ಪ್ಯಾಟರ್ನ್ ಪ್ರದೇಶ." - "ಸ್ಲೈಡ್ ಪ್ರದೇಶ." "ಪಿನ್ ಪ್ರದೇಶ" "ಸಿಮ್ ಪಿನ್ ಪ್ರದೇಶ" "ಸಿಮ್ PUK ಪ್ರದೇಶ" diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml index 2eeef2b402206b04af6aabc7ef3e0aadfa28f024..5d40d4d2a954986f3801f27f4da481ac185e4d64 100644 --- a/packages/Keyguard/res/values-ko/strings.xml +++ b/packages/Keyguard/res/values-ko/strings.xml @@ -46,11 +46,6 @@ "SIM 카드가 잠겨 있습니다." "SIM 카드가 PUK 잠김 상태입니다." "SIM 카드 잠금해제 중..." - "패턴을 사용하여 잠금해제합니다." - "핀을 사용하여 잠금해제합니다." - "비밀번호를 사용하여 잠금해제합니다." - "패턴을 그리는 부분입니다." - "슬라이드하는 부분입니다." "PIN 영역" "SIM PIN 영역" "SIM PUK 영역" diff --git a/packages/Keyguard/res/values-ky-rKG/strings.xml b/packages/Keyguard/res/values-ky-rKG/strings.xml index d42b1fab3a010428a1abb941787a9ad0880307bd..a48552844ffe0c1c171174ff921f18e0bdea9a5b 100644 --- a/packages/Keyguard/res/values-ky-rKG/strings.xml +++ b/packages/Keyguard/res/values-ky-rKG/strings.xml @@ -46,11 +46,6 @@ "SIM-карта бөгөттөлгөн." "SIM-карта PUK-бөгөттө." "SIM-карта бөгөттөн чыгарылууда…" - "Үлгү менен ачуу." - "Пин код менен ачуу." - "Сырсөз менен ачуу." - "Үлгү аймагы." - "Жылмыштыруу аймагы." "PIN аймагы" "SIM PIN аймагы" "SIM PUK аймагы" diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml index 8e7c8136c6ca0fe2d8d3d941d54d71b85d5c8aae..29a1b562cf20f0dc2af002f374168a9a2a168528 100644 --- a/packages/Keyguard/res/values-lo-rLA/strings.xml +++ b/packages/Keyguard/res/values-lo-rLA/strings.xml @@ -46,11 +46,6 @@ "ຊິມກາດຖືກລັອກ." "ຊິມກາດຖືກລັອກດ້ວຍລະຫັດ PUK." "ກຳລັງປົດລັອກຊິມກາດ..." - "ປົດລັອກດ້ວຍຮູບແບບ." - "ປົດລັອກດ້ວຍ PIN." - "ການປົດລັອກດ້ວຍລະຫັດຜ່ານ." - "ພື້ນທີ່ຮູບແບບ." - "ເລື່ອນພື້ນທີ່." "ພື້ນ​ທີ່ PIN" "ພື້ນ​ທີ່ PIN ຂອງ SIM" "ພື້ນ​ທີ່ PUK ຂອງ SIM" diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml index 653c089b915b22d1e647ef031067fa07bcaace1e..fd41efc28db3c0289bb7f75fd1c7327b3a7a1ad5 100644 --- a/packages/Keyguard/res/values-lt/strings.xml +++ b/packages/Keyguard/res/values-lt/strings.xml @@ -46,11 +46,6 @@ "SIM kortelė užrakinta." "SIM kortelė užrakinta PUK kodu." "Atrakinama SIM kortelė…" - "Atrakinimas pagal piešinį." - "Atrakinimas įvedus PIN kodą." - "Atrakinimas įvedus slaptažodį." - "Atrakinimo pagal piešinį sritis." - "Slydimo sritis." "PIN kodo sritis" "SIM kortelės PIN kodo sritis" "SIM kortelės PUK kodo sritis" diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml index 449659e9e63c368746160d167360d20c96f6692b..f801d649fa0a025a5a5befe59f752239db7e9084 100644 --- a/packages/Keyguard/res/values-lv/strings.xml +++ b/packages/Keyguard/res/values-lv/strings.xml @@ -46,11 +46,6 @@ "SIM karte ir bloķēta." "SIM karte ir bloķēta ar PUK." "Notiek SIM kartes atbloķēšana..." - "Autorizācija ar kombināciju." - "Autorizācija ar PIN kodu." - "Autorizācija ar paroli." - "Kombinācijas ievades apgabals." - "Apgabals, kur vilkt ar pirkstu." "PIN apgabals" "SIM PIN apgabals" "SIM PUK apgabals" diff --git a/packages/Keyguard/res/values-mk-rMK/strings.xml b/packages/Keyguard/res/values-mk-rMK/strings.xml index a6ee92106768f2659d13e6184a3d732194847d56..9d833f0266f22985a0a6672b508b7be1eda8e41b 100644 --- a/packages/Keyguard/res/values-mk-rMK/strings.xml +++ b/packages/Keyguard/res/values-mk-rMK/strings.xml @@ -46,11 +46,6 @@ "СИМ картичката е заклучена." "СИМ картичката е заклучена со ПУК." "СИМ картичката се отклучува..." - "Отклучување со шема." - "Отклучување со пин." - "Отклучување со лозинка." - "Област за шема." - "Област за лизгање." "Поле за PIN" "Поле за PIN на СИМ" "Поле за ПУК на СИМ" diff --git a/packages/Keyguard/res/values-ml-rIN/strings.xml b/packages/Keyguard/res/values-ml-rIN/strings.xml index fa39ae11af9be597c6bef4de7520e99b8cc8c054..5d93cf00387850640997f3d7d70b593234cdcb00 100644 --- a/packages/Keyguard/res/values-ml-rIN/strings.xml +++ b/packages/Keyguard/res/values-ml-rIN/strings.xml @@ -46,11 +46,6 @@ "സിം കാർഡ് ലോക്കുചെയ്‌തു." "സിം കാർഡ് PUK-ലോക്ക് ചെയ്‌തതാണ്." "സിം കാർഡ് അൺലോക്കുചെയ്യുന്നു…" - "പാറ്റേൺ അൺലോക്ക്." - "പിൻ അൺലോക്ക്." - "പാസ്‌വേഡ് അൺലോക്ക്." - "പാറ്റേൺ ഏരിയ." - "സ്ലൈഡ് ഏരിയ." "PIN ഏരിയ" "SIM PIN ഏരിയ" "SIM PUK ഏരിയ" diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml index fae032884c0b10e90f1b5f860e7d60903b712193..8641e31285fb960257d46d29d6a0d9713fc06190 100644 --- a/packages/Keyguard/res/values-mn-rMN/strings.xml +++ b/packages/Keyguard/res/values-mn-rMN/strings.xml @@ -46,11 +46,6 @@ "SIM карт түгжигдсэн." "SIM картны PUK-түгжигдсэн." "SIM картны түгжээг гаргаж байна…" - "Тайлах хээ." - "Тайлах пин." - "Тайлах нууц үг." - "Хээний хэсэг." - "Гулсуулах хэсэг." "PIN талбар" "SIM PIN талбар" "SIM PUK талбар" diff --git a/packages/Keyguard/res/values-mr-rIN/strings.xml b/packages/Keyguard/res/values-mr-rIN/strings.xml index 57a95be9971b5f3953d61097cd75a3afb83dbe26..8bcaad6cc504325c807d01e1608b3045b0984cd6 100644 --- a/packages/Keyguard/res/values-mr-rIN/strings.xml +++ b/packages/Keyguard/res/values-mr-rIN/strings.xml @@ -46,11 +46,6 @@ "सिम कार्ड लॉक झाले आहे." "सिम कार्ड PUK-लॉक केलेले आहे." "सिम कार्ड अनलॉक करत आहे…" - "नमुना अनलॉक." - "पिन अनलॉक." - "संकेतशब्द अनलॉक." - "नमुना क्षेत्र." - "स्लाइड क्षेत्र." "पिन क्षेत्र" "सिम पिन क्षेत्र" "सिम PUK क्षेत्र" diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml index 803d40a27133bb38d149f3713f2558d798067237..b7b093f085bfa8e3e91e3dac533e9d9b7a5338f3 100644 --- a/packages/Keyguard/res/values-ms-rMY/strings.xml +++ b/packages/Keyguard/res/values-ms-rMY/strings.xml @@ -46,11 +46,6 @@ "Kad SIM dikunci." "Kad SIM dikunci dengan PUK." "Membuka kunci kad SIM..." - "Buka kunci corak." - "Buka kunci pin." - "Buka kunci kata laluan." - "Kawasan corak." - "Kawasan luncur." "Kawasan PIN" "Kawasan PIN SIM" "Kawasan PUK SIM" diff --git a/packages/SystemUI/res/drawable/notification_header_bg.xml b/packages/Keyguard/res/values-my-rMM/dimens.xml similarity index 71% rename from packages/SystemUI/res/drawable/notification_header_bg.xml rename to packages/Keyguard/res/values-my-rMM/dimens.xml index 1f46502591ce168005dcfb1d0bff167b471aaea9..21b2a46ecea1952a0d705106af8fb12ed33bea5d 100644 --- a/packages/SystemUI/res/drawable/notification_header_bg.xml +++ b/packages/Keyguard/res/values-my-rMM/dimens.xml @@ -1,6 +1,6 @@ - - - - \ No newline at end of file + + 4dp + diff --git a/packages/Keyguard/res/values-my-rMM/strings.xml b/packages/Keyguard/res/values-my-rMM/strings.xml index 5db7e95a76bf2f397b0d0de1f33746507f83ae65..7a7664e2028746ac89d95e4ac78eadcc80799692 100644 --- a/packages/Keyguard/res/values-my-rMM/strings.xml +++ b/packages/Keyguard/res/values-my-rMM/strings.xml @@ -46,16 +46,11 @@ "ဆင်းမ်ကဒ် သော့ကျနေပါသည်" "ဆင်းမ်ကဒ် ရဲ့ ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် သော့ကျနေပါသည်" "ဆင်းမ်ကဒ် ကို သော့ဖွင့်နေပါသည်" - "ပုံစံဖြင့် သော့ဖွင့်ခြင်း" - "ပင်နံပါတ်ဖြင့် သော့ဖွင့်ခြင်း" - "စကားဝှက်ဖြင့် သော့ဖွင့်ခြင်း" - "ပုံစံနေရာ" - "ဘေးတိုက်ပွတ်ဆွဲရန် နေရာ" "PIN နေရာ" "SIM PIN နေရာ" "SIM PUK နေရာ" "%1$s အတွက် နောက် သတိပေးရန် သတ်မှတ်ချက်" - "ဖျက်ရန်ခလုတ်" + "ဖျက်ရန်" "Enterခလုတ်" "ပုံဖော်မှုအား မေ့လျော့ခြင်း" "ပုံဆွဲအမှား" diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml index 1bdf444c05e802546af627e16657869860f173b8..e0035daa10ba23a6afeff0c24e4594d954cdce35 100644 --- a/packages/Keyguard/res/values-nb/strings.xml +++ b/packages/Keyguard/res/values-nb/strings.xml @@ -46,11 +46,6 @@ "SIM-kortet er låst." "SIM-kortet er PUK-låst." "Låser opp SIM-kortet ..." - "Mønsteropplåsning." - "PIN-opplåsning." - "Passordopplåsning." - "Mønsterområde." - "Dra-felt." "PIN-området" "PIN-området for SIM-kortet" "PUK-området for SIM-kortet" diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml index 2cf863d25a1c80a5689100e2e70c0906215b7a25..47f5432a544713401ce0f8298b336b52a8f6b49a 100644 --- a/packages/Keyguard/res/values-ne-rNP/strings.xml +++ b/packages/Keyguard/res/values-ne-rNP/strings.xml @@ -46,11 +46,6 @@ "SIM कार्ड लक गरियो।" "SIM कार्ड PUK-लक छ।" "SIM कार्ड अनलक हुँदै…" - "ढाँचा अनलक।" - "Pin अनलक" - "पासवर्ड अनलक।" - "ढाँचा क्षेत्र।" - "स्लाइड क्षेत्र।" "पीन क्षेत्र" "SIM पिन क्षेत्र" "SIM पुक क्षेत्र" diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml index a33165d8e78109e36f0b30a0dbf7fbe4c80a6ec4..c44381efc8176f3bd21bd69a065440982b15abb4 100644 --- a/packages/Keyguard/res/values-nl/strings.xml +++ b/packages/Keyguard/res/values-nl/strings.xml @@ -46,11 +46,6 @@ "Simkaart is vergrendeld." "Simkaart is vergrendeld met PUK-code." "Simkaart ontgrendelen…" - "Ontgrendeling via patroon." - "Ontgrendeling via pincode." - "Ontgrendeling via wachtwoord." - "Tekengebied voor patroon." - "Schuifgebied." "Gebied voor pincode" "Gebied voor sim-pincode" "Gebied voor sim-pukcode" diff --git a/packages/Keyguard/res/values-pa-rIN/strings.xml b/packages/Keyguard/res/values-pa-rIN/strings.xml index 8cf86a065e8d05a97c24d2e81c9915a388b6212a..16ca29c31172d85e33c2b10d8a33225cebb34750 100644 --- a/packages/Keyguard/res/values-pa-rIN/strings.xml +++ b/packages/Keyguard/res/values-pa-rIN/strings.xml @@ -46,11 +46,6 @@ "SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।" "SIM ਕਾਰਡ PUK-ਲੌਕਡ ਹੈ।" "SIM ਕਾਰਡ ਅਨਲੌਕ ਕਰ ਰਿਹਾ ਹੈ…" - "ਪੈਟਰਨ ਅਨਲੌਕ।" - "Pin ਅਨਲੌਕ।" - "ਪਾਸਵਰਡ ਅਨਲੌਕ।" - "ਪੈਟਰਨ ਖੇਤਰ।" - "ਖੇਤਰ ਸਲਾਈਡ ਕਰੋ।" "PIN ਖੇਤਰ" "SIM PIN ਖੇਤਰ" "SIM PUK ਖੇਤਰ" diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml index ee208508ac0019066f4c8d50cec646caeddb2045..f0980da7d08518e268e9b65332049800a55fe2c6 100644 --- a/packages/Keyguard/res/values-pl/strings.xml +++ b/packages/Keyguard/res/values-pl/strings.xml @@ -46,11 +46,6 @@ "Karta SIM jest zablokowana." "Karta SIM jest zablokowana za pomocą kodu PUK." "Odblokowuję kartę SIM…" - "Odblokowanie wzorem." - "Odblokowanie kodem PIN." - "Odblokowanie hasłem." - "Obszar wzoru." - "Obszar przesuwania." "Miejsce na PIN" "Miejsce na PIN do karty SIM" "Miejsce na PUK do karty SIM" diff --git a/packages/Keyguard/res/values-pt-rBR/strings.xml b/packages/Keyguard/res/values-pt-rBR/strings.xml index d7215c1a2c48634038d13d97de1ba27c5d39c115..2663337cee8203d3038e4d9d7f87d02cd8bd1459 100644 --- a/packages/Keyguard/res/values-pt-rBR/strings.xml +++ b/packages/Keyguard/res/values-pt-rBR/strings.xml @@ -46,11 +46,6 @@ "O cartão SIM está bloqueado." "O cartão SIM está bloqueado pelo PUK." "Desbloqueando o cartão SIM…" - "Desbloqueio com padrão." - "Desbloqueio com PIN." - "Desbloqueio com senha." - "Área do padrão." - "Área de deslize." "Área do PIN" "Área do PIN SIM" "Área do PUK SIM" diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml index f0b2bbcd0d6270b939c37dfc02cc4f9243d51510..e417e07d94f1a86c00f436e2da9fe84d4c14f345 100644 --- a/packages/Keyguard/res/values-pt-rPT/strings.xml +++ b/packages/Keyguard/res/values-pt-rPT/strings.xml @@ -46,11 +46,6 @@ "O cartão SIM está bloqueado." "O cartão SIM está bloqueado por PUK." "A desbloquear o cartão SIM..." - "Desbloqueio através de sequência." - "Desbloqueio através de PIN." - "Desbloqueio através de palavra-passe." - "Área da sequência." - "Área de deslize." "Área do PIN" "Área do PIN do SIM" "Área do PUK do SIM" diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml index d7215c1a2c48634038d13d97de1ba27c5d39c115..2663337cee8203d3038e4d9d7f87d02cd8bd1459 100644 --- a/packages/Keyguard/res/values-pt/strings.xml +++ b/packages/Keyguard/res/values-pt/strings.xml @@ -46,11 +46,6 @@ "O cartão SIM está bloqueado." "O cartão SIM está bloqueado pelo PUK." "Desbloqueando o cartão SIM…" - "Desbloqueio com padrão." - "Desbloqueio com PIN." - "Desbloqueio com senha." - "Área do padrão." - "Área de deslize." "Área do PIN" "Área do PIN SIM" "Área do PUK SIM" diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml index ea5380cbde25f9e4940dc0ca2cd132117c5cd0d6..09a066af2e90978352175fe5da084716f63e1612 100644 --- a/packages/Keyguard/res/values-ro/strings.xml +++ b/packages/Keyguard/res/values-ro/strings.xml @@ -46,11 +46,6 @@ "Cardul SIM este blocat." "Cardul SIM este blocat cu codul PUK." "Se deblochează cardul SIM…" - "Deblocare cu model." - "Deblocare cu PIN." - "Deblocare cu parolă." - "Zonă model." - "Zonă glisare." "Zona codului PIN" "Zona codului PIN al cardului SIM" "Zona codului PUK al cardului SIM" @@ -61,7 +56,7 @@ "Model greșit" "Parolă greșită" "Cod PIN greșit" - "Încercați din nou peste %d (de) secunde." + "Încercați din nou peste %d secunde." "Desenați modelul" "Introduceți codul PIN al cardului SIM" "Introduceți codul PIN al cardului SIM pentru „%1$s”" @@ -77,9 +72,9 @@ "Reintroduceți codul PUK corect. Încercările repetate vor dezactiva definitiv cardul SIM." "Codurile PIN nu coincid" "Prea multe încercări de desenare a modelului" - "Ați introdus incorect codul PIN de %1$d ori.\n\nÎncercați din nou peste %2$d (de) secunde." - "Ați introdus incorect parola de %1$d ori. \n\nÎncercați din nou peste %2$d (de) secunde." - "Ați desenat incorect modelul pentru deblocare de %1$d ori. \n\nÎncercați din nou peste %2$d (de) secunde." + "Ați introdus incorect codul PIN de %1$d ori.\n\nÎncercați din nou peste %2$d secunde." + "Ați introdus incorect parola de %1$d ori. \n\nÎncercați din nou peste %2$d secunde." + "Ați desenat incorect modelul pentru deblocare de %1$d ori. \n\nÎncercați din nou peste %2$d secunde." "Ați efectuat %1$d încercări incorecte de deblocare a tabletei. După încă %2$d încercări nereușite, această tabletă va fi resetată, iar toate datele acesteia vor fi șterse." "Ați efectuat %1$d încercări incorecte de deblocare a telefonului. După încă %2$d încercări nereușite, acest telefon va fi resetat, iar toate datele acestuia vor fi șterse." "Ați efectuat %d încercări incorecte de deblocare a tabletei. Această tabletă va fi resetată, iar toate datele acesteia vor fi șterse." @@ -92,8 +87,8 @@ "Ați efectuat %1$d încercări incorecte de deblocare a telefonului. După încă %2$d încercări nereușite, profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse." "Ați efectuat %d încercări incorecte de deblocare a tabletei. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse." "Ați efectuat %d încercări incorecte de deblocare a telefonului. Profilul de serviciu va fi eliminat, iar toate datele profilului vor fi șterse." - "Ați desenat incorect modelul pentru deblocare de %1$d ori. După încă %2$d încercări nereușite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste %3$d (de) secunde." - "Ați desenat incorect modelul pentru deblocare de %1$d ori. După încă %2$d încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste %3$d (de) secunde." + "Ați desenat incorect modelul pentru deblocare de %1$d ori. După încă %2$d încercări nereușite, vi se va solicita să deblocați tableta cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste %3$d secunde." + "Ați desenat incorect modelul pentru deblocare de %1$d ori. După încă %2$d încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste %3$d secunde." "Codul PIN pentru cardul SIM este incorect. Contactați operatorul pentru a vă debloca dispozitivul." Codul PIN pentru cardul SIM este incorect. V-au mai rămas %d încercări. diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml index 264e42ce60957c422a389dd96874eb3d74c4b1fa..7466c6616032e8e7451c0b45021b733ffc78535b 100644 --- a/packages/Keyguard/res/values-ru/strings.xml +++ b/packages/Keyguard/res/values-ru/strings.xml @@ -46,11 +46,6 @@ "SIM-карта заблокирована" "Для разблокировки SIM-карты требуется PUK-код." "Разблокировка SIM-карты…" - "Графический ключ" - "PIN-код" - "Пароль" - "Область ввода графического ключа" - "Область слайдера" "PIN-код" "PIN-код SIM-карты" "PUK-код SIM-карты" diff --git a/packages/Keyguard/res/values-si-rLK/strings.xml b/packages/Keyguard/res/values-si-rLK/strings.xml index 607e8acd51b49c8d1b2634318fe3b0c65dcc03a1..5f96e8c3f8607b03529103392212e7b56f02a778 100644 --- a/packages/Keyguard/res/values-si-rLK/strings.xml +++ b/packages/Keyguard/res/values-si-rLK/strings.xml @@ -46,11 +46,6 @@ "SIM පත අගුළු දමා ඇත." "SIM පත PUK අගුළු ලා ඇත." "SIM පත අගුළු හරිමින්..." - "රටා අගුළු ඇරීම." - "PIN අගුළු ඇරීම." - "මුරපද අගුළු ඇරීම." - "රටා ප්‍රදේශය." - "සර්පණ ප්‍රදේශය." "PIN කොටස" "SIM PIN කොටස" "SIM PUK කොටස" diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml index 4cbfd51bdf87f53b34cfc458c65c69ee5c1ceb81..82a4f1d46bde77043c2822ed5ec403b8080bd38a 100644 --- a/packages/Keyguard/res/values-sk/strings.xml +++ b/packages/Keyguard/res/values-sk/strings.xml @@ -46,11 +46,6 @@ "SIM karta je uzamknutá." "SIM karta je uzamknutá pomocou kódu PUK." "Prebieha odomykanie SIM karty..." - "Odomknutie vzorom." - "Odomknutie kódom PIN." - "Odomknutie heslom." - "Oblasť na zadanie bezpečnostného vzoru." - "Oblasť na prejdenie prstom." "Oblasť kódu PIN" "Oblasť kódu PIN SIM karty" "Oblasť kódu PUK SIM karty" diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml index 91083f50bd8bc665f86eaa8c2b7ad67b7eeafeb1..9100bd3e62ce0020871d489c2dfd74f912199344 100644 --- a/packages/Keyguard/res/values-sl/strings.xml +++ b/packages/Keyguard/res/values-sl/strings.xml @@ -46,11 +46,6 @@ "Kartica SIM je zaklenjena." "Kartica SIM je zaklenjena s kodo PUK." "Odklepanje kartice SIM …" - "Odklepanje z vzorcem." - "Odklepanje s kodo PIN." - "Odklepanje z geslom." - "Območje vzorca." - "Območje podrsanja." "Območje za kodo PIN" "Območje za kodo PIN za SIM" "Območje za kodo PUK za SIM" diff --git a/packages/Keyguard/res/values-sq-rAL/strings.xml b/packages/Keyguard/res/values-sq-rAL/strings.xml index 7f4becbda4f03053b99bf9ea24dbc329a430ee1c..31d31b79c76b9ff60499188b0a93e50ca2d023a1 100644 --- a/packages/Keyguard/res/values-sq-rAL/strings.xml +++ b/packages/Keyguard/res/values-sq-rAL/strings.xml @@ -46,11 +46,6 @@ "Karta SIM është e kyçur." "Karta SIM është e kyçur me PUK." "Po shkyç kartën SIM…" - "Shkyçje me motiv." - "Shkyçje me PIN." - "Shkyçja e fjalëkalimit." - "Zona e motivit." - "Zonën e rrëshqitjes." "Zona PIN" "Zona PIN e kartës SIM" "Zona e PUK-ut të kartës SIM" diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml index 62614a6fd5dff70695f0e68ba8af2820d43d0f3f..23c0b50f9c30a58de30d6f2fab245e4e4f433378 100644 --- a/packages/Keyguard/res/values-sr/strings.xml +++ b/packages/Keyguard/res/values-sr/strings.xml @@ -46,11 +46,6 @@ "SIM картица је закључана." "SIM картица је закључана PUK кодом." "Откључавање SIM картице…" - "Откључавање шаблоном." - "Откључавање PIN-ом." - "Откључавање лозинком." - "Област шаблона." - "Област превлачења." "Област за PIN" "Област за PIN за SIM" "Област за PUK за SIM" @@ -61,7 +56,7 @@ "Погрешан шаблон" "Погрешна лозинка" "Погрешан PIN" - "Покушајте поново за %d секунде(и)." + "Пробајте поново за %d секунде(и)." "Нацртајте шаблон" "Унесите PIN SIM картице" "Унесите PIN за SIM „%1$s“" @@ -77,9 +72,9 @@ "Поново унесите исправни PUK кôд. Поновљени покушаји ће трајно онемогућити SIM." "PIN кодови се не подударају" "Превише покушаја уноса шаблона" - "Унели сте нетачни PIN %1$d пута. \n\nПокушајте поново за %2$d секунде(и)." - "Унели сте нетачну лозинку %1$d пута. \n\nПокушајте поново за %2$d секунде(и)." - "Нацртали сте шаблон за откључавање нетачно %1$d пута. \n\nПокушајте поново за %2$d секунде(и)." + "Унели сте нетачни PIN %1$d пута. \n\nПробајте поново за %2$d секунде(и)." + "Унели сте нетачну лозинку %1$d пута. \n\nПробајте поново за %2$d секунде(и)." + "Нацртали сте шаблон за откључавање нетачно %1$d пута. \n\nПробајте поново за %2$d секунде(и)." "Погрешно сте покушали да откључате таблет %1$d пут(а). Имате још %2$d покушај(а), након чега се таблет ресетује и сви подаци са њега бришу." "Погрешно сте покушали да откључате телефон %1$d пут(а). Имате још %2$d покушај(а), након чега се телефон ресетује и сви подаци са њега бришу." "Погрешно сте покушали да откључате таблет %d пут(а). Таблет ће бити ресетован и сви подаци са њега ће бити избрисани." @@ -92,8 +87,8 @@ "Погрешно сте покушали да откључате телефон %1$d пут(а). Имате још %2$d покушај(а), након чега се пословни профил уклања и сви подаци са профила бришу." "Погрешно сте покушали да откључате таблет %d пут(а). Пословни профил ће бити уклоњен и сви подаци са њега ће бити избрисани." "Погрешно сте покушали да откључате телефон %d пут(а). Пословни профил ће бити уклоњен и сви подаци са њега ће бити избрисани." - "Нацртали сте шаблон за откључавање нетачно %1$d пута. После још %2$d неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПокушајте поново за %3$d секунде(и)." - "Нацртали сте шаблон за откључавање нетачно %1$d пута. После још %2$d неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПокушајте поново за %3$d секунде(и)." + "Нацртали сте шаблон за откључавање нетачно %1$d пута. После још %2$d неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПробајте поново за %3$d секунде(и)." + "Нацртали сте шаблон за откључавање нетачно %1$d пута. После још %2$d неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за %3$d секунде(и)." "Нетачан SIM PIN кôд. Сада морате да контактирате мобилног оператера да бисте откључали уређај." Нетачан SIM PIN кôд. Имате још %d покушај. diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml index 378f0474c28ee402f77ddaf6fe3485dd408cbdf0..4a1d67b8d94a5dc0f9930c016cee7a65b774a3d0 100644 --- a/packages/Keyguard/res/values-sv/strings.xml +++ b/packages/Keyguard/res/values-sv/strings.xml @@ -34,7 +34,7 @@ "Laddas snabbt" "Laddas långsamt" "Anslut din laddare." - "Tryck på Meny om du vill låsa upp." + "Tryck på Meny för att låsa upp." "Nätverk låst" "Inget SIM-kort" "Inget SIM-kort i surfplattan." @@ -46,11 +46,6 @@ "SIM-kortet är låst." "SIM-kortet är PUK-låst." "Låser upp SIM-kort …" - "Lås upp med grafiskt lösenord." - "Lås upp med PIN-kod." - "Lås upp med lösenord." - "Fält för grafiskt lösenord." - "Fält med dragreglage." "Pinkodsområde" "Pinkodsområde för SIM-kort" "PUK-kodsområde för SIM-kort" diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml index b570e9f9f4eb93a05cdcb3c40467e5b691d778f7..c2e7ac9f8824a7785f4afb8027d576111cef417f 100644 --- a/packages/Keyguard/res/values-sw/strings.xml +++ b/packages/Keyguard/res/values-sw/strings.xml @@ -46,11 +46,6 @@ "SIM kadi imefungwa." "SIM kadi imefungwa na PUK." "Inafungua SIM kadi..." - "Kufungua kwa ruwaza." - "Kufungua kwa PIN." - "Kufungua kwa nenosiri." - "Eneo la ruwaza." - "Eneo la slaidi." "Eneo la PIN" "Eneo la PIN ya SIM" "Eneo la PUK ya SIM" diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml index 2e3f588955fd537cca7faabb3f48b01d21bb4d7a..c80ddce068c38ac23eec85bbb3074d655b95c2ea 100644 --- a/packages/Keyguard/res/values-ta-rIN/strings.xml +++ b/packages/Keyguard/res/values-ta-rIN/strings.xml @@ -46,11 +46,6 @@ "சிம் கார்டு பூட்டப்பட்டுள்ளது." "சிம் கார்டு PUK ஆல் பூட்டப்பட்டது." "சிம் கார்டின் தடையைநீக்குகிறது..." - "வடிவம் மூலம் திறத்தல்." - "Pin மூலம் திறத்தல்." - "கடவுச்சொல் மூலம் திறத்தல்." - "வடிவப் பகுதி." - "ஸ்லைடு பகுதி." "PIN பகுதி" "சிம் PIN பகுதி" "சிம் PUK பகுதி" diff --git a/packages/Keyguard/res/values-te-rIN/strings.xml b/packages/Keyguard/res/values-te-rIN/strings.xml index 6c521aad79c4442b32c841ff2ee1308d8faf1927..a72a85b1851ecc3c41a837ba16d8e41741d6036e 100644 --- a/packages/Keyguard/res/values-te-rIN/strings.xml +++ b/packages/Keyguard/res/values-te-rIN/strings.xml @@ -46,11 +46,6 @@ "సిమ్ కార్డు లాక్ చేయబడింది." "సిమ్ కార్డు PUK లాక్ చేయబడింది." "సిమ్ కార్డును అన్‌లాక్ చేస్తోంది…" - "నమూనా అన్‌లాక్." - "పిన్ అన్‌లాక్." - "పాస్‌వర్డ్ అన్‌లాక్." - "నమూనా ప్రాంతం." - "స్లయిడ్ ప్రాంతం." "PIN ప్రాంతం" "SIM PIN ప్రాంతం" "SIM PUK ప్రాంతం" diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml index 1799fe8ddec58e208b9033908a2559f58a68490c..e094d3503f2d29d382e6f6754e4b8523ef1e1ef1 100644 --- a/packages/Keyguard/res/values-th/strings.xml +++ b/packages/Keyguard/res/values-th/strings.xml @@ -46,11 +46,6 @@ "ซิมการ์ดถูกล็อก" "ซิมการ์ดถูกล็อกด้วย PUK" "กำลังปลดล็อกซิมการ์ด…" - "การปลดล็อกด้วยรูปแบบ" - "การปลดล็อกด้วย PIN" - "การปลดล็อกด้วยรหัสผ่าน" - "พื้นที่สำหรับรูปแบบ" - "พื้นที่สำหรับการเลื่อน" "พื้นที่ PIN" "พื้นที่ PIN ของซิม" "พื้นที่ PUK ของซิม" diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml index 39cad7274c39d72433abf9038b1c63189ef9292a..73492e2621b87b0e066da123a3e794d1b47acf4e 100644 --- a/packages/Keyguard/res/values-tl/strings.xml +++ b/packages/Keyguard/res/values-tl/strings.xml @@ -46,11 +46,6 @@ "Naka-lock ang SIM card." "Naka-lock ang SIM card gamit ang PUK." "Ina-unlock ang SIM card…" - "Pag-unlock ng pattern." - "Pag-unlock ng pin." - "Pag-unlock ng password." - "Bahagi ng pattern." - "Bahagi ng slide." "Lugar ng PIN" "Lugar ng PIN ng SIM" "Lugar ng PUK ng SIM" diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml index ffcbd12cf158bdffd18176efb2ebcd2f86a3812a..3ef07056a434bafc2cd67016c8e3ef622dec4d4d 100644 --- a/packages/Keyguard/res/values-tr/strings.xml +++ b/packages/Keyguard/res/values-tr/strings.xml @@ -46,11 +46,6 @@ "SIM kart kilitli." "SIM kart PUK kilidi devrede." "SIM kart kilidi açılıyor…" - "Desenle kilit açma." - "Pin koduyla kilit açma." - "Şifreyle kilit açma." - "Desen alanı." - "Kaydırma alanı." "PIN alanı" "SIM PIN alanı" "SIM PUK alanı" diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml index be19281fec3358e189effcf9ab83e7081105c953..a50868960a8ca6b1c7c1e823a9bd617f36ccbc47 100644 --- a/packages/Keyguard/res/values-uk/strings.xml +++ b/packages/Keyguard/res/values-uk/strings.xml @@ -46,11 +46,6 @@ "SIM-карту заблоковано." "SIM-карту заблоковано PUK-кодом." "Розблокування SIM-карти…" - "Розблокування ключем." - "Розблокування PIN-кодом." - "Розблокування паролем." - "Область ключа." - "Область повзунка." "PIN-код" "PIN-код SIM-карти" "PUK-код SIM-карти" diff --git a/packages/Keyguard/res/values-ur-rPK/strings.xml b/packages/Keyguard/res/values-ur-rPK/strings.xml index 63f4e85034f2e936fdef3105ad4ccd38fc5acd77..1070d58a8dc5d5c639cc2c551236023218e3d0fa 100644 --- a/packages/Keyguard/res/values-ur-rPK/strings.xml +++ b/packages/Keyguard/res/values-ur-rPK/strings.xml @@ -46,11 +46,6 @@ "‏SIM کارڈ مقفل ہے۔" "‏SIM کارڈ PUK-مقفل ہے۔" "‏SIM کارڈ غیر مقفل کیا جا رہا ہے…" - "پیٹرن کے ذریعے غیر مقفل کریں۔" - "پن کے ذریعے غیر مقفل کریں۔" - "پاس ورڈ کے ذریعہ غیر مقفل کریں۔" - "پیٹرن کا علاقہ۔" - "سلائیڈ کرنے کا علاقہ۔" "‏PIN کا علاقہ" "‏SIM PIN کا علاقہ" "‏SIM PUK کا علاقہ" diff --git a/packages/Keyguard/res/values-uz-rUZ/strings.xml b/packages/Keyguard/res/values-uz-rUZ/strings.xml index ad71a56651c38a499500bf13120ef52f59bcbf40..a9df331487e66ffb7fd6359e6133ca4f1576bcaa 100644 --- a/packages/Keyguard/res/values-uz-rUZ/strings.xml +++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml @@ -46,11 +46,6 @@ "SIM karta qulflangan." "SIM karta PUK kod bilan qulflangan." "SIM karta qulfi ochilmoqda…" - "Grafik kalit bilan ochish." - "Pin qulfini ochish." - "Parolli qulfni ochish." - "Grafik kalit chiziladigan hudud." - "Maydonni silang" "PIN-kod maydoni" "SIM karta PIN kodi maydoni" "SIM karta PUK kodi maydoni" diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml index ad3da9fbf32d431530347c454cc1cf79edec4bd3..c6d2bd808e8b73299951515793d259047fc33f1e 100644 --- a/packages/Keyguard/res/values-vi/strings.xml +++ b/packages/Keyguard/res/values-vi/strings.xml @@ -46,11 +46,6 @@ "Thẻ SIM đã bị khóa." "Thẻ SIM đã bị khóa PUK." "Đang mở khóa thẻ SIM…" - "Mở khóa bằng hình." - "Mở khóa bằng mã pin." - "Mở khóa bằng mật khẩu." - "Khu vực hình." - "Khu vực trượt." "Khu vực mã PIN" "Khu vực mã PIN của SIM" "Khu vực PUK của SIM" diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml index 274d9e69492ed3570516d47f5838b27d01d71dea..e15950f7779d022ad845339b6cbc853ee25d8e55 100644 --- a/packages/Keyguard/res/values-zh-rCN/strings.xml +++ b/packages/Keyguard/res/values-zh-rCN/strings.xml @@ -36,7 +36,7 @@ "请连接充电器。" "按“菜单”键解锁。" "网络已锁定" - "无 SIM 卡" + "没有 SIM 卡" "平板电脑中没有SIM卡。" "手机中没有SIM卡。" "请插入SIM卡。" @@ -46,11 +46,6 @@ "SIM卡已被锁定。" "SIM卡已被PUK码锁定。" "正在解锁SIM卡..." - "图案解锁。" - "PIN码解锁。" - "密码解锁。" - "图案区域。" - "滑动区域。" "PIN 码区域" "SIM 卡 PIN 码区域" "SIM 卡 PUK 码区域" diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml index 7d511540d7eca8078b8d827490f0292f596fa22d..5b1903b4b96126c5fc280860e371d852adf484a8 100644 --- a/packages/Keyguard/res/values-zh-rHK/strings.xml +++ b/packages/Keyguard/res/values-zh-rHK/strings.xml @@ -46,11 +46,6 @@ "SIM 卡處於鎖定狀態。" "SIM 卡處於 PUK 鎖定狀態。" "正在解開上鎖的 SIM 卡..." - "圖案解鎖。" - "PIN 解鎖。" - "密碼解鎖。" - "圖案區域。" - "滑動區域。" "PIN 區域" "SIM PIN 區域" "SIM PUK 區域" diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml index 50895f3da3b9169851c5425c534a957904fce0db..388f8e17872ac848b91042a437ac6a8b95c5a605 100644 --- a/packages/Keyguard/res/values-zh-rTW/strings.xml +++ b/packages/Keyguard/res/values-zh-rTW/strings.xml @@ -46,11 +46,6 @@ "SIM 卡處於鎖定狀態。" "SIM 卡處於 PUK 鎖定狀態" "正在解除 SIM 卡鎖定..." - "圖案解鎖。" - "PIN 解鎖。" - "密碼解鎖。" - "圖案區域。" - "滑動區域。" "PIN 區" "SIM 卡 PIN 區" "SIM 卡 PUK 區" diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml index c5f2a85bd4b863e7f83da2cbaabde9212697538f..a9b62634548aec9646c6766d4564ff95028940d5 100644 --- a/packages/Keyguard/res/values-zu/strings.xml +++ b/packages/Keyguard/res/values-zu/strings.xml @@ -46,11 +46,6 @@ "Ikhadi le-SIM likhiyiwe." "Ikhadi le-SIM likhiywe nge-PUK." "Ivula ikhadi le-SIM..." - "Ukuvula ngephethini." - "Ukuvula ngephinikhodi." - "Ukuvula ngephasiwedi." - "Indawo yephethini." - "Indawo yokushelelisa." "Indawo yephinikhodi" "Indawo yephinikhodi ye-SIM" "Indawo ye-SIM PUK" diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml index 09fec81e45ac3bc8401cf813529f47ce6a4033f5..ff689aab7a745c058e2500ee5aabfb9309195691 100644 --- a/packages/Keyguard/res/values/strings.xml +++ b/packages/Keyguard/res/values/strings.xml @@ -103,15 +103,6 @@ kk\uee01mm - Pattern unlock. - - Pin unlock. - - Password unlock. - - Pattern area. - - Slide area. PIN area diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java index 725684332fe964fca0b1a8f3de79df791ab82d4b..0474df7bd89cb29aa72105822f320aed068a01e4 100644 --- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java +++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java @@ -151,6 +151,11 @@ public class EmergencyButton extends Button { return super.onTouchEvent(event); } + @Override + public boolean performLongClick() { + return super.performLongClick(); + } + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java index 60eaad2699eea3f84bf6ba2481b1d8e99e031cdc..038e08d758eb01c59c259c150bd4c0ff507a63a6 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -137,12 +137,21 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout entry, userId, new LockPatternChecker.OnCheckCallback() { + + @Override + public void onEarlyMatched() { + onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */, + true /* isValidPassword */); + } + @Override public void onChecked(boolean matched, int timeoutMs) { setPasswordEntryInputEnabled(true); mPendingLockCheck = null; - onPasswordChecked(userId, matched, timeoutMs, - true /* isValidPassword */); + if (!matched) { + onPasswordChecked(userId, false /* matched */, timeoutMs, + true /* isValidPassword */); + } } }); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java index 7ea767c004fb50a8a925f041cec640609ddd7c94..285b1aeb7bebc0ff3c46d37e8290fc3075fb05bc 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java @@ -16,12 +16,8 @@ package com.android.keyguard; -import android.animation.Animator; -import android.animation.ObjectAnimator; import android.content.Context; import android.util.AttributeSet; -import android.view.RenderNode; -import android.view.RenderNodeAnimator; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; @@ -36,6 +32,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { private final AppearAnimationUtils mAppearAnimationUtils; private final DisappearAnimationUtils mDisappearAnimationUtils; + private final DisappearAnimationUtils mDisappearAnimationUtilsLocked; private ViewGroup mContainer; private ViewGroup mRow0; private ViewGroup mRow1; @@ -44,6 +41,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { private View mDivider; private int mDisappearYTranslation; private View[][] mViews; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; public KeyguardPINView(Context context) { this(context, null); @@ -56,8 +54,14 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { 125, 0.6f /* translationScale */, 0.45f /* delayScale */, AnimationUtils.loadInterpolator( mContext, android.R.interpolator.fast_out_linear_in)); + mDisappearAnimationUtilsLocked = new DisappearAnimationUtils(context, + (long) (125 * KeyguardPatternView.DISAPPEAR_MULTIPLIER_LOCKED), + 0.6f /* translationScale */, + 0.45f /* delayScale */, AnimationUtils.loadInterpolator( + mContext, android.R.interpolator.fast_out_linear_in)); mDisappearYTranslation = getResources().getDimensionPixelSize( R.dimen.disappear_y_translation); + mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context); } @Override @@ -136,7 +140,11 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { setTranslationY(0); AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 280 /* duration */, mDisappearYTranslation, mDisappearAnimationUtils.getInterpolator()); - mDisappearAnimationUtils.startAnimation2d(mViews, + DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor + .needsSlowUnlockTransition() + ? mDisappearAnimationUtilsLocked + : mDisappearAnimationUtils; + disappearAnimationUtils.startAnimation2d(mViews, new Runnable() { @Override public void run() { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java index b75f52987a928c5cc5fd910a94231c8a2e5ba2fa..ddccc14a60f00797ac32bac791a0634c7eb10096 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java @@ -42,16 +42,21 @@ import java.util.List; * Displays an alphanumeric (latin-1) key entry for the user to enter * an unlock password */ - public class KeyguardPasswordView extends KeyguardAbsKeyInputView implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { private final boolean mShowImeAtScreenOn; private final int mDisappearYTranslation; + // A delay constant to be used in a workaround for the situation where InputMethodManagerService + // is not switched to the new user yet. + // TODO: Remove this by ensuring such a race condition never happens. + private static final int DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON = 500; // 500ms + InputMethodManager mImm; private TextView mPasswordEntry; private TextViewInputDisabler mPasswordEntryDisabler; + private View mSwitchImeButton; private Interpolator mLinearOutSlowInInterpolator; private Interpolator mFastOutLinearInInterpolator; @@ -141,12 +146,31 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView mPasswordEntry.requestFocus(); } + private void updateSwitchImeButton() { + // If there's more than one IME, enable the IME switcher button + final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE; + final boolean shouldBeVisible = hasMultipleEnabledIMEsOrSubtypes(mImm, false); + if (wasVisible != shouldBeVisible) { + mSwitchImeButton.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE); + } + + // TODO: Check if we still need this hack. + // If no icon is visible, reset the start margin on the password field so the text is + // still centered. + if (mSwitchImeButton.getVisibility() != View.VISIBLE) { + android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); + if (params instanceof MarginLayoutParams) { + final MarginLayoutParams mlp = (MarginLayoutParams) params; + mlp.setMarginStart(0); + mPasswordEntry.setLayoutParams(params); + } + } + } + @Override protected void onFinishInflate() { super.onFinishInflate(); - boolean imeOrDeleteButtonVisible = false; - mImm = (InputMethodManager) getContext().getSystemService( Context.INPUT_METHOD_SERVICE); @@ -171,31 +195,29 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView mPasswordEntry.requestFocus(); + mSwitchImeButton = findViewById(R.id.switch_ime_button); + mSwitchImeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mCallback.userActivity(); // Leave the screen on a bit longer + // Do not show auxiliary subtypes in password lock screen. + mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */); + } + }); + // If there's more than one IME, enable the IME switcher button - View switchImeButton = findViewById(R.id.switch_ime_button); - if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) { - switchImeButton.setVisibility(View.VISIBLE); - imeOrDeleteButtonVisible = true; - switchImeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mCallback.userActivity(); // Leave the screen on a bit longer - // Do not show auxiliary subtypes in password lock screen. - mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */); - } - }); - } + updateSwitchImeButton(); - // If no icon is visible, reset the start margin on the password field so the text is - // still centered. - if (!imeOrDeleteButtonVisible) { - android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); - if (params instanceof MarginLayoutParams) { - final MarginLayoutParams mlp = (MarginLayoutParams) params; - mlp.setMarginStart(0); - mPasswordEntry.setLayoutParams(params); + // When we the current user is switching, InputMethodManagerService sometimes has not + // switched internal state yet here. As a quick workaround, we check the keyboard state + // again. + // TODO: Remove this workaround by ensuring such a race condition never happens. + postDelayed(new Runnable() { + @Override + public void run() { + updateSwitchImeButton(); } - } + }, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON); } @Override diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java index e07049262c6ec0be0f1a65e9c354b0ccdf1d7dbb..506f77d443c6828fa4e9bc1e33dfb5c0efe5bbed 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java @@ -55,9 +55,13 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit // how many cells the user has to cross before we poke the wakelock private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2; + // How much we scale up the duration of the disappear animation when the current user is locked + public static final float DISAPPEAR_MULTIPLIER_LOCKED = 1.5f; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final AppearAnimationUtils mAppearAnimationUtils; private final DisappearAnimationUtils mDisappearAnimationUtils; + private final DisappearAnimationUtils mDisappearAnimationUtilsLocked; private CountDownTimer mCountdownTimer = null; private LockPatternUtils mLockPatternUtils; @@ -109,6 +113,10 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit 125, 1.2f /* translationScale */, 0.6f /* delayScale */, AnimationUtils.loadInterpolator( mContext, android.R.interpolator.fast_out_linear_in)); + mDisappearAnimationUtilsLocked = new DisappearAnimationUtils(context, + (long) (125 * DISAPPEAR_MULTIPLIER_LOCKED), 1.2f /* translationScale */, + 0.6f /* delayScale */, AnimationUtils.loadInterpolator( + mContext, android.R.interpolator.fast_out_linear_in)); mDisappearYTranslation = getResources().getDimensionPixelSize( R.dimen.disappear_y_translation); } @@ -239,11 +247,21 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit pattern, userId, new LockPatternChecker.OnCheckCallback() { + + @Override + public void onEarlyMatched() { + onPatternChecked(userId, true /* matched */, 0 /* timeoutMs */, + true /* isValidPattern */); + } + @Override public void onChecked(boolean matched, int timeoutMs) { mLockPatternView.enableInput(); mPendingLockCheck = null; - onPatternChecked(userId, matched, timeoutMs, true); + if (!matched) { + onPatternChecked(userId, false /* matched */, timeoutMs, + true /* isValidPattern */); + } } }); if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) { @@ -390,25 +408,31 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit @Override public boolean startDisappearAnimation(final Runnable finishRunnable) { + float durationMultiplier = mKeyguardUpdateMonitor.needsSlowUnlockTransition() + ? DISAPPEAR_MULTIPLIER_LOCKED + : 1f; mLockPatternView.clearPattern(); enableClipping(false); setTranslationY(0); - AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 300 /* duration */, + AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, + (long) (300 * durationMultiplier), -mDisappearAnimationUtils.getStartTranslation(), mDisappearAnimationUtils.getInterpolator()); - mDisappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(), - new Runnable() { - @Override - public void run() { - enableClipping(true); - if (finishRunnable != null) { - finishRunnable.run(); - } + + DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor + .needsSlowUnlockTransition() + ? mDisappearAnimationUtilsLocked + : mDisappearAnimationUtils; + disappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(), + () -> { + enableClipping(true); + if (finishRunnable != null) { + finishRunnable.run(); } }, KeyguardPatternView.this); if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) { mDisappearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0, - 200, + (long) (200 * durationMultiplier), - mDisappearAnimationUtils.getStartTranslation() * 3, false /* appearing */, mDisappearAnimationUtils.getInterpolator(), diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java index 8d6e07e619ff0b0dd616c5597ce0117765c54b4d..108b466e44afbad44463f74b5a32775912a4dfbe 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -20,13 +20,14 @@ import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; /** * A Pin based Keyguard input view */ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView - implements View.OnKeyListener { + implements View.OnKeyListener, View.OnTouchListener { protected PasswordTextView mPasswordEntry; private View mOkButton; @@ -185,10 +186,10 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView mOkButton = findViewById(R.id.key_enter); if (mOkButton != null) { + mOkButton.setOnTouchListener(this); mOkButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - doHapticKeyClick(); if (mPasswordEntry.isEnabled()) { verifyPasswordAndUnlock(); } @@ -199,6 +200,7 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView mDeleteButton = findViewById(R.id.delete_button); mDeleteButton.setVisibility(View.VISIBLE); + mDeleteButton.setOnTouchListener(this); mDeleteButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -206,7 +208,6 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView if (mPasswordEntry.isEnabled()) { mPasswordEntry.deleteLastChar(); } - doHapticKeyClick(); } }); mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() { @@ -236,6 +237,14 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView super.onFinishInflate(); } + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + doHapticKeyClick(); + } + return false; + } + @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java index aa74940492f218d96f0bd39c36764f94be29d9eb..829084202f5af6f009e40a05f621fbe2429a79bb 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java @@ -48,11 +48,6 @@ public interface KeyguardSecurityView { */ int PROMPT_REASON_AFTER_LOCKOUT = 5; - /** - * Some auth is required because a single wrong credential has been tried. - */ - int PROMPT_REASON_WRONG_CREDENTIAL = 6; - /** * Interface back to keyguard to tell it when security * @param callback diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java index 9d1df26514eeed08454f06859f2772ec4897b6b9..e1657c7dacc277bbfba0de580f69d1daf58fca43 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java @@ -127,6 +127,11 @@ public class KeyguardStatusView extends GridLayout { super.onConfigurationChanged(newConfig); mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.widget_big_font_size)); + // Some layouts like burmese have a different margin for the clock + MarginLayoutParams layoutParams = (MarginLayoutParams) mClockView.getLayoutParams(); + layoutParams.bottomMargin = getResources().getDimensionPixelSize( + R.dimen.bottom_text_spacing_digital); + mClockView.setLayoutParams(layoutParams); mDateView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.widget_label_font_size)); mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX, diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index a8419bf4cbdfb77f6dafc5a7f428e64036d8b136..a9f6dc9052b3ac56db227d721e7bf8a18f75c54a 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -16,6 +16,17 @@ package com.android.keyguard; +import static android.content.Intent.ACTION_USER_UNLOCKED; +import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; +import static android.os.BatteryManager.BATTERY_STATUS_FULL; +import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; +import static android.os.BatteryManager.EXTRA_HEALTH; +import static android.os.BatteryManager.EXTRA_LEVEL; +import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT; +import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE; +import static android.os.BatteryManager.EXTRA_PLUGGED; +import static android.os.BatteryManager.EXTRA_STATUS; + import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AlarmManager; @@ -24,12 +35,14 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.graphics.Bitmap; -import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; @@ -41,7 +54,9 @@ import android.os.IRemoteCallback; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; +import android.os.Trace; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; @@ -69,16 +84,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map.Entry; -import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN; -import static android.os.BatteryManager.BATTERY_STATUS_FULL; -import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; -import static android.os.BatteryManager.EXTRA_HEALTH; -import static android.os.BatteryManager.EXTRA_LEVEL; -import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT; -import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE; -import static android.os.BatteryManager.EXTRA_PLUGGED; -import static android.os.BatteryManager.EXTRA_STATUS; - /** * Watches for updates that may be interesting to the keyguard, and provides * the up to date information as well as a registration for callbacks that care @@ -107,12 +112,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF"; - /** - * Milliseconds after unlocking with fingerprint times out, i.e. the user has to use a - * strong auth method like password, PIN or pattern. - */ - private static final long FINGERPRINT_UNLOCK_TIMEOUT_MS = 72 * 60 * 60 * 1000; - // Callback messages private static final int MSG_TIME_UPDATE = 301; private static final int MSG_BATTERY_UPDATE = 302; @@ -137,6 +136,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int MSG_SERVICE_STATE_CHANGE = 330; private static final int MSG_SCREEN_TURNED_ON = 331; private static final int MSG_SCREEN_TURNED_OFF = 332; + private static final int MSG_DREAMING_STATE_CHANGED = 333; + private static final int MSG_USER_UNLOCKED = 334; /** Fingerprint state: Not listening to fingerprint. */ private static final int FINGERPRINT_STATE_STOPPED = 0; @@ -158,6 +159,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private static final int DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT = 5000000; + private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName( + "com.android.settings", "com.android.settings.FallbackHome"); + private static KeyguardUpdateMonitor sInstance; private final Context mContext; @@ -176,6 +180,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private boolean mGoingToSleep; private boolean mBouncer; private boolean mBootCompleted; + private boolean mNeedsSlowUnlockTransition; + private boolean mHasLockscreenWallpaper; // Device provisioning state private boolean mDeviceProvisioned; @@ -202,6 +208,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private AlarmManager mAlarmManager; private List mSubscriptionInfo; private TrustManager mTrustManager; + private UserManager mUserManager; private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED; private final Handler mHandler = new Handler() { @@ -257,10 +264,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { handleFinishedGoingToSleep(msg.arg1); break; case MSG_STARTED_WAKING_UP: + Trace.beginSection("KeyguardUpdateMonitor#handler MSG_STARTED_WAKING_UP"); handleStartedWakingUp(); + Trace.endSection(); break; case MSG_FACE_UNLOCK_STATE_CHANGED: + Trace.beginSection("KeyguardUpdateMonitor#handler MSG_FACE_UNLOCK_STATE_CHANGED"); handleFaceUnlockStateChanged(msg.arg1 != 0, msg.arg2); + Trace.endSection(); break; case MSG_SIM_SUBSCRIPTION_INFO_CHANGED: handleSimSubscriptionInfoChanged(); @@ -275,7 +286,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { handleScreenTurnedOn(); break; case MSG_SCREEN_TURNED_OFF: + Trace.beginSection("KeyguardUpdateMonitor#handler MSG_SCREEN_TURNED_ON"); handleScreenTurnedOff(); + Trace.endSection(); + break; + case MSG_DREAMING_STATE_CHANGED: + handleDreamingStateChanged(msg.arg1); + break; + case MSG_USER_UNLOCKED: + handleUserUnlocked(); break; } } @@ -370,7 +389,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } /** @return List of SubscriptionInfo records, maybe empty but never null */ - List getSubscriptionInfo(boolean forceReload) { + public List getSubscriptionInfo(boolean forceReload) { List sil = mSubscriptionInfo; if (sil == null || forceReload) { sil = mSubscriptionManager.getActiveSubscriptionInfoList(); @@ -397,6 +416,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void onFingerprintAuthenticated(int userId) { + Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated"); mUserFingerprintAuthenticated.put(userId, true); // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a @@ -409,6 +429,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onFingerprintAuthenticated(userId); } } + Trace.endSection(); } private void handleFingerprintAuthFailed() { @@ -433,7 +454,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - private void handleFingerprintAuthenticated() { + private void handleFingerprintAuthenticated(int authUserId) { + Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated"); try { final int userId; try { @@ -442,6 +464,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { Log.e(TAG, "Failed to get current user id: ", e); return; } + if (userId != authUserId) { + Log.d(TAG, "Fingerprint authenticated for wrong user: " + authUserId); + return; + } if (isFingerprintDisabled(userId)) { Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId); return; @@ -450,6 +476,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } finally { setFingerprintRunningState(FINGERPRINT_STATE_STOPPED); } + Trace.endSection(); } private void handleFingerprintHelp(int msgId, String helpString) { @@ -554,6 +581,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { && !hasFingerprintUnlockTimedOut(sCurrentUser); } + public boolean needsSlowUnlockTransition() { + return mNeedsSlowUnlockTransition; + } + public StrongAuthTracker getStrongAuthTracker() { return mStrongAuthTracker; } @@ -576,7 +607,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } private void scheduleStrongAuthTimeout() { - long when = SystemClock.elapsedRealtime() + FINGERPRINT_UNLOCK_TIMEOUT_MS; + final DevicePolicyManager dpm = + (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); + long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, + sCurrentUser); Intent intent = new Intent(ACTION_STRONG_AUTH_TIMEOUT); intent.putExtra(USER_ID, sCurrentUser); PendingIntent sender = PendingIntent.getBroadcast(mContext, @@ -684,14 +718,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_INFO_CHANGED, intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()), 0)); } else if (ACTION_FACE_UNLOCK_STARTED.equals(action)) { + Trace.beginSection("KeyguardUpdateMonitor.mBroadcastAllReceiver#onReceive ACTION_FACE_UNLOCK_STARTED"); mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 1, getSendingUserId())); + Trace.endSection(); } else if (ACTION_FACE_UNLOCK_STOPPED.equals(action)) { mHandler.sendMessage(mHandler.obtainMessage(MSG_FACE_UNLOCK_STATE_CHANGED, 0, getSendingUserId())); } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED .equals(action)) { mHandler.sendEmptyMessage(MSG_DPM_STATE_CHANGED); + } else if (ACTION_USER_UNLOCKED.equals(action)) { + mHandler.sendEmptyMessage(MSG_USER_UNLOCKED); } } }; @@ -725,7 +763,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { @Override public void onAuthenticationSucceeded(AuthenticationResult result) { - handleFingerprintAuthenticated(); + Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded"); + handleFingerprintAuthenticated(result.getUserId()); + Trace.endSection(); } @Override @@ -900,6 +940,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } protected void handleStartedWakingUp() { + Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp"); updateFingerprintListeningState(); final int count = mCallbacks.size(); for (int i = 0; i < count; i++) { @@ -908,6 +949,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onStartedWakingUp(); } } + Trace.endSection(); } protected void handleStartedGoingToSleep(int arg1) { @@ -956,6 +998,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + private void handleDreamingStateChanged(int dreamStart) { + final int count = mCallbacks.size(); + boolean showingDream = dreamStart == 1; + for (int i = 0; i < count; i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onDreamingStateChanged(showingDream); + } + } + } + /** * IMPORTANT: Must be called from UI thread. */ @@ -979,6 +1032,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + private void handleUserUnlocked() { + mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition(); + for (int i = 0; i < mCallbacks.size(); i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onUserUnlocked(); + } + } + } + private KeyguardUpdateMonitor(Context context) { mContext = context; mSubscriptionManager = SubscriptionManager.from(context); @@ -1019,6 +1082,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { allUserFilter.addAction(ACTION_FACE_UNLOCK_STARTED); allUserFilter.addAction(ACTION_FACE_UNLOCK_STOPPED); allUserFilter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); + allUserFilter.addAction(ACTION_USER_UNLOCKED); context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter, null, null); @@ -1040,10 +1104,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { public void onForegroundProfileSwitch(int newProfileId) { // Ignore. } - }); + }, TAG); } catch (RemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + e.rethrowAsRuntimeException(); } IntentFilter strongAuthTimeoutFilter = new IntentFilter(); @@ -1059,6 +1122,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { if (mFpm != null) { mFpm.addLockoutResetCallback(mLockoutResetCallback); } + + mUserManager = context.getSystemService(UserManager.class); } private void updateFingerprintListeningState() { @@ -1144,6 +1209,30 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } + /** + * Update the state whether Keyguard currently has a lockscreen wallpaper. + * + * @param hasLockscreenWallpaper Whether Keyguard has a lockscreen wallpaper. + */ + public void setHasLockscreenWallpaper(boolean hasLockscreenWallpaper) { + if (hasLockscreenWallpaper != mHasLockscreenWallpaper) { + mHasLockscreenWallpaper = hasLockscreenWallpaper; + for (int i = mCallbacks.size() - 1; i >= 0; i--) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onHasLockscreenWallpaperChanged(hasLockscreenWallpaper); + } + } + } + } + + /** + * @return Whether Keyguard has a lockscreen wallpaper. + */ + public boolean hasLockscreenWallpaper() { + return mHasLockscreenWallpaper; + } + /** * Handle {@link #MSG_DPM_STATE_CHANGED} */ @@ -1391,6 +1480,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private void handleKeyguardReset() { if (DEBUG) Log.d(TAG, "handleKeyguardReset"); updateFingerprintListeningState(); + mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition(); + } + + private boolean resolveNeedsSlowUnlockTransition() { + if (mUserManager.isUserUnlocked(getCurrentUser())) { + return false; + } + Intent homeIntent = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME); + ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivity(homeIntent, + 0 /* flags */); + return FALLBACK_HOME_COMPONENT.equals(resolveInfo.getComponentInfo().getComponentName()); } /** @@ -1665,6 +1766,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF); } + public void dispatchDreamingStarted() { + mHandler.sendMessage(mHandler.obtainMessage(MSG_DREAMING_STATE_CHANGED, 1, 0)); + } + + public void dispatchDreamingStopped() { + mHandler.sendMessage(mHandler.obtainMessage(MSG_DREAMING_STATE_CHANGED, 0, 0)); + } + public boolean isDeviceInteractive() { return mDeviceInteractive; } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index bd6c51c3b89c07a3ea900ce17a701f97be08e769..14d6b599a9b53b7b6578bd9466ec5de0bf6f853b 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -127,6 +127,11 @@ public class KeyguardUpdateMonitorCallback { */ public void onUserInfoChanged(int userId) { } + /** + * Called when a user got unlocked. + */ + public void onUserUnlocked() { } + /** * Called when boot completed. * @@ -240,4 +245,15 @@ public class KeyguardUpdateMonitorCallback { * has changed. */ public void onStrongAuthStateChanged(int userId) { } + + /** + * Called when the state whether we have a lockscreen wallpaper has changed. + */ + public void onHasLockscreenWallpaperChanged(boolean hasLockscreenWallpaper) { } + + /** + * Called when the dream's window state is changed. + * @param dreaming true if the dream's window has been created and is visible + */ + public void onDreamingStateChanged(boolean dreaming) { } } diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java index 2ff7e121721a5adbed7afa4e745ef1d4fcf1574b..1518bdced99a57ddd1f7fdbc05b9c58d50550b76 100644 --- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java +++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java @@ -23,6 +23,7 @@ import android.os.SystemClock; import android.util.AttributeSet; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -53,8 +54,7 @@ public class NumPadKey extends ViewGroup { if (mTextView != null && mTextView.isEnabled()) { mTextView.append(Character.forDigit(mDigit, 10)); } - userActivity(); - doHapticKeyClick(); + userActivity();; } }; @@ -125,6 +125,14 @@ public class NumPadKey extends ViewGroup { setContentDescription(mDigitText.getText().toString()); } + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + doHapticKeyClick(); + } + return super.onTouchEvent(event); + } + @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); diff --git a/packages/MtpDocumentsProvider/res/values-gl-rES/strings.xml b/packages/MtpDocumentsProvider/res/values-gl-rES/strings.xml index 54bf4a9771ecf3296a365befe331e99cd18efbbe..7e61c7cedff98a8c66c8b6e75f57e0549919f4c2 100644 --- a/packages/MtpDocumentsProvider/res/values-gl-rES/strings.xml +++ b/packages/MtpDocumentsProvider/res/values-gl-rES/strings.xml @@ -19,7 +19,7 @@ "Host MTP" "Descargas" "%2$s de %1$s" - "Accedendo aos ficheiros de %1$s" + "Accedendo aos ficheiros do dispositivo %1$s" "O outro dispositivo está ocupado. Non podes transferir ficheiros ata que estea dispoñible." "Non se atopou ningún ficheiro. Se o outro dispositivo está bloqueado, desbloquéao e téntao de novo." diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java index cce619e67d198ddb6164cc652727e3bc820a0ecc..4950af3e14e08cfcef5c44e594f019a3689607f0 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java @@ -873,7 +873,7 @@ class MtpDatabase { } private static int getRootFlags(int[] operationsSupported) { - int rootFlag = Root.FLAG_SUPPORTS_IS_CHILD; + int rootFlag = Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_LOCAL_ONLY; if (MtpDeviceRecord.isWritingSupported(operationsSupported)) { rootFlag |= Root.FLAG_SUPPORTS_CREATE; } diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java index 404047b8baed8ea6982269b745b60c3945012ae9..8c13c813552babe0151ff619dad9604298f840c4 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java @@ -128,7 +128,7 @@ public class MtpDatabaseTest extends AndroidTestCase { cursor.moveToNext(); assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID)); assertEquals( - Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, + Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY, getInt(cursor, Root.COLUMN_FLAGS)); assertEquals(R.drawable.ic_root_mtp, getInt(cursor, Root.COLUMN_ICON)); assertEquals("Device Storage", getString(cursor, Root.COLUMN_TITLE)); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java index 9ed15c82f33649e07856999b97b39898216a6efa..d19b46083f91fac3a0873f3481aa4d895fda5aab 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java @@ -210,7 +210,11 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { assertEquals(2, cursor.getCount()); cursor.moveToNext(); assertEquals("1", cursor.getString(0)); - assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1)); + assertEquals( + Root.FLAG_SUPPORTS_IS_CHILD | + Root.FLAG_SUPPORTS_CREATE | + Root.FLAG_LOCAL_ONLY, + cursor.getInt(1)); assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2)); assertEquals("Device A Storage A", cursor.getString(3)); assertEquals("1", cursor.getString(4)); @@ -225,7 +229,8 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { cursor.moveToNext(); cursor.moveToNext(); assertEquals("2", cursor.getString(0)); - assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1)); + assertEquals( + Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_LOCAL_ONLY, cursor.getInt(1)); assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2)); assertEquals("Device B Storage B", cursor.getString(3)); assertEquals("2", cursor.getString(4)); @@ -271,7 +276,9 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { cursor.moveToNext(); assertEquals("1", cursor.getString(0)); - assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1)); + assertEquals( + Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY, + cursor.getInt(1)); assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2)); assertEquals("Device A", cursor.getString(3)); assertEquals("1", cursor.getString(4)); @@ -279,7 +286,9 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { cursor.moveToNext(); assertEquals("2", cursor.getString(0)); - assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1)); + assertEquals( + Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY, + cursor.getInt(1)); assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2)); assertEquals("Device B Storage B", cursor.getString(3)); assertEquals("2", cursor.getString(4)); diff --git a/packages/PrintSpooler/res/drawable/print_button.xml b/packages/PrintSpooler/res/drawable/print_button.xml index b59afba80293972c3fde4eb987ce643213acb720..01141032e66f52033107af87006635c6549be1fa 100644 --- a/packages/PrintSpooler/res/drawable/print_button.xml +++ b/packages/PrintSpooler/res/drawable/print_button.xml @@ -16,7 +16,7 @@ --> + android:color="?android:attr/colorControlHighlight"> diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml index 2db6fb06480cda166a7126f828509c2e36dbf144..31a776c99e805dd47a5ee5d47ae07a1b7ca88766 100644 --- a/packages/PrintSpooler/res/layout/print_activity.xml +++ b/packages/PrintSpooler/res/layout/print_activity.xml @@ -16,7 +16,6 @@ @@ -28,12 +27,14 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingStart="8dip" + android:layout_marginEnd="16dp" android:elevation="@dimen/preview_controls_elevation" android:background="?android:attr/colorPrimary"> diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml index d23e1bc93595e44dc9639634707b03227ed945ee..9751ca283b7d88ede1590f48e46481a85237197c 100644 --- a/packages/PrintSpooler/res/values-ar/strings.xml +++ b/packages/PrintSpooler/res/values-ar/strings.xml @@ -30,7 +30,7 @@ "اختر طابعة" "جميع الصفحات وعددها %1$s" "النطاق %1$s" - "مثلاً، ۱—۵،‏۹،۷—۱۰" + "مثلاً، ١—٥،‏٨،‏١١—١٣" "معاينة قبل الطباعة" "‏تثبيت برنامج عرض PDF للمعاينة" "تعطّل تطبيق الطباعة" diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml index 6d03880d5399ec9215ff3c7efb88d29a41239d42..0519083eb4af47f5a4635e49b7d188e6f7d7e4db 100644 --- a/packages/PrintSpooler/res/values-ja/strings.xml +++ b/packages/PrintSpooler/res/values-ja/strings.xml @@ -29,7 +29,7 @@ "ページ" "プリンタを選択" "%1$sページすべて" - "%1$sページ分" + "範囲選択(%1$sページ内)" "例: 1-5,8,11-13" "印刷プレビュー" "プレビュー用PDFビューアをインストール" diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml index f4b9d6190f4addfc1fd1928d591ce66207618a60..487ac0128159630995896d6f678f95b7c0a1ed26 100644 --- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml +++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml @@ -47,7 +47,7 @@ "PDF ಗೆ ಉಳಿಸು" "ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ವಿಸ್ತರಿಸಲಾಗಿದೆ" "ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ" - "ಹುಡುಕು" + "ಹುಡುಕಿ" "ಎಲ್ಲಾ ಪ್ರಿಂಟರ್‌ಗಳು" "ಸೇವೆಯನ್ನು ಸೇರಿಸು" "ಹುಡುಕಾಟ ಪೆಟ್ಟಿಗೆಯನ್ನು ತೋರಿಸಲಾಗಿದೆ" @@ -81,10 +81,10 @@ "%1$s ರದ್ದು ಮಾಡಲಾಗುತ್ತಿದೆ" "ಮುದ್ರಕ ದೋಷ %1$s" "ಮುದ್ರಕವು %1$s ನಿರ್ಬಂಧಿಸಿದೆ" - "ರದ್ದುಮಾಡು" + "ರದ್ದುಮಾಡಿ" "ಮರುಪ್ರಾರಂಭಿಸು" "ಮುದ್ರಕಕ್ಕೆ ಸಂಪರ್ಕವಿಲ್ಲ" - "ಅಜ್ಞಾತ" + "ಅಪರಿಚಿತ" "%1$s ಬಳಸುವುದೇ?" "ನಿಮ್ಮ ಡಾಕ್ಯುಮೆಂಟ್‌ ಪ್ರಿಂಟರ್‌ಗೆ ಹೋಗುವ ಸಂದರ್ಭದಲ್ಲಿ ಒಂದು ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸರ್ವರ್‌ಗಳ ಮೂಲಕ ಹಾದು ಹೋಗಬಹುದು." diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml index c277c558b96500d7500c942dc0c04350c8027267..11b1664114d0e3f3687daad25811951c0cc0a635 100644 --- a/packages/PrintSpooler/res/values-my-rMM/strings.xml +++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml @@ -33,7 +33,7 @@ "ဥပမာ ၁-၅၊ ၈၊ ၁၁-၁၃" "အစမ်းကြည့်ရှုရန်" "အစမ်းကြည့်ရန် ပီဒီအက်ဖ် ဖတ်ရှုစရာ ထည့်သွင်းပါ" - "စာထုတ်လုပ်သော အက်ပ် ခဏ ပျက်သွားပါသည်" + "စာထုတ်လုပ်သော အက်ပ်ခဏ ပျက်သွားပါသည်" "စာထုတ်အလုပ်ကို လုပ်နေပါသည်" "ပီဒီအက်ဖ် အဖြစ်သိမ်းဆည်းရန်" "စာထုတ်စက် အားလုံး" @@ -81,7 +81,7 @@ "%1$s ကို ပယ်ဖျက်နေပါသည်" "စာထုတ်စက်မှ အမှား %1$s" "%1$sကိုစာထုတ်စက်ကငြင်းလိုက်သည်" - "မလုပ်တော့ပါ" + "မလုပ်တော့" "အစက ပြန်စရန်" "စာထုတ်စက်နဲ့ ဆက်သွယ်ထားမှု မရှိပါ" "အကြောင်းအရာ မသိရှိ" diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml index 3b66b380bb72499a95c4830f94ba8b309f904bc9..c96fd914786de06a14cdf88a1342eb91cfc5dca4 100644 --- a/packages/PrintSpooler/res/values-sr/strings.xml +++ b/packages/PrintSpooler/res/values-sr/strings.xml @@ -103,8 +103,8 @@ "Водоравно" "Уписивање у датотеку није могуће" - "Жао нам је, ово није успело. Покушајте поново." - "Покушајте поново" + "Жао нам је, ово није успело. Пробајте поново." + "Пробајте поново" "Овај штампач тренутно није доступан." "Није успео приказ прегледа" "Припрема прегледа..." diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml index 3debf8e60cdbcfca569914ab4483e41ec13860ab..d4e796339bc9a30943263177b572531c6dbb2166 100644 --- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml +++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml @@ -60,7 +60,7 @@ 找到 %1$s 台打印机 "%1$s - %2$s" - "关于此打印机的更多信息" + "此打印机的详细信息" "无法创建文件" "部分打印服务已停用" "正在搜索打印机" diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml index 47e616ef40c77a19228b1b70a179be1ed3703ba7..9464c678e59c256875ee7fb406edf4f9da876579 100644 --- a/packages/PrintSpooler/res/values/colors.xml +++ b/packages/PrintSpooler/res/values/colors.xml @@ -16,8 +16,6 @@ - #EEFF41 - #99000000 #F2F1F2 diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java index 999d82d592ea325796a30c4f590cf70d03447e73..6140428d353f70ea1f76c51dddfbaba254995e5f 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java @@ -838,9 +838,15 @@ public final class PageContentRepository { try (ParcelFileDescriptor source = pipe[0]) { try (ParcelFileDescriptor destination = pipe[1]) { - - mRenderer.renderPage(mPageIndex, bitmap.getWidth(), bitmap.getHeight(), - mRenderSpec.printAttributes, destination); + synchronized (mLock) { + if (mRenderer != null) { + mRenderer.renderPage(mPageIndex, bitmap.getWidth(), + bitmap.getHeight(), mRenderSpec.printAttributes, + destination); + } else { + throw new IllegalStateException("Renderer is disconnected"); + } + } } BitmapSerializeUtils.readBitmapPixels(bitmap, source); diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java index 99145b7bda0a4891c17ffd4f10fc58c8e3ad1bc5..eea92b5ca62e5d90fda91fb1545f6baf1443e5ca 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java +++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java @@ -94,6 +94,7 @@ public final class RemotePrintDocument { // but the content has changed. if (mNextCommand == null) { if (mUpdateSpec.pages != null && (mDocumentInfo.changed + || mDocumentInfo.writtenPages == null || (mDocumentInfo.info.getPageCount() != PrintDocumentInfo.PAGE_COUNT_UNKNOWN && !PageRangeUtils.contains(mDocumentInfo.writtenPages, diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java index 2f58de531dda78ecb9a42d7aba6ed9ef91319a86..c06e8496a7d53ff341abd57c4baf7588acfc5c68 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java @@ -737,9 +737,11 @@ public class AddPrinterActivity extends ListActivity implements AdapterView.OnIt public void updateInstalledServices(List services) { mInstalledServices.clear(); - final int numServices = services.size(); - for (int i = 0; i < numServices; i++) { - mInstalledServices.add(services.get(i).getComponentName().getPackageName()); + if (services != null) { + final int numServices = services.size(); + for (int i = 0; i < numServices; i++) { + mInstalledServices.add(services.get(i).getComponentName().getPackageName()); + } } filterRecommendations(); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index c318275aafd082be2d2698502e13d23f8197f160..3b25edb5443ea1eb28eddd15c4b96b333eb9c988 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -244,6 +244,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setTitle(R.string.print_dialog); + Bundle extras = getIntent().getExtras(); mPrintJob = extras.getParcelable(PrintManager.EXTRA_PRINT_JOB); @@ -298,7 +300,6 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat // Now that we are bound to the local print spooler service // and the printer registry loaded the historical printers // we can show the UI without flickering. - setTitle(R.string.print_dialog); setContentView(R.layout.print_activity); try { @@ -526,6 +527,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat .setContentType(info.getContentType()) .setPageCount(pageCount) .build(); + + File file = mFileProvider.acquireFile(null); + try { + adjustedInfo.setDataSize(file.length()); + } finally { + mFileProvider.releaseFile(); + } + mPrintJob.setDocumentInfo(adjustedInfo); mPrintJob.setPages(document.printedPages); } @@ -2060,6 +2069,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat if (mPrinterRegistry != null) { mPrinterRegistry.setTrackedPrinter(null); + mPrinterRegistry.setOnPrintersChangeListener(null); } if (mPrintersObserver != null) { @@ -3076,6 +3086,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat .setContentType(oldDocInfo.getContentType()) .setPageCount(newPageCount) .build(); + + File file = mFileProvider.acquireFile(null); + try { + newDocInfo.setDataSize(file.length()); + } finally { + mFileProvider.releaseFile(); + } + mPrintJob.setDocumentInfo(newDocInfo); } diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java index 86366dd21eada4c2d0e0561ca6aec1c1e0ebf4ea..9fca9593162c2f47fd22b425211034ba2243820f 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java @@ -120,13 +120,11 @@ public class PrinterRegistry { @Override public void onLoaderReset(Loader> loader) { mPrinters.clear(); - if (mOnPrintersChangeListener != null) { - // Post a message as we are in onLoadFinished and certain operations - // are not allowed in this callback, such as fragment transactions. - // Clients should not handle this explicitly. - mHandler.obtainMessage(MyHandler.MSG_PRINTERS_INVALID, - mOnPrintersChangeListener).sendToTarget(); - } + + // Post a message as we are in onLoadFinished and certain operations + // are not allowed in this callback, such as fragment transactions. + // Clients should not handle this explicitly. + mHandler.obtainMessage(MyHandler.MSG_PRINTERS_INVALID).sendToTarget(); } // LoaderCallbacks#onLoadFinished @@ -134,15 +132,12 @@ public class PrinterRegistry { public void onLoadFinished(Loader> loader, List printers) { mPrinters.clear(); mPrinters.addAll(printers); - if (mOnPrintersChangeListener != null) { - // Post a message as we are in onLoadFinished and certain operations - // are not allowed in this callback, such as fragment transactions. - // Clients should not handle this explicitly. - SomeArgs args = SomeArgs.obtain(); - args.arg1 = mOnPrintersChangeListener; - args.arg2 = printers; - mHandler.obtainMessage(MyHandler.MSG_PRINTERS_CHANGED, args).sendToTarget(); - } + + // Post a message as we are in onLoadFinished and certain operations + // are not allowed in this callback, such as fragment transactions. + // Clients should not handle this explicitly. + mHandler.obtainMessage(MyHandler.MSG_PRINTERS_CHANGED, printers).sendToTarget(); + if (!mReady) { mReady = true; if (mReadyCallback != null) { @@ -158,7 +153,7 @@ public class PrinterRegistry { } }; - private static final class MyHandler extends Handler { + private final class MyHandler extends Handler { public static final int MSG_PRINTERS_CHANGED = 0; public static final int MSG_PRINTERS_INVALID = 1; @@ -171,16 +166,17 @@ public class PrinterRegistry { public void handleMessage(Message message) { switch (message.what) { case MSG_PRINTERS_CHANGED: { - SomeArgs args = (SomeArgs) message.obj; - OnPrintersChangeListener callback = (OnPrintersChangeListener) args.arg1; - List printers = (List) args.arg2; - args.recycle(); - callback.onPrintersChanged(printers); + List printers = (List) message.obj; + + if (mOnPrintersChangeListener != null) { + mOnPrintersChangeListener.onPrintersChanged(printers); + } } break; case MSG_PRINTERS_INVALID: { - OnPrintersChangeListener callback = (OnPrintersChangeListener) message.obj; - callback.onPrintersInvalid(); + if (mOnPrintersChangeListener != null) { + mOnPrintersChangeListener.onPrintersInvalid(); + } } break; } } diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_cellphone.png deleted file mode 100644 index 6e29d233fb18efa91ec2590e12546622517e8df1..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-hdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_headphones_a2dp.png deleted file mode 100644 index 6110e9e7b1c872d71d9eeb5fb94b54b4e1662901..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-hdpi/ic_bt_headphones_a2dp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_headset_hfp.png deleted file mode 100644 index 6cca2250815e5c0b00ed62f7a90c0c86726d5528..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-hdpi/ic_bt_headset_hfp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_misc_hid.png deleted file mode 100644 index 6445f2ae2e30f17f57ee4c78d58db95ecd411d19..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-hdpi/ic_bt_misc_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_network_pan.png deleted file mode 100644 index 78c02948619cbd614d127c937e40d94e6b07cfd7..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-hdpi/ic_bt_network_pan.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_pointing_hid.png deleted file mode 100644 index 2fcc3b00e56e1bb0f610adb3572a997bf12f9a21..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-hdpi/ic_bt_pointing_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-hdpi/ic_lockscreen_ime.png deleted file mode 100644 index 70d35bf8e279dfdc7297830c942c1882e24a0e2e..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-hdpi/ic_lockscreen_ime.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png deleted file mode 100644 index 2d9b75e96f29f2b178a106ec47eb789069dcdceb..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png deleted file mode 100644 index b6ebe34838e4d4622c6a12db0c0334e35e1eb147..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png deleted file mode 100644 index 8b67b91ef6675e93d48731a7701db549534dfe17..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_cellphone.png deleted file mode 100644 index 1fa0a3db722ccc21eb845d649b4d59acae8338ad..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-mdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_headphones_a2dp.png deleted file mode 100644 index 175bd7831078189e9426712dd27f366036ef930e..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-mdpi/ic_bt_headphones_a2dp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_headset_hfp.png deleted file mode 100644 index 05b27e883056f2322a2e65fe0120a141d45fcc56..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-mdpi/ic_bt_headset_hfp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_misc_hid.png deleted file mode 100644 index 6e9f8ae0cfd7b901ff8f8f2d1513c85b248a5c5d..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-mdpi/ic_bt_misc_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_network_pan.png deleted file mode 100644 index 5f3371f86c1a11c0fa0c3d75208b027c37915ce6..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-mdpi/ic_bt_network_pan.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_pointing_hid.png deleted file mode 100644 index 539d77f8e7dcafe1ce3949d7274341e4386e6064..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-mdpi/ic_bt_pointing_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-mdpi/ic_lockscreen_ime.png deleted file mode 100644 index 3216776def011c92d1d61ff05a19a49223b37124..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-mdpi/ic_lockscreen_ime.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_cellphone.png deleted file mode 100644 index 4f381ba7976cec7ce9e64e3b4f2a9a41774b6eb5..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headphones_a2dp.png deleted file mode 100644 index c67127d6fd806218b43415ce27fdbde3631e44f6..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headphones_a2dp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headset_hfp.png deleted file mode 100644 index d3b356b2c80518ce6cf042c7723ec105d1cae042..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headset_hfp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_misc_hid.png deleted file mode 100644 index 2d381292df5ece2bc76c2de4e4ab33f9908ff28f..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_misc_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_network_pan.png deleted file mode 100644 index fb76575fec6e1848b3a19af662c3dd30904589b7..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_network_pan.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_pointing_hid.png deleted file mode 100644 index d8b68ebc13f6033fb78c6620b7fc37879df43303..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_pointing_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-xhdpi/ic_lockscreen_ime.png deleted file mode 100644 index 02cc3afd776730e64b537c73ce5835905a713b58..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xhdpi/ic_lockscreen_ime.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_cellphone.png deleted file mode 100644 index 7805b7ac7a66508b70d9fe2340499ee661056fcd..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headphones_a2dp.png deleted file mode 100644 index 812777439e80908dc187ab7f03c4e49bdf07230a..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headphones_a2dp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headset_hfp.png deleted file mode 100644 index 84b8085c0bf62d6c39e2e1fa62b2835f0829fcdc..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headset_hfp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_misc_hid.png deleted file mode 100644 index 289d6ac13e75ea197ecf205dd41db023ba2419c1..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_misc_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_network_pan.png deleted file mode 100644 index 72bc8040a4caa05612406385ae79d3701f47ca3d..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_network_pan.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_pointing_hid.png deleted file mode 100644 index e31ce2b28b41bb04f090bb077f47df21c1a4f242..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_pointing_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_lockscreen_ime.png deleted file mode 100644 index f23b0e78d271a501fbd485f12ea71279a816d8d3..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxhdpi/ic_lockscreen_ime.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_cellphone.png deleted file mode 100644 index 1e12f96a5e52c839e28b5b4c28a6fe82676bc5d1..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_cellphone.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headphones_a2dp.png deleted file mode 100644 index 8b547d9bba89f434a1e2def06fa8623885f4b3c4..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headphones_a2dp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headset_hfp.png deleted file mode 100644 index 03c503388bcd70c03e90c834b590d326694207f0..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headset_hfp.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_misc_hid.png deleted file mode 100644 index b9a99231dd207eef974396ec2e6235e2ed83af1f..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_misc_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_network_pan.png deleted file mode 100644 index 989e1ab7e38617f2122b15ec5192c0db3a905356..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_network_pan.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_pointing_hid.png deleted file mode 100644 index de8c389c6689f930be66afb18ef337fe90884754..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_pointing_hid.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_lockscreen_ime.png deleted file mode 100644 index 2eb8a927644adecc88738143684d00b10a12efce..0000000000000000000000000000000000000000 Binary files a/packages/SettingsLib/res/drawable-xxxhdpi/ic_lockscreen_ime.png and /dev/null differ diff --git a/packages/SettingsLib/res/drawable/ic_bt_cellphone.xml b/packages/SettingsLib/res/drawable/ic_bt_cellphone.xml new file mode 100644 index 0000000000000000000000000000000000000000..cc9b73238d71e609d7c3c8edfad6e0a6955d8fb4 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_cellphone.xml @@ -0,0 +1,29 @@ + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/drawable/ic_bt_headphones_a2dp.xml b/packages/SettingsLib/res/drawable/ic_bt_headphones_a2dp.xml new file mode 100644 index 0000000000000000000000000000000000000000..bbe39143c53911026c54ca03dc3aa7b566b35a14 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_headphones_a2dp.xml @@ -0,0 +1,26 @@ + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/drawable/ic_bt_headset_hfp.xml b/packages/SettingsLib/res/drawable/ic_bt_headset_hfp.xml new file mode 100644 index 0000000000000000000000000000000000000000..ceeef191bc99ec363841f675efd4fc6e72288b3f --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_headset_hfp.xml @@ -0,0 +1,27 @@ + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/drawable/ic_bt_misc_hid.xml b/packages/SettingsLib/res/drawable/ic_bt_misc_hid.xml new file mode 100644 index 0000000000000000000000000000000000000000..67b42ae020d821b9fc233f01718f326ea8c352a8 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_misc_hid.xml @@ -0,0 +1,26 @@ + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/drawable/ic_bt_network_pan.xml b/packages/SettingsLib/res/drawable/ic_bt_network_pan.xml new file mode 100644 index 0000000000000000000000000000000000000000..c5ab01c5ede8d965644e8f30a5464b5461557c8c --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_network_pan.xml @@ -0,0 +1,30 @@ + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/drawable/ic_bt_pointing_hid.xml b/packages/SettingsLib/res/drawable/ic_bt_pointing_hid.xml new file mode 100644 index 0000000000000000000000000000000000000000..821618dbc4a62a8b4f59d2c0061ba981c7fc52c0 --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_bt_pointing_hid.xml @@ -0,0 +1,26 @@ + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/drawable/ic_lockscreen_ime.xml b/packages/SettingsLib/res/drawable/ic_lockscreen_ime.xml new file mode 100644 index 0000000000000000000000000000000000000000..4aa8569466f1564b3e0f519de713e2698301e71a --- /dev/null +++ b/packages/SettingsLib/res/drawable/ic_lockscreen_ime.xml @@ -0,0 +1,26 @@ + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml index 67296a6c251d838b9c906e0c9d937bd82e85222e..a68a44e0937198fb21fb23785f2a219f7009bc36 100644 --- a/packages/SettingsLib/res/layout/settings_with_drawer.xml +++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml @@ -40,6 +40,11 @@ style="?android:attr/toolbarStyle" android:background="?android:attr/colorPrimary" /> + - + diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml index 51933841adc0bf5f08c3bfaf635fbd46b6c1d3b8..13c22c4348a114ff2a7abfadbdaa850f6f62c5ea 100644 --- a/packages/SettingsLib/res/values-af/arrays.xml +++ b/packages/SettingsLib/res/values-af/arrays.xml @@ -84,11 +84,13 @@ "Af" "Alles" "Alles behalwe radio" + "net kern" "Af" "Alle loglêerbuffers" "Alles behalwe radiologlêerbuffers" + "net kernloglêerbuffer" "Animasie af" diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 54d1201748e46da509fceaf78d6d471088d7fff0..66f2f87fa31e90f9ad5dad61b91a3236cac57aef 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -28,7 +28,8 @@ "WiFi-verbinding het misluk" "Stawingsprobleem" "Nie binne ontvangs nie" - "Geen internettoegang bespeur nie, sal nie outomaties herkoppel nie." + "Geen internettoegang word bespeur nie, sal nie outomaties herkoppel nie." + "Geen internettoegang nie." "Gestoor deur %1$s" "Gekoppel via Wi-Fi-assistent" "Gekoppel via %1$s" @@ -184,7 +185,6 @@ "Laat skynliggings toe" "Laat skynliggings toe" "Aktiveer aansigkenmerkinspeksie" - "Gebruik eerder die DHCP-kliënt van Lollipop af as die nuwe Android DHCP-kliënt." "Hou mobiele data altyd aktief, selfs wanneer Wi‑Fi aktief is (vir vinnige netwerkwisseling)." "Laat USB-ontfouting toe?" "USB-ontfouting is net vir ontwikkelingsdoeleindes bedoel. Gebruik dit om data te kopieer tussen jou rekenaar en jou toestel, programme op jou toestel te installeer sonder kennisgewing en om loglêerdata te lees." @@ -234,8 +234,6 @@ "Wys snitgrense, kantlyne, ens." "Dwing RTL-uitlegrigting" "Dwing skermuitlegrigting na RTL vir alle locales" - "Wys CPU-verbruik" - "Skermlaag wys huidige CPU-gebruik" "Forseer GPU-lewering" "Dwing gebruik van GPU vir 2D-tekening" "Dwing 4x MSAA" @@ -342,4 +340,5 @@ "Grootste" "Gepasmaak (%d)" "Hulp en terugvoer" + "Kieslys" diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml index e8176e107eb0f013b165df1c220f758ee641adbd..5767829476efc99957b615ce30a07f3f296308f4 100644 --- a/packages/SettingsLib/res/values-am/arrays.xml +++ b/packages/SettingsLib/res/values-am/arrays.xml @@ -84,11 +84,13 @@ "ጠፍቷል" "ሁሉም" "ከሬዲዮ በስተቀር ሁሉም" + "አውራ ከዋኝ ብቻ" "ጠፍቷል" "የሁሉም ምዝግብ ማስታወሻ ቋቶች" "ከሬዲዮ ምዝግብ ማስታወሻ ቋቶች በስተቀር ሁሉም" + "የአውራ ከዋኝ ምዝግብ ማስታወሻ ቋት ብቻ" "እነማ ጠፍቷል" diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index ecedd50a230b1d9c32a245146b6c3ba2e4e6b3de..cfda4ab177d976afbbfabc886de0e2177e696c10 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -28,7 +28,8 @@ "የWiFi ግንኙነት መሰናከል" "የማረጋገጫ ችግር" "በክልል ውስጥ የለም" - "ምንም የበይነ መረብ መዳረሻ ተፈልጎ አልተገኘም፣ በራስ-ሰር እንደገና እንዲገናኝ አይደረግም።" + "ምንም የበይነ መረብ መዳረሻ አልተገኘም፣ በራስ-ሰር እንደገና እንዲገናኝ አይደረግም።" + "ምንም የበይነመረብ መዳረሻ የለም።" "የተቀመጠው በ%1$s" "በWi‑Fi ረዳት አማካኝነት ተገናኝቷል" "በ%1$s በኩል መገናኘት" @@ -184,7 +185,6 @@ "አስቂኝ ሥፍራዎችን ፍቀድ" "አስቂኝ ሥፍራዎችን ፍቀድ" "የእይታ አይነታ ምርመራን አንቃ" - "ከአዲሱ የAndroid DHCP ደንበኛ ይልቅ የLollipop DHCP ደንበኛውን ይጠቀሙ።" "ምንም እንኳን Wi‑Fi ንቁ ቢሆንም የሞባይል ውሂብን ንቁ እንደሆነ አቆይ (ለፈጣን የአውታረ መረብ ቅይይር)።" "የUSB ማረሚያ ይፈቀድ?" "የUSB አድስ ለግንባታ አላማ ብቻ የታሰበ ነው። ከኮምፒዩተርህ ወደ መሳሪያህ ውሂብ ለመገልበጥ፣ መሣሪያህ ላይ ያለ ማሳወቂያ መተግበሪያዎችን መጫን፣ እና ማስታወሻ ውሂብ ማንበብ ለመጠቀም ይቻላል።" @@ -234,8 +234,6 @@ "የቅንጥብ ገደቦች፣ ጠርዞች፣ ወዘተ አሳይ" "የቀኝ-ወደ-ግራ አቀማመጥ አቅጣጫ አስገድድ" "ለሁሉም አካባቢዎች የማያ ገጽ አቀማመጥ ከቀኝ-ወደ-ግራ እንዲሆን አስገድድ" - "የCPU አጠቃቀም አሳይ" - "የማያ ተደራቢ የአሁኑን የCPU አጠቃቀም እያሳየ ነው።" "GPU ምላሽ መስጠትን አስገድድ" "ለ2-ልኬት መሳል የGPU ስራ አስገድድ" "4x MSAA አስገድድ" @@ -342,4 +340,5 @@ "በጣም ተለቅ ያለ" "ብጁ (%d)" "እገዛ እና ግብረመልስ" + "ምናሌ" diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml index e50421ed30d4808fe28da1189632b456900fd28e..e3d70fe088438f809e070999c5d95305d79dfd0a 100644 --- a/packages/SettingsLib/res/values-ar/arrays.xml +++ b/packages/SettingsLib/res/values-ar/arrays.xml @@ -84,11 +84,13 @@ "إيقاف" "الكل" "الكل دون اللاسلكي" + "‏kernel فقط" "إيقاف" "كل المخازن المؤقتة للسجلات" "كل المخازن المؤقتة باستثناء مخازن سجلات اللاسلكي" + "‏التخزين المؤقت لسجل kernel فقط" "إيقاف الرسوم المتحركة" diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 1f6e9bf8040f3bc2ad05b14991ca7585690b4b4b..e65feff40590fd6e90e46623bf7628bf5a4ffb92 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -28,7 +28,8 @@ "‏أخفق اتصال WiFi" "حدثت مشكلة في المصادقة" "ليست في النطاق" - "لم يتم اكتشاف اتصال بالإنترنت." + "لم يتم اكتشاف اتصال بالإنترنت، ولن تتم إعادة الاتصال تلقائيًا." + "لا يتوفر اتصال بالإنترنت." "تم الحفظ بواسطة %1$s" "‏تم التوصيل عبر مساعد Wi-Fi" "‏تم الاتصال عبر %1$s" @@ -184,7 +185,6 @@ "السماح بمواقع وهمية" "السماح بمواقع وهمية" "تمكين فحص سمة العرض" - "‏يمكنك استخدام برنامج DHCP من Lollipop بدلاً من برنامج DHCP الجديد على Android." "‏اجعل بيانات الجوّال نشطة دائمًا، حتى عندما يكون اتصال Wi‑Fi نشطًا (لتبديل الشبكة بسرعة)." "‏هل تريد السماح بتصحيح أخطاء USB؟" "‏تم تصميم تصحيح أخطاء USB لأغراض التطوير فقط. يمكن استخدامه لنسخ البيانات بين الكمبيوتر والجهاز، وتثبيت التطبيقات على جهازك بدون تنبيه، وقراءة بيانات السجل." @@ -234,8 +234,6 @@ "عرض حدود وهوامش المقطع وما إلى ذلك." "فرض اتجاه التنسيق ليكون من اليمين إلى اليسار" "فرض اتجاه تنسيق الشاشة ليكون من اليمين إلى اليسار لجميع اللغات" - "‏عرض استخدام CPU" - "‏عرض تراكب الشاشة لاستخدام CPU الحالي" "‏فرض عرض رسومات GPU" "فرض استخدام وحدة معالجة الرسومات للرسم ثنائي الأبعاد" "‏فرض 4x MSAA" @@ -330,7 +328,7 @@ "الشاشة الرئيسية للإعدادات" "٠‏٪" - "٪۵۰" + "٥٠٪" "٪۱۰۰" "قبل %1$s" @@ -342,4 +340,5 @@ "أكبر مستوى" "مخصص (%d)" "المساعدة والتعليقات" + "القائمة" diff --git a/packages/SettingsLib/res/values-az-rAZ/arrays.xml b/packages/SettingsLib/res/values-az-rAZ/arrays.xml index 49bc262ac7dcea62275012131604d3e23a0c93f0..396dfa114636366792e8b1d159ca3e36df79ccab 100644 --- a/packages/SettingsLib/res/values-az-rAZ/arrays.xml +++ b/packages/SettingsLib/res/values-az-rAZ/arrays.xml @@ -84,11 +84,13 @@ "Deaktiv" "Bütün" "Radiodan başqa hamısı" + "yalnız kernel" "Qeyri-aktiv" "Bütün loq buferləri" "Radio loq buferlərindən başqa hamısı" + "yalnız kernel loq bufferi" "Animasiya deaktiv" diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml index 2be5150e5ddbb431a7245549c8527c7eef013fed..5aac49e14443c56b59025a4e1882cd8fb24719c8 100644 --- a/packages/SettingsLib/res/values-az-rAZ/strings.xml +++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml @@ -28,7 +28,8 @@ "WiFi Bağlantı Uğursuzluğu" "Autentifikasiya problemi" "Diapazonda deyil" - "İnternet bağlantısı tapılmadı, avtomatik olaraq yenidən qoşulmayacaq." + "İnternet bağlantısı tapılmadı, avtomatik olaraq yenidən qoşulmayacaq." + "İnternet girişi yoxdur." "%1$s tərəfindən saxlandı" "Wi‑Fi köməkçisi vasitəsilə qoşulub" "%1$s vasitəsilə qoşuludur" @@ -184,7 +185,6 @@ "Sınaq yerləşmələrə icazə verin" "Sınaq yerləşmələrə icazə verin" "Atribut inspeksiyasına baxışa icazə verin" - "Android DHCP klienti əvəzinə Lollipopdan DHCP klient istifadə edin." "Hətta Wi‑Fi aktiv olanda da mobil datanı həmişə aktiv saxlayın (sürətli şəbəkək keçidi üçün)." "USB debaq funksiyasına icazə verilsin?" "USB sazlanması yalnız inkişaf məqsədlidir. Kompüteriniz və cihazınız arasında datanı kopyalamaq üçün ondan istifadə edin, bildiriş olmadan tətbiqləri cihazınıza quraşdırın və qeydiyyat datasını oxuyun." @@ -234,8 +234,6 @@ "Klip sərhədləri, boşluqları və s. göstər" "RTL düzən istiqamətinə məcbur edin" "Ekran düzən istiqamətini RTL üzərinə bütün yerli variantlar üçün məcbur edin" - "CPU istifadəsini göstər" - "Ekran örtüşməsi cari CPU istifadəsini göstərir" "GPU renderə məcbur edin" "2d rəsm üçün GPU məcburi istifadə" "4x MSAA məcbur edin" @@ -342,4 +340,5 @@ "Ən böyük" "Fərdi (%d)" "Yardım və rəy" + "Menyu" diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml index 5831456606bbb36bec32be2f9e7a7aa92fc2347a..8e803f5a1df4981af08fcfbf75a2148f918631a0 100644 --- a/packages/SettingsLib/res/values-bg/arrays.xml +++ b/packages/SettingsLib/res/values-bg/arrays.xml @@ -84,11 +84,13 @@ "Изкл." "Всички" "Вс. без радио" + "само ядрото" "Изкл." "Всички регистрационни буфери" "Всички регистрационни буфери освен тези за радиото" + "само регистрационния буфер на ядрото" "Анимацията е изключена" diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 81c834f96100ebd84b116bee41bd5253ed950e79..eba51b37dc792531ac2997abd5669655038920c2 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -28,7 +28,8 @@ "Неуспешна връзка с Wi-Fi" "Проблем при удостоверяването" "Извън обхват" - "Не е открит достъп до интернет. Няма да се свърже отново автоматично." + "Не е открит достъп до интернет. Връзката няма да се възобнови автоматично." + "Няма достъп до интернет." "Запазено от %1$s" "Установена е връзка чрез помощника за Wi-Fi" "Установена е връзка през „%1$s“" @@ -184,7 +185,6 @@ "Разрешаване на измислени местоположения" "Разрешаване на измислени местоположения" "Актив. на инспектирането на атрибутите за преглед" - "Използване на клиентската програма за DHCP от Lollipop вместо новата програма на Android." "Мобилните данни са активни винаги – дори когато функцията за Wi‑Fi е включена (за бързо превключване между мрежите)." "Разрешаване на отстраняването на грешки през USB?" "Отстраняването на грешки през USB е предназначено само за програмни цели. Използвайте го за копиране на данни между компютъра и устройството си, за инсталиране на приложения на устройството си без известяване и за четене на регистрационни данни." @@ -234,8 +234,6 @@ "Показв. на границите на изрязване, полетата и др." "Принуд. оформл. отдясно наляво" "Принуд. оформл. на екрана отдясно наляво за вс. локали" - "Употреба на процесора" - "Наслагване на екрана показва употр. на процесора" "Принудително изобразяване" "Принуд. използв. на GPU за двуизмерно начертаване" "Задаване на 4x MSAA" @@ -342,4 +340,5 @@ "Най-голямо" "Персонализирано (%d)" "Помощ и отзиви" + "Меню" diff --git a/packages/SettingsLib/res/values-bn-rBD/arrays.xml b/packages/SettingsLib/res/values-bn-rBD/arrays.xml index bf666cf15d0bfc0fc6fcba78d7a94c8aa4fe36ea..d653a9717e70b8327cb3d7fad2cb2a444babf827 100644 --- a/packages/SettingsLib/res/values-bn-rBD/arrays.xml +++ b/packages/SettingsLib/res/values-bn-rBD/arrays.xml @@ -84,11 +84,13 @@ "বন্ধ আছে" "সমস্ত" "সমস্ত কিন্তু রেডিও" + "শুধুমাত্র কার্নেল" "বন্ধ আছে" "সমস্ত লগ বাফার" "সমস্ত কিন্তু রেডিও লগ বাফারগুলি" + "শুধুমাত্র কার্নেল লগ বাফার" "অ্যানিমেশন বন্ধ করুন" diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml index f6c24192a041e9092750414deaa35c11aa722ab5..4ad361bd39b919c49ed076c8648c044f5aee6435 100644 --- a/packages/SettingsLib/res/values-bn-rBD/strings.xml +++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml @@ -28,7 +28,8 @@ "WiFi সংযোগের ব্যর্থতা" "প্রমাণীকরণ সমস্যা" "পরিসরের মধ্যে নয়" - "কোনো ইন্টারনেট অ্যাক্সেস শনাক্ত হয়নি, স্বয়ংক্রিয়ভাবে পুনরায় সংযোগ স্থাপন করবে না৷" + "কোনো ইন্টারনেট অ্যাক্সেস শনাক্ত হয়নি, স্বয়ংক্রিয়ভাবে পুনরায় সংযোগ স্থাপন করবে না৷" + "কোনো ইন্টারনেট অ্যাক্সেস নেই৷" "%1$s দ্বারা সংরক্ষিত" "ওয়াই-ফাই সহায়ক-এর মাধ্যমে সংযুক্ত হয়েছে" "%1$s মাধ্যমে সংযুক্ত হয়েছে" @@ -184,7 +185,6 @@ "নকল অবস্থানের অনুমতি দিন" "মক অবস্থানগুলি মঞ্জুর করুন" "অ্যাট্রিবিউট পরিদর্শন দেখা সক্ষম করুন" - "নতুন Android DHCP ক্লায়েন্টের পরিবর্তে Lollipop এর থেকে DHCP ক্লায়েন্ট ব্যবহার করুন৷" "ওয়াই-ফাই সক্রিয় থাকার সময়েও (দ্রুত নেটওয়ার্কে পাল্টানোর জন্য) সর্বদা মোবাইল ডেটা সক্রিয় রাখুন।" "USB ডিবাগিং মঞ্জুর করবেন?" "USB ডিবাগিং কেবলমাত্র বিকাশ করার উদ্দেশ্যে। আপনার কম্পিউটার এবং আপনার ডিভাইসের মধ্যে ডেটা অনুলিপি করতে এটি ব্যবহার করুন, বিজ্ঞপ্তি ছাড়া আপনার ডিভাইসে অ্যাপ্লিকেশানগুলি ইনস্টল করুন এবং ডেটা লগ পড়ুন।" @@ -234,8 +234,6 @@ "ক্লিপ বাউন্ড, মার্জিন ইত্যাদি দেখান" "RTL লেআউট দিকনির্দেশ জোর দিন" "সমস্ত স্থানের জন্য RTL এ স্ক্রীন লেআউট দিকনির্দেশে জোর দেয়" - "CPU এর ব্যবহার দেখান" - "স্ক্রীন ওভারলে বর্তমান CPU ব্যবহার দেখাচ্ছে" "জোর করে GPU রেন্ডারিং করুন" "2D অঙ্কনের জন্য GPU-এর ব্যবহারে জোর দিন" "4x MSAA এ জোর দিন" @@ -342,4 +340,5 @@ "বৃহত্তম" "কাস্টম (%d)" "সহায়তা ও মতামত" + "মেনু" diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml index 9f987e65eb90825d6d989ba1ba3419551775490d..e4f618e13eada8bdee7a569c1cccbbd2f497321b 100644 --- a/packages/SettingsLib/res/values-ca/arrays.xml +++ b/packages/SettingsLib/res/values-ca/arrays.xml @@ -84,11 +84,13 @@ "Desactivat" "Tot" "Tot menys mòbil" + "només kernel" "Desactivat" "Totes les memòries intermèdies de registre" "Tot menys mem. interm. de registre de senyal mòbil" + "només memòria intermèdia del registre de kernel" "Animació desactivada" diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 13933aea46236aa006abc8f1bbe0311e62d901de..20ae6b0ce23ab079cbee0ac6f736a60a4b2fc61f 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -28,7 +28,8 @@ "Error de connexió Wi-Fi" "Problema d\'autenticació" "Fora de l\'abast" - "No s\'ha detectat accés a Internet, no s\'hi tornarà a connectar automàticament." + "No s\'ha detectat accés a Internet; no s\'hi tornarà a connectar automàticament." + "No hi ha accés a Internet." "Desat per %1$s" "Connectat mitjançant l\'assistent de Wi‑Fi" "Connectada mitjançant %1$s" @@ -111,7 +112,7 @@ "Reprodueix una breu demostració de síntesi de veu" "Instal·la dades de veu" "Instal·la les dades de veu necessàries per a la síntesi de veu" - "Pot ser que aquest motor de síntesi de la parla pugui recopilar tot el text que es dirà en veu alta, incloses les dades personals, com ara les contrasenyes i els números de les targetes de crèdit. Ve del motor %s. Voleu activar l\'ús d\'aquest motor de síntesi de la parla?" + "Pot ser que aquest motor de síntesi de la parla pugui recopilar tot el text que es dirà en veu alta, incloses les dades personals, com ara les contrasenyes i els números de les targetes de crèdit. Ve del motor %s. Vols activar l\'ús d\'aquest motor de síntesi de la parla?" "Aquest idioma requereix una connexió de xarxa activa per a la sortida de síntesi de veu." "Això és un exemple de síntesi de veu" "Estat de l\'idioma predeterminat" @@ -184,7 +185,6 @@ "Ubicacions simulades" "Permet les ubicacions simulades" "Inspecció d\'atributs de visualització" - "Utilitza el client DHCP de Lollipop en lloc del nou client DHCP d\'Android" "Mantén les dades mòbils sempre actives, fins i tot quan la Wi‑Fi està activada (per canviar de xarxa ràpidament)." "Voleu permetre la depuració USB?" "La depuració USB només està indicada per a activitats de desenvolupament. Fes-la servir intercanviar dades entre l\'ordinador i el dispositiu, per instal·lar aplicacions al dispositiu sense rebre notificacions i per llegir dades de registre." @@ -234,8 +234,6 @@ "Mostra els límits de clips, els marges, etc." "Força direcció dreta-esquerra" "Força direcció de pantalla dreta-esquerra en totes les llengües" - "Mostra l\'ús de la CPU" - "Superposa l\'ús de la CPU a la pantalla" "Força acceleració GPU" "Força l\'ús de GPU per a dibuixos en 2D" "Força MSAA 4x" @@ -342,4 +340,5 @@ "Màxim" "Personalitzat (%d)" "Ajuda i suggeriments" + "Menú" diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml index f70eb78690617efaf8ef2162c1cef2e1a9433221..b0185e87b600c2c67d8f022f16ed450349a2f27a 100644 --- a/packages/SettingsLib/res/values-cs/arrays.xml +++ b/packages/SettingsLib/res/values-cs/arrays.xml @@ -84,11 +84,13 @@ "Vypnuto" "Vše" "Bezdrát. ne" + "pouze jádro" "Vypnuto" "Všechny vyrovnávací paměti protokolů" "Všechny kromě protokolu bezdrátových modulů" + "pouze protokol vyrovnávací paměti jádra" "Animace je vypnuta" diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 781f65a640193a9482ac9dd7e4c2be6ad4a427dc..bbc1266cd5544901753562eb718c9afe33532d71 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -28,7 +28,8 @@ "Selhání připojení Wi-Fi" "Problém s ověřením" "Mimo dosah" - "Nebyl zjištěn žádný přístup k internetu, připojení nebude automaticky obnoveno." + "Nebyl zjištěn žádný přístup k internetu, připojení nebude automaticky obnoveno." + "Není k dispozici přístup k internetu." "Uloženo uživatelem %1$s" "Připojeno pomocí asistenta připojení Wi-Fi" "Připojeno prostřednictvím %1$s" @@ -184,7 +185,6 @@ "Povolit simulované polohy" "Povolit simulované polohy" "Kontrola atributu zobrazení" - "Namísto nového klientu DHCP Android použít klient DHCP z verze Lollipop." "Mobilní data budou vždy ponechána aktivní, i když bude aktivní Wi-Fi (za účelem rychlého přepínání sítí)." "Povolit ladění USB?" "Ladění prostřednictvím rozhraní USB je určeno pouze pro účely vývoje. Použijte je ke kopírování dat mezi počítačem a zařízením, instalaci aplikací do zařízení bez upozornění a čtení dat protokolů." @@ -234,8 +234,6 @@ "Zobrazit u výstřižku ohraničení, okraje atd." "Vynutit rozvržení zprava doleva" "Vynutit ve všech jazycích rozvržení obrazovky zprava doleva" - "Zobrazit využití CPU" - "Překryvná vrstva s aktuálním využitím procesoru" "Vykreslování pomocí GPU" "Vynutit použití GPU pro 2D vykreslování" "Vynutit 4x MSAA" @@ -342,4 +340,5 @@ "Největší" "Vlastní (%d)" "Nápověda a zpětná vazba" + "Nabídka" diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml index 7413f656224911761f86d5f0479f295fef14ae0b..d06f39f34a178299a062824e7fcf70d50dc7a840 100644 --- a/packages/SettingsLib/res/values-da/arrays.xml +++ b/packages/SettingsLib/res/values-da/arrays.xml @@ -84,11 +84,13 @@ "Slået fra" "Alle" "Radio undtaget" + "kun kerne" "Slået fra" "Alle logbuffere" "Alle undtagen radiologbuffere" + "kun logbuffer for kerne" "Animation fra" diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 45a3978236883c3b4168949b7b782e803fb2b6d9..108d8dccd4191ce28b63f8780fa5a8867db918bf 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi-forbindelsesfejl" "Problem med godkendelse" "Ikke inden for rækkevidde" - "Der blev ikke fundet nogen internetadgang. Forbindelsen bliver ikke automatisk genoprettet." + "Der blev ikke fundet nogen internetadgang. Forbindelsen bliver ikke automatisk genoprettet." + "Ingen internetadgang." "Gemt af %1$s" "Forbindelse via Wi-Fi-assistent" "Tilsluttet via %1$s" @@ -151,7 +152,7 @@ "Tilbagekald tilladelser for USB-fejlfinding" "Genvej til fejlrapporting" "Vis en knap til oprettelse af fejlrapporter i menu for slukknap" - "Undgå dvale" + "Lås ikke" "Skærmen går ikke i dvale under opladning" "Aktivér Bluetooth HCI snoop log" "Gem alle Bluetooth HCI-pakker i en fil" @@ -184,7 +185,6 @@ "Imiterede placeringer" "Tillad imiterede placeringer" "Aktivér visning af attributinspektion" - "Brug DHCP-klienten fra Lollipop i stedet for den nye DHCP-klient i Android." "Hold altid mobildata aktiveret, selv når Wi-Fi er aktiveret (for at skifte hurtigt mellem netværk)." "Vil du tillade USB-fejlretning?" "USB-fejlretning er kun beregnet til udvikling og kan bruges til at kopiere data mellem din computer og enheden, installere apps på enheden uden meddelelser og læse logdata." @@ -234,8 +234,6 @@ "Vis grænser for klip, margener osv." "Tving læsning mod venstre" "Tving til højre mod venstre-layout for alle sprog" - "Vis CPU-forbrug" - "Skærmoverlejring viser det aktuelle CPU-forbrug" "Tving gengivelse af GPU" "Gennemtving brug af GPU til 2D-tegning" "Tving 4x MSAA" @@ -342,4 +340,5 @@ "Størst" "Tilpasset (%d)" "Hjælp og feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml index ab62cd2a81f8c319d1f154cd7b9a8f383ad97d40..9a81e8fda6df1c7b67e29a555659682c73544a30 100644 --- a/packages/SettingsLib/res/values-de/arrays.xml +++ b/packages/SettingsLib/res/values-de/arrays.xml @@ -84,11 +84,13 @@ "Aus" "Alle" "Alle außer Funkschnittstelle" + "Nur Kernel" "Aus" "Alle Protokollzwischenspeicher" "Alle Protokollzwischenspeicher außer Funkschnittstelle" + "Nur Kernelprotokoll-Zwischenspeicher" "Animation aus" diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index ef2f62ea1ced1203158d73bd273f41a27cf9dc0f..d93dbac8965d700d13d9b1dd0c94d031023bfca6 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -28,7 +28,8 @@ "WLAN-Verbindungsfehler" "Authentifizierungsproblem" "Nicht in Reichweite" - "Keine Internetverbindung erkannt, es kann nicht automatisch eine Verbindung hergestellt werden." + "Keine Internetverbindung erkannt. Es kann nicht automatisch eine Verbindung hergestellt werden." + "Kein Internetzugriff." "Gespeichert von %1$s" "Über WLAN-Assistenten verbunden" "Über %1$s verbunden" @@ -38,7 +39,7 @@ "Verbindung wird getrennt..." "Verbindung wird hergestellt..." "Verbunden" - "Pairing läuft…" + "Kopplung läuft…" "Verbunden (kein Telefon)" "Verbunden (außer Audiomedien)" "Verbunden (ohne Nachrichtenzugriff)" @@ -69,12 +70,12 @@ "Für Audiosystem des Telefons verwenden" "Für Dateiübertragung verwenden" "Für Eingabe verwenden" - "Pairing durchführen" - "Pairing durchführen" + "Koppeln" + "KOPPELN" "Abbrechen" - "Über das Pairing kann auf deine Kontakte und auf deinen Anrufverlauf zugegriffen werden, wenn eine Verbindung besteht." - "Pairing mit %1$s war nicht möglich." - "Pairing mit %1$s war nicht möglich, weil die eingegebene PIN oder der Zugangscode falsch ist." + "Über die Kopplung kann auf deine Kontakte und auf deinen Anrufverlauf zugegriffen werden, wenn eine Verbindung besteht." + "Kopplung mit %1$s war nicht möglich." + "Kopplung mit %1$s war nicht möglich, weil die eingegebene PIN oder der Zugangscode falsch ist." "Kommunikation mit %1$s ist nicht möglich." "Verbindung wurde von %1$s abgelehnt." "WLAN: aus" @@ -184,7 +185,6 @@ "Simulierte Standorte" "Simulierte Standorte zulassen" "Inspektion der Anzeigeattribute aktivieren" - "DHCP-Client von Lollipop statt des neuen Android-DHCP-Clients verwenden" "Die mobile Datennutzung bleibt auch dann aktiviert, wenn WLAN aktiviert ist. Dies dient einem schnelleren Wechsel zwischen Netzwerken." "USB-Debugging zulassen?" "USB-Debugging ist nur für Entwicklungszwecke vorgesehen. Damit kannst du Daten zwischen deinem Computer und deinem Gerät kopieren, Apps auf deinem Gerät ohne Benachrichtigung installieren und Protokolldaten lesen." @@ -234,8 +234,6 @@ "Clip-Begrenzungen, Ränder usw. anzeigen" "RTL-Layout erzwingen" "RTL-Bildschirmlayout für alle Sprachen erzwingen" - "CPU-Auslastung anzeigen" - "Bildschirm-Overlay mit aktueller CPU-Auslastung" "GPU-Rendering erzwingen" "Einsatz von GPU für 2D-Zeichnung erzwingen" "4x MSAA erzwingen" @@ -342,4 +340,5 @@ "Am größten" "Benutzerdefiniert (%d)" "Hilfe & Feedback" + "Menü" diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml index 8a0ff8cb0cb6730c8af44a770b97336b2caf4622..a6ce80ae0d011f4d8e54ed97bd7283b5e82c8a22 100644 --- a/packages/SettingsLib/res/values-el/arrays.xml +++ b/packages/SettingsLib/res/values-el/arrays.xml @@ -84,11 +84,13 @@ "Ανενεργό" "Όλα" "Όλοι εκτός από του αποστολέα" + "μόνο πυρήνας" "Ανενεργό" "Όλα τα αρχεία καταγραφής προσωρινής μνήμης" "Όλα εκτός από τα αρχεία κατ.προσ.μνήμης αποστολέα" + "μόνο προσωρινή μνήμη αρχείου καταγραφής πυρήνα" "Κινούμ.εικόνες απενεργοποιημένες" diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index c8086970472d468171556686f4a6d8bd3a220c53..6bbc11c73d28da8c76b1c9a59c9ad0b4db240b3a 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -28,7 +28,8 @@ "Αποτυχία σύνδεσης Wi-Fi" "Πρόβλημα ελέγχου ταυτότητας" "Εκτός εμβέλειας" - "Δεν εντοπίστηκε καμία πρόσβαση στο διαδίκτυο, δεν θα γίνει αυτόματη επανασύνδεση." + "Δεν εντοπίστηκε πρόσβαση στο διαδίκτυο. Δεν θα πραγματοποιηθεί αυτόματη επανασύνδεση." + "Δεν υπάρχει πρόσβαση στο διαδίκτυο." "Αποθηκεύτηκε από %1$s" "Σύνδεση μέσω βοηθού Wi‑Fi" "Συνδέθηκε μέσω %1$s" @@ -184,7 +185,6 @@ "Να επιτρέπονται ψευδείς τοποθεσίες" "Να επιτρέπονται ψευδείς τοποθεσίες" "Ενεργοποίηση του ελέγχου χαρακτηριστικών προβολής" - "Χρήση εφαρμογής-πελάτη DHCP παλαιού τύπου από το Lollipop αντί για τη νέα εφαρμογή-πελάτη DHCP Android." "Τα δεδομένα κινητής τηλεφωνίας να διατηρούνται πάντα ενεργά, ακόμα και όταν είναι ενεργό το Wi-Fi (για γρήγορη εναλλαγή δικτύου)." "Να επιτρέπεται ο εντοπισμός σφαλμάτων USB;" "Ο εντοπισμός σφαλμάτων USB προορίζεται μόνο για σκοπούς προγραμματισμού. Χρησιμοποιήστε τον για αντιγραφή δεδομένων μεταξύ του υπολογιστή και της συσκευής σας, για την εγκατάσταση εφαρμογών στη συσκευή σας χωρίς προειδοποίηση και για την ανάγνωση δεδομένων καταγραφής." @@ -234,8 +234,6 @@ "Εμφάνιση ορίων κλιπ, περιθωρίων, κλπ." "Επιβολή κατ. διάταξης RTL" "Επιβολή διάταξης οθόν. RTL για όλες τις τοπ. ρυθμ." - "Προβολή χρήσης CPU" - "Επικάλυψη οθόνης για προβολή τρέχουσας χρήσης CPU" "Αναγκαστική απόδοση GPU" "Αναγκαστική χρήση του GPU για σχέδιο 2D" "Αναγκαστικά 4x MSAA" @@ -288,8 +286,8 @@ "Μετατροπή…" "Με κρυπτογράφηση αρχείου" "Μετατροπή σε κρυπτογράφηση βάσει αρχείου…" - "Μετατροπή τμήματος δεδομένων σε κρυπτογράφηση βάσει αρχείου.\n !!Προσοχή!! Με αυτήν την ενέργεια, θα διαγραφούν όλα τα δεδομένα σας.\n Αυτή η λειτουργία βρίσκεται σε δοκιμαστικό στάδιο alpha και ενδέχεται να μην λειτουργεί σωστά.\n Πατήστε \"Εκκαθάριση και μετατροπή…\" για να συνεχίσετε." - "Εκκαθάριση και μετατροπή…" + "Μετατροπή τμήματος δεδομένων σε κρυπτογράφηση βάσει αρχείου.\n !!Προσοχή!! Με αυτήν την ενέργεια, θα διαγραφούν όλα τα δεδομένα σας.\n Αυτή η λειτουργία βρίσκεται σε δοκιμαστικό στάδιο alpha και ενδέχεται να μην λειτουργεί σωστά.\n Πατήστε \"Διαγραφή και μετατροπή…\" για να συνεχίσετε." + "Διαγραφή και μετατροπή…" "Λειτουργία χρώματος εικόνας" "Χρήση sRGB" "Απενεργοποιημένο" @@ -342,4 +340,5 @@ "Μεγαλύτερα" "Προσαρμοσμένη (%d)" "Βοήθεια και σχόλια" + "Μενού" diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml index 465fffa122385821f873e88379afddc7b2a3f496..2ee613fc03439998b789f59bd0ac9384a7550710 100644 --- a/packages/SettingsLib/res/values-en-rAU/arrays.xml +++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml @@ -84,11 +84,13 @@ "Off" "All" "All but radio" + "kernel only" "Off" "All log buffers" "All but radio log buffers" + "kernel log buffer only" "Animation off" diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index c4075307f3354c70efb9cbe6152b13b0a4dd0d8e..a571affde0777bcb1f78aa99099db83a58eb101f 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi Connection Failure" "Authentication problem" "Not in range" - "No Internet Access Detected, won\'t automatically reconnect." + "No Internet access detected, won\'t automatically reconnect." + "No Internet Access." "Saved by %1$s" "Connected via Wi‑Fi assistant" "Connected via %1$s" @@ -184,7 +185,6 @@ "Allow mock locations" "Allow mock locations" "Enable view attribute inspection" - "Use the DHCP client from Lollipop instead of the new Android DHCP client." "Always keep mobile data active, even when Wi‑Fi is active (for fast network switching)." "Allow USB debugging?" "USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data." @@ -234,8 +234,6 @@ "Show clip bounds, margins, etc." "Force RTL layout direction" "Force screen layout direction to RTL for all locales" - "Show CPU usage" - "Screen overlay showing current CPU usage" "Force GPU rendering" "Force use of GPU for 2D drawing" "Force 4x MSAA" @@ -342,4 +340,5 @@ "Largest" "Custom (%d)" "Help & feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml index 465fffa122385821f873e88379afddc7b2a3f496..2ee613fc03439998b789f59bd0ac9384a7550710 100644 --- a/packages/SettingsLib/res/values-en-rGB/arrays.xml +++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml @@ -84,11 +84,13 @@ "Off" "All" "All but radio" + "kernel only" "Off" "All log buffers" "All but radio log buffers" + "kernel log buffer only" "Animation off" diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index c4075307f3354c70efb9cbe6152b13b0a4dd0d8e..a571affde0777bcb1f78aa99099db83a58eb101f 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi Connection Failure" "Authentication problem" "Not in range" - "No Internet Access Detected, won\'t automatically reconnect." + "No Internet access detected, won\'t automatically reconnect." + "No Internet Access." "Saved by %1$s" "Connected via Wi‑Fi assistant" "Connected via %1$s" @@ -184,7 +185,6 @@ "Allow mock locations" "Allow mock locations" "Enable view attribute inspection" - "Use the DHCP client from Lollipop instead of the new Android DHCP client." "Always keep mobile data active, even when Wi‑Fi is active (for fast network switching)." "Allow USB debugging?" "USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data." @@ -234,8 +234,6 @@ "Show clip bounds, margins, etc." "Force RTL layout direction" "Force screen layout direction to RTL for all locales" - "Show CPU usage" - "Screen overlay showing current CPU usage" "Force GPU rendering" "Force use of GPU for 2D drawing" "Force 4x MSAA" @@ -342,4 +340,5 @@ "Largest" "Custom (%d)" "Help & feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml index 465fffa122385821f873e88379afddc7b2a3f496..2ee613fc03439998b789f59bd0ac9384a7550710 100644 --- a/packages/SettingsLib/res/values-en-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml @@ -84,11 +84,13 @@ "Off" "All" "All but radio" + "kernel only" "Off" "All log buffers" "All but radio log buffers" + "kernel log buffer only" "Animation off" diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index c4075307f3354c70efb9cbe6152b13b0a4dd0d8e..a571affde0777bcb1f78aa99099db83a58eb101f 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi Connection Failure" "Authentication problem" "Not in range" - "No Internet Access Detected, won\'t automatically reconnect." + "No Internet access detected, won\'t automatically reconnect." + "No Internet Access." "Saved by %1$s" "Connected via Wi‑Fi assistant" "Connected via %1$s" @@ -184,7 +185,6 @@ "Allow mock locations" "Allow mock locations" "Enable view attribute inspection" - "Use the DHCP client from Lollipop instead of the new Android DHCP client." "Always keep mobile data active, even when Wi‑Fi is active (for fast network switching)." "Allow USB debugging?" "USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data." @@ -234,8 +234,6 @@ "Show clip bounds, margins, etc." "Force RTL layout direction" "Force screen layout direction to RTL for all locales" - "Show CPU usage" - "Screen overlay showing current CPU usage" "Force GPU rendering" "Force use of GPU for 2D drawing" "Force 4x MSAA" @@ -342,4 +340,5 @@ "Largest" "Custom (%d)" "Help & feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml index d01c810b62d1bbc538dc1150cc5fd0b9e54919e5..eae9b1b30577a3ccd91245fa8d2c8bbb9d59c091 100644 --- a/packages/SettingsLib/res/values-es-rUS/arrays.xml +++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml @@ -84,11 +84,13 @@ "Desactivado" "Todo" "Excepto radio" + "solo kernel" "Desactivado" "Todos los búferes de registro" "Todos los búferes de registro, excepto radio" + "solo búfer de registro de kernel" "Animación desactivada" diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 3a939293ea667543130873d7995641fb011e3c09..924c18ad92fd206ecfa35350fda93fb25e5a3da2 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -28,7 +28,8 @@ "Error de conexión Wi-Fi" "Problema de autenticación" "Fuera de alcance" - "No se detectó el acceso a Internet. No se volverá a conectar de forma automática." + "No se detectó el acceso a Internet. No se volverá a conectar de forma automática." + "No se detectó el acceso a Internet." "Guardadas por %1$s" "Conexión por asistente de Wi-Fi" "Conexión a través de %1$s" @@ -184,7 +185,6 @@ "Ubicaciones de prueba" "Permitir ubicaciones de prueba" "Habilitar inspección de atributos de vista" - "Usar el cliente DHCP de Lollipop en lugar del nuevo cliente DHCP de Android" "Siempre mantén los datos móviles activos, incluso cuando esté activada la conexión Wi‑Fi (para cambiar de red de forma rápida)." "¿Permitir depuración por USB?" "La depuración por USB solo está indicada para actividades de programación. Úsala para copiar datos entre tu computadora y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro." @@ -234,8 +234,6 @@ "Mostrar límites de recortes, márgenes, etc." "Forzar diseño der. a izq." "Forzar diseño pantalla der.>izq., cualquier idioma" - "Mostrar el uso de CPU" - "Mostrar superposición en pantalla con uso actual de la CPU" "Forzar representación GPU" "Forzar uso de GPU para dibujar en 2d" "Forzar MSAA 4x" @@ -342,4 +340,5 @@ "Máximo" "Personalizado (%d)" "Ayuda y comentarios" + "Menú" diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml index 42d98632f9de18fabd7a7956b24603829bed9afd..168f3789719e7ee3df961b70e32f8b54c8ebd6ae 100644 --- a/packages/SettingsLib/res/values-es/arrays.xml +++ b/packages/SettingsLib/res/values-es/arrays.xml @@ -84,11 +84,13 @@ "No" "Todo" "Todo menos señal móvil" + "solo kernel" "No" "Todos los búferes de registro" "Todo excepto búferes de registro de señal móvil" + "solo búfer de registro del kernel" "Animación desactivada" diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 61af3ac23fe3426a452077eef3c831021fdac896..7824949072223d0c2e7c9bd4524b52c99236b552 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -28,7 +28,8 @@ "Error de conexión Wi-Fi" "Error de autenticación" "Fuera de rango" - "No se ha detectado acceso a Internet, no se volverá a conectar automáticamente." + "No se ha detectado acceso a Internet, por lo que no se volverá a conectar automáticamente." + "No se ha detectado acceso a Internet." "Guardadas por %1$s" "Conectado a través de asistente Wi‑Fi" "Conectado a través de %1$s" @@ -173,7 +174,7 @@ "Aumentar el nivel de logging de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi" "Si está habilitada, la conexión Wi‑Fi será más agresiva al transferir la conexión de datos al móvil (si la señal Wi‑Fi no es estable)" "Permitir/No permitir búsquedas de Wi-Fi basadas en la cantidad de tráfico de datos presente en la interfaz" - "Tamaños del búfer de Logger" + "Tamaños de búfer de registrador" "Elige el tamaño del Logger por búfer" "¿Borrar almacenamiento continuo del registrador?" "Cuando ya no supervisamos la actividad con el registrador de forma continua, estamos obligados a borrar los datos del registrador almacenados en el dispositivo." @@ -184,7 +185,6 @@ "Ubicaciones simuladas" "Permitir ubicaciones simuladas" "Inspección de atributos de vista" - "Utiliza el cliente DHCP de Lollipop en lugar del nuevo cliente DHCP de Android." "Mantén los datos móviles siempre activos, aunque la conexión Wi‑Fi esté activada (para cambiar de red rápidamente)." "¿Permitir depuración por USB?" "La depuración por USB solo está indicada para actividades de desarrollo. Puedes utilizarla para intercambiar datos entre el ordenador y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro." @@ -234,8 +234,6 @@ "Mostrar límites de vídeo, márgenes, etc." "Forzar dirección diseño RTL" "Forzar dirección (RTL) para todas configuraciones" - "Mostrar uso de la CPU" - "Suporponer el uso de la CPU en la pantalla" "Forzar aceleración GPU" "Forzar uso de GPU para dibujos en 2D" "Forzar MSAA 4x" @@ -342,4 +340,5 @@ "Lo más grande posible" "Personalizado (%d)" "Ayuda y sugerencias" + "Menú" diff --git a/packages/SettingsLib/res/values-et-rEE/arrays.xml b/packages/SettingsLib/res/values-et-rEE/arrays.xml index 1df93cfb1203827bae5f1f249b4123cdcbeac058..019bf50499acd221616e3f2de2c42e425247952b 100644 --- a/packages/SettingsLib/res/values-et-rEE/arrays.xml +++ b/packages/SettingsLib/res/values-et-rEE/arrays.xml @@ -84,11 +84,13 @@ "Väljas" "Kõik" "Kõik, v.a raadio" + "ainult tuum" "Väljas" "Kõik logi puhvrid" "Kõik, v.a raadiologi puhvrid" + "ainult tuuma logi puhver" "Animatsioon väljas" diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml index 66c81e8d6113a98b1c002b178876ff105843d752..5f76b9fd9723b435ce0e39a7e1cc22796a5aea30 100644 --- a/packages/SettingsLib/res/values-et-rEE/strings.xml +++ b/packages/SettingsLib/res/values-et-rEE/strings.xml @@ -28,7 +28,8 @@ "WiFi-ühenduse viga" "Autentimise probleem" "Pole vahemikus" - "Interneti-ühendust ei tuvastatud, seadet ei ühendata automaatselt." + "Interneti-ühendust ei tuvastatud, seadet ei ühendata automaatselt uuesti." + "Interneti-ühendus puudub." "Salvestas: %1$s" "Ühendatud WiFi-abi kaudu" "Ühendatud üksuse %1$s kaudu" @@ -184,7 +185,6 @@ "Luba võltsasukohti" "Luba võltsasukohti" "Luba kuva atribuudi hindamine" - "Kasutage uue Androidi DHCP-kliendi asemel Lollipopi DHCP-klienti." "Hoidke mobiilne andmeside alati aktiivsena, isegi kui WiFi on aktiivne (võrkude kiireks vahetamiseks)." "Luban USB silumise?" "USB-silumine on mõeldud ainult arendamiseks. Kasutage seda andmete kopeerimiseks oma arvuti ja seadme vahel, seadmesse rakenduste installimiseks ilma teatisteta ning logiandmete lugemiseks." @@ -234,8 +234,6 @@ "Kuva klipi piirid, veerised jms" "Paremalt vasakule paig." "Määra lokaatides ekraanipaig. paremalt vasakule" - "CPU-kasutuse kuvamine" - "Praegust CPU-kasutust kuvav ekraani ülekate" "Jõusta GPU renderdamine" "Jõusta GPU kasutam. kahemõõtmeliste jooniste puhul" "Jõusta 4x MSAA" @@ -342,4 +340,5 @@ "Suurim" "Kohandatud (%d)" "Abi ja tagasiside" + "Menüü" diff --git a/packages/SettingsLib/res/values-eu-rES/arrays.xml b/packages/SettingsLib/res/values-eu-rES/arrays.xml index e349774a950614945bdb0435bd58c0b9dc01a76c..c6174457ca84566ad2d04f9e011e208c7fc6bcf5 100644 --- a/packages/SettingsLib/res/values-eu-rES/arrays.xml +++ b/packages/SettingsLib/res/values-eu-rES/arrays.xml @@ -84,11 +84,13 @@ "Desaktibatuta" "Guztiak" "Guztiak, irratiarenak izan ezik" + "kernela soilik" "Desaktibatuta" "Erregistroen buffer guztiak" "Erregistroen buffer guztiak, irratiarenak izan ezik" + "kernelaren erregistroaren bufferra soilik" "Animazioa desaktibatuta" diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml index e4c2d1bb0c38ece78942da4bf20fdeb8486b75c6..abcf2828e2c014ff8330acbfc78acef54fbcd55a 100644 --- a/packages/SettingsLib/res/values-eu-rES/strings.xml +++ b/packages/SettingsLib/res/values-eu-rES/strings.xml @@ -28,7 +28,8 @@ "Ezin izan da konektatu Wi-Fi sarera" "Autentifikazio-arazoa" "Urrunegi" - "Ez da hauteman Interneterako sarbiderik. Ez da automatikoki berriro konektatuko." + "Ez da hauteman Interneterako sarbiderik. Ez da automatikoki berriro konektatuko." + "Ezin da konektatu Internetera." "%1$s aplikazioak gorde du" "Wi‑Fi laguntzailearen bidez konektatuta" "%1$s bidez konektatuta" @@ -184,7 +185,6 @@ "Onartu kokapen faltsuak" "Onartu kokapen faltsuak" "Gaitu ikuspegiaren atributuak ikuskatzeko aukera" - "Erabili Lollipop bertsioko DHCP bezeroa eta ez Android DHCP bezero berria." "Mantendu mugikorreko datuak beti aktibo, baita Wi-Fi konexioa aktibo dagoenean ere (sarez bizkor aldatu ahal izateko)." "USB arazketa onartu?" "USB arazketa garapen-xedeetarako soilik dago diseinatuta. Erabil ezazu ordenagailuaren eta gailuaren artean datuak kopiatzeko, aplikazioak gailuan jakinarazi gabe instalatzeko eta erregistro-datuak irakurtzeko." @@ -234,8 +234,6 @@ "Erakutsi kliparen mugak, marjinak, etab." "Behartu eskuin-ezker norabidea." "Behartu pantaila-diseinuaren norabidea eskuin-ezker izatera eskualdeko ezarpen guztiekin." - "Erakutsi PUZ erabilera" - "PUZ erabilera erakusten duen pantaila-gainjartzea" "Behartu GPU errendatzea" "Behartu GPUa erabiltzera 2 dimentsioko marrazkietan." "Behartu 4x MSAA" @@ -342,4 +340,5 @@ "Handiena" "Pertsonalizatua (%d)" "Laguntza eta iritziak" + "Menua" diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml index 60f1757b0fb25f09b5d16d65f6e07e5e673012eb..6dc8491cd589d89643dd03a1fd77ee996b78b2a3 100644 --- a/packages/SettingsLib/res/values-fa/arrays.xml +++ b/packages/SettingsLib/res/values-fa/arrays.xml @@ -84,11 +84,13 @@ "خاموش" "همه" "همه به‌جز رادیو" + "فقط هسته اصلی" "خاموش" "همه بافرهای گزارش" "همه به‌جز بافرهای گزارش رادیو" + "فقط بافر گزارش هسته اصلی" "پویانمایی خاموش" diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 541440acee375b9801d4723db17606050c14af84..c573b687967e1086481c19b3752d4d4043fcccca 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -28,7 +28,8 @@ "‏اتصال Wi-Fi برقرار نشد" "مشکل احراز هویت" "در محدوده نیست" - "دسترسی به اینترنت شناسایی نشد، به صورت خودکار وصل نمی‌شود." + "دسترسی به اینترنت شناسایی نشد، به‌صورت خودکار وصل نمی‌شود." + "دسترسی به اینترنت وجود ندارد." "ذخیره‌شده توسط %1$s" "‏متصل شده از طریق دستیار Wi-Fi" "‏متصل از طریق %1$s" @@ -183,8 +184,7 @@ "‏انتخاب پیکربندی USB" "مکان‌های کاذب مجاز هستند" "مکان‌های کاذب مجاز هستند" - "فعال کردن بازبینی ویژگی بازدید" - "‏به جای کلاینت Android DHCP جدید، از کلاینت Lollipop DHCP استفاده کنید." + "فعال کردن نمایش بازبینی ویژگی" "‏داده سلولی همیشه فعال نگه داشته می‌شود، حتی وقتی Wi-Fi فعال است (برای جابه‌جایی سریع شبکه)." "‏اشکال‌زدایی USB انجام شود؟" "‏اشکال‌زدایی USB فقط برای اهداف برنامه‌نویسی در نظر گرفته شده است. از آن برای رونوشت‌برداری داده بین رایانه و دستگاهتان، نصب برنامه‌ها در دستگاهتان بدون اعلان و خواندن داده‌های گزارش استفاده کنید." @@ -234,8 +234,6 @@ "نمایش مرزها، حاشیه‌ها و ویژگی‌های دیگر کلیپ." "‏اجباری کردن چیدمان RTL" "‏اجباری کردن چیدمان RTL صفحه برای همه زبان‌ها" - "‏نمایش میزان استفاده از CPU" - "‏هم‌پوشانی صفحه‌نمایش میزان استفاده از CPU فعلی" "‏پردازش اجباری GPU" "‏استفاده اجباری از GPU برای طراحی دوم" "‏اجبار 4x MSAA" @@ -342,4 +340,5 @@ "بزرگ‌ترین" "سفارشی (%d)" "راهنما و بازخورد" + "منو" diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml index 6796235c0be8dc92ae7dc15ac2ba79f4cce92261..3c2fe617c425bf26dd366c8f7489a72d7905d735 100644 --- a/packages/SettingsLib/res/values-fi/arrays.xml +++ b/packages/SettingsLib/res/values-fi/arrays.xml @@ -84,11 +84,13 @@ "Ei käytössä" "Kaikki" "Kaikki paitsi radio" + "vain kernel" "Ei käytössä" "Kaikki lokipuskurit" "Kaikki paitsi radiolokipuskurit" + "vain kernel-lokipuskuri" "Animaatio pois käytöstä" diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 0999c860efc76607fd13ddefcb955a741f0b6aa5..05f786addec2309a1fd8a2411faba8ad6d35ce32 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi-yhteysvirhe" "Todennusvirhe" "Ei kantoalueella" - "Internetyhteyttä ei havaittu, yhteyttä ei muodosteta automaattisesti uudelleen." + "Internetyhteyttä ei havaittu. Yhteyttä ei muodosteta automaattisesti uudelleen." + "Ei internetyhteyttä" "Tallentaja: %1$s" "Yhteys muodostettu Wi‑Fi-apurin kautta" "Yhdistetty seuraavan kautta: %1$s" @@ -184,7 +185,6 @@ "Salli sijaintien imitointi" "Salli sijaintien imitointi" "Ota attribuuttinäkymän tarkistus käyttöön" - "Käytä Lollipopin DHCP-asiakassovellusta Androidin uuden DHCP-asiakassovelluksen sijasta." "Pidä mobiilidata aina käytössä, vaikka Wi-Fi olisi aktiivinen. Tämä mahdollistaa nopeamman vaihtelun verkkojen välillä." "Sallitaanko USB-vianetsintä?" "USB-vianetsintä on tarkoitettu vain kehittäjien käyttöön. Sen avulla voidaan kopioida tietoja tietokoneesi ja laitteesi välillä, asentaa laitteeseesi sovelluksia ilmoittamatta siitä sinulle ja lukea lokitietoja." @@ -234,8 +234,6 @@ "Näytä leikkeiden rajat, marginaalit jne." "Pakota RTL-ulkoasun suunta" "Pakota kaikkien kielten näytön ulkoasun suunnaksi RTL" - "Näytä suorittimen käyttö" - "Näytön peittokuva näyttää nykyisen suoritinkäytön" "Pakota GPU-hahmonnus" "Käytä GPU:ta 2d-piirtämiseen" "Pakota 4x MSAA" @@ -342,4 +340,5 @@ "Suurin" "Muokattu (%d)" "Ohje ja palaute" + "Valikko" diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml index b0be48af1447443cb6fa096a995a80f24a0ee3fa..ba25d2752de644268efa17ab0ff203b9a33c3c17 100644 --- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml +++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml @@ -84,11 +84,13 @@ "Désactivé" "Tous" "Tous sauf radio" + "noyau uniquement" "Désactivé" "Tous les tampons de journal" "Tous les tampons de journal sauf celui de la radio" + "tampon journal du noyau uniquement" "Animation désactivée" diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 62395b8f5685fa0d0c823b53e411e66549c331b7..732d515498edcfafb41429eec9e044053af4262b 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -28,7 +28,8 @@ "Échec de connexion Wi-Fi" "Problème d\'authentification" "Hors de portée" - "Aucun accès à Internet détecté, reconnexion automatique impossible" + "Aucun accès à Internet détecté, reconnexion automatique impossible." + "Aucun accès à Internet." "Enregistrés par %1$s" "Connecté à l\'aide de l\'assistant Wi-Fi" "Connecté par %1$s" @@ -90,7 +91,7 @@ "Point d\'accès Wi-Fi mobile" "Via Bluetooth" "Partage de connexion" - "Partage de connexion et point d\'accès mobile" + "Partage de connexion" "Toutes les applis profess." "Invité" "Inconnu" @@ -184,7 +185,6 @@ "Autoriser les positions fictives" "Autoriser les positions fictives" "Activer l\'inspection d\'attribut d\'affichage" - "Utiliser le client DHCP de Lollipop au lieu du nouveau client DHCP Android." "Toujours garder les données cellulaires actives, même lorsque le Wi-Fi est activé (pour la commutation rapide entre les réseaux)." "Autoriser le débogage USB?" "Le débogage USB est conçu uniquement pour le développement. Utilisez-le pour copier des données entre votre ordinateur et votre appareil, installer des applications sur votre appareil sans notification et lire les données de journal." @@ -234,8 +234,6 @@ "Afficher les limites, les marges de clip, etc." "Forcer orient. : g. à d." "Forcer l\'orientation: g. à droite (toutes langues)" - "Afficher mém. CPU utilisée" - "Superposition écran indiquant mémoire CPU utilisée" "Forcer le rendu GPU" "Forcer l\'utilisation du GPU pour le dessin 2D" "Forcer MSAA 4x" @@ -342,4 +340,5 @@ "La plus grande" "Personnalisée (%d)" "Aide et commentaires" + "Menu" diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml index 14f175c08d81b4bc4c617c0aeb93a11bd44ef8b1..3340afb9341f00efea2393ffb90f283441283dd7 100644 --- a/packages/SettingsLib/res/values-fr/arrays.xml +++ b/packages/SettingsLib/res/values-fr/arrays.xml @@ -84,11 +84,13 @@ "Désactivé" "Tous" "Tous sauf radio" + "noyau uniquement" "Désactivé" "Toutes les mémoires tampon journal" "Toutes sauf les mémoires tampon journal radio" + "tampon journal du noyau uniquement" "Animation désactivée" diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 5dd2516ec6fd9a00a249180978a2f0a11cd8eeb7..3b5491f5ca33d3585a4c6d09a43235f0d541ae54 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -28,7 +28,8 @@ "Échec de la connexion Wi-Fi" "Problème d\'authentification." "Hors de portée" - "Aucun accès à Internet détecté, reconnexion automatique impossible" + "Aucun accès à Internet détecté. Reconnexion automatique impossible." + "Aucun accès à Internet" "Enregistré par %1$s" "Connecté via l\'assistant Wi‑Fi" "Connecté via %1$s" @@ -184,7 +185,6 @@ "Positions fictives" "Autoriser les positions fictives" "Activer inspect. attribut affich." - "Utiliser le client DHCP de Lollipop au lieu du nouveau client DHCP Android" "Maintenir l\'état actif des données mobiles, même lorsque le Wi‑Fi est actif (pour changer rapidement de réseau)" "Autoriser le débogage USB ?" "Le débogage USB est conçu uniquement pour le développement. Utilisez-le pour copier des données entre votre ordinateur et votre appareil, installer des applications sur votre appareil sans notification et lire les données de journal." @@ -234,8 +234,6 @@ "Afficher les limites de coupe, les marges, etc." "Forcer droite à gauche" "Forcer orient. droite à gauche pour toutes langues" - "Afficher mém. CPU utilisée" - "Superposition écran indiquant mémoire CPU utilisée" "Forcer le rendu GPU" "Forcer l\'utilisation du GPU pour le dessin 2D" "Forcer MSAA 4x" @@ -342,4 +340,5 @@ "Le plus grand" "Personnalisé (%d)" "Aide et commentaires" + "Menu" diff --git a/packages/SettingsLib/res/values-gl-rES/arrays.xml b/packages/SettingsLib/res/values-gl-rES/arrays.xml index db7184dacb4585ce52c13a1b47be3fa6524614e6..201cda220d3ea328b5abcc8e623a3c4242dd7f7d 100644 --- a/packages/SettingsLib/res/values-gl-rES/arrays.xml +++ b/packages/SettingsLib/res/values-gl-rES/arrays.xml @@ -84,11 +84,13 @@ "Desactivado" "Todo" "Agás radio" + "só kernel" "Desactivado" "Todos os búfers de rexistro" "Todo agás os búfers de rexistro de radio" + "só búfer do rexistro do kernel" "Animación desactivada" diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml index e1c24868b0ffd36af15c056de17772656350befd..dcd45a85dd301d165e1a64b023b7cd0cee2fb067 100644 --- a/packages/SettingsLib/res/values-gl-rES/strings.xml +++ b/packages/SettingsLib/res/values-gl-rES/strings.xml @@ -28,7 +28,8 @@ "Erro na conexión wifi" "Problema de autenticación" "Non está dentro da zona de cobertura" - "Non se detectou acceso a Internet e non se volverá conectar automaticamente." + "Non se detectou acceso a Internet e non se volverá establecer conexión automaticamente." + "Non hai acceso a Internet." "Redes gardadas por %1$s" "Conectado ao asistente de wifi" "Conectado a través de %1$s" @@ -184,7 +185,6 @@ "Permitir localizacións falsas" "Permite localizacións falsas" "Activar a inspección de atributos de visualización" - "Utiliza o cliente DHCP de Lollipop en lugar do novo cliente DHCP de Android." "Mantén sempre os datos móbiles activos, aínda que a wifi estea activada (para un rápido cambio de rede)." "Queres permitir a depuración USB?" "A depuración de erros USB está deseñada unicamente para fins de programación. Utilízaa para copiar datos entre o ordenador e o dispositivo, instalar aplicacións no dispositivo sen enviar notificacións e ler os datos do rexistro." @@ -234,8 +234,6 @@ "Mostra os límites dos clips, as marxes, etc." "Forzar dirección do deseño RTL" "Forza a dirección de pantalla a RTL (dereita a esquerda) para todas as configuración rexionais" - "Mostrar uso da CPU" - "Superpoñer o uso da CPU na pantalla" "Forzar procesamento GPU" "Forzar o uso de GPU para o debuxo en 2D" "Forzar MSAA 4x" @@ -342,4 +340,5 @@ "O máis grande" "Personalizado (%d)" "Axuda e suxestións" + "Menú" diff --git a/packages/SettingsLib/res/values-gu-rIN/arrays.xml b/packages/SettingsLib/res/values-gu-rIN/arrays.xml index e2d4a0641607e96d0e7ba9605eb881addeec5761..c7461889ac6676d2dfb4bf43f2c8b38218ee2d6b 100644 --- a/packages/SettingsLib/res/values-gu-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-gu-rIN/arrays.xml @@ -84,11 +84,13 @@ "બંધ" "તમામ" "તમામ પરંતુ રેડિઓ" + "ફક્ત કર્નલ" "બંધ" "તમામ લૉગ બફર્સ" "તમામ પરંતુ રેડિઓ લૉગ બફર્સ" + "ફક્ત કર્નલ લૉગ બફર" "એનિમેશન બંધ" diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml index b7ec401397e3b7c06789d603ec4bcc1c625874dd..554ca40a751b052148d25f8c90c94f57f23d5784 100644 --- a/packages/SettingsLib/res/values-gu-rIN/strings.xml +++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml @@ -28,7 +28,8 @@ "WiFi કનેક્શન નિષ્ફળ" "પ્રમાણીકરણ સમસ્યા" "રેન્જમાં નથી" - "કોઈ ઇન્ટરનેટ અ‍ૅક્સેસ શોધાયું નથી, આપમેળે ફરીથી કનેક્ટ કરશે નહીં." + "કોઈ ઇન્ટરનેટ અ‍ૅક્સેસ મળી નથી, આપમેળે ફરીથી કનેક્ટ કરશે નહીં." + "કોઈ ઇન્ટરનેટ ઍક્સેસ નથી." "%1$s દ્વારા સચવાયું" "Wi-Fi સહાયક દ્વારા કનેક્ટ થયું" "%1$s દ્વારા કનેક્ટ થયેલ" @@ -184,7 +185,6 @@ "મોક સ્થાનોની મંજૂરી આપો" "મોક સ્થાનોની મંજૂરી આપો" "લક્ષણ નિરીક્ષણ જોવાનું સક્ષમ કરો" - "નવા Android DHCP ક્લાઇન્ટને બદલે Lollipop પરના DHCP ક્લાઇન્ટનો ઉપયોગ કરો." "Wi‑Fi સક્રિય હોય ત્યારે પણ, હંમેશા મોબાઇલ ડેટાને સક્રિય રાખો (ઝડપી નેટવર્ક સ્વિચિંગ માટે)." "USB ડિબગિંગને મંજૂરી આપીએ?" "USB ડિબગીંગ ફક્ત વિકાસ હેતુઓ માટે જ બનાવાયેલ છે. તેનો ઉપયોગ તમારા કમ્પ્યુટર અને તમારા ઉપકરણ વચ્ચે ડેટાને કૉપિ કરવા, સૂચના વગર તમારા ઉપકરણ પર ઍપ્લિકેશનો ઇન્સ્ટોલ કરવા અને લૉગ ડેટા વાંચવા માટે કરો." @@ -234,8 +234,6 @@ "ક્લિપ બાઉન્ડ્સ, હાંસિયાં વગેરે બતાવો." "RTL લેઆઉટ દિશા નિર્દેશની ફરજ પાડો" "તમામ લૉકેલ્સ માટે સ્ક્રીન લેઆઉટ દિશા નિર્દેશને RTL ની ફરજ પાડો" - "CPU સંગ્રહ બતાવો" - "વર્તમાન CPU વપરાશ દર્શાવતું સ્ક્રીન ઓવરલે" "GPU રેન્ડરિંગની ફરજ પાડો" "2જા રેખાંકન માટે GPU ના ઉપયોગની ફરજ પાડો" "4x MSAA ને ફરજ પાડો" @@ -342,4 +340,5 @@ "સૌથી મોટું" "કસ્ટમ (%d)" "સહાય અને પ્રતિસાદ" + "મેનુ" diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml index e54b8c57cf6fdc4c9deaa5cd814e99d5023dcec3..29b6beff427db1f87e1671511c0829f43c771679 100644 --- a/packages/SettingsLib/res/values-hi/arrays.xml +++ b/packages/SettingsLib/res/values-hi/arrays.xml @@ -84,11 +84,13 @@ "बंद" "सभी" "रेडियो छोड़कर सभी" + "केवल कर्नल" "बंद" "सभी लॉग बफ़र" "रेडियो लॉग बफ़र को छोड़कर सभी" + "केवल कर्नल लॉग बफ़र" "एनिमेशन बंद" diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 45b3e3b03b08da99c6b72683eae4150acd9c39ac..fb6f181e6b20d32083dbe3dc6dbe33396bc76c29 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -28,7 +28,8 @@ "वाईफ़ाई कनेक्‍शन विफलता" "प्रमाणीकरण समस्या" "रेंज में नहीं" - "किसी इंटरनेट कनेक्‍शन का पता नहीं चला, अपने आप पुन: कनेक्‍ट नहीं हो सकता." + "किसी इंटरनेट कनेक्‍शन का पता नहीं चला, अपने आप फिर से कनेक्‍ट नहीं हो सकता." + "कोई इंटरनेट एक्सेस नहीं." "%1$s के द्वारा सहेजा गया" "वाई-फ़ाई सहायक के द्वारा कनेक्‍ट है" "%1$s के द्वारा उपलब्ध" @@ -184,7 +185,6 @@ "कृत्रिम स्‍थानों को अनुमति दें" "कृत्रिम स्‍थानों को अनुमति दें" "दृश्य विशेषता निरीक्षण सक्षम करें" - "नए Android DHCP क्‍लाइंट के बजाय Lollipop के DHCP क्‍लाइंट का उपयोग करें." "वाई-फ़ाई के सक्रिय रहने पर भी, हमेशा मोबाइल डेटा सक्रिय रखें (तेज़ी से नेटवर्क स्विच करने के लिए)." "USB डीबग करने की अनुमति दें?" "USB डीबग डीबग करने का उद्देश्‍य केवल विकास है. इसका उपयोग आपके कंप्‍यूटर और आपके डिवाइस के बीच डेटा की प्रतिलिपि बनाने, बिना नोटिफिकेशन के आपके डिवाइस पर ऐप्स इंस्‍टॉल करने और लॉग डेटा पढ़ने के लिए करें." @@ -234,8 +234,6 @@ "क्लिप सीमाएं, मार्जिन, आदि दिखाएं." "RTL लेआउट दिशा लागू करें" "सभी भाषाओं के लिए स्क्रीन लेआउट दिशा को RTL रखें" - "CPU उपयोग दिखाएं" - "स्‍क्रीन ओवरले वर्तमान CPU उपयोग को दिखा रहा है" "बलपूर्वक GPU रेंडर करें" "2d ड्रॉइंग के लिए GPU का बलपूर्वक उपयोग करें" "4x MSAA को बाध्य करें" @@ -342,4 +340,5 @@ "सबसे बड़ा" "कस्टम (%d)" "सहायता और फ़ीडबैक" + "मेनू" diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml index 795cf68c4b32026e5b666cd5448d8ce41b5e9d45..a2d253c05a1f6cd810e0d6793e082b2e121d1910 100644 --- a/packages/SettingsLib/res/values-hr/arrays.xml +++ b/packages/SettingsLib/res/values-hr/arrays.xml @@ -84,11 +84,13 @@ "Isključeno" "Sve" "Sve osim radija" + "samo jezgra" "Isključeno" "Svi međuspremnici zapisa" "Sve osim međuspremnika zapisnika radija" + "samo međuspremnik zapisnika jezgre" "Animacija isključena" diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index cda2fb9e6bcd20065175419c0fa30516541e7ee9..619826d274f495f0235347ee2b182a05e701b683 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -28,7 +28,8 @@ "Povezivanje s Wi-Fi-jem nije uspjelo" "Problem u autentifikaciji" "Nije u rasponu" - "Pristup internetu nije otkriven. Nema automatskog ponovnog povezivanja." + "Pristup internetu nije otkriven. Nema automatskog ponovnog povezivanja." + "Nema pristupa internetu." "Spremljeno: %1$s" "Povezani putem pomoćnika za Wi-Fi" "Povezano putem %1$s" @@ -184,7 +185,6 @@ "Dopusti probne lokacije" "Dopusti probne lokacije" "Omogući pregled atributa prikaza" - "Upotrebljavajte DHCP klijent iz Lollipopa umjesto novog Android DHCP klijenta." "Neka mobilni podaci uvijek budu aktivni, čak i kada je Wi‑Fi aktivan (za brzo prebacivanje s jedne na drugu mrežu)." "Omogućiti otklanjanje pogrešaka putem USB-a?" "Otklanjanje pogrešaka putem USB-a namijenjeno je samo u razvojne svrhe. Može se upotrijebiti za kopiranje podataka s računala na uređaj i obrnuto, instalaciju aplikacija na uređaju bez obavijesti i za čitanje dnevničkih zapisa." @@ -234,8 +234,6 @@ "Prikazuju se obrubi, margine itd. isječaka." "Nametni zdesna ulijevo" "Nametni smjer zdesna ulijevo za sve zemlje/jezike" - "Prikaži upotrebu procesora" - "Na zaslonu se prikazuje iskorištenost procesora." "Nametni GPU renderiranje" "Nametni upotrebu GPU-a za 2D crteže" "Nametni 4x MSAA" @@ -342,4 +340,5 @@ "Najveće" "Prilagođeno (%d)" "Pomoć i povratne informacije" + "Izbornik" diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml index 850ef5d4e3864b77ece2d7f7c8b189efdd069811..41ce4b06db7d2764b06fc87b210e1c3387c8a179 100644 --- a/packages/SettingsLib/res/values-hu/arrays.xml +++ b/packages/SettingsLib/res/values-hu/arrays.xml @@ -84,11 +84,13 @@ "Kikapcsolva" "Összes" "Rádiót kivéve" + "csak kernel" "Kikapcsolva" "Minden naplópuffer" "A rádiónapló-pufferen kívül mindegyik" + "csak kernelnaplópuffer" "Animáció ki" diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 35312379cd443239e50207ccefc29eaf340fffcc..e389c0093a9e930e53187134b0362df49c15d4d3 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi-kapcsolati hiba" "Azonosítási probléma" "Hatókörön kívül" - "Nincs érzékelhető internet-hozzáférés, ezért nem kapcsolódik újra automatikusan." + "Nincs érzékelhető internet-hozzáférés, ezért nem kapcsolódik újra automatikusan." + "Nincs internet-hozzáférés." "Mentette: %1$s" "Csatlakozva Wi‑Fi-segéddel" "Csatlakozva a következőn keresztül: %1$s" @@ -184,7 +185,6 @@ "Helyutánzatok engedélyezése" "Helyutánzatok engedélyezése" "Nézetattribútum vizsgálatának engedélyezése" - "A Lollipop DHCP-kliensének használata az új androidos DHCP-kliens helyett." "A mobiladat-kapcsolat mindig maradjon aktív, még akkor is, ha a Wi‑Fi aktív (a gyors hálózatváltás érdekében)." "Engedélyezi az USB hibakeresést?" "Az USB hibakeresés fejlesztési célokat szolgál. Használhatja adatok másolására a számítógép és a készülék között, alkalmazások a készülékre való értesítés nélküli telepítésére és naplózási adatok olvasására." @@ -234,8 +234,6 @@ "Kliphatárok, margók stb. megjelenítése." "Elrendezés jobbról balra" "Elrendezés jobbról balra minden nyelvnél" - "CPU-használat mutatása" - "Képernyőfedvény a jelenlegi CPU-használattal" "GPU-megjelenítés" "GPU használatának kényszerítése 2D rajzhoz" "4x MSAA kényszerítése" @@ -327,7 +325,7 @@ "Rendszergazda által irányítva" "Engedélyezve a rendszergazda által" "Letiltva a rendszergazda által" - "Kezdőlap beállítása" + "Beállítások kezdőlapja" "0%" "50%" @@ -342,4 +340,5 @@ "Legnagyobb" "Egyéni (%d)" "Súgó és visszajelzés" + "Menü" diff --git a/packages/SettingsLib/res/values-hy-rAM/arrays.xml b/packages/SettingsLib/res/values-hy-rAM/arrays.xml index 43c5eab15c7b82951b3dd783e7adac13a9450b91..e93cbfcdf54733788401e4f4fdd66486e57ec757 100644 --- a/packages/SettingsLib/res/values-hy-rAM/arrays.xml +++ b/packages/SettingsLib/res/values-hy-rAM/arrays.xml @@ -84,11 +84,13 @@ "Անջատված է" "Բոլորը" "Բոլորը, ռադիոյից բացի" + "միայն միջուկը" "Անջատված է" "Մատյանի բոլոր բուֆերները" "Մատյանի բոլոր բուֆերները, ռադիո բուֆերներից բացի" + "միայն միջուկի մատյանի պահնակը" "Անջատել շարժապատկերը" diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml index 8472f6680fb390df52ed5ad01ae7a7e841370f7c..8d2d78efc45c5b0f720667691323880d62114dfe 100644 --- a/packages/SettingsLib/res/values-hy-rAM/strings.xml +++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml @@ -28,7 +28,8 @@ "WiFi կապի ձախողում" "Նույնականացման խնդիր" "Ընդգրկույթից դուրս է" - "Ինտերնետի հասանելիություն չկա. ավտոմատ կերպով կրկին չի միանա:" + "Ինտերնետ կապ չկա, ինչի պատճառով ավտոմատ վերամիացում չի կատարվի:" + "Ինտերնետ կապ չկա:" "Պահել է հետևյալ օգտվողը՝ %1$s" "Կապակցված է Wi‑Fi Օգնականի միջոցով" "Կապակցված է %1$s-ի միջոցով" @@ -38,7 +39,7 @@ "Անջատվում է..." "Միանում է..." "Միացված է" - "Զուգավորում..." + "Զուգակցում..." "Միացված (առանց հեռախոսի)" "Միացված է (առանց մեդիա)" "Միացված է (հաղորդագրությանը մուտք չկա)" @@ -72,7 +73,7 @@ "Զուգավորել" "Զուգավորել" "Չեղարկել" - "Զուգավորում է մուտքի թույլտվությունը դեպի ձեր կոնտակտները և զանգերի պատմությունը, երբ միացված է:" + "Զուգակցում է մուտքի թույլտվությունը դեպի ձեր կոնտակտները և զանգերի պատմությունը, երբ միացված է:" "Չհաջողվեց զուգավորել %1$s-ի հետ:" "Հնարավոր չեղավ զուգավորվել %1$s-ի հետ սխալ PIN-ի կամ անցաբառի պատճառով:." "Հնարավոր չէ կապ հաստատել %1$s-ի հետ:" @@ -184,7 +185,6 @@ "Թույատրել կեղծ տեղադրությունները" "Թույլ տալ կեղծ տեղադրություններ" "Միացնել ցուցադրման հատկանիշների ստուգումը" - "Օգտագործել Lollipop-ի DHCP ծրագիրը՝ նոր Android DHCP ծրագրի փոխարեն:" "Միշտ ակտիվացրած պահել բջջային տվյալները, նույնիսկ Wi‑Fi-ը միացրած ժամանակ (ցանցերի միջև արագ փոխարկման համար):" "Թույլատրե՞լ USB-ի վրիպազերծումը:" "USB վրիպազերծումը միայն ծրագրավորման նպատակների համար է: Օգտագործեք այն ձեր համակարգչից տվյալները ձեր սարք պատճենելու համար, առանց ծանուցման ձեր սարքի վրա ծրագրեր տեղադրելու և տվյալների մատյանը ընթերցելու համար:" @@ -234,8 +234,6 @@ "Ցույց տալ կտրվածքի սահմանները, լուսանցքները և այլն" "Փոխել RTL-ի դասավորության ուղղությունը" "Դարձնել էկրանի դասավորության ուղղությունը դեպի RTL բոլոր լեզուների համար" - "Ցույց տալ CPU-ի աշխատանքը" - "Էկրանի վերադրումը ցույց է տալիս ընթացիկ CPU օգտագործումը" "Ստիպել GPU-ին մատուցել" "Ստիպողաբար GPU-ի օգտագործում 2-րդ պատկերի համար" "Ստիպել 4x MSAA" @@ -342,4 +340,5 @@ "Ամենամեծ" "Հատուկ (%d)" "Օգնություն և հետադարձ կապ" + "Ընտրացանկ" diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml index 47223d25b06501f9e2e9581db9578696b0c4e876..a6126391c1c3a0848a3fcc1aa441d1e5e07b516f 100644 --- a/packages/SettingsLib/res/values-in/arrays.xml +++ b/packages/SettingsLib/res/values-in/arrays.xml @@ -84,11 +84,13 @@ "Nonaktif" "Semua" "Selain radio" + "khusus kernel" "Nonaktif" "Semua penyangga log" "Semua kecuali penyangga log radio" + "khusus penyangga log kernel" "Animasi mati" diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 2d7115ac846f46b8ba45ca7f2f6412bcf1cfe674..0e0d32f0065d93bc9ebfef36a6f3bdf0a330164c 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -28,7 +28,8 @@ "Kegagalan Sambungan Wi-Fi" "Masalah autentikasi" "Tidak dalam jangkauan" - "Akses Internet Tidak Terdeteksi, tidak akan menyambung ulang secara otomatis." + "Akses Internet Tidak Terdeteksi, tidak akan menyambung ulang secara otomatis." + "Tidak Ada Akses Internet." "Disimpan oleh %1$s" "Terhubung melalui Asisten Wi-Fi" "Terhubung melalui %1$s" @@ -184,7 +185,6 @@ "Mengizinkan lokasi palsu" "Mengizinkan lokasi palsu" "Aktifkan inspeksi atribut tampilan" - "Gunakan klien DHCP dari Lollipop alih-alih klien DHCP Android baru." "Selalu aktifkan data seluler, meski Wi-Fi aktif (agar jaringan beralih dengan cepat)." "Izinkan melakukan debug USB?" "Debugging USB dimaksudkan untuk tujuan pengembangan saja. Gunakan untuk menyalin data antara komputer dan perangkat Anda, memasang apl pada perangkat tanpa notifikasi, dan membaca data log." @@ -234,8 +234,6 @@ "Tampilkan batas klip, margin, dll." "Paksa arah tata letak RTL" "Paksa arah tata letak layar RTL untuk semua lokal" - "Tampilkan penggunaan CPU" - "Hamparan layar menampilkan penggunaan CPU saat ini" "Paksa perenderan GPU" "Paksa penggunaan GPU untuk gambar 2d" "Force 4x MSAA" @@ -342,4 +340,5 @@ "Terbesar" "(%d) khusus" "Bantuan & masukan" + "Menu" diff --git a/packages/SettingsLib/res/values-is-rIS/arrays.xml b/packages/SettingsLib/res/values-is-rIS/arrays.xml index 324f689391784f9fe2bbdc486edee2ee2ca8606c..64d4da202059dee80d843b49dc59cd672524c79a 100644 --- a/packages/SettingsLib/res/values-is-rIS/arrays.xml +++ b/packages/SettingsLib/res/values-is-rIS/arrays.xml @@ -84,11 +84,13 @@ "Slökkt" "Allt" "Allt n. útvarp" + "einungis kjarni" "Slökkt" "Allt biðminni" "Allt nema útvarpsbiðminni" + "einungis kjarnaannálabiðminni" "Slökkt á hreyfiáhrifum" diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml index db23162ac5a0017c26042e8006dd9d7f2657450c..d1c177bcd44d98384772503c25a93d63347340bb 100644 --- a/packages/SettingsLib/res/values-is-rIS/strings.xml +++ b/packages/SettingsLib/res/values-is-rIS/strings.xml @@ -28,7 +28,8 @@ "WiFi-tengingarvilla" "Vandamál við auðkenningu" "Ekkert samband" - "Enginn netaðgangur fannst; endurtengist ekki sjálfkrafa." + "Enginn netaðgangur fannst, endurtengist ekki sjálfkrafa." + "Enginn netaðgangur." "%1$s vistaði" "Tengt í gegnum Wi-Fi aðstoð" "Tengt í gegnum %1$s" @@ -184,7 +185,6 @@ "Leyfa gervistaðsetningar" "Leyfa gervistaðsetningar" "Virkja yfirlit skoðunar eiginda" - "Nota gamla DHCP-biðlarann úr Lollipop í staðinn fyrir nýja Android DHCP-biðlarann." "Hafa alltaf kveikt á farsímagögnum, líka þegar kveikt er á Wi-Fi (til að skipta megi hratt milli kerfa)." "Leyfa USB-villuleit?" "USB-villuleit er aðeins ætluð til nota í þróunarskyni. Hana má nota til að afrita gögn á milli tölvu og tækis, setja forrit upp í tækinu án tilkynninga og lesa annálagögn." @@ -234,8 +234,6 @@ "Sýna skurðlínur, spássíur o.s.frv." "Þvinga umbrot frá hægri til vinstri" "Þvinga umbrot skjás frá hægri til vinstri fyrir alla tungumálskóða" - "Sýna örgjörvanotkun" - "Skjáyfirlögn sem sýnir núverandi örgjörvanotkun" "Þvinga skjákortsteiknun" "Þvinga notkun skjákorts fyrir tvívíða teikningu" "Þvinga 4x MSAA" @@ -342,4 +340,5 @@ "Stærst" "Sérsniðið (%d)" "Hjálp og ábendingar" + "Valmynd" diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml index 45fe546e29a84fed02049f1db92f9bafd2f3e3a5..e6938e0e33c5ac389bcff131c3dfb0649b700195 100644 --- a/packages/SettingsLib/res/values-it/arrays.xml +++ b/packages/SettingsLib/res/values-it/arrays.xml @@ -84,11 +84,13 @@ "Off" "Tutti" "Tutti tranne il segnale radio" + "solo kernel" "Off" "Tutti i buffer log" "Tutti tranne i buffer log del segnale radio" + "solo buffer log kernel" "Animazione disattivata" diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 600e0e07f03645b9af837c9a60aa3a442207c368..c566e79a7f0a2b27205b8e6c041f1958c74fd88a 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -28,7 +28,8 @@ "Errore connessione Wi-Fi" "Problema di autenticazione" "Fuori portata" - "Nessun accesso a Internet rilevato, non verrà eseguita la riconnessione automatica." + "Nessun accesso a Internet rilevato. Non verrà eseguita la riconnessione automatica." + "Nessun accesso a Internet." "Salvata da %1$s" "Connesso tramite assistente Wi‑Fi" "Collegato tramite %1$s" @@ -184,7 +185,6 @@ "Posizioni fittizie" "Consenti posizioni fittizie" "Attiva controllo attributi visualizzazione" - "Utilizza il client DHCP di Lollipop anziché il nuovo client DHCP Android." "Mantieni sempre i dati cellulare attivi, anche se il Wi‑Fi è attivo (per un passaggio fra reti rapido)." "Consentire debug USB?" "Il debug USB è solo a scopo di sviluppo. Utilizzalo per copiare dati tra il computer e il dispositivo, per installare applicazioni sul tuo dispositivo senza notifica e per leggere i dati dei log." @@ -192,7 +192,7 @@ "Consentire impostazioni di sviluppo?" "Queste impostazioni sono utilizzabili solo a scopo di sviluppo. Possono causare l\'arresto o il comportamento anomalo del dispositivo e delle applicazioni su di esso." "Verifica app tramite USB" - "Controlla che le applicazioni installate tramite ADB/ADT non abbiano un comportamento dannoso." + "Controlla che le app installate tramite ADB/ADT non abbiano un comportamento dannoso." "Consente di disattivare la funzione del volume assoluto Bluetooth in caso di problemi con il volume dei dispositivi remoti, ad esempio un volume troppo alto o la mancanza di controllo." "Terminale locale" "Abilita l\'app Terminale che offre l\'accesso alla shell locale" @@ -234,8 +234,6 @@ "Mostra limiti, margini dei clip e così via" "Forza direzione layout RTL" "Direzione layout schermo RTL per tutte le lingue" - "Mostra utilizzo CPU" - "Overlay schermo che mostra l\'uso corrente della CPU" "Forza rendering GPU" "Forza l\'uso della GPU per i disegni 2D" "Forza MSAA 4x" @@ -329,9 +327,9 @@ "Disattivata dall\'amministratore" "Home page Impostazioni" - "0%%" - "50%%" - "100%%" + "0%" + "50%" + "100%" "%1$s fa" "%1$s rimanenti" @@ -342,4 +340,5 @@ "Massimo" "Personalizzato (%d)" "Guida e feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml index 7a186a0a3ed30f4de26e7d4c229d6d0d641e699a..7bd46ad3a301774d38c2b5400655e13702356089 100644 --- a/packages/SettingsLib/res/values-iw/arrays.xml +++ b/packages/SettingsLib/res/values-iw/arrays.xml @@ -84,11 +84,13 @@ "כבוי" "הכול" "הכול מלבד רדיו" + "ליבה בלבד" "כבוי" "כל מאגרי הנתונים הזמניים של היומן" "הכול מלבד מאגרי הנתונים הזמניים של יומן הרדיו" + "מאגר נתונים זמני של היומן השמור בליבה בלבד" "אנימציה כבויה" diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index e175e34fbbcda1213243a315cb7492784685ad62..4523380ca44734cc21a98291e87414ae819d52b4 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -28,7 +28,8 @@ "‏כשל בחיבור Wi-Fi" "בעיית אימות" "מחוץ לטווח" - "אין גישה לאינטרנט. לא יתבצע חיבור מחדש באופן אוטומטי." + "אין גישה לאינטרנט. לא יתבצע חיבור מחדש באופן אוטומטי." + "אין גישה לאינטרנט." "נשמר על ידי %1$s" "‏מחובר באמצעות אסיסטנט ה-Wi-Fi" "‏מחובר דרך %1$s" @@ -184,7 +185,6 @@ "אפשר מיקומים מדומים" "אפשר מיקומים מדומים" "אפשר בדיקת תכונת תצוגה" - "‏השתמש בלקוח DHCP של Lollipop במקום לקוח DHCP החדש של Android." "‏השאר את הנתונים לנייד פעילים תמיד, גם כש-Wi‑Fi פעיל (למעבר מהיר בין רשתות)." "‏לאפשר ניפוי באגים של USB?" "‏ניפוי באגים באמצעות USB מיועד למטרות פיתוח בלבד. השתמש בו להעתקת נתונים בין המחשב והמכשיר שלך, להתקנת אפליקציות במכשיר ללא התראה ולקריאת נתוני יומן." @@ -234,8 +234,6 @@ "הצג גבולות קליפ, שוליים וכו\'" "אלץ כיוון פריסה מימין לשמאל" "אלץ כיוון פריסת מסך מימין לשמאל עבור כל השפות בכל המקומות" - "‏הצג את השימוש ב-CPU" - "‏שכבת-על של מסך שמציגה את השימוש הנוכחי ב-CPU" "‏אלץ עיבוד ב-GPU" "‏אכוף שימוש ב-GPU לשרטוט דו-מימדי" "‏אלץ הפעלת 4x MSAA" @@ -342,4 +340,5 @@ "הכי גדול" "מותאם אישית (%d)" "עזרה ומשוב" + "תפריט" diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml index e34f27010197163b2646acddcc555ab78fa8284e..5b9b41cf6772b256a22e35ecd917fcc0a10f079f 100644 --- a/packages/SettingsLib/res/values-ja/arrays.xml +++ b/packages/SettingsLib/res/values-ja/arrays.xml @@ -84,11 +84,13 @@ "OFF" "すべて" "ラジオ以外すべて" + "カーネルのみ" "OFF" "すべてのログバッファ" "ラジオ ログバッファ以外すべて" + "カーネル ログ バッファのみ" "アニメーションオフ" diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index b9149b740aef3df7e435874759a0da7e984c2b53..1761adb503d893340bfb01abc8f886f3d973f443 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -28,7 +28,8 @@ "WiFi接続エラー" "認証に問題" "圏外" - "インターネットアクセスを検出できないため、自動的に再接続されません。" + "インターネット アクセスを検出できないため、自動的に再接続されません。" + "インターネットに接続していません。" "%1$sで保存" "Wi‑Fiアシスタント経由で接続" "%1$s経由で接続" @@ -184,7 +185,6 @@ "擬似ロケーションを許可" "擬似ロケーションを許可する" "表示属性検査を有効にする" - "新しいAndroid DHCPクライアントの代わりにLollipopのDHCPクライアントを使用します。" "Wi‑Fiが(ネットワークの自動切り替えで)ONのときでもモバイルデータが常にONになります。" "USBデバッグを許可しますか?" "USBデバッグは開発専用に設計されています。パソコンと端末の間でデータをコピーする場合や、アプリを通知なしで端末にインストールする場合、ログデータを読み取る場合に使用できます。" @@ -234,8 +234,6 @@ "クリップの境界線、マージンなどを表示" "RTLレイアウト方向を使用" "すべての言語/地域で画面レイアウト方向をRTLに設定" - "CPU使用状況を表示" - "現在のCPU使用状況をオーバーレイ表示する" "GPUレンダリングを使用" "2D描画にGPUを常に使用する" "4x MSAAを適用" @@ -344,4 +342,5 @@ "最大" "カスタム(%d)" "ヘルプとフィードバック" + "メニュー" diff --git a/packages/SettingsLib/res/values-ka-rGE/arrays.xml b/packages/SettingsLib/res/values-ka-rGE/arrays.xml index d3fdb2b6627dd9c87fb9569751f43dd94a79d7c5..5e63ddd2578acca37a2919d2b4b78fc5e79bb1db 100644 --- a/packages/SettingsLib/res/values-ka-rGE/arrays.xml +++ b/packages/SettingsLib/res/values-ka-rGE/arrays.xml @@ -84,11 +84,13 @@ "გამორთული" "ყველა" "რადიოს გარდა ყველა" + "მხოლოდ ბირთვი" "გამორთული" "ჟურნალების ყველა ბუფერი" "რადიოჟურნალების ბუფერების გარდა ყველა" + "მხოლოდ ბირთვის ჟურნალის ბუფერი" "ანიმაციის გამორთვა" diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml index a581a634837dad4bb0867fd5499d8f7ee3c411f9..a39d4b2ce0ec2cdca4f0c8aa140e7d7e609d8e4a 100644 --- a/packages/SettingsLib/res/values-ka-rGE/strings.xml +++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml @@ -28,7 +28,8 @@ "WiFi კავშირის შეფერხება" "ავთენტიკაციის პრობლემა" "არ არის დიაპაზონში" - "ინტერნეტთან წვდომის ამოცნობა ვერ მოხერხდა. ავტომატურად ხელახლა დაკავშირება არ განხორციელდება." + "ინტერნეტთან კავშირის ამოცნობა ვერ მოხერხდა. ავტომატურად ხელახლა დაკავშირება არ განხორციელდება." + "ინტერნეტთან კავშირი არ არის." "შენახული %1$s-ის მიერ" "დაკავშირებულია Wi-Fi თანაშემწით" "%1$s-ით დაკავშირებული" @@ -184,7 +185,6 @@ "ფიქტიური მდებარეობების დაშვება" "ფიქტიური მდებარეობების დაშვება" "ნახვის ატრიბუტის ინსპექტირების ჩართვა" - "ახალი Android DHCP კლიენტის ნაცვლად, Lollipop-ის DHCP კლიენტის გამოყენება." "მობილური მოწყობილობის მონაცემები ყოველთვის აქტიური დარჩეს, მაშინაც კი, როდესაც Wi-Fi აქტიურია (ქსელის სწრაფი გადართვისთვის)." "ჩაირთოს USB გამართვა?" "USB გამართვა განკუთვნილია მხოლოდ დეველოპერული მიზნებისთვის. გამოიყენეთ კომპიუტერსა და თქვენ მოწყობილობას შორის მონაცემების გადასატანად, თქვენ მოწყობილობაზე აპების შეტყობინების გარეშე დასაყენებლად და ჟურნალის მონაცემების წასაკითხად." @@ -234,8 +234,6 @@ "კლიპის საზღვრების, მინდვრების ჩვენება და ა.შ." "მარჯვნიდან მარცხნივ განლაგების მიმართულების იძულება" "ეკრანის RTL მიმართულებაზე იძულება ყველა ლოკალისათვის" - "ცენტრალური პროცესორის ჩატვირთვის ჩვენება" - "ეკრანის გადაფარვა აჩვენებს CPU ამჟამინდელ გამოყენებას" "GPU-აჩქარება" "GPU-ის ძალით გამოყენება 2d drawing-თვის" "4x MSAA-ს ჩართვა" @@ -342,4 +340,5 @@ "უდიდესი" "მორგებული (%d)" "დახმარება და გამოხმაურება" + "მენიუ" diff --git a/packages/SettingsLib/res/values-kk-rKZ/arrays.xml b/packages/SettingsLib/res/values-kk-rKZ/arrays.xml index c7103ab9ca676ccb274751a2ed2f0df446d6539c..d1dae87441525ac86006ae6388532c7bcccddae7 100644 --- a/packages/SettingsLib/res/values-kk-rKZ/arrays.xml +++ b/packages/SettingsLib/res/values-kk-rKZ/arrays.xml @@ -84,11 +84,13 @@ "Өшірулі" "Барлығы" "Радиодан басқасының барлығы" + "тек ядро" "Өшірулі" "Барлық журнал буфері" "Радио журналының буферлерінен басқасының барлығы" + "тек ядро журналының буфері" "Aнимация өшірілген" diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml index 704af065e2f4a4c613ed877c71b18b02006bfbb9..c636feb73aa65a6bc43dda52debed41fad87545d 100644 --- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml +++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi байланысының қатесі" "Растау мәселесі" "Аумақта жоқ" - "Интернетке қатынас анықталмады, автоматты түрде қайта қосылу орындалмайды." + "Интернетпен байланыс жоқ, автоматты түрде қайта қосылмайды." + "Интернетпен байланыс жоқ." "%1$s сақтаған" "Wi‑Fi көмекшісі арқылы қосылу орындалды" "%1$s арқылы қосылған" @@ -184,7 +185,6 @@ "Жасанды аймақтарға рұқсат беру" "Жасанды аймақтарды пайдалануға рұқсат беру" "Көру төлсипатын тексеруді қосу" - "Жаңа Android DHCP клиентінің орнына Lollipop ішіндегі DHCP клиентін пайдалану" "Wi‑Fi қосулы кезде де ұялы деректерді белсенді етіп ұстау (желіні жылдам ауыстыру үшін)." "USB жөндеулеріне рұқсат берілсін бе?" "USB жөндеу дамыту мақсаттарына ғана арналған. Оны компьютер және құрылғы арасында дерек көшіру, құрылғыға ескертусіз қолданба орнату және тіркелім деректерін оқу үшін қолданыңыз." @@ -234,8 +234,6 @@ "Қию шектерін, жиектерін, т.б көрсету." "Оңнан солға орналасу бағытына реттеу" "Экранның орналасу бағытын барлық тілдер үшін оңнан солға қарату" - "CPU (орталық өңдеу бірлігі) қолданысы" - "Экран бетіне ағымдағы CPU қолданысы көрсетіледі" "GPU рендерингін жылдамдату" "Графикалық процессорды 2d сызбаларына қолдану" "4x MSAA қолдану" @@ -342,4 +340,5 @@ "Ең үлкен" "Арнаулы (%d)" "Анықтама және пікір" + "Mәзір" diff --git a/packages/SettingsLib/res/values-km-rKH/arrays.xml b/packages/SettingsLib/res/values-km-rKH/arrays.xml index 08d3880e6a7f703b074887c6431c838b5b865a61..17371f6a8df42b76cc2235d1e3b1783ec0f494be 100644 --- a/packages/SettingsLib/res/values-km-rKH/arrays.xml +++ b/packages/SettingsLib/res/values-km-rKH/arrays.xml @@ -84,11 +84,13 @@ "បិទ" "ទាំង​អស់" "ទាំងអស់ក្រៅពីវិទ្យុ" + "kernel តែប៉ុណ្ណោះ" "បិទ" "អង្គចងចាំកំណត់ហេតុបណ្តោះអាសន្នទាំងអស់" "ទាំងអស់ក្រៅពីអង្គចងចាំកំណត់ហេតុវិទ្យុបណ្តោះអាសន្ន" + "អង្គចងចាំបណ្ដោះអាសន្នកំណត់ហេតុ kernel តែប៉ុណ្ណោះ" "បិទ​ចលនា" diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml index 996544b708e847f0204e08ed6ad845b3283f168d..94ce5f1596405a152408b226ae1231174a5faeeb 100644 --- a/packages/SettingsLib/res/values-km-rKH/strings.xml +++ b/packages/SettingsLib/res/values-km-rKH/strings.xml @@ -28,7 +28,8 @@ "ការ​ភ្ជាប់​ WiFi បរាជ័យ" "បញ្ហា​ក្នុង​ការ​ផ្ទៀងផ្ទាត់" "នៅ​ក្រៅ​តំបន់" - "រក​មិន​ឃើញ​ការ​ចូល​ដំណើរការ​អ៊ីនធឺណិត, នឹង​មិន​ភ្ជាប់​ឡើង​វិញ​ដោយ​ស្វ័យ​ប្រវត្តិ​ទេ។" + "រកមិនឃើញការតភ្ជាប់អ៊ីនធឺណិតទេ វានឹងមិនភ្ជាប់ឡើងវិញដោយស្វ័យប្រវត្តិទេ។" + "គ្មានការតភ្ជាប់អ៊ីនធឺណិតទេ" "បានរក្សាទុកដោយ %1$s" "បានភ្ជាប់តាមរយៈជំនួយការ Wi‑Fi" "បានភ្ជាប់តាមរយៈ %1$s" @@ -184,7 +185,6 @@ "ឲ្យ​ក្លែង​ទីតាំង" "អនុញ្ញាត​ទីតាំង​ក្លែងក្លាយ" "បើក​ការ​ត្រួតពិនិត្យ​គុណ​លក្ខណៈ​ទិដ្ឋភាព" - "ប្រើម៉ាស៊ីនកូន DHCP ចេញពី Lollipop ជំនួសឲ្យម៉ាស៊ីនកូន Android DHCP ថ្មី។" "រក្សាទិន្នន័យចល័តឲ្យសកម្មជានិច្ច បើទោះបីជា Wi‑Fi សកម្មក៏ដោយ (សម្រាប់ការប្តូរបណ្តាញដែលមានល្បឿនលឿន)។" "អនុញ្ញាត​ការ​កែ​កំហុស​យូអេសប៊ី?" "ការ​កែ​កំហុស​​យូអេសប៊ី​គឺ​សម្រាប់​តែ​ការ​អភិវឌ្ឍ​ប៉ុណ្ណោះ។ ប្រើ​វា​ដើម្បី​ចម្លង​ទិន្នន័យ​រវាង​កុំព្យូទ័រ និង​ឧបករណ៍​របស់​អ្នក ដំឡើង​កម្មវិធី​ក្នុង​ឧបករណ៍​របស់​អ្នក​ដោយ​មិន​ជូន​ដំណឹង និង​អាន​ទិន្នន័យ​កំណត់ហេតុ។" @@ -234,8 +234,6 @@ "បង្ហាញ​ការ​ភ្ជាប់​អត្ថបទ​សម្រង់ រឹម ។ល។" "បង្ខំ​ទិស​ប្លង់ RTL" "បង្ខំ​ទិស​ប្លង់​អេក្រង់​ទៅកាន់ RTL សម្រាប់​មូលដ្ឋាន​ទាំងអស់" - "បង្ហាញ​​ការ​ប្រើ CPU" - "អេក្រង់​ត្រួត​គ្នា​បង្ហាញ​​ការ​ប្រើ CPU បច្ចុប្បន្ន" "បង្ខំ​ឲ្យ​បង្ហាញ GPU" "បង្ខំ​ប្រើ GPU សម្រាប់​ការ​គូរ​លើក​ទី​ពីរ" "បង្ខំ 4x MSAA" @@ -342,4 +340,5 @@ "ធំបំផុត" "ផ្ទាល់ខ្លួន (%d)" "ជំនួយ និងមតិស្ថាបនា" + "ម៉ឺនុយ" diff --git a/packages/SettingsLib/res/values-kn-rIN/arrays.xml b/packages/SettingsLib/res/values-kn-rIN/arrays.xml index 432d46c04e820440a2df3b4053e8e50752631578..5f6d69976932a6c677694360db22766a9797d1ed 100644 --- a/packages/SettingsLib/res/values-kn-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-kn-rIN/arrays.xml @@ -84,11 +84,13 @@ "ಆಫ್" "ಎಲ್ಲಾ" "ಎಲ್ಲಾ ಆದರೆ ರೇಡಿಯೊ" + "ಕೆರ್ನಲ್ ಮಾತ್ರ" "ಆಫ್ ಆಗಿದೆ" "ಎಲ್ಲಾ ಲಾಗ್ ಬಫರ್‌ಗಳು" "ಎಲ್ಲಾ ಆದರೆ ರೇಡಿಯೊ ಲಾಗ್ ಬಫರ್‌ಗಳು" + "ಕೆರ್ನಲ್ ಲಾಗ್ ಬಫರ್ ಮಾತ್ರ" "ಆನಿಮೇಶನ್ ಆಫ್" diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml index 7bf14a15cc3f272fc49ac2c4c0137dcb3f77e896..03da75390e496b6b00e72c882ed170f50296cf99 100644 --- a/packages/SettingsLib/res/values-kn-rIN/strings.xml +++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml @@ -28,7 +28,8 @@ "WiFi ಸಂಪರ್ಕ ವಿಫಲತೆ" "ಪ್ರಮಾಣೀಕರಣ ಸಮಸ್ಯೆ" "ವ್ಯಾಪ್ತಿಯಲ್ಲಿಲ್ಲ" - "ಯಾವುದೇ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶ ಪತ್ತೆಯಾಗಿಲ್ಲ, ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರುಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ." + "ಯಾವುದೇ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶ ಪತ್ತೆಯಾಗಿಲ್ಲ, ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಮರುಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ." + "ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವಿಲ್ಲ." "%1$s ರಿಂದ ಉಳಿಸಲಾಗಿದೆ" "Wi‑Fi ಸಹಾಯಕದ ಮೂಲಕ ಸಂಪರ್ಕಿತಗೊಳಿಸಲಾಗಿದೆ" "%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ" @@ -71,7 +72,7 @@ "ಇನ್‌ಪುಟ್‌ಗಾಗಿ ಬಳಸು" "ಜೋಡಿ" "ಜೋಡಿ ಮಾಡು" - "ರದ್ದುಮಾಡು" + "ರದ್ದುಮಾಡಿ" "ಸಂಪರ್ಕಪಡಿಸಿದಾಗ, ಜೋಡಿಸುವಿಕೆಯು ನಿಮ್ಮ ಸಂಪರ್ಕಗಳು ಮತ್ತು ಕರೆ ಇತಿಹಾಸಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಅನುಮತಿಸುತ್ತದೆ." "%1$s ಜೊತೆಗೆ ಜೋಡಣೆ ಮಾಡಲಾಗಲಿಲ್ಲ." "ತಪ್ಪಾಗಿರುವ ಪಿನ್‌ ಅಥವಾ ಪಾಸ್‌ಕೀ ಕಾರಣದಿಂದಾಗಿ %1$s ಜೊತೆಗೆ ಜೋಡಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ." @@ -93,7 +94,7 @@ "ಟೆಥರಿಂಗ್ & ಪೋರ್ಟಬಲ್ ಹಾಟ್‌ಸ್ಪಾಟ್" "ಎಲ್ಲ ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು" "ಅತಿಥಿ" - "ಅಜ್ಞಾತ" + "ಅಪರಿಚಿತ" "ಬಳಕೆದಾರ: %1$s" "ಕೆಲವು ಡೀಫಾಲ್ಟ್‌ಗಳನ್ನು ಹೊಂದಿಸಲಾಗಿದೆ" "ಡೀಫಾಲ್ಟ್‌ಗಳನ್ನು ಹೊಂದಿಸಲಾಗಿಲ್ಲ" @@ -184,7 +185,6 @@ "ಅಣಕು ಸ್ಥಾನಗಳನ್ನು ಅನುಮತಿಸು" "ಅಣಕು ಸ್ಥಾನಗಳನ್ನು ಅನುಮತಿಸು" "ವೀಕ್ಷಣೆ ಆಟ್ರಿಬ್ಯೂಟ್ ಪರಿಶೀಲನೆ" - "ಹೊಸ Android DHCP ಕ್ಲೈಂಟ್ ಬದಲಾಗಿ Lollipop ನಿಂದ DHCP ಕ್ಲೈಂಟ್ ಬಳಸಿ." "ವೈ-ಫೈ ಸಕ್ರಿಯವಾಗಿರುವಾಗಲೂ, ಯಾವಾಗಲೂ ಮೊಬೈಲ್‌ ಡೇಟಾ ಸಕ್ರಿಯವಾಗಿರಿಸಿ (ವೇಗವಾಗಿ ನೆಟ್‌ವರ್ಕ್‌ ಬದಲಾಯಿಸಲು)." "USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದೇ?" "USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯು ಅಭಿವೃದ್ಧಿ ಉದ್ದೇಶಗಳಿಗೆ ಮಾತ್ರ ಆಗಿದೆ. ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ನಡುವೆ ಡೇಟಾವನ್ನು ನಕಲಿಸಲು, ಅಧಿಸೂಚನೆ ಇಲ್ಲದೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ಮತ್ತು ಲಾಗ್ ಡೇಟಾ ಓದಲು ಅದನ್ನು ಬಳಸಿ." @@ -234,8 +234,6 @@ "ಕ್ಲಿಪ್‌ನ ಗಡಿಗಳು, ಅಂಚುಗಳು, ಇತ್ಯಾದಿ ತೋರಿಸು." "RTL ಲೇಔಟ್‌ ಪರಿಮಿತಿ ಬಲಗೊಳಿಸಿ" "ಎಲ್ಲ ಸ್ಥಳಗಳಿಗಾಗಿ RTL ಗೆ ಸ್ಕ್ರೀನ್‌ ಲೇಔಟ್‌ ದಿಕ್ಕನ್ನು ಪ್ರಬಲಗೊಳಿಸಿ" - "CPU ಬಳಕೆಯನ್ನು ತೋರಿಸು" - "ಪ್ರಸ್ತುತ CPU ಬಳಕೆಯನ್ನು ತೋರಿಸುತ್ತಿರುವ ಪರದೆಯ ಓವರ್‌ಲೇ" "GPU ನೀಡುವಿಕೆ ಬಲಗೊಳಿಸು" "2d ಚಿತ್ರಕಲೆಗಾಗಿ GPU ಬಳಕೆ ಬಲಗೊಳಿಸಿ" "4x MSAA ಪ್ರಬಲಗೊಳಿಸಿ" @@ -313,7 +311,7 @@ "%1$s - %2$s" "%1$s - %2$s ವೈರ್‌‌ಲೆಸ್‌ನಿಂದ ಪೂರ್ಣವಾಗುವವರೆಗೆ" "%1$s - %2$s" - "ಅಜ್ಞಾತ" + "ಅಪರಿಚಿತ" "ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ" "AC ನಲ್ಲಿ ಚಾರ್ಜ್‌" "ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ" @@ -341,5 +339,6 @@ "ಸ್ವಲ್ಪ ದೊಡ್ಡ" "ದೊಡ್ಡ" "ಕಸ್ಟಮ್ (%d)" - "ಸಹಾಯ & ಪ್ರತಿಕ್ರಿಯೆ" + "ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ" + "ಮೆನು" diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml index 936e7d89f654b64f15c442edda4292039d95cca5..596f93e4abad1abf0721ebf358cf116dcdaf2cde 100644 --- a/packages/SettingsLib/res/values-ko/arrays.xml +++ b/packages/SettingsLib/res/values-ko/arrays.xml @@ -84,11 +84,13 @@ "사용 안함" "전체" "라디오 외 모두" + "커널만" "사용 안함" "모든 로그 버퍼" "라디오 로그 버퍼를 제외한 모든 버퍼" + "커널 로그 버퍼만" "애니메이션 사용 안함" diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index baa73004250a01aa3b09d7ddc12b29836f51ee6b..6910b375d7a024d72d8c2b60e1d1b31df0d06f0e 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi 연결 실패" "인증 문제" "범위 내에 없음" - "감지된 인터넷 액세스가 없으며 자동으로 다시 연결되지 않습니다." + "감지된 인터넷 액세스가 없으며 자동으로 다시 연결되지 않습니다." + "인터넷에 연결되어 있지 않습니다." "%1$s(으)로 저장됨" "Wi‑Fi 도우미를 통해 연결됨" "%1$s을(를) 통해 연결됨" @@ -184,7 +185,6 @@ "모의 위치 허용" "모의 위치 허용" "보기 속성 검사 사용" - "새로운 Android DHCP 클라이언트 대신 Lollipop의 DHCP 클라이언트 사용" "Wi‑Fi가 활성화되어 있을 때에도 빠른 네트워크 전환을 위하여 항상 모바일 데이터를 활성 상태로 유지합니다." "USB 디버깅을 허용하시겠습니까?" "USB 디버깅은 개발용으로만 설계되었습니다. 이 기능을 사용하면 컴퓨터와 기기 간에 데이터를 복사하고 알림 없이 기기에 앱을 설치하며 로그 데이터를 읽을 수 있습니다." @@ -234,8 +234,6 @@ "클립 경계, 여백 등을 표시" "RTL 레이아웃 방향 강제 적용" "모든 언어에 대해 화면 레이아웃 방향을 RTL로 강제 적용" - "CPU 사용량 표시" - "현재 CPU 사용량 오버레이 표시" "GPU 렌더링 강제 설정" "2D 드로잉용으로 GPU 강제 사용" "4x MSAA 강제 사용" @@ -341,5 +339,6 @@ "더 크게" "가장 크게" "맞춤(%d)" - "도움말 및 의견" + "고객센터" + "메뉴" diff --git a/packages/SettingsLib/res/values-ky-rKG/arrays.xml b/packages/SettingsLib/res/values-ky-rKG/arrays.xml index ffaaa5ca917473797cdda29afda89626ac4221c9..33a0b5d3e4c06ba3686485875e25185debedc8e2 100644 --- a/packages/SettingsLib/res/values-ky-rKG/arrays.xml +++ b/packages/SettingsLib/res/values-ky-rKG/arrays.xml @@ -84,11 +84,13 @@ "Өчүк" "Бардыгы" "Радиодон башка" + "өзөк гана" "Өчүк" "Бардык таржымал буферлери" "Радио таржымал буферлеринен башкаларынын баары" + "өзөктүк журнал буфери гана" "Анимацияны өчүрүү" diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml index bed6b6d8ea9e7e44dd925645d3d13c473faae5bc..711551b01c74535302f5a7d38f19c83cdde035d6 100644 --- a/packages/SettingsLib/res/values-ky-rKG/strings.xml +++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml @@ -28,7 +28,8 @@ "WiFi туташуусу бузулду" "Аутентификация маселеси бар" "Тейлөө аймагында эмес" - "Интернетке кирүү мүмкүнчүлүгү табылган жок, андыктан автоматтык түрдө кайра туташпайт." + "Интернетке кирүү мүмкүнчүлүгү жок, андыктан автоматтык түрдө кайра туташпайт." + "Интернетке туташпай турат." "%1$s тарабынан сакталды" "Wi‑Fi жардамчысы аркылуу туташып турат" "%1$s аркылуу жеткиликтүү" @@ -184,7 +185,6 @@ "Жасалма жайгашкан жерди көрсөтүүгө уруксат берилсин" "Жасалма жайгашкан жерди көрсөтүүгө уруксат берилсин" "Аттрибут текшерүүсүнүн көрүнүшүн иштетүү" - "Жаңы Android DHCP кардарынын ордуна Lollipop\'тон DHCP кардарын колдонуңуз." "Wi-Fi иштеп турганда да дайындар мобилдик тармак аркылуу өткөрүлө берсин (тармактар ортосунда тезирээк которулуу үчүн)." "USB аркылуу жөндөөгө уруксат берилсинби?" "USB-жөндөө - өндүрүү максатында гана түзүлгөн. Аны компүтериңиз менен түзмөгүңүздүн ортосунда берилиштерди алмашуу, түзмөгүңүзгө колдонмолорду эскертүүсүз орнотуу жана лог берилиштерин окуу үчүн колдонсоңуз болот." @@ -234,8 +234,6 @@ "Клиптин чектерин, талааларын ж.б. көргөзүү" "Солдон оңго багытына мажбурлоо" "Экрандын жайгашуу багытын бардык тилдер үчүн Оңдон-солго кылуу" - "CPU колдонулушун көрсөтүү" - "Учурдагы CPU колдонулушун көрсөтүүчү экран катмары" "GPU иштетүүсүн мажбурлоо" "2d тартуу үчүн GPU\'ну колдонууга мажбурлоо" "4x MSAA мажбурлоо" @@ -342,4 +340,5 @@ "Эң чоң" "Ыңгайлаштырылган (%d)" "Жардам жана жооп пикир" + "Меню" diff --git a/packages/SettingsLib/res/values-lo-rLA/arrays.xml b/packages/SettingsLib/res/values-lo-rLA/arrays.xml index 11ec7a85fee48297759ff20bccd7c95f1c5c0e6e..7a6b77ac4dc3733ce1b162c5a999e0fdf674064d 100644 --- a/packages/SettingsLib/res/values-lo-rLA/arrays.xml +++ b/packages/SettingsLib/res/values-lo-rLA/arrays.xml @@ -84,11 +84,13 @@ "ປິດ" "ທັງໝົດ" "ທັງໝົດຍົກເວັ້ນວິທະຍຸ" + "ເຄີນເນວເທົ່ານັ້ນ" "ປິດ" "ບັບເຟີບັນທຶກທັງໝົດ" "ທັງໝົດຍົກເວັ້ນບັບເຟີບັນທຶກວິທະຍຸ" + "ບັບເຟີບັນທຶກເຄີນເນວເທົ່ານັ້ນ" "ປິດອະນິເມຊັນ" diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml index a2569bf9303476823173fabeb5f4277f84f8f321..abf36e35891a7ace7a99c36288d9f08bb03f3246 100644 --- a/packages/SettingsLib/res/values-lo-rLA/strings.xml +++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml @@ -28,7 +28,8 @@ "​ການ​ເຊື່ອມ​ຕໍ່ WiFi ລົ້ມ​ເຫຼວ" "ບັນຫາການພິສູດຢືນຢັນ" "ບໍ່ຢູ່ໃນໄລຍະທີ່ເຊື່ອມຕໍ່ໄດ້" - "​ບໍ່​ພົບ​ການ​ເຊື່ອມ​ຕໍ່​ອິນ​ເຕີ​ເນັດ​, ຈະ​ບໍ່​ຖືກ​ເຊື່ອມ​ຕໍ່​ໃໝ່​ໂດຍ​ອັດ​ຕະ​ໂນ​ມັດ." + "ບໍ່ພົບການເຊື່ອມຕໍ່ອິນເຕີເນັດ, ຈະບໍ່ເຊື່ອມຕໍ່ໃໝ່ໂດຍອັດຕະໂນມັດ." + "ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ." "ບັນທຶກ​​​ໂດຍ %1$s" "ເຊື່ອມ​ຕໍ່​ຜ່ານ Wi‑Fi ຕົວ​ຊ່ວຍ​ແລ້ວ" "​ເຊື່ອມຕໍ່​ຜ່ານ %1$s ​ແລ້ວ" @@ -184,7 +185,6 @@ "ອະນຸຍາດໃຫ້ຈຳລອງຕຳແໜ່ງ" "ອະນຸຍາດໃຫ້ຈຳລອງຕຳແໜ່ງ" "ເປີດ​ນຳ​ໃຊ້​ການກວດ​ສອບ​ຄຸນ​ສົມ​ບັດ​ມຸມມອງ" - "ໃຊ້​ລູກ​ຄ້າ DHCP ຈາກ Lollipop ແທນ​ລູກ​ຄ້າ Android DHCP ໃໝ່." "ໃຫ້​ຂໍ້​ມູນ​ມື​ຖື​ເປີດ​ຢູ່​ສະ​ເໝີ, ແມ້​ແຕ່​ເມື່ອ Wi‑Fi ເປີດ​ຢູ່ (ສຳ​ລັບ​ການ​ສະ​ຫຼັບ​ເຄືອ​ຂ່າຍ​ໄວ)." "ອະນຸຍາດໃຫ້ດີບັ໊ກຜ່ານ USB?" "ການດີບັ໊ກຜ່ານ USB ແມ່ນມີຈຸດປະສົງເພື່ອການພັດທະນາເທົ່ານັ້ນ. ມັນສາມາດໃຊ້ເພື່ອສຳເນົາຂໍ້ມູນລະຫວ່າງຄອມພິວເຕີ ແລະອຸປະກອນຂອງທ່ານ, ຕິດຕັ້ງແອັບຯໂດຍບໍ່ຜ່ານການແຈ້ງເຕືອນ ແລະອ່ານຂໍ້ມູນການບັນທຶກ." @@ -234,8 +234,6 @@ "ສະແດງໜ້າປົກຄລິບ, ຂອບ ແລະອື່ນໆ." "ບັງ​ຄັບ​ໃຫ້ຮູບຮ່າງຂຽນຈາກຂວາຫາຊ້າຍ" "ບັງຄັບໃຫ້ຮູບຮ່າງໜ້າຈໍ ຂຽນຈາກຂວາໄປຊ້າຍ ສຳລັບທຸກພາສາ" - "ສະແດງການນຳໃຊ້ CPU" - "ການວາງຊ້ອນໜ້າຈໍທີ່ສະແດງການນຳໃຊ້ CPU ໃນປັດຈຸບັນ" "ບັງຄັບໃຊ້ GPU ປະມວນພາບ" "ບັງຄັບໃຊ້ GPU ເພື່ອການແຕ້ມພາບ 2 ມິຕິ" "ບັງຄັບໃຊ້ 4x MSAA" @@ -342,4 +340,5 @@ "ໃຫຍ່ທີ່ສຸດ" "ປັບແຕ່ງເອງ (%d)" "ຊ່ວຍເຫຼືອ & ຄຳຕິຊົມ" + "ເມນູ" diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml index 04bb2ed2620513147c40718cfc49d091a95f0348..49908ada5c2b7e810e12b908e5e7c8358c5bc9b8 100644 --- a/packages/SettingsLib/res/values-lt/arrays.xml +++ b/packages/SettingsLib/res/values-lt/arrays.xml @@ -84,11 +84,13 @@ "Išjungta" "Viskas" "Viskas, išsk. rad. r." + "tik branduolys" "Išjungta" "Visi žurnalų buferiai" "Visi, išskyrus radijo ryšio žurnalų buferius" + "tik branduolio žurnalo buferis" "Animacija išjungta" diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index f9decd6c19e4d549ce402f95f2bc14ef8e35be76..cab29de0f6a1e35e885562e596dc71a549553109 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -28,7 +28,8 @@ "„Wi-Fi“ ryšio triktis" "Autentifikavimo problema" "Ne diapazone" - "Neaptikta jokia prieiga prie interneto, nebus automatiškai iš naujo prisijungta." + "Neaptikta jokia prieiga prie interneto, nebus automatiškai iš naujo prisijungta." + "Nėra prieigos prie interneto." "Išsaugojo %1$s" "Prisijungta naudojant „Wi‑Fi“ pagelbiklį" "Prisijungta naudojant „%1$s“" @@ -184,7 +185,6 @@ "Leisti imituoti vietas" "Leisti imituoti vietas" "Įgalinti peržiūros atributų tikrinimą" - "DHCP kliento programos iš „Lollipop“ versijos naudojimas vietoje naujos „Android“ DHCP kliento programos." "Visada suaktyvinti mobiliojo ryšio duomenis, net kai aktyvus „Wi‑Fi“ ryšys (kad būtų galima greitai perjungti tinklą)." "Leisti USB perkrovimą?" "USB derinimas skirtas naudoti tik kūrimo tikslais. Jis gali būti naudojamas norint kopijuoti duomenis iš kompiuterio į įrenginį ir atvirkščiai, įdiegti programas įrenginyje be pranešimo ir skaityti žurnalo duomenis." @@ -234,8 +234,6 @@ "Rodyti iškarpų ribas, kraštines ir t. t." "Išdėst. iš dešin. į kairę" "Nust. visų lokalių ekran. išdėst. iš deš. į kairę" - "Rodyti centr. proc. naud." - "Ekrano perdanga rodo dabartinį centr. proc. naud." "Priverst. GPU atvaizd." "Priverstinai naudoti GPU atvaizduojant 2D formatą" "Priverst. vykdyti 4x MSAA" @@ -342,4 +340,5 @@ "Didžiausias" "Tinkintas (%d)" "Pagalba ir atsiliepimai" + "Meniu" diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml index f59a870b860c39b64a25fa033794b58d54129d0c..801de5d8fa4dee71e1767a4016fbef2eef9332ab 100644 --- a/packages/SettingsLib/res/values-lv/arrays.xml +++ b/packages/SettingsLib/res/values-lv/arrays.xml @@ -84,11 +84,13 @@ "Izslēgts" "Visi" "Visi, izņemot radio" + "tikai kodolā" "Izslēgts" "Visi reģistra buferi" "Visi, izņemot radio reģistra buferus" + "tikai kodola žurnāla buferī" "Animācija ir izslēgta" diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 54a576fece669ea51cb6a2989e70ffe66f76858a..90bf867403d02b690e6c5c10e51fa368383c0cd4 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi savienojuma kļūme" "Autentificēšanas problēma" "Nav diapazona ietvaros" - "Nevar noteikt interneta savienojumu. Savienojums netiks izveidots vēlreiz automātiski." + "Nevar noteikt interneta savienojumu. Savienojums netiks izveidots vēlreiz automātiski." + "Nav piekļuves internetam." "Saglabāja: %1$s" "Izveidots savienojums ar Wi‑Fi palīgu" "Savienots, izmantojot %1$s" @@ -184,7 +185,6 @@ "Atļaut neīstas vietas" "Atļaut neīstas vietas" "Iespējot atribūtu pārbaudi" - "Lietot DHCP klientu no operētājsistēmas Lollipop, nevis jauno Android DHCP klientu." "Mobilo datu savienojums būs vienmēr aktīvs, pat ja būs aktīvs Wi-Fi savienojums (ātrai ierīces pārslēgšanai uz citu tīklu)." "Vai atļaut USB atkļūdošanu?" "USB atkļūdošana ir paredzēta tikai ar izstrādi saistītām darbībām. Izmantojiet to datu kopēšanai no datora uz ierīci un pretēji, lietotņu instalēšanai ierīcē bez paziņojumiem un žurnāla datu lasīšanai." @@ -234,8 +234,6 @@ "Rādīt klipu robežas, malas utt." "Virziens no labās uz kreiso (Obligāts) WL: 295" "Obl. izkārt. virz. no labās uz kr. pusi visām lok." - "Rādīt CPU lietojumu" - "Ekrāna pārklājums ar aktuālo CPU lietojumu" "Piespiedu GPU render." "Izmantot GPU atveidi divdimensiju zīmējumiem" "4x MSAA piespiedu palaiš." @@ -342,4 +340,5 @@ "Vislielākais" "Pielāgots (%d)" "Palīdzība un atsauksmes" + "Izvēlne" diff --git a/packages/SettingsLib/res/values-mk-rMK/arrays.xml b/packages/SettingsLib/res/values-mk-rMK/arrays.xml index 7a1c320b68c93d72a4fd81ccc9b52601b38e252e..a72bcd3ad98be2244583a52eb846c0a98b5782a7 100644 --- a/packages/SettingsLib/res/values-mk-rMK/arrays.xml +++ b/packages/SettingsLib/res/values-mk-rMK/arrays.xml @@ -84,11 +84,13 @@ "Исклучено" "Сите" "Сите освен радио" + "само јадро" "Исклучено" "Привремена меморија на целата евиденција" "Привремена мем. на цела евиденција освен за радио" + "само привремена меморија за евиденција на јадро" "Без анимација" diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml index 3d4307d78a77d948f70100b93311539f3c1385a8..725a39d0a3625eea54a34ae621993b590b3194be 100644 --- a/packages/SettingsLib/res/values-mk-rMK/strings.xml +++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml @@ -28,7 +28,8 @@ "Поврзувањето преку Wi-Fi не успеа" "Проблем со автентикација" "Надвор од опсег" - "Не е откриен пристап до интернет, нема автоматски повторно да се поврзете." + "Не е откриен пристап до Интернет, нема автоматски повторно да се поврзете." + "Нема пристап до Интернет." "Зачувано од %1$s" "Поврзано преку помошник за Wi-Fismile" "Поврзано преку %1$s" @@ -184,7 +185,6 @@ "Овозможи лажни локации" "Овозможи лажни локации" "Овозможете проверка на атрибутот на приказот" - "Користете го клиентот на DHCP од Lollipop наместо новиот клиент на DHCP на Android." "Секогаш држи го активен мобилниот интернет, дури и при активно Wi-Fi (за брзо префрлување мрежа)." "Овозможи отстранување грешки на УСБ?" "Отстранувањето грешки на УСБ е наменето само за целите на развој. Користете го за копирање податоци меѓу вашиот компјутер и вашиот уред, за инсталирање апликации на вашиот уред без известување и за читање евиденција на податоци." @@ -234,8 +234,6 @@ "Прикажи граници на клип, маргини, итн." "Сила на RTL за насока на слој" "Присилно постави насока на распоред на екран во РТЛ за сите локални стандарди" - "Прикажи употреба на ЦПУ" - "Прекривка на екран прикаж. употреба на тековен ЦПУ" "Присили рендерирање на GPU" "Присилно користење на GPU за цртеж 2D" "Сила 4x MSAA" @@ -342,4 +340,5 @@ "Најголем" "Приспособен (%d)" "Помош и повратни информации" + "Мени" diff --git a/packages/SettingsLib/res/values-ml-rIN/arrays.xml b/packages/SettingsLib/res/values-ml-rIN/arrays.xml index ff0652f2e607478363893baff3b3eae8fe7be014..ac6841eb74fe09c3cb07cb1e5cbbbf81ad6dc738 100644 --- a/packages/SettingsLib/res/values-ml-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-ml-rIN/arrays.xml @@ -84,11 +84,13 @@ "ഓഫ്" "എല്ലാം" "റേഡിയോ ഒഴികെയുള്ള എല്ലാം" + "കേർനൽ മാത്രം" "ഓഫ്" "എല്ലാ ലോഗ് ബഫറുകളും" "റേഡിയോ ലോഗ് ബഫറുകൾ ഒഴികെയുള്ള എല്ലാം" + "കേർനൽ ലോഗ് ബഫർ മാത്രം" "ആനിമേഷൻ ഓഫുചെയ്യുക" diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml index 71262386497d96afe2a012fa862a008ae91eedbd..01565acd2cebfb4a38b6547ef6723a2f820779c9 100644 --- a/packages/SettingsLib/res/values-ml-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml @@ -28,7 +28,8 @@ "WiFi കണക്ഷൻ പരാജയം" "ആധികാരികമാക്കുന്നതിലെ പ്രശ്‌നം" "പരിധിയിലില്ല" - "ഇന്റർനെറ്റ് ആക്സസ്സൊന്നും കണ്ടെത്താത്തതിനാൽ സ്വയം വീണ്ടും കണക്‌റ്റുചെയ്യില്ല." + "ഇന്റർനെറ്റ് ആക്സസ്സൊന്നും കണ്ടെത്താത്തതിനാൽ സ്വയം വീണ്ടും കണക്‌റ്റുചെയ്യില്ല." + "ഇന്റർനെറ്റ് ആക്‌സസ്സ് ഇല്ല." "%1$s സംരക്ഷിച്ചത്" "വൈഫൈ അസിസ്റ്റന്റ് മുഖേന കണക്‌റ്റുചെയ്തു" "%1$s വഴി ബന്ധിപ്പിച്ചു" @@ -184,7 +185,6 @@ "വ്യാജ ലൊക്കേഷനുകൾ അനുവദിക്കുക" "വ്യാജ ലൊക്കേഷനുകൾ അനുവദിക്കുക" "ആട്രിബ്യൂട്ട് പരിശോധന കാണൽ സജീവമാക്കൂ" - "പുതിയ Android DHCP ക്ലയന്റിനുപകരം Lollipop-ൽ നിന്ന് DHCP ക്ലയന്റ് ഉപയോഗിക്കുക." "വൈഫൈ സജീവമാണെങ്കിലും, മൊബൈൽ ഡാറ്റ സജീവമായി നിർത്തുക (വേഗത്തിൽ നെറ്റ്‌വർക്ക് മാറുന്നതിനായി)." "USB ഡീബഗ്ഗുചെയ്യാൻ അനുവദിക്കണോ?" "USB ഡീബഗ്ഗിംഗ് വികസന ആവശ്യകതകൾക്ക് മാത്രമുള്ളതാണ്. നിങ്ങളുടെ കമ്പ്യൂട്ടറിനും ഉപകരണത്തിനുമിടയിൽ ഡാറ്റ പകർത്തുന്നതിനും അറിയിപ്പില്ലാതെ തന്നെ നിങ്ങളുടെ ഉപകരണത്തിൽ അപ്ലിക്കേഷനുകൾ ഇൻസ്‌റ്റാളുചെയ്യുന്നതിനും ലോഗ് ഡാറ്റ റീഡുചെയ്യുന്നതിനും ഇത് ഉപയോഗിക്കുക." @@ -234,8 +234,6 @@ "ക്ലിപ്പ് ബൗണ്ടുകൾ, മാർജിനുകൾ തുടങ്ങിയവ ദൃശ്യമാക്കുക" "RTL ലേഔട്ട് ഡയറക്ഷൻ നിർബന്ധമാക്കുക" "എല്ലാ ഭാഷകൾക്കുമായി സ്‌ക്രീൻ ലേഔട്ട് ഡയറക്ഷൻ RTL-ലേക്ക് നിർബന്ധമാക്കുക" - "CPU ഉപയോഗം ദൃശ്യമാക്കുക" - "സ്ക്രീൻ ഓവർലേ നിലവിലെ CPU ഉപയോഗം ദൃശ്യമാക്കുന്നു" "GPU റെൻഡറിംഗ് ഫോഴ്സ്ചെയ്യുക" "2d ഡ്രോയിംഗിനായുള്ള നിരബന്ധിത GPU ഉപയോഗം" "4x MSAA നിർബന്ധമാക്കുക" @@ -342,4 +340,5 @@ "ഏറ്റവും വലുത്" "ഇഷ്ടാനുസൃതം ( %d )" "സഹായവും പ്രതികരണവും" + "മെനു" diff --git a/packages/SettingsLib/res/values-mn-rMN/arrays.xml b/packages/SettingsLib/res/values-mn-rMN/arrays.xml index f7c81bc828d8643d2140fd8dc3831bfd8fd9d4fe..e812043b975bfdc5a9f2665e4e8178828cd13a80 100644 --- a/packages/SettingsLib/res/values-mn-rMN/arrays.xml +++ b/packages/SettingsLib/res/values-mn-rMN/arrays.xml @@ -84,11 +84,13 @@ "Идэвхгүй" "Бүгд" "Радиогоос бусад бүх" + "зөвхөн төвд" "Идэвхгүй" "Бүх логийн хамгаалалт" "Радиогоос бусад бүх логийн хамгаалалт" + "зөвхөн үйлдлийн системийн төв логийн хамгаалалтад" "Дүрс амилуулалт идэвхгүй" diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml index f8497d3afd5260fde91559bac4802da0950cc655..5121f4460ac35748517baaaad0d9066de037a8e3 100644 --- a/packages/SettingsLib/res/values-mn-rMN/strings.xml +++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml @@ -28,7 +28,8 @@ "WiFi холболт амжилтгүй" "Гэрчлэлийн асуудал" "Хүрээнд байхгүй" - "Интернэт холболт илэрсэнгүй, автоматаар дахин холболт хийгдэхгүй" + "Интернэт хандалт олдсонгүй тул автоматаар дахин холбогдохгүй." + "Интернэт хандалт алга" "%1$s хадгалсан" "Wi-Fi туслагчаар дамжуулан холбогдлоо" "%1$s-р холбогдсон" @@ -184,7 +185,6 @@ "Хуурамч байршлыг зөвшөөрөх" "Хуурамч байршлыг зөвшөөрөх" "Харах тохируулгын шалгалтыг идэвхжүүлэх" - "Шинэ Андройд DHCP харилцагчийн оронд Lollipop-ийн DHCP харилцагчийг хэрэглэ." "Wi‑Fi идэвхтэй байхад ч гэсэн гар утасны датаг идэвхтэй байлгадаг (сүлжээг түргэн солихын тулд)." "USB дебаг хийхийг зөвшөөрөх үү?" "USB дебаг нь зөвхөн хөгжүүлэлтийн зорилготой. Үүнийг өөрийн компьютер болон төхөөрөмжийн хооронд өгөгдөл хуулах, өөрийн төхөөрөмж дээр мэдэгдэлгүйгээр аппликешн суулгах, лог датаг унших зэрэгт ашиглаж болно." @@ -234,8 +234,6 @@ "Клипийн зах, хязгаар зэргийг харуулах" "RTL байрлалын чиглэлийг хүчээр тогтоох" "Бүх локалын хувьд дэлгэцийн байрлалын чиглэлийг хүчээр RTL болгох" - "CPU ашиглалтыг харуулах" - "Дэлгэцийн давхцалаар одоогийн CPU ашиглалтыг харуулж байна" "Хүчээр GPU ашиглах" "GPU-г 2d зурагт хүчээр ашиглах" "Хүчээр 4x MSAA ашиглах" @@ -342,4 +340,5 @@ "Хамгийн том" "Тогтмол утга (%d)" "Тусламж, санал хүсэлт" + "Цэс" diff --git a/packages/SettingsLib/res/values-mr-rIN/arrays.xml b/packages/SettingsLib/res/values-mr-rIN/arrays.xml index 956539c74437ecfd4b4bdcfab62b7d16bc4384fe..5de2f4976ae9d3fe944d51eab6b0efa7fe2a2e64 100644 --- a/packages/SettingsLib/res/values-mr-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-mr-rIN/arrays.xml @@ -84,11 +84,13 @@ "बंद" "सर्व" "सर्व परंतु रेडिओ" + "फक्त कर्नेल" "बंद" "सर्व लॉग बफर" "सर्व परंतु रेडिओ लॉग बफर" + "फक्त कर्नेल लॉग बफर" "अॅनिमेशन बंद" diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml index 3dee8182153755377dcb600f5c40a86a4d2c888b..5ee18d54dc0961c82a2d2081d9dae2a8707aade6 100644 --- a/packages/SettingsLib/res/values-mr-rIN/strings.xml +++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml @@ -28,7 +28,8 @@ "WiFi कनेक्शन अयशस्वी" "प्रमाणीकरण समस्या" "परिक्षेत्रामध्ये नाही" - "कोणताही इंटरनेट प्रवेश आढळला नाही, स्वयंचलितपणे रीकनेक्ट करणार नाही." + "कोणताही इंटरनेट प्रवेश आढळला नाही, स्वयंचलितपणे पुन्हा कनेक्ट करणार नाही." + "इंटरनेट प्रवेश नाही." "%1$s द्वारे जतन केले" "Wi‑Fi सहाय्यक द्वारे कनेक्ट केले" "%1$s द्वारे कनेक्‍ट केले" @@ -184,7 +185,6 @@ "बनावट स्थानांना अनुमती द्या" "बनावट स्थानांना अनुमती द्या" "दृश्‍य विशेषता तपासणी सक्षम करा" - "नवीन Android DHCP क्लायंट ऐवजी Lollipop वरून DHCP क्लायंटचा वापर करा." "जरी वाय-फाय सक्रिय असले तरीही, नेहमी मोबाईल डेटा सक्रिय ठेवा (जलद नेटवर्क स्विच करण्यासाठी)." "USB डीबग करण्यास अनुमती द्यायची?" "USB डीबग करण्याचा हेतू फक्त विकासाच्या उद्देशांसाठी आहे. याचा वापर आपला संगणक आणि आपले डिव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय आपल्या डिव्हाइसवर अॅप्स स्थापित करा आणि लॉग डेटा वाचा." @@ -234,8 +234,6 @@ "क्लिप सीमा, समास इत्यादी दर्शवा." "RTL लेआउट दिशानिर्देशाची सक्ती करा" "सर्व लोकॅलसाठी RTL स्क्रीन लेआउट दिशानिर्देशाची सक्ती करा" - "CPU वापर दर्शवा" - "वर्तमान CPU वापर दर्शविणारे स्क्रीन आच्छादन" "GPU प्रस्तुतीस सक्ती करा" "2d रेखांकनासाठी GPU च्या वापराची सक्ती करा" "4x MSAA ची सक्ती करा" @@ -342,4 +340,5 @@ "सर्वात मोठा" "सानुकूल करा (%d)" "मदत आणि अभिप्राय" + "मेनू" diff --git a/packages/SettingsLib/res/values-ms-rMY/arrays.xml b/packages/SettingsLib/res/values-ms-rMY/arrays.xml index 245af94b5075cad310ed7ff612ea0932103ff019..d6ea50ccc195240b1c61cc231ce474bb422bdd13 100644 --- a/packages/SettingsLib/res/values-ms-rMY/arrays.xml +++ b/packages/SettingsLib/res/values-ms-rMY/arrays.xml @@ -84,11 +84,13 @@ "Mati" "Semua" "Sma kcli radio" + "inti sahaja" "Mati" "Semua penimbal log" "Semua kecuali penimbal log radio" + "penimbal log inti sahaja" "Animasi dimatikan" diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml index 46bbe6360b295dd3459162a91c3059a978f31a04..fabfd637c6ed09949bee684529ab7e7735d03cbe 100644 --- a/packages/SettingsLib/res/values-ms-rMY/strings.xml +++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml @@ -28,7 +28,8 @@ "Kegagalan Sambungan WiFi" "Masalah pengesahan" "Tidak dalam liputan" - "Tiada Akses Internet Dikesan, tidak akan menyambung secara automatik." + "Tiada Akses Internet Dikesan, tidak akan menyambung secara automatik." + "Tiada Akses Internet." "Diselamatkan oleh %1$s" "Disambungkan melalui Pembantu Wi-Fi" "Disambungkan melalui %1$s" @@ -184,7 +185,6 @@ "Benarkan lokasi olokan" "Benarkan lokasi olokan" "Dayakan pemeriksaan atribut paparan" - "Gunakan pelanggan DHCP daripada Lollipop bukannya pelanggan DHCP Android baharu." "Pastikan data mudah alih sentiasa aktif, walaupun Wi-Fi aktif (untuk penukaran rangkaian yang pantas)." "Benarkan penyahpepijatan USB?" "Penyahpepijatan USB adalah dimaksudkan untuk tujuan pembangunan sahaja. Gunakannya untuk menyalin data antara komputer dan peranti anda, memasang aplikasi pada peranti anda tanpa pemberitahuan, dan membaca data log." @@ -234,8 +234,6 @@ "Tunjukkan batas klip, margin dll." "Paksa arah reka letak RTL" "Paksa arah reka letak skrin RTL bagi semua tempat peristiwa" - "Tunjukkan penggunaan CPU" - "Tindihan skrin menunjukkan penggunaan semasa CPU" "Paksa pemaparan GPU" "Paksa penggunaan GPU untuk lukisan 2d" "Paksa 4x MSAA" @@ -342,4 +340,5 @@ "Terbesar" "Tersuai (%d)" "Bantuan & maklum balas" + "Menu" diff --git a/packages/SettingsLib/res/values-my-rMM/arrays.xml b/packages/SettingsLib/res/values-my-rMM/arrays.xml index 14981b6076710ff878590e30e39d61561772f23a..7ba8e9495ab0c789e72924f046a8ca5f7a5d896d 100644 --- a/packages/SettingsLib/res/values-my-rMM/arrays.xml +++ b/packages/SettingsLib/res/values-my-rMM/arrays.xml @@ -49,12 +49,12 @@ "နှေးကွေးသောဆက်သွယ်မှုကို ယာယီရှောင်ရှားထားသည်" - "မည်သည့်အခါမှ မစစ်ဆေးပါနှင့်" + "ဘယ်တော့မှ မစစ်ဆေးပါနှင့်" "DRMအကြောင်းအရာကိုသာ စစ်ဆေးမည်" "အမြဲစစ်ဆေးရန်" - "HDCP checkingအားမည်သည့်အခါမျှမသုံးပါနှင့်" + "HDCP checking အား ဘယ်တော့မှ မသုံးပါနှင့်" "DRMအကြောင်းအရာအတွက် HDCPစစ်ဆေးခြင်းကိုသုံးမည်" "HDCP checkingအားအမြဲသုံးပါ" @@ -84,11 +84,13 @@ "ပိတ်ပါ" "အားလုံး" "ရေဒီယိုမှလွဲ၍ အားလုံး" + "ကာနယ်သာ" "ပိတ်ပါ" "မှတ်တမ်းသိမ်းဆည်းရန် လျာထားချက်များ အားလုံး" "ရေဒီယို မှတ်တမ်းသိမ်းဆည်းရန်လျာထားချက်မှလွဲ၍ အားလုံး" + "ကာနယ်မှတ်တမ်းသိမ်းဆည်းရန် လျာထားချက်သာ" "လှုပ်ရှားသက်ဝင်မှုပုံများကိုပိတ်ပါ" diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml index 06105055ff6d842dadedc6439d150d6703edee54..571a93133677129be29ca969486b7d25797b2e7a 100644 --- a/packages/SettingsLib/res/values-my-rMM/strings.xml +++ b/packages/SettingsLib/res/values-my-rMM/strings.xml @@ -28,7 +28,8 @@ "WiFi ချိတ်ဆက်မှု မအောင်မြင်ပါ" "စစ်မှန်ကြောင်းအတည်ပြုရန်၌ ပြသနာရှိခြင်း" "စက်ကွင်းထဲတွင် မဟုတ်ပါ" - "မည်သည့် အင်တာနက်မျှမရှိပါ၊ အလိုအလျောက် ပြန်လည်မချိတ်ဆက်ပါ။" + "အင်တာနက်ချိတ်ဆက်မှု ရှာမတွေ့ပါ၊ အလိုအလျောက် ပြန်လည်ချိတ်ဆက်မည် မဟုတ်ပါ။" + "အင်တာနက် ချိတ်ဆက်မှု မရှိပါ။" "%1$s မှသိမ်းဆည်းခဲ့သည်" "ကြိုးမဲ့ကူညီသူမှတဆင့် ချိတ်ဆက်၏" "%1$s မှတစ်ဆင့် ချိတ်ဆက်ထားသည်" @@ -71,7 +72,7 @@ "ထည့်သွင်းရန်အသုံးပြုသည်" "အတူတွဲပါ" "ချိတ်တွဲရန်" - "မလုပ်တော့ပါ" + "မလုပ်တော့" "ချိတ်တွဲမှုက ချိတ်ဆက်ထားလျှင် သင်၏ အဆက်အသွယ်များ နှင့် ခေါ်ဆိုမှု မှတ်တမ်းကို ရယူခွင့် ပြုသည်။" "%1$sနှင့် တွဲချိတ်မရပါ" "ပင်နံပါတ် သို့မဟုတ် ဖြတ်သန်းခွင့်ကီးမမှန်ကန်သောကြောင့်%1$sနှင့် တွဲချိတ်မရပါ။" @@ -159,8 +160,8 @@ "အစပြုခြင်းကိရိယာအား သော့ဖွင့်ရန် ခွင့်ပြုမည်" "OEM သော့ဖွင့်ခြင်း ခွင့်ပြုမလား?" "သတိပေးချက်: ဤချိန်ညှိချက်ဖွင့်ထားလျှင်၊ ဤစက်ပစ္စည်းပေါ်တွင် စက်ပစ္စည်းကာကွယ်သည့် အထူးပြုလုပ်ချက် အလုပ်လုပ်မည်မဟုတ်ပါ။" - "တည်နေရာအတုပြု အက်ပ် ရွေးရန်" - "တည်နေရာအတုပြ အက်ပ် သတ်မှတ်ထားခြင်းမရှိပါ" + "တည်နေရာအတုပြု အက်ပ်ရွေးရန်" + "တည်နေရာအတုပြ အက်ပ်သတ်မှတ်ထားခြင်းမရှိပါ" "တည်နေရာအတုပြ အက်ပ်- %1$s" "ကွန်ရက်လုပ်ငန်း" "ကြိုးမဲ့ပြသမှု အသိအမှတ်ပြုလက်မှတ်" @@ -184,7 +185,6 @@ "ပုံစံတုတည်နေရာများကို ခွင့်ပြုရန်" "ပုံစံတုတည်နေရာများကို ခွင့်ပြုရန်" "အရည်အချင်းများ စူးစမ်းမှု မြင်ကွင်းကို ဖွင့်ပေးရန်" - "Android DHCP ကလိုင်းယင့် အသစ် အစား Lollipop မှ DHCP ကလိုင်းယင့်အား သုံးပါ။" "ဝိုင်ဖိုင်ဖွင့်ထားလျှင်တောင် မိုဘိုင်းဒေတာအမြဲတမ်းဖွင့်မည် (မြန်ဆန်သည့် ကွန်ရက် ပြောင်းခြင်းအတွက်)။" "USB ပြသနာရှာခြင်း ခွင့်ပြုပါမလား?" "USBအမှားရှားခြင်းမှာ ဆော့ဝဲလ်ရေးသားရန်အတွက်သာ ရည်ရွယ်ပါသည်။ သင့်ကွန်ပြုတာနှင့်သင့်စက်ကြားတွင် ဒေတာများကိုကူးယူရန်၊ အကြောင်းမကြားပဲနှင့် သင့်စက်အတွင်းသို့ အပလီကေးရှင်းများထည့်သွင်းခြင်းနှင့် ဒေတာမှတ်တမ်းများဖတ်ရန်အတွက် အသုံးပြုပါ" @@ -205,7 +205,7 @@ "အပလီကေးရှင်းရွေးချယ်ရန်" "တခုမှမရှိ" "အပြစ်ရှာဖွေ ဖယ်ရှားချက်ကိုစောင့်ရန်" - "အမှားပြင်ဆင်ရှာဖွေသည့် အပလီကေးရှင်းသည် လုပ်ငန်းမစမှီ တွဲဖက်ရန် အမှားရှာဖွေမည့်သူကို စောင့်နေသည်။" + "အမှားပြင်ဆင်ရှာဖွေသည့် အပလီကေးရှင်းသည် လုပ်ငန်းမစမီ တွဲဖက်ရန် အမှားရှာဖွေမည့်သူကို စောင့်နေသည်။" "ထည့်သွင်းရန်" "ရေးဆွဲခြင်း" "ဟာ့ဒ်ဝဲ အရှိန်မြှင့် ပုံဖော်ခြင်း" @@ -218,11 +218,11 @@ "တို့ခြင်းများကို ပြပါ" "တို့ခြင်းများအတွက် အမြင်ဖြင့် တုံ့ပြန်မှုပြပါ" "surface အဆင့်မြှင့်မှုများပြပါ" - "အဆင့်မြှင့်နေစဉ် ဝင်းဒိုးမျက်နှာတပြင်လုံးကို အချက်ပြရန်" + "အပ်ဒိတ်လုပ်စဉ် ဝင်းဒိုးမျက်နှာပြင်တွင် အချက်ပြရန်" "GPUမြင်ကွင်းအဆင့်မြှင့်ခြင်းများပြရန်" "GPU နှင့်ဆွဲစဉ် ၀င်းဒိုးအတွင်းပိုင်း လျှပ်တပြက်မြင်ကွင်းများ" "ဟာ့ဒ်ဝဲအလွှာများအဆင်မြှင့်မှုကိုပြရန်" - "အဆင့်မြှင်ချိန် ဟာ့ဒ်ဝဲအလွှာများကို အစိမ်းရောင်ဖြင့်အချက်ပြရန်" + "အပ်ဒိတ်လုပ်ချိန် ဟာ့ဒ်ဝဲအလွှာများ အစိမ်းရောင်ပြပါ" "GPU ပိုသုံးစွဲမှုအမှားရှာဖွေပြင်ဆင်ရန်" "HWထပ်ဆင့်အရာများပိတ်ရန်" "GPU ကိုမျက်နှာပြင်ခင်းကျင်းရာတွင် အမြဲသုံးပါ။" @@ -234,8 +234,6 @@ "ဖြတ်ပိုင်းအနားသတ်များ၊ အနားများ စသဖြင့် ပြပါ။" "RTL ဖွဲ့စည်းပုံအညွှန်း မဖြစ်မနေလုပ်ပါ" "လိုကယ်လ်အားလုံးအတွက် မျက်နှာပြင် ဖွဲ့စည်းပုံအညွှန်း မဖြစ်မနေလုပ်ရန်" - "CPUအသုံးပြုမှုအား ပြသရန်" - "လက်ရှိCPUအသုံးပြုမှုအားလုံး မျက်နှာပြင်တွင်ပြသမှု" "GPUအား အတင်းအကျပ်ဖြစ်စေမည်" "GPUကို ၂ဖက်မြင်ပုံဆွဲခြင်းအတွက် မဖြစ်မနေအသုံးပြုစေရန်" "တွန်းအား ၄× MSAA" @@ -246,7 +244,7 @@ "သက်ဝင်အသွင်ပြောင်းခြင်း" "လှုပ်ရှားမှုကြာချိန်စကေး" "ဆင့်ပွားမျက်နှာပြင်များအသွင်ဆောင်သည်" - "အပလီကေးရှင်းများ" + "အက်ပ်များ" "ဆောင်ရွက်မှုများကို မသိမ်းထားပါနှင့်" "အသုံးပြုသူထွက်ခွါသွားသည်နှင့် လုပ်ဆောင်ချက်များကို ဖျက်ပစ်မည်" "နောက်ခံလုပ်ငန်းစဉ်ကန့်သတ်ခြင်း" @@ -274,7 +272,7 @@ "မျက်လုံးမှတွေ့ရသည့် သဘာဝအရောင်" "ဒီဂျစ်တယ်အကြောင်းအရာအတွက် ပြင်ဆင်ထားသည့် အရောင်များ" - "အလုပ်မလုပ်သော အက်ပ် များ" + "အလုပ်မလုပ်သော အက်ပ်များ" "ပွင့်မနေပါ။ ပြောင်းရန်တို့ပါ။" "ပွင့်နေသည်။ ပြောင်းရန်တို့ပါ။" "အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ" @@ -288,7 +286,7 @@ "ပြောင်းရန်…" "ဖိုင်ကို လုံခြုံအောင်ပြုလုပ်ပြီးပါပြီ" "ဖိုင်အခြေပြုလုံခြုံအောင်ပြုလုပ်ခြင်းသို့ ပြောင်းလဲရန်" - "အချက်အလက်အပိုင်းကို ဖိုင်အခြေပြုလုံခြုံအောင်ပြုလုပ်ခြင်းသို့ ပြောင်းပါ။\n !!သတိ!! ၎င်းသည်သင့် အချက်အလက်များအားလုံးကို ဖျက်ပါမည်။ \n ဤလုပ်ဆောင်ချက်သည် ပထမအဆင့်တွင်သာ ရှိသေးပြီး မှန်ကန်စွာ လုပ်ဆောင်လိမ့်မည် မဟုတ်ပါ။\n ရှေ့ဆက်ရန် \'ရှင်းလင်းပြီး ပြောင်းလဲရန်…\' ကိုနှိပ်ပါ။" + "အချက်အလက်အပိုင်းကို ဖိုင်အခြေပြုလုံခြုံအောင်ပြုလုပ်ခြင်းသို့ ပြောင်းပါ။\n !!သတိ!! ၎င်းသည်သင့် အချက်အလက်များအားလုံးကို ဖျက်ပါမည်။ \n ဤလုပ်ဆောင်ချက်သည် ပထမအဆင့်တွင်သာ ရှိသေးပြီး မှန်ကန်စွာ လုပ်ဆောင်လိမ့်မည် မဟုတ်ပါ။\n ဆက်လုပ်ရန် \'ရှင်းလင်းပြီး ပြောင်းလဲရန်…\' ကိုနှိပ်ပါ။" "ရှင်းလင်းပြီး ပြောင်းလဲရန်…" "ဓာတ်ပုံအရောင်မုဒ်" "sRGB ကို အသုံးပြုပါ" @@ -342,4 +340,5 @@ "အကြီးဆုံး" "စိတ်ကြိုက် (%d)" "အကူအညီနှင့် အကြံပြုချက်" + "မီနူး" diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml index 45fcb87c55407b93b8d322d3ae0d358c709d7613..bc4ff27d85e8647f56a0073a69eb502b7c14718c 100644 --- a/packages/SettingsLib/res/values-nb/arrays.xml +++ b/packages/SettingsLib/res/values-nb/arrays.xml @@ -84,11 +84,13 @@ "Av" "Alle" "Unntatt radio" + "bare kjerne" "Av" "Alle loggbuffere" "Alle unntatt radiologgbuffere" + "bare kjerneloggbuffer" "Animasjon av" diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index d3fcdd25cd04d5404f6e5635d14963da99f6ac79..834c849a227f7fcc5d0bc26c003bcb2f0eff03f0 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi-tilkoblingsfeil" "Autentiseringsproblem" "Utenfor område" - "Ingen Internett-tilgang ble funnet. Kan ikke koble til på nytt automatisk." + "Fant ingen Internett-tilgang. Kan ikke automatisk koble til på nytt." + "Ingen Internett-tilgang." "Lagret av %1$s" "Koblet til via en Wi-Fi-assistent" "Tilkoblet via %1$s" @@ -184,7 +185,6 @@ "Tillat simulert posisjon" "Tillat bruk av simulerte GPS-koordinater" "Slå på inspeksjon av visningsattributt" - "Bruk DHCP-klienten fra Lollipop i stedet for den nye DHCP-klienten for Android." "Ha alltid mobildata slått på, selv når Wi-Fi er aktiv (for hurtig nettverksbytting)." "Tillate USB-feilsøking?" "USB-feilsøking er bare ment for utviklingsformål. Bruk det til å kopiere data mellom datamaskinen og enheten, installere apper på enheten uten varsel og lese loggdata." @@ -234,8 +234,6 @@ "Vis kanter, marger osv." "Tving layoutretning for RTL" "Tving RTL-retning på skjermen for alle språk" - "Vis CPU-bruk" - "Skjermoverlegg viser gjeldende CPU-bruk" "Tving GPU-gjengivelse" "Tving bruk av GPU for 2D-tegning" "Tving 4x MSAA" @@ -342,4 +340,5 @@ "Størst" "Egendefinert (%d)" "Hjelp og tilbakemelding" + "Meny" diff --git a/packages/SettingsLib/res/values-ne-rNP/arrays.xml b/packages/SettingsLib/res/values-ne-rNP/arrays.xml index 39b32d999798169915d3d1bd06a6b75bee176a5e..2063f17cc8f61e79cca56e95b436b6b2e1925db3 100644 --- a/packages/SettingsLib/res/values-ne-rNP/arrays.xml +++ b/packages/SettingsLib/res/values-ne-rNP/arrays.xml @@ -84,11 +84,13 @@ "निष्क्रिय" "सबै" "रेडियो बाहेक सबै" + "कर्नेल मात्र" "निष्क्रिय" "सबै लग सम्बन्धी बफरहरू" "रेडियो सम्बन्धी लगका बफरहरू बाहेक सबै" + "कर्नेलको लग सम्बन्धी बफर मात्र" "सजीविकरण बन्द" diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml index 3e53d1ec48ab341d72871dc6c66091208d9ac64a..01b39a0308fb90a8a168251cc56c089c1c23e083 100644 --- a/packages/SettingsLib/res/values-ne-rNP/strings.xml +++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml @@ -28,7 +28,8 @@ "वाईफाई जडान असफल" "प्रमाणीकरण समस्या" "दायराभित्र छैन" - "कुनै इन्टरनेट पहुँच पाईएन, स्वचालित रूपमा पुन: जडान छैन।" + "इन्टरनेट माथिको पहुँच पत्ता लागेन, स्वतः पुनः जडान हुने छैन।" + "इन्टरनेट माथिको पहुँच छैन।" "%1$s द्वारा सुरक्षित गरियो" "Wi-Fi सहायक द्वारा जोडिएको" "%1$s मार्फत जडित" @@ -184,7 +185,6 @@ "नक्कली स्थानहरूलाई अनुमति दिनुहोस्" "नक्कली स्थानहरूलाई अनुमति दिनुहोस्" "दृष्टिकोण विशेषता निरीक्षण सक्षम पार्नुहोस्" - "नयाँ Android DHCP ग्राहकको सट्टा Lollipop बाट DHCP ग्राहक प्रयोग गर्नुहोस्।" "Wi-Fi सक्रिय हुँदा पनि मोबाइल डेटा सधैँ सक्रिय राख्नुहोस् (द्रूत नेटवर्क स्विच गर्नको लागि)।" "USB डिबग गर्न लागि अनुमति दिने हो?" "युएसबी डिबगिङ विकास प्रयोजनका लागि मात्र निर्मित हुन्छ। यसलाई तपाईँको कम्प्युटर र तपाईँको उपकरणका बीच डेटा प्रतिलिपि गर्न, बिना सूचना तपाईँको उपकरणमा अनुप्रयोगहरू स्थापना गर्न र लग डेटा पढ्नका लागि प्रयोग गर्नुहोस्।" @@ -234,8 +234,6 @@ "क्लिप सीमा, मार्जिन, इत्यादि देखाउनुहोस्।" "RTL लेआउट दिशामा जबर्जस्ती गर्नुहोस्" "सबै लोकेलहरूको लागि RTLमा स्क्रिन लेआउट दिशामा जबर्जस्ती गर्नुहोस्" - "CPU उपयोग देखाउनुहोस्" - "स्क्रिन ओभरले वर्तमान CPU प्रयोग देखाउँदै" "GPU रेन्डर गर्न जोड गर्नुहोस्" "2d चित्र कोर्नका लागि GPU को प्रयोगलाई जोड दिनुहोस्" "4x MSAA जोड गर्नुहोस्" @@ -342,4 +340,5 @@ "सबैभन्दा ठूलो" "अनुकूलन (%d)" "मद्दत र प्रतिक्रिया" + "मेनु" diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml index e4c19027fbb9284f85efe3dcb2e23750ce2752f4..d1903103cda3e1b4774b94e5527f6aeba16e20f9 100644 --- a/packages/SettingsLib/res/values-nl/arrays.xml +++ b/packages/SettingsLib/res/values-nl/arrays.xml @@ -50,12 +50,12 @@ "Nooit controleren" - "Alleen controleren op DRM-inhoud" + "Alleen controleren op DRM-content" "Altijd controleren" "HDCP-controle nooit gebruiken" - "HDCP-controle alleen voor DRM-inhoud gebruiken" + "HDCP-controle alleen voor DRM-content gebruiken" "HDCP-controle altijd gebruiken" @@ -84,11 +84,13 @@ "Uit" "Alle" "Alle beh. keuzerondje" + "alleen kernel" "Uit" "Alle logboekbuffers" "Alle logboekbuffers behalve voor keuzerondjes" + "alleen kernel-logbuffer" "Animatie uit" diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 411fc0aac1f1d53c1d8f04133d419fddb6b1c944..e4d2a6610c2834bfe0f7c3be6b0b6828d2a449cb 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -28,7 +28,8 @@ "Wifi-verbinding mislukt" "Authenticatieprobleem" "Niet binnen bereik" - "Geen internettoegang gevonden. Er wordt niet automatisch opnieuw verbinding gemaakt." + "Geen internettoegang gevonden. Er wordt niet automatisch opnieuw verbinding gemaakt." + "Geen internettoegang." "Opgeslagen door %1$s" "Verbonden via wifi-assistent" "Verbonden via %1$s" @@ -131,10 +132,10 @@ "Normaal" "Snel" "Sneller" - "Zeer snel" - "Vlug" - "Zeer vlug" - "Snelst" + "Nog sneller" + "Heel erg snel" + "Snelst" + "Allerallersnelst" "Profiel kiezen" "Persoonlijk" @@ -167,7 +168,7 @@ "Uitgebreide wifi-logregistratie insch." "Agressieve handover van wifi naar mobiel" "Altijd roamingscans voor wifi toestaan" - "Mobiele gegevens altijd actief" + "Mobiele data altijd actief" "Absoluut volume uitschakelen" "Opties weergeven voor certificering van draadloze weergave" "Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer" @@ -184,7 +185,6 @@ "Neplocaties toestaan" "Neplocaties toestaan" "Inspectie van weergavekenmerk inschakelen" - "De DHCP-client van Lollipop gebruiken in plaats van de nieuwe Android DHCP-client." "Mobiele gegevens altijd actief houden, ook als wifi actief is (voor sneller schakelen tussen netwerken)." "USB-foutopsporing toestaan?" "USB-foutopsporing is alleen bedoeld voor ontwikkeldoeleinden. Het kan worden gebruikt om gegevens te kopiëren tussen je computer en je apparaat, apps zonder melding op je apparaat te installeren en loggegevens te lezen." @@ -234,8 +234,6 @@ "Clipgrenzen, marges en meer weergeven" "V.r.n.l.-indelingsrichting afdwingen" "Schermindelingsrichting geforceerd instellen op v.r.n.l. voor alle talen" - "CPU-gebruik weergeven" - "Schermoverlay met huidig CPU-gebruik" "GPU-rendering afdwingen" "Gebruik van GPU voor 2D-tekening forceren" "4x MSAA forceren" @@ -342,4 +340,5 @@ "Grootst" "Aangepast (%d)" "Help en feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-pa-rIN/arrays.xml b/packages/SettingsLib/res/values-pa-rIN/arrays.xml index 1a035e7d621a35fbf2fd5e5ddad3c704edf97bbb..d0a26c8d40c43fade57a0ffa3679a9f7e789b87a 100644 --- a/packages/SettingsLib/res/values-pa-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-pa-rIN/arrays.xml @@ -84,11 +84,13 @@ "ਬੰਦ" "ਸਭ" "ਸਭ ਪਰ ਰੇਡੀਓ" + "ਸਿਰਫ਼ ਕਰਨਲ" "ਬੰਦ" "ਸਭ ਲੌਗ ਬਫ਼ਰ" "ਸਭ ਪਰ ਰੇਡੀਓ ਲੌਗ ਬਫ਼ਰ" + "ਸਿਰਫ਼ ਕਰਨਲ ਲੌਗ ਬਫ਼ਰ" "ਐਨੀਮੇਸ਼ਨ ਬੰਦ" diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml index 037d2c1cd5ed8958349529543b5e4cbc65c30ada..f21ee6df9385eb4152c735eb8e905722ef142230 100644 --- a/packages/SettingsLib/res/values-pa-rIN/strings.xml +++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml @@ -28,7 +28,8 @@ "WiFi ਕਨੈਕਸ਼ਨ ਅਸਫਲਤਾ" "ਪ੍ਰਮਾਣੀਕਰਨ ਸਮੱਸਿਆ" "ਰੇਂਜ ਵਿੱਚ ਨਹੀਂ ਹੈ" - "ਕੋਈ ਇੰਟਰਨੈਟ ਪਹੁੰਚ ਨਹੀਂ ਮਿਲੀ, ਆਟੋਮੈਟਿਕਲੀ ਰੀਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾਏਗਾ।" + "ਕੋਈ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਮਿਲੀ, ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਮੁੜ-ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।" + "ਕੋਈ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ।" "%1$s ਵੱਲੋਂ ਸੁਰੱਖਿਅਤ ਕੀਤਾ" "Wi‑Fi ਸਹਾਇਕ ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ" "%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ" @@ -184,7 +185,6 @@ "ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ" "ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ" "ਗੁਣ ਛਾਣਬੀਣ ਦੇਖੋ ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ" - "ਨਵੇਂ Android DHCP ਕਲਾਈਂਟ ਦੀ ਬਜਾਇ Lollipop ਦਾ DHCP ਕਲਾਈਂਟ ਵਰਤੋ।" "ਹਮੇਸ਼ਾ ਮੋਬਾਈਲ ਡੇਟਾ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਰੱਖੋ ਭਾਵੇਂ Wi‑Fi ਕਿਰਿਆਸ਼ੀਲ ਹੋਵੇ (ਤੇਜ਼ ਨੈੱਟਵਰਕ ਸਵਿੱਚਿੰਗ ਲਈ)।" "ਕੀ USB ਡੀਬਗਿੰਗ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?" "USB ਡੀਬਗਿੰਗ ਕੇਵਲ ਵਿਕਾਸ ਮੰਤਵਾਂ ਲਈ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੀ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡੈਟਾ ਕਾਪੀ ਕਰਨ ਲਈ ਵਰਤੋ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਡੀਵਾਈਸ ਤੇ ਐਪਸ ਇੰਸਟੌਲ ਕਰੋ ਅਤੇ ਲੌਗ ਡੈਟਾ ਪੜ੍ਹੋ।" @@ -234,8 +234,6 @@ "ਕਲਿਪ ਬਾਊਂਡਸ, ਮਾਰਜਿਨ ਆਦਿ ਦਿਖਾਓ" "RTL ਲੇਆਉਟ ਦਿਸ਼ਾ ਤੇ ਜ਼ੋਰ ਪਾਓ" "ਸਾਰੇ ਸਥਾਨਾਂ ਲਈ RTL ਵੱਲ ਸਕ੍ਰੀਨ ਲੇਆਉਟ ਦਿਸ਼ਾ ਤੇ ਜ਼ੋਰ ਪਾਓ" - "CPU ਵਰਤੋਂ ਦਿਖਾਓ" - "ਸਕ੍ਰੀਨ ਓਵਰਲੇ ਵਰਤਮਾਨ CPU ਵਰਤੋਂ ਦਿਖਾ ਰਿਹਾ ਹੈ" "GPU ਪ੍ਰਗਟਾਅ ਤੇ ਜ਼ੋਰ ਪਾਓ" "2d ਡ੍ਰਾਇੰਗ ਲਈ GPU ਦੀ ਵਰਤੋਂ ਤੇ ਜ਼ੋਰ ਪਾਓ" "4x MSAA ਤੇ ਜ਼ੋਰ ਪਾਓ" @@ -342,4 +340,5 @@ "ਸਭ ਤੋਂ ਵੱਡਾ" "ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ (%d)" "ਮਦਦ ਅਤੇ ਪ੍ਰਤੀਕਰਮ" + "ਮੀਨੂ" diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml index b12ea236239d8592390b2ed78e7d367c329e9996..ff36e42bdd9b62a76965174f749ce3296c3b17d0 100644 --- a/packages/SettingsLib/res/values-pl/arrays.xml +++ b/packages/SettingsLib/res/values-pl/arrays.xml @@ -84,11 +84,13 @@ "Wyłączone" "Wszystkie" "Bez radiowych" + "tylko jądro" "Wyłączone" "Wszystkie bufory dziennika" "Wszystkie oprócz buforów dzienników radiowych" + "tylko bufor dziennika jądra" "Animacja wyłączona" diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 0cf194e793d45bfb5db27c8fec0b5548c0de6598..bcdf81293e2d63facf5e35084999bcf4e738e1c2 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -28,7 +28,8 @@ "Błąd połączenia Wi-Fi" "Problem z uwierzytelnianiem" "Poza zasięgiem" - "Nie wykryto dostępu do internetu. Nie można automatycznie przywrócić połączenia." + "Nie wykryto dostępu do internetu. Nie można automatycznie przywrócić połączenia." + "Brak dostępu do internetu." "Zapisane przez: %1$s" "Połączono przez Asystenta Wi‑Fi" "Połączono przez %1$s" @@ -184,7 +185,6 @@ "Pozorowanie lokalizacji" "Zezwalaj na pozorowanie lokalizacji" "Inspekcja wyświetlania atrybutu" - "Użyj klienta DHCP z Lollipop zamiast nowego klienta DHCP Androida" "Nie wyłączaj transmisji danych przez sieć komórkową, nawet gdy aktywne jest połączenie Wi-Fi (aby szybko przełączać sieci)" "Czy zezwalać na debugowanie USB?" "Debugowanie USB jest przeznaczone wyłącznie do celów programistycznych. Może służyć do kopiowania danych między komputerem a urządzeniem, instalowania aplikacji na urządzeniu bez powiadamiania, a także odczytu danych dziennika." @@ -234,8 +234,6 @@ "Pokaż granice przycięcia, marginesy itd." "Układ od prawej do lewej" "Wymuś wszędzie układ ekranu od prawej do lewej" - "Pokaż użycie procesora" - "Nakładka na ekranie pokazująca użycie procesora" "Renderowanie na GPU" "Wymuszaj użycie GPU do rysowania 2D" "Wymuś 4x MSAA" @@ -342,4 +340,5 @@ "Największy" "Niestandardowe (%d)" "Pomoc i opinie" + "Menu" diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml index e39427deb7b4ad84653765149f6a767c73b1e16b..90f061c0f9b02a3070d2c380733063264770a80b 100644 --- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml @@ -84,11 +84,13 @@ "Desativado" "Todos" "Todos, exceto o rádio" + "somente kernel" "Desativado" "Todos os buffers de registro" "Todos, exceto os buffers de registro de rádio" + "somente buffer de registro de kernel" "Animação desligada" diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 4645821e44a682f22fea0485c7723c9454ad70c7..ef4ec778ee04aafefaca5f81a832acef16b0309d 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -28,7 +28,8 @@ "Falha de conexão Wi-Fi" "Problema de autenticação" "Fora do alcance" - "Nenhum acesso à Internet detectado. O dispositivo não conectará automaticamente." + "Nenhum acesso à Internet foi detectado. O dispositivo não será reconectado automaticamente." + "Sem acesso à Internet." "Salvas por %1$s" "Conectado via assistente de Wi‑Fi" "Conectado via %1$s" @@ -184,7 +185,6 @@ "Permitir locais fictícios" "Permitir locais fictícios" "Ativar visualiz. insp. atributo" - "Usar cliente DHCP do Lollipop, em vez do novo cliente DHCP do Android." "Sempre manter dados móveis ativos, mesmo quando o Wi-Fi estiver ativado (para troca rápida de rede)." "Permitir a depuração USB?" "A depuração USB serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro." @@ -234,8 +234,6 @@ "Mostrar limites de corte, margens, etc." "Forçar dir. layout (RTL)" "Forçar direção do layout (RTL) p/ todas as local." - "Mostrar o uso da CPU" - "Sobreposição de tela que mostra o uso da CPU atual" "Forçar renderização GPU" "Forçar uso da GPU para desenho em 2D" "Forçar 4x MSAA" @@ -342,4 +340,5 @@ "Maior" "Personalizada (%d)" "Ajuda e feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml index 92657e8daa09e16f282a4ff0c645e27b5e1a06e9..2c8b835838cfe7522861a54ecc35c798a3537e32 100644 --- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml @@ -84,11 +84,13 @@ "Desativado" "Todos" "Td, exc. rádio" + "apenas kernel" "Desativado" "Todos os buffers de registo" "Todos, exceto os buffers de registo de rádio" + "apenas buffer do registo do kernel" "Animação desativada" diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 9a2549e9bb36580ac9333537dfdb0fd5f34af914..b6e9b4f35a97f6feceb0681f2eafb6f3655722b8 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -28,7 +28,8 @@ "Falha de ligação Wi-Fi" "Problema de autenticação" "Fora do alcance" - "Nenhum acesso à Internet detetado; não será efetuada uma nova ligação automaticamente." + "Nenhum acesso à Internet detetado. Não será efetuada uma nova ligação automaticamente." + "Sem acesso à Internet." "Guardada por %1$s" "Ligado através do Assistente de Wi‑Fi" "Ligado através de %1$s" @@ -184,7 +185,6 @@ "Permitir locais fictícios" "Permitir locais fictícios" "Ativar a inspeção do atributo de visualização" - "Utilizar o cliente DHCP do Lollipop em vez do novo cliente DHCP do Android." "Manter sempre os dados móveis ativados, mesmo quando o Wi‑Fi estiver ativado (para mudança de rede rápida)" "Permitir depuração USB?" "A depuração USB é utilizada apenas para fins de programação. Utilize-a para copiar dados entre o computador e o aparelho, instalar aplicações no aparelho sem notificação e ler dados de registo." @@ -226,7 +226,7 @@ "Depurar sobreposição GPU" "Desativ. sobreposições HW" "Utilizar sempre GPU para a composição do ecrã" - "Simular espaço de cor" + "Simular espaço da cor" "Ativar vestígios OpenGL" "Desativ. encam. áudio USB" "Desativar encam. auto. para periféricos áudio USB" @@ -234,8 +234,6 @@ "Apresentar limites de clipes, margens, etc." "Forçar dir. do esq. RTL" "Forçar dir. do esq. do ecrã p. RTL tds os locais" - "Mostrar utilização da CPU" - "Sobrep. de ecrã que mostra a utiliz. atual da CPU" "Forçar composição GPU" "Forçar a utilização de GPU para desenho 2D" "Forçar 4x MSAA" @@ -342,4 +340,5 @@ "O maior" "Personalizado (%d)" "Ajuda e comentários" + "Menu" diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml index e39427deb7b4ad84653765149f6a767c73b1e16b..90f061c0f9b02a3070d2c380733063264770a80b 100644 --- a/packages/SettingsLib/res/values-pt/arrays.xml +++ b/packages/SettingsLib/res/values-pt/arrays.xml @@ -84,11 +84,13 @@ "Desativado" "Todos" "Todos, exceto o rádio" + "somente kernel" "Desativado" "Todos os buffers de registro" "Todos, exceto os buffers de registro de rádio" + "somente buffer de registro de kernel" "Animação desligada" diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 4645821e44a682f22fea0485c7723c9454ad70c7..ef4ec778ee04aafefaca5f81a832acef16b0309d 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -28,7 +28,8 @@ "Falha de conexão Wi-Fi" "Problema de autenticação" "Fora do alcance" - "Nenhum acesso à Internet detectado. O dispositivo não conectará automaticamente." + "Nenhum acesso à Internet foi detectado. O dispositivo não será reconectado automaticamente." + "Sem acesso à Internet." "Salvas por %1$s" "Conectado via assistente de Wi‑Fi" "Conectado via %1$s" @@ -184,7 +185,6 @@ "Permitir locais fictícios" "Permitir locais fictícios" "Ativar visualiz. insp. atributo" - "Usar cliente DHCP do Lollipop, em vez do novo cliente DHCP do Android." "Sempre manter dados móveis ativos, mesmo quando o Wi-Fi estiver ativado (para troca rápida de rede)." "Permitir a depuração USB?" "A depuração USB serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro." @@ -234,8 +234,6 @@ "Mostrar limites de corte, margens, etc." "Forçar dir. layout (RTL)" "Forçar direção do layout (RTL) p/ todas as local." - "Mostrar o uso da CPU" - "Sobreposição de tela que mostra o uso da CPU atual" "Forçar renderização GPU" "Forçar uso da GPU para desenho em 2D" "Forçar 4x MSAA" @@ -342,4 +340,5 @@ "Maior" "Personalizada (%d)" "Ajuda e feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml index 35d39bd144b78eca7ec1f0c9474babc0629e8d13..d5574dd226c0128cea4ba16cf5298dec84d1393e 100644 --- a/packages/SettingsLib/res/values-ro/arrays.xml +++ b/packages/SettingsLib/res/values-ro/arrays.xml @@ -84,11 +84,13 @@ "Dezactivată" "Toate" "Toate, fără radio" + "numai nucleul" "Dezactivată" "Toate zonele-tampon pentru jurnale" "Toate zonele-tampon pentru jurnale fără cele radio" + "numai zona-tampon pentru jurnalul nucleului" "Animație dezactivată" diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index be4bd2fc1e1b216bae34599d248a4792808c8ad2..a5ee78ae2c2cd8aa6fd03ac39a81f51953ec5145 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -28,7 +28,8 @@ "Eroare de conexiune Wi-Fi" "Problemă la autentificare" "În afara ariei de acoperire" - "Nu s-a detectat acces la internet, nu se va efectua reconectarea automată." + "Nu s-a detectat acces la internet, nu se va reconecta automat." + "Nu există acces la internet." "Salvată de %1$s" "Conexiune realizată printr-un asistent Wi-Fi" "Conectată prin %1$s" @@ -184,7 +185,6 @@ "Permiteți locațiile fictive" "Permiteți locațiile fictive" "Activați inspectarea atributelor de vizualizare" - "Folosiți clientul DHCP din Lollipop în locul noului client Android DHCP." "Păstrați întotdeauna conexiunea de date mobile activată, chiar și atunci când funcția Wi‑Fi este activată (pentru comutarea rapidă între rețele)." "Permiteți depanarea USB?" "Depanarea USB are exclusiv scopuri de dezvoltare. Utilizați-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale." @@ -234,8 +234,6 @@ "Afișați limitele clipului, marginile etc." "Direcție aspect dreapta - stânga" "Direcție obligatorie aspect ecran dreapta - stânga" - "Afișați utiliz. procesor" - "Suprapunere care indică utilizare curentă procesor" "Forțați redarea cu GPU" "Forțați utilizarea GPU pentru desen în 2D" "Forțați MSAA 4x" @@ -342,4 +340,5 @@ "Cel mai mare" "Personalizat (%d)" "Ajutor și feedback" + "Meniu" diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml index 48406e4f2457148fd6493c16e97587c7199fd9b3..2fff9ddf476c05ade9f3e6aaa2f98768cbd5a9db 100644 --- a/packages/SettingsLib/res/values-ru/arrays.xml +++ b/packages/SettingsLib/res/values-ru/arrays.xml @@ -84,11 +84,13 @@ "Отключено" "Все" "Все, кроме системных" + "только ядро" "Отключено" "Все буферы журналов" "Все, кроме буферов системного журнала" + "только буфер журнала ядра" "Без анимации" diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index b3e48be148efdad63a7ac8293576a619af172f09..b24a705ba106616293a9e2eb6e81678bf1bf65e7 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -28,13 +28,14 @@ "Ошибка подключения Wi-Fi" "Ошибка аутентификации" "Недоступна" - "Подключение к Интернету отсутствует и не будет восстановлено автоматически." + "Отсутствует интернет-соединение. Повторное подключение к сети не будет выполняться автоматически." + "Отсутствует подключение к Интернету" "Кто сохранил: %1$s" "Установлено подключение через Ассистента Wi-Fi" "Подключено к %1$s" "Доступно через %1$s" "Подключено, без Интернета" - "Отключено" + "Нет подключения" "Отключение..." "Подключение..." "Подключено" @@ -184,7 +185,6 @@ "Фиктивные местоположения" "Разрешить использование фиктивных местоположений" "Включить проверку атрибутов" - "Использовать DHCP-клиент для Android 5.0, а не для новой версии." "Не отключать передачу данных по мобильной сети даже при активном Wi-Fi-подключении (для быстрого переключения между сетями)." "Разрешить отладку USB?" "Отладка по USB – это режим, который позволяет использовать ваше устройство как внешний накопитель: перемещать файлы (с компьютера и на компьютер), напрямую устанавливать приложения, а также просматривать системные журналы." @@ -234,8 +234,6 @@ "Показывать границы клипа, поля и т. д." "Написание справа налево" "Включить написание справа налево для всех языков" - "Показывать загрузку ЦП" - "Экран, показывающий текущую загрузку ЦП" "GPU-ускорение" "Всегда использовать GPU для двухмерного рисования" "Включить 4x MSAA" @@ -247,7 +245,7 @@ "Длительность анимации" "Эмуляция доп. экранов" "Приложения" - "Не сохранять действия" + "Не сохранять активности" "Удалять сводку действий после их завершения" "Лимит фоновых процессов" "Все ANR" @@ -342,4 +340,5 @@ "Максимальный" "Другой (%d)" "Справка/отзыв" + "Меню" diff --git a/packages/SettingsLib/res/values-si-rLK/arrays.xml b/packages/SettingsLib/res/values-si-rLK/arrays.xml index 328cf99d7c9a9bcce69a62293c3b747cdc271c32..518a3300682a40b94a6ba6ba570cf8b73ebc1571 100644 --- a/packages/SettingsLib/res/values-si-rLK/arrays.xml +++ b/packages/SettingsLib/res/values-si-rLK/arrays.xml @@ -84,11 +84,13 @@ "ක්‍රියාවිරහිතය" "සියලු" "සැම වුවද රේඩි." + "කර්නල පමණි" "ක්‍රියාවිරහිතයි" "සියලු ලොග අන්තරාචය" "සියලු නමුත් රේඩියෝ ලොග අන්තරාචය" + "කර්නල ලොග් අන්තරාචය පමණි" "සජිවිකරණය අක්‍රිය කිරීම" diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml index aa7f59a01e55705e808c2d2e0dfd58bb27bf87ff..e3acfaee3fe86cccb9ebdd347a66718da8093e77 100644 --- a/packages/SettingsLib/res/values-si-rLK/strings.xml +++ b/packages/SettingsLib/res/values-si-rLK/strings.xml @@ -28,7 +28,8 @@ "WiFi සම්බන්ධතාව අසාර්ථකයි" "සත්‍යාපනයේ ගැටලුවකි" "පරාසයේ නැත" - "අන්තර්ජාල ප්‍රවේශය අනාවරණය වුයේ නැත, ස්වයංක්‍රිය නැවත සම්බන්ධ වීම වූ නැත" + "අන්තර්ජාල ප්‍රවේශය නැත, ස්වයංක්‍රිය නැවත සම්බන්ධ නොවනු ඇත." + "අන්තර්ජාල ප්‍රවේශය නැත." "%1$s විසින් සුරකින ලදී" "Wi‑Fi සහායක හරහා සම්බන්ධ කරන ලදි" "%1$s හරහා සම්බන්ධ විය" @@ -184,7 +185,6 @@ "ව්‍යාජ ස්ථානයන්ට අවසර දෙන්න" "ව්‍යාජ ස්ථාන අනුමත කරන්න" "උපලක්ෂණ පරික්ෂාව බැලීම සබල කරන්න" - "නව Android DHCP සේවාලාභියා වෙනුවට Lollipop වෙතින් DHCP සේවාලාභියා භාවිත කරන්න." "Wi‑Fi අක්‍රිය විට පවා, සැම විටම ජංගම දත්ත ක්‍රියාකාරීව තබන්න (අවසන් ජාල මාරුව සඳහා)." "USB දෝශාවේක්ෂණයට ඉඩ දෙන්නද?" "USB දෝශාවේක්ෂණය සංවර්ධන කටයුතු සඳහා පමණක් යොදාගැනේ. එය ඔබගේ පරිගණකය සහ ඔබගේ උපාංගය අතර දත්ත පිටපත් කිරීමට පමණක් භාවිතා කරන්න, ඔබගේ උපාංගය මත දැනුම්දීම් රහිතව යෙදුම් ස්ථාපනය කරන්න, සහ ලොග් දත්ත කියවන්න." @@ -234,8 +234,6 @@ "ක්ලිප් සීමා, මායිම්, ආදිය පෙන්වන්න." "බල RTL පිරිසැලසුම් දිශාව" "සියලු පෙදෙසි සඳහා RTL වෙත බල තිර පිරිසැලසුම" - "CPU භාවිතය පෙන්වන්න" - "තීර උඩැතිරිය වත්මන් CPU භාවිතය පෙන්නුම් කරයි" "GPU විදහාපෑම බලකරන්න" "2d ඇඳීම් සඳහා GPU බලයෙන් භාවිතා කරන්න" "4x MSAA බල කරන්න" @@ -342,4 +340,5 @@ "විශාලතම" "අභිරුචි (%d)" "උදව් සහ ප්‍රතිපෝෂණ" + "මෙනුව" diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml index c8f9a069a1e224cf1975709fa14e1480261e0c53..28480404b4cb955173bb2ab072527dcd55ea3d9a 100644 --- a/packages/SettingsLib/res/values-sk/arrays.xml +++ b/packages/SettingsLib/res/values-sk/arrays.xml @@ -84,11 +84,13 @@ "Vypnuté" "Všetko" "Okrem rádia" + "iba jadro" "Vypnuté" "Všetky vyrovnávacie pamäte denníka" "Všetky vyrovnávacie pamäte denníka (okrem rádia)" + "iba vyrovnávacia pamäť denníka jadra" "Animácia je vypnutá" diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index eaec1fc970bf247b18c06d05e76616c9644b38fc..74a2b4693eb0b923871ee7a0383d738b43e1ff3c 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -28,7 +28,8 @@ "Zlyhanie pripojenia Wi-Fi" "Problém s overením totožnosti" "Mimo dosah" - "Nenašiel sa žiadny prístup k internetu, preto nedôjde k automatickému opätovnému pripojeniu" + "Nenašiel sa žiadny prístup k internetu, preto nedôjde k automatickému opätovnému pripojeniu." + "Žiadny prístup k internetu." "Uložil(a) %1$s" "Pripojené pomocou Asistenta Wi-Fi" "Pripojené prostredníctvom %1$s" @@ -173,8 +174,8 @@ "Zvýšiť úroveň denníkov Wi-Fi, zobrazovať podľa SSID RSSI pri výbere siete Wi-Fi" "Keď túto možnosť zapnete, Wi-Fi bude agresívnejšie odovzdávať dát. pripoj. na mob. sieť vtedy, keď bude slabý signál Wi-Fi" "Povoliť alebo zakázať funkciu Wifi Roam Scans na základe objemu prenosu údajov v rozhraní" - "Veľkosti vyrovnávacej pamäte denníka" - "Veľkosť na vyrovnávaciu pamäť nástroja denníkov" + "Vyrovnávacia pamäť nástroja denníkov" + "Veľkosť vyrovnávacej pamäte nástroja denníkov" "Vymazať trvalé úložisko zapisovača do denníka?" "Keď prestaneme monitorovať pomocou trvalého zapisovača do denníka, musíme vymazať jeho dáta, ktoré sa nachádzajú vo vašom zariadení." "Natrvalo ukladať dáta zapisovača do denníka na zariadení" @@ -184,11 +185,10 @@ "Povoliť simulované polohy" "Povoliť simulované polohy" "Kontrola atribútov zobrazenia" - "Použitie klienta DHCP z verzie Lollipop namiesto nového klienta Android DHCP." "Vždy ponechávať mobilné dáta aktívne, dokonca aj pri aktívnej sieti Wi‑Fi (na rýchle prepínanie sietí)" "Povoliť ladenie cez USB?" - "Ladenie prostredníctvom USB je určené iba na účely vývoja. Použite ho na kopírovanie dát medzi počítačom a zariadením, inštaláciu aplikácií do zariadenia bez upozornenia a čítanie údajov denníka." - "Chcete odvolať prístup k ladeniu cez USB zo všetkých počítačov, ktoré ste predtým autorizovali?" + "Ladenie cez USB je určené iba na účely vývoja. Možno ho použiť na kopírovanie dát medzi počítačom a zariadením, inštaláciu aplikácií do zariadenia bez upozornenia a čítanie dát denníka." + "Chcete všetkým v minulosti autorizovaným počítačom odvolať prístup k ladeniu cez USB?" "Povoliť nastavenia pre vývojárov?" "Tieto nastavenia sú určené len pre vývojárov. Môžu spôsobiť poruchu alebo nesprávne fungovanie zariadenia a nainštalovaných aplikácií." "Overovať aplikácie z USB" @@ -234,8 +234,6 @@ "Zobraziť vo výstrižku ohraničenie, okraje a pod." "Rozloženia sprava doľava" "Vynútiť pre všetky jazyky rozloženie obrazovky sprava doľava" - "Zobraziť využitie CPU" - "Prekryvná vrstva s aktuálnym využitím procesora" "Vykresľovat pomocou GPU" "Používať GPU na dvojrozmerné vykresľovanie" "Vynútiť 4x MSAA" @@ -342,4 +340,5 @@ "Najväčšie" "Vlastné (%d)" "Pomocník a spätná väzba" + "Ponuka" diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml index 124b5d82d554e602d4fdefdcde44254aa4150979..baa16acba8e0db92c8b4269f96508c77c51ee24d 100644 --- a/packages/SettingsLib/res/values-sl/arrays.xml +++ b/packages/SettingsLib/res/values-sl/arrays.xml @@ -84,11 +84,13 @@ "Izklopljeno" "Vse" "Vse (brez rad.)" + "samo jedro" "Izklopljeno" "Vsi medpomnilniki dnevnika" "Vsi medpomnilniki dnevnika, razen za radio" + "samo medpomnilnik dnevnika jedra" "Animacija je izključena" diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index df5f1012cd4beeff6785f4f2a15c604901466467..788b97ce5714225eb7c299124ff32e3bf2911e88 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -28,7 +28,8 @@ "Povezava prek Wi-Fi-ja ni uspela" "Težava s preverjanjem pristnosti" "Ni v obsegu" - "Ni zaznanega dostopa do interneta; samodejna vnovična vzpostavitev povezave se ne bo izvedla." + "Ni zaznanega dostopa do interneta; samodejna vnovična vzpostavitev povezave se ne bo izvedla." + "Ni dostopa do interneta." "Shranil(-a): %1$s" "Povezava vzpostavljena prek pomočnika za Wi-Fi" "Vzpostavljena povezava prek: %1$s" @@ -184,7 +185,6 @@ "Dovoli lažne lokacije" "Dovoli lažne lokacije" "Omogoči pregled atributa pogleda" - "Uporaba odjemalca DHCP za Lollipop namesto novega odjemalca DHCP za Android." "Prenos podatkov v mobilnih omrežjih je vedno aktiven – tudi ko je aktivna povezava Wi-Fi (za hiter preklop med omrežji)." "Ali dovolite odpravljanje težav s povezavo USB?" "Odpravljanje težav s povezavo USB je namenjeno samo za razvoj. Lahko ga uporabljate za kopiranje podatkov med računalnikom in napravo, nameščanje aplikacij v napravo brez obveščanja in branje podatkov v dnevniku." @@ -234,8 +234,6 @@ "Pokaži meje obrezovanja, obrobe ipd." "Vsili od desne proti levi" "Vsili smer postavitve na zaslonu od desne proti levi za vse jezike" - "Prikaži uporabo CPE-ja" - "Prekrivanje zaslona prikazuje tren. uporabo CPE-ja" "Vsili upodabljanje z GPE-jem" "Za risanje 2D vsili uporabo grafičnega procesorja" "Vsili 4x MSAA" @@ -342,4 +340,5 @@ "Največje" "Po meri (%d)" "Pomoč in povratne informacije" + "Meni" diff --git a/packages/SettingsLib/res/values-sq-rAL/arrays.xml b/packages/SettingsLib/res/values-sq-rAL/arrays.xml index 7c0cf6128a6517f110326e84c33ac96b15cdc02b..c40ad83466f21da0ab5cb84e3d06175d914e6d32 100644 --- a/packages/SettingsLib/res/values-sq-rAL/arrays.xml +++ b/packages/SettingsLib/res/values-sq-rAL/arrays.xml @@ -84,11 +84,13 @@ "Joaktive" "Të gjitha" "Të gjitha përveç atyre radio" + "vetëm bërthama" "Joaktive" "Të gjitha memoriet e regjistrit" "Të gjitha memoriet e regjistrit, përveç atyre radio" + "vetëm memoria e regjistrimit të bërthamës" "Animacioni është i çaktivizuar" diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml index 07e5c400cbe8ac030e179a3800fd70f980f19ac5..d6419ddabc5ad271ba565bd4ee309bf579e9eb36 100644 --- a/packages/SettingsLib/res/values-sq-rAL/strings.xml +++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml @@ -28,7 +28,8 @@ "Dështim i lidhjes WiFi" "Problem me vërtetimin" "Nuk është brenda rrezes" - "Nuk u diktua qasje në internet. Lidhja nuk do të realizohet automatikisht." + "Nuk u zbulua qasje në internet. Nuk do të lidhet përsëri automatikisht." + "Nuk ka qasje në internet." "E ruajtur nga %1$s" "I lidhur nëpërmjet ndihmësit të Wi‑Fi" "E lidhur përmes %1$s" @@ -184,7 +185,6 @@ "Lejo vendndodhje të simuluara" "Lejo vendndodhje të simuluara" "Aktivizo shikimin e inspektimit të atributeve" - "Përdor klientin DHCP nga Lollipop në vend të klientit të ri DHCP të Androidit." "Mbaji të dhënat celulare gjithmonë aktive edhe kur Wi‑Fi është aktiv (për ndërrim të shpejtë të rrjetit)." "Të lejohet korrigjimi i USB-së?" "Korrigjuesi i USB-së është vetëm për qëllime zhvillimore. Përdore për të kopjuar të dhëna mes kompjuterit dhe pajisjes tënde, për të instaluar aplikacione në pajisjen tënde pa asnjë njoftim si dhe për të lexuar të dhënat e ditarit." @@ -234,8 +234,6 @@ "Shfaq konturet e klipit, hapësirat etj." "Detyro drejtimin e shkrimit nga e djathta në të majtë" "Ndrysho me detyrim drejtimin e planit të ekranit nga e djathta në të majtë për të gjitha vendet" - "Shfaq përdorimin e CPU-së" - "Mbivendosja e ekranit tregon përdorimin e CPU-së" "Detyro interpretimin e GPU-së" "Detyro përdorimin e GPU-së për vizatimin e dytë" "Detyro 4x MSAA" @@ -342,4 +340,5 @@ "Më i madhi" "I personalizuar (%d)" "Ndihma dhe komentet" + "Menyja" diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml index fd93d4b26288e7d256ae8d7edc884a7fa9c62bf5..1817558cc892a3f3e6f64547a52a5576cbe826ce 100644 --- a/packages/SettingsLib/res/values-sr/arrays.xml +++ b/packages/SettingsLib/res/values-sr/arrays.xml @@ -84,11 +84,13 @@ "Искључено" "Све" "Све сeм радија" + "само језгро" "Искључено" "Све међумеморије евиденција" "Све осим међумеморија евиденција за радио" + "само међумеморија евиденције језгра" "Анимација је искључена" diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index d4e925e1b5ed1cb2f41a7409cc84532e117cd7b3..f8b3b4bccd3c5346225c4634ef82649eeabb7c91 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi веза је отказала" "Проблем са потврдом аутентичности" "Није у опсегу" - "Приступ интернету није откривен, аутоматско повезивање није могуће." + "Приступ интернету није откривен, аутоматско повезивање није могуће." + "Нема приступа интернету." "Сачувао/ла је %1$s" "Повезано преко Wi‑Fi помоћника" "Веза је успостављена преко приступне тачке %1$s" @@ -184,7 +185,6 @@ "Дозволи лажне локације" "Дозволи лажне локације" "Омогући проверу атрибута за преглед" - "Користите DHCP клијент из Lollipop-а уместо новог Android DHCP клијента." "Нека подаци за мобилне уређаје увек буду активни, чак и када је Wi‑Fi активан (ради брзе промене мреже)." "Дозволи отклањање USB грешака?" "Отклањање USB грешака намењено је само за сврхе програмирања. Користите га за копирање података са рачунара на уређај и обрнуто, инсталирање апликација на уређају без обавештења и читање података из евиденције." @@ -234,8 +234,6 @@ "Прикажи границе клипа, маргине итд." "Наметни смер распореда здесна налево" "Наметни смер распореда екрана здесна налево за све локалитете" - "Прик. употребу процесора" - "Постав. елемент са тренутном употребом процесора" "Принудни приказ пом. GPU" "Принудно користи GPU за 2D цртање" "Наметни 4x MSAA" @@ -283,7 +281,7 @@ "Покрећите WebView приказиваче засебно" "Примена WebView-а" "Подесите примену WebView-а" - "Овај избор више није важећи. Покушајте поново." + "Овај избор више није важећи. Пробајте поново." "Конвертуј у шифровање датотека" "Конвертуј..." "Већ се користи шифровање датотека" @@ -342,4 +340,5 @@ "Највећи" "Прилагођени (%d)" "Помоћ и повратне информације" + "Мени" diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml index b8cd8692da7e00fef52891371d28df885bced2c5..9ecedca8429c5cd685936ca955f4d00220507554 100644 --- a/packages/SettingsLib/res/values-sv/arrays.xml +++ b/packages/SettingsLib/res/values-sv/arrays.xml @@ -84,11 +84,13 @@ "Av" "Alla" "Alla utom radio" + "endast kernel" "Av" "Alla loggbuffertar" "Alla loggbuffertar utom för radio" + "endast buffert av kernellogg" "Animering avstängd" diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index db47bb9cb09b50d3e73dc4956d367d32ce61550f..389e03a8288979933b517dc381361d2221057741 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi-anslutningsfel" "Autentiseringsproblem" "Utom räckhåll" - "Ingen internetåtkomst hittades. Det går inte att återansluta automatiskt." + "Ingen internetåtkomst hittades. Det går inte att återansluta automatiskt." + "Ingen internetåtkomst" "Sparades av %1$s" "Ansluten via Wi-Fi-assistent" "Anslutet via %1$s" @@ -184,7 +185,6 @@ "Tillåt skenplatser" "Tillåt skenplatser" "Aktivera inspektion av visningsattribut" - "Använd DHCP-klienten från Lollipop i stället för den nya Android DHCP-klienten." "Håll alltid mobildata aktiverad, även när Wi-Fi är aktiverat (så att du snabbt kan byta mellan nätverk)." "Ska USB-felsökning tillåtas?" "USB-felsökning ska endast användas i utvecklingssyfte. Använd den för att kopiera data mellan datorn och enheten, installera appar på enheten utan meddelanden och läsa loggdata." @@ -234,8 +234,6 @@ "Visa gränser för videoklipp, marginaler m.m." "Tvinga fram RTL-layout" "Tvinga fram RTL-skärmlayout (hö–vä) för alla språk" - "Visa CPU-användning" - "Överlägg på skärmen med aktuell CPU-användning" "Framtvinga GPU-rendering" "Tvingad användning av GPU för 2D-ritning" "Force 4x MSAA" @@ -342,4 +340,5 @@ "Störst" "Anpassad (%d)" "Hjälp och feedback" + "Meny" diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml index 0f78b8bc140900d35225194435f3bf23b3232d2d..e2fbfc3ac536cccf7e7cfcf5501da663314d513b 100644 --- a/packages/SettingsLib/res/values-sw/arrays.xml +++ b/packages/SettingsLib/res/values-sw/arrays.xml @@ -84,11 +84,13 @@ "Yamezimwa" "Zote" "Zote isipokuwa redio" + "keneli pekee" "Imezimwa" "Akiba ya kumbukumbu zote" "Zote isipokuwa akiba ya kumbukumbu za redio" + "akiba ya kumbukumbu ya keneli pekee" "Haiwani imezimwa" diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 20cf0933695fb557043ce29f18b1a0440a4415c3..ff6687cc78f4a1c823800b8f4bb066f0f2559e5a 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -28,7 +28,8 @@ "Haikuweza Kuunganisha kwenye WiFi" "Tatizo la uthibitishaji" "Haiko karibu" - "Hakuna Ufikiaji kwa Intaneti Uliogunduliwa, haitaweza kuunganisha kiotomatiki." + "Haikupata Muunganisho wa Intaneti. Haitaweza kuunganisha tena kiotomatiki." + "Hakuna Muunganisho wa Intaneti." "Ilihifadhiwa na %1$s" "Imeunganishwa kupitia Kisaidizi cha Wi-Fi" "Imeunganishwa kupitia %1$s" @@ -184,7 +185,6 @@ "Ruhusu maeneo ya jaribio" "Ruhusu maeneo ya majaribio" "Washa ukaguzi wa sifa ya onyesho" - "Tumia kiteja cha DHCP kutoka Lollipop badala ya kiteja kipya cha DHCP cha Android." "Washa kila wakati data ya kifaa cha mkononi, hata kama Wi-Fi inatumika (katika uzimaji wa haraka wa mtandao)." "Ruhusu utatuaji USB?" "Ueuaji wa USB umekusudiwa kwa malengo ya utengenezaji tu. Itumi kunakili data kati ya kompyuta yako na kifaa chako, kusanidi programu kwa kifaa chako bila arifa, na kusoma data ya rajisi." @@ -234,8 +234,6 @@ "Onyesha mipaka ya picha, kingo, nk." "Lazimisha uelekezaji wa muundo wa RTL" "Lazimisha uelekezaji wa muundo wa skrini kwa RTL kwa lugha zote" - "Onyesha matumizi ya CPU" - "Kuegeshwa kwa skrini ikionyesha matumizi ya sasa ya CPU" "Lazimisha kutungiliza GPU" "Lazimisha matumizi ya GPU kwa uchoraji wa 2d" "Lazimisha 4x MSAA" @@ -342,4 +340,5 @@ "Kubwa zaidi" "Kiwango maalum (%d)" "Usaidizi na maoni" + "Menyu" diff --git a/packages/SettingsLib/res/values-ta-rIN/arrays.xml b/packages/SettingsLib/res/values-ta-rIN/arrays.xml index faecb0a769e27281c52bf9169b458fabce8bc5c8..fed3cd10b750031c4cd5bb8d8f674eab1262ea27 100644 --- a/packages/SettingsLib/res/values-ta-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-ta-rIN/arrays.xml @@ -84,11 +84,13 @@ "முடக்கத்தில்" "எல்லாம்" "எல்லாம் (ரேடியோ தவிர்த்து)" + "கெர்னல் மட்டும்" "முடக்கத்தில்" "தற்காலிகமாகச் சேமித்த எல்லா பதிவுகளும்" "எல்லாம் (தற்காலிகமாகச் சேமித்த ரேடியோ பதிவுகள் தவிர்த்து)" + "கெர்னல் லாக் பஃபர் மட்டும்" "அனிமேஷனை முடக்கு" diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml index ec4719faeb5142dd7a9044f9928799a7c4f8cce2..86f58fc83e61672edd16d5ec35eaf9be03c05537 100644 --- a/packages/SettingsLib/res/values-ta-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml @@ -28,7 +28,8 @@ "வைஃபை இணைப்பில் தோல்வி" "அங்கீகரிப்புச் சிக்கல்" "தொடர்பு எல்லையில் இல்லை" - "இணைய அணுகல் இல்லை, மீண்டும் தானாக இணையாது." + "இணைய அணுகல் இல்லை, மீண்டும் தானாக இணையாது." + "இணைய அணுகல் இல்லை." "%1$s சேமித்தது" "வைஃபை அசிஸ்டண்ட் மூலம் இணைக்கப்பட்டது" "%1$s வழியாக இணைக்கப்பட்டது" @@ -184,7 +185,6 @@ "போலி இருப்பிடங்களை அனுமதி" "போலி இருப்பிடங்களை அனுமதி" "காட்சி பண்புக்கூறு சோதனையை இயக்கு" - "புதிய Android DHCP க்ளையன்ட்டிற்குப் பதிலாக, Lollipop இலிருந்து DHCP க்ளையன்ட்டைப் பயன்படுத்தவும்." "வைஃபை இயங்கும் போதும் (வேகமான நெட்வொர்க் மாற்றத்திற்கு), மொபைல் தரவை எப்போதும் இயக்கத்தில் வைக்கும்." "USB பிழைத்திருத்தத்தை அனுமதிக்கவா?" "USB பிழைத்திருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் பயன்பாடுகளை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்." @@ -234,8 +234,6 @@ "கிளிப் எல்லைகள், ஓரங்கள், மேலும் பலவற்றைக் காட்டு" "RTL தளவமைப்பின் திசையை வலியுறுத்து" "எல்லா மொழிகளுக்கும் திரையின் தளவமைப்பு திசையை RTL க்கு மாற்று" - "CPU பயன்பாட்டைக் காட்டு" - "தற்போதைய CPU பயன்பாட்டைக் காட்டும் திரை மேலடுக்கு" "GPU காட்சியாக்கத்தை வலியுறுத்து" "2d வரைபடத்திற்கு GPU பயன்பாட்டை வலியுறுத்து" "4x MSAA ஐ வலியுறுத்து" @@ -342,4 +340,5 @@ "மிகப் பெரியது" "தனிப்பயன் (%d)" "உதவி & கருத்து" + "மெனு" diff --git a/packages/SettingsLib/res/values-te-rIN/arrays.xml b/packages/SettingsLib/res/values-te-rIN/arrays.xml index 9d48a836b5c961384c05bca9110494385663d89b..482a1da2e8c5a06c7428e26d513fbb0b9ba6d881 100644 --- a/packages/SettingsLib/res/values-te-rIN/arrays.xml +++ b/packages/SettingsLib/res/values-te-rIN/arrays.xml @@ -84,11 +84,13 @@ "ఆఫ్ చేయి" "అన్నీ" "అన్నీ కానీ రేడియో" + "కెర్నెల్ మాత్రమే" "ఆఫ్ చేయి" "అన్ని లాగ్ బఫర్‌లు" "అన్నీ కానీ రేడియో లాగ్ బఫర్‌లు" + "కెర్నెల్ లాగ్ బఫర్ మాత్రమే" "యానిమేషన్ ఆఫ్‌లో ఉంది" diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml index 17c0f91c083675499bd7f07c3a77b28d6a3cda9b..13265760eaf9e607b909da902e8af83035fe9575 100644 --- a/packages/SettingsLib/res/values-te-rIN/strings.xml +++ b/packages/SettingsLib/res/values-te-rIN/strings.xml @@ -28,7 +28,8 @@ "WiFi కనెక్షన్ వైఫల్యం" "ప్రామాణీకరణ సమస్య" "పరిధిలో లేదు" - "ఇంటర్నెట్ ప్రాప్యత కనుగొనబడలేదు, స్వయంచాలకంగా మళ్లీ కనెక్ట్ చేయబడదు." + "ఇంటర్నెట్ ప్రాప్యత కనుగొనబడలేదు, స్వయంచాలకంగా మళ్లీ కనెక్ట్ చేయబడదు." + "ఇంటర్నెట్ ప్రాప్యత లేదు." "%1$s ద్వారా సేవ్ చేయబడింది" "Wi‑Fi సహాయకం ద్వారా కనెక్ట్ చేయబడింది" "%1$s ద్వారా కనెక్ట్ చేయబడింది" @@ -184,7 +185,6 @@ "అనుకృత స్థానాలను అనుమతించు" "అనుకృత స్థానాలను అనుమతించు" "వీక్షణ లక్షణ పర్యవేక్షణను ప్రారంభించు" - "కొత్త Android DHCP క్లయింట్‌కి బదులుగా Lollipop నుండి DHCP క్లయింట్‌ను ఉపయోగించండి." "ఎల్లప్పుడూ మొబైల్ డేటాను సక్రియంగా ఉంచు, Wi‑Fi సక్రియంగా ఉన్నా కూడా (వేగవంతమైన నెట్‌వర్క్ మార్పు కోసం)." "USB డీబగ్గింగ్‌ను అనుమతించాలా?" "USB డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్ మరియు మీ పరికరం మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో అనువర్తనాలను ఇన్‌స్టాల్ చేయడానికి మరియు లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి." @@ -234,8 +234,6 @@ "క్లిప్ సరిహద్దులు, అంచులు మొ. చూపు" "RTL లేఅవుట్ దిశను నిర్భందం చేయండి" "అన్ని లొకేల్‌ల కోసం RTLకి స్క్రీన్ లేఅవుట్ దిశను నిర్భందించు" - "CPU వినియోగాన్ని చూపు" - "ప్రస్తుత CPU వినియోగాన్ని చూపేలా స్క్రీన్ అతివ్యాప్తి చేయబడుతుంది" "నిర్బంధంగా GPU భాషాంతరీకరణ" "2d డ్రాయింగ్ కోసం GPU నిర్భంద వినియోగం" "నిర్భందం 4x MSAA" @@ -342,4 +340,5 @@ "అతి పెద్దగా" "అనుకూలం (%d)" "సహాయం & అభిప్రాయం" + "మెను" diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml index e61d5ff6852a237188e0ab6e3a553e59f32ea25b..08caeb6577fb82b53102e48719fe21fc2e1fc29d 100644 --- a/packages/SettingsLib/res/values-th/arrays.xml +++ b/packages/SettingsLib/res/values-th/arrays.xml @@ -84,11 +84,13 @@ "ปิด" "ทั้งหมด" "ทั้งหมดเว้นวิทยุ" + "เฉพาะเคอร์เนล" "ปิด" "บัฟเฟอร์บันทึกทั้งหมด" "ทั้งหมดยกเว้นบัฟเฟอร์บันทึกวิทยุ" + "เฉพาะบัฟเฟอร์ไฟล์บันทึกเคอร์เนล" "ปิดภาพเคลื่อนไหว" diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 97a17f35911a70c32bddd415767e321cc97fa382..5d302d08e89c96df92392618bfd1ef95b72e8e80 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -28,7 +28,8 @@ "การเชื่อมต่อ Wi-Fi ล้มเหลว" "ปัญหาในการตรวจสอบสิทธิ์" "ไม่อยู่ในพื้นที่ให้บริการ" - "ไม่พบการเข้าถึงอินเทอร์เน็ต ระบบจะไม่เชื่อมต่อใหม่โดยอัตโนมัติ" + "ไม่พบการเข้าถึงอินเทอร์เน็ต ระบบจะไม่เชื่อมต่อใหม่โดยอัตโนมัติ" + "ไม่สามารถเข้าถึงอินเทอร์เน็ต" "บันทึกโดย %1$s แล้ว" "เชื่อมต่อผ่านตัวช่วย Wi-Fi อยู่" "เชื่อมต่อผ่าน %1$s แล้ว" @@ -184,7 +185,6 @@ "อนุญาตให้จำลองตำแหน่ง" "อนุญาตให้จำลองตำแหน่ง" "เปิดใช้การตรวจสอบแอตทริบิวต์มุมมอง" - "ใช้ไคลเอ็นต์ DHCP จาก Lollipop แทนไคลเอ็นต์ DHCP ใหม่บน Android" "เปิดใช้ข้อมูลมือถืออยู่เสมอ แม้ในเวลาที่ใช้งาน Wi-Fi อยู่ (สำหรับสวิตชิงเครือข่ายความเร็วสูง)" "อนุญาตให้แก้ไขข้อบกพร่อง USB หรือไม่" "การแก้ไขข้อบกพร่อง USB มีไว้เพื่อการพัฒนาเท่านั้น ให้ใช้การแก้ไขนี้เพื่อคัดลอกข้อมูลระหว่างคอมพิวเตอร์และอุปกรณ์ ติดตั้งแอปพลิเคชันบนอุปกรณ์โดยไม่มีการแจ้งเตือน และอ่านข้อมูลบันทึก" @@ -234,8 +234,6 @@ "แสดงหน้าปกคลิป ขอบ ฯลฯ" "บังคับทิศทางการจัดวาง RTL" "บังคับทิศทางการจัดวางหน้าจอเป็น RTL สำหรับทุกภาษา" - "แสดงการใช้ CPU" - "การวางซ้อนหน้าจอที่แสดงการใช้ CPU ในปัจจุบัน" "เร่งการแสดงผลของ GPU" "ต้องใช้ GPU สำหรับการวาดภาพ 2 มิติ" "บังคับใช้ 4x MSAA" @@ -342,4 +340,5 @@ "ใหญ่ที่สุด" "กำหนดเอง (%d)" "ความช่วยเหลือและความคิดเห็น" + "เมนู" diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml index 032d41b6c429c5b993a09a58dc7a88f098a98668..a1505dc0a610c631b6f66bb28d445d447c5bbdaa 100644 --- a/packages/SettingsLib/res/values-tl/arrays.xml +++ b/packages/SettingsLib/res/values-tl/arrays.xml @@ -84,11 +84,13 @@ "Naka-off" "Lahat" "Maliban sa radyo" + "kernel lang" "Naka-off" "Lahat ng buffer ng log" "Lahat maliban sa buffer ng log ng radyo" + "kernel log buffer lang" "Naka-off ang animation" diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index a0076658544956c9598a3b6c7a36ac6fb8f0db47..c2232ee76e96835a71eb8781cc83293855516a3c 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -28,7 +28,8 @@ "Pagkabigo ng Koneksyon sa WiFi" "Problema sa pagpapatotoo" "Wala sa sakop" - "Walang Natukoy na Access sa Internet, hindi awtomatikong muling kumonekta." + "Walang Na-detect na Access sa Internet, hindi awtomatikong muling kokonekta." + "Walang Access sa Internet." "Na-save ni %1$s" "Nakakonekta sa pamamagitan ng Wi‑Fi assistant" "Nakakonekta sa pamamagitan ng %1$s" @@ -146,7 +147,7 @@ "Hindi available ang mga setting ng VPN para sa user na ito" "Hindi available ang mga setting ng pagte-theter para sa user na ito" "Hindi available ang mga setting ng Access Point Name para sa user na ito" - "Pagde-debug ng USB" + "Pag-debug ng USB" "Debug mode kapag nakakonekta ang USB" "Bawiin ang mga pahintulot sa pag-debug ng USB" "Shortcut ng ulat sa bug" @@ -184,11 +185,10 @@ "Payagan ang mga kunwaring lokasyon" "Payagan ang mga kunwaring lokasyon" "I-enable ang pagsisiyasat sa attribute na view" - "Gamitin ang DHCP client mula sa Lollipop sa halip na ang bagong Android DHCP client." "Palaging panatilihing aktibo ang mobile data, kahit na aktibo ang Wi‑Fi (para sa mabilis na paglipat ng network)." "Payagan ang pag-debug ng USB?" - "Ang pag-debug ng USB ay nilalayon para sa mga layuning pagpapabuti lamang. Gamitin ito upang kumopya ng data sa pagitan ng iyong computer at iyong device, mag-install ng apps sa iyong device nang walang notification, at magbasa ng data ng log." - "Bawiin ang access sa pagde-debug ng USB mula sa lahat ng computer na dati mong pinahintulutan?" + "Ang pag-debug ng USB ay para lang sa mga layuning pag-develop. Gamitin ito upang kumopya ng data sa pagitan ng iyong computer at iyong device, mag-install ng mga app sa iyong device nang walang notification, at magbasa ng data ng log." + "Bawiin ang access sa pag-debug ng USB mula sa lahat ng computer na dati mong pinahintulutan?" "Payagan ang mga setting ng pag-develop?" "Nilalayon ang mga setting na ito para sa paggamit sa pag-develop lamang. Maaaring magsanhi ang mga ito ng pagkasira o hindi paggana nang maayos ng iyong device at mga application na nandito." "I-verify ang mga app sa USB" @@ -234,8 +234,6 @@ "Ipakita ang mga hangganan ng clip, margin, atbp." "Force RTL layout dir." "Force screen layout dir. sa RTL sa lahat ng lokal" - "Ipakita paggamit ng CPU" - "Ipinapakita ng screen overlay ang paggamit ng CPU ngayon" "Ipilit ang pag-render ng GPU" "Sapilitang paggamit sa GPU para sa 2d na pagguhit" "Puwersahin ang 4x MSAA" @@ -342,4 +340,5 @@ "Pinakamalaki" "Custom (%d)" "Tulong at feedback" + "Menu" diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml index f706a70316ab77b1039ab35d1df977cf22da7db0..c97e79c33c2f7b892e9b46f3d5d8de9aa1440bb1 100644 --- a/packages/SettingsLib/res/values-tr/arrays.xml +++ b/packages/SettingsLib/res/values-tr/arrays.xml @@ -84,11 +84,13 @@ "Kapalı" "Tümü" "Radyo hariç tümü" + "yaln. çekirdek" "Kapalı" "Günlük arabelleklerin tümü" "Radyo günlük arabellekleri hariç tümü" + "yalnızca çekirdek günlük arabelleği" "Animasyon kapalı" diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 887efb9b49c3dfd62b87cbd0878ffdd9800f9cb3..2541a3f6bc3165f808d740642ec426f45367241d 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -28,7 +28,8 @@ "Kablosuz Bağlantı Hatası" "Kimlik doğrulama sorunu" "Kapsama alanı dışında" - "İnternet Erişimi algılanmadı, otomatik olarak tekrar bağlanmayacak." + "İnternet Erişimi Algılanmadı, otomatik olarak tekrar bağlanmayacak." + "İnternet Erişimi Yok." "%1$s tarafından kaydedildi" "Kablosuz bağlantı yardımcısıyla bağlandı" "%1$s üzerinden bağlı" @@ -184,7 +185,6 @@ "Sahte konumlara izin ver" "Sahte konumlara izin ver" "Görünüm özelliği incelemeyi etkinleştir" - "Yeni Android DHCP istemcisi yerine Lollipop DHCP istemcisini kullan." "Kablosuz bağlantı etkin bile olsa mobil veri kullanımını her zaman etkin tut (ağlar arasında hızlı geçiş yapmak için)." "USB hata ayıklamasına izin verilsin mi?" "USB hata ayıklaması yalnızca geliştirme amaçlıdır. Verileri bilgisayarınızla cihazınız arasında kopyalamak, bildirim göndermeksizin uygulamaları cihazınıza yüklemek ve günlük verilerini okumak için kullanın." @@ -234,8 +234,6 @@ "Klip sınırlarını, kenar boşluklarını vb. göster" "Sağdan sola düzenini zorla" "Tüm yerel ayarlar için sağdan sola ekran düzenini zorlar" - "CPU kullanımını göster" - "Mevcut CPU kullanımını gösteren yer paylaşımı" "GPU oluşturmayı zorla" "2D çizimde GPU kullanımını zorla" "4x MSAA\'yı zorla" @@ -342,4 +340,5 @@ "En büyük" "Özel (%d)" "Yardım ve geri bildirim" + "Menü" diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml index f6cc7b16135534615f83e39ac7afe2bb927dca1b..7b720f3e9a74a1581094a0451dfb9497f34ec306 100644 --- a/packages/SettingsLib/res/values-uk/arrays.xml +++ b/packages/SettingsLib/res/values-uk/arrays.xml @@ -84,11 +84,13 @@ "Вимкнено" "Усі" "Усі, крім радіо" + "лише ядро" "Вимкнено" "Буфери всіх журналів" "Буфери всіх журналів, крім радіо" + "лише буфер журналу ядра" "Анімацію вимкнено" diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index ad95431414eb0827f0f715ea7cffcc364f27704f..1829677eaf9d26ed34d27670cfff820c8fff9009 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -28,7 +28,8 @@ "Помилка з’єднання Wi-Fi" "Проблема з автентифікацією" "Не в діапазоні" - "Немає доступу до Інтернету. Спроба під’єднання не здійснюватиметься автоматично." + "Немає доступу до Інтернету. Спроба під’єднання не здійснюватиметься автоматично." + "Немає доступу до Інтернету." "Збережено додатком %1$s" "Під’єднано через Диспетчер Wi-Fi-з’єднання" "Під’єднано через %1$s" @@ -184,7 +185,6 @@ "Фіктивні місцезнаходження" "Дозв. фіктивні місцезн." "Увімкнути оцінку атрибуції переглядів" - "Використовувати клієнт DHCP з Lollipop, а не новий клієнт DHCP з Android." "Не вимикати мобільний Інтернет, навіть якщо ввімкнено Wi‑Fi (щоб швидше переходити між мережами)." "Дозвол. налагодж. USB?" "Налагодження USB застосовується лише з метою розробки. Його можна використовувати для копіювання даних між комп’ютером і пристроєм, встановлення програм на вашому пристрої без сповіщення та читання даних журналу." @@ -234,8 +234,6 @@ "Показувати межі роликів, поля тощо" "Макет письма справа наліво" "Застосовувати макет письма справа наліво для всіх мов" - "Показати використання ЦП" - "Показувати на екрані поточне використання ЦП" "Примусова візуалізація GPU" "Примусово використовувати GPU для 2D-малювання" "Примус. запустити 4x MSAA" @@ -342,4 +340,5 @@ "Найбільші елементи" "Спеціальний масштаб (%d)" "Довідка й відгуки" + "Меню" diff --git a/packages/SettingsLib/res/values-ur-rPK/arrays.xml b/packages/SettingsLib/res/values-ur-rPK/arrays.xml index 4b5e3f6f292dc8aedec611a4f927a69e9abbfb3f..4f081e55c7cf8694635ada220a4fe33526afc818 100644 --- a/packages/SettingsLib/res/values-ur-rPK/arrays.xml +++ b/packages/SettingsLib/res/values-ur-rPK/arrays.xml @@ -84,11 +84,13 @@ "آف" "تمام" "ریڈیو کے سوا تمام" + "صرف کرنل" "آف" "تمام لاگ بفرز" "ریڈیو لاگ بفرز کے سوا تمام" + "صرف کرنل لاگ بفر" "اینیمیشن آف ہے" diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml index aedd6a16e81b0cd5252a497186833d41b5166ba2..8bcf20b241d29da271af25e1adf89b48632ab8fc 100644 --- a/packages/SettingsLib/res/values-ur-rPK/strings.xml +++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml @@ -28,7 +28,8 @@ "‏WiFi کنکشن کی ناکامی" "توثیق کا مسئلہ" "رینج میں نہیں ہے" - "انٹرنیٹ تک کسی رسائی کا پتہ نہیں چلا، خود بخود دوبارہ منسلک نہیں ہوگا۔" + "انٹرنیٹ تک کسی رسائی کا پتہ نہیں چلا، خودکار طور پر دوبارہ منسلک نہیں ہوگا۔" + "انٹرنیٹ تک کوئی رسائی نہیں۔" "%1$s کی جانب سے محفوظ کردہ" "‏Wi‑Fi اسسٹنٹ کے ذریعے منسلک ہے" "‏منسلک بذریعہ ‎%1$s" @@ -184,7 +185,6 @@ "فرضی مقامات کی اجازت دیں" "فرضی مقامات کی اجازت دیں" "منظر انتساب کے معائنہ کو فعال کریں" - "‏نئے Android DHCP کلائنٹ کی بجائے Lollipop کا DHCP کلائنٹ استعمال کریں۔" "‏Wi‑Fi فعال ہونے پر بھی موبائل ڈیٹا کو ہمیشہ فعال رکھیں (تیزی سے نیٹ ورک سوئچ کرنے کیلئے)۔" "‏USB ڈیبگ کرنے کی اجازت دیں؟" "‏USB ڈیبگ کرنا صرف ڈیولپمنٹ کے مقاصد کیلئے ہے۔ اپنے کمپیوٹر اور اپنے آلہ کے درمیان ڈیٹا کاپی کرنے کیلئے اسے استعمال کریں، بغیر اطلاع کے اپنے آلہ پر ایپس انسٹال کریں اور لاگ ڈیٹا پڑھیں۔" @@ -234,8 +234,6 @@ "کلپ باؤنڈز، حاشیے وغیرہ دکھائیں" "‏RTL لے آؤٹ سمت زبردستی نافذ کریں" "‏سبھی زبانوں کیلئے اسکرین لے آؤٹ کی سمت کو RTL پر مجبور کریں" - "‏CPU استعمال دکھائیں" - "‏موجودہ CPU استعمال دکھانے والا اسکرین اوورلے" "‏GPU رینڈرنگ زبردستی نافذ کریں" "‏2D ڈرائنگ کیلئے GPU کا استعمال زبردستی نافذ کریں" "‏4x MSAA زبردستی نافذ کریں" @@ -342,4 +340,5 @@ "سب سے بڑا" "حسب ضرورت (%d)" "مدد اور تاثرات" + "مینو" diff --git a/packages/SettingsLib/res/values-uz-rUZ/arrays.xml b/packages/SettingsLib/res/values-uz-rUZ/arrays.xml index ce81feecdf24997ff65fcb18f7f1c62f983bbe08..f501242e96f33cfa4d478c7c33f1a21387481f95 100644 --- a/packages/SettingsLib/res/values-uz-rUZ/arrays.xml +++ b/packages/SettingsLib/res/values-uz-rUZ/arrays.xml @@ -84,11 +84,13 @@ "O‘chiq" "Hammasi" "Radiodan boshqa hammasi" + "faqat yadro" "O‘chiq" "Barcha jurnallar buferi" "Radio jurnallar buferidan tashqari hammasi" + "faqat yadro jurnali buferi" "Animatsiya o‘chiq" diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml index 1132892820376cc9e4193ccb03030b4162654712..a0c72a09e1843920afe4c0e3e13ca03f31ffe05a 100644 --- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml +++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml @@ -28,7 +28,8 @@ "Wi-Fi ulanishini o‘rnatib bo‘lmadi" "Tasdiqdan o‘tishda muammo" "Aloqada emas" - "Internetga ulanish aniqlanmadi, avtomatik ravishda qayta ulana olmaydi." + "Internetga ulanish aniqlanmadi, avtomatik ravishda qayta ulana olmaydi." + "Internet aloqasi yo‘q." "%1$s tomonidan saqlangan" "Wi‑Fi yordamchisi orqali ulangan" "%1$s orqali ulangan" @@ -75,7 +76,7 @@ "Agar ulanishga ruxsat bersangiz, ulangan vaqtda kontakt va qo‘ng‘iroqlaringiz tarixiga kirishi mumkin." "%1$s bilan biriktirib bo‘lmadi." "%1$s qurilmasiga ulanib bo‘lmadi, chunki PIN-kod yoki parol noto‘g‘ri kiritildi." - "Quyidagi qurilma javob bermayapti: %1$s." + "“%1$s” qurilmasi bilan aloqa o‘rnatib bo‘lmayapti." "%1$s biriktirish so‘rovini rad qildi." "Wi-Fi o‘chiq." "Wi-Fi o‘chiq." @@ -184,7 +185,6 @@ "Qo‘lbola joylashuvlarga ruxsat berish" "Joylashuv emulyatsiyasiga ruxsat berish" "Alomatlar tekshiruvini yoqish" - "Yangi Android DHCP mijoz-dasturi o‘rniga Lollipop tizimi DHCP mijoz-dasturidan foydalanilsin." "Mobil internet har doim yoniq tursin, hatto Wi-Fi yoniq bo‘lsa ham (bir tarmoqdan ikkinchisiga tezroq o‘tish uchun)." "USB orqali nosozliklarni tuzatishga ruxsat berilsinmi?" "USB orqali nosozliklarni tuzatish faqat dasturlash maqsadlarida yoqiladi. Undan ma‘lumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal ma‘lumotlarini o‘qish uchun foydalaniladi." @@ -234,8 +234,6 @@ "Klip, maydon va h.k. chegaralarini ko‘rsatish" "O‘ngdan chapga qarab yozish" "Barcha tillarda o‘ngdan chapga qarab yozish" - "MP yuklanishini ko‘rsatish" - "Joriy MP yuklanishini ko‘rsatuvchi ekran" "GPU yordamida tezlatish" "Ikki o‘lchamli chizma uchun doim GPU ishlatilsin" "4x MSAAni yoqish" @@ -342,4 +340,5 @@ "Eng katta" "Moslashtirilgan (%d)" "Yordam va fikr-mulohaza" + "Menyu" diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml index ba2d4b9193af3b2382981a5729a8a28ee0461382..237b4f4d3ddab8907f0005a4f12328e7057887f2 100644 --- a/packages/SettingsLib/res/values-vi/arrays.xml +++ b/packages/SettingsLib/res/values-vi/arrays.xml @@ -84,11 +84,13 @@ "Tắt" "Tất cả" "Tất cả trừ đài" + "chỉ kernel" "Tắt" "Tất cả lần tải nhật ký" "Tất cả trừ lần tải nhật ký qua đài" + "chỉ vùng đệm nhật ký kernel" "Tắt hình động" diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 4d7f36da91aeb77e729f8e3ee5279d7033e7aad5..b99117768d33314573885e0366edf3301ac71e65 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -28,7 +28,8 @@ "Lỗi kết nối WiFi" "Sự cố xác thực" "Ngoài vùng phủ sóng" - "Không phát hiện thấy truy cập Internet nào, mạng sẽ không được tự động kết nối lại." + "Không phát hiện thấy kết nối Internet, mạng sẽ không tự động kết nối lại." + "Không có kết nối Internet." "Được lưu bởi %1$s" "Được kết nối qua trình hỗ trợ Wi‑Fi" "Được kết nối qua %1$s" @@ -184,7 +185,6 @@ "Cho phép vị trí mô phỏng" "Cho phép vị trí mô phỏng" "Cho phép kiểm tra thuộc tính của chế độ xem" - "Sử dụng ứng dụng DHCP từ Lollipop thay vì ứng dụng DHCP mới của Android." "Luôn giữ cho dữ liệu di động hoạt động, ngay cả khi Wi-Fi đang hoạt động (để chuyển đổi mạng nhanh)." "Cho phép gỡ lỗi USB?" "Gỡ lỗi USB chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị của bạn mà không thông báo và đọc dữ liệu nhật ký." @@ -234,8 +234,6 @@ "Hiển thị viền đoạn video, lề, v.v.." "Buộc hướng bố cục RTL" "Buộc hướng bố cục màn hình RTL cho tất cả ngôn ngữ" - "Hiển thị mức sử dụng CPU" - "Lớp phủ màn hình hiển thị mức sử dụng CPU hiện tại" "Bắt buộc kết xuất GPU" "Bắt buộc sử dụng GPU cho bản vẽ 2d" "Bắt buộc 4x MSAA" @@ -342,4 +340,5 @@ "Lớn nhất" "Tùy chỉnh (%d)" "Trợ giúp và phản hồi" + "Menu" diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml index fa1e9096c3ca7c88d8fa5f207d004e067c4ef75f..8a3febdaadd5471a8e837e2e645b032a91248590 100644 --- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml @@ -84,11 +84,13 @@ "关闭" "全部" "所有非无线电" + "仅限内核" "关闭" "所有日志缓冲区" "所有非无线电日志缓冲区" + "仅限内核日志缓冲区" "关闭动画" diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 0a0d35f5d0b22db8caaa2fa264629b33aafd825d..29c4c7313c6f6b4ad82201d0efc69565dd30387e 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -28,7 +28,8 @@ "WLAN 连接失败" "身份验证出现问题" "不在范围内" - "未检测到任何互联网连接,因此不会自动重新连接。" + "未检测到任何互联网连接,系统无法自动为您重新连接。" + "无法连接到互联网。" "已通过%1$s保存" "已连接(通过 WLAN 助手)" "已通过%1$s连接" @@ -132,8 +133,8 @@ "快" "较快" "非常快" - "迅速" - "很迅速" + "超快" + "极快" "最快" "选择个人资料" @@ -184,10 +185,9 @@ "允许模拟位置" "允许模拟位置" "启用视图属性检查功能" - "使用 Lollipop 的 DHCP 客户端,而不是新的 Android DHCP 客户端。" "始终开启移动数据网络,即使 WLAN 网络已开启(便于快速切换网络)。" "是否允许USB调试?" - "USB调试仅适用于开发工作。该功能可用于在您的计算机和设备之间复制数据、在您的设备上安装应用而不发送通知以及读取日志数据。" + "USB 调试仅用于开发目的。该功能可用于在您的计算机和设备之间复制数据、在您的设备上安装应用(事先不发通知)以及读取日志数据。" "是否针对您之前授权的所有计算机撤消USB调试的访问权限?" "允许开发设置?" "这些设置仅适用于开发工作。一旦启用,会导致您的设备以及设备上的应用崩溃或出现异常。" @@ -234,8 +234,6 @@ "显示剪辑边界、边距等。" "强制使用从右到左的布局方向" "强制将所有语言区域的屏幕布局方向改为从右到左" - "显示 CPU 使用情况" - "屏幕叠加层显示当前 CPU 使用情况" "强制进行 GPU 渲染" "强制使用 GPU 进行 2D 绘图" "强制启用 4x MSAA" @@ -342,4 +340,5 @@ "最大" "自定义 (%d)" "帮助和反馈" + "菜单" diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml index 63c7cac149e6921cf8c336ad7a7742f1f565b92f..fe658844d8c958dc9ca67618738fd158b3f9cadc 100644 --- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml @@ -84,11 +84,13 @@ "關閉" "全部" "所有非無線電" + "只限核心" "關閉" "所有記錄緩衝區" "所有非無線電記錄緩衝區" + "只限核心記錄緩衝區" "關閉動畫" diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 5594f82640396f87700768cf6e8890d5b47d66a7..9c955118cf4f6dd40eaf3adeab720b4b455497b1 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -28,7 +28,8 @@ "WiFi 連線失敗" "驗證問題" "超出可用範圍" - "未能偵測到互聯網連線,因此不會自動重新連線。" + "無法偵測互聯網連線,未能自動重新連線。" + "無法偵測互聯網連線。" "%1$s 的儲存" "已透過 Wi-Fi 小幫手連線" "已透過 %1$s 連線" @@ -184,7 +185,6 @@ "允許模擬位置" "允許模擬位置" "啟用檢視屬性檢查" - "使用 Lollipop 的 DHCP 用戶端,而不是新的 Android DHCP 用戶端。" "即使 Wi‑Fi 已啟用,仍永遠啟用流動數據 (可快速切換網絡)。" "允許 USB 偵錯嗎?" "USB 偵錯是針對應用程式開發而設計的功能,可讓您在電腦與裝置間複製資料、不用通知即可在裝置上安裝應用程式,以及讀取記錄資料。" @@ -234,8 +234,6 @@ "顯示剪輯範圍、邊界等" "強制使用從右至左的版面配置方向" "強制將所有語言代碼的畫面配置方向改為從右至左" - "顯示 CPU 使用量" - "在螢幕上重疊顯示目前的 CPU 使用量" "強制使用 GPU 轉譯" "強制使用 GPU 進行 2D 繪圖" "強制 4x MSAA" @@ -341,5 +339,6 @@ "較大" "最大" "自訂 (%d)" - "說明與意見反映" + "說明和意見反映" + "選單" diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml index e816f1a6f4288abfd2a019465b11881d0ea18c7f..0939e93c3e6954fc0de8eea06072d7fa2ac6ee1d 100644 --- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml @@ -84,11 +84,13 @@ "關閉" "全部" "無線電以外" + "僅限核心" "關閉" "所有紀錄緩衝區" "無線電紀錄緩衝區以外的所有紀錄緩衝區" + "僅限核心紀錄緩衝區" "關閉動畫" diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 2834f58d50650b4ec1b3e046859dca1e52f0a938..fb180ff59659ab4f6089782b3b6212a3bf7bbcb1 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -28,7 +28,8 @@ "WiFi 連線失敗" "驗證問題" "不在有效範圍內" - "未偵測到可用的網際網路連線,系統無法為您自動重新連線。" + "未偵測到可用的網際網路連線,系統無法為你自動重新連線。" + "沒有可用的網際網路連線。" "由%1$s儲存" "已透過 Wi‑Fi 小幫手連線" "已透過 %1$s 連線" @@ -184,7 +185,6 @@ "允許模擬位置" "允許模擬位置" "啟用檢視屬性檢查" - "使用 Lollipop 的 DHCP 用戶端,不使用新型 Android DHCP 用戶端。" "即使 Wi‑Fi 連線已啟用,一律將行動數據連線保持啟用狀態 (以便快速切換網路)。" "允許 USB 偵錯嗎?" "USB 偵錯是針對應用程式開發而設計的功能,可讓您複製電腦和裝置中的資料、不需經由通知即可在裝置上安裝應用程式,以及讀取記錄資料。" @@ -234,8 +234,6 @@ "顯示剪輯範圍、邊界等。" "強制使用從右至左版面配置方向" "強制將所有語言代碼的畫面配置方向改為從右至左" - "顯示 CPU 使用量" - "在螢幕上方顯示目前的 CPU 使用量" "強制使用 GPU 轉譯" "強制使用 GPU 進行 2D 繪圖" "強制 4x MSAA" @@ -342,4 +340,5 @@ "最大" "自訂 (%d)" "說明與意見回饋" + "選單" diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml index f6a1f16de977fe2d22f038fda39a78023964e0a6..772dee8f28266646b02b090eee354fe3f5ab32a9 100644 --- a/packages/SettingsLib/res/values-zu/arrays.xml +++ b/packages/SettingsLib/res/values-zu/arrays.xml @@ -84,11 +84,13 @@ "Valiwe" "Konke" "Konke ngaphandle kwerediyo" + "i-kernel kuphela" "Valiwe" "Onke amabhafa elogi" "Konke ngaphandle kwamabhafa elogi yerediyo" + "ilogi ye-kernel kuphela" "Isithombe esinyakazayo sivliwe" diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index c78a90ff7f546df7c3290baabdaaa98bb7d3ac43..2f9d4282386d9be93463118f94618740b79a79ae 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -28,7 +28,8 @@ "Ukwehlulekla koxhumo le-WiFi" "Inkinga yokufakazela ubuqiniso" "Ayikho ebubanzini" - "Ukufinyeela okungekhona kwe-inthanethi kutholakele, ngeke kuxhumeke ngokuzenzakalelayo." + "Ukufinyeela okungekhona kwe-inthanethi kutholakele, ngeke kuxhumeke ngokuzenzakalelayo." + "Akukho ukufinyelela kwe-intanethi." "Kulondolozwe ngu-%1$s" "Ixhunywe ngomsizi we-Wi-FI" "Kuxhumeke nge-%1$s" @@ -184,7 +185,6 @@ "Vumela izindawo mbumbulu" "Vumela izindawo mbumbulu" "Nika amandla ukubuka" - "Sebenzisa iklayenti le-DHCP kusukela ku-Lollipop esikhundleni seklayenti elisha le-Android DHCP." "Hlala ugcine idatha yeselula isebenza, nanoma i-Wi-Fi isebenza (ngokushintshwa kwenethiwekhi okusheshayo)." "Vumela ukulungisa iphutha le-USB?" "Ukulungisa iphutha le-USB kuhloselwe izinjongo zokuthuthukisa kuphela. Ingasebenziselwa ukukopisha idatha phakathi kwekhompyutha yakho nedivaysi yakho, faka izinhlelo zokusebenza kwidivaysi yakho ngaphandle kwesaziso, bese ufunda idatha yefayela lokungena." @@ -234,8 +234,6 @@ "Bonisa imikhawulo, imiphetho, njll, yesiqeshana." "Phoqelela isikhombisi-ndlela sesakhiwo se-RTL" "Phoqelela isikhombisi-ndlela sesikrini ku-RTL kuzo zonke izifunda" - "Bonisa ukusebenzisa i-CPU" - "Imbondela yesikrini ibonisa ukusetshenziswa kwe-CPU okwamanje" "Phoqa ukunikeza i-GPU" "Phoqelela ukusetshenziswa kwe-GPU ngomdwebo we-2d" "Phoqelela i-4x MSAA" @@ -342,4 +340,5 @@ "Okukhulu kakhulu" "Ngokwezifiso (%d)" "Usizo nempendulo" + "Imenyu" diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index a49fe697298a4f067c2e1130ffc2a41215c6ee23..5b11303247eff8fa3b44d459a29b8b02b9298daa 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -386,4 +386,12 @@ 3 + + + 0 + -1 + 7 + + diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml index 796273dc36a97f3d1f67e7ef28b196064a2f1a4a..02b7ea6ef7a873e38a2589b5e0cb4db76e868952 100644 --- a/packages/SettingsLib/res/values/colors.xml +++ b/packages/SettingsLib/res/values/colors.xml @@ -17,5 +17,5 @@ #66000000 - #455A64 + @*android:color/tertiary_device_default_settings diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml index 299a5b74689c69005ac40daebd83cb322173a63b..e2e721c5ae6bdedc26a14fd6279fcd1a647aa086 100755 --- a/packages/SettingsLib/res/values/config.xml +++ b/packages/SettingsLib/res/values/config.xml @@ -19,4 +19,25 @@ false - + + + 2048 + + + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 6cc5bebb7823409761c5672da34517f2eea980a1..29839e7cbff99900bd025b88171a3d81f41f1cff 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -64,8 +64,10 @@ Authentication problem Not in range + + No Internet Access Detected, won\'t automatically reconnect. - No Internet Access Detected, won\'t automatically reconnect. + No Internet Access. Saved by %1$s @@ -456,8 +458,6 @@ Allow mock locations Enable view attribute inspection - - Use the DHCP client from Lollipop instead of the new Android DHCP client. Always keep mobile data active, even when Wi\u2011Fi is active (for fast network switching). Allow USB debugging? @@ -582,11 +582,6 @@ Force screen layout direction to RTL for all locales - - Show CPU usage - - Screen overlay showing current CPU usage - Force GPU rendering @@ -865,4 +860,7 @@ Help & feedback + + Menu + diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java index ff1c8665b3d2484e80770a59d1c36315a35462b8..b04948b7de5f149eea6c420e48e1b01eb967eeed 100644 --- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java @@ -22,6 +22,9 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Build; +import android.telephony.PhoneNumberUtils; +import android.telephony.SubscriptionInfo; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; @@ -37,6 +40,8 @@ import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static android.content.Context.TELEPHONY_SERVICE; + public class DeviceInfoUtils { private static final String TAG = "DeviceInfoUtils"; @@ -169,4 +174,40 @@ public class DeviceInfoUtils { } } + public static String getFormattedPhoneNumber(Context context, SubscriptionInfo subscriptionInfo) { + String formattedNumber = null; + if (subscriptionInfo != null) { + final TelephonyManager telephonyManager = + (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE); + final String rawNumber = + telephonyManager.getLine1Number(subscriptionInfo.getSubscriptionId()); + if (!TextUtils.isEmpty(rawNumber)) { + formattedNumber = PhoneNumberUtils.formatNumber(rawNumber); + } + + } + return formattedNumber; + } + + public static String getFormattedPhoneNumbers(Context context, + List subscriptionInfo) { + StringBuilder sb = new StringBuilder(); + if (subscriptionInfo != null) { + final TelephonyManager telephonyManager = + (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE); + final int count = subscriptionInfo.size(); + for (int i = 0; i < count; i++) { + final String rawNumber = telephonyManager.getLine1Number( + subscriptionInfo.get(i).getSubscriptionId()); + if (!TextUtils.isEmpty(rawNumber)) { + sb.append(PhoneNumberUtils.formatNumber(rawNumber)); + if (i < count - 1) { + sb.append("\n"); + } + } + } + } + return sb.toString(); + } + } diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java index 320cd580ff8baf5e13749a0d7e8983f559d54540..381f903a97016b28ec3a4bc7152ac1104839d17b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java @@ -23,14 +23,19 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; import android.content.res.Resources.Theme; +import android.content.res.TypedArray; import android.net.Uri; +import android.provider.Settings.Global; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; import android.view.Menu; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.MetricsProto.MetricsEvent; import java.net.URISyntaxException; import java.util.Locale; @@ -91,6 +96,9 @@ public class HelpUtils { */ public static boolean prepareHelpMenuItem(final Activity activity, MenuItem helpMenuItem, String helpUriString, String backupContext) { + if (Global.getInt(activity.getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + return false; + } if (TextUtils.isEmpty(helpUriString)) { // The help url string is empty or null, so set the help menu item to be invisible. helpMenuItem.setVisible(false); @@ -106,6 +114,9 @@ public class HelpUtils { helpMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { + MetricsLogger.action(activity, + MetricsEvent.ACTION_SETTING_HELP_AND_FEEDBACK, + intent.getStringExtra(EXTRA_CONTEXT)); try { activity.startActivityForResult(intent, 0); } catch (ActivityNotFoundException exc) { @@ -128,11 +139,14 @@ public class HelpUtils { public static Intent getHelpIntent(Context context, String helpUriString, String backupContext) { + if (Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + return null; + } // Try to handle as Intent Uri, otherwise just treat as Uri. try { Intent intent = Intent.parseUri(helpUriString, Intent.URI_ANDROID_APP_SCHEME | Intent.URI_INTENT_SCHEME); - addIntentParameters(context, intent, backupContext); + addIntentParameters(context, intent, backupContext, true /* sendPackageName */); ComponentName component = intent.resolveActivity(context.getPackageManager()); if (component != null) { return intent; @@ -156,16 +170,32 @@ public class HelpUtils { return intent; } - private static void addIntentParameters(Context context, Intent intent, String backupContext) { + public static void addIntentParameters(Context context, Intent intent, String backupContext, + boolean sendPackageName) { if (!intent.hasExtra(EXTRA_CONTEXT)) { // Insert some context if none exists. intent.putExtra(EXTRA_CONTEXT, backupContext); } + + Resources resources = context.getResources(); + boolean includePackageName = resources.getBoolean(R.bool.config_sendPackageName); + + if (sendPackageName && includePackageName) { + String[] packageNameKey = + {resources.getString(R.string.config_helpPackageNameKey)}; + String[] packageNameValue = + {resources.getString(R.string.config_helpPackageNameValue)}; + String intentExtraKey = + resources.getString(R.string.config_helpIntentExtraKey); + String intentNameKey = + resources.getString(R.string.config_helpIntentNameKey); + intent.putExtra(intentExtraKey, packageNameKey); + intent.putExtra(intentNameKey, packageNameValue); + } intent.putExtra(EXTRA_THEME, 1 /* Light, dark action bar */); - Theme theme = context.getTheme(); - TypedValue typedValue = new TypedValue(); - theme.resolveAttribute(android.R.attr.colorPrimary, typedValue, true); - intent.putExtra(EXTRA_PRIMARY_COLOR, context.getColor(typedValue.resourceId)); + TypedArray array = context.obtainStyledAttributes(new int[]{android.R.attr.colorPrimary}); + intent.putExtra(EXTRA_PRIMARY_COLOR, array.getColor(0, 0)); + array.recycle(); } /** diff --git a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java index 741b0ea82951cbf2ace04e2c8d556ff77538b59b..21786c91776354fb710adfd296bb8073eb2c741d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java +++ b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java @@ -28,7 +28,6 @@ import android.util.Xml; import android.provider.Settings; import android.accounts.Account; import android.accounts.AccountManager; -import android.content.ContentValues; import android.content.pm.PackageManager; import android.content.res.Resources; import android.view.InflateException; @@ -176,6 +175,9 @@ public class SuggestionParser { } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent()); return false; + } catch (Resources.NotFoundException e) { + Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent(), e); + return false; } } diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index d98f1a4740ad428daa27bc8d8f39ca23c641fa9a..e0490792001ed82118d30bdff39a24fd30f40020 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -1,5 +1,6 @@ package com.android.settingslib; +import android.annotation.ColorInt; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; @@ -8,12 +9,14 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.content.pm.Signature; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import android.net.ConnectivityManager; import android.os.BatteryManager; import android.os.UserManager; +import android.print.PrintManager; import com.android.internal.util.UserIcons; import com.android.settingslib.drawable.UserIconDrawable; @@ -154,11 +157,19 @@ public class Utils { return statusString; } + @ColorInt + public static int getColorAccent(Context context) { + TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent}); + @ColorInt int colorAccent = ta.getColor(0, 0); + ta.recycle(); + return colorAccent; + } + /** * Determine whether a package is a "system package", in which case certain things (like * disabling notifications or disabling the package altogether) should be disallowed. */ - public static boolean isSystemPackage(PackageManager pm, PackageInfo pkg) { + public static boolean isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg) { if (sSystemSignature == null) { sSystemSignature = new Signature[]{ getSystemSignature(pm) }; } @@ -175,7 +186,9 @@ public class Utils { && sSystemSignature[0].equals(getFirstSignature(pkg))) || pkg.packageName.equals(sPermissionControllerPackageName) || pkg.packageName.equals(sServicesSystemSharedLibPackageName) - || pkg.packageName.equals(sSharedSystemSharedLibPackageName); + || pkg.packageName.equals(sSharedSystemSharedLibPackageName) + || pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME) + || isDeviceProvisioningPackage(resources, pkg.packageName); } private static Signature getFirstSignature(PackageInfo pkg) { @@ -193,4 +206,14 @@ public class Utils { } return null; } + + /** + * Returns {@code true} if the supplied package is the device provisioning app. Otherwise, + * returns {@code false}. + */ + public static boolean isDeviceProvisioningPackage(Resources resources, String packageName) { + String deviceProvisioningPackage = resources.getString( + com.android.internal.R.string.config_deviceProvisioningPackage); + return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index 739245330d7ce6f5695a7ce4739cfd19772505c8..f0ec107865075635b25e40b7f60455e5aac28069 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -47,6 +47,7 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.util.ArrayUtils; +import com.android.settingslib.R; import java.io.File; import java.text.Collator; @@ -582,10 +583,10 @@ public class ApplicationsState { public ArrayList rebuild(AppFilter filter, Comparator comparator, boolean foreground) { synchronized (mRebuildSync) { - synchronized (mEntriesMap) { + synchronized (mRebuildingSessions) { mRebuildingSessions.add(this); mRebuildRequested = true; - mRebuildAsync = false; + mRebuildAsync = true; mRebuildFilter = filter; mRebuildComparator = comparator; mRebuildForeground = foreground; @@ -597,23 +598,7 @@ public class ApplicationsState { } } - // We will wait for .25s for the list to be built. - long waitend = SystemClock.uptimeMillis()+250; - - while (mRebuildResult == null) { - long now = SystemClock.uptimeMillis(); - if (now >= waitend) { - break; - } - try { - mRebuildSync.wait(waitend - now); - } catch (InterruptedException e) { - } - } - - mRebuildAsync = true; - - return mRebuildResult; + return null; } } @@ -637,7 +622,7 @@ public class ApplicationsState { } if (filter != null) { - filter.init(); + filter.init(mContext); } List apps; @@ -765,6 +750,7 @@ public class ApplicationsState { static final int MSG_LOAD_ICONS = 3; static final int MSG_LOAD_SIZES = 4; static final int MSG_LOAD_LAUNCHER = 5; + static final int MSG_LOAD_HOME_APP = 6; boolean mRunning; @@ -776,7 +762,7 @@ public class ApplicationsState { public void handleMessage(Message msg) { // Always try rebuilding list first thing, if needed. ArrayList rebuildingSessions = null; - synchronized (mEntriesMap) { + synchronized (mRebuildingSessions) { if (mRebuildingSessions.size() > 0) { rebuildingSessions = new ArrayList(mRebuildingSessions); mRebuildingSessions.clear(); @@ -833,13 +819,33 @@ public class ApplicationsState { if (!mMainHandler.hasMessages(MainHandler.MSG_LOAD_ENTRIES_COMPLETE)) { mMainHandler.sendEmptyMessage(MainHandler.MSG_LOAD_ENTRIES_COMPLETE); } - sendEmptyMessage(MSG_LOAD_LAUNCHER); + sendEmptyMessage(MSG_LOAD_HOME_APP); } } break; + case MSG_LOAD_HOME_APP: { + final List homeActivities = new ArrayList<>(); + mPm.getHomeActivities(homeActivities); + synchronized (mEntriesMap) { + final int entryCount = mEntriesMap.size(); + for (int i = 0; i < entryCount; i++) { + if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_HOME_APP acquired lock"); + final HashMap userEntries = mEntriesMap.valueAt(i); + for (ResolveInfo activity : homeActivities) { + String packageName = activity.activityInfo.packageName; + AppEntry entry = userEntries.get(packageName); + if (entry != null) { + entry.isHomeApp = true; + } + } + if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_HOME_APP releasing lock"); + } + } + sendEmptyMessage(MSG_LOAD_LAUNCHER); + } + break; case MSG_LOAD_LAUNCHER: { Intent launchIntent = new Intent(Intent.ACTION_MAIN, null) .addCategory(Intent.CATEGORY_LAUNCHER); - for (int i = 0; i < mEntriesMap.size(); i++) { int userId = mEntriesMap.keyAt(i); // If we do not specify MATCH_DIRECT_BOOT_AWARE or @@ -1135,6 +1141,11 @@ public class ApplicationsState { */ public boolean hasLauncherEntry; + /** + * Whether or not it's a Home app. + */ + public boolean isHomeApp; + public String getNormalizedLabel() { if (normalizedLabel != null) { return normalizedLabel; @@ -1270,6 +1281,9 @@ public class ApplicationsState { public interface AppFilter { void init(); + default void init(Context context) { + init(); + } boolean filterApp(AppEntry info); } @@ -1326,6 +1340,8 @@ public class ApplicationsState { return true; } else if (entry.hasLauncherEntry) { return true; + } else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0 && entry.isHomeApp) { + return true; } return false; } @@ -1386,6 +1402,33 @@ public class ApplicationsState { } }; + public static final AppFilter FILTER_NOT_HIDE = new AppFilter() { + private String[] mHidePackageNames; + + public void init(Context context) { + mHidePackageNames = context.getResources() + .getStringArray(R.array.config_hideWhenDisabled_packageNames); + } + + @Override + public void init() { + } + + @Override + public boolean filterApp(AppEntry entry) { + if (ArrayUtils.contains(mHidePackageNames, entry.info.packageName)) { + if (!entry.info.enabled) { + return false; + } else if (entry.info.enabledSetting == + PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { + return false; + } + } + + return true; + } + }; + public static class VolumeFilter implements AppFilter { private final String mVolumeUuid; @@ -1412,6 +1455,12 @@ public class ApplicationsState { mSecondFilter = second; } + @Override + public void init(Context context) { + mFirstFilter.init(context); + mSecondFilter.init(context); + } + @Override public void init() { mFirstFilter.init(); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 281f1db80104ae39de10a74cdc6302557045234c..52e686c9bce976eecfb27b1a1aa3542a489f33fd 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -803,7 +803,9 @@ public final class CachedBluetoothDevice implements Comparable + * The change will be applied to the user specified by the value of + * {@link UserHandle#myUserId()} at the time the method is called. * * @param displayId the identifier of the display to modify */ public static void clearForcedDisplayDensity(final int displayId) { - AsyncTask.execute(new Runnable() { - @Override - public void run() { - try { - final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - wm.clearForcedDisplayDensity(displayId); - } catch (RemoteException exc) { - Log.w(LOG_TAG, "Unable to clear forced display density setting"); - } + final int userId = UserHandle.myUserId(); + AsyncTask.execute(() -> { + try { + final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + wm.clearForcedDisplayDensityForUser(displayId, userId); + } catch (RemoteException exc) { + Log.w(LOG_TAG, "Unable to clear forced display density setting"); } }); } /** * Asynchronously applies display density changes to the specified display. + *

        + * The change will be applied to the user specified by the value of + * {@link UserHandle#myUserId()} at the time the method is called. * * @param displayId the identifier of the display to modify * @param density the density to force for the specified display */ public static void setForcedDisplayDensity(final int displayId, final int density) { - AsyncTask.execute(new Runnable() { - @Override - public void run() { - try { - final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); - wm.setForcedDisplayDensity(displayId, density); - } catch (RemoteException exc) { - Log.w(LOG_TAG, "Unable to save forced display density setting"); - } + final int userId = UserHandle.myUserId(); + AsyncTask.execute(() -> { + try { + final IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); + wm.setForcedDisplayDensityForUser(displayId, density, userId); + } catch (RemoteException exc) { + Log.w(LOG_TAG, "Unable to save forced display density setting"); } }); } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java index 37e3c531229a888352af3e907ea4d49ab44012f9..e6e0243c53e177ad47df4a90a7872faebe1cac0c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java @@ -28,8 +28,11 @@ import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.os.AsyncTask; import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.support.v4.widget.DrawerLayout; +import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Pair; @@ -41,8 +44,10 @@ import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.widget.AdapterView; +import android.widget.FrameLayout; import android.widget.ListView; import android.widget.Toolbar; + import com.android.settingslib.R; import com.android.settingslib.applications.InterestingConfigChanges; @@ -54,6 +59,7 @@ public class SettingsDrawerActivity extends Activity { protected static final boolean DEBUG_TIMING = false; private static final String TAG = "SettingsDrawerActivity"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final String EXTRA_SHOW_MENU = "show_drawer_menu"; @@ -68,8 +74,10 @@ public class SettingsDrawerActivity extends Activity { private final List mCategoryListeners = new ArrayList<>(); private SettingsDrawerAdapter mDrawerAdapter; + private FrameLayout mContentHeaderContainer; private DrawerLayout mDrawerLayout; private boolean mShowingMenu; + private UserManager mUserManager; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -84,6 +92,7 @@ public class SettingsDrawerActivity extends Activity { requestWindowFeature(Window.FEATURE_NO_TITLE); } super.setContentView(R.layout.settings_with_drawer); + mContentHeaderContainer = (FrameLayout) findViewById(R.id.content_header_container); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); if (mDrawerLayout == null) { return; @@ -104,8 +113,10 @@ public class SettingsDrawerActivity extends Activity { public void onItemClick(android.widget.AdapterView parent, View view, int position, long id) { onTileClicked(mDrawerAdapter.getTile(position)); - }; + } }); + + mUserManager = UserManager.get(this); if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms"); } @@ -134,8 +145,16 @@ public class SettingsDrawerActivity extends Activity { new CategoriesUpdater().execute(); } - if (getIntent() != null && getIntent().getBooleanExtra(EXTRA_SHOW_MENU, false)) { - showMenuIcon(); + final Intent intent = getIntent(); + if (intent != null) { + if (intent.hasExtra(EXTRA_SHOW_MENU)) { + if (intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) { + // Intent explicitly set to show menu. + showMenuIcon(); + } + } else if (isTopLevelTile(intent)) { + showMenuIcon(); + } } } @@ -148,6 +167,30 @@ public class SettingsDrawerActivity extends Activity { super.onPause(); } + private boolean isTopLevelTile(Intent intent) { + final ComponentName componentName = intent.getComponent(); + if (componentName == null) { + return false; + } + // Look for a tile that has the same component as incoming intent + final List categories = getDashboardCategories(); + for (DashboardCategory category : categories) { + for (Tile tile : category.tiles) { + if (TextUtils.equals(tile.intent.getComponent().getClassName(), + componentName.getClassName())) { + if (DEBUG) { + Log.d(TAG, "intent is for top level tile: " + tile.title); + } + return true; + } + } + } + if (DEBUG) { + Log.d(TAG, "Intent is not for top level settings " + intent); + } + return false; + } + public void addCategoryListener(CategoryListener listener) { mCategoryListeners.add(listener); } @@ -180,6 +223,13 @@ public class SettingsDrawerActivity extends Activity { } } + public void setContentHeaderView(View headerView) { + mContentHeaderContainer.removeAllViews(); + if (headerView != null) { + mContentHeaderContainer.addView(headerView); + } + } + @Override public void setContentView(@LayoutRes int layoutResID) { final ViewGroup parent = (ViewGroup) findViewById(R.id.content_frame); @@ -215,6 +265,7 @@ public class SettingsDrawerActivity extends Activity { public void showMenuIcon() { mShowingMenu = true; getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu); + getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button); getActionBar().setDisplayHomeAsUpEnabled(true); } @@ -245,6 +296,7 @@ public class SettingsDrawerActivity extends Activity { return true; } try { + updateUserHandlesIfNeeded(tile); int numUserHandles = tile.userHandle.size(); if (numUserHandles > 1) { ProfileSelectDialog.show(getFragmentManager(), tile); @@ -266,12 +318,32 @@ public class SettingsDrawerActivity extends Activity { return true; } + private void updateUserHandlesIfNeeded(Tile tile) { + List userHandles = tile.userHandle; + + for (int i = userHandles.size() - 1; i >= 0; i--) { + if (mUserManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) { + if (DEBUG) { + Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier()); + } + userHandles.remove(i); + } + } + } + protected void onTileClicked(Tile tile) { if (openTile(tile)) { finish(); } } + public HashMap, Tile> getTileCache() { + if (sTileCache == null) { + getDashboardCategories(); + } + return sTileCache; + } + public void onProfileTileOpen() { finish(); } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index 994f038c941858f0b38772498ab1054ccd762837..4f986e1ce2271bf21a45447ad6eb7c9fe545c1e4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -27,6 +27,7 @@ import android.graphics.drawable.Icon; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings.Global; import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -115,6 +116,8 @@ public class TileUtils { public static List getCategories(Context context, HashMap, Tile> cache) { final long startTime = System.currentTimeMillis(); + boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) + != 0; ArrayList tiles = new ArrayList<>(); UserManager userManager = UserManager.get(context); for (UserHandle user : userManager.getUserProfiles()) { @@ -127,7 +130,9 @@ public class TileUtils { getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache, MANUFACTURER_DEFAULT_CATEGORY, tiles, false, true); } - getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false); + if (setup) { + getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false); + } } HashMap categoryMap = new HashMap<>(); for (Tile tile : tiles) { @@ -310,7 +315,7 @@ public class TileUtils { return false; } - private static final Comparator TILE_COMPARATOR = + public static final Comparator TILE_COMPARATOR = new Comparator() { @Override public int compare(Tile lhs, Tile rhs) { diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java index ee1821dc6bbe528ab117eb8ad96a61fe6923b520..c6a45bcf1e9f4446e664f5ae33244c607bf60cd6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java +++ b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java @@ -71,10 +71,11 @@ public class UsageView extends FrameLayout { layout.addView(labels); // Set gravity. labels.setGravity(Gravity.END); - // Swap the bottom label padding + // Swap the bottom space order. LinearLayout bottomLabels = (LinearLayout) findViewById(R.id.bottom_label_group); - bottomLabels.setPadding(bottomLabels.getPaddingRight(), bottomLabels.getPaddingTop(), - bottomLabels.getPaddingLeft(), bottomLabels.getPaddingBottom()); + View bottomSpace = bottomLabels.findViewById(R.id.bottom_label_space); + bottomLabels.removeView(bottomSpace); + bottomLabels.addView(bottomSpace); } else if (gravity != Gravity.START) { throw new IllegalArgumentException("Unsupported gravity " + gravity); } diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index e53dd2f42c75d0a5705b5b2af477a5fd50e67acc..994ea88a80dda5f80f53f5ecf6fd7d7cbda86920 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -32,6 +32,8 @@ import android.text.format.DateUtils; import android.text.format.Time; import android.util.Log; +import com.android.settingslib.R; + import java.util.Date; import java.util.Locale; @@ -41,12 +43,12 @@ import static android.net.NetworkStatsHistory.FIELD_TX_BYTES; import static android.telephony.TelephonyManager.SIM_STATE_READY; import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH; import static android.text.format.DateUtils.FORMAT_SHOW_DATE; +import static android.net.TrafficStats.MB_IN_BYTES; public class DataUsageController { + private static final String TAG = "DataUsageController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - public static final long DEFAULT_WARNING_LEVEL = 2L * 1024 * 1024 * 1024; private static final int FIELDS = FIELD_RX_BYTES | FIELD_TX_BYTES; private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50); private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter( @@ -75,6 +77,14 @@ public class DataUsageController { mNetworkController = networkController; } + /** + * Returns the default warning level in bytes. + */ + public long getDefaultWarningLevel() { + return MB_IN_BYTES + * mContext.getResources().getInteger(R.integer.default_data_warning_level_mb); + } + private INetworkStatsSession getSession() { if (mSession == null) { try { @@ -169,7 +179,7 @@ public class DataUsageController { usage.limitLevel = policy.limitBytes > 0 ? policy.limitBytes : 0; usage.warningLevel = policy.warningBytes > 0 ? policy.warningBytes : 0; } else { - usage.warningLevel = DEFAULT_WARNING_LEVEL; + usage.warningLevel = getDefaultWarningLevel(); } if (usage != null && mNetworkController != null) { usage.carrier = mNetworkController.getMobileDataNetworkName(); diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index 63d1b1ed961649b5966c843c2830b94145a4da73..3a16a75f26db7a394e807abbcbf84c22a09a69e3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -377,17 +377,18 @@ public class AccessPoint implements Comparable { } public String getSavedNetworkSummary() { - if (mConfig != null) { + WifiConfiguration config = mConfig; + if (config != null) { PackageManager pm = mContext.getPackageManager(); String systemName = pm.getNameForUid(android.os.Process.SYSTEM_UID); - int userId = UserHandle.getUserId(mConfig.creatorUid); + int userId = UserHandle.getUserId(config.creatorUid); ApplicationInfo appInfo = null; - if (mConfig.creatorName != null && mConfig.creatorName.equals(systemName)) { + if (config.creatorName != null && config.creatorName.equals(systemName)) { appInfo = mContext.getApplicationInfo(); } else { try { IPackageManager ipm = AppGlobals.getPackageManager(); - appInfo = ipm.getApplicationInfo(mConfig.creatorName, 0 /* flags */, userId); + appInfo = ipm.getApplicationInfo(config.creatorName, 0 /* flags */, userId); } catch (RemoteException rex) { } } @@ -402,29 +403,36 @@ public class AccessPoint implements Comparable { } public String getSummary() { - return getSettingsSummary(); + return getSettingsSummary(mConfig); } public String getSettingsSummary() { + return getSettingsSummary(mConfig); + } + + private String getSettingsSummary(WifiConfiguration config) { // Update to new summary StringBuilder summary = new StringBuilder(); - if (isActive() && mConfig != null && mConfig.isPasspoint()) { + if (isActive() && config != null && config.isPasspoint()) { // This is the active connection on passpoint summary.append(getSummary(mContext, getDetailedState(), - false, mConfig.providerFriendlyName)); + false, config.providerFriendlyName)); } else if (isActive()) { // This is the active connection on non-passpoint network summary.append(getSummary(mContext, getDetailedState(), mInfo != null && mInfo.isEphemeral())); - } else if (mConfig != null && mConfig.isPasspoint()) { + } else if (config != null && config.isPasspoint()) { String format = mContext.getString(R.string.available_via_passpoint); - summary.append(String.format(format, mConfig.providerFriendlyName)); - } else if (mConfig != null && mConfig.hasNoInternetAccess()) { - summary.append(mContext.getString(R.string.wifi_no_internet)); - } else if (mConfig != null && !mConfig.getNetworkSelectionStatus().isNetworkEnabled()) { + summary.append(String.format(format, config.providerFriendlyName)); + } else if (config != null && config.hasNoInternetAccess()) { + int messageID = config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled() + ? R.string.wifi_no_internet_no_reconnect + : R.string.wifi_no_internet; + summary.append(mContext.getString(messageID)); + } else if (config != null && !config.getNetworkSelectionStatus().isNetworkEnabled()) { WifiConfiguration.NetworkSelectionStatus networkStatus = - mConfig.getNetworkSelectionStatus(); + config.getNetworkSelectionStatus(); switch (networkStatus.getNetworkSelectionDisableReason()) { case WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE: summary.append(mContext.getString(R.string.wifi_disabled_password_failure)); @@ -440,7 +448,7 @@ public class AccessPoint implements Comparable { } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range summary.append(mContext.getString(R.string.wifi_not_in_range)); } else { // In range, not disabled. - if (mConfig != null) { // Is saved network + if (config != null) { // Is saved network summary.append(mContext.getString(R.string.wifi_remembered)); } } @@ -452,11 +460,11 @@ public class AccessPoint implements Comparable { summary.append(" f=" + Integer.toString(mInfo.getFrequency())); } summary.append(" " + getVisibilityStatus()); - if (mConfig != null && !mConfig.getNetworkSelectionStatus().isNetworkEnabled()) { - summary.append(" (" + mConfig.getNetworkSelectionStatus().getNetworkStatusString()); - if (mConfig.getNetworkSelectionStatus().getDisableTime() > 0) { + if (config != null && !config.getNetworkSelectionStatus().isNetworkEnabled()) { + summary.append(" (" + config.getNetworkSelectionStatus().getNetworkStatusString()); + if (config.getNetworkSelectionStatus().getDisableTime() > 0) { long now = System.currentTimeMillis(); - long diff = (now - mConfig.getNetworkSelectionStatus().getDisableTime()) / 1000; + long diff = (now - config.getNetworkSelectionStatus().getDisableTime()) / 1000; long sec = diff%60; //seconds long min = (diff/60)%60; //minutes long hour = (min/60)%60; //hours @@ -468,9 +476,9 @@ public class AccessPoint implements Comparable { summary.append(")"); } - if (mConfig != null) { + if (config != null) { WifiConfiguration.NetworkSelectionStatus networkStatus = - mConfig.getNetworkSelectionStatus(); + config.getNetworkSelectionStatus(); for (int index = WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE; index < WifiConfiguration.NetworkSelectionStatus .NETWORK_SELECTION_DISABLED_MAX; index++) { diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java index 284827b579295afcb40e946ec7b58af1ef8a26ae..aae9cf6de7978f8d71a3df4b662b1a1fa0de1cfe 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java @@ -29,7 +29,6 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.SparseArray; import android.widget.TextView; - import com.android.settingslib.R; public class AccessPointPreference extends Preference { @@ -44,13 +43,14 @@ public class AccessPointPreference extends Preference { private final StateListDrawable mWifiSld; private final int mBadgePadding; private final UserBadgeCache mBadgeCache; - private TextView mTitleView; + private boolean mForSavedNetworks = false; private AccessPoint mAccessPoint; private Drawable mBadge; private int mLevel; private CharSequence mContentDescription; + private int mDefaultIconResId; static final int[] WIFI_CONNECTION_STRENGTH = { R.string.accessibility_wifi_one_bar, @@ -85,6 +85,24 @@ public class AccessPointPreference extends Preference { refresh(); } + public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache, + int iconResId, boolean forSavedNetworks) { + super(context); + mBadgeCache = cache; + mAccessPoint = accessPoint; + mForSavedNetworks = forSavedNetworks; + mAccessPoint.setTag(this); + mLevel = -1; + mDefaultIconResId = iconResId; + + mWifiSld = (StateListDrawable) context.getTheme() + .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0); + + // Distance from the end of the title at which this AP's user badge should sit. + mBadgePadding = context.getResources() + .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding); + } + public AccessPoint getAccessPoint() { return mAccessPoint; } @@ -112,7 +130,7 @@ public class AccessPointPreference extends Preference { protected void updateIcon(int level, Context context) { if (level == -1) { - setIcon(null); + safeSetDefaultIcon(); } else { if (getIcon() == null) { // To avoid a drawing race condition, we first set the state (SECURE/NONE) and then @@ -124,16 +142,24 @@ public class AccessPointPreference extends Preference { ? STATE_SECURED : STATE_NONE); Drawable drawable = mWifiSld.getCurrent(); - if (!mForSavedNetworks) { + if (!mForSavedNetworks && drawable != null) { setIcon(drawable); - } else { - setIcon(null); + return; } } + safeSetDefaultIcon(); } } } + private void safeSetDefaultIcon() { + if (mDefaultIconResId != 0) { + setIcon(mDefaultIconResId); + } else { + setIcon(null); + } + } + protected void updateBadge(Context context) { WifiConfiguration config = mAccessPoint.getConfig(); if (config != null) { diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index f147a3b5c2640ef65b448bc2baa345150fed2bdf..f0878ab99b89376fcfd51aa8a08b8f5fa95b6b91 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -36,7 +36,7 @@ 100% true - false + true false false true @@ -154,7 +154,10 @@ -1 - 500 + 400 + + + 300 false diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 7338a9cb654bdf6d794818e1df9bab18c998910e..c1a1f844f6d9bc8aebe6c7384052854dc6c3589c 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -1483,7 +1483,6 @@ class DatabaseHelper extends SQLiteOpenHelper { Settings.Global.CALL_AUTO_RETRY, Settings.Global.DEBUG_APP, Settings.Global.WAIT_FOR_DEBUGGER, - Settings.Global.SHOW_PROCESSES, Settings.Global.ALWAYS_FINISH_ACTIVITIES, }; String[] secureToGlobal = { diff --git a/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags b/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags index 298d7768d01ffa9ddbc24f07d4d30a2eef63ab0b..7eff16b0def4c2f264cacf10f7a8c16722bf25a5 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags +++ b/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags @@ -1,5 +1,6 @@ -# See system/core/logcat/e for a description of the format of this file. +# See system/core/logcat/event.logtags for a description of the format of this file. option java_package com.android.providers.settings; 52100 unsupported_settings_query (uri|3),(selection|3),(whereArgs|3) +52101 persist_setting_error (message|3) diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index b79ce8027231802b711dbbf3ad7b271d9b3c5809..bf48e5de1da3204273239ea3f27b69b9c4708d2b 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -247,7 +247,6 @@ public class SettingsHelper { return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0; case Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES: case Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES: - case Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX: case Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER: case Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE: return !TextUtils.isEmpty(Settings.Secure.getString( diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 774be60d082a1d7950243586019579227245c9c6..e66e963c017948014c611a576831e056316515f1 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -114,7 +114,7 @@ import java.util.regex.Pattern; public class SettingsProvider extends ContentProvider { private static final boolean DEBUG = false; - private static final boolean DROP_DATABASE_ON_MIGRATION = !Build.IS_DEBUGGABLE; + private static final boolean DROP_DATABASE_ON_MIGRATION = true; private static final String LOG_TAG = "SettingsProvider"; @@ -544,7 +544,7 @@ public class SettingsProvider extends ContentProvider { final int userCount = users.size(); for (int i = 0; i < userCount; i++) { UserInfo user = users.get(i); - dumpForUser(user.id, pw); + dumpForUserLocked(user.id, pw); } } finally { Binder.restoreCallingIdentity(identity); @@ -552,12 +552,16 @@ public class SettingsProvider extends ContentProvider { } } - private void dumpForUser(int userId, PrintWriter pw) { + private void dumpForUserLocked(int userId, PrintWriter pw) { if (userId == UserHandle.USER_SYSTEM) { pw.println("GLOBAL SETTINGS (user " + userId + ")"); Cursor globalCursor = getAllGlobalSettings(ALL_COLUMNS); dumpSettings(globalCursor, pw); pw.println(); + + SettingsState globalSettings = mSettingsRegistry.getSettingsLocked( + SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); + globalSettings.dumpHistoricalOperations(pw); } pw.println("SECURE SETTINGS (user " + userId + ")"); @@ -565,10 +569,18 @@ public class SettingsProvider extends ContentProvider { dumpSettings(secureCursor, pw); pw.println(); + SettingsState secureSettings = mSettingsRegistry.getSettingsLocked( + SETTINGS_TYPE_SECURE, userId); + secureSettings.dumpHistoricalOperations(pw); + pw.println("SYSTEM SETTINGS (user " + userId + ")"); Cursor systemCursor = getAllSystemSettings(userId, ALL_COLUMNS); dumpSettings(systemCursor, pw); pw.println(); + + SettingsState systemSettings = mSettingsRegistry.getSettingsLocked( + SETTINGS_TYPE_SYSTEM, userId); + systemSettings.dumpHistoricalOperations(pw); } private void dumpSettings(Cursor cursor, PrintWriter pw) { @@ -799,7 +811,8 @@ public class SettingsProvider extends ContentProvider { // If this is a setting that is currently restricted for this user, do not allow // unrestricting changes. - if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) { + if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value, + Binder.getCallingUid())) { return false; } @@ -930,7 +943,8 @@ public class SettingsProvider extends ContentProvider { // If this is a setting that is currently restricted for this user, do not allow // unrestricting changes. - if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) { + if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value, + Binder.getCallingUid())) { return false; } @@ -1153,7 +1167,7 @@ public class SettingsProvider extends ContentProvider { * @return true if the change is prohibited, false if the change is allowed. */ private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId, - String value) { + String value, int callingUid) { String restriction; switch (setting) { case Settings.Secure.LOCATION_MODE: @@ -1191,6 +1205,20 @@ public class SettingsProvider extends ContentProvider { restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS; break; + case Settings.Secure.ALWAYS_ON_VPN_APP: + case Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN: + // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn + if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) { + return false; + } + restriction = UserManager.DISALLOW_CONFIG_VPN; + break; + + case Settings.Global.SAFE_BOOT_DISALLOWED: + if ("1".equals(value)) return false; + restriction = UserManager.DISALLOW_SAFE_BOOT; + break; + default: if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) { if ("0".equals(value)) return false; @@ -2074,7 +2102,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 127; + private static final int SETTINGS_VERSION = 131; private final int mUserId; @@ -2114,6 +2142,12 @@ public class SettingsProvider extends ContentProvider { // Now upgrade should work fine. onUpgradeLocked(mUserId, oldVersion, newVersion); + + // Make a note what happened, so we don't wonder why data was lost + String reason = "Settings rebuilt! Current version: " + + curVersion + " while expected: " + newVersion; + getGlobalSettingsLocked().insertSettingLocked( + Settings.Global.DATABASE_DOWNGRADE_REASON, reason, "android"); } // Set the global settings version if owner. @@ -2329,6 +2363,84 @@ public class SettingsProvider extends ContentProvider { currentVersion = 127; } + if (currentVersion == 127) { + // version 127 is no longer used. + currentVersion = 128; + } + + if (currentVersion == 128) { + // Version 128: Allow OEMs to grant DND access to default apps. Note that + // the new apps are appended to the list of already approved apps. + final SettingsState systemSecureSettings = + getSecureSettingsLocked(userId); + + final Setting policyAccess = systemSecureSettings.getSettingLocked( + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES); + String defaultPolicyAccess = getContext().getResources().getString( + com.android.internal.R.string.config_defaultDndAccessPackages); + if (!TextUtils.isEmpty(defaultPolicyAccess)) { + if (policyAccess.isNull()) { + systemSecureSettings.insertSettingLocked( + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES, + defaultPolicyAccess, + SettingsState.SYSTEM_PACKAGE_NAME); + } else { + StringBuilder currentSetting = + new StringBuilder(policyAccess.getValue()); + currentSetting.append(":"); + currentSetting.append(defaultPolicyAccess); + systemSecureSettings.updateSettingLocked( + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES, + currentSetting.toString(), + SettingsState.SYSTEM_PACKAGE_NAME); + } + } + + currentVersion = 129; + } + + if (currentVersion == 129) { + // default longpress timeout changed from 500 to 400. If unchanged from the old + // default, update to the new default. + final SettingsState systemSecureSettings = + getSecureSettingsLocked(userId); + final String oldValue = systemSecureSettings.getSettingLocked( + Settings.Secure.LONG_PRESS_TIMEOUT).getValue(); + if (TextUtils.equals("500", oldValue)) { + systemSecureSettings.insertSettingLocked( + Settings.Secure.LONG_PRESS_TIMEOUT, + String.valueOf(getContext().getResources().getInteger( + R.integer.def_long_press_timeout_millis)), + SettingsState.SYSTEM_PACKAGE_NAME); + } + currentVersion = 130; + } + + if (currentVersion == 130) { + // Initialize new multi-press timeout to default value + final SettingsState systemSecureSettings = getSecureSettingsLocked(userId); + final String oldValue = systemSecureSettings.getSettingLocked( + Settings.Secure.MULTI_PRESS_TIMEOUT).getValue(); + if (TextUtils.equals(null, oldValue)) { + systemSecureSettings.insertSettingLocked( + Settings.Secure.MULTI_PRESS_TIMEOUT, + String.valueOf(getContext().getResources().getInteger( + R.integer.def_multi_press_timeout_millis)), + SettingsState.SYSTEM_PACKAGE_NAME); + } + + currentVersion = 131; + } + + if (currentVersion != newVersion) { + Slog.wtf("SettingsProvider", "warning: upgrading settings database to version " + + newVersion + " left it at " + + currentVersion + " instead; this is probably a bug", new Throwable()); + if (DEBUG) { + throw new RuntimeException("db upgrade error"); + } + } + // vXXX: Add new settings above this point. // Return the current version. diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java index 2167b76ae490f21d625ffe3ed03e02ebc10fab2d..832c9d95cc606ddeda1973404280b309eea7137c 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java @@ -16,6 +16,7 @@ package com.android.providers.settings; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -26,6 +27,7 @@ import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Base64; import android.util.Slog; +import android.util.TimeUtils; import android.util.Xml; import com.android.internal.annotations.GuardedBy; import libcore.io.IoUtils; @@ -39,6 +41,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -60,7 +63,7 @@ final class SettingsState { private static final String LOG_TAG = "SettingsState"; - static final int SETTINGS_VERSOIN_NEW_ENCODING = 121; + static final int SETTINGS_VERSION_NEW_ENCODING = 121; private static final long WRITE_SETTINGS_DELAY_MILLIS = 200; private static final long MAX_WRITE_SETTINGS_DELAY_MILLIS = 2000; @@ -93,6 +96,12 @@ final class SettingsState { // This was used in version 120 and before. private static final String NULL_VALUE_OLD_STYLE = "null"; + private static final int HISTORICAL_OPERATION_COUNT = 20; + private static final String HISTORICAL_OPERATION_UPDATE = "update"; + private static final String HISTORICAL_OPERATION_DELETE = "delete"; + private static final String HISTORICAL_OPERATION_PERSIST = "persist"; + private static final String HISTORICAL_OPERATION_INITIALIZE = "initialize"; + private final Object mLock; private final Handler mHandler; @@ -116,6 +125,9 @@ final class SettingsState { } }; + @GuardedBy("mLock") + private final List mHistoricalOperations; + @GuardedBy("mLock") public final int mKey; @@ -134,6 +146,9 @@ final class SettingsState { @GuardedBy("mLock") private long mNextId; + @GuardedBy("mLock") + private int mNextHistoricalOpIdx; + public SettingsState(Object lock, File file, int key, int maxBytesPerAppPackage, Looper looper) { // It is important that we use the same lock as the settings provider @@ -150,6 +165,10 @@ final class SettingsState { mMaxBytesPerAppPackage = maxBytesPerAppPackage; mPackageToMemoryUsage = null; } + + mHistoricalOperations = Build.IS_DEBUGGABLE + ? new ArrayList<>(HISTORICAL_OPERATION_COUNT) : null; + synchronized (mLock) { readStateSyncLocked(); } @@ -238,16 +257,20 @@ final class SettingsState { Setting oldState = mSettings.get(name); String oldValue = (oldState != null) ? oldState.value : null; + Setting newState; if (oldState != null) { if (!oldState.update(value, packageName)) { return false; } + newState = oldState; } else { - Setting state = new Setting(name, value, packageName); - mSettings.put(name, state); + newState = new Setting(name, value, packageName); + mSettings.put(name, newState); } + addHistoricalOperationLocked(HISTORICAL_OPERATION_UPDATE, newState); + updateMemoryUsagePerPackageLocked(packageName, oldValue, value); scheduleWriteIfNeededLocked(); @@ -271,6 +294,8 @@ final class SettingsState { updateMemoryUsagePerPackageLocked(oldState.packageName, oldState.value, null); + addHistoricalOperationLocked(HISTORICAL_OPERATION_DELETE, oldState); + scheduleWriteIfNeededLocked(); return true; @@ -290,6 +315,51 @@ final class SettingsState { } } + private void addHistoricalOperationLocked(String type, Setting setting) { + if (mHistoricalOperations == null) { + return; + } + HistoricalOperation operation = new HistoricalOperation( + SystemClock.elapsedRealtime(), type, + setting != null ? new Setting(setting) : null); + if (mNextHistoricalOpIdx >= mHistoricalOperations.size()) { + mHistoricalOperations.add(operation); + } else { + mHistoricalOperations.set(mNextHistoricalOpIdx, operation); + } + mNextHistoricalOpIdx++; + if (mNextHistoricalOpIdx >= HISTORICAL_OPERATION_COUNT) { + mNextHistoricalOpIdx = 0; + } + } + + public void dumpHistoricalOperations(PrintWriter pw) { + synchronized (mLock) { + if (mHistoricalOperations == null) { + return; + } + pw.println("Historical operations"); + final int operationCount = mHistoricalOperations.size(); + for (int i = 0; i < operationCount; i++) { + int index = mNextHistoricalOpIdx - 1 - i; + if (index < 0) { + index = operationCount + index; + } + HistoricalOperation operation = mHistoricalOperations.get(index); + pw.print(TimeUtils.formatForLogging(operation.mTimestamp)); + pw.print(" "); + pw.print(operation.mOperation); + if (operation.mSetting != null) { + pw.print(" "); + pw.print(operation.mSetting); + } + pw.println(); + } + pw.println(); + pw.println(); + } + } + private void updateMemoryUsagePerPackageLocked(String packageName, String oldValue, String newValue) { if (mMaxBytesPerAppPackage == MAX_BYTES_PER_APP_PACKAGE_UNLIMITED) { @@ -407,6 +477,10 @@ final class SettingsState { serializer.endDocument(); destination.finishWrite(out); + synchronized (mLock) { + addHistoricalOperationLocked(HISTORICAL_OPERATION_PERSIST, null); + } + if (DEBUG_PERSISTENCE) { Slog.i(LOG_TAG, "[PERSIST END]"); } @@ -435,7 +509,7 @@ final class SettingsState { static void setValueAttribute(int version, XmlSerializer serializer, String value) throws IOException { - if (version >= SETTINGS_VERSOIN_NEW_ENCODING) { + if (version >= SETTINGS_VERSION_NEW_ENCODING) { if (value == null) { // Null value -> No ATTR_VALUE nor ATTR_VALUE_BASE64. } else if (isBinary(value)) { @@ -454,7 +528,7 @@ final class SettingsState { } private String getValueAttribute(XmlPullParser parser) { - if (mVersion >= SETTINGS_VERSOIN_NEW_ENCODING) { + if (mVersion >= SETTINGS_VERSION_NEW_ENCODING) { final String value = parser.getAttributeValue(null, ATTR_VALUE); if (value != null) { return value; @@ -479,22 +553,26 @@ final class SettingsState { private void readStateSyncLocked() { FileInputStream in; if (!mStatePersistFile.exists()) { + Slog.i(LOG_TAG, "No settings state " + mStatePersistFile); + addHistoricalOperationLocked(HISTORICAL_OPERATION_INITIALIZE, null); return; } try { in = new AtomicFile(mStatePersistFile).openRead(); } catch (FileNotFoundException fnfe) { - Slog.i(LOG_TAG, "No settings state"); + String message = "No settings state " + mStatePersistFile; + Slog.wtf(LOG_TAG, message); + Slog.i(LOG_TAG, message); return; } try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(in, StandardCharsets.UTF_8.name()); parseStateLocked(parser); - } catch (XmlPullParserException | IOException e) { - throw new IllegalStateException("Failed parsing settings file: " - + mStatePersistFile , e); + String message = "Failed parsing settings file: " + mStatePersistFile; + Slog.wtf(LOG_TAG, message); + throw new IllegalStateException(message , e); } finally { IoUtils.closeQuietly(in); } @@ -567,6 +645,19 @@ final class SettingsState { } } + private class HistoricalOperation { + final long mTimestamp; + final String mOperation; + final Setting mSetting; + + public HistoricalOperation(long timestamp, + String operation, Setting setting) { + mTimestamp = timestamp; + mOperation = operation; + mSetting = setting; + } + } + class Setting { private String name; private String value; @@ -629,6 +720,10 @@ final class SettingsState { this.id = String.valueOf(mNextId++); return true; } + + public String toString() { + return "Setting{name=" + value + " from " + packageName + "}"; + } } /** diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java index b5bd8ad3073d9213297ef0d6d3e3b2da19e59d94..9964467fb5ecaaa830e595d619ee6eb2474cb494 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java @@ -15,7 +15,6 @@ */ package com.android.providers.settings; -import android.os.Handler; import android.os.Looper; import android.test.AndroidTestCase; import android.util.Xml; @@ -99,10 +98,10 @@ public class SettingsStateTest extends AndroidTestCase { checkWriteSingleSetting(serializer, null, null); checkWriteSingleSetting(serializer, CRAZY_STRING, null); SettingsState.writeSingleSetting( - SettingsState.SETTINGS_VERSOIN_NEW_ENCODING, + SettingsState.SETTINGS_VERSION_NEW_ENCODING, serializer, null, "k", "v", "package"); SettingsState.writeSingleSetting( - SettingsState.SETTINGS_VERSOIN_NEW_ENCODING, + SettingsState.SETTINGS_VERSION_NEW_ENCODING, serializer, "1", "k", "v", null); } @@ -115,7 +114,7 @@ public class SettingsStateTest extends AndroidTestCase { String key, String value) throws Exception { // Make sure the XML serializer won't crash. SettingsState.writeSingleSetting( - SettingsState.SETTINGS_VERSOIN_NEW_ENCODING, + SettingsState.SETTINGS_VERSION_NEW_ENCODING, serializer, "1", key, value, "package"); } @@ -129,7 +128,7 @@ public class SettingsStateTest extends AndroidTestCase { final SettingsState ssWriter = new SettingsState(lock, file, 1, SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED, Looper.getMainLooper()); - ssWriter.setVersionLocked(SettingsState.SETTINGS_VERSOIN_NEW_ENCODING); + ssWriter.setVersionLocked(SettingsState.SETTINGS_VERSION_NEW_ENCODING); ssWriter.insertSettingLocked("k1", "\u0000", "package"); ssWriter.insertSettingLocked("k2", "abc", "p2"); diff --git a/packages/Shell/Android.mk b/packages/Shell/Android.mk index 73a044951bd50f4581e92438d95b9edb5d3725d6..81ab2ffc2a232a62c21fb57d86a836e3b8c7ceaf 100644 --- a/packages/Shell/Android.mk +++ b/packages/Shell/Android.mk @@ -12,6 +12,8 @@ LOCAL_PACKAGE_NAME := Shell LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true +LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.shell.* + include $(BUILD_PACKAGE) include $(LOCAL_PATH)/tests/Android.mk diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 2efefb3bc1aac82c19c030d102e6e184b1d30c7d..227d0e944e6ea57897d89703eb18f8b98e185095 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -114,6 +114,8 @@ + + diff --git a/packages/Shell/res/layout/confirm_repeat.xml b/packages/Shell/res/layout/confirm_repeat.xml index ad90af186c059aa3e20a358b3b9d77d175c9b10e..9f1d53e7799ab2f19fb82ecadd6a61e35a497700 100644 --- a/packages/Shell/res/layout/confirm_repeat.xml +++ b/packages/Shell/res/layout/confirm_repeat.xml @@ -18,10 +18,10 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="16dip" - android:paddingEnd="16dip" - android:paddingTop="8dip" - android:paddingBottom="16dip" + android:paddingStart="24dip" + android:paddingEnd="24dip" + android:paddingTop="24dip" + android:paddingBottom="8dip" android:orientation="vertical" android:keepScreenOn="true"> "Foutverslag #%d is vasgevang" "Voeg tans besonderhede by die foutverslag" "Wag asseblief …" - "Swiep na links om jou foutverslag te deel" + "Die foutverslag sal binnekort op die foon verskyn" "Tik om jou foutverslag te deel" "Tik om jou foutverslag sonder \'n skermkiekie te deel, of wag totdat die skermkiekie gereed is" "Tik om jou foutverslag sonder \'n skermkiekie te deel, of wag totdat die skermkiekie gereed is" diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml index f04e882f46099fd174675b6c718b039b2c6f95b9..dccf9dde56433a3986d8c043bc6f969c08d5b56e 100644 --- a/packages/Shell/res/values-am/strings.xml +++ b/packages/Shell/res/values-am/strings.xml @@ -21,7 +21,7 @@ "የሳንካ ሪፖርት #%d ተወስዷል" "ዝርዝሮችን ወደ የሳንካ ሪፖርቱ በማከል ላይ" "እባክዎ ይጠብቁ…" - "የሳንካ ሪፖርትዎን ለማጋራት ወደ ግራ ያንሸራትቱ" + "የሳንካ ሪፖርቱ ከትንሽ ጊዜ በኋላ በስልኩ ላይ ይመጣል" "የሳንካ ሪፖርትዎን ለማጋራት መታ ያድርጉ" "የእርስዎን የሳንካ ሪፖርት ያለ ቅጽበታዊ ማያ ገጽ ለማጋራት መታ ያድርጉ ወይም ቅጽበታዊ ማያ ገጹ እስኪጨርስ ይጠብቁ" "የእርስዎን የሳንካ ሪፖርት ያለ ቅጽበታዊ ማያ ገጽ ለማጋራት መታ ያድርጉ ወይም ቅጽበታዊ ማያ ገጹ እስኪጨርስ ይጠብቁ" diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml index 37516a1c8a4e10f186fa4331c8d2ce043261d172..d2e3cc581750387e3f216f829232184fcfeed595 100644 --- a/packages/Shell/res/values-ar/strings.xml +++ b/packages/Shell/res/values-ar/strings.xml @@ -21,7 +21,7 @@ "تم تسجيل تقرير الخطأ #%d." "إضافة تفاصيل إلى تقرير الخطأ" "الرجاء الانتظار…" - "مرر بسرعة لليمين لمشاركة تقرير الخطأ" + "سيظهر تقرير الخطأ على الهاتف بعد قليل" "انقر لمشاركة تقرير الخطأ." "انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة" "انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة" diff --git a/packages/Shell/res/values-az-rAZ/strings.xml b/packages/Shell/res/values-az-rAZ/strings.xml index 303467bf62e6845ce5addefd5a80ea69c431eb24..9e6c84b194a1ea9b4248be944bfa7394015f7721 100644 --- a/packages/Shell/res/values-az-rAZ/strings.xml +++ b/packages/Shell/res/values-az-rAZ/strings.xml @@ -21,7 +21,7 @@ "Baq hesabatı #%d alındı" "Detallar baq hesabatına əlavə olunur" "Lütfən, gözləyin..." - "Baq raportunu paylaşmaq üçün sola sürüşdürün" + "Baq həlli tezliklə telefonda görünəcək" "Baq hesabatınızı paylaşmaq üçün tıklayın" "baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin" "baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin" diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml index 0787900a86aba81e982f01cf0cafdaea3bd9849a..ed8caaf39cccc4642b47f7b6442f6ed1e563cdf2 100644 --- a/packages/Shell/res/values-bg/strings.xml +++ b/packages/Shell/res/values-bg/strings.xml @@ -21,7 +21,7 @@ "Сигналът за програмна грешка „#%d“ е заснет" "Подробностите се добавят към сигнала за пр. грешка" "Моля, изчакайте…" - "Прекарайте пръст наляво, за да споделите сигнала си за програмна грешка" + "Сигналът за програмна грешка скоро ще се покаже на телефона" "Докоснете, за да споделите сигнала си за програмна грешка" "Докоснете, за да споделите сигнала за прогр. грешка без екранна снимка, или изчакайте завършването й" "Докоснете, за да споделите сигнала за прогр. грешка без екранна снимка, или изчакайте завършването й" diff --git a/packages/Shell/res/values-bn-rBD/strings.xml b/packages/Shell/res/values-bn-rBD/strings.xml index a51950a712fdc40c7a905df3f5a82684783ca646..b7d550c37fd9d38b329cfce9433d5acb1cc268aa 100644 --- a/packages/Shell/res/values-bn-rBD/strings.xml +++ b/packages/Shell/res/values-bn-rBD/strings.xml @@ -21,7 +21,7 @@ "ত্রুটির প্রতিবেদন #%d ক্যাপচার করা হয়েছে" "ত্রুটির প্রতিবেদনে বিশদ বিবরণ যোগ করা হচ্ছে" "অনুগ্রহ করে অপেক্ষা করুন..." - "আপনার বাগ রিপোর্ট শেয়ার করতে বামে সোয়াইপ করুন" + "ফোনে শীঘ্রই ত্রুটির প্রতিবেদন দেখা যাবে" "আপনার ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন" "কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন" "কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন" diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml index f8ed8133a48bd3216a7cd4e181d00618fe638b1e..d570a5449917f48cbd307deb3529d844765e7132 100644 --- a/packages/Shell/res/values-ca/strings.xml +++ b/packages/Shell/res/values-ca/strings.xml @@ -21,7 +21,7 @@ "S\'ha capturat l\'informe d\'errors #%d" "S\'estan afegint detalls a l\'informe d\'errors" "Espera…" - "Llisca cap a l\'esquerra per compartir l\'informe d\'errors." + "L\'informe d\'errors es mostrarà al telèfon aviat" "Toca per compartir l\'informe d\'errors" "Toca per compartir l\'informe d\'errors sense captura de pantalla o espera que es creï la captura" "Toca per compartir l\'informe d\'errors sense captura de pantalla o espera que es creï la captura" diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml index 4e41b79b56d1954fc4784a91720475b5e91c36fe..f05a9ba9c309c214c159125938e38fab476139ea 100644 --- a/packages/Shell/res/values-cs/strings.xml +++ b/packages/Shell/res/values-cs/strings.xml @@ -21,7 +21,7 @@ "Zpráva o chybě #%d byla vytvořena" "Přidávání podrobností do zprávy o chybě" "Čekejte prosím…" - "Chcete-li hlášení chyby sdílet, přejeďte doleva." + "Na telefonu se brzy zobrazí zpráva o chybě." "Zprávu o chybě můžete sdílet klepnutím" "Klepnutím můžete zprávu o chybě sdílet bez snímku obrazovky, nebo vyčkejte, než se snímek připraví" "Klepnutím můžete zprávu o chybě sdílet bez snímku obrazovky, nebo vyčkejte, než se snímek připraví" diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml index 19e800bf82a5f8b57ee853438c2d973e7f562ddf..3675eebd6b40aa106d85c1121cf14c4dc0ad1ac3 100644 --- a/packages/Shell/res/values-da/strings.xml +++ b/packages/Shell/res/values-da/strings.xml @@ -21,7 +21,7 @@ "Fejrapporten #%d blev gemt" "Tilføjelse af oplysninger til fejlrapporten" "Vent et øjeblik…" - "Stryg til venstre for at dele din fejlrapport" + "Fejlrapporten vises på telefonen om et øjeblik" "Tryk for at dele din fejlrapport" "Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres" "Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres" diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml index 023582408c882b3b498f67a65ef79a9e8afe85d4..543ccddbc525ee37dd39777a1a7fc1375b60aa0e 100644 --- a/packages/Shell/res/values-de/strings.xml +++ b/packages/Shell/res/values-de/strings.xml @@ -21,7 +21,7 @@ "Fehlerbericht #%d erfasst" "Informationen werden zum Fehlerbericht hinzugefügt" "Bitte warten…" - "Wische nach links, um deinen Fehlerbericht zu teilen." + "Der Fehlerbericht wird in Kürze auf dem Smartphone angezeigt" "Zum Teilen des Fehlerberichts tippen" "Tippe, um den Fehlerbericht ohne Screenshot zu teilen, oder warte auf den Screenshot" "Tippe, um den Fehlerbericht ohne Screenshot zu teilen, oder warte auf den Screenshot" diff --git a/packages/Shell/res/values-el/strings.xml b/packages/Shell/res/values-el/strings.xml index 4bed10c74e9b77227940b0e14db187ca58ae5154..a0222d8e8a5f2e704fb879679634e734818d7ec0 100644 --- a/packages/Shell/res/values-el/strings.xml +++ b/packages/Shell/res/values-el/strings.xml @@ -21,7 +21,7 @@ "Έγινε λήψη της αναφοράς σφάλματος #%d" "Προσθήκη λεπτομερειών στην αναφορά σφάλματος" "Περιμένετε…" - "Σύρετε προς τα αριστερά για κοινή χρήση της αναφοράς σφαλμάτων" + "Η αναφορά σφαλμάτων θα εμφανιστεί σύντομα στο τηλέφωνο" "Πατήστε για κοινή χρήση της αναφοράς σφάλματος" "Πατήστε για κοινοποίηση της αναφοράς σφάλματος χωρίς στιγμιότυπο οθόνης ή περιμένετε να ολοκληρωθεί" "Πατήστε για κοινοποίηση της αναφοράς σφάλματος χωρίς στιγμιότυπο οθόνης ή περιμένετε να ολοκληρωθεί" diff --git a/packages/Shell/res/values-en-rAU/strings.xml b/packages/Shell/res/values-en-rAU/strings.xml index 15b587b657647db29f0f4d22d64bcfe31924a031..55cfd60e98adcd708ac289f68f84b9c18e3bce64 100644 --- a/packages/Shell/res/values-en-rAU/strings.xml +++ b/packages/Shell/res/values-en-rAU/strings.xml @@ -21,7 +21,7 @@ "Bug report #%d captured" "Adding details to the bug report" "Please wait…" - "Swipe left to share your bug report" + "The bug report will appear on the phone shortly" "Tap to share your bug report" "Tap to share your bug report without a screenshot or wait for the screenshot to finish" "Tap to share your bug report without a screenshot or wait for the screenshot to finish" diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml index 15b587b657647db29f0f4d22d64bcfe31924a031..55cfd60e98adcd708ac289f68f84b9c18e3bce64 100644 --- a/packages/Shell/res/values-en-rGB/strings.xml +++ b/packages/Shell/res/values-en-rGB/strings.xml @@ -21,7 +21,7 @@ "Bug report #%d captured" "Adding details to the bug report" "Please wait…" - "Swipe left to share your bug report" + "The bug report will appear on the phone shortly" "Tap to share your bug report" "Tap to share your bug report without a screenshot or wait for the screenshot to finish" "Tap to share your bug report without a screenshot or wait for the screenshot to finish" diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml index 15b587b657647db29f0f4d22d64bcfe31924a031..55cfd60e98adcd708ac289f68f84b9c18e3bce64 100644 --- a/packages/Shell/res/values-en-rIN/strings.xml +++ b/packages/Shell/res/values-en-rIN/strings.xml @@ -21,7 +21,7 @@ "Bug report #%d captured" "Adding details to the bug report" "Please wait…" - "Swipe left to share your bug report" + "The bug report will appear on the phone shortly" "Tap to share your bug report" "Tap to share your bug report without a screenshot or wait for the screenshot to finish" "Tap to share your bug report without a screenshot or wait for the screenshot to finish" diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml index b7398dbb15460e6447a27009d8c7936890f5b2a6..dac7fdba7eb3daf4db5deb764fb33dd291bea04f 100644 --- a/packages/Shell/res/values-es-rUS/strings.xml +++ b/packages/Shell/res/values-es-rUS/strings.xml @@ -21,7 +21,7 @@ "Se capturó el informe de errores #%d" "Agregando detalles al informe de errores" "Espera…" - "Desliza el dedo hacia la izquierda para compartir el informe de errores." + "El informe de errores aparecerá en el teléfono en breve" "Toca para compartir el informe de errores" "Toca para compartir tu informe de errores sin una captura de pantalla o espera a que finalice" "Toca para compartir tu informe de errores sin una captura de pantalla o espera a que finalice" diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml index 81d8078aa424378db55c03b84f14f5a9f58b87c7..b090b8a3e9e051a4b63d2fe1344aecbf8a3ca6d4 100644 --- a/packages/Shell/res/values-es/strings.xml +++ b/packages/Shell/res/values-es/strings.xml @@ -21,7 +21,7 @@ "Informe de errores #%d capturado" "Añadiendo detalles al informe de errores" "Espera…" - "Desliza el dedo hacia la izquierda para compartir el informe de error" + "El informe de errores aparecerá en el teléfono en breve" "Toca para compartir el informe de errores" "Toca para compartir el informe de errores sin captura de pantalla o espera a que se haga la captura." "Toca para compartir el informe de errores sin captura de pantalla o espera a que se haga la captura." diff --git a/packages/Shell/res/values-et-rEE/strings.xml b/packages/Shell/res/values-et-rEE/strings.xml index edf1c09c10e97e26fc8ca019315430b94b8b95c5..aaae44b73a95fa1c78942a8a9d48a13b14936939 100644 --- a/packages/Shell/res/values-et-rEE/strings.xml +++ b/packages/Shell/res/values-et-rEE/strings.xml @@ -21,7 +21,7 @@ "Jäädvustati veaaruanne #%d" "Üksikasjade lisamine veaaruandesse" "Oodake …" - "Veaaruande jagamiseks pühkige vasakule" + "Veaaruanne kuvatakse telefonis peagi" "Veaaruande jagamiseks puudutage" "Puudutage, et veaaruannet ilma ekraanipildita jagada, või oodake, kuni ekraanipilt tehtud saab." "Puudutage, et veaaruannet ilma ekraanipildita jagada, või oodake, kuni ekraanipilt tehtud saab." diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml index 1a220ea193b6923c80baaeb281563daeb0047a98..f60e5898b7b514769d66a6fb072c6405ed654ff7 100644 --- a/packages/Shell/res/values-eu-rES/strings.xml +++ b/packages/Shell/res/values-eu-rES/strings.xml @@ -21,7 +21,7 @@ "Akatsen #%d txostena egin da" "Akatsen txostenean xehetasunak gehitzen" "Itxaron, mesedez…" - "Programa-akatsen txostena partekatzeko, pasatu hatza ezkerrera" + "Akatsen txostena telefonoan agertuko da laster" "Sakatu akatsen txostena partekatzeko" "Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte" "Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte" diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml index 0a5b84e3fc0776aa8bd8d082ca3c5616a323f1d3..f3e92d2a02aa4d92ce8a6c75cc9cb1df2e2fcfab 100644 --- a/packages/Shell/res/values-fa/strings.xml +++ b/packages/Shell/res/values-fa/strings.xml @@ -21,7 +21,7 @@ "گزارش اشکال #%d ثبت شد" "اضافه کردن جزئیات به گزارش اشکال" "لطفاً منتظر بمانید..." - "برای اشتراک‌گذاری گزارش اشکال، به تندی آن را به چپ بکشید" + "گزارش مشکل به‌زودی در تلفن نشان داده می‌شود" "برای به اشتراک گذاشتن گزارش اشکال، ضربه بزنید" "برای اشتراک‌گذاری گزارش مشکل بدون عکس صفحه‌نمایش، ضربه بزنید یا صبر کنید تا عکس صفحه‌نمایش گرفته شود." "برای اشتراک‌گذاری گزارش مشکل بدون عکس صفحه‌نمایش، ضربه بزنید یا صبر کنید تا عکس صفحه‌نمایش گرفته شود." diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml index 894217e6fcaa6259245769163351a1deccb86099..a790cd96e89f52fa32413a72ae582382e6098d07 100644 --- a/packages/Shell/res/values-fi/strings.xml +++ b/packages/Shell/res/values-fi/strings.xml @@ -21,7 +21,7 @@ "Virheraportti #%d tallennettu" "Lisätään tietoja virheraporttiin" "Odota…" - "Jaa virheraportti pyyhkäisemällä vasemmalle" + "Virheraportti näkyy puhelimessa pian." "Jaa virheraportti napauttamalla." "Jaa virheraportti ilman kuvakaappausta napauttamalla tai odota, että kuvakaappaus latautuu." "Jaa virheraportti ilman kuvakaappausta napauttamalla tai odota, että kuvakaappaus latautuu." diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml index 495d26db83d3aa52c76d2112c172b56686263457..baacdd1c1a913920e0ba3e5f92809bec5d08a893 100644 --- a/packages/Shell/res/values-fr-rCA/strings.xml +++ b/packages/Shell/res/values-fr-rCA/strings.xml @@ -21,7 +21,7 @@ "Rapport de bogue #%d enregistré" "Ajout de détails au rapport de bogue" "Veuillez patienter…" - "Faites glisser le doigt vers la gauche pour partager votre rapport de bogue." + "Le rapport de bogue s\'affichera bientôt sur le téléphone" "Touchez ici pour partager votre rapport de bogue" "Touchez pour partager le rapport de bogue sans saisie d\'écran ou attendez que la saisie soit prête" "Touchez pour partager le rapport de bogue sans saisie d\'écran ou attendez que la saisie soit prête" diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml index 04659160b7cf220d49a7bf500a51d648f4f02a2c..506cd68f901b32311fff0b4d999158f3955969e6 100644 --- a/packages/Shell/res/values-fr/strings.xml +++ b/packages/Shell/res/values-fr/strings.xml @@ -21,7 +21,7 @@ "Le rapport de bug \"#%d\" a bien été enregistré" "Ajout d\'informations au rapport de bug" "Veuillez patienter…" - "Faites glisser le doigt vers la gauche pour partager votre rapport d\'erreur." + "Le rapport de bug s\'affichera bientôt sur le téléphone." "Appuyer pour partager votre rapport de bug" "Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran" "Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran" diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml index a06a49b851f1dd73fe24dc77dc33428bf94ca067..d2a39fd625d100c639842f822ecd497b62a382d5 100644 --- a/packages/Shell/res/values-gl-rES/strings.xml +++ b/packages/Shell/res/values-gl-rES/strings.xml @@ -21,7 +21,7 @@ "Rexistrouse o informe de erros #%d" "Engadindo detalles ao informe de erro" "Agarda..." - "Pasa o dedo á esquerda para compartir o teu informe de erros" + "O informe de erros aparecerá no teléfono en breve" "Toca para compartir o teu informe de erros" "Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura" "Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura" diff --git a/packages/Shell/res/values-gu-rIN/strings.xml b/packages/Shell/res/values-gu-rIN/strings.xml index 83a0ab6a944c44e15dfd2f534cd66e84da713909..849f1eaf14db2bb68769ae34716e82a76eabf557 100644 --- a/packages/Shell/res/values-gu-rIN/strings.xml +++ b/packages/Shell/res/values-gu-rIN/strings.xml @@ -21,7 +21,7 @@ "બગ રિપોર્ટ #%d કૅપ્ચર કરી" "બગ રિપોર્ટમાં વિગતો ઉમેરવી" "કૃપા કરીને રાહ જુઓ…" - "તમારી બગ રિપોર્ટ શેર કરવા માટે ડાબે સ્વાઇપ કરો" + "બગ રિપોર્ટ ટૂંક સમયમાં ફોન પર દેખાશે" "તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો" "સ્ક્રીનશૉટ વગર અથવા સ્ક્રીનશૉટ સમાપ્ત થવાની રાહ જોયા વગર તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો" "સ્ક્રીનશૉટ વગર અથવા સ્ક્રીનશૉટ સમાપ્ત થવાની રાહ જોયા વગર તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો" diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml index 9086d8959dada38929f31ac44451447b918eff4a..fc314aff221dad714825de2883f9dbb1bb3a79c9 100644 --- a/packages/Shell/res/values-hi/strings.xml +++ b/packages/Shell/res/values-hi/strings.xml @@ -21,7 +21,7 @@ "बग रिपोर्ट #%d कैप्चर की गई" "बग रिपोर्ट में विवरण जोड़े जा रहे हैं" "कृपया प्रतीक्षा करें…" - "अपनी बग रिपोर्ट साझा करने के लिए बाएं स्वाइप करें" + "बग रिपोर्ट थोड़ी ही देर में फ़ोन पर दिखाई देगी" "अपनी बग रिपोर्ट साझा करने के लिए टैप करें" "अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें" "अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें" diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml index 24b657b4381521b4e2ffbbff6f25e2d17ede304a..ed48fd9e5d527acd03e666606e651f811dc159e7 100644 --- a/packages/Shell/res/values-hr/strings.xml +++ b/packages/Shell/res/values-hr/strings.xml @@ -21,7 +21,7 @@ "Izvješće o programskoj pogrešci #%d snimljeno" "Dodavanje pojedinosti u izvješće o progr. pogrešci" "Pričekajte..." - "Prijeđite prstom ulijevo da biste poslali izvješće o programskim pogreškama" + "Izvješće o programskoj pogrešci uskoro će se pojaviti na telefonu" "Dodirnite da biste podijelili izvješće o programskoj pogrešci" "Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka" "Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka" diff --git a/packages/Shell/res/values-hu/strings.xml b/packages/Shell/res/values-hu/strings.xml index a8c5c76f1dd018240feda6ee3aa8a4a6a646e0a4..b7def063e60720b75208b77b7944e73ae784207f 100644 --- a/packages/Shell/res/values-hu/strings.xml +++ b/packages/Shell/res/values-hu/strings.xml @@ -21,7 +21,7 @@ "Hibajelentés (#%d) rögzítve" "Információk hozzáadása a hibajelentéshez" "Kérjük, várjon..." - "Húzza ujját balra a hibajelentés megosztásához" + "A hibajelentés hamarosan megjelenik a telefonon." "Koppintson a hibajelentés megosztásához" "Koppintson ide, ha képernyőkép nélkül osztaná meg a hibajelentést, vagy várjon a képernyőképre." "Koppintson ide, ha képernyőkép nélkül osztaná meg a hibajelentést, vagy várjon a képernyőképre." diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml index 56627f4ed38bcf73855b8393b47a8d00821d5c6a..27e25c6ae93b9526c0c2841b1c557caa5a9e10c4 100644 --- a/packages/Shell/res/values-hy-rAM/strings.xml +++ b/packages/Shell/res/values-hy-rAM/strings.xml @@ -21,7 +21,7 @@ "#%d վրիպակի զեկույցը գրանցվեց" "Տվյալների ավելացում վրիպակի զեկույցում" "Խնդրում ենք սպասել…" - "Սահեցրեք ձախ՝ սխալի հաշվետվությունը համօգտագործելու համար" + "Վրիպակների մասին հաշվետվությունը շուտով կստանաք հեռախոսին" "Հպեք՝ վրիպակի զեկույցը տրամադրելու համար" "Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը" "Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը" diff --git a/packages/Shell/res/values-in/strings.xml b/packages/Shell/res/values-in/strings.xml index 90700c7ddadcccb9923b966c84f2cf9cfe6a09f7..d4851e3287eb4de18e21dd10e4bba9c10f09cbad 100644 --- a/packages/Shell/res/values-in/strings.xml +++ b/packages/Shell/res/values-in/strings.xml @@ -21,7 +21,7 @@ "Laporan bug #%d dijepret" "Menambahkan detail ke laporan bug" "Harap tunggu..." - "Gesek ke kiri untuk membagikan laporan bug Anda" + "Laporan bug akan segera muncul di ponsel" "Ketuk untuk membagikan laporan bug" "Ketuk untuk membagikan laporan bug tanpa tangkapan layar atau menunggu tangkapan layar selesai" "Ketuk untuk membagikan laporan bug tanpa tangkapan layar atau menunggu tangkapan layar selesai" diff --git a/packages/Shell/res/values-is-rIS/strings.xml b/packages/Shell/res/values-is-rIS/strings.xml index dc21b3577eeedf83b81ac1b19fa2052bd39a1418..872c0298ed85a331f34ce2d315a51332c2714d12 100644 --- a/packages/Shell/res/values-is-rIS/strings.xml +++ b/packages/Shell/res/values-is-rIS/strings.xml @@ -21,7 +21,7 @@ "Villutilkynning #%d búin til" "Bætir upplýsingum við villutilkynningu" "Augnablik..." - "Strjúktu til vinstri til að deila villuskýrslunni" + "Villuskýrslan birtist brátt í símanum" "Ýttu til að deila villutilkynningunni" "Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin" "Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin" diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml index 0fd6c7ab6af550be455c2e9f221964e15fa07584..d1e7c099924398c4dfee5b205988ec6262de25ce 100644 --- a/packages/Shell/res/values-it/strings.xml +++ b/packages/Shell/res/values-it/strings.xml @@ -21,7 +21,7 @@ "Segnalazione di bug #%d acquisita" "Aggiunta di dettagli alla segnalazione di bug" "Attendi..." - "Scorri verso sinistra per condividere il rapporto sui bug" + "La segnalazione di bug comparirà a breve sul telefono" "Tocca per condividere la segnalazione di bug" "Tocca per inviare la segnalazione del bug senza screenshot o attendi che lo screenshot sia completo" "Tocca per inviare la segnalazione del bug senza screenshot o attendi che lo screenshot sia completo" diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml index b3f9d028b9476515aacca47b221ee345b9df6681..be4b1903b9715d611a1529c154fd60b6de5d05ae 100644 --- a/packages/Shell/res/values-iw/strings.xml +++ b/packages/Shell/res/values-iw/strings.xml @@ -21,7 +21,7 @@ "הדוח על הבאג #%d צולם" "מוסיף פרטים לדוח על הבאג" "המתן…" - "החלק שמאלה כדי לשתף את דוח הבאגים" + "הדוח על הבאג יופיע בטלפון בקרוב" "הקש כדי לשתף את הדוח על הבאג" "הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך" "הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך" diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml index eca0ea0a4515958585f969a140f52c7d4fdc9899..c6682d9144bdd7f81fe82efbd42c0f435436a9bc 100644 --- a/packages/Shell/res/values-ja/strings.xml +++ b/packages/Shell/res/values-ja/strings.xml @@ -21,7 +21,7 @@ "バグレポート #%d の記録完了" "バグレポートに詳細情報を追加しています" "お待ちください…" - "バグレポートを共有するには左にスワイプ" + "バグレポートはまもなくスマートフォンに表示されます" "バグレポートを共有するにはタップします" "タップしてバグレポートをスクリーンショットなしで共有するか、スクリーンショット完成までお待ちください" "タップしてバグレポートをスクリーンショットなしで共有するか、スクリーンショット完成までお待ちください" diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml index 43cdeee22d0b0f760b175f725d87a295559d581a..f97f94a93ed4fe4ed64e5a62856dbc556dea35e6 100644 --- a/packages/Shell/res/values-ka-rGE/strings.xml +++ b/packages/Shell/res/values-ka-rGE/strings.xml @@ -21,7 +21,7 @@ "ხარვეზების შესახებ ანგარიში #%d აღბეჭდილია" "ხარვეზის შესახებ ანგარიშს დეტალები ემატება" "გთხოვთ, მოითმინოთ..." - "გაასრიალეთ მარცხნივ თქვენი ხარვეზის შეტყობინების გასაზიარებლად" + "ხარვეზის შესახებ ანგარიში ტელეფონის ეკრანზე მალე გამოჩნდება." "შეეხეთ ხარვეზების შესახებ ანგარიშის გასაზიარებლად" "შეეხეთ ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გარეშე გასაზიარებლად, ან დაელოდეთ მის შექმნას" "შეეხეთ ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გარეშე გასაზიარებლად, ან დაელოდეთ მის შექმნას" diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml index 7d1218fe9f1049b5bff868f217f709c2cd54bc66..3d49f4cc8c9a1b2a696f05895882bf2f4c944ab1 100644 --- a/packages/Shell/res/values-kk-rKZ/strings.xml +++ b/packages/Shell/res/values-kk-rKZ/strings.xml @@ -21,7 +21,7 @@ "#%d қате туралы есебі жазып алынды" "Қате туралы есепке мәліметтер қосылуда" "Күте тұрыңыз…" - "Қате туралы есепті бөлісу үшін солға жанаңыз" + "Көп ұзамай қате туралы есеп телефон экранына шығады" "Қате туралы есепті бөлісу үшін түртіңіз" "Қате туралы есепті скриншотсыз бөлісу үшін түртіңіз немесе скриншот сақталып болғанша күтіңіз" "Қате туралы есепті скриншотсыз бөлісу үшін түртіңіз немесе скриншот сақталып болғанша күтіңіз" diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml index c9633db7f449d4ae9036b708bc338668121250cc..a73cfaa3d3eab7407bb8bd159da36f575812cdd9 100644 --- a/packages/Shell/res/values-km-rKH/strings.xml +++ b/packages/Shell/res/values-km-rKH/strings.xml @@ -21,7 +21,7 @@ "#%d របាយការណ៍កំហុសត្រូវបានថត" "កំពុងបន្ថែមព័ត៌មានលម្អិតទៅរបាយការណ៍កំហុស" "សូម​រង់ចាំ…" - "អូស​ទៅ​ឆ្វេង​​ ដើម្បី​ចែក​រំលែក​របាយការណ៍​កំហុស​របស់​អ្នក" + "របាយការណ៍កំហុសនេះនឹងបង្ហាញនៅលើទូរស័ព្ទរបស់អ្នកនាពេលបន្តិចទៀតនេះ" "ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក" "ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់" "ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់" diff --git a/packages/Shell/res/values-kn-rIN/strings.xml b/packages/Shell/res/values-kn-rIN/strings.xml index fc8d03c3408f360e67ae33112c266702c06daf24..117400a1ac4ca164fe0f9a282b920bf85fa879cd 100644 --- a/packages/Shell/res/values-kn-rIN/strings.xml +++ b/packages/Shell/res/values-kn-rIN/strings.xml @@ -21,7 +21,7 @@ "ದೋಷ ವರದಿಯ #%d ಅನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿಕೊಳ್ಳಲಾಗಿದೆ" "ಬಗ್ ವರದಿಗೆ ವಿವರಗಳನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ" "ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ..." - "ನಿಮ್ಮ ದೋಷ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್‌ ಮಾಡಿ" + "ಬಗ್ ವರದಿ ಶೀಘ್ರದಲ್ಲೇ ಫೋನ್‌ನಲ್ಲಿ ಗೋಚರಿಸಲಿದೆ" "ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ" "ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ" "ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ" diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml index d382fb163d8cc841f13bfd39b576b8b3bd83ebed..6fde0723b286c19cc1040cf86e94dadc4fcefdde 100644 --- a/packages/Shell/res/values-ko/strings.xml +++ b/packages/Shell/res/values-ko/strings.xml @@ -21,7 +21,7 @@ "버그 신고 #%d 캡처됨" "세부정보를 버그 보고서에 추가" "잠시 기다려 주세요..." - "왼쪽으로 스와이프하여 버그 신고서를 공유하세요." + "곧 버그 보고서가 휴대전화에 표시됩니다." "버그 신고를 공유하려면 탭하세요." "스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요." "스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요." diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml index fe2dde41924cb5378ef4ede7e176e960370abfb4..2c972776ef13bdbfcd395744f2c9d358892634e3 100644 --- a/packages/Shell/res/values-ky-rKG/strings.xml +++ b/packages/Shell/res/values-ky-rKG/strings.xml @@ -21,7 +21,7 @@ "Мүчүлүштүк тууралуу билдирүү #%d жаздырылды" "Мүчүлүштүк жөнүндө кабардын чоо-жайы кошулууда" "Күтө туруңуз…" - "Ката жөнүндө кабар менен бөлүшүү үчүн солго серпип коюңуз" + "Мүчүлүштүктөр жөнүндө кабар жакында телефонго чыгат" "Мүчүлүштүк тууралуу билдирүүңүздү бөлүшүү үчүн таптап коюңуз" "Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз" "Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз" diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml index 2cc157358944ec6f8fc4c0abd100623d9e5dd7a1..0673c5189e326fdacc09590207e9e27a52c14472 100644 --- a/packages/Shell/res/values-lo-rLA/strings.xml +++ b/packages/Shell/res/values-lo-rLA/strings.xml @@ -21,7 +21,7 @@ "ບັນທຶກລາຍງານຂໍ້ຜິດພາດ #%d ແລ້ວ" "ກຳລັງເພີ່ມລາຍລະອຽດໃສ່ລາຍງານຂໍ້ຜິດພາດ" "ກະລຸນາລໍຖ້າ..." - "​ປັດ​ໄປ​ຊ້າຍ​ເພື່ອ​ສົ່ງ​ລາຍ​ງານ​ຂໍ້​ຜິດ​ພາດ​ຂອງ​ທ່ານ" + "ລາຍງານຂໍ້ຜິດພາດຈະປາກົດໃນໂທລະສັບໃນໄວໆນີ້" "ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານ" "ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານໂດຍບໍ່ໃຊ້ຮູບໜ້າຈໍ ຫຼື ລໍຖ້າໃຫ້ຮູບໜ້າຈໍແລ້ວໆ" "ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານໂດຍບໍ່ໃຊ້ຮູບໜ້າຈໍ ຫຼື ລໍຖ້າໃຫ້ຮູບໜ້າຈໍແລ້ວໆ" diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml index 23fba5fe31cec0d0a0c138af3ff5aa44727c09a4..8d7f0ded699141d2554e6f1de68abe17ac6b6f5b 100644 --- a/packages/Shell/res/values-lt/strings.xml +++ b/packages/Shell/res/values-lt/strings.xml @@ -21,7 +21,7 @@ "Pranešimas apie riktą (#%d) užfiksuotas" "Pridedama informacijos prie pranešimo apie riktą" "Palaukite…" - "Perbraukite kairėn, kad bendrintumėte rikto ataskaitą" + "Pranešimai apie riktus netrukus bus rodomi telefone" "Palieskite, kad bendrintumėte pranešimą apie riktą" "Palieskite ir bendrinkite pranešimą apie riktą be ekrano kopijos arba palaukite, kol ji bus sukurta" "Palieskite ir bendrinkite pranešimą apie riktą be ekrano kopijos arba palaukite, kol ji bus sukurta" diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml index d6bfee32b1d08f24738920ac2fd69fe0d3cc33ae..f2258a56403d780f97885f9b22e31570009c0331 100644 --- a/packages/Shell/res/values-lv/strings.xml +++ b/packages/Shell/res/values-lv/strings.xml @@ -21,7 +21,7 @@ "Kļūdas pārskats #%d reģistrēts" "Informācijas pievienošana kļūdas pārskatam" "Lūdzu, uzgaidiet..." - "Velciet pa kreisi, lai kopīgotu savu kļūdu ziņojumu." + "Tālrunī pēc brīža būs redzams kļūdu pārskats" "Pieskarieties, lai kopīgotu kļūdas pārskatu." "Pieskarieties, lai kopīgotu kļūdas pārskatu bez ekrānuzņēmuma vai gaidiet ekrānuzņēmumu." "Pieskarieties, lai kopīgotu kļūdas pārskatu bez ekrānuzņēmuma vai gaidiet ekrānuzņēmumu." diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml index 3ce94366b87f7df2e193602cf9860b7171638a4f..f90f4eab1c60f0322361044b3e11550016d87f8d 100644 --- a/packages/Shell/res/values-mk-rMK/strings.xml +++ b/packages/Shell/res/values-mk-rMK/strings.xml @@ -21,7 +21,7 @@ "Извештајот за грешки #%d е снимен" "Се додаваат детали на извештајот за грешка" "Почекајте..." - "Повлечете налево за да споделите пријава за грешка" + "Извештајот за грешки наскоро ќе се појави на телефонот" "Допрете за да го споделите извештајот за грешки" "Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата" "Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата" diff --git a/packages/Shell/res/values-ml-rIN/strings.xml b/packages/Shell/res/values-ml-rIN/strings.xml index 13d6ee43072aa466aee70dac85b6fdf97dcf433e..930f72352af65b4063086fdedb6955cdbda11ef5 100644 --- a/packages/Shell/res/values-ml-rIN/strings.xml +++ b/packages/Shell/res/values-ml-rIN/strings.xml @@ -21,7 +21,7 @@ "ബഗ് റിപ്പോർട്ട് #%d ക്യാപ്ചർ ചെയ്തു" "ബഗ് റിപ്പോർട്ടിലേക്ക് വിശദാംശങ്ങൾ ചേർക്കുന്നു" "കാത്തിരിക്കുക..." - "നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നതിന് ഇടത്തേയ്‌ക്ക് സ്വൈപ്പുചെയ്യുക" + "ബഗ് റിപ്പോർട്ട് താമസിയാതെ ഫോണിൽ ദൃശ്യമാകും" "നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക" "സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക" "സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക" diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml index 591e5425d4a83b2a07ab8ee7ff846938416dea20..6bde789aa91db5c36db259c4afdb30bd1deb7b7a 100644 --- a/packages/Shell/res/values-mn-rMN/strings.xml +++ b/packages/Shell/res/values-mn-rMN/strings.xml @@ -21,7 +21,7 @@ "Програмд гарсан алдааны мэдээллийн #%d-г бүртгэгдлээ" "Алдааны тайланд дэлгэрэнгүй мэдээлэл нэмж байна" "Түр хүлээнэ үү..." - "Өөрийн согог репортыг хуваалцахын тулд зүүн шудрана уу" + "Утсанд удахгүй алдааны тайлан гарч ирэх болно" "Програмд гарсан алдааны мэдээллээ хуваалцах бол дарна уу" "Алдааны тайлангаа дэлгэцээс авсан зураггүйгээр хуваалцах бол дарж, эсвэл дэлгэцээс авсан зургийг бэлэн болтол нь хүлээнэ үү" "Алдааны тайлангаа дэлгэцээс авсан зураггүйгээр хуваалцах бол дарж, эсвэл дэлгэцээс авсан зургийг бэлэн болтол нь хүлээнэ үү" diff --git a/packages/Shell/res/values-mr-rIN/strings.xml b/packages/Shell/res/values-mr-rIN/strings.xml index 035ac01396348d95e508294afe04204e885cb2d0..084901ab8ee8cc1cea6955ca8928de1d8778f869 100644 --- a/packages/Shell/res/values-mr-rIN/strings.xml +++ b/packages/Shell/res/values-mr-rIN/strings.xml @@ -21,7 +21,7 @@ "दोष अहवाल #%d कॅप्चर केला" "दोष अहवालामध्‍ये तपशील जोडत आहे" "कृपया प्रतीक्षा करा..." - "आपला दोष अहवाल सामायिक करण्यासाठी डावीकडे स्वाइप करा" + "फोनवर दोष अहवाल लवकरच दिसेल" "आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा" "स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा" "स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा" diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml index 085152f429bbdb502311a9616b3372d6fe077cf3..36e70c545195e96aa8d850b3576d82852b027768 100644 --- a/packages/Shell/res/values-ms-rMY/strings.xml +++ b/packages/Shell/res/values-ms-rMY/strings.xml @@ -21,7 +21,7 @@ "Laporan pepijat #%d telah ditangkap" "Menambahkan butiran pada laporan pepijat" "Sila tunggu…" - "Leret ke kiri untuk berkongsi laporan pepijat anda" + "Laporan pepijat akan dipaparkan pada telefon sebentar lagi" "Ketik untuk berkongsi laporan pepijat anda" "Ketik untuk berkongsi laporan pepijat anda tanpa tangkapan skrin atau tunggu tangkapan skrin selesai" "Ketik untuk berkongsi laporan pepijat anda tanpa tangkapan skrin atau tunggu tangkapan skrin selesai" diff --git a/packages/Shell/res/values-my-rMM/strings.xml b/packages/Shell/res/values-my-rMM/strings.xml index c9486c97eeeb7b605dfc74a42277ce09a9f9139f..ece4a869449acba13bddbd0525b1c9371ff672cc 100644 --- a/packages/Shell/res/values-my-rMM/strings.xml +++ b/packages/Shell/res/values-my-rMM/strings.xml @@ -21,7 +21,7 @@ "ချွတ်ယွင်းမှုအစီရင်ခံချက် #%d ကိုရယူထားပြီးပါပြီ" "ချွတ်ယွင်းချက်အစီရင်ခံချက်သို့ အသေးစိတ်များပေါင်းထည့်ရန်" "ခေတ္တစောင့်ပါ..." - "သင်၏ ဘာဂ် အစီရင်ခံစာကို မျှပေးရန် ဘယ်ဘက်သို့ ပွတ်ဆွဲရန်" + "ချွတ်ယွင်းချက်အစီရင်ခံစာကို မကြာခင် ဖုန်းထဲတွင် မြင်တွေ့ရပါလိမ့်မည်" "သင့်ချွတ်ယွင်းမှုအစီရင်ခံချက်ကို မျှဝေရန် တို့ပါ" "ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ" "ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ" @@ -39,5 +39,5 @@ "ဖိုင်အမည်" "ချွတ်ယွင်းချက် ခေါင်းစဉ်" "ချွတ်ယွင်းချက် အကျဉ်းချုပ်" - "သိမ်းဆည်းပါ" + "သိမ်းရန်" diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml index 43fb97bb61507db63a715ebb4e1c53df3e573b39..0d5db309a61b6f2a2e53e147234eca746b78c099 100644 --- a/packages/Shell/res/values-nb/strings.xml +++ b/packages/Shell/res/values-nb/strings.xml @@ -21,7 +21,7 @@ "Feilrapporten #%d er fullført" "Legger til detaljer i feilrapporten" "Vent litt" - "Sveip til venstre for å dele feilrapporten din" + "Feilrapporten vises snart på telefonen" "Trykk for å dele feilrapporten" "Trykk for å dele feilrapporten uten noen skjermdump, eller vent til skjermdumpen er klar" "Trykk for å dele feilrapporten uten noen skjermdump, eller vent til skjermdumpen er klar" diff --git a/packages/Shell/res/values-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml index 4ffa42290e4879c0b4f576fcfd570b371bf1f7fb..d71cb9f7589677c55891907ba6f17d177b352aeb 100644 --- a/packages/Shell/res/values-ne-rNP/strings.xml +++ b/packages/Shell/res/values-ne-rNP/strings.xml @@ -21,7 +21,7 @@ "बग रिपोर्ट #%dलाई कैद गरियो" "बग रिपोर्टमा विवरणहरू थप्दै" "कृपया प्रतीक्षा गर्नुहोला..." - "तपाईँको बग रिपोर्ट साझेदारी गर्न बायाँ स्वाइप गर्नुहोस्" + "उक्त बग सम्बन्धी रिपोर्ट चाँडै नै यस फोनमा देखा पर्नेछ" "तपाईंको बग रिपोर्टलाई साझेदारी गर्न ट्याप गर्नुहोस्" "तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्" "तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्" diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml index 1b60f0de1ea10892507404d36f839b42f55ef6a1..c13ad36db8e9d31451ca5e80b8276fdaadbe5901 100644 --- a/packages/Shell/res/values-nl/strings.xml +++ b/packages/Shell/res/values-nl/strings.xml @@ -21,7 +21,7 @@ "Bugrapport #%d is vastgelegd" "Details toevoegen aan het bugrapport" "Even geduld…" - "Veeg naar links om je bugmelding te delen" + "Het bugrapport wordt over enkele ogenblikken op de telefoon weergegeven" "Tik om je bugrapport te delen" "Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid" "Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid" diff --git a/packages/Shell/res/values-pa-rIN/strings.xml b/packages/Shell/res/values-pa-rIN/strings.xml index db8b29f65b2379c40f7678544e2089bf76601600..f0bf46e7379b18108f6b5da24076cf52ced6fe85 100644 --- a/packages/Shell/res/values-pa-rIN/strings.xml +++ b/packages/Shell/res/values-pa-rIN/strings.xml @@ -21,7 +21,7 @@ "ਬੱਗ ਰਿਪੋਰਟ #%d ਕੈਪਚਰ ਕੀਤੀ ਗਈ" "ਬੱਗ ਰਿਪੋਰਟ ਵਿੱਚ ਵੇਰਵਿਆਂ ਨੂੰ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" "ਕਿਰਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ..." - "ਤੁਹਾਡੀ ਬਗ ਰਿਪੋਰਟ ਸ਼ੇਅਰ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਸਵਾਈਪ ਕਰੋ" + "ਬੱਗ ਰਿਪੋਰਟ ਜਲਦ ਹੀ ਫ਼ੋਨ \'ਤੇ ਵਿਖਾਈ ਦੇਵੇਗੀ" "ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" "ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ" "ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ" diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml index d0375b61efdc85d74f8d9a82f317ddf82cfb4a21..9734b2ecfc2bdc41f79a3eee86db8a8ccd11ddce 100644 --- a/packages/Shell/res/values-pl/strings.xml +++ b/packages/Shell/res/values-pl/strings.xml @@ -21,7 +21,7 @@ "Raport o błędzie #%d został zapisany" "Dodaję szczegóły do raportu o błędzie" "Czekaj..." - "Przesuń palcem w lewo, by udostępnić swoje zgłoszenie błędu" + "Raport o błędzie będzie pojawiał się na telefonie przez chwilę" "Kliknij, by udostępnić raport o błędzie" "Kliknij, by udostępnić raport o błędzie bez zrzutu ekranu, lub poczekaj, aż zostanie on wygenerowany" "Kliknij, by udostępnić raport o błędzie bez zrzutu ekranu, lub poczekaj, aż zostanie on wygenerowany" diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml index 12cf2e4c3c8ff971c5e02510b2eea1e8c5ce27c0..2947122eccf57c8922f7dc2d2c9096e96aeefe2c 100644 --- a/packages/Shell/res/values-pt-rBR/strings.xml +++ b/packages/Shell/res/values-pt-rBR/strings.xml @@ -21,7 +21,7 @@ "Relatório do bug #%d capturado" "Adicionando detalhes ao relatório do bug" "Aguarde…" - "Deslize para a esquerda para compartilhar seu relatório de bugs" + "O relatório de bugs será exibido no smartphone em breve" "Toque para compartilhar seu relatório do bug" "Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão" "Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão" diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml index 2148f97ad22c5c5b5d5b08f2803235fe66136406..0b08fd67574adf9babe59d5ec96fad9821c36ea5 100644 --- a/packages/Shell/res/values-pt-rPT/strings.xml +++ b/packages/Shell/res/values-pt-rPT/strings.xml @@ -21,7 +21,7 @@ "Relatório de erro #%d criado" "A adicionar detalhes ao relatório de erro" "Aguarde..." - "Deslizar rapidamente para a esquerda para partilhar o seu relatório de erros" + "O relatório de erro será apresentado brevemente no telemóvel" "Toque para partilhar o relatório de erro" "Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma" "Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma" diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml index 12cf2e4c3c8ff971c5e02510b2eea1e8c5ce27c0..2947122eccf57c8922f7dc2d2c9096e96aeefe2c 100644 --- a/packages/Shell/res/values-pt/strings.xml +++ b/packages/Shell/res/values-pt/strings.xml @@ -21,7 +21,7 @@ "Relatório do bug #%d capturado" "Adicionando detalhes ao relatório do bug" "Aguarde…" - "Deslize para a esquerda para compartilhar seu relatório de bugs" + "O relatório de bugs será exibido no smartphone em breve" "Toque para compartilhar seu relatório do bug" "Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão" "Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão" diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml index 4e57b60c2c18611a249c5701104a5ee3463413e0..e15456364abd39f1f89244b17e1ea307f20794be 100644 --- a/packages/Shell/res/values-ro/strings.xml +++ b/packages/Shell/res/values-ro/strings.xml @@ -21,7 +21,7 @@ "Raportul de eroare #%d a fost creat" "Se adaugă detaliile la raportul de eroare" "Așteptați…" - "Glisați la stânga pentru a trimite raportul de erori" + "Raportul de eroare va apărea curând pe telefon" "Atingeți pentru a trimite raportul de eroare" "Atingeți ca să trimiteți raportul de eroare fără captură de ecran sau așteptați finalizarea acesteia" "Atingeți ca să trimiteți raportul de eroare fără captură de ecran sau așteptați finalizarea acesteia" diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml index 62647ca3c8abd6fe940d5656a044e0e071f5e7cf..9ad590e1afc40d9cceb9544fd53208af56cdbf9f 100644 --- a/packages/Shell/res/values-ru/strings.xml +++ b/packages/Shell/res/values-ru/strings.xml @@ -21,7 +21,7 @@ "Отчет об ошибке #%d сохранен" "Добавление данных в отчет об ошибке" "Подождите…" - "Проведите влево, чтобы отправить отчет" + "Отчет об ошибке скоро появится на телефоне" "Нажмите, чтобы отправить отчет об ошибке." "Нажмите, чтобы отправить отчет об ошибке сразу, или подождите, пока будет сохранен скриншот." "Нажмите, чтобы отправить отчет об ошибке сразу, или подождите, пока будет сохранен скриншот." diff --git a/packages/Shell/res/values-si-rLK/strings.xml b/packages/Shell/res/values-si-rLK/strings.xml index 0b1d478a1dd3e74e311bb08883d5c0e786ee9045..ecc134ea76bc2868acb12a7feb4976fd86b401af 100644 --- a/packages/Shell/res/values-si-rLK/strings.xml +++ b/packages/Shell/res/values-si-rLK/strings.xml @@ -21,7 +21,7 @@ "දෝෂ වාර්තා #%d ග්‍රහණය කර ගන්නා ලදී" "දෝෂ වාර්තාව වෙත විස්තර එක් කිරීම" "කරුණාකර රැඳී සිටින්න..." - "ඔබගේ දෝෂ වාර්තාව බෙදාගැනීමට වමට ස්වයිප් කරන්න" + "දෝෂ වාර්තාව ඉක්මනින් දුරකථනය මත දිස් වනු ඇත" "ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න" "තිර රුවක් රහිතව ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න නැතහොත් තිර රුව ගැනීම අවසන් වන තෙක් රැඳෙන්න" "තිර රුවක් රහිතව ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න නැතහොත් තිර රුව ගැනීම අවසන් වන තෙක් රැඳෙන්න" diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml index 3e3a0e44c1e2e156d2a660349aee307400a314a7..733287e415f42e038adf6b7efb3b0615388b6b11 100644 --- a/packages/Shell/res/values-sk/strings.xml +++ b/packages/Shell/res/values-sk/strings.xml @@ -21,7 +21,7 @@ "Hlásenie chyby #%d bolo zaznamenané" "Pridanie podrobností o hlásení chyby" "Čakajte prosím…" - "Ak chcete hlásenie o chybe zdieľať, prejdite prstom doľava." + "Hlásenie chyby sa čoskoro zobrazí na telefóne" "Hlásenie chyby môžete zdieľať klepnutím" "Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky" "Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky" diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml index 6b07e4654dbc621dd2b7ee13f2c9b72dbbabee84..31c944cac37ab90708a4731860c2840f3f9ded55 100644 --- a/packages/Shell/res/values-sl/strings.xml +++ b/packages/Shell/res/values-sl/strings.xml @@ -21,7 +21,7 @@ "Poročilo o napaki #%d zajeto" "Dodajanje podrobnosti v poročilo o napakah" "Počakajte ..." - "Povlecite v levo, če želite poslati sporočilo o napaki" + "Poročilo o napakah bo kmalu prikazano v telefonu" "Dotaknite se, če želite poročilo o napaki dati v skupno rabo" "Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča" "Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča" diff --git a/packages/Shell/res/values-sq-rAL/strings.xml b/packages/Shell/res/values-sq-rAL/strings.xml index 08c77c29f0a12bbb659c6fa4878c53a6c36b303a..b97c6eb72a4f8c2e720c85f69a502b8cdac0722d 100644 --- a/packages/Shell/res/values-sq-rAL/strings.xml +++ b/packages/Shell/res/values-sq-rAL/strings.xml @@ -21,7 +21,7 @@ "Raporti i defekteve në kod #%d u regjistrua" "Po shtohen detajet te raporti i defekteve në kod" "Qëndro në pritje..." - "Rrëshqit majtas për të ndarë raportin e defektit në kod" + "Raporti i defektit nëkod do të shfaqet së shpejti në telefon" "Trokit për të ndarë raportin e defekteve në kod" "Trokit për të ndarë raportin e defekteve në kod pa një pamje çasti ose prit që pamja e çastit të përfundojë" "Trokit për të ndarë raportin e defekteve në kod pa një pamje çasti ose prit që pamja e çastit të përfundojë" diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml index 72a5dc8bcb4fdb4d81c42ac6cafa9d5c3f68908d..c9547c0e6e99644232ca280af2a88b6725f75f8f 100644 --- a/packages/Shell/res/values-sr/strings.xml +++ b/packages/Shell/res/values-sr/strings.xml @@ -21,7 +21,7 @@ "Извештај о грешци #%d је снимљен" "Додају се детаљи у извештај о грешци" "Сачекајте..." - "Превуците улево да бисте делили извештај о грешкама" + "Извештај о грешци ће се ускоро појавити на телефону" "Додирните да бисте делили извештај о грешци" "Додирните за дељење извештаја о грешци без снимка екрана или сачекајте да се направи снимак екрана" "Додирните за дељење извештаја о грешци без снимка екрана или сачекајте да се направи снимак екрана" diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml index 52ff7c554df130a9dbbaa90ea8460d87ff93afae..dcc38dba3d4d8f566e64f67dc7aa58cf37f835a5 100644 --- a/packages/Shell/res/values-sv/strings.xml +++ b/packages/Shell/res/values-sv/strings.xml @@ -21,7 +21,7 @@ "Felrapporten #%d har skapats" "Lägger till information i felrapporten" "Vänta …" - "Svep åt vänster om du vill dela felrapporten" + "Felrapporten visas på mobilen inom kort" "Tryck om du vill dela felrapporten" "Tryck om du vill dela felrapporten utan en skärmdump eller vänta tills skärmdumpen är klar" "Tryck om du vill dela felrapporten utan en skärmdump eller vänta tills skärmdumpen är klar" diff --git a/packages/Shell/res/values-sw/strings.xml b/packages/Shell/res/values-sw/strings.xml index b31b54f39e9ef35dba8a83b5df4c72f178d5a9cb..83f205d7284c11c3d22524ce94b4bbae305960b8 100644 --- a/packages/Shell/res/values-sw/strings.xml +++ b/packages/Shell/res/values-sw/strings.xml @@ -21,7 +21,7 @@ "Ripoti ya hitilafu ya #%d imerekodiwa" "Inaongeza maelezo kwenye ripoti ya hitilafu" "Tafadhali subiri…" - "Telezesha kidole kushoto ili ushiriki ripoti yako ya hitilafu" + "Tutatuma ripoti ya hitilafu kwenye simu baada ya muda mfupi" "Gonga ili ushiriki ripoti yako ya hitilafu" "Gonga ili ushiriki ripoti yako ya hitilafu bila picha ya skrini au usubiri picha ya skrini itayarishwe" "Gonga ili ushiriki ripoti yako ya hitilafu bila picha ya skrini au usubiri picha ya skrini itayarishwe" diff --git a/packages/Shell/res/values-ta-rIN/strings.xml b/packages/Shell/res/values-ta-rIN/strings.xml index bd727ea3871a0ff424f9964602f2bc651c6b35f7..2a83db0ebf35326ce3cba22889f1718098dc0584 100644 --- a/packages/Shell/res/values-ta-rIN/strings.xml +++ b/packages/Shell/res/values-ta-rIN/strings.xml @@ -21,7 +21,7 @@ "பிழை அறிக்கை #%d எடுக்கப்பட்டது" "பிழை அறிக்கையில் விவரங்களைச் சேர்க்கிறது" "காத்திருக்கவும்…" - "பிழை அறிக்கையைப் பகிர இடது புறமாகத் தேய்க்கவும்" + "பிழை அறிக்கை சிறிது நேரத்தில் மொபைலில் தோன்றும்" "பிழை அறிக்கையைப் பகிர, தட்டவும்" "ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்" "ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்" diff --git a/packages/Shell/res/values-te-rIN/strings.xml b/packages/Shell/res/values-te-rIN/strings.xml index a6beb3c6a3dbcb10fc521c29a6c42fbb700f1de0..47074fd972a74ab16941ca297672c8415ad5fb3c 100644 --- a/packages/Shell/res/values-te-rIN/strings.xml +++ b/packages/Shell/res/values-te-rIN/strings.xml @@ -21,7 +21,7 @@ "బగ్ నివేదిక #%d సంగ్రహించబడింది" "బగ్ నివేదికకు వివరాలను జోడిస్తోంది" "దయచేసి వేచి ఉండండి..." - "మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి ఎడమవైపుకు స్వైప్ చేయండి" + "బగ్ నివేదిక త్వరలో ఫోన్‌లో కనిపిస్తుంది" "మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి నొక్కండి" "స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి" "స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి" diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml index d76bf12526bcb7a6e9342a60a184487ebb651b7e..dddb3b0459dfdbefaf35b658ccbed0448bad47b4 100644 --- a/packages/Shell/res/values-th/strings.xml +++ b/packages/Shell/res/values-th/strings.xml @@ -21,7 +21,7 @@ "บันทึกรายงานข้อบกพร่อง #%d แล้ว" "กำลังเพิ่มรายละเอียดในรายงานข้อบกพร่อง" "โปรดรอสักครู่…" - "กวาดไปทางซ้ายเพื่อแชร์รายงานข้อบกพร่อง" + "รายงานข้อบกพร่องจะปรากฏบนโทรศัพท์ในไม่ช้า" "แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ" "แตะเพื่อแชร์รายงานข้อบกพร่องของคุณโดยไม่มีภาพหน้าจอ หรือรอให้ภาพหน้าจอเสร็จสมบูรณ์" "แตะเพื่อแชร์รายงานข้อบกพร่องของคุณโดยไม่มีภาพหน้าจอ หรือรอให้ภาพหน้าจอเสร็จสมบูรณ์" diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml index fc556e12b6dd3c9e16ebf4e45c727a66e9d1bbc8..28805c867f32b6488e4120ac0aea57a65d7909bb 100644 --- a/packages/Shell/res/values-tl/strings.xml +++ b/packages/Shell/res/values-tl/strings.xml @@ -21,7 +21,7 @@ "Na-capture ang ulat ng bug na #%d" "Pagdaragdag ng mga detalye sa ulat ng bug" "Mangyaring maghintay..." - "Mag-swipe pakaliwa upang ibahagi ang iyong ulat ng bug" + "Lalabas sa telepono ang ulat ng bug pagkalipas ng ilang sandali" "Mag-tap upang ibahagi ang iyong ulat ng bug" "Mag-tap para ibahagi ang iyong ulat ng bug nang walang screenshot o hintaying matapos ang screenshot" "Mag-tap para ibahagi ang iyong ulat ng bug nang walang screenshot o hintaying matapos ang screenshot" diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml index f2b02c37e0c346ced3be9161576c33eff306b170..69d526a04a1f638ad443c3927774d02063ca1107 100644 --- a/packages/Shell/res/values-tr/strings.xml +++ b/packages/Shell/res/values-tr/strings.xml @@ -21,8 +21,8 @@ "Hata raporu (#%d) yakalandı" "Hata raporuna ayrıntılar ekleniyor" "Lütfen bekleyin…" - "Hata raporunuzu paylaşmak için hızlıca sola kaydırın" - "Hata raporunuzu paylaşmak için hafifçe dokunun" + "Hata raporu kısa süre içinde telefonda görüntülenecektir" + "Hata raporunuzu paylaşmak için dokunun" "Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin" "Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin" "Hata raporları, sistemin çeşitli günlük dosyalarından veriler içerir. Bu günlükler, hassas olarak kabul ettiğiniz verileri (uygulama kullanımı ve konum verileri gibi) içerebilir. Hata raporlarını yalnızca güvendiğiniz kişiler ve uygulamalarla paylaşın." diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml index 919a2b51d39c56770eec857a158fa26eee32965e..3bb101f2f3bb9c0d979dc041237682f6976f71d0 100644 --- a/packages/Shell/res/values-uk/strings.xml +++ b/packages/Shell/res/values-uk/strings.xml @@ -21,7 +21,7 @@ "Повідомлення про помилку #%d створено" "Додаються деталі до повідомлення про помилку" "Зачекайте…" - "Проведіть пальцем ліворуч, щоб надіслати звіт про помилки" + "Звіт про помилку невдовзі з’явиться на телефоні" "Торкніться, щоб надіслати повідомлення про помилку" "Торкніться, щоб надіслати повідомлення про помилку без знімка екрана або зачекайте на знімок" "Торкніться, щоб надіслати повідомлення про помилку без знімка екрана або зачекайте на знімок" diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml index d97a6931bed25165841ca50a3f0c1f7e2eac2ef8..3f85bf47eb3829d7026583421c297b385856124c 100644 --- a/packages/Shell/res/values-ur-rPK/strings.xml +++ b/packages/Shell/res/values-ur-rPK/strings.xml @@ -21,7 +21,7 @@ "بگ رپورٹ #%d کیپچر ہو گئی" "بگ رپورٹ میں تفصیلات شامل کی جا رہی ہیں" "براہ کرم انتظار کریں…" - "اپنی بگ رپورٹ کا اشتراک کرنے کیلئے بائیں سوائپ کریں" + "بگ رپورٹ فون پر تھوڑی دیر میں ظاہر ہوگی" "اپنی بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں" "بغیر اسکرین شاٹ کے بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں یا اسکرین شاٹ کے ختم ہونے کا انتظار کریں" "بغیر اسکرین شاٹ کے بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں یا اسکرین شاٹ کے ختم ہونے کا انتظار کریں" diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml index 605fc1250def22512b1025d8826c01fe50a72901..0738ece39a035487252c85e4cbb72768ceddb788 100644 --- a/packages/Shell/res/values-uz-rUZ/strings.xml +++ b/packages/Shell/res/values-uz-rUZ/strings.xml @@ -21,7 +21,7 @@ "Xatoliklar hisoboti (#%d) yozib olindi" "Xatoliklar hisobotiga tafsilotlar qo‘shilmoqda" "Iltimos, kuting…" - "Xatolik hisobotini yuborish uchun barmog‘ingiz bilan chapga suring" + "Xatoliklar hisoboti tez orada telefonda paydo bo‘ladi" "Xatoliklar hisobotini ulashish uchun bosing" "Xatoliklar hisobotini darhol yuborish uchun shu yerga bosing yoki skrinshot saqlanguncha kuting" "Xatoliklar hisobotini darhol yuborish uchun shu yerga bosing yoki skrinshot saqlanguncha kuting" diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml index e9b5a9d83077a936e38315f44a60a44252754e21..f98880164bc2141dc3d8f8fcc466f30c4f39ee67 100644 --- a/packages/Shell/res/values-vi/strings.xml +++ b/packages/Shell/res/values-vi/strings.xml @@ -21,7 +21,7 @@ "Đã chụp báo cáo lỗi #%d" "Đang thêm thông tin chi tiết vào báo cáo lỗi" "Vui lòng đợi…" - "Vuốt sang trái để chia sẻ báo cáo lỗi của bạn" + "Báo cáo lỗi sẽ xuất hiện ngay trên điện thoại" "Nhấn để chia sẻ báo cáo lỗi của bạn" "Bấm để chia sẻ báo cáo lỗi mà không cần ảnh chụp màn hình hoặc đợi hoàn tất ảnh chụp màn hình" "Bấm để chia sẻ báo cáo lỗi mà không cần ảnh chụp màn hình hoặc đợi hoàn tất ảnh chụp màn hình" diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml index ce10d56b252a25ba017ba3cd8410b2447e88d844..a42534cc164b673a70bba74d0d1ca64c55f5cbe8 100644 --- a/packages/Shell/res/values-zh-rCN/strings.xml +++ b/packages/Shell/res/values-zh-rCN/strings.xml @@ -18,10 +18,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Shell" "正在生成错误报告 #%d" - "已捕获错误报告 #%d" + "已获取错误报告 #%d" "正在向错误报告添加详细信息" "请稍候…" - "向左滑动即可分享错误报告" + "错误报告将很快显示在手机上" "点按即可分享您的错误报告" "点按即可分享不含屏幕截图的错误报告;您也可以等待屏幕截图完成" "点按即可分享不含屏幕截图的错误报告;您也可以等待屏幕截图完成" diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml index 8433d2295799d618e09fee5f589be5e03592b20c..600462184c2d35fdbe68663f6607f07dc44a077b 100644 --- a/packages/Shell/res/values-zh-rHK/strings.xml +++ b/packages/Shell/res/values-zh-rHK/strings.xml @@ -21,7 +21,7 @@ "已擷取錯誤報告 #%d" "正在新增錯誤報告詳細資訊" "請稍候…" - "向左滑動即可分享錯誤報告" + "錯誤報告即將在手機上顯示" "輕按即可分享錯誤報告" "輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成" "輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成" diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml index 85dde84a5270a48a7df97f3f7479b0995c776749..1b7bee391ffce6d2fac92314c97008e839c04c75 100644 --- a/packages/Shell/res/values-zh-rTW/strings.xml +++ b/packages/Shell/res/values-zh-rTW/strings.xml @@ -21,7 +21,7 @@ "已擷取錯誤報告 #%d" "正在新增錯誤報告詳細資訊" "請稍候…" - "向左滑動即可分享錯誤報告" + "系統即將在手機上顯示錯誤報告" "輕觸即可分享錯誤報告" "輕觸即可分享無螢幕擷圖的錯誤報告;您也可以等候螢幕畫面擷取完畢" "輕觸即可分享無螢幕擷圖的錯誤報告;您也可以等候螢幕畫面擷取完畢" diff --git a/packages/Shell/res/values-zu/strings.xml b/packages/Shell/res/values-zu/strings.xml index a12a2b7b62d7e147fd04c1c6f47b330d52fd4a40..c1165ea825d0b7792bf62df28d41baa4fba0bc42 100644 --- a/packages/Shell/res/values-zu/strings.xml +++ b/packages/Shell/res/values-zu/strings.xml @@ -21,7 +21,7 @@ "Umbiko wesiphazamisi ongu-#%d uthwetshuliwe" "Ingeza imininingwane kumbiko wesiphazamisi" "Sicela ulinde..." - "Swayiphela kwesokunxele ukuze wabelane umbiko wesiphazamiso sakho" + "Umbiko wesiphazamisi uzobonakala efonini maduze" "Thepha ukuze wabelane ngombiko wakho wesiphazamisi" "Thepha ukuze wabelane ngombiko wesiphazamisi ngaphandle kwesithombe-skrini noma ulinde isithombe-skrini ukuthi siqede" "Thepha ukuze wabelane ngombiko wesiphazamisi ngaphandle kwesithombe-skrini noma ulinde isithombe-skrini ukuthi siqede" diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml index 3d6643d8b0a0e3035115d0e0b968259810354797..5dfac95e3527450348a5f8d8d74da50f8e79ac3f 100644 --- a/packages/Shell/res/values/strings.xml +++ b/packages/Shell/res/values/strings.xml @@ -25,8 +25,8 @@ Please wait\u2026 - - Swipe left to share your bug report + + The bug report will appear on the phone shortly Tap to share your bug report diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 6bc4df71fc5c72834bd37e28a9a75e9d2526c638..5a75f40c403653bcb055201fd5f4264c966b3cc6 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -60,6 +60,8 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.hardware.display.DisplayManagerGlobal; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; @@ -78,6 +80,8 @@ import android.text.format.DateUtils; import android.util.Log; import android.util.Patterns; import android.util.SparseArray; +import android.view.Display; +import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; import android.view.View.OnFocusChangeListener; @@ -212,6 +216,8 @@ public class BugreportProgressService extends Service { private static final Bundle sNotificationBundle = new Bundle(); + private boolean mIsWatch; + @Override public void onCreate() { mContext = getApplicationContext(); @@ -225,6 +231,9 @@ public class BugreportProgressService extends Service { Log.w(TAG, "Could not create directory " + mScreenshotsDir); } } + final Configuration conf = mContext.getResources().getConfiguration(); + mIsWatch = (conf.uiMode & Configuration.UI_MODE_TYPE_MASK) == + Configuration.UI_MODE_TYPE_WATCH; } @Override @@ -439,56 +448,68 @@ public class BugreportProgressService extends Service { return; } + if (info.finished) { + Log.w(TAG, "Not sending progress notification because bugreport has finished already (" + + info + ")"); + return; + } + final NumberFormat nf = NumberFormat.getPercentInstance(); nf.setMinimumFractionDigits(2); nf.setMaximumFractionDigits(2); final String percentageText = nf.format((double) info.progress / info.max); - final Action cancelAction = new Action.Builder(null, mContext.getString( - com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build(); - final Intent infoIntent = new Intent(mContext, BugreportProgressService.class); - infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH); - infoIntent.putExtra(EXTRA_ID, info.id); - final PendingIntent infoPendingIntent = - PendingIntent.getService(mContext, info.id, infoIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - final Action infoAction = new Action.Builder(null, - mContext.getString(R.string.bugreport_info_action), - infoPendingIntent).build(); - final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class); - screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT); - screenshotIntent.putExtra(EXTRA_ID, info.id); - PendingIntent screenshotPendingIntent = mTakingScreenshot ? null : PendingIntent - .getService(mContext, info.id, screenshotIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - final Action screenshotAction = new Action.Builder(null, - mContext.getString(R.string.bugreport_screenshot_action), - screenshotPendingIntent).build(); - - final String title = mContext.getString(R.string.bugreport_in_progress_title, info.id); + + String title = mContext.getString(R.string.bugreport_in_progress_title, info.id); + + // TODO: Remove this workaround when notification progress is implemented on Wear. + if (mIsWatch) { + nf.setMinimumFractionDigits(0); + nf.setMaximumFractionDigits(0); + final String watchPercentageText = nf.format((double) info.progress / info.max); + title = title + "\n" + watchPercentageText; + } final String name = info.name != null ? info.name : mContext.getString(R.string.bugreport_unnamed); - final Notification notification = newBaseNotification(mContext) + final Notification.Builder builder = newBaseNotification(mContext) .setContentTitle(title) .setTicker(title) .setContentText(name) .setProgress(info.max, info.progress, false) - .setOngoing(true) - .setContentIntent(infoPendingIntent) - .setActions(infoAction, screenshotAction, cancelAction) - .build(); - - if (info.finished) { - Log.w(TAG, "Not sending progress notification because bugreport has finished already (" - + info + ")"); - return; + .setOngoing(true); + + // Wear bugreport doesn't need the bug info dialog, screenshot and cancel action. + if (!mIsWatch) { + final Action cancelAction = new Action.Builder(null, mContext.getString( + com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build(); + final Intent infoIntent = new Intent(mContext, BugreportProgressService.class); + infoIntent.setAction(INTENT_BUGREPORT_INFO_LAUNCH); + infoIntent.putExtra(EXTRA_ID, info.id); + final PendingIntent infoPendingIntent = + PendingIntent.getService(mContext, info.id, infoIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + final Action infoAction = new Action.Builder(null, + mContext.getString(R.string.bugreport_info_action), + infoPendingIntent).build(); + final Intent screenshotIntent = new Intent(mContext, BugreportProgressService.class); + screenshotIntent.setAction(INTENT_BUGREPORT_SCREENSHOT); + screenshotIntent.putExtra(EXTRA_ID, info.id); + PendingIntent screenshotPendingIntent = mTakingScreenshot ? null : PendingIntent + .getService(mContext, info.id, screenshotIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + final Action screenshotAction = new Action.Builder(null, + mContext.getString(R.string.bugreport_screenshot_action), + screenshotPendingIntent).build(); + builder.setContentIntent(infoPendingIntent) + .setActions(infoAction, screenshotAction, cancelAction); } + if (DEBUG) { Log.d(TAG, "Sending 'Progress' notification for id " + info.id + " (pid " + info.pid + "): " + percentageText); } - sendForegroundabledNotification(info.id, notification); + sendForegroundabledNotification(info.id, builder.build()); } private void sendForegroundabledNotification(int id, Notification notification) { @@ -754,7 +775,6 @@ public class BugreportProgressService extends Service { } msg = mContext.getString(R.string.bugreport_screenshot_taken); } else { - // TODO: try again using Framework APIs instead of relying on screencap. msg = mContext.getString(R.string.bugreport_screenshot_failed); Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show(); } @@ -854,10 +874,7 @@ public class BugreportProgressService extends Service { // Stop running on foreground, otherwise share notification cannot be dismissed. stopForegroundWhenDone(id); - final Configuration conf = mContext.getResources().getConfiguration(); - if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) { - triggerLocalNotification(mContext, info); - } + triggerLocalNotification(mContext, info); } /** @@ -1336,22 +1353,24 @@ public class BugreportProgressService extends Service { /** * Takes a screenshot and save it to the given location. */ - private static boolean takeScreenshot(Context context, String screenshotFile) { - final ProcessBuilder screencap = new ProcessBuilder() - .command("/system/bin/screencap", "-p", screenshotFile); - Log.d(TAG, "Taking screenshot using " + screencap.command()); - try { - final int exitValue = screencap.start().waitFor(); - if (exitValue == 0) { + private static boolean takeScreenshot(Context context, String path) { + final Bitmap bitmap = Screenshooter.takeScreenshot(); + if (bitmap == null) { + return false; + } + boolean status; + try (final FileOutputStream fos = new FileOutputStream(path)) { + if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)) { ((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(150); return true; + } else { + Log.e(TAG, "Failed to save screenshot on " + path); } - Log.e(TAG, "screencap (" + screencap.command() + ") failed: " + exitValue); - } catch (IOException e) { - Log.e(TAG, "screencap (" + screencap.command() + ") failed", e); - } catch (InterruptedException e) { - Log.w(TAG, "Thread interrupted while screencap still running"); - Thread.currentThread().interrupt(); + } catch (IOException e ) { + Log.e(TAG, "Failed to save screenshot on " + path, e); + return false; + } finally { + bitmap.recycle(); } return false; } diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java index 8b0759942df8b7c98a1f476d8f16a36f3bd734a1..9fd80d3ef616596ad5ebfad2b2e9afdc094d80bd 100644 --- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java +++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java @@ -132,6 +132,7 @@ public class BugreportStorageProvider extends DocumentsProvider { if (!getFileForDocId(documentId).delete()) { throw new FileNotFoundException("Failed to delete: " + documentId); } + getContext().getContentResolver().notifyChange(getNotificationUri(), null); } // This is used by BugreportProgressService so that the notification uri shared by diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java new file mode 100644 index 0000000000000000000000000000000000000000..ce0fbbc8239577be6b5e9c1908a601a0d4907013 --- /dev/null +++ b/packages/Shell/src/com/android/shell/Screenshooter.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.shell; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Point; +import android.hardware.display.DisplayManagerGlobal; +import android.os.Binder; +import android.os.RemoteException; +import android.util.Log; +import android.view.Display; +import android.view.Surface; +import android.view.SurfaceControl; + +/** + * Helper class used to take screenshots. + * + * TODO: logic below was copied and pasted from UiAutomation; it should be refactored into a common + * component that could be used by both (Shell and UiAutomation). + */ +final class Screenshooter { + + private static final String TAG = "Screenshooter"; + + /** Rotation constant: Freeze rotation to 0 degrees (natural orientation) */ + public static final int ROTATION_FREEZE_0 = Surface.ROTATION_0; + + /** Rotation constant: Freeze rotation to 90 degrees . */ + public static final int ROTATION_FREEZE_90 = Surface.ROTATION_90; + + /** Rotation constant: Freeze rotation to 180 degrees . */ + public static final int ROTATION_FREEZE_180 = Surface.ROTATION_180; + + /** Rotation constant: Freeze rotation to 270 degrees . */ + public static final int ROTATION_FREEZE_270 = Surface.ROTATION_270; + + /** + * Takes a screenshot. + * + * @return The screenshot bitmap on success, null otherwise. + */ + static Bitmap takeScreenshot() { + Display display = DisplayManagerGlobal.getInstance() + .getRealDisplay(Display.DEFAULT_DISPLAY); + Point displaySize = new Point(); + display.getRealSize(displaySize); + final int displayWidth = displaySize.x; + final int displayHeight = displaySize.y; + + final float screenshotWidth; + final float screenshotHeight; + + final int rotation = display.getRotation(); + switch (rotation) { + case ROTATION_FREEZE_0: { + screenshotWidth = displayWidth; + screenshotHeight = displayHeight; + } break; + case ROTATION_FREEZE_90: { + screenshotWidth = displayHeight; + screenshotHeight = displayWidth; + } break; + case ROTATION_FREEZE_180: { + screenshotWidth = displayWidth; + screenshotHeight = displayHeight; + } break; + case ROTATION_FREEZE_270: { + screenshotWidth = displayHeight; + screenshotHeight = displayWidth; + } break; + default: { + throw new IllegalArgumentException("Invalid rotation: " + + rotation); + } + } + + Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight); + // Take the screenshot + Bitmap screenShot = + SurfaceControl.screenshot((int) screenshotWidth, (int) screenshotHeight); + if (screenShot == null) { + Log.e(TAG, "Failed to take screenshot of dimensions " + screenshotWidth + " x " + + screenshotHeight); + return null; + } + + // Rotate the screenshot to the current orientation + if (rotation != ROTATION_FREEZE_0) { + Bitmap unrotatedScreenShot = Bitmap.createBitmap(displayWidth, displayHeight, + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(unrotatedScreenShot); + canvas.translate(unrotatedScreenShot.getWidth() / 2, + unrotatedScreenShot.getHeight() / 2); + canvas.rotate(getDegreesForRotation(rotation)); + canvas.translate(- screenshotWidth / 2, - screenshotHeight / 2); + canvas.drawBitmap(screenShot, 0, 0, null); + canvas.setBitmap(null); + screenShot.recycle(); + screenShot = unrotatedScreenShot; + } + + // Optimization + screenShot.setHasAlpha(false); + + return screenShot; + } + + private static float getDegreesForRotation(int value) { + switch (value) { + case Surface.ROTATION_90: { + return 360f - 90f; + } + case Surface.ROTATION_180: { + return 360f - 180f; + } + case Surface.ROTATION_270: { + return 360f - 270f; + } default: { + return 0; + } + } + } + +} diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index eadb4bf4fdafcfb6d99957dfd3b71a198ee27c54..a74fbf81a0219ab26a5acc85788ecb9f85ad68bf 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -150,9 +150,6 @@ - - - @@ -165,6 +162,9 @@ + + + - - - - - - - - diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml index c211e438174a34580aac938f6b6ba256200fa2a2..3b8d59bae7445521c10181ff4fdaf9a11e9279d6 100644 --- a/packages/SystemUI/res/color/notification_guts_buttons.xml +++ b/packages/SystemUI/res/color/notification_guts_buttons.xml @@ -1,7 +1,7 @@ + android:color="?android:attr/colorAccent" /> \ No newline at end of file diff --git a/packages/SystemUI/res/color/qs_detail_empty.xml b/packages/SystemUI/res/color/qs_detail_empty.xml new file mode 100644 index 0000000000000000000000000000000000000000..4be39c7ca6e036a1c5bf2ea6f5253d11e110df94 --- /dev/null +++ b/packages/SystemUI/res/color/qs_detail_empty.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/color/qs_detail_progress_track.xml b/packages/SystemUI/res/color/qs_detail_progress_track.xml new file mode 100644 index 0000000000000000000000000000000000000000..c56382e6047f67f1f9f8215dbb7e9431819175eb --- /dev/null +++ b/packages/SystemUI/res/color/qs_detail_progress_track.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml index 20251c2fedc026c25f089a90e69f13e702b7417d..344859c27e34bacbe336ae0794a2da148c44e79c 100644 --- a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml +++ b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml @@ -17,6 +17,6 @@ --> - + \ No newline at end of file diff --git a/packages/SystemUI/res/color/qs_user_detail_name.xml b/packages/SystemUI/res/color/qs_user_detail_name.xml index 35c7a4fe754bc27d4dc504e4a014a769cc89026b..e262209a82c3611f630eab459e7628d6660ce5a9 100644 --- a/packages/SystemUI/res/color/qs_user_detail_name.xml +++ b/packages/SystemUI/res/color/qs_user_detail_name.xml @@ -17,7 +17,7 @@ --> - + \ No newline at end of file diff --git a/packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml b/packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml new file mode 100644 index 0000000000000000000000000000000000000000..5370f7afb5f5abd24b40cbbbe36f522eb1ad6f8c --- /dev/null +++ b/packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_carmode.png index 6242084ea1757276b04b6f6b62297c831fb060ba..95e5778448b253718c9ed2374291db8269342932 100644 Binary files a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_carmode.png index 1b37a47338aaa1a3a7357e4a20f9444769a2d32d..6421146caae36b02b3b55b112550fda128918dc6 100644 Binary files a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_carmode.png and b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_carmode.png differ diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_carmode.png index 9e0575883a06aa78fbc926b5b2ed38f456857bfb..151d5feee7eb78bc0b1eea66e75ceef449f598ef 100644 Binary files a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_carmode.png and b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_carmode.png differ diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_carmode.png index 2fcfdde08164d7c2bdbf11e09ed5df501fe48532..b954aa7adc0cda8a978da0065bad0a137c2ae990 100644 Binary files a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_carmode.png index 48708a5099a83badc09ffec99fe22ebfa443ba5e..61d5db6598502490d76b1c95378ef6091e2dc143 100644 Binary files a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_carmode.png index 3d731840a93f6ae3743b05956d8dbfc84e132564..7b98c1fa7504e1e97cce34840fdc1b9cab044366 100644 Binary files a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_carmode.png index 786935d5d185c4d4b71659f4a9c868d24d5b0bc2..aad13204b048a06e773a724e88354d6e8e674604 100644 Binary files a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_carmode.png index e4bd4bc3e39d4020c9e40cdf237c6cae0946ac0f..754b2d99ec29643d246761054c3b29018917ea6b 100644 Binary files a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_carmode.png index 94ccf7912e8fb51bcf664a37b447d31823a470c4..873ed7f9e744e72c5a7998ce3073f206c2d527ca 100644 Binary files a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_carmode.png and b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_carmode.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_carmode.png index 980bbbcb4ceb795796e8253aed45eb22311a3f0d..7696d872fe21e3459e6f31eae5f5d29cf4c00ccb 100644 Binary files a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_carmode.png and b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_carmode.png differ diff --git a/packages/SystemUI/res/drawable-nodpi/play.xml b/packages/SystemUI/res/drawable-nodpi/play.xml index 747e60ba4c7622e88a839334bd9ff071bd9d5ca5..772023051636ec54fc3b3676ce8d7fc30cca840d 100644 --- a/packages/SystemUI/res/drawable-nodpi/play.xml +++ b/packages/SystemUI/res/drawable-nodpi/play.xml @@ -21,7 +21,4 @@ Copyright (C) 2015 The Android Open Source Project - diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_carmode.png index 201be3b3c8b5c659bed5c5805000fce4a55c5935..c98f55e071d8261e1bbf5ce3e391ea0a0defcf83 100644 Binary files a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_carmode.png index 2770d6264da047e1f7130c57058494b619c4ab3a..187a5661a38be686620c6f9cd47effa432e09bad 100644 Binary files a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_carmode.png and b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_carmode.png index 8ac64937007b8dbd751a343f28a0f63b12451ca4..c66f8be323d647946b47a981a332f93b831f0952 100644 Binary files a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_carmode.png and b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_carmode.png index 8e3678b292b8411336c7de57b4804fd3dfc813a1..3a3a119041bdd4320fff391a4e8db187f34d2890 100644 Binary files a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_carmode.png index 6c7cb058273300ae64b37ab2f45fd54b711a14ba..7198c825322f0a6e0079209d62a7ff56fe1f08c7 100644 Binary files a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_carmode.png and b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_carmode.png index ea2b108e1e4ca889565a1563ef4d5f922545c309..b1fc02e51502d66a685c78dc6bd442d7f31b59f4 100644 Binary files a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_carmode.png and b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_carmode.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_carmode.png index 3e11023ef7e182aebd7fba193e8d52563cc82542..c06bfdab0abd11bc34ddaddcdd52effa5ad8d333 100644 Binary files a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_carmode.png and b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_carmode.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_carmode.png index fe8213d6390e1698916d21dccc45e9f2df3e0b4e..a8c76bfc664c84d972583607163a1a1e9eda16c2 100644 Binary files a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_carmode.png and b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_carmode.png differ diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_carmode.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_carmode.png index c117efd1e654db89efee477d8b6815fdf66a1010..b798e3d6ea0650a17a6c3ffe962fc2e7d976c855 100644 Binary files a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_carmode.png and b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_carmode.png differ diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml index e901e40fe23d220a9c33f8eeafc0ce7bc303f1b9..0c69d89b47097eaab6c3fd0fbbc3a1d8ce615a8d 100644 --- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml +++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml @@ -15,5 +15,5 @@ ~ limitations under the License --> - + diff --git a/packages/SystemUI/res/drawable/car_ic_arrow.xml b/packages/SystemUI/res/drawable/car_ic_arrow.xml index 9d292cc0259a64ca83bd62fd6a9a10369fa5781b..2c5ad27fe292af4209708643f0d420d04193d1fd 100644 --- a/packages/SystemUI/res/drawable/car_ic_arrow.xml +++ b/packages/SystemUI/res/drawable/car_ic_arrow.xml @@ -21,7 +21,4 @@ - diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml index dc978fe0d48ddc027e110a47d03135d4ffd0bd4f..24ac0184a55121b88caa772eb10b5f3ac0db7f59 100644 --- a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml +++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml @@ -20,7 +20,7 @@ Copyright (C) 2014 The Android Open Source Project android:viewportHeight="24.0"> + android:fillColor="?android:attr/colorPrimary" /> diff --git a/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml b/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml index 7ddb40c503a6ebae6d93d3ad804f6e10bf3fa921..314a25a6d5b21a9005054d435da63e2237ea280e 100644 --- a/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml +++ b/packages/SystemUI/res/drawable/ic_fullscreen_white_24dp.xml @@ -18,9 +18,6 @@ Copyright (C) 2016 The Android Open Source Project android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - - diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml index 6519673de87120f68f4ed28d4e7974b2afcffca1..1183203bc58d49b4aa01926125b6b8e0642c8563 100644 --- a/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml +++ b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml @@ -19,7 +19,6 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - - diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_left.xml b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml index 038187e86acbceef775eda77a1696e4d67283b4b..57d0423e9ce0fe1b32a44ee89eec8a2db1bc9922 100644 --- a/packages/SystemUI/res/drawable/ic_ksh_key_left.xml +++ b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml @@ -21,5 +21,4 @@ android:viewportHeight="24"> - diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml index 1e2195edaf21e057208bc05ce302a8ec344a06ad..be8fe8c57215cbd2d11c82c926c2a8ed13dabe4b 100644 --- a/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml +++ b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml @@ -24,5 +24,4 @@ 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27 .28 v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> - diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_right.xml b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml index f2d73150705a07b9a188efbb274e4d329d011f29..720d4e4b24fbdf5e2bdc77a73377c4e7ba4441f5 100644 --- a/packages/SystemUI/res/drawable/ic_ksh_key_right.xml +++ b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml @@ -21,5 +21,4 @@ android:viewportHeight="24"> - diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_up.xml b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml index 36a83b1d1e821fa636e7a825069bd3fc23aa66c7..350c9949bc4b946eeb4bd5dd787402a8bb1d0502 100644 --- a/packages/SystemUI/res/drawable/ic_ksh_key_up.xml +++ b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml @@ -21,5 +21,4 @@ android:viewportHeight="24"> - diff --git a/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml b/packages/SystemUI/res/drawable/ic_mode_edit.xml similarity index 66% rename from packages/SystemUI/res/drawable/ic_night_mode_disabled.xml rename to packages/SystemUI/res/drawable/ic_mode_edit.xml index 010815a41819935b35cac03e942107772f844277..8a7368632b062452f219d3cc984dcb9f834efd68 100644 --- a/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml +++ b/packages/SystemUI/res/drawable/ic_mode_edit.xml @@ -14,11 +14,11 @@ limitations under the License. --> + android:fillColor="#FFFFFF" + android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.81,9.94l-3.75,-3.75L3.0,17.25zM20.71,7.04c0.39,-0.3 0.39,-1.02 0.0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/> diff --git a/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml b/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml index d9a4f7bd91372f7afb4da2b886af6f62036fee3a..5b65f100490cdfad000d681a70511df9a57a8505 100644 --- a/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml +++ b/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml @@ -22,6 +22,4 @@ Copyright (C) 2016 The Android Open Source Project - diff --git a/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml b/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml index b8fa99e1dbae162f184e26ebfd33a22181a2ab31..ddc9e8dd17a0e3be039c3bcba80bfc40b358a2e4 100644 --- a/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml +++ b/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml @@ -22,6 +22,4 @@ Copyright (C) 2016 The Android Open Source Project - diff --git a/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml b/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml new file mode 100644 index 0000000000000000000000000000000000000000..736a04a1da4417e2fae2181db3698cadd5deb3a1 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml index b4144a3474fd9a5b419fc553d018c49facf706bd..d11b6f461870519e53b7f9502c31338a9d4f9879 100644 --- a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml +++ b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml @@ -14,8 +14,9 @@ limitations under the License. --> + + + + + diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml new file mode 100644 index 0000000000000000000000000000000000000000..aaca663e59e97dc3df65772c48f6261e324bdf14 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml index f63dfb12e203bae610a5fa7acfce550c5228a755..b78d3bf1c35de7199db2082dc6cd348906805d77 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml @@ -1,7 +1,7 @@ + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml index 7fb423e5fc84dae587f63f0f290a53c79f1a340d..e055de77ebe5b3ac22c66cee8b29c6eeb8a4d8bc 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml @@ -1,7 +1,7 @@ + android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z" + android:fillColor="#FFFFFF"/> + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml index 3358d65b68e6ea2072072d6e3b64a36f169de42b..8a488170e43819c733cef889aa51ca69a7c32c28 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml @@ -1,7 +1,7 @@ + android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z" + android:fillColor="#FFFFFF"/> + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml index 63838a93c686d727f980eee32a9d4b304205077b..39cc94cad4dbc7e9101262dfb96dd0a62e66e01b 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml @@ -1,7 +1,7 @@ + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="#FFFFFF"/> - + android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml index 76690cc2adce21b83f0d5791c1ea9b1e44d0e87e..012e95e985ce55e588a84dc767b56c0fb2a1f683 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml +++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml @@ -1,7 +1,7 @@ + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml new file mode 100644 index 0000000000000000000000000000000000000000..4d7f325073dc5a96b0b1540844c11a627dc704f2 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml new file mode 100644 index 0000000000000000000000000000000000000000..3af0629997282813a6ea2f4585ce5ce23e9121ae --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml @@ -0,0 +1,33 @@ + + + + + + + diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml index 50c427e24c9ba95d79046d9c4bb2f1a0da54311a..e6f9292657096a5a208420a66a6fc6bdfd0edd41 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml index a2d11a09aab8f7cfaad5965781387a77e38d3d2f..d423ccb2d5e22c124c36b6c69f44bd82d5f7aa52 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z" + android:fillColor="#FFFFFF"/> + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml index f2043fc4bcaf62739b38c508fe4a0819fe0aa8eb..1982130fb1c65c9345cab696b8dc1a581e74aea8 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z" + android:fillColor="#FFFFFF"/> + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml index b7a4f4c81ec83dfc64c48fa1c6db86bd01384a63..b35011181a867afa56c6a7074a107f7d7cc5dd59 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="#FFFFFF"/> + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillAlpha="0.3" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml index 35a9138b31d2d5a3a949f03c2ae174fc9e030051..136a004354308458bd8895503a2bba6375a21efc 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="#FFFFFF"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z" + android:fillColor="#FFFFFF"/> diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml index 4d2a35e508a91a0f389a2c619d4a3f25bae54d3c..2dcdb71194d179407bcd9d5ef3a4501ccb10a592 100644 --- a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml +++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml @@ -18,9 +18,6 @@ android:height="24.0dp" android:viewportWidth="26.0" android:viewportHeight="24.0"> - - diff --git a/packages/SystemUI/res/drawable/ic_settings_20dp.xml b/packages/SystemUI/res/drawable/ic_settings_20dp.xml new file mode 100644 index 0000000000000000000000000000000000000000..3170f86811ed5a4588f88422492c3b1687041d2f --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_settings_20dp.xml @@ -0,0 +1,24 @@ + + + + diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml index 67e6a01640b1818cfca62786b189718ba7d80cd2..e207cb3808c0588c0ade2775be959785b2b2064e 100644 --- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml +++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_error_state_to_fp.xml @@ -98,11 +98,11 @@ + android:fillColor="@*android:color/system_error" /> + android:fillColor="@*android:color/system_error" /> diff --git a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml index bbadec197dfd254b677121fc5c1926ed620f5cb6..2b4babce277b5f942cef63a081fcf6debff8a69f 100644 --- a/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml +++ b/packages/SystemUI/res/drawable/lockscreen_fingerprint_fp_to_error_state.xml @@ -96,7 +96,7 @@ @@ -106,7 +106,7 @@ @@ -116,7 +116,7 @@ @@ -126,7 +126,7 @@ @@ -138,7 +138,7 @@ @@ -157,11 +157,11 @@ + android:fillColor="@*android:color/system_error" /> + android:fillColor="@*android:color/system_error" /> diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml index 1bf7d4c9521675497a4d28ba7d02bb225f65454c..8ea9e06391088135c1f752fa5e0fb271b5df905a 100644 --- a/packages/SystemUI/res/drawable/qs_background_primary.xml +++ b/packages/SystemUI/res/drawable/qs_background_primary.xml @@ -15,6 +15,6 @@ --> - + diff --git a/packages/SystemUI/res/drawable/qs_customizer_background.xml b/packages/SystemUI/res/drawable/qs_customizer_background.xml index d90f820f5d4dbd7874fc244210e26e4372788d7c..12d8016bf6a0c1d79175f4f8ae8112650fb42126 100644 --- a/packages/SystemUI/res/drawable/qs_customizer_background.xml +++ b/packages/SystemUI/res/drawable/qs_customizer_background.xml @@ -15,5 +15,5 @@ --> - + diff --git a/packages/SystemUI/res/drawable/qs_detail_background.xml b/packages/SystemUI/res/drawable/qs_detail_background.xml index 692cd441c88d130e1b21af989eea3ba88f280c29..84c793f6abd681cd63093ab63e658c17739ee09e 100644 --- a/packages/SystemUI/res/drawable/qs_detail_background.xml +++ b/packages/SystemUI/res/drawable/qs_detail_background.xml @@ -15,5 +15,5 @@ Copyright (C) 2014 The Android Open Source Project --> - + \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/quick_header_bg.xml b/packages/SystemUI/res/drawable/quick_header_bg.xml index d45d673d8bca3a1d8cd330b19cd115e7a8ec1694..920e6f5ef0867f3fce0bf963d4feab5b2f6c0edd 100644 --- a/packages/SystemUI/res/drawable/quick_header_bg.xml +++ b/packages/SystemUI/res/drawable/quick_header_bg.xml @@ -17,5 +17,5 @@ - + diff --git a/packages/SystemUI/res/drawable/recents_stack_action_background.xml b/packages/SystemUI/res/drawable/recents_stack_action_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..2a40dd0ec6131afa086e5dba445203b31d02e208 --- /dev/null +++ b/packages/SystemUI/res/drawable/recents_stack_action_background.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml b/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml index 354b8bd7607b6c31704aa3c2cffbf8cd9f4c0462..1303bdb00a31be9c0cd78b708be329f3a8cd4fed 100644 --- a/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml +++ b/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml @@ -19,7 +19,7 @@ - + + + + + diff --git a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml index 4e2a0245ab2a2b790f019eb11cad7b3a19b99cae..694019e9886788167242ba77c09888b1e67b17fc 100644 --- a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml +++ b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml @@ -14,9 +14,9 @@ limitations under the License. --> + + + + + diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml new file mode 100644 index 0000000000000000000000000000000000000000..db18fad637e7f6977b47dccb92e29c9c0aa0686d --- /dev/null +++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml @@ -0,0 +1,33 @@ + + + + + + + diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml index 643c4f919d1b3b51df23ca8aafb8cfbc2842c884..8bc872a99951d2569506e54546d201eff6bdc45f 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml +++ b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml @@ -1,7 +1,7 @@ - - + diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml index 64781c3672273b0d3471dfe279c50f9d7b70f1cb..8fa7630b0faef9f4acce45fc1b5ea7ab1f45fbbf 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml +++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml @@ -1,7 +1,7 @@ + android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z" + android:fillColor="?attr/fillColor"/> + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillColor="?attr/backgroundColor"/> - + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml index eb2be08af5f130a83cb495abe1bb24f51209381b..2a660a39d510100b8f338a9eb4d4d929575e356f 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml +++ b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml @@ -1,7 +1,7 @@ + android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z" + android:fillColor="?attr/fillColor"/> - - + diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml index 22afad085231e64fba4214a5cb03c2188112e0f0..9e0a43353eea6cc13e339b9e138847af9ed58058 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml +++ b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml @@ -1,7 +1,7 @@ - + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillColor="?attr/backgroundColor"/> + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="?attr/fillColor"/> + android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml index d1e866dfefb314795ff18467ba7930895611a259..01f6703117505ccce0275998f7142c70ca96c47e 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml +++ b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml @@ -1,7 +1,7 @@ - - + android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" + android:fillColor="?attr/fillColor"/> + android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml index 7f1b715e9a78d85359df734d532675d4d0324caa..2de2e364087935fa1e86fa95de56efbd1dcba0c3 100644 --- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="?attr/backgroundColor"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml index acd89bea9ea8139aeb69d2f7ade6b958bb45c871..144a7c1074e0fe483c2c2e16696dc272baefe8c2 100644 --- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z" + android:fillColor="?attr/fillColor"/> + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="?attr/backgroundColor"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml index f33b25c6261bf4a9c9eb7688d805e246b7d71552..6b7f71268162026086805166acafc818cb66d1fc 100644 --- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z" + android:fillColor="?attr/fillColor"/> + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="?attr/backgroundColor"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml index 09d2e5037bc98d37d2333750d890cc53f545e5c7..d34b4debc5ee9446a8c6335fee6a32effce62002 100644 --- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="?attr/fillColor"/> + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="?attr/backgroundColor"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml index fb1f584250e4cb185cd761a514cc72cc6a1b835e..570135639183663267322eaf63effce5706ff95b 100644 --- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml +++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml @@ -1,7 +1,7 @@ + android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z" + android:fillColor="?attr/fillColor"/> - + android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z" + android:fillColor="?attr/fillColor"/> diff --git a/packages/SystemUI/res/drawable/switchbar_background.xml b/packages/SystemUI/res/drawable/switchbar_background.xml index 8d97c46f8870ad4d25aa492f85fcafe1225ab106..fb59633f3ec3a168d8bada1fadc7287ad8a776d9 100644 --- a/packages/SystemUI/res/drawable/switchbar_background.xml +++ b/packages/SystemUI/res/drawable/switchbar_background.xml @@ -16,6 +16,6 @@ - + diff --git a/packages/SystemUI/res/drawable/volume_dialog_background.xml b/packages/SystemUI/res/drawable/volume_dialog_background.xml index e98bfb8d09f6b9678a44bef9581ccf07ee9e9564..d6adea9924569567bdc45c45af4b59da28bf5e48 100644 --- a/packages/SystemUI/res/drawable/volume_dialog_background.xml +++ b/packages/SystemUI/res/drawable/volume_dialog_background.xml @@ -14,5 +14,5 @@ limitations under the License. --> - + \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/zen_introduction_message_background.xml b/packages/SystemUI/res/drawable/zen_introduction_message_background.xml index 352fb57bb2b99653f7c1c63e727093f96d9475ff..e5b41a3fb44cb6c874312fae58558c5eb8d4e4e9 100644 --- a/packages/SystemUI/res/drawable/zen_introduction_message_background.xml +++ b/packages/SystemUI/res/drawable/zen_introduction_message_background.xml @@ -17,6 +17,6 @@ - + \ No newline at end of file diff --git a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml index ba5c0aa0c7723d383400d57b3d1c9144bf24a7f9..a726161c2c6670f005b2b7b76cc7915d86defede 100644 --- a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml +++ b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml @@ -20,7 +20,7 @@ android:id="@+id/date_time_alarm_group" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="8dp" + android:layout_marginTop="16dp" android:layout_marginStart="16dp" android:gravity="start" android:orientation="vertical"> @@ -62,7 +62,8 @@ diff --git a/packages/SystemUI/res/layout/calibrate_sliders.xml b/packages/SystemUI/res/layout/calibrate_sliders.xml deleted file mode 100644 index 0dec8a18caa4d42b6fb0973257aa7c7af5c5237b..0000000000000000000000000000000000000000 --- a/packages/SystemUI/res/layout/calibrate_sliders.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml b/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml new file mode 100644 index 0000000000000000000000000000000000000000..0a1730a7292012bcb90dad9e78ff65c94f57e024 --- /dev/null +++ b/packages/SystemUI/res/layout/emergency_cryptkeeper_text.xml @@ -0,0 +1,28 @@ + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml index 52cab72df120329bb7d9ccca7ff8d4165cc7b696..69e52c53808d2e2379b3c223b7f992351b3af289 100644 --- a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml +++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml @@ -53,5 +53,6 @@ android:layout_alignParentEnd="true" android:textSize="14sp" android:scrollHorizontally="false" - android:layout_centerVertical="true"/> + android:layout_centerVertical="true" + android:focusable="true"/> diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml index 5db678958ce131b43b3dd89b48d27d8e4c588068..a3901d084930d22dce834320e0c7b22b6bf407e5 100644 --- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml @@ -21,4 +21,4 @@ android:padding="@dimen/ksh_item_padding" android:layout_marginStart="@dimen/ksh_item_margin_start" android:scaleType="fitXY" - android:background="@drawable/ksh_key_item_background"/> + android:background="@drawable/ksh_key_item_background" /> diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml index 31a87730a445e97c2c7d6e0b411017d9b8f0bd25..b06f7fc3c69d3817f246b3f6636e211e7efaa51c 100644 --- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml @@ -23,4 +23,5 @@ android:textColor="@color/ksh_key_item_color" android:singleLine="true" android:gravity="center" - android:textSize="@dimen/ksh_item_text_size"/> + android:textSize="@dimen/ksh_item_text_size" + android:textAllCaps="true"/> diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml index d09c42b8a8c2d60a5e79d4ea4bcf72f5dbc27f86..17bade4a85c7f7faa840e1e9850c709a8a9445ba 100644 --- a/packages/SystemUI/res/layout/notification_guts.xml +++ b/packages/SystemUI/res/layout/notification_guts.xml @@ -26,7 +26,8 @@ android:orientation="vertical" android:paddingStart="@*android:dimen/notification_content_margin_start" android:paddingEnd="8dp" - android:background="@color/notification_guts_bg_color"> + android:background="@color/notification_guts_bg_color" + android:theme="@*android:style/Theme.DeviceDefault.Light"> + + diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml index 63390e2337ae189d06fdfe2bddd5a5827b680563..967db261fab10545f53036d6c50f38c7fc2ed0cf 100644 --- a/packages/SystemUI/res/layout/qs_detail.xml +++ b/packages/SystemUI/res/layout/qs_detail.xml @@ -47,11 +47,12 @@ + android:layout_weight="1" + android:fillViewport="true"> + android:layout_height="match_parent"/> diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml index c062b6d671a5825258aad2ccbef13f43c061d2e7..f6ca862370acd5564a7b4b89d9a04fda53ce3b9b 100644 --- a/packages/SystemUI/res/layout/qs_detail_header.xml +++ b/packages/SystemUI/res/layout/qs_detail_header.xml @@ -22,19 +22,9 @@ android:background="@drawable/btn_borderless_rect" android:gravity="center"> - - - + sysui:itemHeight="@dimen/qs_detail_item_height"/> + android:gravity="center" + android:orientation="vertical"> + android:layout_height="56dp"/> + android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/> diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml index ee55ec2d3ce2e1ab05c64b5485f0774307529f49..8b6060f5eb8b697962a9cdf95a96b1ce4b591d7b 100644 --- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml +++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml @@ -37,19 +37,6 @@ android:importantForAccessibility="yes" android:focusable="true" /> - - diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index 751f18100c7fa2d6afefea626a24338d18ca27fa..26c733950bf05e3cb0aaec70808e47a9175dfedc 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -26,7 +26,7 @@ diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml index 58fc0694c72c45b03913b9679ceb239d3f6d2255..8c6c7cfc8048d482a639f01b32670efb6a0dd522 100644 --- a/packages/SystemUI/res/layout/qs_user_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml @@ -28,6 +28,7 @@ android:minHeight="112dp" android:clipChildren="false" android:clipToPadding="false" + android:focusable="true" android:background="@drawable/ripple_drawable" systemui:activatedFontFamily="sans-serif-medium"> @@ -65,4 +66,4 @@ android:visibility="gone" /> - \ No newline at end of file + diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml index f65a6674e5a5eeb94124c723d71fbf7965a34a75..6673d6e8255f937d896a36633d3e9e71b318f9cf 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -37,13 +37,14 @@ android:clipToPadding="false" android:orientation="horizontal" android:layout_alignParentEnd="true" - android:layout_marginTop="28dp" + android:layout_marginTop="4dp" android:layout_marginEnd="12dp"> + + diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml index 1978a930b199b5eef0b30fb2bd9357f969a3334b..c8e5b61241961252ac7cab34d30c644125e7aadf 100644 --- a/packages/SystemUI/res/layout/recents_task_view.xml +++ b/packages/SystemUI/res/layout/recents_task_view.xml @@ -30,8 +30,8 @@ android:id="@+id/lock_to_app_fab" android:layout_width="@dimen/recents_lock_to_app_size" android:layout_height="@dimen/recents_lock_to_app_size" - android:layout_gravity="bottom|right" - android:layout_marginRight="15dp" + android:layout_gravity="bottom|end" + android:layout_marginEnd="15dp" android:layout_marginBottom="15dp" android:translationZ="4dp" android:contentDescription="@string/recents_lock_to_app_button_label" diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml index 0c8cc9bb5f02579fd048225ca0a5fb225e5b17e4..73f26e2bb57cf3dd55fdcb85c59c9a1751da8403 100644 --- a/packages/SystemUI/res/layout/remote_input.xml +++ b/packages/SystemUI/res/layout/remote_input.xml @@ -42,8 +42,7 @@ android:singleLine="true" android:ellipsize="start" android:inputType="textShortMessage|textAutoCorrect|textCapSentences" - android:textIsSelectable="true" - android:imeOptions="actionNone|flagNoExtractUi" /> + android:imeOptions="actionNone|flagNoExtractUi|flagNoFullscreen" /> + android:orientation="vertical" + android:theme="@android:style/Theme.DeviceDefault.Light"> + android:background="?android:attr/colorAccent" /> + android:background="?android:attr/colorAccent"> + android:paddingEnd="@dimen/screen_pinning_request_frame_padding" + android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent"> + android:background="?android:attr/colorAccent" + android:orientation="vertical"> + android:layout_weight="0" + android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent"> + android:orientation="horizontal" + android:theme="@android:style/Theme.DeviceDefault.Light"> + android:background="?android:attr/colorAccent" + android:gravity="center_vertical"> + + diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml index f94b72794c9771c73b1aed2a4654e797e3da438e..701b621c469beb10889734b3a73bf7fff43ecddb 100644 --- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml +++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml @@ -20,7 +20,7 @@ android:id="@+id/date_time_alarm_group" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="8dp" + android:layout_marginTop="16dp" android:layout_marginStart="16dp" android:gravity="start" android:orientation="vertical"> @@ -60,7 +60,8 @@ +